diff --git a/AUTHORS b/AUTHORS index 6f0b74b..8aede9c 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -1097,6 +1097,7 @@ Simon Jackson <simon.jackson@sonocent.com> Simon La Macchia <smacchia@amazon.com> Siva Kumar Gunturi <siva.gunturi@samsung.com> +Slava Aseev <nullptrnine@gmail.com> Sohan Jyoti Ghosh <sohan.jyoti@huawei.com> Sohan Jyoti Ghosh <sohan.jyoti@samsung.com> Sohom Datta <sohom.datta@learner.manipal.edu>
diff --git a/DEPS b/DEPS index 39137f2..cb080ad 100644 --- a/DEPS +++ b/DEPS
@@ -271,11 +271,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '9b037f4081a986b5d82b9e1c3b03f3050c41b601', + 'skia_revision': '70e432e72745b514d213d350d069dd661afb7e4e', # 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': 'f67292fc2d1f7798e40774b5284fe5ac5ec6e241', + 'v8_revision': '91be46d2f6200acd5be68a6cc964c2b5debc5697', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. @@ -287,7 +287,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': '3da2ecad3a1402295b3cc020765f6790652f32f1', + 'pdfium_revision': '9f882baa7ebaa13bd2ad0d21e80d5cd01a59efe9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -322,7 +322,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': 'a4c4566b6d51a0bd60133e1e1a7fcc19e8fcba9e', + 'freetype_revision': '7838c78f53f206ac5b8e9cefde548aa81cb00cf4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -342,7 +342,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': 'c9c60146a29c50806a892e17093b121cba0d1977', + 'catapult_revision': 'c91b2857e4eeda2bb666a1d7fee3b8aacdcaf309', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -350,7 +350,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': '367472876cbd308076352cd7da6b787b4c7b8827', + 'devtools_frontend_revision': '4fbbbe14852c04f4e60f61fbf558a7c996ee9a3f', # 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. @@ -386,7 +386,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'f8a3a7c121a333f5ecf68969bb0289cbbd6ab50a', + 'dawn_revision': '3bb360f0bb91695d1fe85624a8ef9d70e857c632', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -581,7 +581,7 @@ 'packages': [ { 'package': 'chromium/android_webview/tools/cts_archive', - 'version': 'T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC', + 'version': 'qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C', }, ], 'condition': 'checkout_android', @@ -916,7 +916,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'HuDpDevaflsLdSghrclKds4D47kDaRUxJTXlB3PwT1wC', + 'version': 'QW1zGYiTB7FwtKtfDfyERSj4Guz0Qfym7Gqin2bjbVYC', }, ], 'condition': 'checkout_android', @@ -1025,9 +1025,6 @@ 'src/third_party/highway/src': Var('chromium_git') + '/external/github.com/google/highway.git' + '@' + Var('highway_revision'), - 'src/third_party/glfw/src': - Var('chromium_git') + '/external/github.com/glfw/glfw.git@' + '94773111300fee0453844a4c9407af7e880b4df8', - 'src/third_party/apache-portable-runtime/src': { 'url': Var('chromium_git') + '/external/apache-portable-runtime.git' + '@' + 'c3f11fcd86b42922834cae91103cf068246c6bb6', 'condition': 'checkout_android', @@ -1668,7 +1665,7 @@ 'condition': 'checkout_android', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@aae529072cf30edd47bf24cfd2c26bf7f28a7b97', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@c8893896acff5b3521d72f5f4e9f6093aaa5c9bb', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1707,7 +1704,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '5f05d6d5e625fe6f04903335473c5638ddf94514', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '7df247af56fc66e78b0f91bc42fc88d351aef703', + Var('webrtc_git') + '/src.git' + '@' + 'f5c06f3a421b549426ecd7af4795a5a63caf78e8', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1780,7 +1777,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9cd8b65943371162c9fdaca9baa4e42c8fd61366', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0b2571b7ff9b88e7e9f8af799a71e57ccfa64e2e', 'condition': 'checkout_src_internal', }, @@ -1832,7 +1829,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'LcIMSrJ-SNJDvxx6cpk60HCbRkAwTqVTYGJpoXw9k8kC', + 'version': 'NSf5ffxhFx_ODKm9C1kBJ32VYOo-nscqNf1t50sD4Q4C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4689,7 +4686,8 @@ recursedeps = [ # ANGLE manages DEPS that it also owns the build files for, such as dEQP. 'src/third_party/angle', - # Dawn needs CTS from its DEPS + # Dawn manages DEPS for its copy of the WebGPU CTS as well as GLFW for which + # it has build files. 'src/third_party/dawn', 'src/third_party/openscreen/src', 'src/third_party/vulkan-deps',
diff --git a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc index 2db1a63..6943be6 100644 --- a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc +++ b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.cc
@@ -213,10 +213,4 @@ } } -void AwProxyingRestrictedCookieManager:: - ConvertPartitionedCookiesToUnpartitioned(const GURL& url) { - underlying_restricted_cookie_manager_ - ->ConvertPartitionedCookiesToUnpartitioned(url); -} - } // namespace android_webview
diff --git a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h index 5ccede3d..83a9479e 100644 --- a/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h +++ b/android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h
@@ -83,9 +83,6 @@ bool AllowCookies(const GURL& url, const net::SiteForCookies& site_for_cookies) const; - // TODO(https://crbug.com/1296161): Delete this function. - void ConvertPartitionedCookiesToUnpartitioned(const GURL& url) override; - private: AwProxyingRestrictedCookieManager( mojo::PendingRemote<network::mojom::RestrictedCookieManager>
diff --git a/android_webview/tools/cts_config/webview_cts_gcs_path.json b/android_webview/tools/cts_config/webview_cts_gcs_path.json index e0a6897..45263f3 100644 --- a/android_webview/tools/cts_config/webview_cts_gcs_path.json +++ b/android_webview/tools/cts_config/webview_cts_gcs_path.json
@@ -110,6 +110,14 @@ "match": "android.assist.cts.WebViewTest#testWebView" } ] + }, + { + "apk": "android-cts/repository/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyph" + } + ] } ] }, @@ -164,6 +172,14 @@ "match": "android.assist.cts.WebViewTest#testWebView" } ] + }, + { + "apk": "android-cts/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyph" + } + ] } ] }, @@ -203,6 +219,22 @@ "match": "android.assist.cts.WebViewTest#testWebView" } ] + }, + { + "apk": "android-cts/testcases/CtsWidgetTestCases.apk", + "includes": [ + { + "match": "android.widget.cts.RemoteViewsActivityTest#testWebView" + } + ] + }, + { + "apk": "android-cts/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyph" + } + ] } ] }, @@ -253,6 +285,22 @@ "match": "android.assist.cts.WebViewTest#testWebView" } ] + }, + { + "apk": "android-cts/testcases/CtsWidgetTestCases.apk", + "includes": [ + { + "match": "android.widget.cts.RemoteViewsActivityTest#testWebView" + } + ] + }, + { + "apk": "android-cts/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyph" + } + ] } ] }, @@ -311,6 +359,14 @@ ] }, { + "apk": "android-cts/testcases/CtsWidgetTestCases.apk", + "includes": [ + { + "match": "android.widget.cts.RemoteViewsActivityTest#testWebView" + } + ] + }, + { "apk": "android-cts/testcases/CtsAssistTestCases.apk", "voice_service": "android.assist.service/.MainInteractionService", "additional_apks": [ @@ -326,6 +382,14 @@ "match": "android.assist.cts.WebViewTest#testWebView" } ] + }, + { + "apk": "android-cts/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyphWebView" + } + ] } ] }, @@ -384,6 +448,14 @@ ] }, { + "apk": "android-cts/testcases/CtsWidgetTestCases.apk", + "includes": [ + { + "match": "android.widget.cts.RemoteViewsActivityTest#testWebView" + } + ] + }, + { "apk": "android-cts/testcases/CtsAssistTestCases.apk", "additional_apks": [ { @@ -412,6 +484,25 @@ "match": "android.view.inputmethod.cts.KeyboardVisibilityControlTest#testShowHideKeyboardOnWebView" } ] + }, + { + "apk": "android-cts/testcases/CtsAutoFillServiceTestCases.apk", + "includes": [ + { + "match": "android.autofillservice.cts.inline.InlineAugmentedWebViewActivityTest" + }, + { + "match": "android.autofillservice.cts.inline.InlineWebViewActivityTest" + } + ] + }, + { + "apk": "android-cts/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyphWebView" + } + ] } ] }, @@ -470,6 +561,23 @@ ] }, { + "apk": "android-cts/testcases/CtsAutoFillServiceTestCases.apk", + "includes": [ + { + "match": "android.autofillservice.cts.dropdown.WebViewActivityTest" + }, + { + "match": "android.autofillservice.cts.servicebehavior.WebViewMultiScreenLoginActivityTest" + }, + { + "match": "android.autofillservice.cts.inline.InlineAugmentedWebViewActivityTest" + }, + { + "match": "android.autofillservice.cts.inline.InlineWebViewActivityTest" + } + ] + }, + { "apk": "android-cts/testcases/CtsAssistTestCases.apk", "additional_apks": [ { @@ -507,6 +615,22 @@ "match": "android.view.inputmethod.cts.InputMethodServiceTest#testBatchEdit_commitSpaceThenSetComposingRegion_webView" } ] + }, + { + "apk": "android-cts/testcases/CtsWidgetTestCases.apk", + "includes": [ + { + "match": "android.widget.cts.RemoteViewsActivityTest#testWebView" + } + ] + }, + { + "apk": "android-cts/testcases/CtsTextTestCases.apk", + "includes": [ + { + "match": "android.text.cts.EmojiTest#testEmojiGlyphWebView" + } + ] } ] }
diff --git a/ash/DEPS b/ash/DEPS index 647e680..93740f0 100644 --- a/ash/DEPS +++ b/ash/DEPS
@@ -61,6 +61,7 @@ "+chromeos/ash/components/human_presence", "+chromeos/components/feature_usage", "+chromeos/components/quick_answers", + "+chromeos/components/security_token_pin", "+chromeos/components/sensors", "+chromeos/components/webauthn", "+chromeos/constants",
diff --git a/ash/style/ash_color_provider.cc b/ash/style/ash_color_provider.cc index 8e0ebf3f..813cb29 100644 --- a/ash/style/ash_color_provider.cc +++ b/ash/style/ash_color_provider.cc
@@ -65,8 +65,7 @@ // In the future additional screens will be added. Eventually all screens // will support it and this array will not be needed anymore. constexpr OobeDialogState kStatesSupportingDarkTheme[] = { - OobeDialogState::HIDDEN, OobeDialogState::MARKETING_OPT_IN, - OobeDialogState::THEME_SELECTION}; + OobeDialogState::MARKETING_OPT_IN, OobeDialogState::THEME_SELECTION}; AshColorProvider* g_instance = nullptr; @@ -209,7 +208,7 @@ return; if (state != session_manager::SessionState::OOBE && state != session_manager::SessionState::LOGIN_PRIMARY) { - force_oobe_light_mode_ = false; + oobe_state_ = OobeDialogState::HIDDEN; } NotifyDarkModeEnabledPrefChange(); } @@ -313,9 +312,21 @@ if (is_dark_mode_enabled_in_oobe_for_testing_.has_value()) return is_dark_mode_enabled_in_oobe_for_testing_.value(); - // Always use the LIGHT theme in all OOBE screens except the last two - if (force_oobe_light_mode_) - return false; + if (oobe_state_ != OobeDialogState::HIDDEN) { + if (active_user_pref_service_) { + const PrefService::Preference* pref = + active_user_pref_service_->FindPreference( + prefs::kDarkModeScheduleType); + // Managed users do not see the theme selection screen, so to avoid + // confusion they should always see light colors during OOBE + if (pref->IsManaged() || pref->IsRecommended()) + return false; + + if (!active_user_pref_service_->GetBoolean(prefs::kDarkModeEnabled)) + return false; + } + return base::Contains(kStatesSupportingDarkTheme, oobe_state_); + } // On the login screen use the preference of the focused pod's user if they // had the preference stored in the known_user and the pod is focused. @@ -335,8 +346,7 @@ void AshColorProvider::SetDarkModeEnabledForTest(bool enabled) { DCHECK(features::IsDarkLightModeEnabled()); - if (Shell::Get()->session_controller()->GetSessionState() == - session_manager::SessionState::OOBE) { + if (oobe_state_ != OobeDialogState::HIDDEN) { auto closure = GetNotifyOnDarkModeChangeClosure(); is_dark_mode_enabled_in_oobe_for_testing_ = enabled; return; @@ -348,18 +358,7 @@ void AshColorProvider::OnOobeDialogStateChanged(OobeDialogState state) { auto closure = GetNotifyOnDarkModeChangeClosure(); - // Managed users do not see the theme selection screen, so to avoid confusion - // they should always see light colors during OOBE - if (state != OobeDialogState::HIDDEN && active_user_pref_service_) { - const PrefService::Preference* pref = - active_user_pref_service_->FindPreference(prefs::kDarkModeScheduleType); - if (pref->IsManaged() || pref->IsRecommended()) { - force_oobe_light_mode_ = true; - return; - } - } - - force_oobe_light_mode_ = !base::Contains(kStatesSupportingDarkTheme, state); + oobe_state_ = state; } void AshColorProvider::OnFocusPod(const AccountId& account_id) {
diff --git a/ash/style/ash_color_provider.h b/ash/style/ash_color_provider.h index d4cd9b1..71dc8dd 100644 --- a/ash/style/ash_color_provider.h +++ b/ash/style/ash_color_provider.h
@@ -7,6 +7,7 @@ #include "ash/ash_export.h" #include "ash/login/ui/login_data_dispatcher.h" +#include "ash/public/cpp/login_types.h" #include "ash/public/cpp/session/session_observer.h" #include "ash/public/cpp/style/color_provider.h" #include "base/callback_helpers.h" @@ -146,10 +147,7 @@ // Temporary field for testing purposes while OOBE WebUI is being migrated. absl::optional<bool> is_dark_mode_enabled_in_oobe_for_testing_; - // True if we're in the OOBE state, or OOBE WebUI dialog is open (e.g. for the - // "Add person" flow), except for the last two screens. In those two screens - // the theme is based on user's preferences. - bool force_oobe_light_mode_ = false; + OobeDialogState oobe_state_ = OobeDialogState::HIDDEN; // absl::nullopt in case no user pod is focused. absl::optional<bool> is_dark_mode_enabled_for_focused_pod_;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 31133823..7527786 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3655,6 +3655,7 @@ "allocator/partition_allocator/partition_alloc_base/logging_pa_unittest.cc", "allocator/partition_allocator/partition_alloc_base/rand_util_pa_unittest.cc", "allocator/partition_allocator/partition_alloc_base/scoped_clear_last_error_pa_unittest.cc", + "allocator/partition_allocator/partition_alloc_base/strings/stringprintf_pa_unittest.cc", "allocator/partition_allocator/partition_alloc_base/sys_byteorder_pa_unittest.cc", "allocator/partition_allocator/partition_alloc_base/thread_annotations_pa_unittest.cc", "allocator/partition_allocator/partition_alloc_unittest.cc",
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn index a9105b0f..1e14a2c 100644 --- a/base/allocator/partition_allocator/BUILD.gn +++ b/base/allocator/partition_allocator/BUILD.gn
@@ -110,6 +110,8 @@ "partition_alloc_base/rand_util.cc", "partition_alloc_base/rand_util.h", "partition_alloc_base/scoped_clear_last_error.h", + "partition_alloc_base/strings/stringprintf.cc", + "partition_alloc_base/strings/stringprintf.h", "partition_alloc_base/sys_byteorder.h", "partition_alloc_base/thread_annotations.h", "partition_alloc_base/threading/platform_thread.cc",
diff --git a/base/allocator/partition_allocator/DEPS b/base/allocator/partition_allocator/DEPS index 261b2de..809ba92 100644 --- a/base/allocator/partition_allocator/DEPS +++ b/base/allocator/partition_allocator/DEPS
@@ -28,7 +28,6 @@ include_rules += [ "+base/allocator/allocator_shim_default_dispatch_to_partition_alloc.h", "+base/debug/proc_maps_linux.h", - "+base/strings/stringprintf.h", "+base/system/sys_info.h", "+base/test/gtest_util.h", "+base/timer/lap_timer.h",
diff --git a/base/allocator/partition_allocator/partition_alloc_base/logging.cc b/base/allocator/partition_allocator/partition_alloc_base/logging.cc index cbf408a..cd33a190 100644 --- a/base/allocator/partition_allocator/partition_alloc_base/logging.cc +++ b/base/allocator/partition_allocator/partition_alloc_base/logging.cc
@@ -15,6 +15,7 @@ #include "base/allocator/partition_allocator/partition_alloc_base/debug/alias.h" #include "base/allocator/partition_allocator/partition_alloc_base/immediate_crash.h" +#include "base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.h" #include "base/base_export.h" #include "build/build_config.h" @@ -200,13 +201,14 @@ size_t whitespace_pos = message.find_last_not_of("\n\r "); if (whitespace_pos != std::string::npos) message.erase(whitespace_pos + 1); - return message + base::StringPrintf(" (0x%lX)", error_code); + return message + base::TruncatingStringPrintf(" (0x%lX)", error_code); } - return base::StringPrintf("Error (0x%lX) while retrieving error. (0x%lX)", - GetLastError(), error_code); + return base::TruncatingStringPrintf( + "Error (0x%lX) while retrieving error. (0x%lX)", GetLastError(), + error_code); #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) return base::safe_strerror(error_code) + - base::StringPrintf(" (%d)", error_code); + base::TruncatingStringPrintf(" (%d)", error_code); #endif // BUILDFLAG(IS_WIN) }
diff --git a/base/allocator/partition_allocator/partition_alloc_base/migration_adapter.h b/base/allocator/partition_allocator/partition_alloc_base/migration_adapter.h index 4fe58c05..0b45612 100644 --- a/base/allocator/partition_allocator/partition_alloc_base/migration_adapter.h +++ b/base/allocator/partition_allocator/partition_alloc_base/migration_adapter.h
@@ -25,7 +25,6 @@ template <typename Type> struct LazyInstanceTraitsBase; -BASE_EXPORT std::string StringPrintf(const char* format, ...); BASE_EXPORT void TerminateBecauseOutOfMemory(size_t size); #if BUILDFLAG(IS_ANDROID) @@ -68,7 +67,6 @@ using ::base::LapTimer; using ::base::LazyInstance; using ::base::LazyInstanceTraitsBase; -using ::base::StringPrintf; using ::base::TerminateBecauseOutOfMemory; #if BUILDFLAG(IS_MAC)
diff --git a/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.cc b/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.cc new file mode 100644 index 0000000..c588e9f --- /dev/null +++ b/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.cc
@@ -0,0 +1,47 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// 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/partition_alloc_base/strings/stringprintf.h" + +#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" +#include "base/allocator/partition_allocator/partition_alloc_base/scoped_clear_last_error.h" + +#include <stdarg.h> +#include <stdio.h> + +namespace partition_alloc::internal::base { + +std::string PA_PRINTF_FORMAT(1, 2) + TruncatingStringPrintf(const char* format, ...) { + base::ScopedClearLastError last_error; + char stack_buf[kMaxLengthOfTruncatingStringPrintfResult + 1]; + va_list arguments; + va_start(arguments, format); +#if BUILDFLAG(IS_WIN) + int result = vsnprintf_s(stack_buf, std::size(stack_buf), _TRUNCATE, format, + arguments); +#else + int result = vsnprintf(stack_buf, std::size(stack_buf), format, arguments); +#endif + va_end(arguments); +#if BUILDFLAG(IS_WIN) + // If an output error is encountered or data is larger than count, + // a negative value is returned. So to see whether an output error is really + // encountered or not, need to see errno. If errno == EINVAL or + // errno == ERANGE, an output error is encountered. If not, an output is + // just truncated. + if (result < 0 && (errno == EINVAL || errno == ERANGE)) + return std::string(); +#else + // If an output error is encountered, a negative value is returned. + // In the case, return an empty string. + if (result < 0) + return std::string(); +#endif + // If result is equal or larger than std::size(stack_buf), the output was + // truncated. ::base::StringPrintf doesn't truncate output. + return std::string(stack_buf); +} + +} // namespace partition_alloc::internal::base
diff --git a/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.h b/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.h new file mode 100644 index 0000000..56717a5 --- /dev/null +++ b/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.h
@@ -0,0 +1,30 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// 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_PARTITION_ALLOC_BASE_STRINGS_STRINGPRINTF_H_ +#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_STRINGS_STRINGPRINTF_H_ + +#include <stdarg.h> // va_list + +#include <string> + +#include "base/allocator/partition_allocator/partition_alloc_base/compiler_specific.h" +#include "base/base_export.h" +#include "build/build_config.h" + +namespace partition_alloc::internal::base { + +// Since Only SystemErrorCodeToString and partition_alloc_perftests use +// StringPrintf, make StringPrintf not to support too long results. +// Instead, define max result length and truncate such results. +static constexpr size_t kMaxLengthOfTruncatingStringPrintfResult = 255U; + +// Return a C++ string given printf-like input. +[[nodiscard]] BASE_EXPORT std::string TruncatingStringPrintf(const char* format, + ...) + PA_PRINTF_FORMAT(1, 2); + +} // namespace partition_alloc::internal::base + +#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_BASE_STRINGS_STRINGPRINTF_H_
diff --git a/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf_pa_unittest.cc b/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf_pa_unittest.cc new file mode 100644 index 0000000..a8be3b5 --- /dev/null +++ b/base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf_pa_unittest.cc
@@ -0,0 +1,44 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// 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/partition_alloc_base/strings/stringprintf.h" + +#include <errno.h> +#include <stddef.h> + +#include "build/build_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace partition_alloc::internal::base { + +TEST(PartitionAllocStringPrintfTest, TruncatingStringPrintfEmpty) { + EXPECT_EQ("", TruncatingStringPrintf("%s", "")); +} + +TEST(PartitionAllocStringPrintfTest, TruncatingStringPrintfMisc) { + EXPECT_EQ("123hello w", + TruncatingStringPrintf("%3d%2s %1c", 123, "hello", 'w')); +} + +// Test that TruncatingStringPrintf truncates too long result. +// The original TruncatingStringPrintf does not truncate. Instead, it allocates +// memory and returns an entire result. +TEST(PartitionAllocStringPrintfTest, TruncatingStringPrintfTruncatesResult) { + std::vector<char> buffer; + buffer.resize(kMaxLengthOfTruncatingStringPrintfResult + 1); + std::fill(buffer.begin(), buffer.end(), 'a'); + buffer.push_back('\0'); + std::string result = TruncatingStringPrintf("%s", buffer.data()); + EXPECT_EQ(kMaxLengthOfTruncatingStringPrintfResult, result.length()); + EXPECT_EQ(std::string::npos, result.find_first_not_of('a')); +} + +// Test that TruncatingStringPrintf does not change errno. +TEST(PartitionAllocStringPrintfTest, TruncatingStringPrintfErrno) { + errno = 1; + EXPECT_EQ("", TruncatingStringPrintf("%s", "")); + EXPECT_EQ(1, errno); +} + +} // namespace partition_alloc::internal::base
diff --git a/base/allocator/partition_allocator/partition_alloc_perftest.cc b/base/allocator/partition_allocator/partition_alloc_perftest.cc index b8b6d0a3..25a31d1 100644 --- a/base/allocator/partition_allocator/partition_alloc_perftest.cc +++ b/base/allocator/partition_allocator/partition_alloc_perftest.cc
@@ -10,11 +10,11 @@ #include "base/allocator/partition_allocator/partition_alloc.h" #include "base/allocator/partition_allocator/partition_alloc_base/logging.h" +#include "base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.h" #include "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread_for_testing.h" #include "base/allocator/partition_allocator/partition_alloc_base/time/time.h" #include "base/allocator/partition_allocator/partition_alloc_check.h" #include "base/allocator/partition_allocator/thread_cache.h" -#include "base/strings/stringprintf.h" #include "base/timer/lap_timer.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,14 +28,6 @@ namespace partition_alloc::internal { -namespace base { - -// TODO(https://crbug.com/1288247): Remove these 'using' declarations once -// the migration to the new namespaces gets done. -using ::base::StringPrintf; - -} // namespace base - namespace { // Change kTimeLimit to something higher if you need more time to capture a @@ -379,9 +371,9 @@ break; } - std::string name = - base::StringPrintf("%s%s_%s_%d", kMetricPrefixMemoryAllocation, - story_base_name, alloc_type_str, thread_count); + std::string name = base::TruncatingStringPrintf( + "%s%s_%s_%d", kMetricPrefixMemoryAllocation, story_base_name, + alloc_type_str, thread_count); DisplayResults(name + "_total", total_laps_per_second); DisplayResults(name + "_worst", min_laps_per_second);
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc index 2bb24d58..2b5a452 100644 --- a/base/allocator/partition_allocator/partition_alloc_unittest.cc +++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -28,6 +28,7 @@ #include "base/allocator/partition_allocator/partition_alloc_base/logging.h" #include "base/allocator/partition_allocator/partition_alloc_base/numerics/checked_math.h" #include "base/allocator/partition_allocator/partition_alloc_base/rand_util.h" +#include "base/allocator/partition_allocator/partition_alloc_base/strings/stringprintf.h" #include "base/allocator/partition_allocator/partition_alloc_base/thread_annotations.h" #include "base/allocator/partition_allocator/partition_alloc_base/threading/platform_thread_for_testing.h" #include "base/allocator/partition_allocator/partition_alloc_config.h" @@ -41,7 +42,6 @@ #include "base/allocator/partition_allocator/partition_tag_bitmap.h" #include "base/allocator/partition_allocator/reservation_offset_table.h" #include "base/allocator/partition_allocator/tagging.h" -#include "base/strings/stringprintf.h" #include "base/system/sys_info.h" #include "build/build_config.h" #include "build/chromecast_buildflags.h"
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 10d59a2..6761882 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -8.20220524.3.1 +8.20220525.1.1
diff --git a/build_overrides/dawn.gni b/build_overrides/dawn.gni index 25414dd..288ceb28 100644 --- a/build_overrides/dawn.gni +++ b/build_overrides/dawn.gni
@@ -4,7 +4,7 @@ # The paths to Dawn's dependencies dawn_angle_dir = "//third_party/angle" -dawn_glfw_dir = "//third_party/glfw/src" +dawn_glfw_dir = "//third_party/dawn/third_party/glfw" dawn_googletest_dir = "//third_party/googletest/src" dawn_jinja2_dir = "//third_party/jinja2" dawn_jsoncpp_dir = "//third_party/jsoncpp"
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc index b86cca4..96b098f 100644 --- a/cc/layers/heads_up_display_layer_impl.cc +++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -373,10 +373,10 @@ constexpr SkColor4f background_color = SkColors::kTransparent; constexpr GLuint msaa_sample_count = -1; constexpr bool can_use_lcd_text = true; - ri->BeginRasterCHROMIUM( - background_color.toSkColor(), needs_clear, msaa_sample_count, - gpu::raster::kNoMSAA, can_use_lcd_text, - /*visible=*/true, gfx::ColorSpace::CreateSRGB(), backing->mailbox.name); + ri->BeginRasterCHROMIUM(background_color, needs_clear, msaa_sample_count, + gpu::raster::kNoMSAA, can_use_lcd_text, + /*visible=*/true, gfx::ColorSpace::CreateSRGB(), + backing->mailbox.name); constexpr gfx::Vector2dF post_translate(0.f, 0.f); constexpr gfx::Vector2dF post_scale(1.f, 1.f); DummyImageProvider image_provider;
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc index 471991f1..2be00ce75 100644 --- a/cc/paint/oop_pixeltest.cc +++ b/cc/paint/oop_pixeltest.cc
@@ -87,6 +87,11 @@ return bitmap; } +// TODO(https://bugs.chromium.org/p/skia/issues/detail?id=13329) +SkBitmap MakeSolidColorBitmap(gfx::Size size, SkColor4f color) { + return MakeSolidColorBitmap(size, color.toSkColor()); +} + // Creates a SkImage filled with magenta and a 30x40 green rectangle. sk_sp<SkImage> MakeSkImage(const gfx::Size& size, sk_sp<SkColorSpace> color_space = nullptr) { @@ -96,9 +101,9 @@ SkBitmap::kZeroPixels_AllocFlag); SkCanvas canvas(bitmap, SkSurfaceProps{}); - canvas.drawColor(SK_ColorMAGENTA); + canvas.drawColor(SkColors::kMagenta); SkPaint green; - green.setColor(SK_ColorGREEN); + green.setColor(SkColors::kGreen); canvas.drawRect(SkRect::MakeXYWH(10, 20, 30, 40), green); return SkImage::MakeFromBitmap(bitmap); @@ -154,7 +159,7 @@ playback_rect = gfx::Rect(playback_size); } - SkColor background_color = SK_ColorBLACK; + SkColor4f background_color = SkColors::kBlack; int msaa_sample_count = 0; bool use_lcd_text = false; PlaybackImageProvider::RasterMode image_provider_raster_mode = @@ -168,7 +173,7 @@ TargetColorParams target_color_params; bool requires_clear = false; bool preclear = false; - SkColor preclear_color; + SkColor4f preclear_color; raw_ptr<ImageDecodeCache> image_cache = nullptr; std::vector<scoped_refptr<DisplayItemList>> additional_lists; raw_ptr<PaintShader> shader_with_animated_images = nullptr; @@ -216,8 +221,9 @@ if (options.preclear) { raster_implementation->BeginRasterCHROMIUM( - options.preclear_color, /*needs_clear=*/options.preclear, - options.msaa_sample_count, msaa_mode, options.use_lcd_text, + options.preclear_color, + /*needs_clear=*/options.preclear, options.msaa_sample_count, + msaa_mode, options.use_lcd_text, /*visible=*/true, options.target_color_params.color_space, mailbox.name); raster_implementation->EndRasterCHROMIUM(); @@ -228,8 +234,9 @@ // the BeginRasterCHROMIUM call above, and we want to test that it is indeed // cleared, so set |needs_clear| to false here. raster_implementation->BeginRasterCHROMIUM( - options.background_color, /*needs_clear=*/!options.preclear, - options.msaa_sample_count, msaa_mode, options.use_lcd_text, + options.background_color, + /*needs_clear=*/!options.preclear, options.msaa_sample_count, msaa_mode, + options.use_lcd_text, /*visible=*/true, options.target_color_params.color_space, mailbox.name); size_t max_op_size_limit = @@ -388,7 +395,7 @@ display_item_list->EndPaintOfUnpaired(rect); display_item_list->Finalize(); - SkBitmap expected = MakeSolidColorBitmap(rect.size(), SK_ColorBLUE); + SkBitmap expected = MakeSolidColorBitmap(rect.size(), SkColors::kBlue); auto actual = Raster(display_item_list, rect.size()); ExpectEquals(actual, expected); @@ -466,7 +473,7 @@ // green, but its record bounds are configured to clip it to the bottom right // quarter of the output. PaintFlags internal_flags; - internal_flags.setColor(SK_ColorGREEN); + internal_flags.setColor4f(SkColors::kGreen); sk_sp<PaintOpBuffer> filter_buffer(new PaintOpBuffer); filter_buffer->push<DrawRectOp>( SkRect::MakeLTRB(output_size.width() / 2.f, 0.f, output_size.width(), @@ -492,9 +499,10 @@ SkImageInfo::MakeN32Premul(output_size.width(), output_size.height()); SkBitmap expected; expected.allocPixels(ii, ii.minRowBytes()); - expected.eraseColor(SK_ColorWHITE); + // TODO(https://bugs.chromium.org/p/skia/issues/detail?id=13329) + expected.eraseColor(SkColors::kWhite.toSkColor()); expected.erase( - SK_ColorGREEN, + SkColors::kGreen.toSkColor(), SkIRect::MakeLTRB(output_size.width() / 2, output_size.height() / 2, output_size.width(), output_size.height())); @@ -615,7 +623,7 @@ // tiling starts from the origin, so starting at 2,1 in the offset_rect // below cuts off part of that, leaving two green i's. PaintFlags internal_flags; - internal_flags.setColor(SK_ColorGREEN); + internal_flags.setColor4f(SkColors::kGreen); sk_sp<PaintOpBuffer> shader_buffer(new PaintOpBuffer); shader_buffer->push<DrawRectOp>(SkRect::MakeXYWH(x_offset, y_offset, 1, 2), internal_flags); @@ -681,7 +689,8 @@ comparator); // Verify some conversion occurred here and that actual != bitmap. - EXPECT_NE(actual.getColor(0, 0), SK_ColorMAGENTA); + // TODO(https://bugs.chromium.org/p/skia/issues/detail?id=13329) + EXPECT_NE(actual.getColor(0, 0), SkColors::kMagenta.toSkColor()); } TEST_F(OopPixelTest, DrawImageWithSourceColorSpace) { @@ -823,9 +832,9 @@ expected_bitmap.allocPixels(backing_info); SkCanvas canvas(expected_bitmap, SkSurfaceProps{}); - canvas.drawColor(SK_ColorMAGENTA); + canvas.drawColor(SkColors::kMagenta); SkPaint green; - green.setColor(SK_ColorGREEN); + green.setColor(SkColors::kGreen); canvas.drawRect(SkRect::MakeXYWH(1, 2, 3, 4), green); auto* ri = raster_context_provider_->RasterInterface(); @@ -866,13 +875,13 @@ options.resource_size = rect.size(); options.full_raster_rect = rect; options.playback_rect = rect; - options.background_color = SK_ColorMAGENTA; + options.background_color = SkColors::kMagenta; options.preclear = true; - options.preclear_color = SK_ColorGREEN; + options.preclear_color = SkColors::kGreen; auto actual = Raster(display_item_list, options); - auto expected = MakeSolidColorBitmap(rect.size(), SK_ColorGREEN); + auto expected = MakeSolidColorBitmap(rect.size(), SkColors::kGreen); ExpectEquals(actual, expected); } @@ -894,12 +903,12 @@ } else { options.playback_rect = options.full_raster_rect; } - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; float arbitrary_scale = 0.25f; options.post_scale = arbitrary_scale; options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -942,12 +951,12 @@ options.content_size = gfx::Size(options.full_raster_rect.right(), options.full_raster_rect.bottom()); options.playback_rect = options.full_raster_rect; - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; float arbitrary_scale = 0.25f; options.post_scale = arbitrary_scale; options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -983,10 +992,10 @@ options.full_raster_rect.bottom()); options.playback_rect = gfx::Rect(arbitrary_offset.x() + 5, arbitrary_offset.y() + 3, 2, 3); - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Verify this is internal. EXPECT_NE(options.playback_rect.right(), options.full_raster_rect.right()); @@ -1031,11 +1040,11 @@ options.playback_rect = options.full_raster_rect; } - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; options.post_translate = gfx::Vector2dF(0.3f, 0.7f); options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1085,12 +1094,12 @@ options.playback_rect = options.full_raster_rect; } - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; float arbitrary_scale = 0.25f; options.post_scale = arbitrary_scale; options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1140,11 +1149,11 @@ } else { options.playback_rect = options.full_raster_rect; } - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; options.post_translate = gfx::Vector2dF(0.3f, 0.7f); options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1195,12 +1204,12 @@ } else { options.playback_rect = options.full_raster_rect; } - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; float arbitrary_scale = 0.25f; options.post_scale = arbitrary_scale; options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1240,13 +1249,13 @@ // Very large content rect to make this an internal tile. options.content_size = gfx::Size(1000, 1000); options.playback_rect = options.full_raster_rect; - options.background_color = SK_ColorGREEN; + options.background_color = SkColors::kGreen; options.post_translate = gfx::Vector2dF(0.3f, 0.7f); float arbitrary_scale = 1.2345f; options.post_scale = arbitrary_scale; options.requires_clear = false; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1275,12 +1284,12 @@ options.content_size = gfx::Size(options.full_raster_rect.right(), options.full_raster_rect.bottom()); options.playback_rect = options.full_raster_rect; - options.background_color = SK_ColorTRANSPARENT; + options.background_color = SkColors::kTransparent; float arbitrary_scale = 3.7f; options.post_scale = arbitrary_scale; options.requires_clear = true; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1296,7 +1305,7 @@ SkBitmap::kZeroPixels_AllocFlag); SkCanvas canvas(bitmap, SkSurfaceProps{}); - canvas.drawColor(SK_ColorTRANSPARENT); + canvas.drawColor(SkColors::kTransparent); ExpectEquals(oop_result, bitmap); } @@ -1310,12 +1319,12 @@ options.full_raster_rect = gfx::Rect(arbitrary_offset, options.resource_size); options.content_size = gfx::Size(1000, 1000); options.playback_rect = options.full_raster_rect; - options.background_color = SK_ColorTRANSPARENT; + options.background_color = SkColors::kTransparent; float arbitrary_scale = 3.7f; options.post_scale = arbitrary_scale; options.requires_clear = true; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Note that clearing of the tile should supersede any early outs due to an // empty display list. This is due to the fact that partial raster may in fact @@ -1334,7 +1343,7 @@ SkBitmap::kZeroPixels_AllocFlag); SkCanvas canvas(bitmap, SkSurfaceProps{}); - canvas.drawColor(SK_ColorTRANSPARENT); + canvas.drawColor(SkColors::kTransparent); ExpectEquals(oop_result, bitmap); } @@ -1348,12 +1357,12 @@ options.full_raster_rect.bottom()); options.playback_rect = gfx::Rect(arbitrary_offset.x() + 5, arbitrary_offset.y() + 3, 2, 4); - options.background_color = SK_ColorTRANSPARENT; + options.background_color = SkColors::kTransparent; float arbitrary_scale = 0.23f; options.post_scale = arbitrary_scale; options.requires_clear = true; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; // Make a non-empty but noop display list to avoid early outs. auto display_item_list = MakeNoopDisplayItemList(); @@ -1372,7 +1381,7 @@ canvas.drawColor(options.preclear_color); canvas.translate(-arbitrary_offset.x(), -arbitrary_offset.y()); canvas.clipRect(gfx::RectToSkRect(options.playback_rect)); - canvas.drawColor(SK_ColorTRANSPARENT, SkBlendMode::kSrc); + canvas.drawColor(SkColors::kTransparent, SkBlendMode::kSrc); ExpectEquals(oop_result, bitmap); } @@ -1395,7 +1404,7 @@ options.content_size = gfx::Size(options.full_raster_rect.right(), options.full_raster_rect.bottom()); options.playback_rect = gfx::Rect(4, 2, 5, 6); - options.background_color = SK_ColorMAGENTA; + options.background_color = SkColors::kMagenta; auto actual = Raster(display_item_list, options); ExpectEquals(actual, FILE_PATH_LITERAL("oop_draw_rect_playback_rect.png")); @@ -1423,7 +1432,7 @@ options.content_size = {25, 25}; options.full_raster_rect = {5, 5, 20, 20}; options.playback_rect = {5, 5, 13, 9}; - options.background_color = SK_ColorCYAN; + options.background_color = SkColors::kCyan; options.post_translate = {0.5f, 0.25f}; options.post_scale = 2.f; @@ -1455,7 +1464,7 @@ options.full_raster_rect = {5, 5, 20, 20}; options.playback_rect = {5, 5, 20, 20}; options.preclear = true; - options.preclear_color = SK_ColorRED; + options.preclear_color = SkColors::kRed; options.post_translate = {0.5f, 0.25f}; options.post_scale = 2.f; @@ -1490,7 +1499,7 @@ options.content_size = {20, 20}; options.full_raster_rect = {0, 10, 1, 10}; options.playback_rect = {0, 10, 1, 10}; - options.background_color = SK_ColorGRAY; + options.background_color = SkColors::kGray; options.post_translate = {0.f, 0.f}; options.post_scale = 2.f; @@ -1511,7 +1520,7 @@ display_item_list->StartPaint(); PaintFlags flags; flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(SK_ColorGREEN); + flags.setColor4f(SkColors::kGreen); display_item_list->push<DrawRectOp>( gfx::RectToSkRect(gfx::Rect(options.resource_size)), flags); display_item_list->EndPaintOfUnpaired(options.full_raster_rect); @@ -1730,7 +1739,7 @@ kTopLeft_GrSurfaceOrigin, &surface_props); SkCanvas* canvas = surface->getCanvas(); - canvas->clear(SK_ColorBLACK); + canvas->clear(SkColors::kBlack); DrawExpectedToCanvas(*canvas); surface->flushAndSubmit(); @@ -1769,7 +1778,7 @@ } SkPaint text_paint; - text_paint.setColor(SK_ColorGREEN); + text_paint.setColor(SkColors::kGreen); if (filter && (strategy == TextBlobStrategy::kDirect || strategy == TextBlobStrategy::kDrawRecord)) { text_paint.setImageFilter(std::move(filter)); @@ -1868,7 +1877,7 @@ PaintFlags text_flags; text_flags.setStyle(PaintFlags::kFill_Style); - text_flags.setColor(SK_ColorGREEN); + text_flags.setColor4f(SkColors::kGreen); if (filter && (strategy == TextBlobStrategy::kDirect || strategy == TextBlobStrategy::kDrawRecord)) { // If there's a filter, the only PaintFlags that are available for these @@ -2044,7 +2053,7 @@ display_item_list->StartPaint(); PaintFlags flags; flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(SK_ColorGREEN); + flags.setColor4f(SkColors::kGreen); display_item_list->push<DrawTextBlobOp>(BuildTextBlob(sk_typeface_1), 0.0f, kTextBlobY, flags); display_item_list->EndPaintOfUnpaired(options.full_raster_rect); @@ -2085,7 +2094,7 @@ display_item_list->StartPaint(); PaintFlags flags; flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(SK_ColorGREEN); + flags.setColor4f(SkColors::kGreen); display_item_list->push<DrawTextBlobOp>(BuildTextBlob(), 0.0f, kTextBlobY, flags); display_item_list->EndPaintOfUnpaired(options.full_raster_rect); @@ -2096,11 +2105,11 @@ // Perform the same operations on a software SkCanvas to produce an expected // bitmap. SkBitmap expected = - MakeSolidColorBitmap(options.resource_size, SK_ColorBLACK); + MakeSolidColorBitmap(options.resource_size, SkColors::kBlack); SkCanvas canvas(expected, SkSurfaceProps{}); - canvas.drawColor(SK_ColorBLACK); + canvas.drawColor(SkColors::kBlack); SkPaint paint; - paint.setColor(SK_ColorGREEN); + paint.setColor(SkColors::kGreen); canvas.drawTextBlob(BuildTextBlob(), 0, kTextBlobY, paint); // Allow 1% of pixels to be off by 1 due to differences between software and @@ -2254,9 +2263,9 @@ expected_bitmap.allocPixels(dest_info); SkCanvas canvas(expected_bitmap, SkSurfaceProps{}); - canvas.drawColor(SK_ColorMAGENTA); + canvas.drawColor(SkColors::kMagenta); SkPaint green; - green.setColor(SK_ColorGREEN); + green.setColor(SkColors::kGreen); canvas.drawRect(SkRect::MakeXYWH(1, 2, 3, 4), green); auto* ri = raster_context_provider_->RasterInterface(); @@ -2387,11 +2396,11 @@ display_item_list->push<DrawColorOp>(SkColors::kWhite, SkBlendMode::kSrc); PaintFlags flags; flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(SK_ColorGREEN); + flags.setColor4f(SkColors::kGreen); SkPath path; path.addCircle(20, 20, 10); display_item_list->push<DrawPathOp>(path, flags); - flags.setColor(SK_ColorBLUE); + flags.setColor4f(SkColors::kBlue); display_item_list->push<DrawRectOp>(SkRect::MakeWH(10, 10), flags); display_item_list->EndPaintOfUnpaired(options.full_raster_rect); display_item_list->Finalize(); @@ -2423,7 +2432,7 @@ shader_record->push<DrawColorOp>(SkColors::kWhite, SkBlendMode::kSrc); PaintFlags flags; flags.setStyle(PaintFlags::kFill_Style); - flags.setColor(SK_ColorGREEN); + flags.setColor4f(SkColors::kGreen); shader_record->push<DrawRectOp>(rect, flags); auto shader = PaintShader::MakePaintRecord( shader_record, rect, SkTileMode::kRepeat, SkTileMode::kRepeat, nullptr);
diff --git a/cc/raster/gpu_raster_buffer_provider.cc b/cc/raster/gpu_raster_buffer_provider.cc index e8bbd4d..bf0d9d7b 100644 --- a/cc/raster/gpu_raster_buffer_provider.cc +++ b/cc/raster/gpu_raster_buffer_provider.cc
@@ -389,10 +389,12 @@ bool is_raw_draw_backing = client_->is_using_raw_draw_ && !backing_->overlay_candidate; bool use_lcd_text = playback_settings.use_lcd_text && !is_raw_draw_backing; + ri->BeginRasterCHROMIUM( - raster_source->background_color().toSkColor(), mailbox_needs_clear, + raster_source->background_color(), mailbox_needs_clear, playback_settings.msaa_sample_count, msaa_mode, use_lcd_text, playback_settings.visible, color_space_, backing_->mailbox.name); + gfx::Vector2dF recording_to_raster_scale = transform.scale(); recording_to_raster_scale.Scale(1 / raster_source->recording_scale_factor()); gfx::Size content_size = raster_source->GetContentSize(transform.scale());
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index cf09cae3..1dbc83b 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1061,7 +1061,6 @@ "//chrome/browser/ui/android/appmenu:java", "//chrome/browser/ui/android/appmenu/internal:junit", "//chrome/browser/ui/android/autofill/internal:junit", - "//chrome/browser/ui/android/autofill/test:test_support_java", "//chrome/browser/ui/android/default_browser_promo:java", "//chrome/browser/ui/android/default_browser_promo:junit", "//chrome/browser/ui/android/favicon:java", @@ -1198,6 +1197,7 @@ "//third_party/google-truth:google_truth_java", "//third_party/hamcrest:hamcrest_java", "//ui/android:ui_java", + "//ui/android:ui_java_test_support", "//ui/android:ui_junit_test_support", "//ui/base/mojom:mojom_java", "//url:gurl_java",
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 4428755..55a0fe6 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
@@ -131,6 +131,7 @@ import org.chromium.chrome.browser.toolbar.top.ToolbarPhone; import org.chromium.chrome.browser.toolbar.top.ToolbarTablet; import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator; +import org.chromium.chrome.browser.toolbar.top.TopToolbarInteractabilityManager; import org.chromium.chrome.browser.toolbar.top.ViewShiftingActionBarDelegate; import org.chromium.chrome.browser.ui.TabObscuringHandler; import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinator; @@ -1825,6 +1826,14 @@ } /** + * @return A {@link TopToolbarInteractabilityManager} which allows non toolbar clients to toggle + * the interactability of elements present in the top toolbar. + */ + public @NonNull TopToolbarInteractabilityManager getTopToolbarInteractabilityManager() { + return mToolbar.getTopToolbarInteractabilityManager(); + } + + /** * Updates the current button states and calls appropriate abstract visibility methods, giving * inheriting classes the chance to update the button visuals as well. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java index 567bef6..37062785 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -67,6 +67,7 @@ import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthController; import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthCoordinatorFactory; import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager; +import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthTopToolbarDelegate; import org.chromium.chrome.browser.layouts.LayoutManager; import org.chromium.chrome.browser.layouts.LayoutStateProvider; import org.chromium.chrome.browser.layouts.LayoutType; @@ -116,6 +117,7 @@ import org.chromium.chrome.browser.toolbar.adaptive.OptionalNewTabButtonController; import org.chromium.chrome.browser.toolbar.top.ToolbarActionModeCallback; import org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer; +import org.chromium.chrome.browser.toolbar.top.TopToolbarInteractabilityManager; import org.chromium.chrome.browser.ui.appmenu.AppMenuBlocker; import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinator; import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinatorFactory; @@ -729,24 +731,49 @@ } if (IncognitoReauthManager.isIncognitoReauthFeatureAvailable()) { - TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get(); - OneshotSupplier<TabSwitcherCustomViewManager> tabSwitcherCustomViewSupplier = - new OneshotSupplierImpl<>(); - tabSwitcherCustomViewSupplier = (mActivityType == ActivityType.TABBED) - ? mStartSurfaceSupplier.get().getTabSwitcherCustomViewManagerSupplier() - : tabSwitcherCustomViewSupplier; - IncognitoReauthCoordinatorFactory incognitoReauthCoordinatorFactory = - new IncognitoReauthCoordinatorFactory(mActivity, tabModelSelector, - mModalDialogManagerSupplier.get(), new SettingsLauncherImpl(), - tabSwitcherCustomViewSupplier); - mIncognitoReauthController = new IncognitoReauthController(tabModelSelector, - mActivityLifecycleDispatcher, mLayoutStateProviderOneShotSupplier, - mProfileSupplier, incognitoReauthCoordinatorFactory); + initIncognitoReauthController(); } new OneShotCallback<>(mProfileSupplier, this::initHistoryClustersCoordinator); } + private void initIncognitoReauthController() { + TabModelSelector tabModelSelector = mTabModelSelectorSupplier.get(); + OneshotSupplier<TabSwitcherCustomViewManager> tabSwitcherCustomViewSupplier = + new OneshotSupplierImpl<>(); + tabSwitcherCustomViewSupplier = (mActivityType == ActivityType.TABBED) + ? mStartSurfaceSupplier.get().getTabSwitcherCustomViewManagerSupplier() + : tabSwitcherCustomViewSupplier; + + // TODO(crbug.com/1324211, crbug.com/1227656) : Refactor below to remove + // IncognitoReauthTopToolbarDelegate and pass TopToolbarInteractabilityManager. + IncognitoReauthTopToolbarDelegate incognitoReauthTopToolbarDelegate = null; + + if (mActivityType == ActivityType.TABBED) { + TopToolbarInteractabilityManager topToolbarInteractabilityManager = + mToolbarManager.getTopToolbarInteractabilityManager(); + incognitoReauthTopToolbarDelegate = new IncognitoReauthTopToolbarDelegate() { + @Override + public int disableNewTabButton() { + return topToolbarInteractabilityManager.disableNewTabButton(); + } + + @Override + public void enableNewTabButton(int clientToken) { + topToolbarInteractabilityManager.enableNewTabButton(clientToken); + } + }; + } + + IncognitoReauthCoordinatorFactory incognitoReauthCoordinatorFactory = + new IncognitoReauthCoordinatorFactory(mActivity, tabModelSelector, + mModalDialogManagerSupplier.get(), new SettingsLauncherImpl(), + tabSwitcherCustomViewSupplier, incognitoReauthTopToolbarDelegate); + mIncognitoReauthController = new IncognitoReauthController(tabModelSelector, + mActivityLifecycleDispatcher, mLayoutStateProviderOneShotSupplier, mProfileSupplier, + incognitoReauthCoordinatorFactory); + } + private void initHistoryClustersCoordinator(Profile profile) { if (ChromeFeatureList.isEnabled(ChromeFeatureList.HISTORY_JOURNEYS)) { mHistoryClustersCoordinator = new HistoryClustersCoordinator(profile, mActivity,
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 ad812db..a6c6195 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
@@ -45,8 +45,10 @@ import org.hamcrest.Matcher; import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -59,6 +61,8 @@ import org.chromium.base.Callback; import org.chromium.base.supplier.OneshotSupplierImpl; +import org.chromium.base.test.params.ParameterAnnotations; +import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; @@ -74,6 +78,7 @@ import org.chromium.chrome.browser.firstrun.MobileFreProgress; import org.chromium.chrome.browser.firstrun.PolicyLoadListener; import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.DisplayableProfileData; import org.chromium.chrome.browser.signin.services.FREMobileIdentityConsistencyFieldTrial; @@ -81,7 +86,7 @@ import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninChecker; import org.chromium.chrome.browser.signin.services.SigninManager; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ActivityTestUtils; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; @@ -92,10 +97,12 @@ import org.chromium.components.signin.identitymanager.ConsentLevel; import org.chromium.components.signin.identitymanager.IdentityManager; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.test.util.NightModeTestUtils; import org.chromium.ui.test.util.ViewUtils; /** Tests for the class {@link SigninFirstRunFragment}. */ -@RunWith(ChromeJUnit4ClassRunner.class) +@RunWith(ParameterizedRunner.class) +@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) public class SigninFirstRunFragmentTest { private static final String TEST_EMAIL1 = "test.account1@gmail.com"; @@ -157,6 +164,18 @@ private FakeEnterpriseInfo mFakeEnterpriseInfo = new FakeEnterpriseInfo(); private CustomSigninFirstRunFragment mFragment; + @ParameterAnnotations.UseMethodParameterBefore(NightModeTestUtils.NightModeParams.class) + public void setupNightMode(boolean nightModeEnabled) { + TestThreadUtils.runOnUiThreadBlocking(() -> { + ChromeNightModeTestUtils.setUpNightModeForChromeActivity(nightModeEnabled); + }); + } + + @BeforeClass + public static void setUpBeforeActivityLaunched() { + ChromeNightModeTestUtils.setUpNightModeBeforeChromeActivityLaunched(); + } + @Before public void setUp() { when(mExternalAuthUtilsMock.canUseGooglePlayServices()).thenReturn(true); @@ -186,6 +205,11 @@ EnterpriseInfo.setInstanceForTest(null); } + @AfterClass + public static void tearDownAfterActivityDestroyed() { + ChromeNightModeTestUtils.tearDownNightModeAfterChromeActivityDestroyed(); + } + @Test @MediumTest public void testFragmentWhenAddingAccountDynamically() { @@ -616,6 +640,20 @@ @Test @MediumTest + @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) + public void testFragmentWhenClickingOnTosLinkInDarkMode(boolean nightModeEnabled) { + TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); }); + launchActivityWithFragment(); + + onView(withId(R.id.signin_fre_footer)).perform(clickOnTosLink()); + + verify(mFirstRunPageDelegateMock) + .showInfoPage(nightModeEnabled ? R.string.google_terms_of_service_dark_mode_url + : R.string.google_terms_of_service_url); + } + + @Test + @MediumTest public void testFragmentWhenClickingOnUmaDialogLink() { TestThreadUtils.runOnUiThreadBlocking(() -> { mFragment.onNativeInitialized(); }); launchActivityWithFragment();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java index e479dad..affe3ec 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardEnrollmentDialogTest.java
@@ -33,10 +33,10 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeStringConstants; import org.chromium.chrome.browser.autofill.LegalMessageLine; -import org.chromium.chrome.browser.ui.autofill.FakeModalDialogManager; import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; import org.chromium.ui.text.NoUnderlineClickableSpan; import java.util.ArrayList;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialogTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialogTest.java index 0eabd05..ffe8035 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialogTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AutofillVirtualCardUnenrollmentDialogTest.java
@@ -32,9 +32,9 @@ import org.chromium.base.Callback; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.customtabs.CustomTabActivity; -import org.chromium.chrome.browser.ui.autofill.FakeModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; import org.chromium.ui.text.NoUnderlineClickableSpan; /**
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index eaa03c4d..e6661f0 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -13096,19 +13096,19 @@ <message name="IDS_PRIVACY_SANDBOX_DIALOG_CONSENT_TITLE" desc="CONTEXT: there are updates to the Chrome browser each month. Just after the user accepts the latest update, this message will appear. The user must make a choice, and this page can’t be dismissed until they do. The title of the page. * The title needs to be framed so that clicking the accept button makes sense * “Help us” is intended to convey a sense of collaboration. Privacy Sandbox is an ongoing multi-year effort. There are sites participating to help us and we also need users to agree to these trials so that we can measure the effectiveness of the features we're building. * “build” is intended to convey that this is a process. The user is agreeing to an effort rather than a stable set of features. Something like “make” doesn't have the same nuance.* “private web” is the promise of privacy sandbox."> Help us build a more private web </message> - <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_TITLE" translateable="false"> + <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_TITLE" desc="CONTEXT: there are updates to the Chrome browser each month. Just after the user accepts the latest update, this message will appear. The title of the page. * “Help us” is intended to convey a sense of collaboration. Privacy Sandbox is an ongoing multi-year effort. There are sites participating to help us and we also need users to agree to these trials so that we can measure the effectiveness of the features we're building. * “build” is intended to convey that this is a process. The user is agreeing to an effort rather than a stable set of features. Something like “make” doesn't have the same nuance. * See www.privacysandbox.com for more context"> Help us build a better web </message> <message name="IDS_PRIVACY_SANDBOX_DIALOG_CONSENT_BODY_HEADER_1" desc="1 of 2 subtitles on the page. We want to write for users who skim the page. That means that the page title, the sub titles, and the button label all work well together as a mini story: 1) Help us build a more private web How? 2) Limit sharing between sites 3) More control over the ads you see 4) Yes, I’ll try it"> Limited sharing between sites </message> - <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION" translateable="false"> + <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION" desc="The body text of the bubble. * “During the trials”: The trials happen in addition to today’s current system (which is based on third-party cookies). In other words, even by agreeing to or remaining in a trial, the user’s core experience doesn’t change much. This is an experiment, and we need the user to understand as much. "> During trials, Chrome is exploring ways to limit spam, fraud, and sharing between sites. Chrome also <ph name="ESTIMATE_INTERESTS_LINK">$1<ex>estimates your interests</ex></ph> that sites can use to show you ads. You can manage your interests in settings. </message> - <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_SETTINGS_LINK" translateable="false"> + <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_SETTINGS_LINK" desc="The user can choose “Go to settings” to visit chrome://settings/privacySandbox. If they do, they’ll find the toggle on for Sandbox trials, which include everything they’ve read above. They can leave trials on or turn them off on this page. Choosing “Go to settings”, the user will navigate away from this page and won’t be able to return here."> Go to settings </message> - <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION_ESTIMATES_INTERESTS_LINK" translateable="false"> + <message name="IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION_ESTIMATES_INTERESTS_LINK" desc="This will be inserted as a link in IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION instead of ESTIMATE_INTERESTS_LINK placeholder. * “estimate your interests”: Topics of interest include things like “Live comedy” and “Rock music”. Chrome estimates these interests based on the sites users visit. It’s an “estimation”, and we don’t want to suggest that we know with certainty the user’s interests. Avoid words like “guess”, “establish”, “define”, etc. (in place of “estimate”). "> estimates your interests </message> <message name="IDS_PRIVACY_SANDBOX_DIALOG_CONSENT_BODY_DESCRIPTION_1" desc="* “restrict” means to lessen. We don’t want to suggest that we’re “eliminating” cross-site tracking. * “cross-site tracking”: An example: a user visits site A and then site B. Based on how third-party cookies work today, when that user later visits site C, site C can be aware that the user visited sites A and B, and can even have some sense for what they did on those sites. * “stop ad spam and fraud”: This feature isn’t really related to restricting cross-site tracking but we combined these features in the same sentence / section for structural reasons.">
diff --git a/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..b8a6c5d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +ff7a1754ecdd3a4ecc3032fbb24bd9f4b71996ca \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION_ESTIMATES_INTERESTS_LINK.png.sha1 b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION_ESTIMATES_INTERESTS_LINK.png.sha1 new file mode 100644 index 0000000..b8a6c5d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_DESCRIPTION_ESTIMATES_INTERESTS_LINK.png.sha1
@@ -0,0 +1 @@ +ff7a1754ecdd3a4ecc3032fbb24bd9f4b71996ca \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_SETTINGS_LINK.png.sha1 b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_SETTINGS_LINK.png.sha1 new file mode 100644 index 0000000..b8a6c5d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_SETTINGS_LINK.png.sha1
@@ -0,0 +1 @@ +ff7a1754ecdd3a4ecc3032fbb24bd9f4b71996ca \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_TITLE.png.sha1 new file mode 100644 index 0000000..b8a6c5d --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_PRIVACY_SANDBOX_BUBBLE_NOTICE_TITLE.png.sha1
@@ -0,0 +1 @@ +ff7a1754ecdd3a4ecc3032fbb24bd9f4b71996ca \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 18c9ff8..4bcef28 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -619,6 +619,9 @@ <message name="IDS_SETTINGS_PASSWORDS_NOTE" desc="Label for the password note when viewing or editing a password."> Note </message> + <message name="IDS_SETTINGS_PASSWORDS_NO_NOTE_ADDED" desc="Label for the password note when the note is empty."> + No note added + </message> <message name="IDS_SETTINGS_PASSWORDS_NOTE_CHARACTER_COUNT" desc="Warning for the password note when the user exceeds or is about to exceed the character limit."> <ph name="CHARACTER_COUNT">$1<ex>950</ex></ph>/<ph name="CHARACTER_LIMIT">$2<ex>1000</ex></ph> </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORDS_NO_NOTE_ADDED.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORDS_NO_NOTE_ADDED.png.sha1 new file mode 100644 index 0000000..8a2b8a25 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_PASSWORDS_NO_NOTE_ADDED.png.sha1
@@ -0,0 +1 @@ +0d420973ec9e1ee274b31921d71d7c049d139cc5 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 4205c33..321126d 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4373,7 +4373,6 @@ "//chrome/app/theme:chrome_unscaled_resources_grit", "//chrome/app/vector_icons", "//chrome/browser/ash/system_web_apps/types:types", - "//chrome/browser/autofill_assistant/password_change/proto:proto", "//chrome/browser/cart:mojo_bindings", "//chrome/browser/enterprise/signals:utils", "//chrome/browser/first_party_sets",
diff --git a/chrome/browser/android/omnibox/omnibox_prerender.cc b/chrome/browser/android/omnibox/omnibox_prerender.cc index 16d45cd..b150aac 100644 --- a/chrome/browser/android/omnibox/omnibox_prerender.cc +++ b/chrome/browser/android/omnibox/omnibox_prerender.cc
@@ -93,7 +93,8 @@ // TODO(https://crbug.com/1310147): Consider how to co-work with preconnect. if (SearchPrefetchService* search_prefetch_service = SearchPrefetchServiceFactory::GetForProfile(profile)) { - search_prefetch_service->OnResultChanged(*autocomplete_result); + search_prefetch_service->OnResultChanged(web_contents, + *autocomplete_result); } auto* default_match = autocomplete_result->default_match(); @@ -129,20 +130,6 @@ NOTREACHED(); break; } - - if (!prerender_utils::IsSearchSuggestionPrerenderEnabled()) { - return; - } - // If search engine asks to prerender a search result explicitly, prerender - // it. - // TODO(https://crbug.com/1295170): Migrate this part to - // SearchPrefetchService, to unify pre* operations. - for (const AutocompleteMatch& match : *autocomplete_result) { - if (BaseSearchProvider::ShouldPrerender(match)) { - DoPrerender(match, profile, web_contents); - break; - } - } } void OmniboxPrerender::DoPrerender(const AutocompleteMatch& match, @@ -155,22 +142,16 @@ if (!web_contents) return; - // Treat search hint differently, since AutocompleteActionPredictor does not - // prerender search results. - // TODO(https://crbug.com/1278634): Refactor relevant code to reuse common - // code, and ensure metrics are correctly recorded. - if (AutocompleteMatch::IsSearchType(match.type)) { - DCHECK(BaseSearchProvider::ShouldPrerender(match)); - DCHECK(prerender_utils::IsSearchSuggestionPrerenderEnabled()); - PrerenderManager::CreateForWebContents(web_contents); - auto* prerender_manager = PrerenderManager::FromWebContents(web_contents); - prerender_manager->StartPrerenderSearchSuggestion(match); - } else { - gfx::Rect container_bounds = web_contents->GetContainerBounds(); - predictors::AutocompleteActionPredictorFactory::GetForProfile(profile) - ->StartPrerendering(match.destination_url, *web_contents, - container_bounds.size()); - } + // AutocompleteActionPredictor does not perform prerendering for search + // AutocompleteMatches. See `AutocompleteActionPredictor::RecommendAction` for + // more information. + // SearchPrefetchService is responsible for handling search + // AutocompleteMatches and preloading search result pages when needed. + DCHECK(!AutocompleteMatch::IsSearchType(match.type)); + gfx::Rect container_bounds = web_contents->GetContainerBounds(); + predictors::AutocompleteActionPredictorFactory::GetForProfile(profile) + ->StartPrerendering(match.destination_url, *web_contents, + container_bounds.size()); } void OmniboxPrerender::DoPreconnect(const AutocompleteMatch& match,
diff --git a/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc b/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc index 720e387..75dc9e1 100644 --- a/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc +++ b/chrome/browser/apps/app_service/browser_app_instance_tracker_browsertest.cc
@@ -718,10 +718,8 @@ IN_PROC_BROWSER_TEST_F(BrowserAppInstanceTrackerTest, TabbedSystemWebApp) { // Make sure we can use crosh. Profile* profile = ProfileManager::GetPrimaryUserProfile(); - DCHECK(web_app::WebAppProvider::GetForSystemWebApps(profile)); - web_app::WebAppProvider::GetForSystemWebApps(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + DCHECK(web_app::SystemWebAppManager::Get(profile)); + web_app::SystemWebAppManager::Get(profile)->InstallSystemAppsForTesting(); Browser* browser = nullptr; aura::Window* window = nullptr;
diff --git a/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc b/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc index 30ac637..f1367da 100644 --- a/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc +++ b/chrome/browser/apps/app_service/metrics/app_platform_metrics_browsertest.cc
@@ -39,9 +39,7 @@ } AppId InstallSystemWebApp() { - web_app::WebAppProvider::GetForSystemWebApps(profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::Get(profile())->InstallSystemAppsForTesting(); return *web_app::GetAppIdForSystemWebApp(profile(), ash::SystemWebAppType::HELP);
diff --git a/chrome/browser/ash/OWNERS b/chrome/browser/ash/OWNERS index f3692367..f4e4a5b 100644 --- a/chrome/browser/ash/OWNERS +++ b/chrome/browser/ash/OWNERS
@@ -1,2 +1,5 @@ # //chrome/browser/chromeos is moving to this directory, so share OWNERS. file://chrome/browser/chromeos/OWNERS + +per-file note_taking*=glenrob@chromium.org +per-file note_taking*=ericwilligers@chromium.org
diff --git a/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc b/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc index b74489d..8571462 100644 --- a/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc +++ b/chrome/browser/ash/accessibility/accessibility_extension_api_browsertest.cc
@@ -76,9 +76,8 @@ Profile* profile = AccessibilityManager::Get()->profile(); // Install the Settings App. - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); ASSERT_TRUE(RunSubtest("testOpenSettingsSubpage")) << message_; @@ -102,9 +101,8 @@ Profile* profile = AccessibilityManager::Get()->profile(); // Install the Settings App. - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); ASSERT_TRUE(RunSubtest("testOpenSettingsSubpageInvalidSubpage")) << message_;
diff --git a/chrome/browser/ash/app_mode/app_session_ash.cc b/chrome/browser/ash/app_mode/app_session_ash.cc index f6e3ca0e..e007f9f 100644 --- a/chrome/browser/ash/app_mode/app_session_ash.cc +++ b/chrome/browser/ash/app_mode/app_session_ash.cc
@@ -45,6 +45,7 @@ void AppSessionAsh::InitForWebKioskWithLacros(Profile* profile) { SetProfile(profile); + CreateBrowserWindowHandler(nullptr); StartFloatingAccessibilityMenu(); }
diff --git a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc index edb488c..44c5609 100644 --- a/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc +++ b/chrome/browser/ash/arc/input_overlay/display_overlay_controller.cc
@@ -55,8 +55,9 @@ } DisplayOverlayController::~DisplayOverlayController() { - RemoveOverlayIfAny(); ash::Shell::Get()->RemovePreTargetHandler(this); + touch_injector_->set_display_overlay_controller(nullptr); + RemoveOverlayIfAny(); } void DisplayOverlayController::OnWindowBoundsChanged() {
diff --git a/chrome/browser/ash/crosapi/web_app_service_ash.cc b/chrome/browser/ash/crosapi/web_app_service_ash.cc index a0b910d..7afe495 100644 --- a/chrome/browser/ash/crosapi/web_app_service_ash.cc +++ b/chrome/browser/ash/crosapi/web_app_service_ash.cc
@@ -4,6 +4,9 @@ #include "chrome/browser/ash/crosapi/web_app_service_ash.h" +#include "chrome/browser/ash/apps/apk_web_app_service.h" +#include "chrome/browser/profiles/profile_manager.h" + namespace crosapi { WebAppServiceAsh::WebAppServiceAsh() = default; @@ -39,6 +42,32 @@ } } +void WebAppServiceAsh::GetAssociatedAndroidPackage( + const std::string& app_id, + GetAssociatedAndroidPackageCallback callback) { + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + ash::ApkWebAppService* apk_web_app_service = + ash::ApkWebAppService::Get(profile); + if (!apk_web_app_service || !apk_web_app_service->IsWebOnlyTwa(app_id)) { + std::move(callback).Run({}); + return; + } + + const absl::optional<std::string> package_name = + apk_web_app_service->GetPackageNameForWebApp(app_id); + const absl::optional<std::string> fingerprint = + apk_web_app_service->GetCertificateSha256Fingerprint(app_id); + + // Any web-only TWA should have an associated package name and fingerprint. + DCHECK(package_name.has_value()); + DCHECK(fingerprint.has_value()); + + auto result = crosapi::mojom::WebAppAndroidPackage::New(); + result->package_name = *package_name; + result->sha256_fingerprint = *fingerprint; + std::move(callback).Run(std::move(result)); +} + mojom::WebAppProviderBridge* WebAppServiceAsh::GetWebAppProviderBridge() { // At the moment only a single connection is supported. // TODO(crbug.com/1174246): Support SxS lacros.
diff --git a/chrome/browser/ash/crosapi/web_app_service_ash.h b/chrome/browser/ash/crosapi/web_app_service_ash.h index 8bf2fce..c7a0748 100644 --- a/chrome/browser/ash/crosapi/web_app_service_ash.h +++ b/chrome/browser/ash/crosapi/web_app_service_ash.h
@@ -41,6 +41,10 @@ mojo::PendingRemote<mojom::WebAppProviderBridge> web_app_provider_bridge) override; + void GetAssociatedAndroidPackage( + const std::string& app_id, + GetAssociatedAndroidPackageCallback callback) override; + // Returns the web app provider bridge of the currently connected // lacros-chrome, or nullptr if there is no connection. mojom::WebAppProviderBridge* GetWebAppProviderBridge();
diff --git a/chrome/browser/ash/file_manager/copy_or_move_io_task.cc b/chrome/browser/ash/file_manager/copy_or_move_io_task.cc index 4582371..be71ab45 100644 --- a/chrome/browser/ash/file_manager/copy_or_move_io_task.cc +++ b/chrome/browser/ash/file_manager/copy_or_move_io_task.cc
@@ -62,6 +62,23 @@ std::move(complete_callback)); } +// Starts the move operation via FileSystemOperationRunner. +storage::FileSystemOperationRunner::OperationID StartMoveOnIOThread( + scoped_refptr<storage::FileSystemContext> file_system_context, + const storage::FileSystemURL& source_url, + const storage::FileSystemURL& destination_url, + storage::FileSystemOperation::CopyOrMoveOptionSet options, + const FileManagerCopyOrMoveHookDelegate::ProgressCallback& + progress_callback, + storage::FileSystemOperation::StatusCallback complete_callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + return file_system_context->operation_runner()->Move( + source_url, destination_url, options, + storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT, + std::make_unique<FileManagerCopyOrMoveHookDelegate>(progress_callback), + std::move(complete_callback)); +} + } // namespace CopyOrMoveIOTask::CopyOrMoveIOTask(
diff --git a/chrome/browser/ash/file_manager/external_filesystem_apitest.cc b/chrome/browser/ash/file_manager/external_filesystem_apitest.cc index daa29af..554b595 100644 --- a/chrome/browser/ash/file_manager/external_filesystem_apitest.cc +++ b/chrome/browser/ash/file_manager/external_filesystem_apitest.cc
@@ -704,9 +704,8 @@ void SetUpOnMainThread() override { Profile* profile = browser()->profile(); file_manager::test::AddDefaultComponentExtensionsOnMainThread(profile); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); LocalFileSystemExtensionApiTest::SetUpOnMainThread(); }
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index 5950058..df1a946 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -2095,10 +2095,8 @@ // Enable System Web Apps if needed. if (options.media_swa || options.files_swa) { - auto& system_web_app_manager = - web_app::WebAppProvider::GetForTest(profile()) - ->system_web_app_manager(); - system_web_app_manager.InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile()) + ->InstallSystemAppsForTesting(); } // For tablet mode tests, enable the Ash virtual keyboard.
diff --git a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc index 0e0c7099..10fbc884 100644 --- a/chrome/browser/ash/file_manager/file_tasks_browsertest.cc +++ b/chrome/browser/ash/file_manager/file_tasks_browsertest.cc
@@ -112,9 +112,8 @@ public: void SetUpOnMainThread() override { test::AddDefaultComponentExtensionsOnMainThread(browser()->profile()); - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); } // Tests that each of the passed expectations open by default in the expected
diff --git a/chrome/browser/ash/file_manager/io_task_util.cc b/chrome/browser/ash/file_manager/io_task_util.cc index 00df4b8..e3bee2d 100644 --- a/chrome/browser/ash/file_manager/io_task_util.cc +++ b/chrome/browser/ash/file_manager/io_task_util.cc
@@ -11,22 +11,6 @@ namespace file_manager { namespace io_task { -storage::FileSystemOperationRunner::OperationID StartMoveOnIOThread( - scoped_refptr<storage::FileSystemContext> file_system_context, - const storage::FileSystemURL& source_url, - const storage::FileSystemURL& destination_url, - storage::FileSystemOperation::CopyOrMoveOptionSet options, - const FileManagerCopyOrMoveHookDelegate::ProgressCallback& - progress_callback, - storage::FileSystemOperation::StatusCallback complete_callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return file_system_context->operation_runner()->Move( - source_url, destination_url, options, - storage::FileSystemOperation::ERROR_BEHAVIOR_ABORT, - std::make_unique<FileManagerCopyOrMoveHookDelegate>(progress_callback), - std::move(complete_callback)); -} - void GetFileMetadataOnIOThread( scoped_refptr<storage::FileSystemContext> file_system_context, const storage::FileSystemURL& url,
diff --git a/chrome/browser/ash/file_manager/io_task_util.h b/chrome/browser/ash/file_manager/io_task_util.h index 36c113d..1949972 100644 --- a/chrome/browser/ash/file_manager/io_task_util.h +++ b/chrome/browser/ash/file_manager/io_task_util.h
@@ -14,16 +14,6 @@ namespace file_manager { namespace io_task { -// Performs a move via the FileSystemOperationRunner. -storage::FileSystemOperationRunner::OperationID StartMoveOnIOThread( - scoped_refptr<storage::FileSystemContext> file_system_context, - const storage::FileSystemURL& source_url, - const storage::FileSystemURL& destination_url, - storage::FileSystemOperation::CopyOrMoveOptionSet options, - const FileManagerCopyOrMoveHookDelegate::ProgressCallback& - progress_callback, - storage::FileSystemOperation::StatusCallback complete_callback); - // Obtains metadata of a URL. Used to get the filesize of the transferred files. void GetFileMetadataOnIOThread( scoped_refptr<storage::FileSystemContext> file_system_context,
diff --git a/chrome/browser/ash/file_manager/trash_io_task.cc b/chrome/browser/ash/file_manager/trash_io_task.cc index 124e3d8..9a10b15 100644 --- a/chrome/browser/ash/file_manager/trash_io_task.cc +++ b/chrome/browser/ash/file_manager/trash_io_task.cc
@@ -54,6 +54,17 @@ url, /*exclusive=*/false, /*recursive=*/true, std::move(callback)); } +storage::FileSystemOperationRunner::OperationID StartMoveFileLocalOnIOThread( + scoped_refptr<storage::FileSystemContext> file_system_context, + const storage::FileSystemURL source_url, + const storage::FileSystemURL destination_url, + storage::FileSystemOperation::CopyOrMoveOptionSet options, + storage::FileSystemOperation::StatusCallback callback) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + return file_system_context->operation_runner()->MoveFileLocal( + source_url, destination_url, options, std::move(callback)); +} + bool WriteMetadataFileOnBlockingThread(const base::FilePath& destination_path, const std::string& contents) { // If the metadata file already exists either a previous copy failed or @@ -411,9 +422,7 @@ // File browsers generally default to preserving mtimes on copy/move so we // should do the same. storage::FileSystemOperation::CopyOrMoveOptionSet options( - storage::FileSystemOperation::CopyOrMoveOption::kPreserveLastModified, - storage::FileSystemOperation::CopyOrMoveOption:: - kRemovePartiallyCopiedFilesOnError); + storage::FileSystemOperation::CopyOrMoveOption::kPreserveLastModified); auto complete_callback = base::BindPostTask(base::SequencedTaskRunnerHandle::Get(), @@ -425,8 +434,8 @@ // callback is never invoked. content::GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&StartMoveOnIOThread, file_system_context_, source_url, - destination_url, options, base::DoNothing(), + base::BindOnce(&StartMoveFileLocalOnIOThread, file_system_context_, + source_url, destination_url, options, std::move(complete_callback)), base::BindOnce(&TrashIOTask::SetCurrentOperationID, weak_ptr_factory_.GetWeakPtr()));
diff --git a/chrome/browser/ash/first_run/first_run.cc b/chrome/browser/ash/first_run/first_run.cc index 102d8c2..f912e49b 100644 --- a/chrome/browser/ash/first_run/first_run.cc +++ b/chrome/browser/ash/first_run/first_run.cc
@@ -90,11 +90,8 @@ private: explicit AppLauncher(Profile* profile) : profile_(profile) { profile->AddObserver(this); - web_app::WebAppProvider::GetForSystemWebApps(profile) - ->system_web_app_manager() - .on_apps_synchronized() - .Post(FROM_HERE, - base::BindOnce(&AppLauncher::LaunchHelpApp, AsWeakPtr())); + web_app::SystemWebAppManager::Get(profile)->on_apps_synchronized().Post( + FROM_HERE, base::BindOnce(&AppLauncher::LaunchHelpApp, AsWeakPtr())); } ~AppLauncher() override { this->profile_->RemoveObserver(this); }
diff --git a/chrome/browser/ash/login/screens/theme_selection_screen.cc b/chrome/browser/ash/login/screens/theme_selection_screen.cc index b69150a..0692dd0 100644 --- a/chrome/browser/ash/login/screens/theme_selection_screen.cc +++ b/chrome/browser/ash/login/screens/theme_selection_screen.cc
@@ -51,7 +51,8 @@ ProfileManager::GetActiveUserProfile()->GetPrefs()->FindPreference( prefs::kDarkModeScheduleType); if (pref->IsManaged() || pref->IsRecommended() || - !chromeos::features::IsOobeThemeSelectionEnabled()) { + !chromeos::features::IsOobeThemeSelectionEnabled() || + !features::IsDarkLightModeEnabled()) { exit_callback_.Run(Result::kNotApplicable); return true; }
diff --git a/chrome/browser/ash/login/wizard_controller_browsertest.cc b/chrome/browser/ash/login/wizard_controller_browsertest.cc index cc3d917..0f8359f 100644 --- a/chrome/browser/ash/login/wizard_controller_browsertest.cc +++ b/chrome/browser/ash/login/wizard_controller_browsertest.cc
@@ -89,6 +89,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/dbus/system_clock/system_clock_client.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/dbus/constants/dbus_switches.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" #include "chromeos/dbus/shill/fake_shill_manager_client.h" @@ -3249,7 +3250,9 @@ : public WizardControllerThemeSelectionDefaultSettingsTest { public: WizardControllerThemeSelectionEnabledTest() { - feature_list_.InitAndEnableFeature(features::kEnableOobeThemeSelection); + feature_list_.InitWithFeatures({features::kEnableOobeThemeSelection, + chromeos::features::kDarkLightMode}, + {}); } base::test::ScopedFeatureList feature_list_;
diff --git a/chrome/browser/ash/settings/device_settings_service.cc b/chrome/browser/ash/settings/device_settings_service.cc index 297e853b..2822532 100644 --- a/chrome/browser/ash/settings/device_settings_service.cc +++ b/chrome/browser/ash/settings/device_settings_service.cc
@@ -185,7 +185,9 @@ if (GetOwnershipStatus() != OWNERSHIP_UNKNOWN) { // Report status immediately. base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), GetOwnershipStatus())); + FROM_HERE, + base::BindOnce(&DeviceSettingsService::ValidateOwnershipStatusAndNotify, + weak_factory_.GetWeakPtr(), std::move(callback))); } else { // If the key hasn't been loaded yet, enqueue the callback to be fired when // the next SessionManagerOperation completes. If no operation is pending, @@ -196,6 +198,18 @@ } } +void DeviceSettingsService::ValidateOwnershipStatusAndNotify( + OwnershipStatusCallback callback) { + if (GetOwnershipStatus() == OWNERSHIP_UNKNOWN) { + // OwnerKeySet() could be called upon user sign-in while event was in queue, + // which resets status to OWNERSHIP_UNKNOWN. + // We need to retry the logic in this case. + GetOwnershipStatusAsync(std::move(callback)); + return; + } + std::move(callback).Run(GetOwnershipStatus()); +} + bool DeviceSettingsService::HasPrivateOwnerKey() { return owner_settings_service_ && owner_settings_service_->IsOwner(); }
diff --git a/chrome/browser/ash/settings/device_settings_service.h b/chrome/browser/ash/settings/device_settings_service.h index 5289425..514795b 100644 --- a/chrome/browser/ash/settings/device_settings_service.h +++ b/chrome/browser/ash/settings/device_settings_service.h
@@ -246,6 +246,10 @@ SessionManagerOperation* operation, Status status); + // Helper method for GetOwnershipStatusAsync to avoid data race upon + // user sign-in. + void ValidateOwnershipStatusAndNotify(OwnershipStatusCallback callback); + // Run OwnershipStatusChanged() for observers. void NotifyOwnershipStatusChanged() const;
diff --git a/chrome/browser/ash/web_applications/camera_app/chrome_camera_app_ui_delegate.cc b/chrome/browser/ash/web_applications/camera_app/chrome_camera_app_ui_delegate.cc index 90a0632..424dff27 100644 --- a/chrome/browser/ash/web_applications/camera_app/chrome_camera_app_ui_delegate.cc +++ b/chrome/browser/ash/web_applications/camera_app/chrome_camera_app_ui_delegate.cc
@@ -199,9 +199,8 @@ auto my_files_folder_path = file_manager::util::GetMyFilesFolderForProfile(profile); - auto* provider = web_app::WebAppProvider::GetForSystemWebApps(profile); absl::optional<web_app::AppId> app_id = - provider->system_web_app_manager().GetAppIdForSystemApp( + web_app::SystemWebAppManager::Get(profile)->GetAppIdForSystemApp( ash::SystemWebAppType::CAMERA); // The launch directory is passed here rather than
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 6871c68b..b6224762 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
@@ -694,9 +694,8 @@ // Wait for system apps background tasks to start. base::RunLoop run_loop; - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .on_tasks_started() + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->on_tasks_started() .Post(FROM_HERE, run_loop.QuitClosure()); run_loop.Run();
diff --git a/chrome/browser/ash/web_applications/settings_app_integration_browsertest.cc b/chrome/browser/ash/web_applications/settings_app_integration_browsertest.cc index 11a2bf6..ac412446 100644 --- a/chrome/browser/ash/web_applications/settings_app_integration_browsertest.cc +++ b/chrome/browser/ash/web_applications/settings_app_integration_browsertest.cc
@@ -64,9 +64,8 @@ // This test verifies that the settings page is opened in a new browser window. IN_PROC_BROWSER_TEST_P(SettingsAppIntegrationTest, OmniboxNavigateToSettings) { // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); GURL old_url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL(); { content::WindowedNotificationObserver observer( @@ -95,9 +94,8 @@ RedirectIncognitoToOriginalProfile) { // Install the real SWA, not the test mock. This verifies the production // SystemAppInfo is correct. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); // When launching from incognito profile, OS Settings gets launched to the // original profile.
diff --git a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc index 0fc8268d..184e4de 100644 --- a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc +++ b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.cc
@@ -17,3 +17,7 @@ result.set_success(true); std::move(end_action_callback).Run(result); } + +void ApcExternalActionDelegate::OnInterruptStarted() {} + +void ApcExternalActionDelegate::OnInterruptFinished() {}
diff --git a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h index b4decb3..2b567e45 100644 --- a/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h +++ b/chrome/browser/autofill_assistant/password_change/apc_external_action_delegate.h
@@ -22,6 +22,8 @@ base::OnceCallback<void()> start_dom_checks_callback, base::OnceCallback<void(const autofill_assistant::external::Result& result)> end_action_callback) override; + void OnInterruptStarted() override; + void OnInterruptFinished() override; }; #endif // CHROME_BROWSER_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_APC_EXTERNAL_ACTION_DELEGATE_H_
diff --git a/chrome/browser/chromeos/OWNERS b/chrome/browser/chromeos/OWNERS index 6d0a775..4230c5f7 100644 --- a/chrome/browser/chromeos/OWNERS +++ b/chrome/browser/chromeos/OWNERS
@@ -11,5 +11,3 @@ oshima@chromium.org xiyuan@chromium.org per-file *active_directory*=file://chrome/browser/ash/authpolicy/OWNERS -per-file note_taking*=glenrob@chromium.org -per-file note_taking*=ericwilligers@chromium.org
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index 51f3485..3587c89 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -2085,13 +2085,13 @@ ExtensionFunction::ResponseAction AutotestPrivateWaitForSystemWebAppsInstallFunction::Run() { Profile* profile = Profile::FromBrowserContext(browser_context()); - web_app::WebAppProvider* provider = - web_app::WebAppProvider::GetForTest(profile); + web_app::SystemWebAppManager* swa_manager = + web_app::SystemWebAppManager::GetForTest(profile); - if (!provider) - return RespondNow(Error("Web Apps are not available for profile.")); + if (!swa_manager) + return RespondNow(Error("System Web Apps are not available for profile.")); - provider->system_web_app_manager().on_apps_synchronized().Post( + swa_manager->on_apps_synchronized().Post( FROM_HERE, base::BindOnce( &AutotestPrivateWaitForSystemWebAppsInstallFunction::Respond, this, @@ -2112,16 +2112,16 @@ ExtensionFunction::ResponseAction AutotestPrivateGetRegisteredSystemWebAppsFunction::Run() { Profile* profile = Profile::FromBrowserContext(browser_context()); - web_app::WebAppProvider* provider = - web_app::WebAppProvider::GetForTest(profile); + web_app::SystemWebAppManager* swa_manager = + web_app::SystemWebAppManager::GetForTest(profile); - if (!provider) - return RespondNow(Error("Web Apps are not available for profile.")); + if (!swa_manager) + return RespondNow(Error("System Web Apps are not available for profile.")); std::vector<api::autotest_private::SystemApp> result; for (const auto& type_and_info : - provider->system_web_app_manager().GetRegisteredSystemAppsForTesting()) { + swa_manager->GetRegisteredSystemAppsForTesting()) { api::autotest_private::SystemApp system_app; ash::SystemWebAppDelegate* delegate = type_and_info.second.get(); system_app.internal_name = delegate->GetInternalName(); @@ -2230,13 +2230,14 @@ << params->app_name << " url: " << params->url; Profile* profile = Profile::FromBrowserContext(browser_context()); - auto* provider = web_app::WebAppProvider::GetForTest(profile); - if (!provider) - return RespondNow(Error("Web Apps not enabled for profile.")); + web_app::SystemWebAppManager* swa_manager = + web_app::SystemWebAppManager::GetForTest(profile); + if (!swa_manager) + return RespondNow(Error("System Web Apps not enabled for profile.")); absl::optional<ash::SystemWebAppType> app_type; for (const auto& type_and_info : - provider->system_web_app_manager().GetRegisteredSystemAppsForTesting()) { + swa_manager->GetRegisteredSystemAppsForTesting()) { if (type_and_info.second->GetInternalName() == params->app_name) { app_type = type_and_info.first; break;
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc index 8fe3b832..24dae0f1 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc
@@ -13,7 +13,9 @@ #include "base/feature_list.h" #include "base/files/file_util.h" #include "base/format_macros.h" +#include "base/logging.h" #include "base/memory/weak_ptr.h" +#include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "chrome/browser/ash/drive/file_system_util.h" #include "chrome/browser/ash/file_manager/file_tasks_notifier.h" @@ -35,6 +37,13 @@ #include "ui/shell_dialogs/selected_file_info.h" namespace extensions { +namespace { + +std::string Redact(const base::StringPiece path) { + return LOG_IS_ON(INFO) ? base::StrCat({"'", path, "'"}) : "(redacted)"; +} + +} // namespace using ::ash::disks::DiskMountManager; using content::BrowserThread; @@ -70,7 +79,8 @@ std::vector<storage::FileSystemURL> urls; const storage::FileSystemURL url = - file_system_context->CrackURLInFirstPartyContext(GURL(params->file_url)); + file_system_context->CrackURLInFirstPartyContext( + GURL(params->file_url)); urls.push_back(url); notifier->NotifyFileTasks(urls); @@ -183,10 +193,14 @@ VolumeManager* const volume_manager = VolumeManager::Get(profile); DCHECK(volume_manager); - base::WeakPtr<Volume> volume = + const base::WeakPtr<Volume> volume = volume_manager->FindVolumeById(params->volume_id); - if (!volume.get()) - return RespondNow(Error("Volume not available")); + if (!volume) { + LOG(ERROR) << "Cannot find volume " << Redact(params->volume_id); + return RespondNow(Error(file_manager_private::ToString( + api::file_manager_private:: + MOUNT_COMPLETED_STATUS_ERROR_PATH_NOT_MOUNTED))); + } // TODO(tbarzic): Send response when callback is received, it would make more // sense than remembering issued unmount requests in file manager and showing
diff --git a/chrome/browser/chromeos/tablet_mode/chrome_content_browser_client_tablet_mode_part_browsertest.cc b/chrome/browser/chromeos/tablet_mode/chrome_content_browser_client_tablet_mode_part_browsertest.cc index 3da34e8..6a53ba5 100644 --- a/chrome/browser/chromeos/tablet_mode/chrome_content_browser_client_tablet_mode_part_browsertest.cc +++ b/chrome/browser/chromeos/tablet_mode/chrome_content_browser_client_tablet_mode_part_browsertest.cc
@@ -20,9 +20,8 @@ IN_PROC_BROWSER_TEST_F(ChromeContentBrowserClientTabletModePartTest, SettingsWindowFontSize) { // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); const blink::web_pref::WebPreferences kDefaultPrefs; const int kDefaultFontSize = kDefaultPrefs.default_font_size;
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc index b8193763..21749eb 100644 --- a/chrome/browser/client_hints/client_hints_browsertest.cc +++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -56,6 +56,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" @@ -66,6 +67,7 @@ #include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" #include "content/public/test/url_loader_interceptor.h" +#include "net/base/features.h" #include "net/dns/mock_host_resolver.h" #include "net/http/http_request_headers.h" #include "net/http/http_status_code.h" @@ -81,6 +83,8 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/cpp/network_switches.h" #include "services/network/public/cpp/resource_request.h" +#include "services/network/public/mojom/cookie_manager.mojom.h" +#include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/web_client_hints_types.mojom-shared.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gmock/include/gmock/gmock.h" @@ -1050,6 +1054,13 @@ continue; } + // Skip over the `Sec-CH-Partitioned-Cookies' client hint because it is + // only added in the presence of a valid "PartitionedCookies" Origin + // Trial token. + if (header == "sec-ch-partitioned-cookies") { + continue; + } + EXPECT_EQ(expect_client_hints, base::Contains(request.headers, header)); } } @@ -5169,6 +5180,830 @@ /*ch_ua_exist_expected=*/true); } +// TODO(crbug.com/1296161): Delete this when the partitioned cookies Origin +// Trial is over. +class PartitionedCookiesOriginTrialBrowserTest : public InProcessBrowserTest { + public: + void SetUpCommandLine(base::CommandLine* command_line) override { + // The public key for the default privatey key used by the + // tools/origin_trials/generate_token.py tool. + static constexpr char kOriginTrialTestPublicKey[] = + "dRCs+TocuKkocNKa0AtZ4awrt9XKH2SQCI6o4FY6BNA="; + command_line->AppendSwitchASCII(embedder_support::kOriginTrialPublicKey, + kOriginTrialTestPublicKey); + } + + void SetUp() override { + scoped_feature_list_.InitWithFeatureList(EnabledFeatures()); + InProcessBrowserTest::SetUp(); + } + + void TearDownOnMainThread() override { + url_loader_interceptor_.reset(); + InProcessBrowserTest::TearDownOnMainThread(); + } + + network::mojom::CookieManager* GetCookieManager() { + return browser() + ->profile() + ->GetDefaultStoragePartition() + ->GetCookieManagerForBrowserProcess(); + } + + void SetCookie(const std::string& name, + const std::string& value, + const GURL& url, + const absl::optional<net::CookiePartitionKey>& partition_key) { + auto cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting( + name, value, url.host(), "/", base::Time::Now() - base::Days(1), + base::Time::Now() + base::Days(1), base::Time::Now(), base::Time::Now(), + /*secure=*/true, /*httponly=*/false, + net::CookieSameSite::NO_RESTRICTION, + net::CookiePriority::COOKIE_PRIORITY_DEFAULT, /*same_party=*/false, + partition_key); + EXPECT_TRUE(cookie->IsCanonical()); + + base::RunLoop run_loop; + GetCookieManager()->SetCanonicalCookie( + *cookie, url, net::CookieOptions::MakeAllInclusive(), + base::BindLambdaForTesting( + [&](net::CookieAccessResult set_cookie_result) { + EXPECT_TRUE(set_cookie_result.status.IsInclude()); + run_loop.Quit(); + })); + run_loop.Run(); + } + + std::vector<net::CanonicalCookie> GetCookies(const GURL& url) { + std::vector<net::CanonicalCookie> cookies; + + base::RunLoop run_loop; + GetCookieManager()->GetCookieList( + url, net::CookieOptions::MakeAllInclusive(), + net::CookiePartitionKeyCollection::ContainsAll(), + base::BindLambdaForTesting( + [&](const std::vector<::net::CookieWithAccessResult>& result, + const std::vector<::net::CookieWithAccessResult>& + excluded_cookies) { + EXPECT_TRUE(excluded_cookies.empty()); + for (const auto& el : result) { + cookies.push_back(el.cookie); + } + run_loop.Quit(); + })); + run_loop.Run(); + + return cookies; + } + + void SetTestOptions(const OriginTrialTestOptions& test_setting, + const std::set<GURL>& expected_request_urls) { + test_options_ = test_setting; + expected_request_urls_ = expected_request_urls; + } + + void NavigateTo(const GURL& url) { + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); + } + + void NavigateAndCheckClientHint(const GURL& url, + bool expects_hint_is_present, + bool expected_hint_value) { + NavigateTo(url); + auto header_value = GetLastPartitionedCookiesClientHintValue(); + if (expects_hint_is_present) { + EXPECT_THAT(header_value, + Optional(Eq(expected_hint_value ? "?1" : "?0"))); + } else { + EXPECT_THAT(header_value, Eq(absl::nullopt)); + } + } + + void NavigateTwiceAndCheckClientHint(const GURL& url, + bool expects_hint_is_present, + bool expected_hint_value) { + NavigateTo(url); + NavigateAndCheckClientHint(url, expects_hint_is_present, + expected_hint_value); + } + + absl::optional<std::string> GetLastPartitionedCookiesClientHintValue() { + std::string header_value; + if (url_loader_interceptor_->GetLastRequestHeaders().GetHeader( + "sec-ch-partitioned-cookies", &header_value)) { + return header_value; + } + return absl::nullopt; + } + + protected: + virtual std::string BuildOriginTrialHeader() const { return ""; } + + virtual std::unique_ptr<base::FeatureList> EnabledFeatures() { + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine( + "UserAgentClientHint,CriticalClientHint,AcceptCHFrame," + "PartitionedCookies", + ""); + return feature_list; + } + + OriginTrialTestOptions test_options_; + std::set<GURL> expected_request_urls_; + std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Tests that verify Sec-CH-Partitioned-Cookies client hint is sent if and only +// if the PartitionedCookies Origin Trial token is present and valid in the +// response headers. +// +// The test Origin Trial token was generated by running: +// python tools/origin_trials/generate_token.py https://127.0.0.1:44444 \ +// PartitionedCookies \ +// --expire-timestamp=2000000000 +// +// The Origin Trial token expires in 2033. Generate a new token by then, or +// find a better way to re-generate a test trial token. +class SameOriginPartitionedCookiesOriginTrialBrowserTest + : public PartitionedCookiesOriginTrialBrowserTest { + public: + SameOriginPartitionedCookiesOriginTrialBrowserTest() = default; + + void SetUpOnMainThread() override { + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since + // the origin trial token in the response is associated with a fixed + // origin, whereas EmbeddedTestServer serves content on a random port. + url_loader_interceptor_ = std::make_unique< + URLLoaderInterceptor>(base::BindRepeating( + &SameOriginPartitionedCookiesOriginTrialBrowserTest::InterceptRequest, + base::Unretained(this))); + InProcessBrowserTest::SetUpOnMainThread(); + } + + // The URL that was used to register the Origin Trial token. + static constexpr const char kOriginUrl[] = "https://127.0.0.1:44444"; + + GURL partitioned_cookies_url() const { + return GURL( + base::StrCat({kOriginUrl, "/partitioned_cookies_same_origin.html"})); + } + + std::string BuildOriginTrialHeader() const override { + std::string headers; + + static constexpr const char kOriginTrialToken[] = + "A4s/" + "iPKfhEfgqQIIuz4zLuCpONpXOuYyJFBhBx1MfgS1aNhFujyhsg4lkfTRfjzQCI3aUbMwtN" + "m25elLTR4UIgAAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAi" + "ZmVhdHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH" + "0="; + + if (test_options_.has_accept_ch_header) { + base::StrAppend(&headers, + {"Accept-CH: ", "sec-ch-partitioned-cookies", "\n"}); + } + if (test_options_.has_critical_ch_header) { + base::StrAppend(&headers, + {"Critical-CH: ", "sec-ch-partitioned-cookies", "\n"}); + } + if (test_options_.has_ot_token) { + base::StrAppend( + &headers, + {"Origin-Trial: ", + test_options_.valid_ot_token ? kOriginTrialToken : "invalid", "\n"}); + } + + return headers; + } + + // URLLoaderInterceptor callback + bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { + if (expected_request_urls_.find(params->url_request.url) == + expected_request_urls_.end()) + return false; + + std::string path = "chrome/test/data/client_hints"; + path.append(static_cast<std::string>(params->url_request.url.path_piece())); + + std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; + base::StrAppend(&headers, {BuildOriginTrialHeader()}); + URLLoaderInterceptor::WriteResponse(path, params->client.get(), &headers, + absl::nullopt, + /*url=*/params->url_request.url); + return true; + } +}; + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + ValidTokenAndHeaderPresent) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + NavigateTwiceAndCheckClientHint(partitioned_cookies_url(), true, true); +} + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + NoTokenPresent) { + SetTestOptions( + {/*has_ot_token=*/false, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + NavigateTwiceAndCheckClientHint(partitioned_cookies_url(), false, false); +} + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + InvalidToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + NavigateTwiceAndCheckClientHint(partitioned_cookies_url(), false, false); +} + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + NoAcceptChHeader) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/false, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + NavigateTwiceAndCheckClientHint(partitioned_cookies_url(), false, false); +} + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + ConvertsPartitionedCookieOnOptOut_NoToken) { + // First check on the first request we still send the cookie and the + // Sec-CH-Partitioned-Cookies header in the false state. + SetTestOptions( + {/*has_ot_token=*/false, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + SetCookie("__Host-A", "0", GURL(kOriginUrl), + net::CookiePartitionKey::FromURLForTesting(GURL(kOriginUrl))); + + auto cookies = GetCookies(GURL(kOriginUrl)); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(partitioned_cookies_url()); + + cookies = GetCookies(GURL(kOriginUrl)); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_FALSE(cookies[0].IsPartitioned()); +} + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + ConvertsPartitionedCookieOnOptOut_InvalidToken) { + // First check on the first request we still send the cookie and the + // Sec-CH-Partitioned-Cookies header in the false state. + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + SetCookie("__Host-A", "0", GURL(kOriginUrl), + net::CookiePartitionKey::FromURLForTesting(GURL(kOriginUrl))); + + auto cookies = GetCookies(GURL(kOriginUrl)); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(partitioned_cookies_url()); + + cookies = GetCookies(GURL(kOriginUrl)); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_FALSE(cookies[0].IsPartitioned()); +} + +IN_PROC_BROWSER_TEST_F(SameOriginPartitionedCookiesOriginTrialBrowserTest, + ConvertsPartitionedCookieOnOptOut_NoAcceptCh) { + // First check on the first request we still send the cookie and the + // Sec-CH-Partitioned-Cookies header in the false state. + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/false, /*has_critical_ch_header=*/false}, + {partitioned_cookies_url()}); + + SetCookie("__Host-A", "0", GURL(kOriginUrl), + net::CookiePartitionKey::FromURLForTesting(GURL(kOriginUrl))); + + auto cookies = GetCookies(GURL(kOriginUrl)); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(partitioned_cookies_url()); + + cookies = GetCookies(GURL(kOriginUrl)); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_FALSE(cookies[0].IsPartitioned()); +} + +// Tests that verify Sec-CH-Partitioned-Cookies client hint is sent if and only +// if the PartitionedCookies Origin Trial token is present and valid in the +// response headers. +// This test is specifically to exercise that third-party embeds will get the +// client hint if the top-level origin is opted into the trial. +// +// The test Origin Trial token was generated by running: +// python tools/origin_trials/generate_token.py https://my-site.com:44444 \ +// PartitionedCookies \ +// --expire-timestamp=2000000000 +// +// The Origin Trial token expires in 2033. Generate a new token by then, or +// find a better way to re-generate a test trial token. +class ThirdPartyPartitionedCookiesOriginTrialBrowserTest + : public PartitionedCookiesOriginTrialBrowserTest { + public: + ThirdPartyPartitionedCookiesOriginTrialBrowserTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + https_server_.ServeFilesFromSourceDirectory( + "chrome/test/data/client_hints"); + https_server_.RegisterRequestMonitor(base::BindRepeating( + &ThirdPartyPartitionedCookiesOriginTrialBrowserTest:: + MonitorResourceRequest, + base::Unretained(this))); + EXPECT_TRUE(https_server_.Start()); + } + + void SetUpOnMainThread() override { + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since + // the origin trial token in the response is associated with a fixed + // origin, whereas EmbeddedTestServer serves content on a random port. + url_loader_interceptor_ = std::make_unique< + URLLoaderInterceptor>(base::BindRepeating( + &ThirdPartyPartitionedCookiesOriginTrialBrowserTest::InterceptRequest, + base::Unretained(this))); + InProcessBrowserTest::SetUpOnMainThread(); + } + + // The URL that was used to register the Origin Trial token as the first + // party. Requests to this origin should be handled by URLLoader interceptor. + static constexpr const char kFirstPartyOriginUrl[] = + "https://my-site.com:44444"; + + // The URL of the site receiving cookies. + // Requests to this origin should be handled by the test server. + static constexpr char kCookieOriginUrlNoPort[] = "https://127.0.0.1:"; + + GURL partitioned_cookies_url() const { + return GURL(base::StrCat({kCookieOriginUrlNoPort, + base::NumberToString(https_server_.port()), + "/partitioned_cookies_embeddee.html"})); + } + + GURL origin_trial_participant_url() const { + return GURL(base::StrCat( + {kFirstPartyOriginUrl, "/partitioned_cookies_embedder.html"})); + } + + GURL last_requested_url() { + base::AutoLock lock(last_request_lock_); + return last_requested_url_; + } + + absl::optional<std::string> last_sec_ch_partitioned_cookies_value() { + base::AutoLock lock(last_request_lock_); + return last_sec_ch_partitioned_cookies_value_; + } + + // Called by `https_server_`. + void MonitorResourceRequest(const net::test_server::HttpRequest& request) { + base::AutoLock lock(last_request_lock_); + last_requested_url_ = request.GetURL(); + const auto& it = request.headers.find("sec-ch-partitioned-cookies"); + last_sec_ch_partitioned_cookies_value_ = + it != request.headers.end() ? absl::make_optional(it->second) + : absl::nullopt; + } + + // URLLoaderInterceptor callback + bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { + if (expected_request_urls_.find(params->url_request.url) == + expected_request_urls_.end()) + return false; + + if (params->url_request.url.path() == + base::StrCat({"/partitioned_cookies_embedder.html"})) { + std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; + base::StrAppend(&headers, {BuildOriginTrialHeader()}); + std::string body = "<html><head>"; + base::StrAppend(&body, {"</head><body>"}); + base::StrAppend(&body, {BuildIframeHTML()}); + base::StrAppend(&body, {"</body></html>"}); + URLLoaderInterceptor::WriteResponse(headers, body, params->client.get()); + return true; + } + + NOTREACHED(); + return false; + } + + private: + std::string BuildOriginTrialHeader() const override { + std::string headers; + + // The test Origin Trial token was generated by running: + // python tools/origin_trials/generate_token.py https://my-site.com:44444 \ + // PartitionedCookies \ + // --expire-timestamp=2000000000 + // + static constexpr const char kOriginTrialToken[] = + "A56J4whdQCcxi5r8mpiT1kXOUobK2NMpZmYtJaT5HD/" + "uDBtZgrVipOJhhp4VDL37SA4l9ve6dyZCs5Gr/" + "mEuGQcAAABeeyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJmZWF" + "0dXJlIjogIlBhcnRpdGlvbmVkQ29va2llcyIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ=="; + + if (test_options_.has_accept_ch_header) { + base::StrAppend(&headers, + {"Accept-CH: ", "sec-ch-partitioned-cookies", "\n"}); + } + if (test_options_.has_critical_ch_header) { + base::StrAppend(&headers, + {"Critical-CH: ", "sec-ch-partitioned-cookies", "\n"}); + } + if (test_options_.has_ot_token) { + base::StrAppend( + &headers, + {"Origin-Trial: ", + test_options_.valid_ot_token ? kOriginTrialToken : "invalid", "\n"}); + } + + return headers; + } + + std::string BuildIframeHTML() { + std::string html = "<iframe src=\""; + base::StrAppend( + &html, + {https_server_.GetURL("/partitioned_cookies_embeddee.html").spec(), + "\"></iframe>"}); + return html; + } + + net::EmbeddedTestServer https_server_; + base::Lock last_request_lock_; + GURL last_requested_url_; + absl::optional<std::string> last_sec_ch_partitioned_cookies_value_; +}; + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + ValidTokenAndHeaderPresent) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + NavigateTo(origin_trial_participant_url()); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), "?1"); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + InvalidToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + NavigateTo(origin_trial_participant_url()); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), absl::nullopt); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + NoToken) { + SetTestOptions( + {/*has_ot_token=*/false, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + NavigateTo(origin_trial_participant_url()); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), absl::nullopt); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + NoAcceptChHeader) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/false, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + NavigateTo(origin_trial_participant_url()); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), absl::nullopt); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + ConvertsPartitionedCookieOnOptOut_NoToken) { + // First check on the first request we still send the cookie and the + // Sec-CH-Partitioned-Cookies header in the false state. + SetTestOptions( + {/*has_ot_token=*/false, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + SetCookie( + "__Host-A", "0", partitioned_cookies_url(), + net::CookiePartitionKey::FromURLForTesting(GURL(kFirstPartyOriginUrl))); + + auto cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(origin_trial_participant_url()); + // Can only test this header is present when using https_server_ because it is + // added by the network service. + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), "?0"); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + + cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_FALSE(cookies[0].IsPartitioned()); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + ConvertsPartitionedCookieOnOptOut_InvalidToken) { + // First check on the first request we still send the cookie and the + // Sec-CH-Partitioned-Cookies header in the false state. + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + SetCookie( + "__Host-A", "0", partitioned_cookies_url(), + net::CookiePartitionKey::FromURLForTesting(GURL(kFirstPartyOriginUrl))); + + auto cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(origin_trial_participant_url()); + // Can only test this header is present when using https_server_ because it is + // added by the network service. + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), "?0"); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + + cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_FALSE(cookies[0].IsPartitioned()); +} + +IN_PROC_BROWSER_TEST_F(ThirdPartyPartitionedCookiesOriginTrialBrowserTest, + ConvertsPartitionedCookieOnOptOut_NoAcceptChHeader) { + // First check on the first request we still send the cookie and the + // Sec-CH-Partitioned-Cookies header in the false state. + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/false, /*has_critical_ch_header=*/false}, + {origin_trial_participant_url()}); + + SetCookie( + "__Host-A", "0", partitioned_cookies_url(), + net::CookiePartitionKey::FromURLForTesting(GURL(kFirstPartyOriginUrl))); + + auto cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(origin_trial_participant_url()); + // Can only test this header is present when using https_server_ because it is + // added by the network service. + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), "?0"); + + EXPECT_EQ(last_requested_url(), partitioned_cookies_url()); + + cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_FALSE(cookies[0].IsPartitioned()); +} + +class EmbeddedPartitionedCookiesOriginTrialBrowserTest + : public PartitionedCookiesOriginTrialBrowserTest { + public: + EmbeddedPartitionedCookiesOriginTrialBrowserTest() = default; + + void SetUpOnMainThread() override { + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since + // the origin trial token in the response is associated with a fixed + // origin, whereas EmbeddedTestServer serves content on a random port. + url_loader_interceptor_ = + std::make_unique<URLLoaderInterceptor>(base::BindRepeating( + &EmbeddedPartitionedCookiesOriginTrialBrowserTest::InterceptRequest, + base::Unretained(this))); + InProcessBrowserTest::SetUpOnMainThread(); + } + + // URLLoaderInterceptor callback + bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { + if (expected_request_urls_.find(params->url_request.url) == + expected_request_urls_.end()) + return false; + + if (params->url_request.url.path() == + base::StrCat({"/partitioned_cookies_embedder.html"})) { + std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; + std::string body = "<html><head>"; + base::StrAppend(&body, {"</head><body>"}); + base::StrAppend(&body, {BuildIframeHTML()}); + base::StrAppend(&body, {"</body></html>"}); + URLLoaderInterceptor::WriteResponse(headers, body, params->client.get()); + return true; + } + + if (params->url_request.url.path() == + base::StrCat({"/partitioned_cookies_embeddee.html"})) { + std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; + base::StrAppend(&headers, {BuildOriginTrialHeader()}); + URLLoaderInterceptor::WriteResponse( + "chrome/test/data/client_hints/partitioned_cookies_embeddee.html", + params->client.get(), &headers, absl::nullopt, + params->url_request.url); + return true; + } + + NOTREACHED(); + return false; + } + + GURL embedder_url() const { + return GURL(base::StrCat( + {kFirstPartyOriginUrl, "/partitioned_cookies_embedder.html"})); + } + + // In this test, the OT participant is the embedded site. + GURL origin_trial_participant_url() const { + return GURL( + base::StrCat({kCookieOriginUrl, "/partitioned_cookies_embeddee.html"})); + } + + // The URL that was used to register the Origin Trial token as the first + // party. Requests to this origin should be handled by URLLoader interceptor. + static constexpr const char kFirstPartyOriginUrl[] = + "https://my-site.com:44444"; + + // The URL of the site receiving cookies. + // Requests to this origin should be handled by the test server. + static constexpr char kCookieOriginUrl[] = "https://127.0.0.1:44444"; + + std::string BuildOriginTrialHeader() const override { + std::string headers; + + static constexpr const char kOriginTrialToken[] = + "A1mBOyrOKGAaaoT8mjM1qSNrOSrdDUa9WyqicVLlDGW3feIBSdWqSiHDAXUeKkGKaVqUiC" + "X8avwCM0gpG5LtxgAAAAByeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQi" + "LCAiZmVhdHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMjAwMDAwMD" + "AwMCwgImlzVGhpcmRQYXJ0eSI6IHRydWV9"; + + if (test_options_.has_accept_ch_header) { + base::StrAppend(&headers, + {"Accept-CH: ", "sec-ch-partitioned-cookies", "\n"}); + } + if (test_options_.has_critical_ch_header) { + base::StrAppend(&headers, + {"Critical-CH: ", "sec-ch-partitioned-cookies", "\n"}); + } + if (test_options_.has_ot_token) { + base::StrAppend( + &headers, + {"Origin-Trial: ", + test_options_.valid_ot_token ? kOriginTrialToken : "invalid", "\n"}); + } + + return headers; + } + + private: + std::string BuildIframeHTML() { + std::string html = "<iframe src=\""; + base::StrAppend(&html, + {kCookieOriginUrl, "/partitioned_cookies_embeddee.html", + "\"></iframe>"}); + return html; + } +}; + +IN_PROC_BROWSER_TEST_F(EmbeddedPartitionedCookiesOriginTrialBrowserTest, + ValidTokenAndHeaderPresent) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {embedder_url(), origin_trial_participant_url()}); + + NavigateTwiceAndCheckClientHint(embedder_url(), true, true); +} + +IN_PROC_BROWSER_TEST_F(EmbeddedPartitionedCookiesOriginTrialBrowserTest, + InvalidToken) { + SetTestOptions( + {/*has_ot_token=*/false, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {embedder_url(), origin_trial_participant_url()}); + + NavigateTwiceAndCheckClientHint(embedder_url(), false, false); +} + +class PartitionedCookiesBypassOriginTrialBrowserTest + : public PartitionedCookiesOriginTrialBrowserTest { + public: + PartitionedCookiesBypassOriginTrialBrowserTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { + https_server_.ServeFilesFromSourceDirectory( + "chrome/test/data/client_hints"); + https_server_.RegisterRequestMonitor(base::BindRepeating( + &PartitionedCookiesBypassOriginTrialBrowserTest::MonitorResourceRequest, + base::Unretained(this))); + EXPECT_TRUE(https_server_.Start()); + } + + // The URL of the site receiving cookies. + // Requests to this origin should be handled by the test server. + static constexpr char kCookieOriginUrlNoPort[] = "https://127.0.0.1:"; + + GURL partitioned_cookies_url() const { + return GURL(base::StrCat({kCookieOriginUrlNoPort, + base::NumberToString(https_server_.port()), + "/partitioned_cookies_embeddee.html"})); + } + + absl::optional<std::string> last_sec_ch_partitioned_cookies_value() { + base::AutoLock lock(last_request_lock_); + return last_sec_ch_partitioned_cookies_value_; + } + + void MonitorResourceRequest(const net::test_server::HttpRequest& request) { + base::AutoLock lock(last_request_lock_); + const auto& it = request.headers.find("sec-ch-partitioned-cookies"); + last_sec_ch_partitioned_cookies_value_ = + it != request.headers.end() ? absl::make_optional(it->second) + : absl::nullopt; + } + + protected: + std::unique_ptr<base::FeatureList> EnabledFeatures() override { + std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine( + "UserAgentClientHint,CriticalClientHint,AcceptCHFrame," + "PartitionedCookies,PartitionedCookiesBypassOriginTrial", + ""); + return feature_list; + } + + net::EmbeddedTestServer https_server_; + absl::optional<std::string> last_sec_ch_partitioned_cookies_value_; + base::Lock last_request_lock_; +}; + +IN_PROC_BROWSER_TEST_F(PartitionedCookiesBypassOriginTrialBrowserTest, + ShouldAllowCookiesWithoutToken) { + SetCookie( + "__Host-A", "0", partitioned_cookies_url(), + net::CookiePartitionKey::FromURLForTesting(partitioned_cookies_url())); + + auto cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + NavigateTo(partitioned_cookies_url()); + + // Check that the partitioned cookie did not get converted to unpartitioned + // even though the site never opted into the origin trial. + cookies = GetCookies(partitioned_cookies_url()); + EXPECT_EQ(cookies.size(), 1u); + EXPECT_EQ(cookies[0].Name(), "__Host-A"); + EXPECT_TRUE(cookies[0].IsPartitioned()); + + // We will still send the client hint in the false state if there are + // partitioned cookies on the machine. + EXPECT_EQ(last_sec_ch_partitioned_cookies_value(), "?0"); +} + // CrOS multi-profiles implementation is too different for these tests. #if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.cc b/chrome/browser/component_updater/sw_reporter_installer_win.cc index 8655a2ed..177fc347 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win.cc
@@ -16,6 +16,7 @@ #include "base/base64.h" #include "base/base_paths.h" #include "base/bind.h" +#include "base/callback.h" #include "base/callback_helpers.h" #include "base/check_op.h" #include "base/command_line.h" @@ -53,6 +54,7 @@ #include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" +#include "third_party/abseil-cpp/absl/types/optional.h" // For ::GetTickCount() #include <windows.h> @@ -126,40 +128,52 @@ // Add |behaviour_flag| to |supported_behaviours| if |behaviour_name| is found // in the dictionary. Returns false on error. bool GetOptionalBehaviour( - const base::Value* invocation_params, + const base::Value::Dict& invocation_params, base::StringPiece behaviour_name, SwReporterInvocation::Behaviours behaviour_flag, SwReporterInvocation::Behaviours* supported_behaviours) { - DCHECK(invocation_params); DCHECK(supported_behaviours); // Parameters enabling behaviours are optional, but if present must be // boolean. - const base::Value* value = invocation_params->FindPath(behaviour_name); + const base::Value* value = invocation_params.Find(behaviour_name); if (value) { - if (!value->is_bool()) { + const absl::optional<bool> enabled = value->GetIfBool(); + if (!enabled.has_value()) { ReportConfigurationError(kBadParams); return false; } - if (value->GetBool()) + if (*enabled) *supported_behaviours |= behaviour_flag; } return true; } // Reads the command-line params and an UMA histogram suffix from the manifest -// and adds the invocations to be run to |out_sequence|. -// Returns whether the manifest was successfully read. -bool ExtractInvocationSequenceFromManifest( +// and schedules an invocation sequence of the software reporter if successful. +void ScheduleSoftwareReporterWithManifest( const base::FilePath& exe_path, - base::Value manifest, - safe_browsing::SwReporterInvocationSequence* out_sequence) { - // Allow an empty or missing |parameter_list| list, but log an error if - // |parameter_list| cannot be parsed as a list. - base::Value* parameter_list = manifest.FindPath("launch_params"); - if (parameter_list && !parameter_list->is_list()) { - ReportConfigurationError(kBadParams); - return false; + const base::Version& version, + base::Value::Dict manifest, + OnComponentReadyCallback ready_callback) { + safe_browsing::SwReporterInvocationSequence invocations(version); + + const std::string* prompt_seed = manifest.FindString("prompt_seed"); + if (!prompt_seed) { + ReportConfigurationError(kMissingPromptSeed); + return; + } + + // Allow an empty or missing "launch_params" list, but log an error if it + // cannot be parsed as a list. + const base::Value::List* parameter_list = nullptr; + const base::Value* launch_params = manifest.Find("launch_params"); + if (launch_params) { + parameter_list = launch_params->GetIfList(); + if (!parameter_list) { + ReportConfigurationError(kBadParams); + return; + } } // Use a random session id to link reporter invocations together. @@ -167,21 +181,23 @@ // If there are no launch parameters, create a single invocation with default // behaviour. - if (!parameter_list || parameter_list->GetListDeprecated().empty()) { + if (!parameter_list || parameter_list->empty()) { base::CommandLine command_line(exe_path); command_line.AppendSwitchASCII(chrome_cleaner::kSessionIdSwitch, session_id); - out_sequence->PushInvocation( + invocations.PushInvocation( SwReporterInvocation(command_line) .WithSupportedBehaviours( SwReporterInvocation::BEHAVIOURS_ENABLED_BY_DEFAULT)); - return true; + ready_callback.Run(*prompt_seed, std::move(invocations)); + return; } - for (const auto& invocation_params : parameter_list->GetListDeprecated()) { - if (!invocation_params.is_dict()) { + for (const base::Value& entry : *parameter_list) { + const base::Value::Dict* invocation_params = entry.GetIfDict(); + if (!invocation_params) { ReportConfigurationError(kBadParams); - return false; + return; } // Max length of the registry and histogram suffix. Fairly arbitrary: the @@ -191,30 +207,31 @@ // The suffix must be an alphanumeric string. (Empty is fine as long as the // "suffix" key is present.) - const std::string* suffix = invocation_params.FindStringPath("suffix"); + const std::string* suffix = invocation_params->FindString("suffix"); if (!suffix || !ValidateString(*suffix, std::string(), kMaxSuffixLength)) { ReportConfigurationError(kBadParams); - return false; + return; } // Build a command line for the reporter out of the executable path and the // arguments from the manifest. (The "arguments" key must be present, but // it's ok if it's an empty list or a list of empty strings.) - const base::Value* arguments = invocation_params.FindListPath("arguments"); + const base::Value::List* arguments = + invocation_params->FindList("arguments"); if (!arguments) { ReportConfigurationError(kBadParams); - return false; + return; } std::vector<std::wstring> argv = {exe_path.value()}; - for (const auto& value : arguments->GetListDeprecated()) { - if (!value.is_string()) { + for (const base::Value& value : *arguments) { + const std::string* argument = value.GetIfString(); + if (!argument) { ReportConfigurationError(kBadParams); - return false; + return; } - std::string argument = value.GetString(); - if (!argument.empty()) - argv.push_back(base::UTF8ToWide(argument)); + if (!argument->empty()) + argv.push_back(base::UTF8ToWide(*argument)); } base::CommandLine command_line(argv); @@ -224,24 +241,25 @@ // Add the histogram suffix to the command-line as well, so that the // reporter will add the same suffix to registry keys where it writes // metrics. - if (!suffix->empty()) + if (!suffix->empty()) { command_line.AppendSwitchASCII(chrome_cleaner::kRegistrySuffixSwitch, *suffix); - - SwReporterInvocation::Behaviours supported_behaviours = 0; - if (!GetOptionalBehaviour(&invocation_params, "prompt", - SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT, - &supported_behaviours)) { - return false; } - out_sequence->PushInvocation( + SwReporterInvocation::Behaviours supported_behaviours = 0; + if (!GetOptionalBehaviour(*invocation_params, "prompt", + SwReporterInvocation::BEHAVIOUR_TRIGGER_PROMPT, + &supported_behaviours)) { + return; + } + + invocations.PushInvocation( SwReporterInvocation(command_line) .WithSuffix(*suffix) .WithSupportedBehaviours(supported_behaviours)); } - return true; + ready_callback.Run(*prompt_seed, std::move(invocations)); } void ReportOnDemandUpdateSucceededHistogram(bool value) { @@ -283,14 +301,12 @@ const base::Version& version, const base::FilePath& install_dir, base::Value manifest) { - safe_browsing::SwReporterInvocationSequence invocations(version); - const base::FilePath exe_path(install_dir.Append(kSwReporterExeName)); - if (ExtractInvocationSequenceFromManifest(exe_path, std::move(manifest), - &invocations)) { - // Unless otherwise specified by a unit test, This will post - // |safe_browsing::OnSwReporterReady| to the UI thread. - on_component_ready_callback_.Run(std::move(invocations)); - } + ScheduleSoftwareReporterWithManifest( + install_dir.Append(kSwReporterExeName), version, + std::move(manifest.GetDict()), + // Unless otherwise specified by a unit test, This will post + // |safe_browsing::OnSwReporterReady| to the UI thread. + on_component_ready_callback_); } base::FilePath SwReporterInstallerPolicy::GetRelativeInstallDir() const { @@ -376,20 +392,25 @@ // Once the component is ready and browser startup is complete, run // |safe_browsing::OnSwReporterReady|. - auto lambda = [](safe_browsing::SwReporterInvocationSequence&& invocations) { - content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT}) - ->PostTask( - FROM_HERE, - base::BindOnce( - &safe_browsing::ChromeCleanerController::OnSwReporterReady, - base::Unretained( - safe_browsing::ChromeCleanerController::GetInstance()), - std::move(invocations))); - }; + using ChromeCleanerController = safe_browsing::ChromeCleanerController; + OnComponentReadyCallback ready_callback = base::BindRepeating( + [](const std::string& prompt_seed, + safe_browsing::SwReporterInvocationSequence&& invocations) { + // Unretained is safe since ChromeCleanerController is a leaked global + // singleton. + content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT}) + ->PostTask( + FROM_HERE, + base::BindOnce( + &ChromeCleanerController::OnSwReporterReady, + base::Unretained(ChromeCleanerController::GetInstance()), + prompt_seed, std::move(invocations))); + }); // Install the component. auto installer = base::MakeRefCounted<ComponentInstaller>( - std::make_unique<SwReporterInstallerPolicy>(base::BindRepeating(lambda))); + std::make_unique<SwReporterInstallerPolicy>(std::move(ready_callback))); + installer->Register(cus, runner.Release()); }
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win.h b/chrome/browser/component_updater/sw_reporter_installer_win.h index f88c730..6326163 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win.h +++ b/chrome/browser/component_updater/sw_reporter_installer_win.h
@@ -42,11 +42,13 @@ kBadTag = 0, kBadParams = 1, kMissingParams = 2, - kMaxValue = kMissingParams + kMissingPromptSeed = 3, + kMaxValue = kMissingPromptSeed }; // Callback for running the software reporter after it is downloaded. using OnComponentReadyCallback = base::RepeatingCallback<void( + const std::string& prompt_seed, safe_browsing::SwReporterInvocationSequence&& invocations)>; class SwReporterInstallerPolicy : public ComponentInstallerPolicy {
diff --git a/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc b/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc index 817a386..8b45144 100644 --- a/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc +++ b/chrome/browser/component_updater/sw_reporter_installer_win_unittest.cc
@@ -62,8 +62,11 @@ SwReporterInstallerTest& operator=(const SwReporterInstallerTest&) = delete; protected: - void SwReporterComponentReady(SwReporterInvocationSequence&& invocations) { - ASSERT_TRUE(extracted_invocations_.container().empty()); + void SwReporterComponentReady(const std::string& prompt_seed, + SwReporterInvocationSequence&& invocations) { + ASSERT_TRUE(extracted_invocations_.container().empty()) + << "SwReporterComponentReady called more than once."; + extracted_prompt_seed_ = prompt_seed; extracted_invocations_ = std::move(invocations); } @@ -102,8 +105,8 @@ } // Expects that the SwReporter was launched exactly once, with a session-id - // switch. - void ExpectDefaultInvocation() const { + // switch and the given |expected_prompt_seed|. + void ExpectDefaultInvocation(const std::string& expected_prompt_seed) const { EXPECT_EQ(default_version_, extracted_invocations_.version()); ASSERT_EQ(1U, extracted_invocations_.container().size()); @@ -119,15 +122,18 @@ EXPECT_TRUE(invocation.suffix().empty()); EXPECT_EQ(SwReporterInvocation::BEHAVIOURS_ENABLED_BY_DEFAULT, invocation.supported_behaviours()); + EXPECT_EQ(extracted_prompt_seed_, expected_prompt_seed); } // Expects that the SwReporter was launched exactly once, with the given - // |expected_suffix|, a session-id, and one |expected_additional_argument| on - // the command-line. (|expected_additional_argument| mainly exists to test - // that arguments are included at all, so there is no need to test for - // combinations of multiple arguments and switches in this function.) + // |expected_suffix| and |expected_prompt_seed|, a session-id, and optionally + // one |expected_additional_argument| on the command-line. + // (|expected_additional_argument| mainly exists to test that arguments are + // included at all, so there is no need to test for combinations of multiple + // arguments and switches in this function.) void ExpectInvocationFromManifest( const std::string& expected_suffix, + const std::string& expected_prompt_seed, const std::wstring& expected_additional_argument) { EXPECT_EQ(default_version_, extracted_invocations_.version()); ASSERT_EQ(1U, extracted_invocations_.container().size()); @@ -160,6 +166,8 @@ EXPECT_EQ(0U, invocation.supported_behaviours()); histograms_.ExpectTotalCount(kErrorHistogramName, 0); + + EXPECT_EQ(extracted_prompt_seed_, expected_prompt_seed); } // Expects that the SwReporter was launched with the given |expected_suffix|, @@ -191,10 +199,11 @@ EXPECT_EQ(expected_behaviours, invocation.supported_behaviours()); } - void ExpectLaunchError() { + void ExpectLaunchError(SoftwareReporterConfigurationError error) { // The SwReporter should not be launched, and an error should be logged. EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + EXPECT_TRUE(extracted_prompt_seed_.empty()); + histograms_.ExpectUniqueSample(kErrorHistogramName, error, 1); } base::test::ScopedFeatureList scoped_feature_list_; @@ -213,6 +222,9 @@ // Invocations captured by |SwReporterComponentReady|. SwReporterInvocationSequence extracted_invocations_; + + // Prompt seed captured by |SwReporterComponentReady|. + std::string extracted_prompt_seed_; }; TEST_F(SwReporterInstallerTest, MissingManifest) { @@ -220,7 +232,7 @@ ExpectEmptyAttributes(policy); policy.ComponentReady(default_version_, default_path_, base::Value(base::Value::Type::DICTIONARY)); - ExpectDefaultInvocation(); + ExpectLaunchError(kMissingPromptSeed); } TEST_F(SwReporterInstallerTest, MissingTag) { @@ -261,14 +273,17 @@ TEST_F(SwReporterInstallerTest, SingleInvocation) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"--engine=experimental\", \"random argument\"]," - " \"suffix\": \"TestSuffix\"," - " \"prompt\": false" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental", "random argument"], + "suffix": "TestSuffix", + "prompt": false + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); @@ -292,38 +307,43 @@ EXPECT_EQ(L"random argument", invocation.command_line().GetArgs()[0]); EXPECT_EQ("TestSuffix", invocation.suffix()); EXPECT_EQ(0U, invocation.supported_behaviours()); + + EXPECT_EQ("20220421SEED123", extracted_prompt_seed_); + histograms_.ExpectTotalCount(kErrorHistogramName, 0); } TEST_F(SwReporterInstallerTest, MultipleInvocations) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"--engine=experimental\"]," - " \"suffix\": \"TestSuffix\"," - " \"prompt\": false," - " \"allow-reporter-logs\": true" - " }," - " {" - " \"arguments\": [\"--engine=second\"]," - " \"suffix\": \"SecondSuffix\"," - " \"prompt\": true," - " \"allow-reporter-logs\": false" - " }," - " {" - " \"arguments\": [\"--engine=third\"]," - " \"suffix\": \"ThirdSuffix\"" - " }," - " {" - " \"arguments\": [\"--engine=fourth\"]," - " \"suffix\": \"FourthSuffix\"," - " \"prompt\": true," - " \"allow-reporter-logs\": true" - " }" - - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental"], + "suffix": "TestSuffix", + "prompt": false, + "allow-reporter-logs": true + }, + { + "arguments": ["--engine=second"], + "suffix": "SecondSuffix", + "prompt": true, + "allow-reporter-logs": false + }, + { + "arguments": ["--engine=third"], + "suffix": "ThirdSuffix" + }, + { + "arguments": ["--engine=fourth"], + "suffix": "FourthSuffix", + "prompt": true, + "allow-reporter-logs": true + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); @@ -351,131 +371,149 @@ &out_session_id); EXPECT_EQ(first_session_id, out_session_id); + EXPECT_EQ("20220421SEED123", extracted_prompt_seed_); + histograms_.ExpectTotalCount(kErrorHistogramName, 0); } TEST_F(SwReporterInstallerTest, MissingSuffix) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"random argument\"]" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["random argument"] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectLaunchError(); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, EmptySuffix) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"suffix\": \"\"," - " \"arguments\": [\"random argument\"]" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "suffix": "", + "arguments": ["random argument"] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectInvocationFromManifest("", L"random argument"); + ExpectInvocationFromManifest("", "20220421SEED123", L"random argument"); } TEST_F(SwReporterInstallerTest, MissingSuffixAndArgs) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectLaunchError(); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, EmptySuffixAndArgs) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"suffix\": \"\"," - " \"arguments\": []" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "suffix": "", + "arguments": [] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectInvocationFromManifest("", {}); + ExpectInvocationFromManifest("", "20220421SEED123", {}); } TEST_F(SwReporterInstallerTest, EmptySuffixAndArgsWithEmptyString) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"suffix\": \"\"," - " \"arguments\": [\"\"]" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "suffix": "", + "arguments": [""] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectInvocationFromManifest("", {}); + ExpectInvocationFromManifest("", "20220421SEED123", {}); } TEST_F(SwReporterInstallerTest, MissingArguments) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"suffix\": \"TestSuffix\"" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "suffix": "TestSuffix" + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectLaunchError(); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, EmptyArguments) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"suffix\": \"TestSuffix\"," - " \"arguments\": []" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "suffix": "TestSuffix", + "arguments": [] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectInvocationFromManifest("TestSuffix", {}); + ExpectInvocationFromManifest("TestSuffix", "20220421SEED123", {}); } TEST_F(SwReporterInstallerTest, EmptyArgumentsWithEmptyString) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"suffix\": \"TestSuffix\"," - " \"arguments\": [\"\"]" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "suffix": "TestSuffix", + "arguments": [""] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - ExpectInvocationFromManifest("TestSuffix", {}); + ExpectInvocationFromManifest("TestSuffix", "20220421SEED123", {}); } TEST_F(SwReporterInstallerTest, EmptyManifest) { @@ -484,74 +522,107 @@ static constexpr char kTestManifest[] = "{}"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - ExpectDefaultInvocation(); + ExpectLaunchError(kMissingPromptSeed); +} + +TEST_F(SwReporterInstallerTest, MissingLaunchParams) { + SwReporterInstallerPolicy policy(on_component_ready_callback_); + + static constexpr char kTestManifest[] = R"json( + { + "prompt_seed": "20220421SEED123" + })json"; + policy.ComponentReady(default_version_, default_path_, + *base::JSONReader::Read(kTestManifest)); + ExpectDefaultInvocation("20220421SEED123"); } TEST_F(SwReporterInstallerTest, EmptyLaunchParams) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = "{\"launch_params\": []}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - ExpectDefaultInvocation(); + ExpectDefaultInvocation("20220421SEED123"); +} + +TEST_F(SwReporterInstallerTest, MissingPromptSeed) { + SwReporterInstallerPolicy policy(on_component_ready_callback_); + + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental"], + "suffix": "TestSuffix" + } + ] + })json"; + policy.ComponentReady(default_version_, default_path_, + *base::JSONReader::Read(kTestManifest)); + ExpectLaunchError(kMissingPromptSeed); } TEST_F(SwReporterInstallerTest, BadSuffix) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"--engine=experimental\"]," - " \"suffix\": \"invalid whitespace characters\"" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental"], + "suffix": "invalid whitespace characters" + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, SuffixTooLong) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"--engine=experimental\"]," - " \"suffix\": \"%s\"" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental"], + "suffix": "%s" + } + ], + "prompt_seed": "20220421SEED123" + })json"; std::string suffix_too_long(500, 'x'); std::string manifest = base::StringPrintf(kTestManifest, suffix_too_long.c_str()); policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(manifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, BadTypesInManifest_ArgumentsIsNotAList) { SwReporterInstallerPolicy policy(on_component_ready_callback_); // This has a string instead of a list for "arguments". - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": \"--engine=experimental\"," - " \"suffix\": \"TestSuffix\"" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": "--engine=experimental", + "suffix": "TestSuffix" + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, BadTypesInManifest_InvocationParamsIsNotAList) { @@ -559,82 +630,108 @@ // This has the invocation parameters as direct children of "launch_params", // instead of using a list. - static constexpr char kTestManifest[] = - "{\"launch_params\": " - " {" - " \"arguments\": [\"--engine=experimental\"]," - " \"suffix\": \"TestSuffix\"" - " }" - "}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": { + "arguments": ["--engine=experimental"], + "suffix": "TestSuffix" + }, + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, BadTypesInManifest_SuffixIsAList) { SwReporterInstallerPolicy policy(on_component_ready_callback_); // This has a list for suffix as well as for arguments. - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"--engine=experimental\"]," - " \"suffix\": [\"TestSuffix\"]" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental"], + "suffix": ["TestSuffix"] + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, BadTypesInManifest_PromptIsNotABoolean) { SwReporterInstallerPolicy policy(on_component_ready_callback_); // This has an int instead of a bool for prompt. - static constexpr char kTestManifest[] = - "{\"launch_params\": [" - " {" - " \"arguments\": [\"--engine=experimental\"]," - " \"suffix\": \"TestSuffix\"," - " \"prompt\": 1" - " }" - "]}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [ + { + "arguments": ["--engine=experimental"], + "suffix": "TestSuffix", + "prompt": 1 + } + ], + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, BadTypesInManifest_LaunchParamsIsScalar) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = "{\"launch_params\": 0}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": 0, + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); - - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); + ExpectLaunchError(kBadParams); } TEST_F(SwReporterInstallerTest, BadTypesInManifest_LaunchParamsIsDict) { SwReporterInstallerPolicy policy(on_component_ready_callback_); - static constexpr char kTestManifest[] = "{\"launch_params\": {}}"; + static constexpr char kTestManifest[] = R"json( + { + "launch_params": {}, + "prompt_seed": "20220421SEED123" + })json"; policy.ComponentReady(default_version_, default_path_, *base::JSONReader::Read(kTestManifest)); + ExpectLaunchError(kBadParams); +} - // The SwReporter should not be launched, and an error should be logged. - EXPECT_TRUE(extracted_invocations_.container().empty()); - histograms_.ExpectUniqueSample(kErrorHistogramName, kBadParams, 1); +TEST_F(SwReporterInstallerTest, BadTypesInManifest_PromptSeedIsList) { + SwReporterInstallerPolicy policy(on_component_ready_callback_); + + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [], + "prompt_seed": ["20220421SEED123"] + })json"; + policy.ComponentReady(default_version_, default_path_, + *base::JSONReader::Read(kTestManifest)); + ExpectLaunchError(kMissingPromptSeed); +} + +TEST_F(SwReporterInstallerTest, BadTypesInManifest_PromptSeedIsInt) { + SwReporterInstallerPolicy policy(on_component_ready_callback_); + + static constexpr char kTestManifest[] = R"json( + { + "launch_params": [], + "prompt_seed": 20220421 + })json"; + policy.ComponentReady(default_version_, default_path_, + *base::JSONReader::Read(kTestManifest)); + ExpectLaunchError(kMissingPromptSeed); } class SwReporterOnDemandFetcherTest : public ::testing::Test,
diff --git a/chrome/browser/feedback/show_feedback_page_browsertest.cc b/chrome/browser/feedback/show_feedback_page_browsertest.cc index 93497c5d..4decdb0 100644 --- a/chrome/browser/feedback/show_feedback_page_browsertest.cc +++ b/chrome/browser/feedback/show_feedback_page_browsertest.cc
@@ -59,9 +59,8 @@ // opened and the os_feedback is used when the feature kOsFeedback is enabled. IN_PROC_BROWSER_TEST_F(ShowFeedbackPageBrowserTest, OsFeedbackIsOpenedWhenFeatureEnabled) { - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); base::HistogramTester histogram_tester; EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 8b33d0c5..5bb8b57 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -5315,7 +5315,7 @@ { "name": "secondary-google-account-usage", "owners": [ "rodmartin", "sinhak", "chromeos-commercial-identity@google.com" ], - "expiry_milestone": 103 + "expiry_milestone": 102 }, { "name": "semantic-colors-debug-override",
diff --git a/chrome/browser/incognito/BUILD.gn b/chrome/browser/incognito/BUILD.gn index db4d169..d31184b 100644 --- a/chrome/browser/incognito/BUILD.gn +++ b/chrome/browser/incognito/BUILD.gn
@@ -20,6 +20,7 @@ "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthProperties.java", "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingSwitchPreference.java", "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthSettingUtils.java", + "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTopToolbarDelegate.java", "android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthViewBinder.java", ] deps = [
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java index 6c085f3..0f525d002 100644 --- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinator.java
@@ -39,6 +39,8 @@ // This happens when user hasn't yet interacted with tab switcher but we create // this coordinator to display a full-screen dialog. private final @Nullable TabSwitcherCustomViewManager mTabSwitcherCustomViewManager; + // This can be null if the context is not a tabbed Activity. + private final @Nullable IncognitoReauthTopToolbarDelegate mIncognitoReauthTopToolbarDelegate; private final boolean mShowFullScreen; // Non-null for full screen re-auth dialog. @@ -49,6 +51,9 @@ private IncognitoReauthDialog mIncognitoReauthDialog; private PropertyModel mPropertyModel; private PropertyModelChangeProcessor mModelChangeProcessor; + // A token returned by {@link IncognitoReauthTopToolbarDelegate} that needs to be used to + // re-enable the new tab button control state. + private @Nullable Integer mNewTabInteractabilityToken; /** * @param context The {@link Context} to use for inflating the Incognito re-auth view. @@ -64,6 +69,8 @@ * SettingsActivity}. * @param tabSwitcherCustomViewManager A {@link TabSwitcherCustomViewManager} that * allows to communicate with tab switcher to show the re-auth screen. + * @param incognitoReauthTopToolbarDelegate A {@link IncognitoReauthTopToolbarDelegate} + * responsible for controlling the interactability of the top toolbar elements. * @param showFullScreen Whether to show a fullscreen / tab based re-auth dialog. */ public IncognitoReauthCoordinator(@NonNull Context context, @@ -73,10 +80,12 @@ @NonNull IncognitoReauthManager incognitoReauthManager, @NonNull SettingsLauncher settingsLauncher, @Nullable TabSwitcherCustomViewManager tabSwitcherCustomViewManager, + @Nullable IncognitoReauthTopToolbarDelegate incognitoReauthTopToolbarDelegate, boolean showFullScreen) { mContext = context; mModalDialogManager = modalDialogManager; mTabSwitcherCustomViewManager = tabSwitcherCustomViewManager; + mIncognitoReauthTopToolbarDelegate = incognitoReauthTopToolbarDelegate; mShowFullScreen = showFullScreen; mIncognitoReauthMediator = new IncognitoReauthMediator( tabModelSelector, incognitoReauthCallback, incognitoReauthManager); @@ -89,6 +98,7 @@ mModelChangeProcessor.destroy(); } + // TODO(crbug.com/1227656): Rename the method to remove reference to Dialog. void showDialog() { mIncognitoReauthView = LayoutInflater.from(mContext).inflate(R.layout.incognito_reauth_view, null); @@ -110,9 +120,15 @@ != null : "TabSwitcherCustomViewManager can't be null."; boolean success = mTabSwitcherCustomViewManager.requestView(mIncognitoReauthView); assert success : "Unable to signal showing the re-auth screen to tab switcher."; + + assert mIncognitoReauthTopToolbarDelegate + != null : "delegate to top toolbar can't be null"; + mNewTabInteractabilityToken = mIncognitoReauthTopToolbarDelegate.disableNewTabButton(); } } + // TODO(crbug.com/1227656): Rename and possibly refactor the method to remove reference to + // Dialog. void hideDialogAndDestroy(@DialogDismissalCause int dismissalCause) { if (mShowFullScreen) { assert mIncognitoReauthDialog != null : "Incognito re-auth dialog doesn't exists."; @@ -122,6 +138,12 @@ != null : "TabSwitcherCustomViewManager can't be null."; boolean success = mTabSwitcherCustomViewManager.releaseView(); assert success : "Unable to signal removing the re-auth screen from tab switcher."; + + assert mIncognitoReauthTopToolbarDelegate + != null : "delegate to top toolbar can't be null"; + assert mNewTabInteractabilityToken != null : "Top toolbar manager was not acquired."; + mIncognitoReauthTopToolbarDelegate.enableNewTabButton(mNewTabInteractabilityToken); + mNewTabInteractabilityToken = null; } destroy(); }
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java index 7629263..62366fba 100644 --- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthCoordinatorFactory.java
@@ -25,6 +25,8 @@ private final @NonNull ModalDialogManager mModalDialogManager; private final @NonNull IncognitoReauthManager mIncognitoReauthManager; private final @NonNull SettingsLauncher mSettingsLauncher; + // This is non-null for Tabbed activity. + private final @Nullable IncognitoReauthTopToolbarDelegate mIncognitoReauthTopToolbarDelegate; // A callback controller to monitor the availability of {@link TabSwitcherCustomViewManager}. private final CallbackController mTabSwitcherCustomViewManagerController = @@ -44,16 +46,20 @@ * @param tabSwitcherCustomViewManagerOneshotSupplier A {@link OneshotSupplier * <TabSwitcherCustomViewManager>} that allows to communicate with tab switcher to * show the re-auth screen. + * @param topToolbarDelegate A {@link IncognitoReauthTopToolbarDelegate} responsible for + * controlling the interactability of the top toolbar elements. */ public IncognitoReauthCoordinatorFactory(@NonNull Context context, @NonNull TabModelSelector tabModelSelector, @NonNull ModalDialogManager modalDialogManager, @NonNull SettingsLauncher settingsLauncher, @NonNull OneshotSupplier<TabSwitcherCustomViewManager> - tabSwitcherCustomViewManagerOneshotSupplier) { + tabSwitcherCustomViewManagerOneshotSupplier, + @Nullable IncognitoReauthTopToolbarDelegate topToolbarDelegate) { mContext = context; mTabModelSelector = tabModelSelector; mModalDialogManager = modalDialogManager; + mIncognitoReauthTopToolbarDelegate = topToolbarDelegate; mIncognitoReauthManager = new IncognitoReauthManager(); mSettingsLauncher = settingsLauncher; tabSwitcherCustomViewManagerOneshotSupplier.onAvailable( @@ -72,6 +78,6 @@ boolean showFullScreen) { return new IncognitoReauthCoordinator(mContext, mTabModelSelector, mModalDialogManager, incognitoReauthCallback, mIncognitoReauthManager, mSettingsLauncher, - mTabSwitcherCustomViewManager, showFullScreen); + mTabSwitcherCustomViewManager, mIncognitoReauthTopToolbarDelegate, showFullScreen); } }
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java index 5609aa93..30b5b26 100644 --- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthDialog.java
@@ -16,6 +16,8 @@ /** * This class is responsible for managing the Incognito re-auth dialog. It handles creation, * showing and hiding of the re-auth dialog. + * + * TODO(crbug.com/1227656): Clean this up to remove references to non-fullscreen logic. */ class IncognitoReauthDialog { @NonNull
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTopToolbarDelegate.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTopToolbarDelegate.java new file mode 100644 index 0000000..76abce19 --- /dev/null +++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthTopToolbarDelegate.java
@@ -0,0 +1,13 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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.incognito.reauth; + +/** + * An interface to control the interactability of elements in the tab-switcher toolbar. + */ +public interface IncognitoReauthTopToolbarDelegate { + int disableNewTabButton(); + void enableNewTabButton(int clientToken); +}
diff --git a/chrome/browser/metrics/per_user_state_manager_chromeos.cc b/chrome/browser/metrics/per_user_state_manager_chromeos.cc index 3c90ddb..abdb33fc 100644 --- a/chrome/browser/metrics/per_user_state_manager_chromeos.cc +++ b/chrome/browser/metrics/per_user_state_manager_chromeos.cc
@@ -353,9 +353,9 @@ state_ = State::USER_LOGIN; current_user_ = user; - user->AddProfileCreatedObserver(base::BindOnce( - &PerUserStateManagerChromeOS::InitializeProfileMetricsState, - weak_ptr_factory_.GetWeakPtr())); + user->AddProfileCreatedObserver( + base::BindOnce(&PerUserStateManagerChromeOS::WaitForOwnershipStatus, + weak_ptr_factory_.GetWeakPtr())); } void PerUserStateManagerChromeOS::OnUserToBeRemoved( @@ -375,7 +375,19 @@ task_runner_->PostTask(FROM_HERE, base::BindOnce(RemoveGlobalMetricsConsent)); } -void PerUserStateManagerChromeOS::InitializeProfileMetricsState() { +void PerUserStateManagerChromeOS::WaitForOwnershipStatus() { + DCHECK_EQ(state_, State::USER_LOGIN); + + // Device ownership determination happens asynchronously in parallel with + // profile loading, so there is a chance that status is not known yet. + ash::DeviceSettingsService::Get()->GetOwnershipStatusAsync(base::BindOnce( + &PerUserStateManagerChromeOS::InitializeProfileMetricsState, + weak_ptr_factory_.GetWeakPtr())); +} + +void PerUserStateManagerChromeOS::InitializeProfileMetricsState( + ash::DeviceSettingsService::OwnershipStatus status) { + DCHECK_NE(status, ash::DeviceSettingsService::OWNERSHIP_UNKNOWN); DCHECK_EQ(state_, State::USER_LOGIN); state_ = State::USER_PROFILE_READY;
diff --git a/chrome/browser/metrics/per_user_state_manager_chromeos.h b/chrome/browser/metrics/per_user_state_manager_chromeos.h index f5691d6..607220e 100644 --- a/chrome/browser/metrics/per_user_state_manager_chromeos.h +++ b/chrome/browser/metrics/per_user_state_manager_chromeos.h
@@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/task/thread_pool.h" +#include "chrome/browser/ash/settings/device_settings_service.h" #include "chrome/browser/metrics/chrome_metrics_service_accessor.h" #include "chrome/browser/metrics/profile_pref_names.h" #include "chrome/browser/profiles/profile.h" @@ -168,6 +169,18 @@ // owned. virtual bool IsDeviceOwned() const; + // These methods are protected to avoid dependency on DeviceSettingsService + // during testing. + + // Ensures that ownership status is known before proceeding with using + // profile prefs. + virtual void WaitForOwnershipStatus(); + + // Loads appropriate prefs from |current_user_| and creates new log storage + // using profile prefs. + void InitializeProfileMetricsState( + ash::DeviceSettingsService::OwnershipStatus status); + private: // Possible states for |this|. enum class State { @@ -197,10 +210,6 @@ // ash::SessionTerminationManager::Observer: void OnSessionWillBeTerminated() override; - // Loads appropriate prefs from |current_user_| and creates new log storage - // using profile prefs. - void InitializeProfileMetricsState(); - // Updates the current user ID to |new_user_id|. Updates both the profile pref // as well as local state pref. void UpdateCurrentUserId(const std::string& new_user_id);
diff --git a/chrome/browser/metrics/per_user_state_manager_chromeos_unittest.cc b/chrome/browser/metrics/per_user_state_manager_chromeos_unittest.cc index 1079381..be1a75f0 100644 --- a/chrome/browser/metrics/per_user_state_manager_chromeos_unittest.cc +++ b/chrome/browser/metrics/per_user_state_manager_chromeos_unittest.cc
@@ -74,6 +74,12 @@ bool IsDeviceOwned() const override { return is_device_owned_; } + void WaitForOwnershipStatus() override { + InitializeProfileMetricsState( + is_device_owned_ ? ash::DeviceSettingsService::OWNERSHIP_TAKEN + : ash::DeviceSettingsService::OWNERSHIP_NONE); + } + private: bool is_log_store_set_ = false; bool is_client_id_reset_ = false;
diff --git a/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc index 774adac..9c9714b 100644 --- a/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/loading_predictor_page_load_metrics_observer.cc
@@ -66,11 +66,13 @@ return CONTINUE_OBSERVING; } -// TODO(https://crbug.com/1317494): Audit and use appropriate policy. page_load_metrics::PageLoadMetricsObserver::ObservePolicy LoadingPredictorPageLoadMetricsObserver::OnFencedFramesStart( content::NavigationHandle* navigation_handle, const GURL& currently_committed_url) { + // This class is interested only in events that are preprocessed and + // dispatched also to the outermost page at PageLoadTracker. So, this class + // doesn't need to forward events for FencedFrames. return STOP_OBSERVING; }
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index 6b3ae69..ed76813 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -119,6 +119,7 @@ sources = [ "java/src/org/chromium/chrome/browser/password_manager/ConfirmationDialogHelper.java", "java/src/org/chromium/chrome/browser/password_manager/PasswordChangeSuccessTrackerBridge.java", + "java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorder.java", "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerAndroidBackendUtil.java", "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java", "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerLifecycleHelper.java", @@ -160,6 +161,7 @@ testonly = true sources = [ + "junit/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorderTest.java", "junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerAndroidBackendUtilTest.java", "junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelperTest.java", "junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerLifecycleHelperTest.java",
diff --git a/chrome/browser/password_manager/android/credential_leak_controller_android.cc b/chrome/browser/password_manager/android/credential_leak_controller_android.cc index a81849c..dc19a0c2 100644 --- a/chrome/browser/password_manager/android/credential_leak_controller_android.cc +++ b/chrome/browser/password_manager/android/credential_leak_controller_android.cc
@@ -20,21 +20,23 @@ using password_manager::CreateDialogTraits; using password_manager::PasswordChangeSuccessTracker; using password_manager::metrics_util::LeakDialogDismissalReason; +using password_manager::metrics_util::LeakDialogMetricsRecorder; using password_manager::metrics_util::LeakDialogType; -using password_manager::metrics_util::LogLeakDialogTypeAndDismissalReason; CredentialLeakControllerAndroid::CredentialLeakControllerAndroid( password_manager::CredentialLeakType leak_type, const GURL& origin, const std::u16string& username, PasswordChangeSuccessTracker* password_change_success_tracker, - ui::WindowAndroid* window_android) + ui::WindowAndroid* window_android, + std::unique_ptr<LeakDialogMetricsRecorder> metrics_recorder) : leak_type_(leak_type), origin_(origin), username_(username), password_change_success_tracker_(password_change_success_tracker), window_android_(window_android), - leak_dialog_traits_(CreateDialogTraits(leak_type)) {} + leak_dialog_traits_(CreateDialogTraits(leak_type)), + metrics_recorder_(std::move(metrics_recorder)) {} CredentialLeakControllerAndroid::~CredentialLeakControllerAndroid() = default; @@ -44,8 +46,7 @@ } void CredentialLeakControllerAndroid::OnCancelDialog() { - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kClickedClose); delete this; } @@ -76,7 +77,7 @@ break; } - LogLeakDialogTypeAndDismissalReason(dialog_type, dismissal_reason); + metrics_recorder_->LogLeakDialogTypeAndDismissalReason(dismissal_reason); // |window_android_| might be null in tests. if (!window_android_) { @@ -108,8 +109,7 @@ } void CredentialLeakControllerAndroid::OnCloseDialog() { - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kNoDirectInteraction); delete this; }
diff --git a/chrome/browser/password_manager/android/credential_leak_controller_android.h b/chrome/browser/password_manager/android/credential_leak_controller_android.h index 27d3d23..2d84599 100644 --- a/chrome/browser/password_manager/android/credential_leak_controller_android.h +++ b/chrome/browser/password_manager/android/credential_leak_controller_android.h
@@ -29,7 +29,10 @@ const std::u16string& username, password_manager::PasswordChangeSuccessTracker* password_change_success_tracker, - ui::WindowAndroid* window_android); + ui::WindowAndroid* window_android, + // Metrics recorder for leak dialog related UMA and UKM logging. + std::unique_ptr<password_manager::metrics_util::LeakDialogMetricsRecorder> + metrics_recorder); CredentialLeakControllerAndroid(const CredentialLeakControllerAndroid&) = delete; @@ -89,6 +92,10 @@ std::unique_ptr<CredentialLeakDialogViewAndroid> dialog_view_; std::unique_ptr<password_manager::LeakDialogTraits> leak_dialog_traits_; + + // Metrics recorder for leak dialog related UMA and UKM logging. + std::unique_ptr<password_manager::metrics_util::LeakDialogMetricsRecorder> + metrics_recorder_; }; #endif // CHROME_BROWSER_PASSWORD_MANAGER_ANDROID_CREDENTIAL_LEAK_CONTROLLER_ANDROID_H_
diff --git a/chrome/browser/password_manager/android/credential_leak_controller_android_unittest.cc b/chrome/browser/password_manager/android/credential_leak_controller_android_unittest.cc index aa25759..e467779 100644 --- a/chrome/browser/password_manager/android/credential_leak_controller_android_unittest.cc +++ b/chrome/browser/password_manager/android/credential_leak_controller_android_unittest.cc
@@ -9,14 +9,20 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/mock_password_change_success_tracker.h" #include "components/password_manager/core/browser/password_change_success_tracker.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/common/password_manager_features.h" +#include "components/ukm/test_ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_source_id.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +constexpr ukm::SourceId kTestSourceId = 0x1234; + using password_manager::CreateLeakType; using password_manager::HasChangeScript; using password_manager::IsReused; @@ -25,6 +31,9 @@ using password_manager::MockPasswordChangeSuccessTracker; using password_manager::PasswordChangeSuccessTracker; using password_manager::metrics_util::LeakDialogDismissalReason; +using password_manager::metrics_util::LeakDialogMetricsRecorder; +using password_manager::metrics_util::LeakDialogType; +using UkmEntry = ukm::builders::PasswordManager_LeakWarningDialog; namespace { @@ -39,16 +48,40 @@ IsSyncing is_syncing, HasChangeScript has_change_script, PasswordChangeSuccessTracker* password_change_success_tracker = nullptr) { + password_manager::CredentialLeakType leak_type = + CreateLeakType(is_saved, is_reused, is_syncing, has_change_script); + auto recorder = std::make_unique<LeakDialogMetricsRecorder>( + kTestSourceId, password_manager::GetLeakDialogType(leak_type)); + // Set sampling rate to 100% to avoid flakiness. + recorder->SetSamplingRateForTesting(1.0); return new CredentialLeakControllerAndroid( - CreateLeakType(is_saved, is_reused, is_syncing, has_change_script), - GURL(kOrigin), kUsername, password_change_success_tracker, - /*window_android=*/nullptr); + leak_type, GURL(kOrigin), kUsername, password_change_success_tracker, + /*window_android=*/nullptr, std::move(recorder)); +} + +void CheckUkmMetricsExpectations( + ukm::TestAutoSetUkmRecorder& recorder, + LeakDialogType expected_dialog_type, + LeakDialogDismissalReason expected_dismissal_reason) { + const auto& entries = recorder.GetEntriesByName(UkmEntry::kEntryName); + EXPECT_EQ(1u, entries.size()); + for (const auto* entry : entries) { + EXPECT_EQ(kTestSourceId, entry->source_id); + recorder.ExpectEntryMetric(entry, + UkmEntry::kPasswordLeakDetectionDialogTypeName, + static_cast<int64_t>(expected_dialog_type)); + recorder.ExpectEntryMetric( + entry, UkmEntry::kPasswordLeakDetectionDialogDismissalReasonName, + static_cast<int64_t>(expected_dismissal_reason)); + } } } // namespace TEST(CredentialLeakControllerAndroidTest, ClickedCancel) { + base::test::TaskEnvironment task_environment; base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; MakeController(IsSaved(false), IsReused(true), IsSyncing(true), HasChangeScript(false)) @@ -61,10 +94,16 @@ histogram_tester.ExpectUniqueSample( "PasswordManager.LeakDetection.DialogDismissalReason.CheckupAndChange", LeakDialogDismissalReason::kClickedClose, 1); + + CheckUkmMetricsExpectations(test_ukm_recorder, + LeakDialogType::kCheckupAndChange, + LeakDialogDismissalReason::kClickedClose); } TEST(CredentialLeakControllerAndroidTest, ClickedOk) { + base::test::TaskEnvironment task_environment; base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; MakeController(IsSaved(false), IsReused(false), IsSyncing(false), HasChangeScript(false)) @@ -77,10 +116,15 @@ histogram_tester.ExpectUniqueSample( "PasswordManager.LeakDetection.DialogDismissalReason.Change", LeakDialogDismissalReason::kClickedOk, 1); + + CheckUkmMetricsExpectations(test_ukm_recorder, LeakDialogType::kChange, + LeakDialogDismissalReason::kClickedOk); } TEST(CredentialLeakControllerAndroidTest, ClickedCheckPasswords) { + base::test::TaskEnvironment task_environment; base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; MakeController(IsSaved(true), IsReused(true), IsSyncing(true), HasChangeScript(false)) @@ -93,13 +137,19 @@ histogram_tester.ExpectUniqueSample( "PasswordManager.LeakDetection.DialogDismissalReason.Checkup", LeakDialogDismissalReason::kClickedCheckPasswords, 1); + + CheckUkmMetricsExpectations( + test_ukm_recorder, LeakDialogType::kCheckup, + LeakDialogDismissalReason::kClickedCheckPasswords); } TEST(CredentialLeakControllerAndroidTest, ClickedChangePasswordAutomatically) { + base::test::TaskEnvironment task_environment; base::test::ScopedFeatureList enable_password_change; enable_password_change.InitAndEnableFeature( password_manager::features::kPasswordChange); base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; testing::NiceMock<MockPasswordChangeSuccessTracker> password_change_success_tracker; @@ -121,10 +171,16 @@ histogram_tester.ExpectUniqueSample( "PasswordManager.LeakDetection.DialogDismissalReason.ChangeAutomatically", LeakDialogDismissalReason::kClickedChangePasswordAutomatically, 1); + + CheckUkmMetricsExpectations( + test_ukm_recorder, LeakDialogType::kChangeAutomatically, + LeakDialogDismissalReason::kClickedChangePasswordAutomatically); } TEST(CredentialLeakControllerAndroidTest, NoDirectInteraction) { + base::test::TaskEnvironment task_environment; base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; MakeController(IsSaved(false), IsReused(false), IsSyncing(false), HasChangeScript(false)) @@ -137,4 +193,7 @@ histogram_tester.ExpectUniqueSample( "PasswordManager.LeakDetection.DialogDismissalReason.Change", LeakDialogDismissalReason::kNoDirectInteraction, 1); + + CheckUkmMetricsExpectations(test_ukm_recorder, LeakDialogType::kChange, + LeakDialogDismissalReason::kNoDirectInteraction); }
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/CredentialManagerLauncher.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/CredentialManagerLauncher.java index 65e73e2..4720010 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/CredentialManagerLauncher.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/CredentialManagerLauncher.java
@@ -22,7 +22,8 @@ * in enums.xml. */ @IntDef({CredentialManagerError.NO_CONTEXT, CredentialManagerError.NO_ACCOUNT_NAME, - CredentialManagerError.API_ERROR, CredentialManagerError.COUNT}) + CredentialManagerError.API_ERROR, CredentialManagerError.UNCATEGORIZED, + CredentialManagerError.COUNT}) @Retention(RetentionPolicy.SOURCE) public @interface CredentialManagerError { // There is no application context. @@ -31,7 +32,9 @@ int NO_ACCOUNT_NAME = 1; // Error encountered after calling the API to fetch the launch intent. int API_ERROR = 2; - int COUNT = 3; + // Error is not categorized. + int UNCATEGORIZED = 3; + int COUNT = 4; } /**
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorder.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorder.java new file mode 100644 index 0000000..2dbb09c --- /dev/null +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorder.java
@@ -0,0 +1,77 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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.password_manager; + +import com.google.common.base.Optional; + +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError; +import org.chromium.chrome.browser.password_manager.PasswordManagerHelper.PasswordCheckOperation; + +/** + * Records metrics for an asynchronous job or a series of jobs. The job is expected to have started + * when the {@link PasswordCheckupClientMetricsRecorder} instance is created. Histograms are + * recorded in {@link #recordMetrics(Exception) recordMetrics}. + * + * TODO(crbug.com/1326151): Report success and latency metrics. + */ +class PasswordCheckupClientMetricsRecorder { + private static final String PASSWORD_CHECKUP_HISTOGRAM_BASE = "PasswordManager.PasswordCheckup"; + private static final String RUN_PASSWORD_CHECKUP_OPERATION_SUFFIX = "RunPasswordCheckup"; + private static final String GET_BREACHED_CREDENTIALS_COUNT_OPERATION_SUFFIX = + "GetBreachedCredentialsCount"; + private static final String GET_PASSWORD_CHECKUP_INTENT_OPERATION_SUFFIX = "GetIntent"; + + private final @PasswordCheckOperation int mOperation; + + PasswordCheckupClientMetricsRecorder(@PasswordCheckOperation int operation) { + mOperation = operation; + } + + /** + * Records the metrics depending on {@link Exception} provided. + * Error codes are reported for all errors. For GMS errors, API error code is additionally + * reported. + * + * @param exception {@link Exception} instance corresponding to the occurred error + */ + void recordMetrics(Optional<Exception> exception) { + // TODO(crbug.com/1326506): Record success and latency metrics. + if (exception.isPresent()) { + recordErrorMetrics(exception.get()); + } + } + + private void recordErrorMetrics(Exception exception) { + @CredentialManagerError + int error = PasswordManagerAndroidBackendUtil.getPasswordCheckupBackendError(exception); + RecordHistogram.recordEnumeratedHistogram( + getHistogramName("Error"), error, CredentialManagerError.COUNT); + + if (error == CredentialManagerError.API_ERROR) { + int apiErrorCode = PasswordManagerAndroidBackendUtil.getApiErrorCode(exception); + RecordHistogram.recordSparseHistogram(getHistogramName("APIError"), apiErrorCode); + } + } + + private String getHistogramName(String metric) { + return PASSWORD_CHECKUP_HISTOGRAM_BASE + "." + getSuffixForOperation(mOperation) + "." + + metric; + } + + /** Returns histogram suffix (infix in real) for a given operation. */ + private static String getSuffixForOperation(@PasswordCheckOperation int operation) { + switch (operation) { + case PasswordCheckOperation.RUN_PASSWORD_CHECKUP: + return RUN_PASSWORD_CHECKUP_OPERATION_SUFFIX; + case PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT: + return GET_BREACHED_CREDENTIALS_COUNT_OPERATION_SUFFIX; + case PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT: + return GET_PASSWORD_CHECKUP_INTENT_OPERATION_SUFFIX; + default: + throw new AssertionError("All operations need to be handled."); + } + } +}
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerAndroidBackendUtil.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerAndroidBackendUtil.java index 9eec5c6..8b537cd 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerAndroidBackendUtil.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerAndroidBackendUtil.java
@@ -11,6 +11,7 @@ import com.google.android.gms.common.api.ResolvableApiException; import org.chromium.base.Log; +import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError; /** * Collection of utilities used by classes interacting with the password manager backend @@ -31,6 +32,17 @@ return AndroidBackendErrorType.UNCATEGORIZED; } + static @CredentialManagerError int getPasswordCheckupBackendError(Exception exception) { + if (exception instanceof PasswordCheckupClientHelper.PasswordCheckBackendException) { + return ((PasswordCheckupClientHelper.PasswordCheckBackendException) exception) + .errorCode; + } + if (exception instanceof ApiException) { + return CredentialManagerError.API_ERROR; + } + return CredentialManagerError.UNCATEGORIZED; + } + static int getApiErrorCode(Exception exception) { if (exception instanceof ApiException) { return ((ApiException) exception).getStatusCode(); @@ -54,4 +66,4 @@ Log.e(TAG, "Can not launch error resolution intent", e); } } -} \ No newline at end of file +}
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java index c47a828..a3d3918 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
@@ -20,6 +20,7 @@ import com.google.common.base.Optional; +import org.chromium.base.Callback; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -42,6 +43,20 @@ // all points of entry to the passwords settings. public static final String MANAGE_PASSWORDS_REFERRER = "manage-passwords-referrer"; + // Indicates the operation that was requested from the {@link PasswordCheckupClientHelper}. + @IntDef({PasswordCheckOperation.RUN_PASSWORD_CHECKUP, + PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT, + PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT}) + @Retention(RetentionPolicy.SOURCE) + public @interface PasswordCheckOperation { + /** Run password checkup. */ + int RUN_PASSWORD_CHECKUP = 0; + /** Obtain the number of breached credentials. */ + int GET_BREACHED_CREDENTIALS_COUNT = 1; + /** Obtain pending intent for launching password checkup UI */ + int GET_PASSWORD_CHECKUP_INTENT = 2; + } + private static final String UPM_VARIATION_FEATURE_PARAM = "stage"; // Loading dialog is dismissed with this delay after sending an intent to prevent @@ -74,8 +89,6 @@ "PasswordManager.PasswordCheckup.GetIntent.Latency"; private static final String PASSWORD_CHECKUP_GET_INTENT_SUCCESS_HISTOGRAM = "PasswordManager.PasswordCheckup.GetIntent.Success"; - private static final String PASSWORD_CHECKUP_GET_INTENT_ERROR_HISTOGRAM = - "PasswordManager.PasswordCheckup.GetIntent.Error"; private static final String PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM = "PasswordManager.PasswordCheckup.Launch.Success"; @@ -84,6 +97,8 @@ private static final String LOADING_DIALOG_PASSWORD_CHECKUP_HISTOGRAM = "PasswordManager.ModalLoadingDialog.PasswordCheckup.Outcome"; + private static PasswordCheckupClientMetricsRecorder sPasswordCheckupMetricsRecorderForTesting; + /** * The identifier of the loading dialog outcome. * @@ -161,6 +176,54 @@ } /** + * Asynchronously runs Password Checkup in GMS Core and stores the result in + * PasswordSpecifics then saves it to the ChromeSync module. + * + * @param referrer the place that requested to start a check. + * @param checkupClient the {@link PasswordCheckupClientHelper} instance to launch the checkup + * with. + * @param accountName the account name that is syncing passwords. If no value was provided local + * account will be used + * @param successCallback callback called when password check finishes successfully + * @param failureCallback callback called if password check encountered an error + */ + public static void runPasswordCheckupInBackground(@PasswordCheckReferrer int referrer, + PasswordCheckupClientHelper checkupClient, Optional<String> accountName, + Callback<Void> successCallback, Callback<Exception> failureCallback) { + PasswordCheckupClientMetricsRecorder passwordCheckupMetricsRecorder = + new PasswordCheckupClientMetricsRecorder( + PasswordCheckOperation.RUN_PASSWORD_CHECKUP); + checkupClient.runPasswordCheckupInBackground( + referrer, accountName, successCallback, error -> { + passwordCheckupMetricsRecorder.recordMetrics(Optional.of(error)); + failureCallback.onResult(error); + }); + } + + /** + * Asynchronously returns the number of breached credentials for the provided account. + * + * @param referrer the place that requested number of breached credentials. + * @param checkupClient the {@link PasswordCheckupClientHelper} instance to request the count + * with. + * @param accountName the account name that is syncing passwords. If no value was provided local + * account will be used. + * @param successCallback callback called with the number of breached passwords. + * @param failureCallback callback called if encountered an error. + */ + public static void getBreachedCredentialsCount(@PasswordCheckReferrer int referrer, + PasswordCheckupClientHelper checkupClient, Optional<String> accountName, + Callback<Integer> successCallback, Callback<Exception> failureCallback) { + PasswordCheckupClientMetricsRecorder passwordCheckupMetricsRecorder = + new PasswordCheckupClientMetricsRecorder( + PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT); + checkupClient.getBreachedCredentialsCount(referrer, accountName, successCallback, error -> { + passwordCheckupMetricsRecorder.recordMetrics(Optional.of(error)); + failureCallback.onResult(error); + }); + } + + /** * Checks whether the sync feature is enabled and the user has chosen to sync passwords. * Note that this doesn't mean that passwords are actively syncing. * @@ -250,18 +313,18 @@ assert checkupClient != null; loadingDialogCoordinator.show(); - + PasswordCheckupClientMetricsRecorder passwordCheckupMetricsRecorder = + new PasswordCheckupClientMetricsRecorder( + (PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT)); long startTimeMs = SystemClock.elapsedRealtime(); - checkupClient.getPasswordCheckupPendingIntent(referrer, account, + checkupClient.getPasswordCheckupIntent(referrer, account, (intent) -> PasswordManagerHelper.launchPasswordCheckupIntent( intent, startTimeMs, loadingDialogCoordinator), (error) -> { RecordHistogram.recordBooleanHistogram( PASSWORD_CHECKUP_GET_INTENT_SUCCESS_HISTOGRAM, false); - RecordHistogram.recordEnumeratedHistogram( - PASSWORD_CHECKUP_GET_INTENT_ERROR_HISTOGRAM, error, - CredentialManagerError.COUNT); + passwordCheckupMetricsRecorder.recordMetrics(Optional.of(error)); recordLoadingDialogMetrics(LOADING_DIALOG_PASSWORD_CHECKUP_HISTOGRAM, loadingDialogCoordinator.getState()); loadingDialogCoordinator.dismiss();
diff --git a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorderTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorderTest.java new file mode 100644 index 0000000..988f9722 --- /dev/null +++ b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordCheckupClientMetricsRecorderTest.java
@@ -0,0 +1,177 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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.password_manager; + +import static org.junit.Assert.assertEquals; + +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.api.Status; +import com.google.common.base.Optional; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.annotation.Config; + +import org.chromium.base.metrics.test.ShadowRecordHistogram; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError; +import org.chromium.chrome.browser.password_manager.PasswordCheckupClientHelper.PasswordCheckBackendException; +import org.chromium.chrome.browser.password_manager.PasswordManagerHelper.PasswordCheckOperation; + +import java.util.OptionalInt; + +/** + * Tests that metric reporter correctly writes the histograms depending on the operation and error. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE, shadows = {ShadowRecordHistogram.class}) +public class PasswordCheckupClientMetricsRecorderTest { + private static final String PASSWORD_CHECKUP_HISTOGRAM_BASE = "PasswordManager.PasswordCheckup"; + + @Before + public void setUp() { + ShadowRecordHistogram.reset(); + } + + private String getSuffixForOperation(@PasswordCheckOperation int operation) { + switch (operation) { + case PasswordCheckOperation.RUN_PASSWORD_CHECKUP: + return "RunPasswordCheckup"; + case PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT: + return "GetBreachedCredentialsCount"; + case PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT: + return "GetIntent"; + default: + throw new AssertionError(); + } + } + + private void checkHistogramsOnSuccess(@PasswordCheckOperation int operation) { + final String nameWithSuffix = + PASSWORD_CHECKUP_HISTOGRAM_BASE + "." + getSuffixForOperation(operation); + assertEquals(0, + ShadowRecordHistogram.getHistogramTotalCountForTesting(nameWithSuffix + ".Error")); + assertEquals(0, + ShadowRecordHistogram.getHistogramTotalCountForTesting( + nameWithSuffix + ".ApiError")); + } + + private void checkHistogramsOnFailure( + @PasswordCheckOperation int operation, int errorCode, OptionalInt apiErrorCode) { + final String nameWithSuffix = + PASSWORD_CHECKUP_HISTOGRAM_BASE + "." + getSuffixForOperation(operation); + assertEquals(1, + ShadowRecordHistogram.getHistogramValueCountForTesting( + nameWithSuffix + ".Error", errorCode)); + apiErrorCode.ifPresentOrElse(apiError + -> assertEquals(1, + ShadowRecordHistogram.getHistogramValueCountForTesting( + nameWithSuffix + ".APIError", apiError)), + () + -> assertEquals(0, + ShadowRecordHistogram.getHistogramTotalCountForTesting( + nameWithSuffix + ".APIError"))); + } + + @Test + public void testRecordsSuccessHistogramForRunPasswordCheckup() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.RUN_PASSWORD_CHECKUP; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics(Optional.absent()); + checkHistogramsOnSuccess(operation); + } + + @Test + public void testRecordsSuccessHistogramForGetBreachedCredentialsCount() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics(Optional.absent()); + checkHistogramsOnSuccess(operation); + } + + @Test + public void testRecordsSuccessHistogramForGetPasswordCheckupIntentIntent() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics(Optional.absent()); + checkHistogramsOnSuccess(operation); + } + + @Test + public void testRecordsBasicErrorHistogramForRunPasswordCheckup() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.RUN_PASSWORD_CHECKUP; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics(Optional.of( + new PasswordCheckBackendException("", CredentialManagerError.NO_CONTEXT))); + checkHistogramsOnFailure(operation, CredentialManagerError.NO_CONTEXT, OptionalInt.empty()); + } + + @Test + public void testRecordsBasicErrorHistogramForGetBreachedCredentialsCount() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics(Optional.of( + new PasswordCheckBackendException("", CredentialManagerError.NO_CONTEXT))); + checkHistogramsOnFailure(operation, CredentialManagerError.NO_CONTEXT, OptionalInt.empty()); + } + + @Test + public void testRecordsBasicErrorHistogramForGetPasswordCheckupIntentIntent() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics(Optional.of( + new PasswordCheckBackendException("", CredentialManagerError.NO_CONTEXT))); + checkHistogramsOnFailure(operation, CredentialManagerError.NO_CONTEXT, OptionalInt.empty()); + } + + @Test + public void testRecordsApiErrorHistogramForRunPasswordCheckup() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.RUN_PASSWORD_CHECKUP; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics( + Optional.of(new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)))); + checkHistogramsOnFailure(operation, CredentialManagerError.API_ERROR, + OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR)); + } + + @Test + public void testRecordsApiErrorHistogramForGetBreachedCredentialsCount() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.GET_BREACHED_CREDENTIALS_COUNT; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics( + Optional.of(new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)))); + checkHistogramsOnFailure(operation, CredentialManagerError.API_ERROR, + OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR)); + } + + @Test + public void testRecordsApiErrorHistogramForGetPasswordCheckupIntentIntent() { + @PasswordCheckOperation + int operation = PasswordCheckOperation.GET_PASSWORD_CHECKUP_INTENT; + PasswordCheckupClientMetricsRecorder metricsRecorder = + new PasswordCheckupClientMetricsRecorder(operation); + metricsRecorder.recordMetrics( + Optional.of(new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR)))); + checkHistogramsOnFailure(operation, CredentialManagerError.API_ERROR, + OptionalInt.of(CommonStatusCodes.DEVELOPER_ERROR)); + } +}
diff --git a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelperTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelperTest.java index 7b7ed2b..1e05421 100644 --- a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelperTest.java +++ b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelperTest.java
@@ -16,6 +16,9 @@ import android.app.PendingIntent; import android.app.PendingIntent.CanceledException; +import com.google.android.gms.common.api.ApiException; +import com.google.android.gms.common.api.CommonStatusCodes; +import com.google.android.gms.common.api.Status; import com.google.common.base.Optional; import org.junit.Assert; @@ -41,6 +44,7 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.loading_modal.LoadingModalDialogCoordinator; import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError; +import org.chromium.chrome.browser.password_manager.PasswordCheckupClientHelper.PasswordCheckBackendException; import org.chromium.chrome.browser.sync.SyncService; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; @@ -82,6 +86,20 @@ "PasswordManager.PasswordCheckup.GetIntent.Success"; private static final String PASSWORD_CHECKUP_GET_INTENT_ERROR_HISTOGRAM = "PasswordManager.PasswordCheckup.GetIntent.Error"; + private static final String PASSWORD_CHECKUP_GET_INTENT_API_ERROR_HISTOGRAM = + "PasswordManager.PasswordCheckup.GetIntent.APIError"; + + private static final String PASSWORD_CHECKUP_RUN_PASSWORD_CHECKUP_ERROR_HISTOGRAM = + "PasswordManager.PasswordCheckup.RunPasswordCheckup.Error"; + private static final String PASSWORD_CHECKUP_RUN_PASSWORD_CHECKUP_API_ERROR_HISTOGRAM = + "PasswordManager.PasswordCheckup.RunPasswordCheckup.APIError"; + + private static final String PASSWORD_CHECKUP_GET_BREACHED_CREDENTIALS_COUNT_ERROR_HISTOGRAM = + "PasswordManager.PasswordCheckup.GetBreachedCredentialsCount.Error"; + private static final String + PASSWORD_CHECKUP_GET_BREACHED_CREDENTIALS_COUNT_API_ERROR_HISTOGRAM = + "PasswordManager.PasswordCheckup.GetBreachedCredentialsCount.APIError"; + private static final String PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM = "PasswordManager.PasswordCheckup.Launch.Success"; @@ -299,7 +317,7 @@ mSyncServiceMock, mModalDialogManagerSupplier); verify(mPasswordCheckupClientHelperMock) - .getPasswordCheckupPendingIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), + .getPasswordCheckupIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), eq(Optional.of(TEST_EMAIL_ADDRESS)), any(Callback.class), any(Callback.class)); } @@ -313,7 +331,7 @@ mSyncServiceMock, mModalDialogManagerSupplier); verify(mPasswordCheckupClientHelperMock) - .getPasswordCheckupPendingIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), + .getPasswordCheckupIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), eq(Optional.absent()), any(Callback.class), any(Callback.class)); } @@ -355,7 +373,36 @@ @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) public void testRecordsErrorMetricsForPasswordCheckupIntent() { chooseToSyncPasswordsWithoutCustomPassphrase(); - returnErrorWhenFetchingIntentForPasswordCheckup(CredentialManagerError.API_ERROR); + returnErrorWhenFetchingIntentForPasswordCheckup( + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED)); + + PasswordManagerHelper.showPasswordCheckup(ContextUtils.getApplicationContext(), + PasswordCheckReferrer.SAFETY_CHECK, mPasswordCheckupClientHelperMock, + mSyncServiceMock, mModalDialogManagerSupplier); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_GET_INTENT_ERROR_HISTOGRAM, + CredentialManagerError.UNCATEGORIZED)); + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + PASSWORD_CHECKUP_GET_INTENT_API_ERROR_HISTOGRAM)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_GET_INTENT_SUCCESS_HISTOGRAM, 0)); + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + PASSWORD_CHECKUP_GET_INTENT_LATENCY_HISTOGRAM)); + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM)); + } + + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsApiErrorMetricsForPasswordCheckupIntent() { + chooseToSyncPasswordsWithoutCustomPassphrase(); + returnErrorWhenFetchingIntentForPasswordCheckup( + new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR))); PasswordManagerHelper.showPasswordCheckup(ContextUtils.getApplicationContext(), PasswordCheckReferrer.SAFETY_CHECK, mPasswordCheckupClientHelperMock, @@ -366,6 +413,10 @@ CredentialManagerError.API_ERROR)); Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_GET_INTENT_API_ERROR_HISTOGRAM, + CommonStatusCodes.DEVELOPER_ERROR)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( PASSWORD_CHECKUP_GET_INTENT_SUCCESS_HISTOGRAM, 0)); Assert.assertEquals(0, RecordHistogram.getHistogramTotalCountForTesting( @@ -377,6 +428,84 @@ @Test @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsErrorMetricsForRunPasswordCheckup() { + chooseToSyncPasswordsWithoutCustomPassphrase(); + returnErrorWhenRunningPasswordCheckup( + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED)); + + PasswordManagerHelper.runPasswordCheckupInBackground(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), + mock(Callback.class), mock(Callback.class)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_RUN_PASSWORD_CHECKUP_ERROR_HISTOGRAM, + CredentialManagerError.UNCATEGORIZED)); + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + PASSWORD_CHECKUP_RUN_PASSWORD_CHECKUP_API_ERROR_HISTOGRAM)); + } + + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsApiErrorMetricsForRunPasswordCheckup() { + chooseToSyncPasswordsWithoutCustomPassphrase(); + returnErrorWhenRunningPasswordCheckup( + new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR))); + + PasswordManagerHelper.runPasswordCheckupInBackground(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), + mock(Callback.class), mock(Callback.class)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_RUN_PASSWORD_CHECKUP_ERROR_HISTOGRAM, + CredentialManagerError.API_ERROR)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_RUN_PASSWORD_CHECKUP_API_ERROR_HISTOGRAM, + CommonStatusCodes.DEVELOPER_ERROR)); + } + + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsErrorMetricsForGetBreachedCredentialsCount() { + chooseToSyncPasswordsWithoutCustomPassphrase(); + returnErrorWhenGettingBreachedCredentialsCount( + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED)); + + PasswordManagerHelper.getBreachedCredentialsCount(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), + mock(Callback.class), mock(Callback.class)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_GET_BREACHED_CREDENTIALS_COUNT_ERROR_HISTOGRAM, + CredentialManagerError.UNCATEGORIZED)); + Assert.assertEquals(0, + RecordHistogram.getHistogramTotalCountForTesting( + PASSWORD_CHECKUP_GET_BREACHED_CREDENTIALS_COUNT_API_ERROR_HISTOGRAM)); + } + + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsApiErrorMetricsForGetBreachedCredentialsCount() { + chooseToSyncPasswordsWithoutCustomPassphrase(); + returnErrorWhenGettingBreachedCredentialsCount( + new ApiException(new Status(CommonStatusCodes.DEVELOPER_ERROR))); + + PasswordManagerHelper.getBreachedCredentialsCount(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), + mock(Callback.class), mock(Callback.class)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_GET_BREACHED_CREDENTIALS_COUNT_ERROR_HISTOGRAM, + CredentialManagerError.API_ERROR)); + Assert.assertEquals(1, + RecordHistogram.getHistogramValueCountForTesting( + PASSWORD_CHECKUP_GET_BREACHED_CREDENTIALS_COUNT_API_ERROR_HISTOGRAM, + CommonStatusCodes.DEVELOPER_ERROR)); + } + + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) public void testRecordsMetricsWhenPasswordCheckupIntentFails() throws CanceledException { chooseToSyncPasswordsWithoutCustomPassphrase(); setUpSuccessfulCheckupIntentFetching(mPendingIntentMock); @@ -391,9 +520,6 @@ Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( PASSWORD_CHECKUP_GET_INTENT_SUCCESS_HISTOGRAM, 1)); - Assert.assertEquals(0, - RecordHistogram.getHistogramTotalCountForTesting( - PASSWORD_CHECKUP_GET_INTENT_ERROR_HISTOGRAM)); Assert.assertEquals(1, RecordHistogram.getHistogramValueCountForTesting( PASSWORD_CHECKUP_LAUNCH_CREDENTIAL_MANAGER_SUCCESS_HISTOGRAM, 0)); @@ -444,7 +570,8 @@ public void testDismissesLoadingDialogOnPasswordCheckupIntentGetError() throws CanceledException { chooseToSyncPasswordsWithoutCustomPassphrase(); - returnErrorWhenFetchingIntentForPasswordCheckup(CredentialManagerError.API_ERROR); + returnErrorWhenFetchingIntentForPasswordCheckup( + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED)); PasswordManagerHelper.launchPasswordCheckup(PasswordCheckReferrer.SAFETY_CHECK, mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), @@ -962,7 +1089,8 @@ public void testRecordsCheckupLoadingDialogMetricsOnIntentFetchError() throws CanceledException { chooseToSyncPasswordsWithoutCustomPassphrase(); - returnErrorWhenFetchingIntentForPasswordCheckup(CredentialManagerError.API_ERROR); + returnErrorWhenFetchingIntentForPasswordCheckup( + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED)); when(mLoadingModalDialogCoordinator.getState()) .thenReturn(LoadingModalDialogCoordinator.State.PENDING); @@ -999,6 +1127,30 @@ PasswordManagerHelper.LoadingDialogOutcome.NOT_SHOWN_LOADED)); } + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsErrorMetricsWhenRunPasswordCheckupFails() { + Exception expectedException = + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED); + returnErrorWhenRunningPasswordCheckup(expectedException); + + PasswordManagerHelper.runPasswordCheckupInBackground(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), + mock(Callback.class), mock(Callback.class)); + } + + @Test + @EnableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_ANDROID) + public void testRecordsErrorMetricsWhenGetBreachedCredentialsCountFails() { + Exception expectedException = + new PasswordCheckBackendException("", CredentialManagerError.UNCATEGORIZED); + returnErrorWhenGettingBreachedCredentialsCount(expectedException); + + PasswordManagerHelper.getBreachedCredentialsCount(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupClientHelperMock, Optional.of(TEST_EMAIL_ADDRESS), + mock(Callback.class), mock(Callback.class)); + } + private void chooseToSyncPasswordsWithoutCustomPassphrase() { when(mSyncServiceMock.isSyncFeatureEnabled()).thenReturn(true); when(mSyncServiceMock.getChosenDataTypes()) @@ -1025,7 +1177,7 @@ return true; }) .when(mPasswordCheckupClientHelperMock) - .getPasswordCheckupPendingIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), + .getPasswordCheckupIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), eq(Optional.of(TEST_EMAIL_ADDRESS)), any(Callback.class), any(Callback.class)); } @@ -1041,15 +1193,38 @@ eq(TEST_EMAIL_ADDRESS), any(Callback.class), any(Callback.class)); } - private void returnErrorWhenFetchingIntentForPasswordCheckup( - @CredentialManagerError int error) { + private void returnErrorWhenFetchingIntentForPasswordCheckup(Exception error) { doAnswer(invocation -> { - Callback<Integer> cb = invocation.getArgument(3); + Callback<Exception> cb = invocation.getArgument(3); cb.onResult(error); return true; }) .when(mPasswordCheckupClientHelperMock) - .getPasswordCheckupPendingIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), + .getPasswordCheckupIntent(eq(PasswordCheckReferrer.SAFETY_CHECK), + eq(Optional.of(TEST_EMAIL_ADDRESS)), any(Callback.class), + any(Callback.class)); + } + + private void returnErrorWhenRunningPasswordCheckup(Exception error) { + doAnswer(invocation -> { + Callback<Exception> cb = invocation.getArgument(3); + cb.onResult(error); + return true; + }) + .when(mPasswordCheckupClientHelperMock) + .runPasswordCheckupInBackground(eq(PasswordCheckReferrer.SAFETY_CHECK), + eq(Optional.of(TEST_EMAIL_ADDRESS)), any(Callback.class), + any(Callback.class)); + } + + private void returnErrorWhenGettingBreachedCredentialsCount(Exception error) { + doAnswer(invocation -> { + Callback<Exception> cb = invocation.getArgument(3); + cb.onResult(error); + return true; + }) + .when(mPasswordCheckupClientHelperMock) + .getBreachedCredentialsCount(eq(PasswordCheckReferrer.SAFETY_CHECK), eq(Optional.of(TEST_EMAIL_ADDRESS)), any(Callback.class), any(Callback.class)); }
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 21545b8..b1b1b47 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -66,6 +66,7 @@ #include "components/password_manager/core/browser/hsts_query.h" #include "components/password_manager/core/browser/http_auth_manager.h" #include "components/password_manager/core/browser/http_auth_manager_impl.h" +#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_change_success_tracker.h" #include "components/password_manager/core/browser/password_form.h" @@ -650,9 +651,13 @@ HideSavePasswordInfobar(web_contents()); } + auto metrics_recorder = std::make_unique< + password_manager::metrics_util::LeakDialogMetricsRecorder>( + web_contents()->GetMainFrame()->GetPageUkmSourceId(), + password_manager::GetLeakDialogType(leak_type)); (new CredentialLeakControllerAndroid( leak_type, url, username, GetPasswordChangeSuccessTracker(), - web_contents()->GetTopLevelNativeWindow())) + web_contents()->GetTopLevelNativeWindow(), std::move(metrics_recorder))) ->ShowDialog(); #else // !BUILDFLAG(IS_ANDROID) PasswordsClientUIDelegate* manage_passwords_ui_controller =
diff --git a/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc index 3feeff9..be2e0956 100644 --- a/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc +++ b/chrome/browser/picture_in_picture/document_picture_in_picture_window_controller_browsertest.cc
@@ -34,6 +34,7 @@ #include "content/public/browser/overlay_window.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" #include "content/public/common/content_features.h" @@ -112,9 +113,14 @@ return pip_window_controller_; } - DocumentOverlayWindowViews* GetOverlayWindow() { - return static_cast<DocumentOverlayWindowViews*>( - window_controller()->GetWindowForTesting()); + content::RenderWidgetHostView* GetRenderWidgetHostView() { + if (!window_controller()) + return nullptr; + + if (auto* web_contents = window_controller()->GetChildWebContents()) + return web_contents->GetRenderWidgetHostView(); + + return nullptr; } void LoadTabAndEnterPictureInPicture(Browser* browser) { @@ -131,8 +137,7 @@ ASSERT_EQ(true, EvalJs(active_web_contents, "createDocumentPipWindow()")); ASSERT_TRUE(window_controller() != nullptr); - ASSERT_TRUE(window_controller()->GetWindowForTesting() != nullptr); - EXPECT_TRUE(window_controller()->GetWindowForTesting()->IsVisible()); + ASSERT_TRUE(GetRenderWidgetHostView()->IsShowing()); } void ClickButton(views::Button* button) { @@ -141,6 +146,19 @@ views::test::ButtonTestApi(button).NotifyClick(event); } + // Watch for destruction of a WebContents. `is_destroyed()` will report if the + // WebContents has been destroyed yet. + class DestructionObserver : public content::WebContentsObserver { + public: + explicit DestructionObserver(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + + void WebContentsDestroyed() override { Observe(/*web_contents=*/nullptr); } + + // If we've stopped observing, it's because the WebContents was destroyed. + bool is_destroyed() const { return !web_contents(); } + }; + private: raw_ptr<content::DocumentPictureInPictureWindowController> pip_window_controller_ = nullptr; @@ -151,23 +169,38 @@ // Checks the creation of the window controller, as well as basic window // creation, visibility and activation. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Document PiP is not supported in Lacros yet. +#define MAYBE_CreationAndVisibilityAndActivation \ + DISABLED_CreationAndVisibilityAndActivation +#else +#define MAYBE_CreationAndVisibilityAndActivation \ + CreationAndVisibilityAndActivation +#endif IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_CreationAndVisibilityAndActivation) { + MAYBE_CreationAndVisibilityAndActivation) { LoadTabAndEnterPictureInPicture(browser()); - gfx::NativeWindow native_window = GetOverlayWindow()->GetNativeWindow(); - EXPECT_FALSE(platform_util::IsWindowActive(native_window)); + ASSERT_TRUE(GetRenderWidgetHostView()); + EXPECT_TRUE(GetRenderWidgetHostView()->IsShowing()); + EXPECT_FALSE(GetRenderWidgetHostView()->HasFocus()); } // Regression test for https://crbug.com/1296780 - opening a picture-in-picture // window twice in a row should work, closing the old window before opening the // new one. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Document PiP is not supported in Lacros yet. +#define MAYBE_CreateTwice DISABLED_CreateTwice +#else +#define MAYBE_CreateTwice CreateTwice +#endif IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_CreateTwice) { + MAYBE_CreateTwice) { LoadTabAndEnterPictureInPicture(browser()); - gfx::NativeWindow native_window_1 = GetOverlayWindow()->GetNativeWindow(); - EXPECT_FALSE(platform_util::IsWindowActive(native_window_1)); + ASSERT_TRUE(window_controller()->GetChildWebContents()); + DestructionObserver w(window_controller()->GetChildWebContents()); // Now open the window a second time, without previously closing the original // window. @@ -177,43 +210,63 @@ "window.requestPictureInPictureWindow(" " {width: 200, height: 200}" ").then(w => true)")); + base::RunLoop().RunUntilIdle(); - ASSERT_TRUE(window_controller()); - ASSERT_TRUE(window_controller()->GetWindowForTesting()); - EXPECT_TRUE(window_controller()->GetWindowForTesting()->IsVisible()); + // The first WebContents should be destroyed. + EXPECT_TRUE(w.is_destroyed()); - gfx::NativeWindow native_window_2 = GetOverlayWindow()->GetNativeWindow(); - EXPECT_FALSE(platform_util::IsWindowActive(native_window_2)); - - // The two windows should be different. - EXPECT_NE(native_window_1, native_window_2); + // The new WebContents should be visible and unfocused. + ASSERT_TRUE(GetRenderWidgetHostView()); + EXPECT_TRUE(GetRenderWidgetHostView()->IsShowing()); + EXPECT_TRUE(!GetRenderWidgetHostView()->HasFocus()); } // Tests closing the document picture-in-picture window. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Document PiP is not supported in Lacros yet. +#define MAYBE_CloseWindow DISABLED_CloseWindow +#else +#define MAYBE_CloseWindow CloseWindow +#endif IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_CloseWindow) { + MAYBE_CloseWindow) { LoadTabAndEnterPictureInPicture(browser()); window_controller()->Close(/*should_pause_video=*/true); - ASSERT_FALSE(window_controller()->GetWindowForTesting()); + ASSERT_FALSE(window_controller()->GetChildWebContents()); } // Tests navigating the opener closes the picture in picture window. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Document PiP is not supported in Lacros yet. +#define MAYBE_ClosePictureInPictureWhenOpenerNavigates \ + DISABLED_ClosePictureInPictureWhenOpenerNavigates +#else +#define MAYBE_ClosePictureInPictureWhenOpenerNavigates \ + ClosePictureInPictureWhenOpenerNavigates +#endif IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_ClosePictureInPictureWhenOpenerNavigates) { + MAYBE_ClosePictureInPictureWhenOpenerNavigates) { LoadTabAndEnterPictureInPicture(browser()); GURL test_page_url = ui_test_utils::GetTestUrl( base::FilePath(base::FilePath::kCurrentDirectory), base::FilePath(kPictureInPictureDocumentPipPage)); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url)); - ASSERT_FALSE(window_controller()->GetWindowForTesting()); + ASSERT_FALSE(window_controller()->GetChildWebContents()); } // Navigation by the pip window to a new document should close the pip window. -IN_PROC_BROWSER_TEST_F( - DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_CloseOnPictureInPictureNavigationToNewDocument) { +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Document PiP is not supported in Lacros yet. +#define MAYBE_CloseOnPictureInPictureNavigationToNewDocument \ + DISABLED_CloseOnPictureInPictureNavigationToNewDocument +#else +#define MAYBE_CloseOnPictureInPictureNavigationToNewDocument \ + CloseOnPictureInPictureNavigationToNewDocument +#endif +IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, + MAYBE_CloseOnPictureInPictureNavigationToNewDocument) { LoadTabAndEnterPictureInPicture(browser()); content::WebContents* active_web_contents = @@ -222,13 +275,21 @@ "navigateInDocumentPipWindow('http://media/" "picture_in_picture/blank.html');")); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(window_controller()->GetWindowForTesting()); + EXPECT_FALSE(window_controller()->GetChildWebContents()); } // Navigation within the pip window's document should not close the pip window. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +// Document PiP is not supported in Lacros yet. +#define MAYBE_DoNotCloseOnPictureInPictureNavigationInsideDocument \ + DISABLED_DoNotCloseOnPictureInPictureNavigationInsideDocument +#else +#define MAYBE_DoNotCloseOnPictureInPictureNavigationInsideDocument \ + DoNotCloseOnPictureInPictureNavigationInsideDocument +#endif IN_PROC_BROWSER_TEST_F( DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_DoNotCloseOnPictureInPictureNavigationInsideDocument) { + MAYBE_DoNotCloseOnPictureInPictureNavigationInsideDocument) { LoadTabAndEnterPictureInPicture(browser()); content::WebContents* active_web_contents = @@ -236,11 +297,14 @@ ASSERT_EQ(true, EvalJs(active_web_contents, "navigateInDocumentPipWindow('#top');")); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(window_controller()->GetWindowForTesting()); + EXPECT_TRUE(window_controller()->GetChildWebContents()); } +// Make sure that document PiP fails without a secure context. +// Unlike other tests, this one does work on Lacros. +// TODO(crbug.com/1328840): Consider replacing this with a web platform test. IN_PROC_BROWSER_TEST_F(DocumentPictureInPictureWindowControllerBrowserTest, - DISABLED_RequiresSecureContext) { + RequiresSecureContext) { GURL test_page_url("http://media/picture-in-picture/blank.html"); ASSERT_FALSE(network::IsUrlPotentiallyTrustworthy(test_page_url)); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc index d3831b0..183fc2a 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc
@@ -14,6 +14,8 @@ #include "content/public/browser/web_contents_observer.h" #include "ui/gfx/geometry/size.h" +// This is used only for video PiP. Document PiP is handled by the window +// controller internally. class PictureInPictureWindowManager::ContentsObserver final : public content::WebContentsObserver { public: @@ -53,7 +55,7 @@ void PictureInPictureWindowManager::EnterDocumentPictureInPicture( content::WebContents* parent_web_contents, - std::unique_ptr<content::WebContents> child_web_contents) { + content::WebContents* child_web_contents) { // If there was already a controller, close the existing window before // creating the next one. This needs to happen before creating the new // controller so that its precondition (no child_web_contents_) remains @@ -64,7 +66,7 @@ auto* controller = content::PictureInPictureWindowController:: GetOrCreateDocumentPictureInPictureController(parent_web_contents); - controller->SetChildWebContents(std::move(child_web_contents)); + controller->SetChildWebContents(child_web_contents); // Show the new window. As a side effect, this also first closes any // pre-existing PictureInPictureWindowController's window (if any).
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h index 2a56aad..e87ac65 100644 --- a/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h +++ b/chrome/browser/picture_in_picture/picture_in_picture_window_manager.h
@@ -44,9 +44,8 @@ // (i.e. Chrome's BrowserNavigator) then calls this method to create the // window. There's no corresponding path through the WebContentsDelegate, so // it doesn't have a failure state. - void EnterDocumentPictureInPicture( - content::WebContents* parent_web_contents, - std::unique_ptr<content::WebContents> child_web_contents); + void EnterDocumentPictureInPicture(content::WebContents* parent_web_contents, + content::WebContents* child_web_contents); // Shows a PIP window with an explicitly provided window controller. This is // used by ChromeOS ARC windows which do not have a WebContents as the source.
diff --git a/chrome/browser/policy/test/system_features_policy_browsertest.cc b/chrome/browser/policy/test/system_features_policy_browsertest.cc index 1e464f9..0ba8d2cb 100644 --- a/chrome/browser/policy/test/system_features_policy_browsertest.cc +++ b/chrome/browser/policy/test/system_features_policy_browsertest.cc
@@ -139,9 +139,8 @@ } void InstallSWAs() { - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); } void InstallPWA(const GURL& app_url, const char* app_id) {
diff --git a/chrome/browser/predictors/autocomplete_action_predictor.cc b/chrome/browser/predictors/autocomplete_action_predictor.cc index bcf94ef..0180a922 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor.cc +++ b/chrome/browser/predictors/autocomplete_action_predictor.cc
@@ -205,10 +205,6 @@ return; } - // TODO(https://crbug.com/1166085): Reset the handle upon prerendering - // activation/cancellation. There is a case that a user input the same url - // after activation/cancellation, and this mechanism prevents the user from - // starting a new prerendering. PrerenderManager::CreateForWebContents(&web_contents); auto* prerender_manager = PrerenderManager::FromWebContents(&web_contents); direct_url_input_prerender_handle_ =
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.cc index cd94fd9a..1cb3662 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.cc +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.cc
@@ -246,9 +246,10 @@ void SearchPrefetchBaseBrowserTest::AddNewSuggestionRule( std::string origin_query, std::vector<std::string> suggestions, - int prefetch_index) { - search_suggestion_rules_.emplace_back( - SearchSuggestionTuple(origin_query, suggestions, prefetch_index)); + int prefetch_index, + int prerender_index) { + search_suggestion_rules_.emplace_back(SearchSuggestionTuple( + origin_query, suggestions, prefetch_index, prerender_index)); } std::unique_ptr<net::test_server::HttpResponse> @@ -366,8 +367,7 @@ // $1 : origin query // $2 : suggested results. It should be like: "suggestion_1", // "suggestion_2", ..., "suggestion_n". - // $3 : a json that contains prefetch hints. It can be an empty string if - // there is no prefetch hint. + // $3 : a json that contains preload hints. std::string content_template = R"([ "$1", [$2], @@ -378,9 +378,11 @@ }])"; // $1: the index of prefetch hint in suggested results. - std::string prefetch_hint_template = R"( + // $2: the index of prerender hint in suggested results. + std::string preload_hint_template = R"( "google:clientdata": { - "phi": $1 + "phi": $1, + "pre": $2 } )"; @@ -396,12 +398,11 @@ for (size_t i = 0; i < suggestion_rule.suggestions.size(); ++i) { formatted_suggestions[i] = "\"" + suggestion_rule.suggestions[i] + "\""; } - std::string prefetch_hint_json = ""; - if (suggestion_rule.prefetch_hint_index != -1) { - prefetch_hint_json = base::ReplaceStringPlaceholders( - prefetch_hint_template, - {base::NumberToString(suggestion_rule.prefetch_hint_index)}, nullptr); - } + std::string prefetch_hint_json = base::ReplaceStringPlaceholders( + preload_hint_template, + {base::NumberToString(suggestion_rule.prefetch_hint_index), + base::NumberToString(suggestion_rule.prerender_hint_index)}, + nullptr); std::string suggestions_string = base::JoinString(formatted_suggestions, ","); content = base::ReplaceStringPlaceholders( @@ -421,10 +422,12 @@ SearchPrefetchBaseBrowserTest::SearchSuggestionTuple::SearchSuggestionTuple( std::string origin_query, std::vector<std::string> suggestions, - int prefetch_index) + int prefetch_index, + int prerender_index) : origin_query(origin_query), suggestions(suggestions), - prefetch_hint_index(prefetch_index) {} + prefetch_hint_index(prefetch_index), + prerender_hint_index(prerender_index) {} SearchPrefetchBaseBrowserTest::SearchSuggestionTuple::~SearchSuggestionTuple() = default;
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h b/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h index 3c31de3..7f08f292 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h
@@ -65,9 +65,12 @@ const std::string& content, const std::string& content_type); + // Allows tests to add a new suggestion rule for the given `origin_query`. + // See `SearchSuggestionTuple` for details. void AddNewSuggestionRule(std::string origin_query, std::vector<std::string> suggestions, - int prefetch_index); + int prefetch_index, + int prerender_index); size_t search_server_request_count() const { return search_server_request_count_; @@ -108,24 +111,44 @@ struct SearchSuggestionTuple { SearchSuggestionTuple(std::string origin_query, std::vector<std::string> suggestions, - int prefetch_index); + int prefetch_index, + int prerender_index); ~SearchSuggestionTuple(); SearchSuggestionTuple(const SearchSuggestionTuple& other); + // The string that users typed. std::string origin_query; + + // A list of search suggestions associated with `origin_query`. std::vector<std::string> suggestions; + + // The index of prefetch hint in `suggestions`. Set to -1 if none of them + // should be prefetched. int prefetch_hint_index = -1; + + // The index of prefetch hint in `suggestions`. Set to -1 if none of them + // should be prerendered. + int prerender_hint_index = -1; }; // Stores some hard-coded rules for testing. - // Tests can also call AddNewSuggestionRule to append a new rule. - // Note: they are order-sensitive! The last rule(the newest added rule) has + // Tests can also call `AddNewSuggestionRule` to append a new rule. + // Note: they are order-sensitive! The last rule (the newest added rule) has // the highest priority. std::vector<SearchSuggestionTuple> search_suggestion_rules_{ - SearchSuggestionTuple("porgs", {"porgs", "porgsandwich"}, 0), - SearchSuggestionTuple("puffins", {"puffins", "puffinsalad"}, -1), - SearchSuggestionTuple("502_on_prefetch", {"502_on_prefetch"}, 0)}; + SearchSuggestionTuple("porgs", + {"porgs", "porgsandwich"}, + /*prefetch_index=*/0, + /*prerender_index=*/-1), + SearchSuggestionTuple("puffins", + {"puffins", "puffinsalad"}, + /*prefetch_index=*/-1, + /*prerender_index=*/-1), + SearchSuggestionTuple("502_on_prefetch", + {"502_on_prefetch"}, + /*prefetch_index=*/0, + /*prerender_index=*/-1)}; content::ContentMockCertVerifier mock_cert_verifier_;
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc index 62330d3..eb835d7 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h" #include "chrome/browser/prefetch/search_prefetch/search_prefetch_url_loader.h" #include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h" +#include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -31,6 +32,7 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/search_engines/template_url_service.h" +#include "content/public/browser/web_contents.h" #include "net/base/load_flags.h" #include "services/network/public/cpp/resource_request.h" #include "url/origin.h" @@ -442,7 +444,8 @@ last_error_time_ticks_ = base::TimeTicks::Now(); } -void SearchPrefetchService::OnResultChanged(const AutocompleteResult& result) { +void SearchPrefetchService::OnResultChanged(content::WebContents* web_contents, + const AutocompleteResult& result) { auto* template_url_service = TemplateURLServiceFactory::GetForProfile(profile_); DCHECK(template_url_service); @@ -486,6 +489,12 @@ if (BaseSearchProvider::ShouldPrefetch(match)) { MaybePrefetchURL(GetPrefetchURLFromMatch(match, template_url_service)); } + if (prerender_utils::IsSearchSuggestionPrerenderEnabled() && + BaseSearchProvider::ShouldPrerender(match) && web_contents) { + PrerenderManager::CreateForWebContents(web_contents); + auto* prerender_manager = PrerenderManager::FromWebContents(web_contents); + prerender_manager->StartPrerenderSearchSuggestion(match); + } } }
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h index 5e7f0bf..0c31132a 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service.h
@@ -28,6 +28,10 @@ class SearchPrefetchURLLoader; class AutocompleteResult; +namespace content { +class WebContents; +} + namespace network { struct ResourceRequest; } @@ -98,7 +102,8 @@ void OnTemplateURLServiceChanged() override; // Called when `AutocompleteController` receives updates on `result`. - void OnResultChanged(const AutocompleteResult& result); + void OnResultChanged(content::WebContents* web_contents, + const AutocompleteResult& result); // Returns whether the prefetch started or not. bool MaybePrefetchURL(const GURL& url);
diff --git a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc index 285a88e1..143f6ae 100644 --- a/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc +++ b/chrome/browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -1292,7 +1292,7 @@ AddNewSuggestionRule( kOmniboxSuggestPrefetchQuery, {kOmniboxSuggestPrefetchQuery, kOmniboxSuggestPrefetchSecondItemQuery}, - 1); + /*prefetch_index=*/1, /*prerender_index=*/-1); auto* search_prefetch_service = SearchPrefetchServiceFactory::GetForProfile(browser()->profile()); std::string search_terms = kOmniboxSuggestPrefetchQuery;
diff --git a/chrome/browser/prefetch/search_prefetch/search_preload_unified_browsertest.cc b/chrome/browser/prefetch/search_prefetch/search_preload_unified_browsertest.cc new file mode 100644 index 0000000..a1402f1 --- /dev/null +++ b/chrome/browser/prefetch/search_prefetch/search_preload_unified_browsertest.cc
@@ -0,0 +1,242 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "base/bind.h" +#include "base/containers/adapters.h" +#include "base/files/file_path.h" +#include "base/path_service.h" +#include "base/strings/string_number_conversions.h" +#include "build/build_config.h" +#include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h" +#include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h" +#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h" +#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h" +#include "chrome/browser/prerender/prerender_manager.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_paths.h" +#include "chrome/test/base/chrome_test_utils.h" +#include "chrome/test/base/search_test_utils.h" +#include "chrome/test/base/testing_profile.h" +#include "components/omnibox/browser/autocomplete_input.h" +#include "components/omnibox/browser/autocomplete_result.h" +#include "components/policy/policy_constants.h" +#include "components/search_engines/template_url_data.h" +#include "components/search_engines/template_url_service.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/prerender_test_util.h" +#include "net/dns/mock_host_resolver.h" +#include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if BUILDFLAG(IS_ANDROID) +#include "chrome/test/base/android/android_browser_test.h" +#else +#include "chrome/test/base/in_process_browser_test.h" +#endif // BUILDFLAG(IS_ANDROID) + +namespace { + +// Sets up testing context for the search preloading features: search prefetch +// and search prerender. +// These features are able to coordinate with the other: A prefetched result +// might be upgraded to prerender when needed (usually when service suggests +// clients to do so), and they share the prefetched response and other +// resources, so it is a unified test designed to test the interaction between +// these two features. +class SearchPreloadUnifiedBrowserTest : public PlatformBrowserTest { + public: + SearchPreloadUnifiedBrowserTest() + : prerender_helper_(base::BindRepeating( + &SearchPreloadUnifiedBrowserTest::GetActiveWebContents, + base::Unretained(this))) { + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kSupportSearchSuggestionForPrerender2, {}}, + {kSearchPrefetchServicePrefetching, + {{"max_attempts_per_caching_duration", "3"}, + {"cache_size", "1"}, + {"device_memory_threshold_MB", "0"}}}}, + /*disabled_features=*/{kSearchPrefetchBlockBeforeHeaders}); + } + + void SetUp() override { + prerender_helper().SetUp(&search_engine_server_); + PlatformBrowserTest::SetUp(); + } + + void SetUpOnMainThread() override { + PlatformBrowserTest::SetUpOnMainThread(); + host_resolver()->AddRule("*", "127.0.0.1"); + + // Set up a generic server. + embedded_test_server()->ServeFilesFromDirectory( + base::PathService::CheckedGet(chrome::DIR_TEST_DATA)); + ASSERT_TRUE(embedded_test_server()->Start()); + + // Set up server for search engine. + search_engine_server_.SetSSLConfig( + net::test_server::EmbeddedTestServer::CERT_TEST_NAMES); + search_engine_server_.RegisterRequestHandler(base::BindRepeating( + &SearchPreloadUnifiedBrowserTest::HandleSearchRequest, + base::Unretained(this))); + ASSERT_TRUE(search_engine_server_.Start()); + + TemplateURLService* model = TemplateURLServiceFactory::GetForProfile( + chrome_test_utils::GetProfile(this)); + ASSERT_TRUE(model); + search_test_utils::WaitForTemplateURLServiceToLoad(model); + ASSERT_TRUE(model->loaded()); + TemplateURLData data; + data.SetShortName(kSearchDomain16); + data.SetKeyword(data.short_name()); + data.SetURL( + search_engine_server_ + .GetURL(kSearchDomain, + "/search_page.html?q={searchTerms}&{google:prefetchSource}" + "type=test") + .spec()); + data.suggestions_url = + search_engine_server_.GetURL(kSearchDomain, "/?q={searchTerms}").spec(); + TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data)); + ASSERT_TRUE(template_url); + model->SetUserSelectedDefaultSearchProvider(template_url); + } + + std::unique_ptr<net::test_server::HttpResponse> HandleSearchRequest( + const net::test_server::HttpRequest& request) { + if (request.GetURL().spec().find("favicon") != std::string::npos) + return nullptr; + + std::unique_ptr<net::test_server::BasicHttpResponse> resp = + std::make_unique<net::test_server::BasicHttpResponse>(); + resp->set_code(net::HTTP_OK); + resp->set_content_type("text/html"); + std::string content = R"( + <html><body> + PRERENDER: HI PREFETCH! \o/ + </body></html> + )"; + resp->set_content(content); + return resp; + } + + GURL GetSearchUrl(const std::string& search_terms, + bool attach_prefetch_flag) { + // $1: the search terms that will be retrieved. + // $2: parameter for prefetch request. Should be &pf=cs if the url is + // expected to declare itself as a prefetch request. Otherwise it should be + // an empty string. + std::string url_template = "/search_page.html?q=$1$2&type=test"; + return search_engine_server_.GetURL( + kSearchDomain, + base::ReplaceStringPlaceholders( + url_template, {search_terms, attach_prefetch_flag ? "&pf=cs" : ""}, + nullptr)); + } + + void TearDownOnMainThread() override { + ASSERT_TRUE(search_engine_server_.ShutdownAndWaitUntilComplete()); + } + + content::WebContents* GetActiveWebContents() { + return chrome_test_utils::GetActiveWebContents(this); + } + + void SetUpContext() { + // Have SearchPrefetchService and PrerenderManager prepared. + PrerenderManager::CreateForWebContents(GetActiveWebContents()); + prerender_manager_ = + PrerenderManager::FromWebContents(GetActiveWebContents()); + ASSERT_TRUE(prerender_manager_); + search_prefetch_service_ = SearchPrefetchServiceFactory::GetForProfile( + chrome_test_utils::GetProfile(this)); + ASSERT_NE(nullptr, search_prefetch_service_); + } + + Profile* GetProfile() { return chrome_test_utils::GetProfile(this); } + + AutocompleteMatch CreateSearchSuggestionMatch( + const std::string& original_query, + const std::string& search_terms, + bool is_prerender_hint, + bool is_prefetch_hint) { + AutocompleteMatch match; + match.search_terms_args = std::make_unique<TemplateURLRef::SearchTermsArgs>( + base::UTF8ToUTF16(search_terms)); + match.search_terms_args->original_query = base::UTF8ToUTF16(original_query); + match.destination_url = + GetSearchUrl(search_terms, /*attach_prefetch_flag=*/false); + match.keyword = base::UTF8ToUTF16(original_query); + if (is_prerender_hint) + match.RecordAdditionalInfo("should_prerender", "true"); + if (is_prefetch_hint) + match.RecordAdditionalInfo("should_prefetch", "true"); + return match; + } + + content::test::PrerenderTestHelper& prerender_helper() { + return prerender_helper_; + } + + PrerenderManager* prerender_manager() { return prerender_manager_; } + + SearchPrefetchService* search_prefetch_service() { + return search_prefetch_service_; + } + + private: + constexpr static char kSearchDomain[] = "a.test"; + constexpr static char16_t kSearchDomain16[] = u"a.test"; + raw_ptr<PrerenderManager> prerender_manager_ = nullptr; + raw_ptr<SearchPrefetchService> search_prefetch_service_ = nullptr; + net::test_server::EmbeddedTestServer search_engine_server_{ + net::test_server::EmbeddedTestServer::TYPE_HTTPS}; + content::test::PrerenderTestHelper prerender_helper_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Tests that the SearchSuggestionService can trigger prerendering when it +// receives prerender hints. +IN_PROC_BROWSER_TEST_F(SearchPreloadUnifiedBrowserTest, PrerenderBeTriggered) { + const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html"); + ASSERT_TRUE(GetActiveWebContents()); + ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), kInitialUrl)); + SetUpContext(); + + std::string search_query = "pre"; + std::string prerender_query = "prerender"; + GURL expected_prerender_url = + GetSearchUrl(prerender_query, /*attach_prefetch_flag=*/true); + + content::test::PrerenderHostRegistryObserver registry_observer( + *GetActiveWebContents()); + + AutocompleteInput input( + base::ASCIIToUTF16(search_query), metrics::OmniboxEventProto::BLANK, + ChromeAutocompleteSchemeClassifier(chrome_test_utils::GetProfile(this))); + AutocompleteMatch autocomplete_match = CreateSearchSuggestionMatch( + search_query, prerender_query, /*is_prerender_hint=*/true, + /*is_prefetch_hint=*/true); + AutocompleteResult autocomplete_result; + autocomplete_result.AppendMatches({autocomplete_match}); + search_prefetch_service()->OnResultChanged(GetActiveWebContents(), + autocomplete_result); + + // The suggestion service should hint expected_prerender_url, and prerendering + // for this url should start. + registry_observer.WaitForTrigger(expected_prerender_url); + prerender_helper().WaitForPrerenderLoadCompletion(*GetActiveWebContents(), + expected_prerender_url); + // Prefetch should be triggered as well. + auto prefetch_status = + search_prefetch_service()->GetSearchPrefetchStatusForTesting( + base::ASCIIToUTF16(prerender_query)); + EXPECT_TRUE(prefetch_status.has_value()); +} + +} // namespace
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js index 956a2ae..260f77ea 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/settings_test.js
@@ -23,9 +23,8 @@ /** @override */ testGenPreamble() { GEN(` - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); `); super.testGenPreamble(); }
diff --git a/chrome/browser/resources/chromeos/login/cr_ui.js b/chrome/browser/resources/chromeos/login/cr_ui.js index 2dd62800..9f11affd 100644 --- a/chrome/browser/resources/chromeos/login/cr_ui.js +++ b/chrome/browser/resources/chromeos/login/cr_ui.js
@@ -74,14 +74,6 @@ } /** - * Updates missing API keys message visibility. - * @param {boolean} show True if the message should be visible. - */ - static showAPIKeysNotice(show) { - $('api-keys-notice-container').hidden = !show; - } - - /** * Toggles system info visibility. */ static toggleSystemInfo() { @@ -316,10 +308,14 @@ document.documentElement.setAttribute(attribute, localizedString); } + const missingApiId = 'missingAPIKeysNotice'; + if (!loadTimeData.valueExists(missingApiId)) { + return; + } // Update this standalone div in the main document. - const notice = loadTimeData.getValue('missingAPIKeysNotice'); const apiKeysNoticeDiv = $('api-keys-notice'); - apiKeysNoticeDiv.textContent = notice; + apiKeysNoticeDiv.textContent = loadTimeData.getValue(missingApiId); + $('api-keys-notice-container').hidden = false; } /**
diff --git a/chrome/browser/resources/settings/autofill_page/password_view.html b/chrome/browser/resources/settings/autofill_page/password_view.html index 9254925e46..f8f1e22d 100644 --- a/chrome/browser/resources/settings/autofill_page/password_view.html +++ b/chrome/browser/resources/settings/autofill_page/password_view.html
@@ -41,6 +41,10 @@ --cr-input-underline-display: none; } + settings-textarea.empty-note { + --cr-input-color: var(--cr-secondary-text-color); + } + #editButton { margin-inline-end: var(--cr-button-edge-spacing); } @@ -76,7 +80,8 @@ </template> </div> <template is="dom-if" if="[[!isFederated_(credential)]]" restamp> - <settings-textarea id="note" value="[[credential.note]]" readonly autogrow + <settings-textarea id="note" class$="[[getNoteClass_(credential.note)]]" + value="[[getNoteValue_(credential.note)]]" readonly autogrow label="$i18n{passwordNoteLabel}"> </settings-textarea> </template>
diff --git a/chrome/browser/resources/settings/autofill_page/password_view.ts b/chrome/browser/resources/settings/autofill_page/password_view.ts index 6a3b113f..99b1cb3 100644 --- a/chrome/browser/resources/settings/autofill_page/password_view.ts +++ b/chrome/browser/resources/settings/autofill_page/password_view.ts
@@ -178,6 +178,14 @@ return this.isPasswordVisible_ ? 'icon-visibility-off' : 'icon-visibility'; } + private getNoteClass_(): string { + return this.credential!.note ? '' : 'empty-note'; + } + + private getNoteValue_(): string { + return this.credential!.note || this.i18n('passwordNoNoteAdded'); + } + /** * Show the password or a placeholder with 10 characters when password is not * set.
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn index 8827499..b5cffe6d 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -51,7 +51,7 @@ "//chrome/browser/resources/settings:router", "//chrome/browser/resources/settings/chromeos:metrics_recorder", "//chrome/browser/resources/settings/chromeos:route_observer_behavior", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", + "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_components/chromeos/network:network_config.m", "//ui/webui/resources/cr_components/chromeos/network:onc_mojo.m", @@ -283,7 +283,7 @@ deps = [ "//chrome/browser/resources/settings/chromeos:os_route", "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", + "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", "//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_components/chromeos/network:network_icon.m", @@ -321,7 +321,6 @@ ":internet_shared_css", "//chrome/browser/resources/settings/chromeos:metrics_recorder", "//chrome/browser/resources/settings/chromeos:prefs_behavior", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_components/chromeos/network:mojo_interface_provider.m", "//ui/webui/resources/cr_components/chromeos/network:onc_mojo.m",
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_completion_link_row.html b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_completion_link_row.html index edf6da7..ccddd6d 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_completion_link_row.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_completion_link_row.html
@@ -11,6 +11,7 @@ cr-icon-button { --cr-icon-button-icon-size: 24px; + margin: 2px; } </style> <picture>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts index 83574c2..6b2d867 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_guide/privacy_guide_page.ts
@@ -183,11 +183,6 @@ if (newRoute !== routes.PRIVACY_GUIDE || this.exitIfNecessary()) { return; } - // Set the pref that the user has viewed the Privacy guide. - CrSettingsPrefs.initialized.then(() => { - this.setPrefValue('privacy_guide.viewed', true); - }); - this.updateStateFromQueryParameters_(); } @@ -350,8 +345,16 @@ } /** Sets the privacy guide step from the URL parameter. */ - private updateStateFromQueryParameters_() { + private async updateStateFromQueryParameters_() { assert(Router.getInstance().getCurrentRoute() === routes.PRIVACY_GUIDE); + + // Tasks in the privacy guide UI and in multiple fragments rely on prefs + // being loaded. Instead of individually delaying those tasks, await prefs + // once when a navigation to the privacy guide happens. + await CrSettingsPrefs.initialized; + // Set the pref that the user has viewed the Privacy guide. + this.setPrefValue('privacy_guide.viewed', true); + const step = Router.getInstance().getQueryParameters().get('step') as PrivacyGuideStep;
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc index 679b22df..37d73e9 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.cc
@@ -349,10 +349,13 @@ } void ChromeCleanerControllerImpl::OnSwReporterReady( + const std::string& prompt_seed, SwReporterInvocationSequence&& invocations) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(!invocations.container().empty()); + manifest_prompt_seed_ = prompt_seed; + SwReporterInvocationType invocation_type = SwReporterInvocationType::kPeriodicRun; { @@ -503,6 +506,14 @@ prefs::kSwReporterReportingEnabled)); } +std::string ChromeCleanerControllerImpl::GetIncomingPromptSeed() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // This should only be called after OnSwReporterReady, which records the + // prompt seed. + DCHECK(manifest_prompt_seed_); + return *manifest_prompt_seed_; +} + ChromeCleanerControllerImpl::ChromeCleanerControllerImpl() : real_delegate_(std::make_unique<ChromeCleanerControllerDelegate>()), delegate_(real_delegate_.get()) {
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h index 48d4367..f51914c5 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_impl_win.h
@@ -20,6 +20,7 @@ #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_scanner_results_win.h" #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_prompt_actions_win.h" #include "components/component_updater/component_updater_service.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace safe_browsing { @@ -73,13 +74,15 @@ void OnReporterSequenceStarted() override; void OnReporterSequenceDone(SwReporterInvocationResult result) override; void RequestUserInitiatedScan(Profile* profile) override; - void OnSwReporterReady(SwReporterInvocationSequence&& invocations) override; + void OnSwReporterReady(const std::string& prompt_seed, + SwReporterInvocationSequence&& invocations) override; void Scan(const SwReporterInvocation& reporter_invocation) override; void ReplyWithUserResponse(Profile* profile, UserResponse user_response) override; void Reboot() override; bool IsAllowedByPolicy() override; bool IsReportingManagedByPolicy(Profile* profile) override; + std::string GetIncomingPromptSeed() override; static void ResetInstanceForTesting(); // Passing in a nullptr as |delegate| resets the delegate to a default @@ -158,6 +161,9 @@ // to a |ReporterRunner| more than once. std::unique_ptr<SwReporterInvocationSequence> cached_reporter_invocations_; + // The prompt seed specified in the component manifest. + absl::optional<std::string> manifest_prompt_seed_; + THREAD_CHECKER(thread_checker_); base::WeakPtrFactory<ChromeCleanerControllerImpl> weak_factory_{this};
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h index 9784900..9beff86 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h
@@ -147,8 +147,9 @@ // unless the user has manually requested a reporter run, in which case the // |SwReporterInvocationType::kUserInitiatedWithLogsAllowed| or // |SwReporterInvocationType::kUserInitiatedWithLogsDisallowed| types will be - // passed. + // passed. |prompt_seed| is the seed specified in the component manifest. virtual void OnSwReporterReady( + const std::string& prompt_seed, SwReporterInvocationSequence&& invocations) = 0; // Downloads the Chrome Cleaner binary, executes it and waits for the Cleaner @@ -198,6 +199,9 @@ // Returns true if cleaner reporting is managed by enterprise policy. virtual bool IsReportingManagedByPolicy(Profile* profile) = 0; + // Returns the prompt seed specified in the component manifest. + virtual std::string GetIncomingPromptSeed() = 0; + protected: ChromeCleanerController(); virtual ~ChromeCleanerController();
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc index 032fb32bc..026285a 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_browsertest_win.cc
@@ -9,7 +9,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/run_loop.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h" #include "chrome/browser/profiles/keep_alive/scoped_profile_keep_alive.h" #include "chrome/browser/profiles/profile_manager.h" @@ -56,8 +55,6 @@ } void SetUpInProcessBrowserTestFixture() override { - scoped_feature_list_.InitAndEnableFeatureWithParameters( - kChromeCleanupInBrowserPromptFeature, {{"Seed", incoming_seed_}}); // dialog_controller_ expects that the cleaner controller would be on // scanning state. #if DCHECK_IS_ON() @@ -65,6 +62,9 @@ .WillOnce(Return(ChromeCleanerController::State::kScanning)); #endif EXPECT_CALL(mock_cleaner_controller_, AddObserver(_)); + EXPECT_CALL(mock_cleaner_controller_, GetIncomingPromptSeed()) + .WillRepeatedly(Return(incoming_seed_)); + dialog_controller_ = new ChromeCleanerDialogControllerImpl(&mock_cleaner_controller_); dialog_controller_->SetPromptDelegateForTests(&mock_delegate_); @@ -90,8 +90,6 @@ std::string old_seed_; std::string incoming_seed_; - - base::test::ScopedFeatureList scoped_feature_list_; }; IN_PROC_BROWSER_TEST_P(ChromeCleanerPromptUserTest,
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc index 1e748bf3..a8f9f5be 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_dialog_controller_impl_win.cc
@@ -230,7 +230,8 @@ // Don't show the prompt again if it's been shown before for this profile and // for the current variations seed. - const std::string incoming_seed = GetIncomingSRTSeed(); + const std::string incoming_seed = + cleaner_controller_->GetIncomingPromptSeed(); const std::string old_seed = prefs->GetString(prefs::kSwReporterPromptSeed); if (!incoming_seed.empty() && incoming_seed != old_seed) prefs->SetString(prefs::kSwReporterPromptSeed, incoming_seed);
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc index c823ce8d..84764cb 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.cc
@@ -11,8 +11,9 @@ MockChromeCleanerController::~MockChromeCleanerController() = default; void MockChromeCleanerController::OnSwReporterReady( + const std::string& prompt_seed, SwReporterInvocationSequence&& sequence) { - MockedOnSwReporterReady(sequence); + MockedOnSwReporterReady(prompt_seed, sequence); } } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h index 6e6567f..8e49e16 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h +++ b/chrome/browser/safe_browsing/chrome_cleaner/mock_chrome_cleaner_controller_win.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_SAFE_BROWSING_CHROME_CLEANER_MOCK_CHROME_CLEANER_CONTROLLER_WIN_H_ #define CHROME_BROWSER_SAFE_BROWSING_CHROME_CLEANER_MOCK_CHROME_CLEANER_CONTROLLER_WIN_H_ +#include <string> + #include "chrome/browser/safe_browsing/chrome_cleaner/chrome_cleaner_controller_win.h" #include "testing/gmock/include/gmock/gmock.h" @@ -17,8 +19,9 @@ ~MockChromeCleanerController() override; // gmock does not support rvalue references in MOCK_METHOD. This method just - // relays the argument to OnSwReporterReady_. - void OnSwReporterReady(SwReporterInvocationSequence&& sequence) override; + // relays the arguments to MockedOnSwReporterReady_. + void OnSwReporterReady(const std::string& prompt_seed, + SwReporterInvocationSequence&& sequence) override; MOCK_CONST_METHOD0(state, State()); MOCK_CONST_METHOD0(idle_reason, IdleReason()); @@ -31,12 +34,14 @@ MOCK_METHOD0(OnReporterSequenceStarted, void()); MOCK_METHOD1(OnReporterSequenceDone, void(SwReporterInvocationResult)); MOCK_METHOD1(RequestUserInitiatedScan, void(Profile*)); - MOCK_METHOD1(MockedOnSwReporterReady, void(SwReporterInvocationSequence&)); + MOCK_METHOD2(MockedOnSwReporterReady, + void(const std::string&, SwReporterInvocationSequence&)); MOCK_METHOD1(Scan, void(const safe_browsing::SwReporterInvocation&)); MOCK_METHOD2(ReplyWithUserResponse, void(Profile*, UserResponse)); MOCK_METHOD0(Reboot, void()); MOCK_METHOD0(IsAllowedByPolicy, bool()); MOCK_METHOD1(IsReportingManagedByPolicy, bool(Profile*)); + MOCK_METHOD0(GetIncomingPromptSeed, std::string()); }; } // namespace safe_browsing
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 b1e1ad5..d1fe792 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
@@ -21,7 +21,6 @@ #include "base/process/process.h" #include "base/run_loop.h" #include "base/synchronization/lock.h" -#include "base/test/scoped_feature_list.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/version.h" @@ -205,9 +204,6 @@ policy::BrowserPolicyConnector::SetPolicyProviderForTesting( &policy_provider_); - scoped_feature_list_.InitAndEnableFeatureWithParameters( - kChromeCleanupInBrowserPromptFeature, {{"Seed", incoming_seed_}}); - switch (policy_state_) { case PolicyState::kNoLogs: break; @@ -226,6 +222,9 @@ break; } } + + EXPECT_CALL(mock_chrome_cleaner_controller_, GetIncomingPromptSeed()) + .WillRepeatedly(Return(incoming_seed_)); } void SetUpOnMainThread() override { @@ -606,8 +605,6 @@ // can be used to perform actions in the middle of a queue of reporters which // all launch on the same mock clock tick. base::OnceClosure first_launch_callback_; - - base::test::ScopedFeatureList scoped_feature_list_; }; } // namespace
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc index bf8bd9b..e039800 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/reporter_runner_win.cc
@@ -401,7 +401,8 @@ // Don't show the prompt again if it's been shown before for this profile and // for the current variations seed. The seed preference will be updated once // the prompt is shown. - const std::string incoming_seed = GetIncomingSRTSeed(); + const std::string incoming_seed = + GetCleanerController()->GetIncomingPromptSeed(); const std::string old_seed = prefs->GetString(prefs::kSwReporterPromptSeed); if (!incoming_seed.empty() && incoming_seed == old_seed) { RecordPromptNotShownWithReasonHistogram(NO_PROMPT_REASON_ALREADY_PROMPTED); @@ -635,14 +636,6 @@ return; } - if (!IsUserInitiated(invocation_type_) && !IsSRTPromptFeatureEnabled()) { - // Knowing about disabled field trial is more important than reporter not - // finding anything to remove, so check this case first. - RecordPromptNotShownWithReasonHistogram( - NO_PROMPT_REASON_FEATURE_NOT_ENABLED); - return; - } - // Do not accept reboot required or post-reboot exit codes, since they // should not be sent out by the reporter. if (result.exit_code != chrome_cleaner::kSwReporterCleanupNeeded) {
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc index 48c5715..d1b646b 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc +++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
@@ -12,8 +12,6 @@ namespace { -constexpr char kSRTPromptSeedParam[] = "Seed"; - // The download links of the Software Removal Tool. constexpr char kDownloadRootPath[] = "https://dl.google.com/dl/softwareremovaltool/win/"; @@ -30,16 +28,9 @@ namespace safe_browsing { -const base::Feature kChromeCleanupInBrowserPromptFeature{ - "InBrowserCleanerUI", base::FEATURE_DISABLED_BY_DEFAULT}; - const base::Feature kChromeCleanupDistributionFeature{ "ChromeCleanupDistribution", base::FEATURE_DISABLED_BY_DEFAULT}; -bool IsSRTPromptFeatureEnabled() { - return base::FeatureList::IsEnabled(kChromeCleanupInBrowserPromptFeature); -} - GURL GetStableDownloadURL() { const std::string url = base::win::OSInfo::GetArchitecture() == base::win::OSInfo::X86_ARCHITECTURE @@ -75,11 +66,6 @@ return download_url; } -std::string GetIncomingSRTSeed() { - return base::GetFieldTrialParamValueByFeature( - kChromeCleanupInBrowserPromptFeature, kSRTPromptSeedParam); -} - void RecordPromptNotShownWithReasonHistogram( NoPromptReasonHistogramValue value) { UMA_HISTOGRAM_ENUMERATION("SoftwareReporter.NoPromptReason", value,
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h index b26b96f..d44d437f6 100644 --- a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h +++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_SAFE_BROWSING_CHROME_CLEANER_SRT_FIELD_TRIAL_WIN_H_ #define CHROME_BROWSER_SAFE_BROWSING_CHROME_CLEANER_SRT_FIELD_TRIAL_WIN_H_ -#include <string> - #include "base/feature_list.h" #include "url/gurl.h" @@ -52,24 +50,13 @@ PROMPT_TYPE_MAX, }; -// Feature to control whether users should be prompted for a cleanup if the -// software reporter finds bad software on their machine. -extern const base::Feature kChromeCleanupInBrowserPromptFeature; - // Feature, parameters of which control which software reporter and cleanup tool // versions will be downloaded. When not enabled, default versions will be used. extern const base::Feature kChromeCleanupDistributionFeature; -// Returns true if this Chrome is in a field trial group which shows the SRT -// prompt. -bool IsSRTPromptFeatureEnabled(); - // Returns the correct SRT download URL for the current field trial. GURL GetSRTDownloadURL(); -// Returns the value of the incoming SRT seed. -std::string GetIncomingSRTSeed(); - // Records a value for the SRT Prompt Histogram. void RecordSRTPromptHistogram(SRTPromptHistogramValue value);
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java index f90fd91..e50db51e 100644 --- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java +++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
@@ -586,8 +586,8 @@ mPasswordStoreBridge.addObserver(this, true); WeakReference<SafetyCheckMediator> weakRef = new WeakReference(this); - mPasswordCheckupHelper.getNumberOfBreachedCredentials(PasswordCheckReferrer.SAFETY_CHECK, - getSyncingAccount(), + PasswordManagerHelper.getBreachedCredentialsCount(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupHelper, getSyncingAccount(), count -> { if (weakRef.get() == null) return; @@ -612,8 +612,8 @@ } WeakReference<SafetyCheckMediator> weakRef = new WeakReference(this); - mPasswordCheckupHelper.runPasswordCheckup(PasswordCheckReferrer.SAFETY_CHECK, - getSyncingAccount(), + PasswordManagerHelper.runPasswordCheckupInBackground(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupHelper, getSyncingAccount(), unused -> { if (weakRef.get() == null) return; @@ -651,8 +651,8 @@ private void onPasswordCheckFinished() { WeakReference<SafetyCheckMediator> weakRef = new WeakReference(this); - mPasswordCheckupHelper.getNumberOfBreachedCredentials(PasswordCheckReferrer.SAFETY_CHECK, - getSyncingAccount(), + PasswordManagerHelper.getBreachedCredentialsCount(PasswordCheckReferrer.SAFETY_CHECK, + mPasswordCheckupHelper, getSyncingAccount(), count -> { if (weakRef.get() == null) return; @@ -664,7 +664,7 @@ }); } - private void onPasswordCheckFailed(Integer error) { + private void onPasswordCheckFailed(Exception error) { setRunnablePasswords(() -> { if (mModel != null) { RecordHistogram.recordEnumeratedHistogram("Settings.SafetyCheck.PasswordsResult",
diff --git a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java index 322a8eb..e8f221fc 100644 --- a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java +++ b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
@@ -109,7 +109,7 @@ private Callback<Void> mRunPasswordCheckSuccessfullyCallback; - private Callback<Integer> mRunPasswordCheckFailedCallback; + private Callback<Exception> mRunPasswordCheckFailedCallback; private boolean mUseNewApi; @@ -132,7 +132,7 @@ } if (hasError) { assertNotNull(mRunPasswordCheckFailedCallback); - mRunPasswordCheckFailedCallback.onResult(null); + mRunPasswordCheckFailedCallback.onResult(new Exception()); } else { assertNotNull(mRunPasswordCheckSuccessfullyCallback); mRunPasswordCheckSuccessfullyCallback.onResult(null); @@ -171,7 +171,7 @@ return null; }) .when(mPasswordCheckupHelper) - .getNumberOfBreachedCredentials(anyInt(), any(), any(Callback.class), any()); + .getBreachedCredentialsCount(anyInt(), any(), any(Callback.class), any()); when(mPasswordStoreBridge.getPasswordStoreCredentialsCount()).thenReturn(passwordCount); } else { doAnswer(invocation -> { @@ -195,7 +195,7 @@ return null; }) .when(mPasswordCheckupHelper) - .getNumberOfBreachedCredentials(anyInt(), any(), any(Callback.class), any()); + .getBreachedCredentialsCount(anyInt(), any(), any(Callback.class), any()); } private void captureRunPasswordCheckCallback() { @@ -206,7 +206,7 @@ return null; }) .when(mPasswordCheckupHelper) - .runPasswordCheckup(anyInt(), any(), any(Callback.class), any(Callback.class)); + .runPasswordCheckupInBackground(anyInt(), any(), any(Callback.class), any()); } @Before
diff --git a/chrome/browser/sync/test/integration/ash_custom_passphrase_sharing_sync_test.cc b/chrome/browser/sync/test/integration/ash_custom_passphrase_sharing_sync_test.cc new file mode 100644 index 0000000..a76defc --- /dev/null +++ b/chrome/browser/sync/test/integration/ash_custom_passphrase_sharing_sync_test.cc
@@ -0,0 +1,218 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> +#include <utility> + +#include "ash/constants/ash_features.h" +#include "base/files/file_path.h" +#include "base/json/json_writer.h" +#include "base/test/scoped_feature_list.h" +#include "base/values.h" +#include "chrome/browser/ash/crosapi/crosapi_ash.h" +#include "chrome/browser/ash/crosapi/crosapi_manager.h" +#include "chrome/browser/sync/test/integration/encryption_helper.h" +#include "chrome/browser/sync/test/integration/preferences_helper.h" +#include "chrome/browser/sync/test/integration/status_change_checker.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/pref_names.h" +#include "chromeos/crosapi/mojom/account_manager.mojom.h" +#include "chromeos/crosapi/mojom/sync.mojom-test-utils.h" +#include "chromeos/crosapi/mojom/sync.mojom.h" +#include "components/prefs/pref_service.h" +#include "components/sync/chromeos/explicit_passphrase_mojo_utils.h" +#include "components/sync/engine/loopback_server/persistent_unique_client_entity.h" +#include "components/sync/engine/nigori/nigori.h" +#include "components/sync/nigori/cryptographer_impl.h" +#include "components/sync/nigori/nigori_test_utils.h" +#include "components/sync/protocol/os_preference_specifics.pb.h" +#include "components/sync/test/fake_server/fake_server_nigori_helper.h" +#include "content/public/test/browser_test.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace { + +void InjectEncryptedServerOsPreference( + const sync_pb::OsPreferenceSpecifics& unencrypted_specifics, + const syncer::KeyParamsForTesting& key_params, + fake_server::FakeServer* fake_server) { + sync_pb::EntitySpecifics wrapped_unencrypted_specifics; + *wrapped_unencrypted_specifics.mutable_os_preference() = + unencrypted_specifics; + + sync_pb::EntitySpecifics encrypted_specifics; + auto cryptographer = syncer::CryptographerImpl::FromSingleKeyForTesting( + key_params.password, key_params.derivation_params); + bool encrypt_result = cryptographer->Encrypt( + wrapped_unencrypted_specifics, encrypted_specifics.mutable_encrypted()); + *encrypted_specifics.mutable_os_preference() = + sync_pb::OsPreferenceSpecifics(); + DCHECK(encrypt_result); + + fake_server->InjectEntity( + syncer::PersistentUniqueClientEntity::CreateFromSpecificsForTesting( + /*non_unique_name=*/"encrypted", + /*client_tag=*/unencrypted_specifics.preference().name(), + encrypted_specifics, /*creation_time=*/0, /*last_modified_time=*/0)); +} + +std::string PrefValueToProtoString(const base::Value& value) { + std::string result; + bool success = base::JSONWriter::Write(value, &result); + DCHECK(success); + return result; +} + +class PassphraseRequiredNotifiedToCrosapiObserverChecker + : public StatusChangeChecker, + public crosapi::mojom::SyncExplicitPassphraseClientObserver { + public: + explicit PassphraseRequiredNotifiedToCrosapiObserverChecker( + mojo::Remote<crosapi::mojom::SyncExplicitPassphraseClient>* + remote_explicit_passphrase_client) { + DCHECK(remote_explicit_passphrase_client); + remote_explicit_passphrase_client->get()->AddObserver( + receiver_.BindNewPipeAndPassRemote()); + } + + PassphraseRequiredNotifiedToCrosapiObserverChecker( + const PassphraseRequiredNotifiedToCrosapiObserverChecker&) = delete; + PassphraseRequiredNotifiedToCrosapiObserverChecker& operator=( + const PassphraseRequiredNotifiedToCrosapiObserverChecker&) = delete; + ~PassphraseRequiredNotifiedToCrosapiObserverChecker() override = default; + + // crosapi::mojom::SyncExplicitPassphraseClientObserver implementation. + void OnPassphraseAvailable() override {} + + void OnPassphraseRequired() override { + passphrase_required_notified_ = true; + CheckExitCondition(); + } + + // StatusChangeChecker implementation. + bool IsExitConditionSatisfied(std::ostream* os) override { + *os << "Waiting for OnPassphraseRequired() call for crosapi observer"; + return passphrase_required_notified_; + } + + private: + bool passphrase_required_notified_ = false; + mojo::Receiver<crosapi::mojom::SyncExplicitPassphraseClientObserver> + receiver_{this}; +}; + +class AshCustomPassphraseSharingSyncTest : public SyncTest { + public: + AshCustomPassphraseSharingSyncTest() : SyncTest(SINGLE_CLIENT) { + feature_list_.InitWithFeatures({chromeos::features::kLacrosSupport, + chromeos::features::kLacrosPrimary}, + {}); + } + + AshCustomPassphraseSharingSyncTest( + const AshCustomPassphraseSharingSyncTest&) = delete; + AshCustomPassphraseSharingSyncTest& operator=( + const AshCustomPassphraseSharingSyncTest&) = delete; + + ~AshCustomPassphraseSharingSyncTest() override = default; + + // SyncTest overrides. + base::FilePath GetProfileBaseName(int index) override { + // Need to reuse test user profile for this test - Crosapi explicitly + // assumes there is only one regular profile. + // TODO(crbug.com/1102768): eventually this should be the case for all Ash + // tests. + DCHECK_EQ(index, 0); + return base::FilePath(chrome::kTestUserProfileDir); + } + + void SetupCrosapi() { + crosapi::CrosapiAsh* crosapi_ash = + crosapi::CrosapiManager::Get()->crosapi_ash(); + DCHECK(crosapi_ash); + + crosapi_ash->BindSyncService( + sync_mojo_service_remote_.BindNewPipeAndPassReceiver()); + sync_mojo_service_remote_.get()->BindExplicitPassphraseClient( + explicit_passphrase_client_remote_.BindNewPipeAndPassReceiver()); + } + + mojo::Remote<crosapi::mojom::SyncExplicitPassphraseClient>* + explicit_passphrase_client_remote() { + return &explicit_passphrase_client_remote_; + } + + void MimicDecryptionKeyProvidedByLacros( + const syncer::KeyParamsForTesting& key_params) { + auto nigori = syncer::Nigori::CreateByDerivation( + key_params.derivation_params, key_params.password); + + auto account_key = crosapi::mojom::AccountKey::New(); + account_key->id = GetSyncService(0)->GetAccountInfo().gaia; + account_key->account_type = crosapi::mojom::AccountType::kGaia; + + explicit_passphrase_client_remote_.get()->SetDecryptionNigoriKey( + std::move(account_key), + /*decryption_key=*/syncer::NigoriToMojo(*nigori)); + } + + private: + base::test::ScopedFeatureList feature_list_; + + mojo::Remote<crosapi::mojom::SyncService> sync_mojo_service_remote_; + mojo::Remote<crosapi::mojom::SyncExplicitPassphraseClient> + explicit_passphrase_client_remote_; +}; + +IN_PROC_BROWSER_TEST_F(AshCustomPassphraseSharingSyncTest, + ShouldNotifyObserversAndAcceptPassphraseFromLacros) { + ASSERT_TRUE(SetupSync()); + SetupCrosapi(); + + PassphraseRequiredNotifiedToCrosapiObserverChecker + passphrase_required_notified_to_crosapi_observer_checker( + explicit_passphrase_client_remote()); + + // Mimic custom passphrase being set by other client. + const syncer::KeyParamsForTesting kKeyParams = + syncer::ScryptPassphraseKeyParamsForTesting("hunter2"); + fake_server::SetNigoriInFakeServer( + syncer::BuildCustomPassphraseNigoriSpecifics(kKeyParams), + GetFakeServer()); + + // Inject encrypted os preference with non-default value. + sync_pb::OsPreferenceSpecifics os_preference_specifics; + const base::Value kNewPrefValue = base::Value(true); + os_preference_specifics.mutable_preference()->set_name( + prefs::kResolveTimezoneByGeolocationMigratedToMethod); + os_preference_specifics.mutable_preference()->set_value( + PrefValueToProtoString(kNewPrefValue)); + InjectEncryptedServerOsPreference(os_preference_specifics, kKeyParams, + GetFakeServer()); + + // Data isn't decryptable yet, client should enter passphrase required state, + // notify observers (Lacros) via crosapi and have default preference value. + EXPECT_TRUE(passphrase_required_notified_to_crosapi_observer_checker.Wait()); + ASSERT_TRUE( + PassphraseRequiredStateChecker(GetSyncService(0), /*desired_state=*/true) + .Wait()); + ASSERT_NE(*preferences_helper::GetPrefs(0)->Get( + prefs::kResolveTimezoneByGeolocationMigratedToMethod), + kNewPrefValue); + + // Mimic passphrase being provided by Lacros, verify that passphrase is no + // longer required and the data is decryptable. + MimicDecryptionKeyProvidedByLacros(kKeyParams); + EXPECT_TRUE( + PassphraseRequiredStateChecker(GetSyncService(0), /*desired_state=*/false) + .Wait()); + EXPECT_TRUE(BooleanPrefValueChecker( + preferences_helper::GetPrefs(0), + prefs::kResolveTimezoneByGeolocationMigratedToMethod, + kNewPrefValue.GetBool()) + .Wait()); +} + +} // namespace
diff --git a/chrome/browser/sync/test/integration/preferences_helper.cc b/chrome/browser/sync/test/integration/preferences_helper.cc index 6b7d3df1..c43a091 100644 --- a/chrome/browser/sync/test/integration/preferences_helper.cc +++ b/chrome/browser/sync/test/integration/preferences_helper.cc
@@ -180,6 +180,25 @@ } // namespace preferences_helper +BooleanPrefValueChecker::BooleanPrefValueChecker(PrefService* pref_service, + const char* path, + bool expected_value) + : path_(path), + expected_value_(expected_value), + pref_service_(pref_service) { + pref_change_registrar_.Init(pref_service_); + pref_change_registrar_.Add( + path_, base::BindRepeating(&BooleanPrefValueChecker::CheckExitCondition, + base::Unretained(this))); +} + +BooleanPrefValueChecker::~BooleanPrefValueChecker() = default; + +bool BooleanPrefValueChecker::IsExitConditionSatisfied(std::ostream* os) { + *os << "Waiting for pref '" << path_ << "' to be " << expected_value_; + return pref_service_->GetBoolean(path_) == expected_value_; +} + PrefMatchChecker::PrefMatchChecker(const char* path) : path_(path) { for (int i = 0; i < test()->num_clients(); ++i) { RegisterPrefListener(preferences_helper::GetPrefs(i));
diff --git a/chrome/browser/sync/test/integration/preferences_helper.h b/chrome/browser/sync/test/integration/preferences_helper.h index cae9c3f..bfeb9deb 100644 --- a/chrome/browser/sync/test/integration/preferences_helper.h +++ b/chrome/browser/sync/test/integration/preferences_helper.h
@@ -7,6 +7,7 @@ #include <stdint.h> +#include "components/prefs/pref_change_registrar.h" #include "components/sync/base/model_type.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -17,6 +18,7 @@ #include "base/memory/scoped_refptr.h" #include "base/values.h" #include "chrome/browser/sync/test/integration/fake_server_match_status_checker.h" +#include "chrome/browser/sync/test/integration/single_client_status_change_checker.h" #include "chrome/browser/sync/test/integration/status_change_checker.h" #include "components/prefs/json_pref_store.h" #include "components/sync/protocol/preference_specifics.pb.h" @@ -91,6 +93,24 @@ } // namespace preferences_helper +// Checker that blocks until pref has the specified value. +class BooleanPrefValueChecker : public StatusChangeChecker { + public: + BooleanPrefValueChecker(PrefService* pref_service, + const char* path, + bool expected_value); + ~BooleanPrefValueChecker() override; + + bool IsExitConditionSatisfied(std::ostream* os) override; + + private: + const char* path_; + const bool expected_value_; + + const base::raw_ptr<PrefService> pref_service_; + PrefChangeRegistrar pref_change_registrar_; +}; + // Abstract checker that takes care of registering for preference changes. class PrefMatchChecker : public StatusChangeChecker { public:
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index a72f793..02feef67 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -966,6 +966,8 @@ "autofill_assistant/password_change/assistant_onboarding_controller_impl.h", "autofill_assistant/password_change/assistant_onboarding_prompt.h", "autofill_assistant/password_change/assistant_side_panel_coordinator.h", + "autofill_assistant/password_change/password_change_run_controller.h", + "autofill_assistant/password_change/password_change_run_display.h", "blocked_content/framebust_block_tab_helper.cc", "blocked_content/framebust_block_tab_helper.h", "blocked_content/popunder_preventer.cc", @@ -1737,6 +1739,7 @@ "//chrome/browser:browser_themes", "//chrome/browser:theme_properties", "//chrome/browser/ash/system_web_apps/types:types", + "//chrome/browser/autofill_assistant/password_change/proto:proto", "//chrome/browser/browsing_data:constants", "//chrome/browser/cart:mojo_bindings", "//chrome/browser/image_editor", @@ -4138,6 +4141,9 @@ "views/autofill_assistant/password_change/assistant_onboarding_view.h", "views/autofill_assistant/password_change/assistant_side_panel_coordinator_impl.cc", "views/autofill_assistant/password_change/assistant_side_panel_coordinator_impl.h", + "views/autofill_assistant/password_change/password_change_run_display.cc", + "views/autofill_assistant/password_change/password_change_run_view.cc", + "views/autofill_assistant/password_change/password_change_run_view.h", "views/bookmarks/bookmark_bar_view.cc", "views/bookmarks/bookmark_bar_view.h", "views/bookmarks/bookmark_bar_view_observer.h", @@ -5653,6 +5659,8 @@ "autofill_assistant/password_change/mock_assistant_onboarding_controller.h", "autofill_assistant/password_change/mock_assistant_onboarding_prompt.cc", "autofill_assistant/password_change/mock_assistant_onboarding_prompt.h", + "autofill_assistant/password_change/mock_password_change_run_controller.cc", + "autofill_assistant/password_change/mock_password_change_run_controller.h", "exclusive_access/exclusive_access_test.cc", "exclusive_access/exclusive_access_test.h", "exclusive_access/fullscreen_controller_state_test.cc",
diff --git a/chrome/browser/ui/android/autofill/internal/BUILD.gn b/chrome/browser/ui/android/autofill/internal/BUILD.gn index af5f6d5..8223699 100644 --- a/chrome/browser/ui/android/autofill/internal/BUILD.gn +++ b/chrome/browser/ui/android/autofill/internal/BUILD.gn
@@ -69,7 +69,6 @@ "//base:base_java_test_support", "//base:base_junit_test_support", "//base/test:test_support_java", - "//chrome/browser/ui/android/autofill/test:test_support_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_runner_java", @@ -77,6 +76,7 @@ "//third_party/junit:junit", "//third_party/mockito:mockito_java", "//ui/android:ui_full_java", + "//ui/android:ui_java_test_support", ] }
diff --git a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogBridgeTest.java b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogBridgeTest.java index fc1a5c0..82fe021 100644 --- a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogBridgeTest.java +++ b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogBridgeTest.java
@@ -25,6 +25,7 @@ import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.ui.autofill.data.AuthenticatorOption; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; import java.util.ArrayList; import java.util.List;
diff --git a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogTest.java b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogTest.java index 6b31539..5296b70 100644 --- a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogTest.java +++ b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AuthenticatorSelectionDialogTest.java
@@ -29,6 +29,7 @@ import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; import java.util.ArrayList;
diff --git a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillErrorDialogBridgeTest.java b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillErrorDialogBridgeTest.java index efc12be2..7172376 100644 --- a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillErrorDialogBridgeTest.java +++ b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillErrorDialogBridgeTest.java
@@ -23,6 +23,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; /** * Unit tests for {@link AutofillErrorDialogBridge}
diff --git a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillProgressDialogBridgeTest.java b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillProgressDialogBridgeTest.java index 1e99c03..47ac2197 100644 --- a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillProgressDialogBridgeTest.java +++ b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/AutofillProgressDialogBridgeTest.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.ui.autofill.internal.R; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; /** * Unit tests for {@link AutofillProgressDialogBridge}
diff --git a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/OtpVerificationDialogTest.java b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/OtpVerificationDialogTest.java index 7007b6ee..fff4246 100644 --- a/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/OtpVerificationDialogTest.java +++ b/chrome/browser/ui/android/autofill/internal/java/src/org/chromium/chrome/browser/ui/autofill/OtpVerificationDialogTest.java
@@ -29,6 +29,7 @@ import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; import org.chromium.ui.modaldialog.ModalDialogProperties; import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; import java.util.Optional;
diff --git a/chrome/browser/ui/android/autofill/test/BUILD.gn b/chrome/browser/ui/android/autofill/test/BUILD.gn deleted file mode 100644 index 2240eb6..0000000 --- a/chrome/browser/ui/android/autofill/test/BUILD.gn +++ /dev/null
@@ -1,21 +0,0 @@ -# Copyright 2022 The Chromium Authors. All rights reserved. -# 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/android/rules.gni") - -android_library("test_support_java") { - testonly = true - - visibility = [ - ":*", - "//chrome/android:chrome_junit_tests__java_binary", - "//chrome/browser/ui/android/autofill/internal:junit", - ] - sources = [ "java/src/org/chromium/chrome/browser/ui/autofill/FakeModalDialogManager.java" ] - deps = [ - "//third_party/mockito:mockito_java", - "//ui/android:ui_no_recycler_view_java", - ] -}
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmImportSyncDataDialogCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmImportSyncDataDialogCoordinator.java index 8e270170..cdfac53 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmImportSyncDataDialogCoordinator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/ConfirmImportSyncDataDialogCoordinator.java
@@ -28,7 +28,7 @@ import java.util.List; /** - * Coordinator to show a modal dialog that is displayed when the user switches account they are + * A coordinator to show a modal dialog that is displayed when the user switches account they are * syncing to. It gives the option to merge the data of the two accounts or to keep them separate. */ public class ConfirmImportSyncDataDialogCoordinator { @@ -106,7 +106,7 @@ } /** - * Dismisses the account picker dialog. + * Dismisses the confirm import sync data dialog. */ @MainThread public void dismissDialog() {
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java index 1f2516cc..bec916f 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/fre/SigninFirstRunMediator.java
@@ -35,6 +35,7 @@ import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.text.NoUnderlineClickableSpan; import org.chromium.ui.text.SpanApplier; +import org.chromium.ui.util.ColorUtils; import java.util.ArrayList; import java.util.List; @@ -290,8 +291,12 @@ ArrayList<SpanApplier.SpanInfo> spans = new ArrayList<>(); // Terms of Service SpanInfo. - final NoUnderlineClickableSpan clickableTermsOfServiceSpan = new NoUnderlineClickableSpan( - mContext, view -> mDelegate.showInfoPage(R.string.google_terms_of_service_url)); + final NoUnderlineClickableSpan clickableTermsOfServiceSpan = + new NoUnderlineClickableSpan(mContext, + view + -> mDelegate.showInfoPage(ColorUtils.inNightMode(mContext) + ? R.string.google_terms_of_service_dark_mode_url + : R.string.google_terms_of_service_url)); spans.add( new SpanApplier.SpanInfo("<TOS_LINK>", "</TOS_LINK>", clickableTermsOfServiceSpan));
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 38e8201..53fb599a 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1885,6 +1885,9 @@ <message name="IDS_GOOGLE_TERMS_OF_SERVICE_URL" desc="URL for Google terms of service" translateable="false"> https://policies.google.com/terms/embedded </message> + <message name="IDS_GOOGLE_TERMS_OF_SERVICE_DARK_MODE_URL" desc="URL for Google terms of service for dark mode" translateable="false"> + https://policies.google.com/terms/embedded?color_scheme=dark + </message> <message name="IDS_CHROME_ADDITIONAL_TERMS_OF_SERVICE_TITLE" desc="Title for Chrome and ChromeOS addtional terms of service"> Chrome & ChromeOS Additional Terms of Service </message>
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java index 5756e71..0a7ec88 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarCoordinator.java
@@ -9,6 +9,7 @@ import android.view.View.OnLongClickListener; import android.view.ViewStub; +import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; @@ -43,6 +44,8 @@ private final StartSurfaceToolbarMediator mToolbarMediator; private final ViewStub mStub; private final PropertyModel mPropertyModel; + private final TopToolbarInteractabilityManager mTopToolbarInteractabilityManager; + private PropertyModelChangeProcessor mPropertyModelChangeProcessor; private StartSurfaceToolbarView mView; private TabModelSelector mTabModelSelector; @@ -103,6 +106,8 @@ mThemeColorProvider = provider; mMenuButtonCoordinator = menuButtonCoordinator; + mTopToolbarInteractabilityManager = new TopToolbarInteractabilityManager( + enabled -> mToolbarMediator.setNewTabEnabled(enabled)); } /** @@ -242,6 +247,11 @@ mToolbarMediator.setNewTabButtonHighlight(highlight); } + @NonNull + TopToolbarInteractabilityManager getTopToolbarInteractabilityManager() { + return mTopToolbarInteractabilityManager; + } + private void inflate() { mStub.setLayoutResource(R.layout.start_top_toolbar); mView = (StartSurfaceToolbarView) mStub.inflate();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java index fdcc726..7bfd1818 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
@@ -20,6 +20,7 @@ import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.INCOGNITO_TAB_COUNT_PROVIDER; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.INCOGNITO_TAB_MODEL_SELECTOR; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_INCOGNITO; +import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_NEW_TAB_ENABLED; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_VISIBLE; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.LOGO_IS_VISIBLE; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.NEW_TAB_BUTTON_HIGHLIGHT; @@ -277,6 +278,11 @@ && -mPropertyModel.get(TRANSLATION_Y) >= fakeSearchBoxMarginToScreenTop; } + // Updates interactability to both New tab button "+" and New tab view text "New tab". + void setNewTabEnabled(boolean enabled) { + mPropertyModel.set(IS_NEW_TAB_ENABLED, enabled); + } + void setOnNewTabClickHandler(View.OnClickListener listener) { mPropertyModel.set(NEW_TAB_CLICK_HANDLER, listener); }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java index f0d846d..799ce9b 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarProperties.java
@@ -24,6 +24,9 @@ public static final PropertyModel .WritableObjectPropertyKey<View.OnClickListener> NEW_TAB_CLICK_HANDLER = new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>(); + // Handles the enabled state of the New tab button "+" and the text "New tab". + public static final PropertyModel.WritableBooleanPropertyKey IS_NEW_TAB_ENABLED = + new PropertyModel.WritableBooleanPropertyKey(); public static final PropertyModel .WritableObjectPropertyKey<View.OnClickListener> IDENTITY_DISC_CLICK_HANDLER = new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>(); @@ -91,13 +94,13 @@ new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>(); public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {NEW_TAB_CLICK_HANDLER, - IS_VISIBLE, SHOW_ANIMATION, LOGO_IS_VISIBLE, IS_INCOGNITO, INCOGNITO_STATE_PROVIDER, - ACCESSIBILITY_ENABLED, MENU_IS_VISIBLE, NEW_TAB_VIEW_IS_VISIBLE, NEW_TAB_VIEW_AT_START, - NEW_TAB_VIEW_TEXT_IS_VISIBLE, BUTTONS_CLICKABLE, GRID_TAB_SWITCHER_ENABLED, - IDENTITY_DISC_AT_START, INCOGNITO_SWITCHER_VISIBLE, IDENTITY_DISC_IS_VISIBLE, - IDENTITY_DISC_CLICK_HANDLER, IDENTITY_DISC_IMAGE, IDENTITY_DISC_DESCRIPTION, - NEW_TAB_BUTTON_HIGHLIGHT, TRANSLATION_Y, HOME_BUTTON_IS_VISIBLE, - HOMEPAGE_ENABLED_SUPPLIER, HOMEPAGE_MANAGED_BY_POLICY_SUPPLIER, + IS_NEW_TAB_ENABLED, IS_VISIBLE, SHOW_ANIMATION, LOGO_IS_VISIBLE, IS_INCOGNITO, + INCOGNITO_STATE_PROVIDER, ACCESSIBILITY_ENABLED, MENU_IS_VISIBLE, + NEW_TAB_VIEW_IS_VISIBLE, NEW_TAB_VIEW_AT_START, NEW_TAB_VIEW_TEXT_IS_VISIBLE, + BUTTONS_CLICKABLE, GRID_TAB_SWITCHER_ENABLED, IDENTITY_DISC_AT_START, + INCOGNITO_SWITCHER_VISIBLE, IDENTITY_DISC_IS_VISIBLE, IDENTITY_DISC_CLICK_HANDLER, + IDENTITY_DISC_IMAGE, IDENTITY_DISC_DESCRIPTION, NEW_TAB_BUTTON_HIGHLIGHT, TRANSLATION_Y, + HOME_BUTTON_IS_VISIBLE, HOMEPAGE_ENABLED_SUPPLIER, HOMEPAGE_MANAGED_BY_POLICY_SUPPLIER, HOME_BUTTON_CLICK_HANDLER, TAB_SWITCHER_BUTTON_IS_VISIBLE, INCOGNITO_TAB_COUNT_PROVIDER, INCOGNITO_TAB_MODEL_SELECTOR}; }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java index 51c0ec3e..d551bd4 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java
@@ -123,6 +123,18 @@ } /** + * Sets whether the "+" new tab button view and "New tab" text is enabled or not. + * + * @param enabled The desired interactability state for the new tab button and text view. + */ + void setNewTabEnabled(boolean enabled) { + mNewTabButton.setEnabled(enabled); + if (mNewTabViewWithText.getVisibility() == VISIBLE) { + mNewTabViewWithText.setEnabled(enabled); + } + } + + /** * Sets the {@link OnClickListener} that will be notified when the New Tab view or New Tab * button is pressed. * @param listener The callback that will be notified when the New Tab view is pressed.
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java index f01a8ae1..6d9d7ee 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarViewBinder.java
@@ -21,6 +21,7 @@ import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.INCOGNITO_TAB_COUNT_PROVIDER; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.INCOGNITO_TAB_MODEL_SELECTOR; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_INCOGNITO; +import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_NEW_TAB_ENABLED; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.IS_VISIBLE; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.LOGO_IS_VISIBLE; import static org.chromium.chrome.browser.toolbar.top.StartSurfaceToolbarProperties.MENU_IS_VISIBLE; @@ -72,6 +73,8 @@ view.setMenuButtonVisibility(model.get(MENU_IS_VISIBLE)); } else if (propertyKey == NEW_TAB_CLICK_HANDLER) { view.setOnNewTabClickHandler(model.get(NEW_TAB_CLICK_HANDLER)); + } else if (propertyKey == IS_NEW_TAB_ENABLED) { + view.setNewTabEnabled(model.get(IS_NEW_TAB_ENABLED)); } else if (propertyKey == NEW_TAB_BUTTON_HIGHLIGHT) { view.setNewTabButtonHighlight(model.get(NEW_TAB_BUTTON_HIGHLIGHT)); } else if (propertyKey == NEW_TAB_VIEW_IS_VISIBLE) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinator.java index 3e27e6fcf..5ed0c07 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTCoordinator.java
@@ -7,6 +7,7 @@ import android.view.View; import android.view.ViewStub; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import org.chromium.base.supplier.BooleanSupplier; @@ -50,6 +51,7 @@ private final boolean mIsTabletGtsPolishEnabled; private final boolean mIsTabToGtsAnimationEnabled; private final BooleanSupplier mIsIncognitoModeEnabledSupplier; + private final TopToolbarInteractabilityManager mTopToolbarInteractabilityManager; TabSwitcherModeTTCoordinator(ViewStub tabSwitcherToolbarStub, ViewStub tabSwitcherFullscreenToolbarStub, MenuButtonCoordinator menuButtonCoordinator, @@ -62,6 +64,8 @@ mIsTabletGtsPolishEnabled = isTabletGtsPolishEnabled; mIsTabToGtsAnimationEnabled = isTabToGtsAnimationEnabled; mIsIncognitoModeEnabledSupplier = isIncognitoModeEnabledSupplier; + mTopToolbarInteractabilityManager = + new TopToolbarInteractabilityManager(enabled -> setNewTabEnabled(enabled)); } /** @@ -261,6 +265,11 @@ mActiveTabSwitcherToolbar.setNewTabButtonHighlight(highlight); } + @NonNull + TopToolbarInteractabilityManager getTopToolbarInteractabilityManager() { + return mTopToolbarInteractabilityManager; + } + /** * Initialize {@link IncognitoTabModelObserver}, if the new tab variation is enabled. This * function will initialize observer, if it is not initialized before. @@ -301,4 +310,10 @@ boolean doesExist = mTabModelSelector.getModel(true).getCount() != 0; mActiveTabSwitcherToolbar.onIncognitoTabsExistenceChanged(doesExist); } + + private void setNewTabEnabled(boolean enabled) { + if (mActiveTabSwitcherToolbar != null) { + mActiveTabSwitcherToolbar.setNewTabButtonEnabled(enabled); + } + } }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTopToolbar.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTopToolbar.java index 1d7b851..f24cd63 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTopToolbar.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTopToolbar.java
@@ -208,6 +208,14 @@ } /** + * A method to toggle the enabled state of the new tab view button. + */ + void setNewTabButtonEnabled(boolean enabled) { + mNewTabViewButton.setEnabled(enabled); + mNewTabImageButton.setEnabled(enabled); + } + + /** * @param tabCountProvider The {@link TabCountProvider} used to observe the number of tabs in * the current model. */
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java index 8bbb3a3..c478f5c 100644 --- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -10,6 +10,7 @@ import android.view.View.OnClickListener; import android.view.ViewStub; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -706,6 +707,16 @@ } } + /** + * @return A {@link TopToolbarInteractabilityManager} which allows non toolbar clients to toggle + * the interactability of elements present in the top toolbar. + */ + public @NonNull TopToolbarInteractabilityManager getTopToolbarInteractabilityManager() { + return mStartSurfaceToolbarCoordinator != null + ? mStartSurfaceToolbarCoordinator.getTopToolbarInteractabilityManager() + : mTabSwitcherModeCoordinator.getTopToolbarInteractabilityManager(); + } + /** Returns the {@link OptionalBrowsingModeButtonController}. */ @VisibleForTesting public OptionalBrowsingModeButtonController getOptionalButtonControllerForTesting() {
diff --git a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc index 77d8851..fe9fe6c 100644 --- a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc +++ b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
@@ -179,9 +179,8 @@ } IN_PROC_BROWSER_TEST_F(AppListClientImplBrowserTest, ShowAppInfo) { - web_app::WebAppProvider::GetForTest(profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile()) + ->InstallSystemAppsForTesting(); AppListClientImpl* client = AppListClientImpl::GetInstance(); const extensions::Extension* app = InstallPlatformApp("minimal");
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_item_browsertest.cc b/chrome/browser/ui/app_list/app_service/app_service_app_item_browsertest.cc index bd1e9cd..0e063ad7 100644 --- a/chrome/browser/ui/app_list/app_service/app_service_app_item_browsertest.cc +++ b/chrome/browser/ui/app_list/app_service/app_service_app_item_browsertest.cc
@@ -269,9 +269,8 @@ IN_PROC_BROWSER_TEST_P(AppServiceSystemWebAppItemBrowserTest, Activate) { Profile* const profile = browser()->profile(); - auto& system_web_app_manager = - web_app::WebAppProvider::GetForTest(profile)->system_web_app_manager(); - system_web_app_manager.InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); const web_app::AppId app_id = web_app::kHelpAppId; // Wait for app service to see the newly installed apps.
diff --git a/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc b/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc index 747da0d..ddd7683a 100644 --- a/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc +++ b/chrome/browser/ui/app_list/search/help_app_search_browsertest.cc
@@ -134,9 +134,8 @@ // the Discover page. IN_PROC_BROWSER_TEST_P(HelpAppSearchBrowserTest, ClickingDiscoverTabSuggestionChipLaunchesHelpApp) { - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); GetProfile()->GetPrefs()->SetInteger( prefs::kDiscoverTabSuggestionChipTimesLeftToShow, 3); @@ -180,9 +179,8 @@ // left to show it. IN_PROC_BROWSER_TEST_P(HelpAppSearchBrowserTest, AppListSearchHasReleaseNotesSuggestionChip) { - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); GetProfile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); @@ -206,9 +204,8 @@ // the chip is shown. IN_PROC_BROWSER_TEST_P(HelpAppSearchBrowserTest, ReleaseNotesDecreasesTimesShownOnAppListOpen) { - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); GetProfile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); ash::AppListTestApi app_list_test_api; @@ -233,9 +230,8 @@ IN_PROC_BROWSER_TEST_P( HelpAppSearchBrowserTest, ReleaseNotesDecreasesTimesShownOnAppListOpenInTabletMode) { - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); GetProfile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); ash::AppListTestApi app_list_test_api; @@ -266,9 +262,8 @@ // the What's New page. IN_PROC_BROWSER_TEST_P(HelpAppSearchBrowserTest, ClickingReleaseNotesSuggestionChipLaunchesHelpApp) { - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); GetProfile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); @@ -306,9 +301,8 @@ IN_PROC_BROWSER_TEST_P(HelpAppSearchBrowserTest, HelpAppProviderProvidesListResults) { // Need this because it sets up the icon. - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); // Add some searchable content to the help app search handler. std::vector<ash::help_app::mojom::SearchConceptPtr> search_concepts; auto search_concept = ash::help_app::mojom::SearchConcept::New( @@ -384,9 +378,8 @@ // Test that Help App shows up normally even when suggestion chip should show. IN_PROC_BROWSER_TEST_P(HelpAppSwaSearchBrowserTest, AppListSearchHasApp) { - web_app::WebAppProvider::GetForTest(GetProfile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile()) + ->InstallSystemAppsForTesting(); GetProfile()->GetPrefs()->SetInteger( prefs::kReleaseNotesSuggestionChipTimesLeftToShow, 3); @@ -406,9 +399,8 @@ IN_PROC_BROWSER_TEST_P(HelpAppSwaSearchBrowserTest, Launch) { Profile* profile = browser()->profile(); - auto& system_web_app_manager = - web_app::WebAppProvider::GetForTest(profile)->system_web_app_manager(); - system_web_app_manager.InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); const web_app::AppId app_id = web_app::kHelpAppId; ShowAppListAndWaitForZeroStateResults(
diff --git a/chrome/browser/ui/ash/arc_open_url_delegate_impl_browsertest.cc b/chrome/browser/ui/ash/arc_open_url_delegate_impl_browsertest.cc index 698042b5..f203fe1 100644 --- a/chrome/browser/ui/ash/arc_open_url_delegate_impl_browsertest.cc +++ b/chrome/browser/ui/ash/arc_open_url_delegate_impl_browsertest.cc
@@ -100,9 +100,8 @@ const GURL& expected_url, size_t expected_setting_window_count) { // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser->profile()) + ->InstallSystemAppsForTesting(); ArcOpenUrlDelegateImpl::GetForTesting()->OpenChromePageFromArc(page); @@ -379,9 +378,8 @@ IN_PROC_BROWSER_TEST_F(ArcOpenUrlDelegateImplBrowserTest, TestOpenChromePage) { // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); TestAllOSSettingPages(GURL(chrome::kChromeUIOSSettingsURL)); TestAllBrowserSettingPages(GURL(chrome::kChromeUISettingsURL));
diff --git a/chrome/browser/ui/ash/chrome_new_window_client.cc b/chrome/browser/ui/ash/chrome_new_window_client.cc index ff5698f..cb95481 100644 --- a/chrome/browser/ui/ash/chrome_new_window_client.cc +++ b/chrome/browser/ui/ash/chrome_new_window_client.cc
@@ -536,7 +536,7 @@ bool ChromeNewWindowClient::IsCameraAppEnabled() { Profile* const profile = ProfileManager::GetActiveUserProfile(); - auto* provider = web_app::WebAppProvider::GetForSystemWebApps(profile); - return provider && provider->system_web_app_manager().IsAppEnabled( - ash::SystemWebAppType::CAMERA); + auto* swa_manager = web_app::SystemWebAppManager::Get(profile); + return swa_manager && + swa_manager->IsAppEnabled(ash::SystemWebAppType::CAMERA); }
diff --git a/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.cc b/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.cc index cc606ad..cc8ed18 100644 --- a/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.cc +++ b/chrome/browser/ui/ash/desks_templates/desks_templates_app_launch_handler.cc
@@ -119,9 +119,8 @@ absl::optional<ash::SystemWebAppType> swa_type = web_app::GetSystemWebAppTypeForAppId(profile(), app_id); if (swa_type.has_value()) { - auto* system_app = web_app::WebAppProvider::GetForSystemWebApps(profile()) - ->system_web_app_manager() - .GetSystemApp(*swa_type); + auto* system_app = + web_app::SystemWebAppManager::Get(profile())->GetSystemApp(*swa_type); DCHECK(system_app); is_multi_instance_window = system_app->ShouldShowNewWindowMenuOption(); }
diff --git a/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc b/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc index 0ae033b..ffdb48b 100644 --- a/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc +++ b/chrome/browser/ui/ash/desks_templates/desks_templates_client_browsertest.cc
@@ -436,9 +436,8 @@ // extensions::PlatformAppBrowserTest: void SetUpOnMainThread() override { ::full_restore::SetActiveProfilePath(profile()->GetPath()); - web_app::WebAppProvider::GetForTest(profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile()) + ->InstallSystemAppsForTesting(); extensions::PlatformAppBrowserTest::SetUpOnMainThread(); }
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl.cc b/chrome/browser/ui/ash/projector/projector_client_impl.cc index 8908814..82a1f223 100644 --- a/chrome/browser/ui/ash/projector/projector_client_impl.cc +++ b/chrome/browser/ui/ash/projector/projector_client_impl.cc
@@ -270,11 +270,11 @@ void ProjectorClientImpl::OnEnablementPolicyChanged() { Profile* profile = ProfileManager::GetActiveUserProfile(); - web_app::SystemWebAppManager& manager = - web_app::WebAppProvider::GetForSystemWebApps(profile) - ->system_web_app_manager(); + web_app::SystemWebAppManager* swa_manager = + web_app::SystemWebAppManager::Get(profile); const bool is_installed = - manager.IsSystemWebApp(ash::kChromeUITrustedProjectorSwaAppId); + swa_manager && + swa_manager->IsSystemWebApp(ash::kChromeUITrustedProjectorSwaAppId); // We can't enable or disable the app if it's not already installed. if (!is_installed) return;
diff --git a/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc b/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc index b0a8fb4..c3fdafd2 100644 --- a/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc +++ b/chrome/browser/ui/ash/projector/projector_client_impl_browsertest.cc
@@ -183,9 +183,8 @@ IN_PROC_BROWSER_TEST_F(ProjectorClientTest, OpenProjectorApp) { auto* profile = browser()->profile(); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); client()->OpenProjectorApp(); web_app::FlushSystemWebAppLaunchesForTesting(profile); @@ -203,9 +202,8 @@ IN_PROC_BROWSER_TEST_F(ProjectorClientTest, MinimizeProjectorApp) { auto* profile = browser()->profile(); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); client()->OpenProjectorApp(); web_app::FlushSystemWebAppLaunchesForTesting(profile); @@ -227,9 +225,8 @@ IN_PROC_BROWSER_TEST_F(ProjectorClientTest, CloseProjectorApp) { auto* profile = browser()->profile(); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); client()->OpenProjectorApp(); web_app::FlushSystemWebAppLaunchesForTesting(profile); @@ -341,9 +338,8 @@ IN_PROC_BROWSER_TEST_P(ProjectorClientManagedTest, CantOpenProjectorAppWithoutPolicy) { auto* profile = browser()->profile(); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); client()->OpenProjectorApp(); web_app::FlushSystemWebAppLaunchesForTesting(profile); @@ -358,9 +354,8 @@ IN_PROC_BROWSER_TEST_P(ProjectorClientManagedTest, DisableThenEnablePolicy) { auto* profile = browser()->profile(); profile->GetPrefs()->SetBoolean(GetPolicy(), true); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); client()->OpenProjectorApp(); web_app::FlushSystemWebAppLaunchesForTesting(profile);
diff --git a/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc b/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc index aff91db..20b70e7d 100644 --- a/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc +++ b/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
@@ -58,9 +58,8 @@ void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - web_app::WebAppProvider::GetForTest(profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile()) + ->InstallSystemAppsForTesting(); base::Time start_time; ASSERT_TRUE(base::Time::FromUTCString(kStartTime, &start_time)); @@ -280,9 +279,8 @@ void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - web_app::WebAppProvider::GetForTest(profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile()) + ->InstallSystemAppsForTesting(); } protected:
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc index 6a3882d7..6b65de2 100644 --- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc +++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_browsertest.cc
@@ -936,10 +936,8 @@ IN_PROC_BROWSER_TEST_P(AppServiceAppWindowSystemWebAppBrowserTest, SystemWebAppWindow) { - auto& system_web_app_manager = - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager(); - system_web_app_manager.InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); const std::string app_id = web_app::kOsSettingsAppId; web_app::LaunchWebAppBrowser(browser()->profile(), app_id);
diff --git a/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller_browsertest.cc b/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller_browsertest.cc index 26131c4..74d8f173 100644 --- a/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller_browsertest.cc +++ b/chrome/browser/ui/ash/shelf/app_shortcut_shelf_item_controller_browsertest.cc
@@ -64,9 +64,8 @@ } void InstallApp() { - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); app_id_ = *web_app::GetAppIdForSystemWebApp( browser()->profile(), ash::SystemWebAppType::TERMINAL);
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc index aaf85c06a..99ba2dd 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
@@ -2216,10 +2216,8 @@ // icon's context menu works as expected. IN_PROC_BROWSER_TEST_F(ShelfAppBrowserTest, CloseSystemAppByShelfContextMenu) { // Prepare for launching the setting app. - auto& system_web_app_manager = - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager(); - system_web_app_manager.InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); // Record the default shelf item count. const int default_item_count = shelf_model()->item_count(); @@ -2394,9 +2392,8 @@ // Ensure opening settings and task manager windows create new shelf items. IN_PROC_BROWSER_TEST_F(ShelfWebAppBrowserTest, SettingsAndTaskManagerWindows) { // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); chrome::SettingsWindowManager* settings_manager = chrome::SettingsWindowManager::GetInstance(); @@ -3114,9 +3111,8 @@ void WaitForSystemAppsSynchronized() { base::RunLoop run_loop; - WebAppProvider::GetForSystemWebApps(browser()->profile()) - ->system_web_app_manager() - .on_apps_synchronized() + web_app::SystemWebAppManager::Get(browser()->profile()) + ->on_apps_synchronized() .Post(FROM_HERE, run_loop.QuitClosure()); run_loop.Run(); }
diff --git a/chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.cc b/chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.cc new file mode 100644 index 0000000..718a18b9 --- /dev/null +++ b/chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.cc
@@ -0,0 +1,9 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_assistant/password_change/mock_password_change_run_controller.h" + +MockPasswordChangeRunController::MockPasswordChangeRunController() = default; + +MockPasswordChangeRunController::~MockPasswordChangeRunController() = default;
diff --git a/chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.h b/chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.h new file mode 100644 index 0000000..cdd234a --- /dev/null +++ b/chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.h
@@ -0,0 +1,41 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_ASSISTANT_PASSWORD_CHANGE_MOCK_PASSWORD_CHANGE_RUN_CONTROLLER_H_ +#define CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_PASSWORD_CHANGE_RUN_CONTROLLER_H_ + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_controller.h" +#include "testing/gmock/include/gmock/gmock.h" + +// Mocked PasswordChangeRunController used in unit tests. +class MockPasswordChangeRunController : public PasswordChangeRunController { + public: + MockPasswordChangeRunController(); + ~MockPasswordChangeRunController() override; + + MOCK_METHOD(void, + Show, + (base::WeakPtr<PasswordChangeRunDisplay>), + (override)); + MOCK_METHOD(void, + SetTopIcon, + (autofill_assistant::password_change::TopIcon), + (override)); + MOCK_METHOD(void, SetTitle, (std::u16string), (override)); + MOCK_METHOD(void, SetDescription, (std::u16string), (override)); + MOCK_METHOD(void, + SetProgressBarStep, + (autofill_assistant::password_change::ProgressStep), + (override)); + + base::WeakPtr<PasswordChangeRunController> GetWeakPtr() override { + return weak_ptr_factory_.GetWeakPtr(); + } + + private: + base::WeakPtrFactory<MockPasswordChangeRunController> weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_MOCK_PASSWORD_CHANGE_RUN_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill_assistant/password_change/password_change_run_controller.h b/chrome/browser/ui/autofill_assistant/password_change/password_change_run_controller.h new file mode 100644 index 0000000..13758f5 --- /dev/null +++ b/chrome/browser/ui/autofill_assistant/password_change/password_change_run_controller.h
@@ -0,0 +1,44 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_CONTROLLER_H_ +#define CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_CONTROLLER_H_ + +#include <memory> +#include <string> + +#include "chrome/browser/autofill_assistant/password_change/proto/extensions.pb.h" + +class PasswordChangeRunDisplay; + +// Abstract interface for a controller of an `PasswordChangeRunDisplay`. +class PasswordChangeRunController { + public: + // Factory function to create the controller. + static std::unique_ptr<PasswordChangeRunController> Create(); + + virtual ~PasswordChangeRunController() = default; + + // Shows the |PasswordChangeRunDisplay|. + virtual void Show( + base::WeakPtr<PasswordChangeRunDisplay> password_change_run_display) = 0; + + // The below methods are used to set UI. + // They all persist state to a model owned by the controller and call the + // sibling view methods. + virtual void SetTopIcon( + autofill_assistant::password_change::TopIcon top_icon) = 0; + virtual void SetTitle(std::u16string title) = 0; + virtual void SetDescription(std::u16string progress_description) = 0; + virtual void SetProgressBarStep( + autofill_assistant::password_change::ProgressStep progress_step) = 0; + + // Returns a weak pointer to this controller. + virtual base::WeakPtr<PasswordChangeRunController> GetWeakPtr() = 0; + + protected: + PasswordChangeRunController() = default; +}; + +#endif // CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h b/chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h new file mode 100644 index 0000000..7cca64da1 --- /dev/null +++ b/chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h
@@ -0,0 +1,50 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_DISPLAY_H_ +#define CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_DISPLAY_H_ + +#include <memory> + +#include "base/memory/weak_ptr.h" +#include "chrome/browser/autofill_assistant/password_change/proto/extensions.pb.h" +#include "chrome/browser/ui/autofill_assistant/password_change/assistant_display_delegate.h" + +class PasswordChangeRunController; + +// Abstract interface for the view component of a password change script run. +class PasswordChangeRunDisplay { + public: + // Factory function to create a password change run. The + // actual implementation is in the `password_change_run_view.cc` file. + static base::WeakPtr<PasswordChangeRunDisplay> Create( + base::WeakPtr<PasswordChangeRunController> controller, + raw_ptr<AssistantDisplayDelegate> display_delegate); + + virtual ~PasswordChangeRunDisplay() = default; + + // Shows password change run UI. + virtual void Show() = 0; + + // The below methods are used to set UI. + // They all persist state to a model owned by the controller and call the + // sibling view methods. + virtual void SetTopIcon( + autofill_assistant::password_change::TopIcon top_icon) = 0; + virtual void SetTitle(std::u16string title) = 0; + virtual void SetDescription(std::u16string progress_description) = 0; + virtual void SetProgressBarStep( + autofill_assistant::password_change::ProgressStep progress_step) = 0; + + // TODO(crbug.com/1322419): Configure prompts + + // Notifies the view that the controller was destroyed so that the view + // can close itself. + virtual void OnControllerGone() = 0; + + protected: + PasswordChangeRunDisplay() = default; +}; + +#endif // CHROME_BROWSER_UI_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_DISPLAY_H_
diff --git a/chrome/browser/ui/browser_navigator.cc b/chrome/browser/ui/browser_navigator.cc index 0f338d0..9315a94 100644 --- a/chrome/browser/ui/browser_navigator.cc +++ b/chrome/browser/ui/browser_navigator.cc
@@ -362,7 +362,7 @@ case WindowOpenDisposition::NEW_PICTURE_IN_PICTURE: // Always show a new picture in picture window. - params->window_action = NavigateParams::SHOW_WINDOW; + params->window_action = NavigateParams::SHOW_WINDOW_INACTIVE; break; case WindowOpenDisposition::NEW_WINDOW: @@ -837,6 +837,14 @@ } } + // If this is a Picture in Picture window, then notify the pip manager about + // it. This enables the opener and pip window to stay connected, so that (for + // example), the pip window does not outlive the opener. + if (params->disposition == WindowOpenDisposition::NEW_PICTURE_IN_PICTURE) { + PictureInPictureWindowManager::GetInstance()->EnterDocumentPictureInPicture( + params->source_contents, contents_to_navigate_or_insert); + } + params->navigated_or_inserted_contents = contents_to_navigate_or_insert; return navigation_handle; }
diff --git a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc index 885ab2a..69121b4 100644 --- a/chrome/browser/ui/content_settings/framebust_block_browsertest.cc +++ b/chrome/browser/ui/content_settings/framebust_block_browsertest.cc
@@ -254,9 +254,8 @@ #endif IN_PROC_BROWSER_TEST_F(FramebustBlockBrowserTest, MAYBE_ManageButtonClicked) { #if BUILDFLAG(IS_CHROMEOS_ASH) - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); #endif const GURL url = embedded_test_server()->GetURL("/iframe.html");
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc index e1605cc7..313c128d 100644 --- a/chrome/browser/ui/omnibox/chrome_omnibox_client.cc +++ b/chrome/browser/ui/omnibox/chrome_omnibox_client.cc
@@ -260,7 +260,8 @@ if (should_preload) { if (SearchPrefetchService* search_prefetch_service = SearchPrefetchServiceFactory::GetForProfile(profile_)) { - search_prefetch_service->OnResultChanged(result); + search_prefetch_service->OnResultChanged(controller_->GetWebContents(), + result); } } @@ -276,19 +277,6 @@ int result_index = -1; for (const AutocompleteMatch& match : result) { ++result_index; - - // Trigger prerendering only if `should_preload` is set to true. Caller - // uses this parameter to explicitly allow embedders to preload (currently, - // prefetch or prerender). A typical scenario is that the caller will only - // set it to true if the results will not change, to ensure that the - // preload operation is not triggered for the same input repeatedly. - // TODO(https://crbug.com/1295170): Migrate this part to - // SearchPrefetchService, to unify pre* operations. - if (prerender_utils::IsSearchSuggestionPrerenderEnabled() && - should_preload && BaseSearchProvider::ShouldPrerender(match)) { - DoPrerender(match); - } - if (match.ImageUrl().is_empty()) { continue; }
diff --git a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc index 762415a..1be902e 100644 --- a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc +++ b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.cc
@@ -12,18 +12,20 @@ using password_manager::CreateDialogTraits; using password_manager::CredentialLeakType; using password_manager::metrics_util::LeakDialogDismissalReason; -using password_manager::metrics_util::LogLeakDialogTypeAndDismissalReason; +using password_manager::metrics_util::LeakDialogMetricsRecorder; CredentialLeakDialogControllerImpl::CredentialLeakDialogControllerImpl( PasswordsLeakDialogDelegate* delegate, CredentialLeakType leak_type, const GURL& url, - const std::u16string& username) + const std::u16string& username, + std::unique_ptr<LeakDialogMetricsRecorder> metrics_recorder) : delegate_(delegate), leak_type_(leak_type), leak_dialog_traits_(CreateDialogTraits(leak_type)), url_(url), - username_(username) {} + username_(username), + metrics_recorder_(std::move(metrics_recorder)) {} CredentialLeakDialogControllerImpl::~CredentialLeakDialogControllerImpl() { ResetDialog(); @@ -41,35 +43,30 @@ } void CredentialLeakDialogControllerImpl::OnCancelDialog() { - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kClickedClose); delegate_->OnLeakDialogHidden(); } void CredentialLeakDialogControllerImpl::OnAcceptDialog() { if (ShouldOfferAutomatedPasswordChange()) { - delegate_->StartAutomatedPasswordChange(url_, username_); - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kClickedChangePasswordAutomatically); + delegate_->StartAutomatedPasswordChange(url_, username_); } else if (ShouldCheckPasswords()) { - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kClickedCheckPasswords); delegate_->NavigateToPasswordCheckup( password_manager::PasswordCheckReferrer::kPasswordBreachDialog); } else { - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kClickedOk); } delegate_->OnLeakDialogHidden(); } void CredentialLeakDialogControllerImpl::OnCloseDialog() { - LogLeakDialogTypeAndDismissalReason( - password_manager::GetLeakDialogType(leak_type_), + metrics_recorder_->LogLeakDialogTypeAndDismissalReason( LeakDialogDismissalReason::kNoDirectInteraction); delegate_->OnLeakDialogHidden(); }
diff --git a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h index 9ed9900d..25200d9 100644 --- a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h +++ b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl.h
@@ -8,6 +8,7 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/passwords/credential_leak_dialog_controller.h" #include "components/password_manager/core/browser/leak_detection_dialog_utils.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "url/gurl.h" class CredentialLeakPrompt; @@ -21,7 +22,9 @@ PasswordsLeakDialogDelegate* delegate, password_manager::CredentialLeakType leak_type, const GURL& url, - const std::u16string& username); + const std::u16string& username, + std::unique_ptr< + password_manager::metrics_util::LeakDialogMetricsRecorder>); CredentialLeakDialogControllerImpl( const CredentialLeakDialogControllerImpl&) = delete; @@ -54,6 +57,10 @@ std::unique_ptr<password_manager::LeakDialogTraits> leak_dialog_traits_; GURL url_; std::u16string username_; + + // Metrics recorder for leak dialog related UMA and UKM logging. + std::unique_ptr<password_manager::metrics_util::LeakDialogMetricsRecorder> + metrics_recorder_; }; #endif // CHROME_BROWSER_UI_PASSWORDS_CREDENTIAL_LEAK_DIALOG_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc index 048a3ed..a63bf6e 100644 --- a/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc +++ b/chrome/browser/ui/passwords/credential_leak_dialog_controller_impl_unittest.cc
@@ -8,23 +8,33 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "chrome/browser/ui/passwords/password_dialog_prompts.h" #include "chrome/browser/ui/passwords/passwords_leak_dialog_delegate_mock.h" +#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/common/password_manager_features.h" +#include "components/ukm/test_ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_source_id.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace { +constexpr ukm::SourceId kTestSourceId = 0x1234; + using password_manager::CreateLeakType; using password_manager::HasChangeScript; using password_manager::IsReused; using password_manager::IsSaved; using password_manager::IsSyncing; using password_manager::metrics_util::LeakDialogDismissalReason; +using password_manager::metrics_util::LeakDialogMetricsRecorder; +using password_manager::metrics_util::LeakDialogType; using testing::StrictMock; +using UkmEntry = ukm::builders::PasswordManager_LeakWarningDialog; constexpr char kUrl[] = "https://www.example.co.uk"; constexpr char16_t kUsername[] = u"Jane"; @@ -43,8 +53,13 @@ class CredentialLeakDialogControllerTest : public testing::Test { public: void SetUpController(password_manager::CredentialLeakType leak_type) { + auto recorder = std::make_unique<LeakDialogMetricsRecorder>( + kTestSourceId, password_manager::GetLeakDialogType(leak_type)); + // Set sampling rate to 100% for UKM metrics. + recorder->SetSamplingRateForTesting(1.0); controller_ = std::make_unique<CredentialLeakDialogControllerImpl>( - &ui_controller_mock_, leak_type, GURL(kUrl), kUsername); + &ui_controller_mock_, leak_type, GURL(kUrl), kUsername, + std::move(recorder)); } base::HistogramTester& histogram_tester() { return histogram_tester_; } @@ -53,17 +68,40 @@ return ui_controller_mock_; } + ukm::TestAutoSetUkmRecorder& test_ukm_recorder() { + return test_ukm_recorder_; + } + MockCredentialLeakPrompt& leak_prompt() { return leak_prompt_; } CredentialLeakDialogControllerImpl& controller() { return *controller_; } private: + base::test::TaskEnvironment task_environment_; base::HistogramTester histogram_tester_; + ukm::TestAutoSetUkmRecorder test_ukm_recorder_; StrictMock<PasswordsLeakDialogDelegateMock> ui_controller_mock_; StrictMock<MockCredentialLeakPrompt> leak_prompt_; std::unique_ptr<CredentialLeakDialogControllerImpl> controller_; }; +void CheckUkmMetricsExpectations( + ukm::TestAutoSetUkmRecorder& recorder, + LeakDialogType expected_dialog_type, + LeakDialogDismissalReason expected_dismissal_reason) { + const auto& entries = recorder.GetEntriesByName(UkmEntry::kEntryName); + EXPECT_EQ(1u, entries.size()); + for (const auto* entry : entries) { + EXPECT_EQ(kTestSourceId, entry->source_id); + recorder.ExpectEntryMetric(entry, + UkmEntry::kPasswordLeakDetectionDialogTypeName, + static_cast<int64_t>(expected_dialog_type)); + recorder.ExpectEntryMetric( + entry, UkmEntry::kPasswordLeakDetectionDialogDismissalReasonName, + static_cast<int64_t>(expected_dismissal_reason)); + } +} + TEST_F(CredentialLeakDialogControllerTest, CredentialLeakDialogClose) { SetUpController(CreateLeakType(IsSaved(false), IsReused(false), IsSyncing(false), HasChangeScript(false))); @@ -82,6 +120,9 @@ "PasswordManager.LeakDetection.DialogDismissalReason.Change", LeakDialogDismissalReason::kNoDirectInteraction, 1); + CheckUkmMetricsExpectations(test_ukm_recorder(), LeakDialogType::kChange, + LeakDialogDismissalReason::kNoDirectInteraction); + EXPECT_CALL(leak_prompt(), ControllerGone()); } @@ -103,6 +144,9 @@ "PasswordManager.LeakDetection.DialogDismissalReason.Change", LeakDialogDismissalReason::kClickedOk, 1); + CheckUkmMetricsExpectations(test_ukm_recorder(), LeakDialogType::kChange, + LeakDialogDismissalReason::kClickedOk); + EXPECT_CALL(leak_prompt(), ControllerGone()); } @@ -124,6 +168,10 @@ "PasswordManager.LeakDetection.DialogDismissalReason.CheckupAndChange", LeakDialogDismissalReason::kClickedClose, 1); + CheckUkmMetricsExpectations(test_ukm_recorder(), + LeakDialogType::kCheckupAndChange, + LeakDialogDismissalReason::kClickedClose); + EXPECT_CALL(leak_prompt(), ControllerGone()); } @@ -149,6 +197,10 @@ "PasswordManager.LeakDetection.DialogDismissalReason.Checkup", LeakDialogDismissalReason::kClickedCheckPasswords, 1); + CheckUkmMetricsExpectations( + test_ukm_recorder(), LeakDialogType::kCheckup, + LeakDialogDismissalReason::kClickedCheckPasswords); + EXPECT_CALL(leak_prompt(), ControllerGone()); }
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index 88a1d11..65140927 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -45,6 +45,7 @@ #include "components/feature_engagement/public/tracker.h" #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" #include "components/password_manager/core/browser/form_saver_impl.h" +#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/move_password_to_account_store_helper.h" #include "components/password_manager/core/browser/password_bubble_experiment.h" #include "components/password_manager/core/browser/password_form_manager_for_ui.h" @@ -290,8 +291,12 @@ else ClearPopUpFlagForBubble(); - auto* raw_controller = - new CredentialLeakDialogControllerImpl(this, leak_type, url, username); + auto* raw_controller = new CredentialLeakDialogControllerImpl( + this, leak_type, url, username, + std::make_unique< + password_manager::metrics_util::LeakDialogMetricsRecorder>( + web_contents()->GetMainFrame()->GetPageUkmSourceId(), + password_manager::GetLeakDialogType(leak_type))); dialog_controller_.reset(raw_controller); raw_controller->ShowCredentialLeakPrompt( CreateCredentialLeakPrompt(raw_controller));
diff --git a/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc b/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc index 478d4302..3436fc3 100644 --- a/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc +++ b/chrome/browser/ui/settings_window_manager_browsertest_chromeos.cc
@@ -52,9 +52,8 @@ void SetUpOnMainThread() override { // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); } SettingsWindowManagerTest(const SettingsWindowManagerTest&) = delete;
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc index 5bf9b1f..ff7caec 100644 --- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc +++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views.cc
@@ -68,9 +68,8 @@ bool CanShowAppInfoDialog(Profile* profile, const std::string& extension_id) { #if BUILDFLAG(IS_CHROMEOS_ASH) - bool is_system_web_app = web_app::WebAppProvider::GetForSystemWebApps(profile) - ->system_web_app_manager() - .IsSystemWebApp(extension_id); + bool is_system_web_app = + web_app::SystemWebAppManager::Get(profile)->IsSystemWebApp(extension_id); if (is_system_web_app) { return false; }
diff --git a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc index dc669ed..593b37a0 100644 --- a/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc +++ b/chrome/browser/ui/views/autofill/payments/save_card_bubble_views_browsertest.cc
@@ -176,9 +176,8 @@ ASSERT_TRUE(SetupClients()); #if BUILDFLAG(IS_CHROMEOS_ASH) // Install the Settings App. - web_app::WebAppProvider::GetForTest(GetProfile(0)) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(GetProfile(0)) + ->InstallSystemAppsForTesting(); #endif // It's important to use the blank tab here and not some arbitrary page.
diff --git a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_display.cc b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_display.cc new file mode 100644 index 0000000..8188c4e --- /dev/null +++ b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_display.cc
@@ -0,0 +1,19 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> +#include <vector> + +#include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h" +#include "chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.h" + +// Factory function to create PasswordChangeRun for desktop. Today +// apc_client_impl.cc will make sure to finish the script and get rid of the +// pointer to the this display/view once its closed. +base::WeakPtr<PasswordChangeRunDisplay> PasswordChangeRunDisplay::Create( + base::WeakPtr<PasswordChangeRunController> controller, + raw_ptr<AssistantDisplayDelegate> display_delegate) { + return (new PasswordChangeRunView(controller, display_delegate)) + ->GetWeakPtr(); +}
diff --git a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc new file mode 100644 index 0000000..80cd2d7 --- /dev/null +++ b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.cc
@@ -0,0 +1,85 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_assistant/password_change/password_change_run_view.h" + +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/memory/ptr_util.h" +#include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/autofill_assistant/password_change/proto/extensions.pb.h" +#include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_controller.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/views/background.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/view.h" + +PasswordChangeRunView::PasswordChangeRunView( + base::WeakPtr<PasswordChangeRunController> controller, + raw_ptr<AssistantDisplayDelegate> display_delegate) + : controller_(controller), display_delegate_(display_delegate) { + DCHECK(display_delegate_); + + // Renders the view in the display delegate and passes ownership of `this`. + display_delegate_->SetView(base::WrapUnique(this)); +} + +PasswordChangeRunView::~PasswordChangeRunView() = default; + +void PasswordChangeRunView::Show() { + PasswordChangeRunView::CreateView(); +} + +void PasswordChangeRunView::CreateView() { + DCHECK(controller_); + // TODO(crbug.com/1322419): Add proper icons, sizes, style etc. + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical, gfx::Insets())); + SetBackground(views::CreateSolidBackground(SK_ColorWHITE)); + + // Set up top container. + std::unique_ptr<views::View> top_container = std::make_unique<views::View>(); + top_container->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, gfx::Insets())); + + top_icon_ = top_container->AddChildView(std::make_unique<views::ImageView>()); + top_icon_->SetImage( + ui::ImageModel::FromVectorIcon(kKeyIcon, ui::kColorIcon, 64)); + top_icon_->SetHorizontalAlignment(views::ImageView::Alignment::kLeading); + // TODO(brunobraga): Initialise progress bar. + title_ = AddChildView(std::make_unique<views::Label>()); + description_ = AddChildView(std::make_unique<views::Label>()); + body_ = AddChildView(std::make_unique<views::View>()); + + AddChildView(std::move(top_container)); +} + +// TODO(crbug.com/1322419): Implement set methods. +void PasswordChangeRunView::SetTopIcon( + autofill_assistant::password_change::TopIcon top_icon) {} +void PasswordChangeRunView::SetTitle(std::u16string body_title) {} +void PasswordChangeRunView::SetDescription( + std::u16string progress_description) {} +void PasswordChangeRunView::SetProgressBarStep( + autofill_assistant::password_change::ProgressStep progress_step) {} + +void PasswordChangeRunView::OnControllerGone() { + Close(); +} + +void PasswordChangeRunView::Close() { + // Remove this view from the `display_delegate_`, effectively destroying it. + display_delegate_->RemoveView(); +} + +base::WeakPtr<PasswordChangeRunView> PasswordChangeRunView::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +BEGIN_METADATA(PasswordChangeRunView, views::View) +END_METADATA
diff --git a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.h b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.h new file mode 100644 index 0000000..6e1e579 --- /dev/null +++ b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view.h
@@ -0,0 +1,73 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_VIEW_H_ + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/autofill_assistant/password_change/proto/extensions.pb.h" +#include "chrome/browser/ui/autofill_assistant/password_change/password_change_run_display.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/view.h" + +namespace views { +class ImageView; +class Label; +} // namespace views + +class PasswordChangeRunController; + +// View that displays the automatic password change experience. When this class +// is instantiated its ownership is given to the `display_delegate` passed +// during construction. +class PasswordChangeRunView : public views::View, + public PasswordChangeRunDisplay { + public: + METADATA_HEADER(PasswordChangeRunView); + PasswordChangeRunView(base::WeakPtr<PasswordChangeRunController> controller, + raw_ptr<AssistantDisplayDelegate> display_delegate); + ~PasswordChangeRunView() override; + + PasswordChangeRunView(const PasswordChangeRunView&) = delete; + PasswordChangeRunView& operator=(const PasswordChangeRunView&) = delete; + + // PasswordChangeRunDisplay + void Show() override; + void SetTopIcon( + autofill_assistant::password_change::TopIcon top_icon) override; + void SetTitle(std::u16string title) override; + void SetDescription(std::u16string progress_description) override; + void SetProgressBarStep( + autofill_assistant::password_change::ProgressStep progress_step) override; + void OnControllerGone() override; + + // Returns a weak pointer to itself. + base::WeakPtr<PasswordChangeRunView> GetWeakPtr(); + + private: + // Create/initialise the view. + void CreateView(); + + // Closes the view by removing itself from the display. + // This method destroys an instance of this class. + void Close(); + + // The controller belonging to this view. + base::WeakPtr<PasswordChangeRunController> controller_; + // The display that owns this view. + raw_ptr<AssistantDisplayDelegate> display_delegate_; + + raw_ptr<views::ImageView> top_icon_ = nullptr; + raw_ptr<views::Label> title_ = nullptr; + raw_ptr<views::Label> description_ = nullptr; + // The body is used to render stuff under the title and description, i.e + // prompts. + raw_ptr<views::View> body_ = nullptr; + + // Factory for weak pointers to this view. + base::WeakPtrFactory<PasswordChangeRunView> weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_AUTOFILL_ASSISTANT_PASSWORD_CHANGE_PASSWORD_CHANGE_RUN_VIEW_H_
diff --git a/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc new file mode 100644 index 0000000..f9e6070 --- /dev/null +++ b/chrome/browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc
@@ -0,0 +1,47 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_assistant/password_change/password_change_run_view.h" + +#include <memory> + +#include "base/callback_helpers.h" +#include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/autofill_assistant/password_change/mock_assistant_display_delegate.h" +#include "chrome/browser/ui/autofill_assistant/password_change/mock_password_change_run_controller.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/view.h" + +using ::testing::StrictMock; + +class PasswordChangeRunViewTest : public views::ViewsTestBase { + public: + PasswordChangeRunViewTest() { + // Take ownership of the display. + ON_CALL(display_delegate_, SetView) + .WillByDefault([&view = view_](std::unique_ptr<views::View> display) { + view = std::move(display); + return view.get(); + }); + } + ~PasswordChangeRunViewTest() override = default; + + protected: + // Mock display delegate and controller. + StrictMock<MockAssistantDisplayDelegate> display_delegate_; + StrictMock<MockPasswordChangeRunController> controller_; + + // Variable required to simulate the display delegate. + std::unique_ptr<views::View> view_; +}; + +TEST_F(PasswordChangeRunViewTest, CreateAndSetInTheProvidedDisplay) { + // The display delegate is notified that a view wants to register itself. + EXPECT_CALL(display_delegate_, SetView); + + PasswordChangeRunDisplay::Create(controller_.GetWeakPtr(), + &display_delegate_); +}
diff --git a/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc index 9ac03cc..a4e368e 100644 --- a/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc +++ b/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
@@ -141,9 +141,8 @@ SetUncleanStartup(); RegisterApp(); // Ensure Terminal System App is installed. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); // First app should fail with 'cancelled for recovery'. crostini::LaunchCrostiniApp(
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 6ae5e32..8774a0ee 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
@@ -580,9 +580,8 @@ IN_PROC_BROWSER_TEST_P(BrowserNonClientFrameViewChromeOSTest, SettingsSystemWebAppHasMinimumWindowSize) { // Install the Settings System Web App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); // Open a settings window. auto* settings_manager = chrome::SettingsWindowManager::GetInstance();
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc b/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc index fc34b154..5fd657a 100644 --- a/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc +++ b/chrome/browser/ui/views/frame/system_menu_model_builder_browsertest_chromeos.cc
@@ -52,9 +52,8 @@ // Install the Settings App. Profile* profile = ProfileHelper::Get()->GetProfileByUser( UserManager::Get()->FindUser(account_id1_)); - web_app::WebAppProvider::GetForTest(profile) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); // Open the settings window and record the |settings_browser|. auto* manager = SettingsWindowManager::GetInstance();
diff --git a/chrome/browser/ui/views/overlay/document_overlay_window_views_unittest.cc b/chrome/browser/ui/views/overlay/document_overlay_window_views_unittest.cc index ec58249..9181ec9c 100644 --- a/chrome/browser/ui/views/overlay/document_overlay_window_views_unittest.cc +++ b/chrome/browser/ui/views/overlay/document_overlay_window_views_unittest.cc
@@ -64,15 +64,11 @@ content::WebContents* GetWebContents() override { return web_contents_; } // DocumentPictureInPictureWindowController - void SetChildWebContents( - std::unique_ptr<content::WebContents> child) override { - child_web_contents_ = std::move(child); + void SetChildWebContents(content::WebContents* child) override { + child_web_contents_ = child; } content::WebContents* GetChildWebContents() override { - return child_web_contents_.get(); - } - content::DocumentOverlayWindow* GetWindowForTesting() override { - return nullptr; + return child_web_contents_; } void set_web_contents(content::WebContents* web_contents) { @@ -83,7 +79,7 @@ private: raw_ptr<content::WebContents> web_contents_; - std::unique_ptr<content::WebContents> child_web_contents_; + raw_ptr<content::WebContents> child_web_contents_; }; class DocumentOverlayWindowViewsTest : public ChromeViewsTestBase { @@ -106,7 +102,7 @@ auto child = content::WebContentsTester::CreateTestWebContents(&profile_, nullptr); - pip_window_controller_.SetChildWebContents(std::move(child)); + pip_window_controller_.SetChildWebContents(child.get()); #if BUILDFLAG(IS_CHROMEOS) test_views_delegate()->set_context(GetContext());
diff --git a/chrome/browser/ui/views/payments/payment_request_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_browsertest.cc index 76c32ab..9a2d841 100644 --- a/chrome/browser/ui/views/payments/payment_request_browsertest.cc +++ b/chrome/browser/ui/views/payments/payment_request_browsertest.cc
@@ -617,9 +617,8 @@ IN_PROC_BROWSER_TEST_F(PaymentRequestSettingsLinkTest, ClickSettingsLink) { #if BUILDFLAG(IS_CHROMEOS_ASH) // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); #endif NavigateTo("/payment_request_no_shipping_test.html"); @@ -672,9 +671,8 @@ ClickSettingsLink) { #if BUILDFLAG(IS_CHROMEOS_ASH) // Install the Settings App. - web_app::WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager() - .InstallSystemAppsForTesting(); + web_app::SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); #endif // Installs two apps so that the Payment Request UI will be shown.
diff --git a/chrome/browser/ui/views/profiles/profile_picker_turn_sync_on_delegate.cc b/chrome/browser/ui/views/profiles/profile_picker_turn_sync_on_delegate.cc index 368d23b..7c158573 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_turn_sync_on_delegate.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_turn_sync_on_delegate.cc
@@ -13,6 +13,7 @@ #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/profile_picker.h" #include "chrome/browser/ui/ui_features.h" +#include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "chrome/browser/ui/webui/signin/signin_ui_error.h" #include "chrome/browser/ui/webui/signin/signin_utils.h" @@ -198,8 +199,13 @@ absl::optional<ProfileMetrics::ProfileSignedInFlowOutcome> outcome = GetSyncOutcome(enterprise_account_, sync_disabled_, result); - if (outcome) + if (outcome) { LogOutcome(*outcome); + } else if (IsLacrosPrimaryProfileFirstRun(profile_) && + result == LoginUIService::UI_CLOSED) { + ProfileMetrics::LogLacrosPrimaryProfileFirstRunOutcome( + ProfileMetrics::ProfileSignedInFlowOutcome::kAbortedAfterSignIn); + } FinishSyncConfirmation(result); }
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc index adfbbe1..8fbe0d9 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_view_browsertest.cc
@@ -1844,6 +1844,7 @@ // Dummy case to set up the primary profile. } IN_PROC_BROWSER_TEST_F(ProfilePickerLacrosFirstRunBrowserTest, PRE_QuitEarly) { + base::HistogramTester histogram_tester; ProfileManager* profile_manager = g_browser_process->profile_manager(); Profile* profile = profile_manager->GetProfile(profile_manager->GetPrimaryUserProfilePath()); @@ -1865,6 +1866,10 @@ WaitForPickerClosed(); EXPECT_EQ(0u, BrowserList::GetInstance()->size()); EXPECT_TRUE(ShouldOpenPrimaryProfileFirstRun(profile)); + histogram_tester.ExpectBucketCount( + "Profile.LacrosPrimaryProfileFirstRunOutcome", + ProfileMetrics::ProfileSignedInFlowOutcome::kAbortedOnEnterpriseWelcome, + 1); } IN_PROC_BROWSER_TEST_F(ProfilePickerLacrosFirstRunBrowserTest, QuitEarly) { // On the second run, the FRE is still not marked finished and we should @@ -1882,6 +1887,7 @@ // Dummy case to set up the primary profile. } IN_PROC_BROWSER_TEST_F(ProfilePickerLacrosFirstRunBrowserTest, PRE_QuitAtEnd) { + base::HistogramTester histogram_tester; ProfileManager* profile_manager = g_browser_process->profile_manager(); Profile* profile = profile_manager->GetProfile(profile_manager->GetPrimaryUserProfilePath()); @@ -1909,6 +1915,9 @@ // Because we quit, we should also quit chrome, but mark the FRE finished. EXPECT_FALSE(ShouldOpenPrimaryProfileFirstRun(profile)); EXPECT_EQ(0u, BrowserList::GetInstance()->size()); + histogram_tester.ExpectBucketCount( + "Profile.LacrosPrimaryProfileFirstRunOutcome", + ProfileMetrics::ProfileSignedInFlowOutcome::kAbortedAfterSignIn, 1); } IN_PROC_BROWSER_TEST_F(ProfilePickerLacrosFirstRunBrowserTest, QuitAtEnd) { // On the second run, the FRE is marked finished and we should skip it. @@ -1925,6 +1934,7 @@ // Dummy case to set up the primary profile. } IN_PROC_BROWSER_TEST_F(ProfilePickerLacrosFirstRunBrowserTest, PRE_OptIn) { + base::HistogramTester histogram_tester; ProfileManager* profile_manager = g_browser_process->profile_manager(); Profile* profile = profiles::testing::CreateProfileSync( profile_manager, profile_manager->GetPrimaryUserProfilePath()); @@ -1953,6 +1963,9 @@ WaitForPickerClosed(); EXPECT_FALSE(ShouldOpenPrimaryProfileFirstRun(profile)); EXPECT_EQ(1u, BrowserList::GetInstance()->size()); + histogram_tester.ExpectBucketCount( + "Profile.LacrosPrimaryProfileFirstRunOutcome", + ProfileMetrics::ProfileSignedInFlowOutcome::kConsumerSync, 1); } IN_PROC_BROWSER_TEST_F(ProfilePickerLacrosFirstRunBrowserTest, OptIn) {
diff --git a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc index 3b3c631..940e9f9 100644 --- a/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc +++ b/chrome/browser/ui/web_applications/system_web_app_ui_utils.cc
@@ -77,18 +77,16 @@ absl::optional<ash::SystemWebAppType> GetSystemWebAppTypeForAppId( Profile* profile, const AppId& app_id) { - auto* provider = WebAppProvider::GetForSystemWebApps(profile); - return provider ? provider->system_web_app_manager().GetSystemAppTypeForAppId( - app_id) - : absl::optional<ash::SystemWebAppType>(); + auto* swa_manager = SystemWebAppManager::Get(profile); + return swa_manager ? swa_manager->GetSystemAppTypeForAppId(app_id) + : absl::nullopt; } absl::optional<AppId> GetAppIdForSystemWebApp(Profile* profile, ash::SystemWebAppType app_type) { - auto* provider = WebAppProvider::GetForSystemWebApps(profile); - return provider - ? provider->system_web_app_manager().GetAppIdForSystemApp(app_type) - : absl::optional<AppId>(); + auto* swa_manager = SystemWebAppManager::Get(profile); + return swa_manager ? swa_manager->GetAppIdForSystemApp(app_type) + : absl::nullopt; } absl::optional<apps::AppLaunchParams> CreateSystemWebAppLaunchParams( @@ -191,11 +189,15 @@ return nullptr; } - auto* provider = WebAppProvider::GetForSystemWebApps(profile); + SystemWebAppManager* swa_manager = SystemWebAppManager::Get(profile); + if (!swa_manager) + return nullptr; + + auto* provider = WebAppProvider::GetForLocalAppsUnchecked(profile); if (!provider) return nullptr; - auto* system_app = provider->system_web_app_manager().GetSystemApp(app_type); + auto* system_app = swa_manager->GetSystemApp(app_type); #if BUILDFLAG(IS_CHROMEOS) DCHECK(url.DeprecatedGetOriginAsURL() == provider->registrar() @@ -303,12 +305,9 @@ absl::optional<ash::SystemWebAppType> GetCapturingSystemAppForURL( Profile* profile, const GURL& url) { - auto* provider = WebAppProvider::GetForSystemWebApps(profile); - - if (!provider) - return absl::nullopt; - - return provider->system_web_app_manager().GetCapturingSystemAppForURL(url); + SystemWebAppManager* swa_manager = SystemWebAppManager::Get(profile); + return swa_manager ? swa_manager->GetCapturingSystemAppForURL(url) + : absl::nullopt; } gfx::Size GetSystemWebAppMinimumWindowSize(Browser* browser) {
diff --git a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc index 18061ec..24c3b10 100644 --- a/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc +++ b/chrome/browser/ui/web_applications/test/system_web_app_interactive_uitest.cc
@@ -530,25 +530,21 @@ void WaitForSystemWebAppInstall(Profile* profile) { base::RunLoop run_loop; - web_app::WebAppProvider::GetForSystemWebApps(profile) - ->system_web_app_manager() - .on_apps_synchronized() - .Post(FROM_HERE, base::BindLambdaForTesting([&]() { - // Wait one execution loop for - // on_apps_synchronized() to be called on all - // listeners. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, run_loop.QuitClosure()); - })); + web_app::SystemWebAppManager::Get(profile)->on_apps_synchronized().Post( + FROM_HERE, base::BindLambdaForTesting([&]() { + // Wait one execution loop for + // on_apps_synchronized() to be called on all + // listeners. + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); + })); run_loop.Run(); } AppId GetAppId(Profile* profile) { - SystemWebAppManager& manager = - web_app::WebAppProvider::GetForSystemWebApps(profile) - ->system_web_app_manager(); absl::optional<AppId> app_id = - manager.GetAppIdForSystemApp(installation_->GetType()); + web_app::SystemWebAppManager::Get(profile)->GetAppIdForSystemApp( + installation_->GetType()); CHECK(app_id.has_value()); return *app_id; }
diff --git a/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc b/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc index 3770d43..d741a87 100644 --- a/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc +++ b/chrome/browser/ui/web_applications/web_app_guest_session_browsertest_chromeos.cc
@@ -41,10 +41,8 @@ // Test that the OS Settings app launches successfully. IN_PROC_BROWSER_TEST_P(WebAppGuestSessionBrowserTest, LaunchOsSettings) { - auto& system_web_app_manager = - WebAppProvider::GetForTest(browser()->profile()) - ->system_web_app_manager(); - system_web_app_manager.InstallSystemAppsForTesting(); + SystemWebAppManager::GetForTest(browser()->profile()) + ->InstallSystemAppsForTesting(); Profile* profile = browser()->profile(); apps::AppLaunchParams params(
diff --git a/chrome/browser/ui/web_applications/web_app_launch_process.cc b/chrome/browser/ui/web_applications/web_app_launch_process.cc index 8a7dad87..b7b9e01 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_process.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_process.cc
@@ -89,10 +89,11 @@ // DCHECK on the basic scope. DCHECK(provider_.registrar().IsUrlInAppScope(launch_url, params_.app_id) || GetSystemWebAppTypeForAppId(&profile_, params_.app_id) && - provider_.system_web_app_manager().GetSystemApp( - *GetSystemWebAppTypeForAppId(&profile_, params_.app_id)) && - provider_.system_web_app_manager() - .GetSystemApp( + SystemWebAppManager::GetForLocalAppsUnchecked(&profile_) + ->GetSystemApp( + *GetSystemWebAppTypeForAppId(&profile_, params_.app_id)) && + SystemWebAppManager::GetForLocalAppsUnchecked(&profile_) + ->GetSystemApp( *GetSystemWebAppTypeForAppId(&profile_, params_.app_id)) ->IsUrlInSystemAppScope(launch_url)); #endif
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc index c355bc8..8552077a 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -227,7 +227,8 @@ GetSystemWebAppTypeForAppId(browser->profile(), app_id); if (system_app_type) { system_app = - provider->system_web_app_manager().GetSystemApp(*system_app_type); + SystemWebAppManager::GetForLocalAppsUnchecked(browser->profile()) + ->GetSystemApp(*system_app_type); } const bool has_tab_strip = !browser->is_type_app_popup() && @@ -307,6 +308,11 @@ AppBrowserController* app_controller = browser->app_controller(); WebAppProvider* web_app_provider = WebAppProvider::GetForLocalAppsUnchecked(browser->profile()); + DCHECK(web_app_provider); + SystemWebAppManager* swa_manager = + SystemWebAppManager::GetForLocalAppsUnchecked(browser->profile()); + DCHECK(swa_manager); + TRACE_EVENT_INSTANT( "system_apps", "BadNavigate", [&](perfetto::EventContext ctx) { auto* bad_navigate = @@ -322,9 +328,7 @@ bad_navigate->set_web_app_provider_registry_ready( web_app_provider->on_registry_ready().is_signaled()); bad_navigate->set_system_web_app_manager_synchronized( - web_app_provider->system_web_app_manager() - .on_apps_synchronized() - .is_signaled()); + swa_manager->on_apps_synchronized().is_signaled()); }); UMA_HISTOGRAM_ENUMERATION("WebApp.SystemApps.BadNavigate.Type", capturing_system_app_type.value());
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index c42d12be..364fad4 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -1043,9 +1043,9 @@ if (url.host_piece() == chrome::kChromeUIAssistantOptInHost) return &NewWebUI<chromeos::AssistantOptInUI>; if (url.host_piece() == ash::kChromeUICameraAppHost) { - auto* provider = web_app::WebAppProvider::GetForSystemWebApps(profile); - if (provider && provider->system_web_app_manager().IsAppEnabled( - ash::SystemWebAppType::CAMERA)) { + auto* swa_manager = web_app::SystemWebAppManager::Get(profile); + if (swa_manager && + swa_manager->IsAppEnabled(ash::SystemWebAppType::CAMERA)) { return &NewComponentUI<ash::CameraAppUI, ChromeCameraAppUIDelegate>; } }
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc index 8dbd3df..fc9c8e42 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -58,6 +58,8 @@ namespace chromeos { CoreOobeHandler::CoreOobeHandler(const std::string& display_type) { + is_oobe_display_ = display_type == OobeUI::kOobeDisplay; + ash::TabletMode::Get()->AddObserver(this); OobeConfiguration::Get()->AddAndFireObserver(this); @@ -75,12 +77,6 @@ UpdateClientAreaSize( display::Screen::GetScreen()->GetPrimaryDisplay().size()); - bool has_api_keys_configured = google_apis::HasAPIKeyConfigured() && - google_apis::HasOAuthClientConfigured(); - CallJS("cr.ui.Oobe.showAPIKeysNotice", - !has_api_keys_configured && (display_type == OobeUI::kOobeDisplay || - display_type == OobeUI::kLoginDisplay)); - // Don't show version label on the stable and beta channels by default. version_info::Channel channel = chrome::GetChannel(); if (channel != version_info::Channel::STABLE && @@ -113,8 +109,12 @@ // Strings for Asset Identifier shown in version string. builder->Add("assetIdLabel", IDS_OOBE_ASSET_ID_LABEL); - builder->AddF("missingAPIKeysNotice", IDS_LOGIN_API_KEYS_NOTICE, - base::ASCIIToUTF16(google_apis::kAPIKeysDevelopersHowToURL)); + const bool has_api_keys_configured = google_apis::HasAPIKeyConfigured() && + google_apis::HasOAuthClientConfigured(); + if (!has_api_keys_configured && is_oobe_display_) { + builder->AddF("missingAPIKeysNotice", IDS_LOGIN_API_KEYS_NOTICE, + base::ASCIIToUTF16(google_apis::kAPIKeysDevelopersHowToURL)); + } builder->Add("playAnimationAriaLabel", IDS_OOBE_PLAY_ANIMATION_MESSAGE); builder->Add("pauseAnimationAriaLabel", IDS_OOBE_PAUSE_ANIMATION_MESSAGE);
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h index 5328653..b8faac3 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -127,6 +127,8 @@ // Help application used for help dialogs. scoped_refptr<HelpAppLauncher> help_app_; + + bool is_oobe_display_ = false; }; } // namespace chromeos
diff --git a/chrome/browser/ui/webui/realbox/realbox_handler.cc b/chrome/browser/ui/webui/realbox/realbox_handler.cc index 6aeb81b..d3586c2 100644 --- a/chrome/browser/ui/webui/realbox/realbox_handler.cc +++ b/chrome/browser/ui/webui/realbox/realbox_handler.cc
@@ -748,7 +748,7 @@ if (SearchPrefetchService* search_prefetch_service = SearchPrefetchServiceFactory::GetForProfile(profile_)) { search_prefetch_service->OnResultChanged( - autocomplete_controller_->result()); + web_contents_, autocomplete_controller_->result()); } }
diff --git a/chrome/browser/ui/webui/realbox/realbox_handler_browsertest.cc b/chrome/browser/ui/webui/realbox/realbox_handler_browsertest.cc index 58dc811..5bf65023 100644 --- a/chrome/browser/ui/webui/realbox/realbox_handler_browsertest.cc +++ b/chrome/browser/ui/webui/realbox/realbox_handler_browsertest.cc
@@ -11,8 +11,15 @@ #include "base/check.h" #include "base/memory/scoped_refptr.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/prefetch/search_prefetch/field_trial_settings.h" +#include "chrome/browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h" +#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service.h" +#include "chrome/browser/prefetch/search_prefetch/search_prefetch_service_factory.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/omnibox/omnibox_pedal_implementations.h" +#include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" #include "components/omnibox/browser/actions/omnibox_pedal.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_type.h" @@ -20,6 +27,8 @@ #include "components/omnibox/browser/vector_icons.h" #include "components/omnibox/common/omnibox_features.h" #include "content/public/test/browser_test.h" +#include "content/public/test/prerender_test_util.h" +#include "mojo/public/cpp/bindings/remote.h" #include "ui/gfx/vector_icon_types.h" namespace { @@ -113,3 +122,69 @@ EXPECT_FALSE(svg_name.empty()); } } + +class RealboxSearchPreloadBrowserTest : public SearchPrefetchBaseBrowserTest { + public: + RealboxSearchPreloadBrowserTest() + : prerender_helper_(base::BindRepeating( + &RealboxSearchPreloadBrowserTest::GetWebContents, + base::Unretained(this))) { + scoped_feature_list_.InitWithFeaturesAndParameters( + {{features::kSupportSearchSuggestionForPrerender2, {}}, + {kSearchPrefetchServicePrefetching, + {{"max_attempts_per_caching_duration", "3"}, + {"cache_size", "1"}, + {"device_memory_threshold_MB", "0"}}}}, + /*disabled_features=*/{kSearchPrefetchBlockBeforeHeaders}); + } + + private: + content::test::PrerenderTestHelper prerender_helper_; + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// A sink instance that allows Realbox to make IPC without failing DCHECK. +class RealboxSearchBrowserTestPage : public realbox::mojom::Page { + public: + // realbox::mojom::Page + void AutocompleteResultChanged( + realbox::mojom::AutocompleteResultPtr result) override {} + void AutocompleteMatchImageAvailable(uint32_t match_index, + const GURL& url, + const std::string& data_url) override {} + + mojo::PendingRemote<realbox::mojom::Page> GetRemotePage() { + return receiver_.BindNewPipeAndPassRemote(); + } + + private: + mojo::Receiver<realbox::mojom::Page> receiver_{this}; +}; + +// Tests the realbox input can trigger prerender and prefetch. +IN_PROC_BROWSER_TEST_F(RealboxSearchPreloadBrowserTest, SearchPreloadSuccess) { + mojo::Remote<realbox::mojom::PageHandler> remote_page_handler; + RealboxSearchBrowserTestPage page; + RealboxHandler realbox_handler = + RealboxHandler(remote_page_handler.BindNewPipeAndPassReceiver(), + browser()->profile(), GetWebContents()); + realbox_handler.SetPage(page.GetRemotePage()); + content::test::PrerenderHostRegistryObserver registry_observer( + *GetWebContents()); + + std::string input_query = "pre"; + std::string search_terms = "prerender"; + AddNewSuggestionRule(input_query, {search_terms}, /*prefetch_index=*/0, + /*prerender_index=*/0); + GURL prerender_url = GetSearchServerQueryURL(search_terms + "&pf=cs&"); + + // Fake a WebUI input. + remote_page_handler->QueryAutocomplete(base::ASCIIToUTF16(input_query), + /*prevent_inline_autocomplete=*/false); + remote_page_handler.FlushForTesting(); + + // Prerender and Prefetch should be triggered. + WaitUntilStatusChangesTo(base::ASCIIToUTF16(search_terms), + SearchPrefetchStatus::kComplete); + registry_observer.WaitForTrigger(prerender_url); +}
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index ba55900..6b89a35a 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1032,6 +1032,7 @@ {"editPasswordUsernameLabel", IDS_SETTINGS_PASSWORDS_USERNAME}, {"editPasswordPasswordLabel", IDS_SETTINGS_PASSWORDS_PASSWORD}, {"passwordNoteLabel", IDS_SETTINGS_PASSWORDS_NOTE}, + {"passwordNoNoteAdded", IDS_SETTINGS_PASSWORDS_NO_NOTE_ADDED}, {"passwordNoteCharacterCount", IDS_SETTINGS_PASSWORDS_NOTE_CHARACTER_COUNT}, {"passwordNoteCharacterCountWarning",
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc index 4c18781..7df4532 100644 --- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc +++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
@@ -71,6 +71,7 @@ provider_(WebAppProvider::GetForWebApps(profile)), publisher_helper_(profile, provider_, + /*swa_manager=*/nullptr, apps::AppType::kWeb, this, /*observe_media_requests=*/true) {
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc index c22dc4b..aa4341c 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -275,11 +275,13 @@ WebAppPublisherHelper::WebAppPublisherHelper(Profile* profile, WebAppProvider* provider, + SystemWebAppManager* swa_manager, apps::AppType app_type, Delegate* delegate, bool observe_media_requests) : profile_(profile), provider_(provider), + swa_manager_(swa_manager), app_type_(app_type), delegate_(delegate) { DCHECK(profile_); @@ -1607,11 +1609,10 @@ app.show_in_shelf = true; #if BUILDFLAG(IS_CHROMEOS_ASH) - auto system_app_type = - provider_->system_web_app_manager().GetSystemAppTypeForAppId(app.app_id); + DCHECK(swa_manager_); + auto system_app_type = swa_manager_->GetSystemAppTypeForAppId(app.app_id); if (system_app_type.has_value()) { - auto* system_app = - provider_->system_web_app_manager().GetSystemApp(*system_app_type); + auto* system_app = swa_manager_->GetSystemApp(*system_app_type); DCHECK(system_app); app.show_in_launcher = system_app->ShouldShowInLauncher(); app.show_in_search = system_app->ShouldShowInSearch(); @@ -1632,11 +1633,10 @@ app->show_in_shelf = apps::mojom::OptionalBool::kTrue; #if BUILDFLAG(IS_CHROMEOS_ASH) - auto system_app_type = - provider_->system_web_app_manager().GetSystemAppTypeForAppId(app->app_id); + DCHECK(swa_manager_); + auto system_app_type = swa_manager_->GetSystemAppTypeForAppId(app->app_id); if (system_app_type.has_value()) { - auto* system_app = - provider_->system_web_app_manager().GetSystemApp(*system_app_type); + auto* system_app = swa_manager_->GetSystemApp(*system_app_type); DCHECK(system_app); app->show_in_launcher = system_app->ShouldShowInLauncher() ? apps::mojom::OptionalBool::kTrue
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h index 11024d4..aeaaac4 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
@@ -77,6 +77,7 @@ namespace web_app { +class SystemWebAppManager; class WebApp; class WebAppProvider; class WebAppLaunchManager; @@ -119,6 +120,7 @@ WebAppPublisherHelper(Profile* profile, WebAppProvider* provider, + SystemWebAppManager* swa_manager, apps::AppType app_type, Delegate* delegate, bool observe_media_requests); @@ -409,6 +411,8 @@ const raw_ptr<Profile> profile_; const raw_ptr<WebAppProvider> provider_; + // nullptr for Lacros Chrome, valid pointer otherwise. + const raw_ptr<SystemWebAppManager> swa_manager_; // The app type of the publisher. The app type is kSystemWeb if the web apps // are serving from Lacros, and the app type is kWeb for all other cases.
diff --git a/chrome/browser/web_applications/app_service/web_apps.cc b/chrome/browser/web_applications/app_service/web_apps.cc index 1af6c14..b85713c 100644 --- a/chrome/browser/web_applications/app_service/web_apps.cc +++ b/chrome/browser/web_applications/app_service/web_apps.cc
@@ -95,6 +95,7 @@ #endif publisher_helper_(profile_, provider_, + SystemWebAppManager::GetForLocalAppsUnchecked(profile_), app_type_, this, ShouldObserveMediaRequests()) { @@ -394,9 +395,8 @@ ash::SystemWebAppType swa_type = web_app->client_data().system_web_app_data->system_app_type; - auto* system_app = WebAppProvider::GetForSystemWebApps(profile()) - ->system_web_app_manager() - .GetSystemApp(swa_type); + auto* system_app = + SystemWebAppManager::Get(profile())->GetSystemApp(swa_type); if (system_app && system_app->ShouldShowNewWindowMenuOption()) { apps::AddCommandItem(menu_type == apps::mojom::MenuType::kAppList ? ash::LAUNCH_NEW
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc index 7ef50cc..c2a7fb4 100644 --- a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc +++ b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/web_applications/web_app_id.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_install_utils.h" +#include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h" #include "chrome/browser/web_applications/web_app_system_web_app_delegate_map_utils.h" @@ -242,6 +243,37 @@ SystemWebAppManager::~SystemWebAppManager() = default; +// static +SystemWebAppManager* SystemWebAppManager::Get(Profile* profile) { + WebAppProvider* provider = WebAppProvider::GetForSystemWebApps(profile); + if (!provider) + return nullptr; + + provider->CheckIsConnected(); + return provider->system_web_app_manager_.get(); +} + +// static +SystemWebAppManager* SystemWebAppManager::GetForLocalAppsUnchecked( + Profile* profile) { + WebAppProvider* provider = WebAppProvider::GetForLocalAppsUnchecked(profile); + if (!provider) + return nullptr; + + provider->CheckIsConnected(); + return provider->system_web_app_manager_.get(); +} + +// static +SystemWebAppManager* SystemWebAppManager::GetForTest(Profile* profile) { + WebAppProvider* provider = WebAppProvider::GetForTest(profile); + if (!provider) + return nullptr; + + provider->CheckIsConnected(); + return provider->system_web_app_manager_.get(); +} + void SystemWebAppManager::StopBackgroundTasks() { for (auto& task : tasks_) { task->StopTask();
diff --git a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h index e523e2a..5009bed 100644 --- a/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h +++ b/chrome/browser/web_applications/system_web_apps/system_web_app_manager.h
@@ -77,6 +77,24 @@ SystemWebAppManager& operator=(const SystemWebAppManager&) = delete; virtual ~SystemWebAppManager(); + // On Chrome OS: returns the SystemWebAppManager that hosts System Web Apps in + // Ash; In Lacros, returns nullptr (unless + // EnableSystemWebAppInLacrosForTesting). On other platforms, always returns a + // SystemWebAppManager. + static SystemWebAppManager* Get(Profile* profile); + + // Returns the SystemWebAppManager object for the current process. + // Avoid using this function where possible and prefer `Get` which guarantees + // it is being called from the correct process. Only use + // `GetForLocalAppsUnchecked` if the calling code is shared between Ash/Lacros + // and expects that some SystemWebAppManager always exists. In Lacros, this + // function returns an empty SWA manager with no concrete apps. + static SystemWebAppManager* GetForLocalAppsUnchecked(Profile* profile); + + // Returns the SystemWebAppManager for tests, regardless of whether this is + // running in Lacros/Ash. Blocks if the web app registry is not yet ready. + static SystemWebAppManager* GetForTest(Profile* profile); + void SetSubsystems( ExternallyManagedAppManager* externally_managed_app_manager, WebAppRegistrar* registrar,
diff --git a/chrome/browser/web_applications/system_web_apps/test/system_web_app_browsertest_base.cc b/chrome/browser/web_applications/system_web_apps/test/system_web_app_browsertest_base.cc index 2b104da..3f98aaf 100644 --- a/chrome/browser/web_applications/system_web_apps/test/system_web_app_browsertest_base.cc +++ b/chrome/browser/web_applications/system_web_apps/test/system_web_app_browsertest_base.cc
@@ -31,8 +31,9 @@ SystemWebAppBrowserTestBase::~SystemWebAppBrowserTestBase() = default; SystemWebAppManager& SystemWebAppBrowserTestBase::GetManager() { - return WebAppProvider::GetForSystemWebApps(browser()->profile()) - ->system_web_app_manager(); + auto* swa_manager = SystemWebAppManager::Get(browser()->profile()); + DCHECK(swa_manager); + return *swa_manager; } ash::SystemWebAppType SystemWebAppBrowserTestBase::GetMockAppType() {
diff --git a/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc b/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc index fd3d732e2..e0aa0e0 100644 --- a/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc +++ b/chrome/browser/web_applications/system_web_apps/test/system_web_app_manager_browsertest.cc
@@ -1129,9 +1129,8 @@ // resets the OnAppsSynchronized signal, and starts a new synchronize request. void WaitForSystemAppsSynchronized() { base::RunLoop run_loop; - WebAppProvider::GetForSystemWebApps(browser()->profile()) - ->system_web_app_manager() - .on_apps_synchronized() + SystemWebAppManager::Get(browser()->profile()) + ->on_apps_synchronized() .Post(FROM_HERE, run_loop.QuitClosure()); run_loop.Run(); } @@ -1561,9 +1560,8 @@ void WaitForSystemAppsBackgroundTasksStart() { base::RunLoop run_loop; - WebAppProvider::GetForSystemWebApps(browser()->profile()) - ->system_web_app_manager() - .on_tasks_started() + SystemWebAppManager::Get(browser()->profile()) + ->on_tasks_started() .Post(FROM_HERE, run_loop.QuitClosure()); run_loop.Run();
diff --git a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc index c65b85f..5a40e46 100644 --- a/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc +++ b/chrome/browser/web_applications/system_web_apps/test/test_system_web_app_installation.cc
@@ -812,22 +812,19 @@ void TestSystemWebAppInstallation::WaitForAppInstall() { base::RunLoop run_loop; - WebAppProvider::GetForTest(profile_) - ->system_web_app_manager() - .on_apps_synchronized() - .Post(FROM_HERE, base::BindLambdaForTesting([&]() { - // Wait one execution loop for on_apps_synchronized() to be - // called on all listeners. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, run_loop.QuitClosure()); - })); + SystemWebAppManager::GetForTest(profile_)->on_apps_synchronized().Post( + FROM_HERE, base::BindLambdaForTesting([&]() { + // Wait one execution loop for on_apps_synchronized() to be + // called on all listeners. + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + run_loop.QuitClosure()); + })); run_loop.Run(); } AppId TestSystemWebAppInstallation::GetAppId() { - return WebAppProvider::GetForTest(profile_) - ->system_web_app_manager() - .GetAppIdForSystemApp(type_.value()) + return SystemWebAppManager::GetForTest(profile_) + ->GetAppIdForSystemApp(type_.value()) .value(); }
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index b1d7e351..193090fe8 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -204,11 +204,6 @@ return *translation_manager_; } -SystemWebAppManager& WebAppProvider::system_web_app_manager() { - CheckIsConnected(); - return *system_web_app_manager_; -} - OsIntegrationManager& WebAppProvider::os_integration_manager() { CheckIsConnected(); return *os_integration_manager_;
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index 6b8cda6..449f47d 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -127,8 +127,6 @@ WebAppTranslationManager& translation_manager(); - SystemWebAppManager& system_web_app_manager(); - // Manage all OS hooks that need to be deployed during Web Apps install OsIntegrationManager& os_integration_manager(); const OsIntegrationManager& os_integration_manager() const; @@ -153,6 +151,9 @@ } protected: + // TODO(crbug.com/1321984): Delete system_web_app_manager_. + friend class SystemWebAppManager; + virtual void StartImpl(); void CreateSubsystems(Profile* profile);
diff --git a/chrome/browser/web_applications/web_app_tab_helper.cc b/chrome/browser/web_applications/web_app_tab_helper.cc index 8c2b32a..8c1a5a0 100644 --- a/chrome/browser/web_applications/web_app_tab_helper.cc +++ b/chrome/browser/web_applications/web_app_tab_helper.cc
@@ -84,9 +84,11 @@ // If navigating to a System Web App (including navigation in sub frames), let // SystemWebAppManager perform tab-secific setup for navigations in System Web // Apps. - if (provider_->system_web_app_manager().IsSystemWebApp(GetAppId())) { - provider_->system_web_app_manager().OnReadyToCommitNavigation( - GetAppId(), navigation_handle); + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + auto* swa_manager = SystemWebAppManager::GetForLocalAppsUnchecked(profile); + if (swa_manager && swa_manager->IsSystemWebApp(GetAppId())) { + swa_manager->OnReadyToCommitNavigation(GetAppId(), navigation_handle); } }
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index a165fc5..393f9df 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1653415098-194ce5295f1889c17c5cbd97f10e30c876505bb6.profdata +chrome-linux-main-1653457894-c1c98ebdc71e8e5e0a955c22acdd2432e860188e.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 2530305..7807d9e6 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1653415098-14ed3c50df80b4d4570bddf7715e2090814bdd9b.profdata +chrome-mac-arm-main-1653457894-1295a2b381c8cbf13daa4d22086bb419f17c0904.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 11131d6..cb0bb25 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1653415098-b4a54b46c793c9267ad2d644efdf10a880cc7a74.profdata +chrome-mac-main-1653479601-5fd4bd525fcedc71c930dc3a80ac45a74f3d47f9.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 0a73f26..1e146f2a 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1653447597-3bdd82544e0e093e0e15cfd63cc3ac82936d4f75.profdata +chrome-win32-main-1653469178-de1e6b23055601e62606e6521dc479e3d2a90fec.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 2d4e258..aaacfa1e 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1653447597-4b6c87e37b924ca72d3e2ca1ee08d37095aba595.profdata +chrome-win64-main-1653469178-cdd96f0086bae731cb4135c531d0daa3a0eaede9.profdata
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b11d2f9..d8bf697 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -844,6 +844,7 @@ "../browser/password_manager/passwords_navigation_observer.cc", "../browser/password_manager/passwords_navigation_observer.h", "../browser/policy/policy_prefs_browsertest.cc", + "../browser/prefetch/search_prefetch/search_preload_unified_browsertest.cc", "../browser/profiles/profile_browsertest_android.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.cc", "../browser/safe_browsing/test_safe_browsing_database_helper.h", @@ -1933,6 +1934,7 @@ "../browser/prefetch/search_prefetch/search_prefetch_browser_test_base.cc", "../browser/prefetch/search_prefetch/search_prefetch_browser_test_base.h", "../browser/prefetch/search_prefetch/search_prefetch_service_browsertest.cc", + "../browser/prefetch/search_prefetch/search_preload_unified_browsertest.cc", "../browser/prefetch/zero_suggest_prefetch/zero_suggest_prefetch_tab_helper_browsertest.cc", "../browser/prefs/pref_functional_browsertest.cc", "../browser/prefs/pref_service_browsertest.cc", @@ -6588,6 +6590,7 @@ "../browser/ui/views/autofill/save_address_profile_view_unittest.cc", "../browser/ui/views/autofill/update_address_profile_view_unittest.cc", "../browser/ui/views/autofill_assistant/password_change/assistant_side_panel_coordinator_impl_unittest.cc", + "../browser/ui/views/autofill_assistant/password_change/password_change_run_view_unittest.cc", "../browser/ui/views/file_system_access/file_system_access_ui_helpers_unittest.cc", "../browser/ui/views/location_bar/permission_chip_unittest.cc", "../browser/ui/views/passwords/move_to_account_store_bubble_view_unittest.cc", @@ -9823,6 +9826,7 @@ } if (is_chromeos_ash) { sources += [ + "../browser/sync/test/integration/ash_custom_passphrase_sharing_sync_test.cc", "../browser/sync/test/integration/ash_lacros_sync_test.cc", "../browser/sync/test/integration/single_client_app_list_sync_test.cc", "../browser/sync/test/integration/single_client_arc_package_sync_test.cc",
diff --git a/chrome/test/data/client_hints/partitioned_cookies_embeddee.html b/chrome/test/data/client_hints/partitioned_cookies_embeddee.html new file mode 100644 index 0000000..a9213b9 --- /dev/null +++ b/chrome/test/data/client_hints/partitioned_cookies_embeddee.html
@@ -0,0 +1,6 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head> +</head> +Empty file used for embedded partitioned cookies Origin Trial testing. +</html>
diff --git a/chrome/test/data/client_hints/partitioned_cookies_same_origin.html b/chrome/test/data/client_hints/partitioned_cookies_same_origin.html new file mode 100644 index 0000000..9add677 --- /dev/null +++ b/chrome/test/data/client_hints/partitioned_cookies_same_origin.html
@@ -0,0 +1,6 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head> +</head> +Empty file used for same-origin partitioned cookies Origin Trial testing. +</html>
diff --git a/chrome/test/data/webui/settings/password_view_test.ts b/chrome/test/data/webui/settings/password_view_test.ts index 3ea2af1..a485904 100644 --- a/chrome/test/data/webui/settings/password_view_test.ts +++ b/chrome/test/data/webui/settings/password_view_test.ts
@@ -61,6 +61,7 @@ const SITE = 'site1.com'; const USERNAME = 'user1'; const PASSWORD = 'p455w0rd'; + const NOTE = 'some note'; const ID = 0; let passwordManager: TestPasswordManagerProxy; @@ -80,7 +81,7 @@ test('Valid site and username displays an entry', async function() { const passwordList = [ createPasswordEntry( - {url: item.url, username: item.username, id: ID}), + {url: item.url, username: item.username, id: ID, note: NOTE}), ]; passwordManager.data.passwords = passwordList; @@ -94,8 +95,31 @@ await flushTasks(); assertVisibilityOfPageElements(page, /*visibility=*/ true); + assertEquals( + NOTE, + page.shadowRoot!.querySelector('settings-textarea')!.value); })); + test('Empty note shows placeholder text', async function() { + const passwordList = [ + createPasswordEntry({url: SITE, username: USERNAME, id: ID}), + ]; + + passwordManager.data.passwords = passwordList; + const page = document.createElement('password-view'); + document.body.appendChild(page); + const params = new URLSearchParams({ + username: USERNAME, + site: SITE, + }); + Router.getInstance().navigateTo(routes.PASSWORD_VIEW, params); + + await flushTasks(); + assertEquals( + 'No note added', + page.shadowRoot!.querySelector('settings-textarea')!.value); + }); + test( 'Invalid site and username does not display an entry ' + 'and routes to passwords page',
diff --git a/chrome/test/data/webui/settings/privacy_guide_page_test.ts b/chrome/test/data/webui/settings/privacy_guide_page_test.ts index 2fb5ae8..d1f2bfc 100644 --- a/chrome/test/data/webui/settings/privacy_guide_page_test.ts +++ b/chrome/test/data/webui/settings/privacy_guide_page_test.ts
@@ -48,7 +48,7 @@ Router.getInstance().navigateTo( routes.PRIVACY_GUIDE, /* opt_dynamicParameters */ new URLSearchParams('step=' + step)); - flush(); + return flushTasks(); } /** @@ -94,7 +94,6 @@ event.syncAllDataTypes = syncAllDataTypes; event.typedUrlsSynced = typedUrlsSynced; webUIListenerCallback('sync-prefs-changed', event); - flush(); } /** @@ -110,8 +109,6 @@ let page: SettingsPrivacyGuidePageElement; let settingsPrefs: SettingsPrefsElement; let syncBrowserProxy: TestSyncBrowserProxy; - let shouldShowCookiesCard: boolean; - let shouldShowSafeBrowsingCard: boolean; let testMetricsBrowserProxy: TestMetricsBrowserProxy; suiteSetup(function() { @@ -131,8 +128,15 @@ page.disableAnimationsForTesting(); page.prefs = settingsPrefs.prefs!; document.body.appendChild(page); - shouldShowCookiesCard = true; - shouldShowSafeBrowsingCard = true; + + setSafeBrowsingSetting(SafeBrowsingSetting.STANDARD); + setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO); + setupSync({ + syncBrowserProxy: syncBrowserProxy, + syncOn: true, + syncAllDataTypes: true, + typedUrlsSynced: true, + }); setupPrivacyRouteForTest(); @@ -163,10 +167,12 @@ type: chrome.settingsPrivate.PrefType.NUMBER, value: setting, }); - shouldShowCookiesCard = - setting === CookiePrimarySetting.BLOCK_THIRD_PARTY || + } + + function shouldShowCookiesCard(): boolean { + const setting = page.getPref('generated.cookie_primary_setting').value; + return setting === CookiePrimarySetting.BLOCK_THIRD_PARTY || setting === CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO; - flush(); } /** @@ -177,9 +183,12 @@ type: chrome.settingsPrivate.PrefType.NUMBER, value: setting, }); - shouldShowSafeBrowsingCard = setting === SafeBrowsingSetting.ENHANCED || + } + + function shouldShowSafeBrowsingCard(): boolean { + const setting = page.getPref('generated.safe_browsing').value; + return setting === SafeBrowsingSetting.ENHANCED || setting === SafeBrowsingSetting.STANDARD; - flush(); } type AssertCardComponentsVisibleParams = { @@ -248,10 +257,10 @@ if (!shouldShowHistorySyncCard()) { numSteps -= 1; } - if (!shouldShowCookiesCard) { + if (!shouldShowCookiesCard()) { numSteps -= 1; } - if (!shouldShowSafeBrowsingCard) { + if (!shouldShowSafeBrowsingCard()) { numSteps -= 1; } return numSteps; @@ -318,31 +327,22 @@ if (!shouldShowHistorySyncCard()) { activeIndex -= 1; } - if (!shouldShowSafeBrowsingCard) { + if (!shouldShowSafeBrowsingCard()) { activeIndex -= 1; } assertStepIndicatorModel(activeIndex); } - test('startPrivacyGuide', async function() { - await CrSettingsPrefs.initialized; + test('welcomeForwardNavigation', async function() { assertFalse(page.getPref('privacy_guide.viewed').value); // Navigating to the privacy guide without a step parameter navigates to // the welcome card. Router.getInstance().navigateTo(routes.PRIVACY_GUIDE); - flush(); + await flushTasks(); assertWelcomeCardVisible(); assertTrue(page.getPref('privacy_guide.viewed').value); - }); - - test('welcomeForwardNavigation', async function() { - // Navigating to the privacy guide without a step parameter navigates to - // the welcome card. - Router.getInstance().navigateTo(routes.PRIVACY_GUIDE); - flush(); - assertWelcomeCardVisible(); const welcomeFragment = page.shadowRoot!.querySelector<PrivacyGuideWelcomeFragmentElement>( @@ -369,7 +369,7 @@ }); test('msbbBackNavigation', async function() { - navigateToStep(PrivacyGuideStep.MSBB); + await navigateToStep(PrivacyGuideStep.MSBB); assertMsbbCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click(); @@ -382,13 +382,7 @@ }); test('msbbForwardNavigationSyncOn', async function() { - navigateToStep(PrivacyGuideStep.MSBB); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); + await navigateToStep(PrivacyGuideStep.MSBB); assertMsbbCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); @@ -403,14 +397,14 @@ assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickMSBB'); }); - test('msbbForwardNavigationSyncOff', function() { - navigateToStep(PrivacyGuideStep.MSBB); + test('msbbForwardNavigationSyncOff', async function() { setupSync({ syncBrowserProxy: syncBrowserProxy, syncOn: false, syncAllDataTypes: false, typedUrlsSynced: false, }); + await navigateToStep(PrivacyGuideStep.MSBB); assertMsbbCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); @@ -418,13 +412,7 @@ }); test('historySyncBackNavigation', async function() { - navigateToStep(PrivacyGuideStep.HISTORY_SYNC); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); + await navigateToStep(PrivacyGuideStep.HISTORY_SYNC); assertHistorySyncCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click(); @@ -435,14 +423,8 @@ assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickHistorySync'); }); - test('historySyncNavigatesAwayOnSyncOff', function() { - navigateToStep(PrivacyGuideStep.HISTORY_SYNC); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); + test('historySyncNavigatesAwayOnSyncOff', async function() { + await navigateToStep(PrivacyGuideStep.HISTORY_SYNC); assertHistorySyncCardVisible(); // User disables sync while history sync card is shown. @@ -455,14 +437,8 @@ assertSafeBrowsingCardVisible(); }); - test('historySyncNotReachableWhenSyncOff', function() { - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); - navigateToStep(PrivacyGuideStep.HISTORY_SYNC); + test('historySyncNotReachableWhenSyncOff', async function() { + await navigateToStep(PrivacyGuideStep.HISTORY_SYNC); setupSync({ syncBrowserProxy: syncBrowserProxy, syncOn: false, @@ -475,15 +451,7 @@ test( 'historySyncCardForwardNavigationShouldShowSafeBrowsingCard', async function() { - navigateToStep(PrivacyGuideStep.HISTORY_SYNC); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); - setSafeBrowsingSetting(SafeBrowsingSetting.ENHANCED); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); + await navigateToStep(PrivacyGuideStep.HISTORY_SYNC); assertHistorySyncCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); @@ -500,16 +468,10 @@ }); test( - 'historySyncCardForwardNavigationShouldHideSafeBrowsingCard', function() { - navigateToStep(PrivacyGuideStep.HISTORY_SYNC); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); + 'historySyncCardForwardNavigationShouldHideSafeBrowsingCard', + async function() { setSafeBrowsingSetting(SafeBrowsingSetting.DISABLED); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); + await navigateToStep(PrivacyGuideStep.HISTORY_SYNC); assertHistorySyncCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); @@ -517,13 +479,7 @@ }); test('safeBrowsingCardBackNavigationSyncOn', async function() { - navigateToStep(PrivacyGuideStep.SAFE_BROWSING); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); + await navigateToStep(PrivacyGuideStep.SAFE_BROWSING); assertSafeBrowsingCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click(); @@ -535,36 +491,34 @@ }); test('safeBrowsingCardBackNavigationSyncOff', async function() { - navigateToStep(PrivacyGuideStep.SAFE_BROWSING); setupSync({ syncBrowserProxy: syncBrowserProxy, syncOn: false, syncAllDataTypes: false, typedUrlsSynced: false, }); + await navigateToStep(PrivacyGuideStep.SAFE_BROWSING); assertSafeBrowsingCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click(); assertMsbbCardVisible(); }); - test('safeBrowsingCardGetsUpdated', function() { - navigateToStep(PrivacyGuideStep.SAFE_BROWSING); - setSafeBrowsingSetting(SafeBrowsingSetting.ENHANCED); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); + test('safeBrowsingCardGetsUpdated', async function() { + await navigateToStep(PrivacyGuideStep.SAFE_BROWSING); assertSafeBrowsingCardVisible(); const radioButtonGroup = page.shadowRoot!.querySelector('#' + PrivacyGuideStep.SAFE_BROWSING)! .shadowRoot!.querySelector<SettingsRadioGroupElement>( '#safeBrowsingRadioGroup')!; assertEquals( - Number(radioButtonGroup.selected), SafeBrowsingSetting.ENHANCED); + Number(radioButtonGroup.selected), SafeBrowsingSetting.STANDARD); // Changing the safe browsing setting should automatically change the // selected radio button. - setSafeBrowsingSetting(SafeBrowsingSetting.STANDARD); + setSafeBrowsingSetting(SafeBrowsingSetting.ENHANCED); assertEquals( - Number(radioButtonGroup.selected), SafeBrowsingSetting.STANDARD); + Number(radioButtonGroup.selected), SafeBrowsingSetting.ENHANCED); // Changing the safe browsing setting to a disabled state while shown should // navigate away from the safe browsing card. @@ -575,8 +529,7 @@ test( 'safeBrowsingCardForwardNavigationShouldShowCookiesCard', async function() { - navigateToStep(PrivacyGuideStep.SAFE_BROWSING); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); + await navigateToStep(PrivacyGuideStep.SAFE_BROWSING); assertSafeBrowsingCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); @@ -594,25 +547,20 @@ actionResult, 'Settings.PrivacyGuide.NextClickSafeBrowsing'); }); - test('safeBrowsingCardForwardNavigationShouldHideCookiesCard', function() { - navigateToStep(PrivacyGuideStep.SAFE_BROWSING); - setCookieSetting(CookiePrimarySetting.ALLOW_ALL); - assertSafeBrowsingCardVisible(); + test( + 'safeBrowsingCardForwardNavigationShouldHideCookiesCard', + async function() { + setCookieSetting(CookiePrimarySetting.ALLOW_ALL); + await navigateToStep(PrivacyGuideStep.SAFE_BROWSING); + assertSafeBrowsingCardVisible(); - page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); - flush(); - assertCompletionCardVisible(); - }); + page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); + flush(); + assertCompletionCardVisible(); + }); test('cookiesCardBackNavigationShouldShowSafeBrowsingCard', async function() { - navigateToStep(PrivacyGuideStep.COOKIES); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); - setSafeBrowsingSetting(SafeBrowsingSetting.STANDARD); + await navigateToStep(PrivacyGuideStep.COOKIES); assertCookiesCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click(); @@ -624,15 +572,9 @@ assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickCookies'); }); - test('cookiesCardBackNavigationShouldHideSafeBrowsingCard', function() { - navigateToStep(PrivacyGuideStep.COOKIES); - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); + test('cookiesCardBackNavigationShouldHideSafeBrowsingCard', async function() { setSafeBrowsingSetting(SafeBrowsingSetting.DISABLED); + await navigateToStep(PrivacyGuideStep.COOKIES); assertCookiesCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#backButton')!.click(); @@ -641,7 +583,7 @@ }); test('cookiesCardForwardNavigation', async function() { - navigateToStep(PrivacyGuideStep.COOKIES); + await navigateToStep(PrivacyGuideStep.COOKIES); assertCookiesCardVisible(); page.shadowRoot!.querySelector<HTMLElement>('#nextButton')!.click(); @@ -657,9 +599,8 @@ assertEquals(actionResult, 'Settings.PrivacyGuide.NextClickCookies'); }); - test('cookiesCardGetsUpdated', function() { - navigateToStep(PrivacyGuideStep.COOKIES); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); + test('cookiesCardGetsUpdated', async function() { + await navigateToStep(PrivacyGuideStep.COOKIES); assertCookiesCardVisible(); const radioButtonGroup = page.shadowRoot!.querySelector('#' + PrivacyGuideStep.COOKIES)! @@ -667,24 +608,24 @@ '#cookiesRadioGroup')!; assertEquals( Number(radioButtonGroup.selected), - CookiePrimarySetting.BLOCK_THIRD_PARTY); + CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO); // Changing the cookie setting should automatically change the selected // radio button. - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO); + setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); assertEquals( Number(radioButtonGroup.selected), - CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO); + CookiePrimarySetting.BLOCK_THIRD_PARTY); // Changing the cookie setting to a non-third-party state while shown should // navigate away from the cookies card. setCookieSetting(CookiePrimarySetting.ALLOW_ALL); + await flushTasks(); assertCompletionCardVisible(); }); test('completionCardBackNavigation', async function() { - navigateToStep(PrivacyGuideStep.COMPLETION); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); + await navigateToStep(PrivacyGuideStep.COMPLETION); assertCompletionCardVisible(); const completionFragment = @@ -699,16 +640,15 @@ assertEquals(actionResult, 'Settings.PrivacyGuide.BackClickCompletion'); }); - test('privacyGuideVisibilityChildAccount', function() { + test('privacyGuideVisibilityChildAccount', async function() { // Set the user to have a non-child account. const syncStatus: SyncStatus = {childUser: false, statusAction: StatusAction.NO_ACTION}; webUIListenerCallback('sync-status-changed', syncStatus); - flush(); // Navigating to the privacy guide works. Router.getInstance().navigateTo(routes.PRIVACY_GUIDE); - flush(); + await flushTasks(); assertWelcomeCardVisible(); // The user signs in to a child user account. This hides the privacy guide @@ -716,38 +656,35 @@ const newSyncStatus: SyncStatus = {childUser: true, statusAction: StatusAction.NO_ACTION}; webUIListenerCallback('sync-status-changed', newSyncStatus); - flush(); assertEquals(routes.PRIVACY, Router.getInstance().getCurrentRoute()); // User trying to manually navigate to privacy guide fails. Router.getInstance().navigateTo(routes.PRIVACY_GUIDE); - flush(); + await flushTasks(); assertEquals(routes.PRIVACY, Router.getInstance().getCurrentRoute()); }); - test('privacyGuideVisibilityManagedAccount', function() { + test('privacyGuideVisibilityManagedAccount', async function() { // Set the user to have a non-managed account. webUIListenerCallback('is-managed-changed', false); - flush(); // Navigating to the privacy guide works. Router.getInstance().navigateTo(routes.PRIVACY_GUIDE); - flush(); + await flushTasks(); assertWelcomeCardVisible(); // The user signs in to a managed account. This hides the privacy guide and // navigates away back to privacy settings page. webUIListenerCallback('is-managed-changed', true); - flush(); assertEquals(routes.PRIVACY, Router.getInstance().getCurrentRoute()); // User trying to manually navigate to privacy guide fails. Router.getInstance().navigateTo(routes.PRIVACY_GUIDE); - flush(); + await flushTasks(); assertEquals(routes.PRIVACY, Router.getInstance().getCurrentRoute()); }); - test('arrowKeyNavigation', function() { + test('arrowKeyNavigation', async function() { const pgCard = page.shadowRoot!.querySelector<HTMLElement>('#privacyGuideCard')!; const arrowLeftEvent = new KeyboardEvent( @@ -766,18 +703,8 @@ // Ensure a defined text direction. loadTimeData.overrideValues({textdirection: 'ltr'}); - // Ensure that all fragments are part of the flow. - setupSync({ - syncBrowserProxy: syncBrowserProxy, - syncOn: true, - syncAllDataTypes: true, - typedUrlsSynced: true, - }); - setCookieSetting(CookiePrimarySetting.BLOCK_THIRD_PARTY); - setSafeBrowsingSetting(SafeBrowsingSetting.STANDARD); - // Forward flow. - navigateToStep(PrivacyGuideStep.WELCOME); + await navigateToStep(PrivacyGuideStep.WELCOME); dispatchArrowRightEvent(); assertMsbbCardVisible(); dispatchArrowRightEvent(); @@ -878,8 +805,7 @@ }) { page.setPrefValue( 'url_keyed_anonymized_data_collection.enabled', msbbStartOn); - flush(); - navigateToStep(PrivacyGuideStep.MSBB); + await navigateToStep(PrivacyGuideStep.MSBB); if (changeSetting) { page.shadowRoot!.querySelector('#' + PrivacyGuideStep.MSBB)!.shadowRoot! @@ -917,7 +843,7 @@ syncAllDataTypes: historySyncStartOn, typedUrlsSynced: historySyncStartOn, }); - navigateToStep(PrivacyGuideStep.HISTORY_SYNC); + await navigateToStep(PrivacyGuideStep.HISTORY_SYNC); if (changeSetting) { page.shadowRoot!.querySelector('#' + PrivacyGuideStep.HISTORY_SYNC)! @@ -952,8 +878,7 @@ SafeBrowsingSetting.ENHANCED : SafeBrowsingSetting.STANDARD; page.setPrefValue('generated.safe_browsing', safeBrowsingStartState); - flush(); - navigateToStep(PrivacyGuideStep.SAFE_BROWSING); + await navigateToStep(PrivacyGuideStep.SAFE_BROWSING); if (changeSetting) { page.shadowRoot!.querySelector( @@ -993,8 +918,7 @@ CookiePrimarySetting.BLOCK_THIRD_PARTY_INCOGNITO : CookiePrimarySetting.BLOCK_THIRD_PARTY; page.setPrefValue('generated.cookie_primary_setting', cookieStartState); - flush(); - navigateToStep(PrivacyGuideStep.COOKIES); + await navigateToStep(PrivacyGuideStep.COOKIES); if (changeSetting) { page.shadowRoot!.querySelector( @@ -1194,7 +1118,6 @@ event.typedUrlsSynced = typedUrlsSynced; event.passwordsSynced = passwordsSynced; webUIListenerCallback('sync-prefs-changed', event); - flush(); } async function assertBrowserProxyCall({ @@ -1343,9 +1266,7 @@ setupPrivacyRouteForTest(); // The user navigates to the completion step. - navigateToStep(PrivacyGuideStep.COMPLETION); - - return flushTasks(); + return navigateToStep(PrivacyGuideStep.COMPLETION); }); teardown(function() { @@ -1473,9 +1394,7 @@ setupPrivacyRouteForTest(); // The user navigates to the completion step. - navigateToStep(PrivacyGuideStep.COMPLETION); - - return flushTasks(); + return navigateToStep(PrivacyGuideStep.COMPLETION); }); teardown(function() { @@ -1526,7 +1445,7 @@ Router.getInstance().navigateTo(routes.BASIC); // The user navigates to PG. - navigateToStep(PrivacyGuideStep.WELCOME); + return navigateToStep(PrivacyGuideStep.WELCOME); }); test('closeEventClosesDialog', function() {
diff --git a/chromeos/crosapi/mojom/web_app_service.mojom b/chromeos/crosapi/mojom/web_app_service.mojom index cfd13c7..535fe0f 100644 --- a/chromeos/crosapi/mojom/web_app_service.mojom +++ b/chromeos/crosapi/mojom/web_app_service.mojom
@@ -6,6 +6,16 @@ import "chromeos/crosapi/mojom/web_app_types.mojom"; +// Describes an Android package associated with a web app. +[Stable] +struct WebAppAndroidPackage { + // Android package name. + string package_name@0; + + // SHA256 fingerprint of the certificate of this Android app. + string sha256_fingerprint@1; +}; + // Implemented in lacros-chrome. Allows ash-chrome to modify web app state in // lacros-chrome. // Next version: 1 @@ -32,7 +42,7 @@ // 2) to register its own |crosapi::mojom::WebAppProviderBridge| to let // ash-chrome to modify or query WebAppProvider in lacros-chrome. // -// Next version: 1 +// Next version: 2 // Next method id: 2 [Stable, Uuid="dfa7b3f8-236f-4706-861b-98068aa5fc8f"] interface WebAppService { @@ -40,4 +50,11 @@ // WebAppProvider in lacros-chrome. RegisterWebAppProviderBridge@0( pending_remote<WebAppProviderBridge> web_app_provider_bridge); + + // Gets the information about an Android package matching this web app, if + // this app was installed from the Play Store. Returns null if the app was not + // installed from the Play Store. + [MinVersion=1] + GetAssociatedAndroidPackage@1(string web_app_id) + => (WebAppAndroidPackage? package); };
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index d1e46c2a..435cd15c 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -205,9 +205,6 @@ "policy.PopupsForURLCheck.allowlist", # https://crbug.com/1323628 - "crostini.AppEclipse", - "crostini.AppAndroidStudio", - "crostini.AppEmacs", "crostini.AppVscode", "crostini.AppGeditFilesharing",
diff --git a/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js b/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js index b21c1894..9150342 100644 --- a/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js +++ b/components/autofill/core/browser/autofill_and_password_manager_internals/autofill_and_password_manager_internals.js
@@ -204,6 +204,10 @@ if (scrollAfterInsert) { scrollDown(); // Focus marker div, set caret at end of line. + const logDiv = document.getElementById('log-entries'); + if (!logDiv) { + return; + } const markerNode = logDiv.lastChild; const textNode = markerNode.lastChild; markerNode.focus();
diff --git a/components/autofill_assistant/browser/actions/js_flow_action.cc b/components/autofill_assistant/browser/actions/js_flow_action.cc index e9b6c87..d51b5cfa 100644 --- a/components/autofill_assistant/browser/actions/js_flow_action.cc +++ b/components/autofill_assistant/browser/actions/js_flow_action.cc
@@ -26,9 +26,9 @@ JsFlowAction::JsFlowAction(ActionDelegate* delegate, const ActionProto& proto) : Action(delegate, proto), - js_flow_executor_( - std::make_unique<JsFlowExecutorImpl>(delegate->GetWebContents(), - this)) { + js_flow_executor_(std::make_unique<JsFlowExecutorImpl>( + delegate->GetWebContents()->GetBrowserContext(), + this)) { DCHECK(proto_.has_js_flow()); }
diff --git a/components/autofill_assistant/browser/autofill_assistant_impl.cc b/components/autofill_assistant/browser/autofill_assistant_impl.cc index ee7fa70..f4cd369 100644 --- a/components/autofill_assistant/browser/autofill_assistant_impl.cc +++ b/components/autofill_assistant/browser/autofill_assistant_impl.cc
@@ -80,15 +80,17 @@ ServerUrlFetcher(ServerUrlFetcher::GetDefaultServerUrl()); return std::make_unique<AutofillAssistantImpl>( - std::move(request_sender), std::move(dependencies), + browser_context, std::move(request_sender), std::move(dependencies), url_fetcher.GetCapabilitiesByHashEndpoint()); } AutofillAssistantImpl::AutofillAssistantImpl( + content::BrowserContext* browser_context, std::unique_ptr<ServiceRequestSender> request_sender, std::unique_ptr<CommonDependencies> dependencies, const GURL& script_server_url) - : request_sender_(std::move(request_sender)), + : browser_context_(browser_context), + request_sender_(std::move(request_sender)), script_server_url_(script_server_url), dependencies_(std::move(dependencies)) {} @@ -99,6 +101,12 @@ const std::vector<uint64_t>& hash_prefixes, const std::string& intent, GetCapabilitiesResponseCallback callback) { + // Always return an empty response for supervised users. + if (dependencies_->IsSupervisedUser(browser_context_)) { + std::move(callback).Run(net::HTTP_OK, {}); + return; + } + const ScriptParameters& parameters = { base::flat_map<std::string, std::string>{ {kIntentScriptParameterKey, intent}}};
diff --git a/components/autofill_assistant/browser/autofill_assistant_impl.h b/components/autofill_assistant/browser/autofill_assistant_impl.h index 3f71057..f1d1bb9 100644 --- a/components/autofill_assistant/browser/autofill_assistant_impl.h +++ b/components/autofill_assistant/browser/autofill_assistant_impl.h
@@ -8,11 +8,14 @@ #include <memory> #include <vector> +#include "base/memory/raw_ptr.h" #include "components/autofill_assistant/browser/public/autofill_assistant.h" #include "components/autofill_assistant/browser/public/external_script_controller.h" #include "components/autofill_assistant/browser/service/service_request_sender.h" -#include "components/version_info/version_info.h" -#include "content/public/browser/browser_context.h" + +namespace content { +class BrowserContext; +} // namespace content namespace autofill_assistant { @@ -24,7 +27,8 @@ content::BrowserContext* browser_context, std::unique_ptr<CommonDependencies> dependencies); - AutofillAssistantImpl(std::unique_ptr<ServiceRequestSender> request_sender, + AutofillAssistantImpl(content::BrowserContext* browser_context, + std::unique_ptr<ServiceRequestSender> request_sender, std::unique_ptr<CommonDependencies> dependencies, const GURL& script_server_url); ~AutofillAssistantImpl() override; @@ -43,6 +47,10 @@ ExternalActionDelegate* action_extension_delegate) override; private: + // The `BrowserContext` for which this `AutofillAssistantImpl` was created + // and which must outlive it. + const raw_ptr<content::BrowserContext> browser_context_; + // The request sender responsible for communicating with a remote endpoint. std::unique_ptr<ServiceRequestSender> request_sender_;
diff --git a/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc b/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc index 477cf87..9e6e5ef7 100644 --- a/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc +++ b/components/autofill_assistant/browser/autofill_assistant_impl_unittest.cc
@@ -37,10 +37,14 @@ mock_dependencies_ = mock_common_dependencies.get(); ON_CALL(*mock_dependencies_, GetCountryCode).WillByDefault(Return("US")); ON_CALL(*mock_dependencies_, GetLocale).WillByDefault(Return("en-US")); + ON_CALL(*mock_dependencies_, IsSupervisedUser).WillByDefault(Return(false)); + // As long as the `BrowserContext` is only passed as an argument during + // `CommonDependencies` calls, we do not need to set up a test environment + // for it. service_ = std::make_unique<AutofillAssistantImpl>( - std::move(mock_request_sender), std::move(mock_common_dependencies), - GURL(kScriptServerUrl)); + /* browser_context= */ nullptr, std::move(mock_request_sender), + std::move(mock_common_dependencies), GURL(kScriptServerUrl)); } ~AutofillAssistantImpTest() override = default; @@ -140,4 +144,18 @@ mock_response_callback_.Get()); } +TEST_F(AutofillAssistantImpTest, + GetCapabilitiesByHashPrefixDoesNotExecuteForSupervisedUsers) { + EXPECT_CALL(*mock_dependencies_, IsSupervisedUser).WillOnce(Return(true)); + + EXPECT_CALL(*mock_request_sender_, OnSendRequest).Times(0); + + EXPECT_CALL( + mock_response_callback_, + Run(net::HTTP_OK, std::vector<AutofillAssistant::CapabilitiesInfo>())); + + service_->GetCapabilitiesByHashPrefix(16, {1339}, "DUMMY_INTENT", + mock_response_callback_.Get()); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc index fb78baa..554e106 100644 --- a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc +++ b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.cc
@@ -178,4 +178,12 @@ std::move(end_action_callback).Run(result); } +void FakeScriptExecutorUiDelegate::OnInterruptStarted() { + interrupt_notification_history_.emplace_back(INTERRUPT_STARTED); +} + +void FakeScriptExecutorUiDelegate::OnInterruptFinished() { + interrupt_notification_history_.emplace_back(INTERRUPT_FINISHED); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h index 6b72f0b..66b0a2a 100644 --- a/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h +++ b/components/autofill_assistant/browser/fake_script_executor_ui_delegate.h
@@ -20,6 +20,8 @@ // unittests. class FakeScriptExecutorUiDelegate : public ScriptExecutorUiDelegate { public: + enum InterruptNotification { INTERRUPT_STARTED = 0, INTERRUPT_FINISHED = 1 }; + FakeScriptExecutorUiDelegate(); FakeScriptExecutorUiDelegate(const FakeScriptExecutorUiDelegate&) = delete; @@ -85,6 +87,8 @@ base::OnceCallback<void()> start_dom_checks_callback, base::OnceCallback<void(const external::Result& result)> end_action_callback) override; + void OnInterruptStarted() override; + void OnInterruptFinished() override; const std::vector<Details>& GetDetails() { return details_; } @@ -102,6 +106,10 @@ return collect_user_data_ui_loading__field_; } + std::vector<InterruptNotification> GetInterruptNotificationHistory() { + return interrupt_notification_history_; + } + private: std::string status_message_; std::string tts_message_; @@ -120,6 +128,7 @@ bool expand_or_collapse_value_ = false; bool expand_sheet_for_prompt_ = true; std::unique_ptr<GenericUserInterfaceProto> persistent_generic_ui_; + std::vector<InterruptNotification> interrupt_notification_history_; }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/headless/headless_ui_controller.cc b/components/autofill_assistant/browser/headless/headless_ui_controller.cc index 233f788..043d44b 100644 --- a/components/autofill_assistant/browser/headless/headless_ui_controller.cc +++ b/components/autofill_assistant/browser/headless/headless_ui_controller.cc
@@ -13,6 +13,7 @@ bool HeadlessUiController::SupportsExternalActions() { return action_extension_delegate_ != nullptr; } + void HeadlessUiController::ExecuteExternalAction( const external::Action& external_action, base::OnceCallback<void()> start_dom_checks_callback, @@ -25,6 +26,17 @@ std::move(end_action_callback)); } +void HeadlessUiController::OnInterruptStarted() { + if (action_extension_delegate_) { + action_extension_delegate_->OnInterruptStarted(); + } +} +void HeadlessUiController::OnInterruptFinished() { + if (action_extension_delegate_) { + action_extension_delegate_->OnInterruptFinished(); + } +} + // TODO(b/201964911): fail execution instead of just logging a warning if a // method is unexpectedly called.
diff --git a/components/autofill_assistant/browser/headless/headless_ui_controller.h b/components/autofill_assistant/browser/headless/headless_ui_controller.h index deab955..ed9c09a 100644 --- a/components/autofill_assistant/browser/headless/headless_ui_controller.h +++ b/components/autofill_assistant/browser/headless/headless_ui_controller.h
@@ -83,6 +83,8 @@ base::OnceCallback<void()> start_dom_checks_callback, base::OnceCallback<void(const external::Result& result)> end_action_callback) override; + void OnInterruptStarted() override; + void OnInterruptFinished() override; private: const raw_ptr<ExternalActionDelegate> action_extension_delegate_;
diff --git a/components/autofill_assistant/browser/js_flow_executor_impl.cc b/components/autofill_assistant/browser/js_flow_executor_impl.cc index c0cee1da..57bc9f6 100644 --- a/components/autofill_assistant/browser/js_flow_executor_impl.cc +++ b/components/autofill_assistant/browser/js_flow_executor_impl.cc
@@ -14,6 +14,9 @@ #include "components/autofill_assistant/browser/js_flow_util.h" #include "components/autofill_assistant/browser/parse_jspb.h" #include "components/autofill_assistant/browser/web/web_controller_util.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/navigation_controller.h" +#include "content/public/browser/web_contents.h" namespace autofill_assistant { namespace { @@ -115,14 +118,21 @@ } // namespace -JsFlowExecutorImpl::JsFlowExecutorImpl(content::WebContents* web_contents, +JsFlowExecutorImpl::JsFlowExecutorImpl(content::BrowserContext* browser_context, Delegate* delegate) : delegate_(delegate), + // To execute the JS flow we create a dummy WebContents. + dummy_web_contents_(content::WebContents::Create( + content::WebContents::CreateParams(browser_context))), devtools_client_(std::make_unique<DevtoolsClient>( - content::DevToolsAgentHost::GetOrCreateFor(web_contents), + content::DevToolsAgentHost::GetOrCreateFor(dummy_web_contents_.get()), base::FeatureList::IsEnabled( autofill_assistant::features:: - kAutofillAssistantFullJsFlowStackTraces))) {} + kAutofillAssistantFullJsFlowStackTraces))) { + // Navigate to a blank page to connect to a frame tree. + dummy_web_contents_->GetController().LoadURLWithParams( + content::NavigationController::LoadURLParams(GURL("about:blank"))); +} JsFlowExecutorImpl::~JsFlowExecutorImpl() = default; @@ -387,6 +397,8 @@ if (!status.ok() && result_value) { VLOG(1) << "Flow failed with " << status << " and result: " << *result_value; + } else if (!status.ok()) { + VLOG(1) << "Flow failed with " << status; } std::move(callback_).Run(status, std::move(result_value));
diff --git a/components/autofill_assistant/browser/js_flow_executor_impl.h b/components/autofill_assistant/browser/js_flow_executor_impl.h index 4bbd6213..c81b556 100644 --- a/components/autofill_assistant/browser/js_flow_executor_impl.h +++ b/components/autofill_assistant/browser/js_flow_executor_impl.h
@@ -21,7 +21,8 @@ class JsFlowExecutorImpl : public JsFlowExecutor { public: // |delegate| must outlive the JsFlowExecutorImpl. - JsFlowExecutorImpl(content::WebContents* web_contents, Delegate* delegate); + JsFlowExecutorImpl(content::BrowserContext* browser_context, + Delegate* delegate); ~JsFlowExecutorImpl() override; JsFlowExecutorImpl(const JsFlowExecutorImpl&) = delete; JsFlowExecutorImpl& operator=(const JsFlowExecutorImpl&) = delete; @@ -119,6 +120,7 @@ } Delegate* const delegate_; + std::unique_ptr<content::WebContents> dummy_web_contents_; std::unique_ptr<DevtoolsClient> devtools_client_; int isolated_world_context_id_ = -1;
diff --git a/components/autofill_assistant/browser/js_flow_executor_impl_browsertest.cc b/components/autofill_assistant/browser/js_flow_executor_impl_browsertest.cc index 7f97d15e..68aaf6c 100644 --- a/components/autofill_assistant/browser/js_flow_executor_impl_browsertest.cc +++ b/components/autofill_assistant/browser/js_flow_executor_impl_browsertest.cc
@@ -34,6 +34,7 @@ #include "components/autofill_assistant/browser/trigger_context.h" #include "components/autofill_assistant/browser/web/mock_web_controller.h" #include "content/public/test/browser_test.h" +#include "content/public/test/test_browser_context.h" #include "content/shell/browser/shell.h" #include "net/http/http_status_code.h" #include "testing/gmock/include/gmock/gmock.h" @@ -75,12 +76,7 @@ class JsFlowExecutorImplTest : public BaseBrowserTest { public: - void SetUpOnMainThread() override { - BaseBrowserTest::SetUpOnMainThread(); - - flow_executor_ = std::make_unique<JsFlowExecutorImpl>( - shell()->web_contents(), &mock_delegate_); - } + void SetUpOnMainThread() override { BaseBrowserTest::SetUpOnMainThread(); } // Overload, ignore result value, just return the client status. ClientStatus RunTest(const std::string& js_flow) { @@ -92,7 +88,13 @@ std::unique_ptr<base::Value>& result_value) { ClientStatus status; base::RunLoop run_loop; - flow_executor_->Start( + + // Needs to be created inside the RunLoop since we are creating a dummy + // WebContents and navigating to a new url. + JsFlowExecutorImpl flow_executor = JsFlowExecutorImpl( + shell()->web_contents()->GetBrowserContext(), &mock_delegate_); + + flow_executor.Start( js_flow, base::BindOnce(&JsFlowExecutorImplTest::OnFlowFinished, base::Unretained(this), run_loop.QuitClosure(), &status, std::ref(result_value))); @@ -112,7 +114,6 @@ protected: NiceMock<MockJsFlowExecutorImplDelegate> mock_delegate_; - std::unique_ptr<JsFlowExecutorImpl> flow_executor_; }; IN_PROC_BROWSER_TEST_F(JsFlowExecutorImplTest, SmokeTest) { @@ -387,37 +388,6 @@ EXPECT_EQ(status.proto_status(), INVALID_ACTION); } -IN_PROC_BROWSER_TEST_F(JsFlowExecutorImplTest, StartWhileAlreadyRunningFails) { - EXPECT_CALL(mock_delegate_, RunNativeAction) - .WillOnce(WithArg<2>([&](auto callback) { - // Starting a second flow while the first one is running should fail. - EXPECT_EQ(RunTest(std::string()).proto_status(), INVALID_ACTION); - - // The first flow should be able to finish successfully. - std::move(callback).Run(ClientStatus(ACTION_APPLIED), nullptr); - })); - - std::unique_ptr<base::Value> result; - ClientStatus status = RunTest( - R"( - let [status, result] = await runNativeAction(1, "dGVzdA==" /*test*/); - return status; - )", - result); - EXPECT_EQ(status.proto_status(), ACTION_APPLIED); - EXPECT_EQ(*result, base::Value(2)); -} - -IN_PROC_BROWSER_TEST_F(JsFlowExecutorImplTest, - EnvironmentIsPreservedBetweenRuns) { - EXPECT_EQ(RunTest("globalFlowState.i = 5;").proto_status(), ACTION_APPLIED); - - std::unique_ptr<base::Value> result; - EXPECT_EQ(RunTest("return globalFlowState.i;", result).proto_status(), - ACTION_APPLIED); - EXPECT_EQ(*result, base::Value(5)); -} - class JsFlowExecutorImplScriptExecutorTest : public BaseBrowserTest { public: void SetUpOnMainThread() override {
diff --git a/components/autofill_assistant/browser/public/external_action_delegate.h b/components/autofill_assistant/browser/public/external_action_delegate.h index 9a1af5e7..4a5008dc 100644 --- a/components/autofill_assistant/browser/public/external_action_delegate.h +++ b/components/autofill_assistant/browser/public/external_action_delegate.h
@@ -24,6 +24,13 @@ base::OnceCallback<void()> start_dom_checks_callback, base::OnceCallback<void(const external::Result& result)> end_action_callback) = 0; + + // Called before starting the execution of an interrupt. + virtual void OnInterruptStarted() = 0; + + // Called after finishing to execute an interrupt, before resuming the + // execution of the main script + virtual void OnInterruptFinished() = 0; }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/script_executor_ui_delegate.h b/components/autofill_assistant/browser/script_executor_ui_delegate.h index cf52d1e..ea5cbc4 100644 --- a/components/autofill_assistant/browser/script_executor_ui_delegate.h +++ b/components/autofill_assistant/browser/script_executor_ui_delegate.h
@@ -19,13 +19,14 @@ #include "components/autofill_assistant/browser/tts_button_state.h" #include "components/autofill_assistant/browser/user_action.h" #include "components/autofill_assistant/browser/user_data.h" +#include "components/autofill_assistant/browser/wait_for_dom_observer.h" #include "url/gurl.h" namespace autofill_assistant { // A delegate which provides the ScriptExecutor with methods to control the // Autofill Assistant UI. -class ScriptExecutorUiDelegate { +class ScriptExecutorUiDelegate : public WaitForDomObserver { public: virtual void SetStatusMessage(const std::string& message) = 0; virtual std::string GetStatusMessage() const = 0;
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc index ce28fb3..6b98fd8 100644 --- a/components/autofill_assistant/browser/script_executor_unittest.cc +++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -1335,6 +1335,8 @@ EXPECT_CALL(executor_callback_, Run(Field(&ScriptExecutor::Result::success, false))); executor_->Run(&user_data_, executor_callback_.Get()); + EXPECT_THAT(ui_delegate_.GetInterruptNotificationHistory(), + ElementsAre(FakeScriptExecutorUiDelegate::INTERRUPT_STARTED)); } TEST_F(ScriptExecutorTest, InterruptReturnsShutdown) { @@ -1364,6 +1366,8 @@ Field(&ScriptExecutor::Result::at_end, ScriptExecutor::SHUTDOWN)))); executor_->Run(&user_data_, executor_callback_.Get()); + EXPECT_THAT(ui_delegate_.GetInterruptNotificationHistory(), + ElementsAre(FakeScriptExecutorUiDelegate::INTERRUPT_STARTED)); } TEST_F(ScriptExecutorTest, RunInterruptDuringPrompt) { @@ -1456,6 +1460,9 @@ ElementAreaProto::default_instance(), interruptible_area, ElementAreaProto::default_instance())); EXPECT_EQ("done", ui_delegate_.GetStatusMessage()); + EXPECT_THAT(ui_delegate_.GetInterruptNotificationHistory(), + ElementsAre(FakeScriptExecutorUiDelegate::INTERRUPT_STARTED, + FakeScriptExecutorUiDelegate::INTERRUPT_FINISHED)); } TEST_F(ScriptExecutorTest, RunPromptInBrowseMode) { @@ -1550,6 +1557,11 @@ AutofillAssistantState::PROMPT, AutofillAssistantState::RUNNING, AutofillAssistantState::PROMPT, AutofillAssistantState::RUNNING, AutofillAssistantState::PROMPT, AutofillAssistantState::RUNNING)); + EXPECT_THAT(ui_delegate_.GetInterruptNotificationHistory(), + ElementsAre(FakeScriptExecutorUiDelegate::INTERRUPT_STARTED, + FakeScriptExecutorUiDelegate::INTERRUPT_FINISHED, + FakeScriptExecutorUiDelegate::INTERRUPT_STARTED, + FakeScriptExecutorUiDelegate::INTERRUPT_FINISHED)); } TEST_F(ScriptExecutorTest, UpdateScriptListGetNext) {
diff --git a/components/autofill_assistant/browser/ui_controller.cc b/components/autofill_assistant/browser/ui_controller.cc index 1f829d0..3aab78c 100644 --- a/components/autofill_assistant/browser/ui_controller.cc +++ b/components/autofill_assistant/browser/ui_controller.cc
@@ -1186,4 +1186,7 @@ NOTREACHED() << "Flows using default UI don't support external actions."; } +void UiController::OnInterruptStarted() {} +void UiController::OnInterruptFinished() {} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/ui_controller.h b/components/autofill_assistant/browser/ui_controller.h index c1adeb8..c9c8149 100644 --- a/components/autofill_assistant/browser/ui_controller.h +++ b/components/autofill_assistant/browser/ui_controller.h
@@ -113,6 +113,8 @@ collect_user_data_options) override; const CollectUserDataOptions* GetLastSuccessfulUserDataOptions() const override; + void OnInterruptStarted() override; + void OnInterruptFinished() override; // Overrides autofill_assistant::UiDelegate: std::vector<Details> GetDetails() const override;
diff --git a/components/autofill_assistant/browser/wait_for_dom_operation.cc b/components/autofill_assistant/browser/wait_for_dom_operation.cc index c4f6434..59a10e2b 100644 --- a/components/autofill_assistant/browser/wait_for_dom_operation.cc +++ b/components/autofill_assistant/browser/wait_for_dom_operation.cc
@@ -30,11 +30,15 @@ ->GetScriptParameters() .GetEnableObserverWaitForDom() .value_or(false)), - observer_(observer), check_elements_(std::move(check_elements)), callback_(std::move(callback)), timeout_warning_delay_(delegate_->GetSettings().warning_delay), - retry_timer_(delegate_->GetSettings().periodic_element_check_interval) {} + retry_timer_(delegate_->GetSettings().periodic_element_check_interval) { + if (observer) { + observers_.emplace_back(observer); + } + observers_.emplace_back(ui_delegate_); +} WaitForDomOperation::~WaitForDomOperation() { delegate_->RemoveNavigationListener(this); @@ -220,8 +224,9 @@ void WaitForDomOperation::RunInterrupt(const std::string& path) { batch_element_checker_.reset(); - if (observer_) - observer_->OnInterruptStarted(); + for (auto* observer : observers_) { + observer->OnInterruptStarted(); + } SavePreInterruptState(); ran_interrupts_.insert(path); @@ -248,8 +253,9 @@ RunCallbackWithResult(ClientStatus(INTERRUPT_FAILED), &result); return; } - if (observer_) - observer_->OnInterruptFinished(); + for (auto* observer : observers_) { + observer->OnInterruptFinished(); + } RestorePreInterruptState(); RestorePreInterruptScroll();
diff --git a/components/autofill_assistant/browser/wait_for_dom_operation.h b/components/autofill_assistant/browser/wait_for_dom_operation.h index d2e7ff3..c33d844 100644 --- a/components/autofill_assistant/browser/wait_for_dom_operation.h +++ b/components/autofill_assistant/browser/wait_for_dom_operation.h
@@ -121,7 +121,7 @@ const base::TimeDelta max_wait_time_; const bool allow_interrupt_; const bool use_observers_; - raw_ptr<WaitForDomObserver> observer_; + std::vector<WaitForDomObserver*> observers_; base::RepeatingCallback<void(BatchElementChecker*, base::OnceCallback<void(const ClientStatus&)>)> check_elements_;
diff --git a/components/history/core/browser/BUILD.gn b/components/history/core/browser/BUILD.gn index 0b39a710..44df8d93 100644 --- a/components/history/core/browser/BUILD.gn +++ b/components/history/core/browser/BUILD.gn
@@ -192,6 +192,7 @@ "//components/test/data/history/history.52.sql", "//components/test/data/history/history.53.sql", "//components/test/data/history/history.54.sql", + "//components/test/data/history/history.55.sql", "//components/test/data/history/thumbnail_wild/Favicons.corrupt_meta.disable", "//components/test/data/history/thumbnail_wild/Favicons.v2.init.sql", "//components/test/data/history/thumbnail_wild/Favicons.v3.init.sql",
diff --git a/components/history/core/browser/history_backend_db_unittest.cc b/components/history/core/browser/history_backend_db_unittest.cc index 58d0f43..478d2789 100644 --- a/components/history/core/browser/history_backend_db_unittest.cc +++ b/components/history/core/browser/history_backend_db_unittest.cc
@@ -2634,6 +2634,41 @@ } } +TEST_F(HistoryBackendDBTest, + MigrateVisitsAutoincrementIdAndAddOriginatorColumns) { + ASSERT_NO_FATAL_FAILURE(CreateDBVersion(54)); + + constexpr VisitID visit_id1 = 1; + + // Open the db for manual manipulation. + sql::Database db; + ASSERT_TRUE(db.Open(history_dir_.Append(kHistoryFilename))); + + const char kInsertVisitStatement[] = + "INSERT INTO visits " + "(id, url, visit_time) VALUES (?, ?, ?)"; + + // Add a row to `visits` table. + { + sql::Statement s(db.GetUniqueStatement(kInsertVisitStatement)); + s.BindInt64(0, 1); + s.BindInt64(1, 1); + s.BindTime(2, base::Time::Now()); + ASSERT_TRUE(s.Run()); + } + + // Re-open the db, triggering migration. + CreateBackendAndDatabase(); + + // After the migration, the originator columns should return default values. + { + VisitRow visit; + db_->GetRowForVisit(visit_id1, &visit); + EXPECT_EQ(visit.originator_cache_guid, ""); + EXPECT_EQ(visit.originator_visit_id, 0); + } +} + bool FilterURL(const GURL& url) { return url.SchemeIsHTTPOrHTTPS(); }
diff --git a/components/history/core/browser/history_database.cc b/components/history/core/browser/history_database.cc index e950e15..4f6e728 100644 --- a/components/history/core/browser/history_database.cc +++ b/components/history/core/browser/history_database.cc
@@ -38,7 +38,7 @@ // Current version number. We write databases at the "current" version number, // but any previous version that can read the "compatible" one can make do with // our database without *too* many bad effects. -const int kCurrentVersionNumber = 54; +const int kCurrentVersionNumber = 55; const int kCompatibleVersionNumber = 16; const char kEarlyExpirationThresholdKey[] = "early_expiration_threshold"; @@ -690,6 +690,13 @@ meta_table_.SetVersionNumber(cur_version); } + if (cur_version == 54) { + if (!MigrateVisitsAutoincrementIdAndAddOriginatorColumns()) + return LogMigrationFailure(54); + cur_version++; + meta_table_.SetVersionNumber(cur_version); + } + // ========================= ^^ new migration code goes here ^^ // ADDING NEW MIGRATION CODE // =========================
diff --git a/components/history/core/browser/history_types.cc b/components/history/core/browser/history_types.cc index 286fe53..7ca62a8 100644 --- a/components/history/core/browser/history_types.cc +++ b/components/history/core/browser/history_types.cc
@@ -33,6 +33,8 @@ VisitRow::~VisitRow() = default; +VisitRow::VisitRow(const VisitRow&) = default; + // QueryResults ---------------------------------------------------------------- QueryResults::QueryResults() = default;
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index 3e0b0a1..94ee0b4f 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -70,6 +70,7 @@ bool arg_incremented_omnibox_typed_score, VisitID arg_opener_visit); ~VisitRow(); + VisitRow(const VisitRow&); // Compares two visits based on dates, for sorting. bool operator<(const VisitRow& other) const { @@ -116,6 +117,12 @@ // same tab. VisitID opener_visit = 0; + // These are set only for synced visits originating from a different machine. + // `originator_cache_guid` is the originator machine's unique client ID. It's + // called a "cache" just to match Chrome Sync's terminology. + std::string originator_cache_guid; + VisitID originator_visit_id = 0; + // We allow the implicit copy constructor and operator=. };
diff --git a/components/history/core/browser/url_database.h b/components/history/core/browser/url_database.h index e4e5c86..e40ab3e 100644 --- a/components/history/core/browser/url_database.h +++ b/components/history/core/browser/url_database.h
@@ -312,7 +312,7 @@ // be used in between CreateTemporaryURLTable() and CommitTemporaryURLTable(). URLID AddURLInternal(const URLRow& info, bool is_temporary); - // Return ture if the urls table's schema contains "AUTOINCREMENT". + // Return true if the urls table's schema contains "AUTOINCREMENT". // false if table do not contain AUTOINCREMENT, or the table is not created. bool URLTableContainsAutoincrement();
diff --git a/components/history/core/browser/visit_database.cc b/components/history/core/browser/visit_database.cc index fb84c67..5d90a1fc 100644 --- a/components/history/core/browser/visit_database.cc +++ b/components/history/core/browser/visit_database.cc
@@ -111,7 +111,13 @@ // for each row. if (!GetDB().Execute( "CREATE TABLE visits(" - "id INTEGER PRIMARY KEY," + // The `id` uses AUTOINCREMENT to support Sync. Chrome Sync uses the + // `id` in conjunction with the Client ID as a unique identifier. + // If this was not AUTOINCREMENT, deleting a row and creating a new + // one could reuse the same `id` for an entirely new visit, which + // would confuse Sync, as Sync would be unable to distinguish + // an update from a deletion plus a creation. + "id INTEGER PRIMARY KEY AUTOINCREMENT," "url INTEGER NOT NULL," // key of the URL this corresponds to "visit_time INTEGER NOT NULL," "from_visit INTEGER," @@ -121,7 +127,16 @@ // longer used and should NOT be read or written from any longer. "visit_duration INTEGER DEFAULT 0 NOT NULL," "incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL," - "opener_visit INTEGER)")) + "opener_visit INTEGER," + // These two fields are non-null only for remote visits synced to + // the local machine. The `originator_cache_guid` is the unique + // identifier for the originator machine the visit was originally + // made on, and `originator_visit_id` is the `id` of the visit row + // as originally assigned by AUTOINCREMENT on the originator. + // The tuple of (`originator_cache_guid`, `origin_visit_id`) is + // globally unique. + "originator_cache_guid TEXT," + "originator_visit_id INTEGER)")) return false; } @@ -175,6 +190,8 @@ base::TimeDelta::FromInternalValue(statement.ColumnInt64(6)); visit->incremented_omnibox_typed_score = statement.ColumnBool(7); visit->opener_visit = statement.ColumnInt64(8); + visit->originator_cache_guid = statement.ColumnString(9); + visit->originator_visit_id = statement.ColumnInt64(10); } // static @@ -234,8 +251,9 @@ SQL_FROM_HERE, "INSERT INTO visits " "(url, visit_time, from_visit, transition, segment_id, " - "visit_duration, incremented_omnibox_typed_score, opener_visit) " - "VALUES (?,?,?,?,?,?,?,?)")); + "visit_duration, incremented_omnibox_typed_score, opener_visit," + "originator_cache_guid,originator_visit_id) " + "VALUES (?,?,?,?,?,?,?,?,?,?)")); statement.BindInt64(0, visit->url_id); statement.BindInt64(1, visit->visit_time.ToInternalValue()); statement.BindInt64(2, visit->referring_visit); @@ -244,6 +262,8 @@ statement.BindInt64(5, visit->visit_duration.ToInternalValue()); statement.BindBool(6, visit->incremented_omnibox_typed_score); statement.BindInt64(7, visit->opener_visit); + statement.BindString(8, visit->originator_cache_guid); + statement.BindInt64(9, visit->originator_visit_id); if (!statement.Run()) { DVLOG(0) << "Failed to execute visit insert statement: " @@ -325,7 +345,8 @@ SQL_FROM_HERE, "UPDATE visits SET " "url=?,visit_time=?,from_visit=?,transition=?,segment_id=?," - "visit_duration=?,incremented_omnibox_typed_score=?,opener_visit=? " + "visit_duration=?,incremented_omnibox_typed_score=?,opener_visit=?," + "originator_cache_guid=?,originator_visit_id=? " "WHERE id=?")); statement.BindInt64(0, visit.url_id); statement.BindInt64(1, visit.visit_time.ToInternalValue()); @@ -335,7 +356,9 @@ statement.BindInt64(5, visit.visit_duration.ToInternalValue()); statement.BindBool(6, visit.incremented_omnibox_typed_score); statement.BindInt64(7, visit.opener_visit); - statement.BindInt64(8, visit.visit_id); + statement.BindString(8, visit.originator_cache_guid); + statement.BindInt64(9, visit.originator_visit_id); + statement.BindInt64(10, visit.visit_id); return statement.Run(); } @@ -1061,6 +1084,67 @@ transaction.Commit(); } +bool VisitDatabase::MigrateVisitsAutoincrementIdAndAddOriginatorColumns() { + if (!GetDB().DoesTableExist("visits")) { + NOTREACHED() << " Visits table should exist before migration"; + return false; + } + + if (GetDB().DoesColumnExist("visits", "originator_cache_guid") && + GetDB().DoesColumnExist("visits", "originator_visit_id") && + VisitTableContainsAutoincrement()) { + return true; + } + + sql::Transaction transaction(&GetDB()); + return transaction.Begin() && + GetDB().Execute( + "CREATE TABLE visits_tmp(" + "id INTEGER PRIMARY KEY AUTOINCREMENT," + "url INTEGER NOT NULL," // key of the URL this corresponds to + "visit_time INTEGER NOT NULL," + "from_visit INTEGER," + "transition INTEGER DEFAULT 0 NOT NULL," + "segment_id INTEGER," + "visit_duration INTEGER DEFAULT 0 NOT NULL," + "incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL," + "opener_visit INTEGER)") && + GetDB().Execute( + "INSERT INTO visits_tmp SELECT " + "id, url, visit_time, from_visit, transition, segment_id, " + "visit_duration, incremented_omnibox_typed_score, opener_visit " + "FROM visits") && + GetDB().Execute( + "ALTER TABLE visits_tmp ADD COLUMN originator_cache_guid TEXT") && + GetDB().Execute( + "ALTER TABLE visits_tmp ADD COLUMN originator_visit_id INTEGER") && + GetDB().Execute("DROP TABLE visits") && + GetDB().Execute("ALTER TABLE visits_tmp RENAME TO visits") && + transaction.Commit(); +} + +bool VisitDatabase::VisitTableContainsAutoincrement() { + // sqlite_schema has columns: + // type - "index" or "table". + // name - name of created element. + // tbl_name - name of element, or target table in case of index. + // rootpage - root page of the element in database file. + // sql - SQL to create the element. + sql::Statement statement( + GetDB().GetUniqueStatement("SELECT sql FROM sqlite_schema WHERE type = " + "'table' AND name = 'visits'")); + + // visits table does not exist. + if (!statement.Step()) + return false; + + std::string urls_schema = statement.ColumnString(0); + // We check if the whole schema contains "AUTOINCREMENT", since + // "AUTOINCREMENT" only can be used for "INTEGER PRIMARY KEY", so we assume no + // other columns could contain "AUTOINCREMENT". + return urls_schema.find("AUTOINCREMENT") != std::string::npos; +} + bool VisitDatabase::GetAllVisitedURLRowidsForMigrationToVersion40( std::vector<URLID>* visited_url_rowids_sorted) { DCHECK(visited_url_rowids_sorted);
diff --git a/components/history/core/browser/visit_database.h b/components/history/core/browser/visit_database.h index 5ade58b..5db4fba 100644 --- a/components/history/core/browser/visit_database.h +++ b/components/history/core/browser/visit_database.h
@@ -277,6 +277,16 @@ // column which is no longer used. bool MigrateVisitsWithoutOpenerVisitColumnAndDropPubliclyRoutableColumn(); + // Called by the derived classes to migrate the older visits table which + // which aren't ready to accommodate Sync. It sets `id` to AUTOINCREMENT, and + // ensures the existence of the `originator_cache_guid` and + // `originator_visit_id` columns. + bool MigrateVisitsAutoincrementIdAndAddOriginatorColumns(); + + // Return true if the visits table's schema contains "AUTOINCREMENT". + // false if table do not contain AUTOINCREMENT, or the table is not created. + bool VisitTableContainsAutoincrement(); + // A subprocedure in the process of migration to version 40. bool GetAllVisitedURLRowidsForMigrationToVersion40( std::vector<URLID>* visited_url_rowids_sorted); @@ -285,7 +295,8 @@ // Columns, in order, of the visit table. #define HISTORY_VISIT_ROW_FIELDS \ " id,url,visit_time,from_visit,transition,segment_id,visit_duration," \ - "incremented_omnibox_typed_score,opener_visit " + "incremented_omnibox_typed_score,opener_visit,originator_cache_guid," \ + "originator_visit_id " } // namespace history
diff --git a/components/history/core/browser/visit_database_unittest.cc b/components/history/core/browser/visit_database_unittest.cc index fcf7ead..4ed63a1 100644 --- a/components/history/core/browser/visit_database_unittest.cc +++ b/components/history/core/browser/visit_database_unittest.cc
@@ -32,7 +32,9 @@ a.visit_time == b.visit_time && a.referring_visit == b.referring_visit && ui::PageTransitionTypeIncludingQualifiersIs(a.transition, - b.transition); + b.transition) && + a.originator_cache_guid == b.originator_cache_guid && + a.originator_visit_id == b.originator_visit_id; } } // namespace @@ -76,6 +78,9 @@ VisitRow visit_info2(visit_info1.url_id, visit_info1.visit_time + base::Seconds(1), 1, ui::PAGE_TRANSITION_TYPED, 0, true, 0); + // Verify we can fetch originator data too. + visit_info2.originator_cache_guid = "foobar_client"; + visit_info2.originator_visit_id = 42; EXPECT_TRUE(AddVisit(&visit_info2, SOURCE_BROWSED)); // Add third visit for a different page. @@ -145,6 +150,8 @@ modification.transition = ui::PAGE_TRANSITION_TYPED; modification.visit_time = Time::Now() + base::Days(1); modification.referring_visit = 9292; + modification.originator_cache_guid = "foobar_client"; + modification.originator_visit_id = 42; UpdateVisitRow(modification); // Check that the mutated version was written.
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index b9e0e998..55d8443 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -707,6 +707,7 @@ "password_manager_client_helper_unittest.cc", "password_manager_features_util_unittest.cc", "password_manager_metrics_recorder_unittest.cc", + "password_manager_metrics_util_unittest.cc", "password_manager_unittest.cc", "password_manager_util_unittest.cc", "password_notes_table_unittest.cc",
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.cc b/components/password_manager/core/browser/password_manager_metrics_util.cc index 833fdd5..8dd4c26 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.cc +++ b/components/password_manager/core/browser/password_manager_metrics_util.cc
@@ -5,14 +5,19 @@ #include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "base/metrics/histogram_functions.h" +#include "base/rand_util.h" #include "base/strings/strcat.h" #include "components/autofill/core/common/password_generation_util.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_source_id.h" using autofill::password_generation::PasswordGenerationType; -namespace password_manager { +namespace ukm::builders { +class PasswordManager_LeakWarningDialog; +} // namespace ukm::builders -namespace metrics_util { +namespace password_manager::metrics_util { std::string GetPasswordAccountStorageUserStateHistogramSuffix( PasswordAccountStorageUserState user_state) { @@ -51,6 +56,43 @@ return std::string(); } +LeakDialogMetricsRecorder::LeakDialogMetricsRecorder(ukm::SourceId source_id, + LeakDialogType type) + : source_id_(source_id), type_(type) {} + +void LeakDialogMetricsRecorder::LogLeakDialogTypeAndDismissalReason( + LeakDialogDismissalReason reason) { + // Always record UMA. + base::UmaHistogramEnumeration(kHistogram, reason); + base::UmaHistogramEnumeration(base::StrCat({kHistogram, ".", GetUMASuffix()}), + reason); + + // For UKM, sample the recorded events. + if (base::RandDouble() > ukm_sampling_rate_) + return; + + // The entire event is made up of these two fields, so we can build and + // record it in one step. + ukm ::builders::PasswordManager_LeakWarningDialog ukm_builder(source_id_); + ukm_builder.SetPasswordLeakDetectionDialogType(static_cast<int64_t>(type_)); + ukm_builder.SetPasswordLeakDetectionDialogDismissalReason( + static_cast<int64_t>(reason)); + ukm_builder.Record(ukm::UkmRecorder::Get()); +} + +const char* LeakDialogMetricsRecorder::GetUMASuffix() const { + switch (type_) { + case LeakDialogType::kCheckup: + return "Checkup"; + case LeakDialogType::kChange: + return "Change"; + case LeakDialogType::kCheckupAndChange: + return "CheckupAndChange"; + case LeakDialogType::kChangeAutomatically: + return "ChangeAutomatically"; + } +} + void LogGeneralUIDismissalReason(UIDismissalReason reason) { base::UmaHistogramEnumeration("PasswordManager.UIDismissalReason", reason, NUM_UI_RESPONSES); @@ -111,28 +153,6 @@ NUM_UI_RESPONSES); } -void LogLeakDialogTypeAndDismissalReason(LeakDialogType type, - LeakDialogDismissalReason reason) { - static constexpr char kHistogram[] = - "PasswordManager.LeakDetection.DialogDismissalReason"; - auto GetSuffix = [type] { - switch (type) { - case LeakDialogType::kCheckup: - return "Checkup"; - case LeakDialogType::kChange: - return "Change"; - case LeakDialogType::kCheckupAndChange: - return "CheckupAndChange"; - case LeakDialogType::kChangeAutomatically: - return "ChangeAutomatically"; - } - }; - - base::UmaHistogramEnumeration(kHistogram, reason); - base::UmaHistogramEnumeration(base::StrCat({kHistogram, ".", GetSuffix()}), - reason); -} - void LogUIDisplayDisposition(UIDisplayDisposition disposition) { base::UmaHistogramEnumeration("PasswordBubble.DisplayDisposition", disposition, NUM_DISPLAY_DISPOSITIONS); @@ -376,6 +396,4 @@ add_credential_from_settings_user_interaction); } -} // namespace metrics_util - -} // namespace password_manager +} // namespace password_manager::metrics_util
diff --git a/components/password_manager/core/browser/password_manager_metrics_util.h b/components/password_manager/core/browser/password_manager_metrics_util.h index a798a87..90c8de752 100644 --- a/components/password_manager/core/browser/password_manager_metrics_util.h +++ b/components/password_manager/core/browser/password_manager_metrics_util.h
@@ -12,6 +12,7 @@ #include "components/autofill/core/common/mojom/autofill_types.mojom.h" #include "components/autofill/core/common/password_generation_util.h" #include "components/password_manager/core/common/credential_manager_types.h" +#include "services/metrics/public/cpp/ukm_source_id.h" namespace password_manager { @@ -65,7 +66,8 @@ }; // Enum representing the different leak detection dialogs shown to the user. -// Corresponds to LeakDetectionDialogType suffix in histogram_suffixes_list.xml. +// Corresponds to LeakDetectionDialogType suffix in histogram_suffixes_list.xml +// and PasswordLeakDetectionDialogType in enums.xml. // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. enum class LeakDialogType { @@ -547,6 +549,44 @@ std::string GetPasswordAccountStorageUsageLevelHistogramSuffix( PasswordAccountStorageUsageLevel usage_level); +// Records the `type` of a leak dialog shown to the user and the `reason` +// why it was dismissed. +class LeakDialogMetricsRecorder { + public: + // Create a LeakDialogMetricsRecorder corresponding to a navigation with + // `source_id`. + LeakDialogMetricsRecorder(ukm::SourceId source_id, LeakDialogType type); + LeakDialogMetricsRecorder(const LeakDialogMetricsRecorder&) = delete; + LeakDialogMetricsRecorder& operator=(const LeakDialogMetricsRecorder&) = + delete; + + // Log the `reason` for dismissing the leak warning dialog, e.g. signaling + // that the user ignored it or that they asked for an automatic password + // change. + void LogLeakDialogTypeAndDismissalReason(LeakDialogDismissalReason reason); + + // Helper method to overwrite the sampling rate during unit tests. + void SetSamplingRateForTesting(double rate) { ukm_sampling_rate_ = rate; } + + private: + // The UMA prefix. + static constexpr char kHistogram[] = + "PasswordManager.LeakDetection.DialogDismissalReason"; + + // The sampling rate for UKM recording. A value of 0.1 corresponds to a + // sampling rate of 10%. + double ukm_sampling_rate_ = 0.1; + + // Helper method to determine the suffix for the UMA. + const char* GetUMASuffix() const; + + // The source id associated with the navigation. + ukm::SourceId source_id_; + + // The type of the leak dialog. + LeakDialogType type_; +}; + // Log the |reason| a user dismissed the password manager UI except save/update // bubbles. void LogGeneralUIDismissalReason(UIDismissalReason reason); @@ -576,11 +616,6 @@ void LogMoveUIDismissalReason(UIDismissalReason reason, PasswordAccountStorageUserState user_state); -// Log the |type| of a leak dialog shown to the user and the |reason| why it was -// dismissed. -void LogLeakDialogTypeAndDismissalReason(LeakDialogType type, - LeakDialogDismissalReason reason); - // Log the appropriate display disposition. void LogUIDisplayDisposition(UIDisplayDisposition disposition);
diff --git a/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc b/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc new file mode 100644 index 0000000..3627fcd3 --- /dev/null +++ b/components/password_manager/core/browser/password_manager_metrics_util_unittest.cc
@@ -0,0 +1,102 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/password_manager_metrics_util.h" + +#include "base/test/metrics/histogram_tester.h" +#include "base/test/task_environment.h" +#include "components/ukm/test_ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_source.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace password_manager::metrics_util { + +namespace { + +constexpr ukm::SourceId kTestSourceId = 0x1234; + +using UkmEntry = ukm::builders::PasswordManager_LeakWarningDialog; + +// Create a LeakDialogMetricsRecorder for a test source id. +// Tests in this unit test are somewhat perfunctory due to the limited +// functionality of the class. On top of this, the unit tests for +// CredentialLeakDialogControllerImpl also test metrics recording. +LeakDialogMetricsRecorder CreateMetricsRecorder(LeakDialogType dialog_type) { + return LeakDialogMetricsRecorder(kTestSourceId, dialog_type); +} + +} // namespace + +TEST(PasswordManagerMetricsUtilLeakDialogMetricsRecorder, + AutomaticPasswordChangeClicked) { + base::test::TaskEnvironment task_environment_; + base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; + + LeakDialogMetricsRecorder recorder( + CreateMetricsRecorder(LeakDialogType::kChangeAutomatically)); + recorder.SetSamplingRateForTesting(1.0); + recorder.LogLeakDialogTypeAndDismissalReason( + LeakDialogDismissalReason::kClickedChangePasswordAutomatically); + + // Check that UMA logging is correct. + histogram_tester.ExpectUniqueSample( + "PasswordManager.LeakDetection.DialogDismissalReason", + LeakDialogDismissalReason::kClickedChangePasswordAutomatically, 1); + histogram_tester.ExpectUniqueSample( + "PasswordManager.LeakDetection.DialogDismissalReason.ChangeAutomatically", + LeakDialogDismissalReason::kClickedChangePasswordAutomatically, 1); + + // Check that UKM logging is correct. + const auto& entries = + test_ukm_recorder.GetEntriesByName(UkmEntry::kEntryName); + EXPECT_EQ(1u, entries.size()); + for (const auto* entry : entries) { + EXPECT_EQ(kTestSourceId, entry->source_id); + test_ukm_recorder.ExpectEntryMetric( + entry, UkmEntry::kPasswordLeakDetectionDialogTypeName, + static_cast<int64_t>(LeakDialogType::kChangeAutomatically)); + test_ukm_recorder.ExpectEntryMetric( + entry, UkmEntry::kPasswordLeakDetectionDialogDismissalReasonName, + static_cast<int64_t>( + LeakDialogDismissalReason::kClickedChangePasswordAutomatically)); + } +} + +TEST(PasswordManagerMetricsUtilLeakDialogMetricsRecorder, CheckupIgnored) { + base::test::TaskEnvironment task_environment_; + base::HistogramTester histogram_tester; + ukm::TestAutoSetUkmRecorder test_ukm_recorder; + + LeakDialogMetricsRecorder recorder( + CreateMetricsRecorder(LeakDialogType::kCheckup)); + recorder.SetSamplingRateForTesting(1.0); + recorder.LogLeakDialogTypeAndDismissalReason( + LeakDialogDismissalReason::kNoDirectInteraction); + + // Check that UMA logging is correct. + histogram_tester.ExpectUniqueSample( + "PasswordManager.LeakDetection.DialogDismissalReason", + LeakDialogDismissalReason::kNoDirectInteraction, 1); + histogram_tester.ExpectUniqueSample( + "PasswordManager.LeakDetection.DialogDismissalReason.Checkup", + LeakDialogDismissalReason::kNoDirectInteraction, 1); + + // Check that UKM logging is correct. + const auto& entries = + test_ukm_recorder.GetEntriesByName(UkmEntry::kEntryName); + EXPECT_EQ(1u, entries.size()); + for (const auto* entry : entries) { + EXPECT_EQ(kTestSourceId, entry->source_id); + test_ukm_recorder.ExpectEntryMetric( + entry, UkmEntry::kPasswordLeakDetectionDialogTypeName, + static_cast<int64_t>(LeakDialogType::kCheckup)); + test_ukm_recorder.ExpectEntryMetric( + entry, UkmEntry::kPasswordLeakDetectionDialogDismissalReasonName, + static_cast<int64_t>(LeakDialogDismissalReason::kNoDirectInteraction)); + } +} + +} // namespace password_manager::metrics_util
diff --git a/components/policy/core/browser/webui/policy_status_provider.cc b/components/policy/core/browser/webui/policy_status_provider.cc index d22dd5d..60bf9f7d 100644 --- a/components/policy/core/browser/webui/policy_status_provider.cc +++ b/components/policy/core/browser/webui/policy_status_provider.cc
@@ -95,17 +95,22 @@ refresh_scheduler ? refresh_scheduler->GetActualRefreshDelay() : CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs); + const bool is_push_available = + refresh_scheduler && refresh_scheduler->invalidations_available(); + bool no_error = store->status() == CloudPolicyStore::STATUS_OK && client && client->status() == DM_STATUS_SUCCESS; dict->SetBoolKey("error", !no_error); - dict->SetBoolKey( - "policiesPushAvailable", - refresh_scheduler ? refresh_scheduler->invalidations_available() : false); + dict->SetBoolKey("policiesPushAvailable", is_push_available); dict->SetStringKey("status", status); - dict->SetStringKey( - "refreshInterval", - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, - ui::TimeFormat::LENGTH_SHORT, refresh_interval)); + // If push is on, policy update will be done via push. Hide policy fetch + // interval label to prevent users from misunderstanding. + if (!is_push_available) { + dict->SetStringKey( + "refreshInterval", + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, + ui::TimeFormat::LENGTH_SHORT, refresh_interval)); + } base::Time last_refresh_time = policy && policy->has_timestamp() ? base::Time::FromJavaTime(policy->timestamp())
diff --git a/components/policy/core/common/default_chrome_apps_migrator.cc b/components/policy/core/common/default_chrome_apps_migrator.cc index 7dc65b9..4e00965 100644 --- a/components/policy/core/common/default_chrome_apps_migrator.cc +++ b/components/policy/core/common/default_chrome_apps_migrator.cc
@@ -12,7 +12,10 @@ namespace { std::map<std::string, std::string> GetChromeAppToWebAppMapping() { - return std::map<std::string, std::string>(); + return std::map<std::string, std::string>({ + {"ejjicmeblgpmajnghnpcppodonldlgfn", + "https://calendar.google.com/calendar/installwebapp?usp=chrome_default"}, + }); } } // namespace
diff --git a/components/policy/core/common/schema.cc b/components/policy/core/common/schema.cc index 702ded24..ff75b196 100644 --- a/components/policy/core/common/schema.cc +++ b/components/policy/core/common/schema.cc
@@ -1445,7 +1445,8 @@ std::string* error) { base::JSONReader::ValueWithError value_with_error = base::JSONReader::ReadAndReturnValueWithError( - schema, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS); + schema, base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS | + base::JSONParserOptions::JSON_PARSE_CHROMIUM_EXTENSIONS); *error = value_with_error.error_message; if (!value_with_error.value)
diff --git a/components/policy/resources/webui/policy_base.js b/components/policy/resources/webui/policy_base.js index cab2e263..54a34474 100644 --- a/components/policy/resources/webui/policy_base.js +++ b/components/policy/resources/webui/policy_base.js
@@ -189,7 +189,9 @@ } if (scope !== 'updater') { - this.setLabelAndShow_('.refresh-interval', status.refreshInterval); + if (status.refreshInterval) { + this.setLabelAndShow_('.refresh-interval', status.refreshInterval); + } this.setLabelAndShow_('.status', status.status); this.setLabelAndShow_( '.policy-push',
diff --git a/components/sync/engine/cycle/data_type_tracker.cc b/components/sync/engine/cycle/data_type_tracker.cc index a487129f..31832431 100644 --- a/components/sync/engine/cycle/data_type_tracker.cc +++ b/components/sync/engine/cycle/data_type_tracker.cc
@@ -357,25 +357,6 @@ return sync_required_to_resolve_conflict_; } -void DataTypeTracker::SetLegacyNotificationHint( - sync_pb::DataTypeProgressMarker* progress) const { - DCHECK(!IsBlocked()) - << "We should not make requests if the type is throttled or backed off."; - - if (!pending_invalidations_.empty() && - !pending_invalidations_.back()->IsUnknownVersion()) { - // The old-style source info can contain only one hint per type. We grab - // the most recent, to mimic the old coalescing behaviour. - progress->set_notification_hint( - pending_invalidations_.back()->GetPayload()); - } else if (HasLocalChangePending()) { - // The old-style source info sent up an empty string (as opposed to - // nothing at all) when the type was locally nudged, but had not received - // any invalidations. - progress->set_notification_hint(std::string()); - } -} - void DataTypeTracker::FillGetUpdatesTriggersMessage( sync_pb::GetUpdateTriggers* msg) const { // Fill the list of payloads, if applicable. The payloads must be ordered
diff --git a/components/sync/engine/cycle/data_type_tracker.h b/components/sync/engine/cycle/data_type_tracker.h index dfedbde..901e3f6 100644 --- a/components/sync/engine/cycle/data_type_tracker.h +++ b/components/sync/engine/cycle/data_type_tracker.h
@@ -17,7 +17,6 @@ #include "third_party/abseil-cpp/absl/types/optional.h" namespace sync_pb { -class DataTypeProgressMarker; class GetUpdateTriggers; } // namespace sync_pb @@ -122,10 +121,6 @@ // Returns true if this type is requesting a sync to resolve conflict issue. bool IsSyncRequiredToResolveConflict() const; - // Fills in the legacy invalidaiton payload information fields. - void SetLegacyNotificationHint( - sync_pb::DataTypeProgressMarker* progress) const; - // Fills some type-specific contents of a GetUpdates request protobuf. These // messages provide the server with the information it needs to decide how to // handle a request.
diff --git a/components/sync/engine/cycle/nudge_tracker.cc b/components/sync/engine/cycle/nudge_tracker.cc index d6e1d95..8cfa7b81 100644 --- a/components/sync/engine/cycle/nudge_tracker.cc +++ b/components/sync/engine/cycle/nudge_tracker.cc
@@ -259,13 +259,6 @@ return result; } -void NudgeTracker::SetLegacyNotificationHint( - ModelType type, - sync_pb::DataTypeProgressMarker* progress) const { - DCHECK(type_trackers_.find(type) != type_trackers_.end()); - type_trackers_.find(type)->second->SetLegacyNotificationHint(progress); -} - sync_pb::SyncEnums::GetUpdatesOrigin NudgeTracker::GetOrigin() const { for (const auto& [type, tracker] : type_trackers_) { if (!tracker->IsBlocked() && (tracker->HasPendingInvalidation() ||
diff --git a/components/sync/engine/cycle/nudge_tracker.h b/components/sync/engine/cycle/nudge_tracker.h index feb4d6a..ef0c879a 100644 --- a/components/sync/engine/cycle/nudge_tracker.h +++ b/components/sync/engine/cycle/nudge_tracker.h
@@ -18,10 +18,6 @@ #include "components/sync/protocol/sync_enums.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" -namespace sync_pb { -class DataTypeProgressMarker; -} // namespace sync_pb - namespace syncer { // A class to track the outstanding work required to bring the client back into @@ -138,13 +134,6 @@ // information into the GetUpdate request before sending it off to the server. void FillProtoMessage(ModelType type, sync_pb::GetUpdateTriggers* msg) const; - // Fills a ProgressMarker with single legacy notification hint expected by the - // sync server. Newer servers will rely on the data set by FillProtoMessage() - // instead of this. - void SetLegacyNotificationHint( - ModelType type, - sync_pb::DataTypeProgressMarker* progress) const; - // Flips the flag if we're due for a retry. void SetSyncCycleStartTime(base::TimeTicks now);
diff --git a/components/sync/engine/get_updates_delegate.cc b/components/sync/engine/get_updates_delegate.cc index 9acd4cf..8ffd199c 100644 --- a/components/sync/engine/get_updates_delegate.cc +++ b/components/sync/engine/get_updates_delegate.cc
@@ -48,7 +48,6 @@ DCHECK(!nudge_tracker_.IsTypeBlocked(type)) << "Throttled types should have been removed from the request_types."; - nudge_tracker_.SetLegacyNotificationHint(type, progress_marker); nudge_tracker_.FillProtoMessage( type, progress_marker->mutable_get_update_triggers()); }
diff --git a/components/sync/engine/get_updates_processor_unittest.cc b/components/sync/engine/get_updates_processor_unittest.cc index 7145df55..4bfafd2 100644 --- a/components/sync/engine/get_updates_processor_unittest.cc +++ b/components/sync/engine/get_updates_processor_unittest.cc
@@ -124,12 +124,9 @@ // We perform some basic tests of GU trigger and source fields here. The // more complicated scenarios are tested by the NudgeTracker tests. if (type == BOOKMARKS) { - EXPECT_TRUE(progress_marker.has_notification_hint()); - EXPECT_EQ("", progress_marker.notification_hint()); EXPECT_EQ(1, gu_trigger.local_modification_nudges()); EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges()); } else { - EXPECT_FALSE(progress_marker.has_notification_hint()); EXPECT_EQ(0, gu_trigger.local_modification_nudges()); EXPECT_EQ(0, gu_trigger.datatype_refresh_nudges()); } @@ -172,11 +169,8 @@ // We perform some basic tests of GU trigger and source fields here. The // more complicated scenarios are tested by the NudgeTracker tests. if (notified_types.Has(type)) { - EXPECT_TRUE(progress_marker.has_notification_hint()); - EXPECT_FALSE(progress_marker.notification_hint().empty()); EXPECT_EQ(1, gu_trigger.notification_hint_size()); } else { - EXPECT_FALSE(progress_marker.has_notification_hint()); EXPECT_EQ(0, gu_trigger.notification_hint_size()); } }
diff --git a/components/sync/invalidations/fcm_handler.cc b/components/sync/invalidations/fcm_handler.cc index 7ec4d854..188c579 100644 --- a/components/sync/invalidations/fcm_handler.cc +++ b/components/sync/invalidations/fcm_handler.cc
@@ -25,6 +25,9 @@ const int kInstanceIDTokenTTLSeconds = 14 * 24 * 60 * 60; // 2 weeks. +// Limits the number of last received buffered messages. +const size_t kMaxBufferedLastFcmMessages = 5; + FCMHandler::FCMHandler(gcm::GCMDriver* gcm_driver, instance_id::InstanceIDDriver* instance_id_driver, const std::string& sender_id, @@ -43,6 +46,12 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!IsListening()); DCHECK(base::FeatureList::IsEnabled(kUseSyncInvalidations)); + DCHECK(last_received_messages_.empty()); + + // Note that AddAppHandler() causes an immediate replay of all received + // messages in background on Android. Those messages will be stored in + // |last_received_messages_| and delivered to listeners once they have been + // added. gcm_driver_->AddAppHandler(app_id_, this); waiting_for_token_ = true; StartTokenFetch(base::BindOnce(&FCMHandler::DidRetrieveToken, @@ -57,6 +66,7 @@ if (IsListening()) { gcm_driver_->RemoveAppHandler(app_id_); token_validation_timer_.AbandonAndStop(); + last_received_messages_.clear(); } } @@ -92,6 +102,12 @@ void FCMHandler::AddListener(InvalidationsListener* listener) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); listeners_.AddObserver(listener); + + // Immediately replay any buffered messages received before the |listener| + // was added. + for (const std::string& message : last_received_messages_) { + listener->OnInvalidationReceived(message); + } } void FCMHandler::RemoveListener(InvalidationsListener* listener) { @@ -122,6 +138,10 @@ base::UmaHistogramBoolean("Sync.FCMMessageDeliveredToListeners", !listeners_.empty()); + if (last_received_messages_.size() >= kMaxBufferedLastFcmMessages) { + last_received_messages_.pop_front(); + } + last_received_messages_.push_back(message.raw_data); for (InvalidationsListener& listener : listeners_) { listener.OnInvalidationReceived(message.raw_data); }
diff --git a/components/sync/invalidations/fcm_handler.h b/components/sync/invalidations/fcm_handler.h index 68abab0..874b7e9 100644 --- a/components/sync/invalidations/fcm_handler.h +++ b/components/sync/invalidations/fcm_handler.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/containers/circular_deque.h" #include "base/memory/raw_ptr.h" #include "base/observer_list.h" #include "base/sequence_checker.h" @@ -59,7 +60,8 @@ bool IsListening() const; // Add or remove a new listener which will be notified on each new incoming - // invalidation. |listener| must not be nullptr. + // invalidation. |listener| must not be nullptr. When added, some previously + // received messages will be immediately replayed. void AddListener(InvalidationsListener* listener); void RemoveListener(InvalidationsListener* listener); @@ -111,6 +113,10 @@ bool waiting_for_token_ = false; + // A list of the latest incoming messages, used to replay incoming messages + // whenever a new listener is added. + base::circular_deque<std::string> last_received_messages_; + // Contains all listeners to notify about each incoming message in OnMessage // method. base::ObserverList<InvalidationsListener,
diff --git a/components/sync/invalidations/fcm_handler_unittest.cc b/components/sync/invalidations/fcm_handler_unittest.cc index e6c0554..7260b7c 100644 --- a/components/sync/invalidations/fcm_handler_unittest.cc +++ b/components/sync/invalidations/fcm_handler_unittest.cc
@@ -251,5 +251,57 @@ fcm_handler_.RemoveTokenObserver(&mock_token_observer); } +TEST_F(FCMHandlerTest, ShouldReplayIncomingMessagesOnAddingListener) { + const std::string kPayloadValue1 = "payload_1"; + const std::string kPayloadValue2 = "payload_2"; + + gcm::IncomingMessage gcm_message; + gcm_message.raw_data = kPayloadValue1; + fcm_handler_.OnMessage(kSyncInvalidationsAppId, gcm_message); + + gcm_message.raw_data = kPayloadValue2; + fcm_handler_.OnMessage(kSyncInvalidationsAppId, gcm_message); + + NiceMock<MockListener> mock_listener; + EXPECT_CALL(mock_listener, OnInvalidationReceived(kPayloadValue1)); + EXPECT_CALL(mock_listener, OnInvalidationReceived(kPayloadValue2)); + fcm_handler_.AddListener(&mock_listener); + fcm_handler_.RemoveListener(&mock_listener); +} + +TEST_F(FCMHandlerTest, ShouldLimitIncomingMessagesForReplay) { + gcm::IncomingMessage gcm_message; + gcm_message.raw_data = "payload"; + for (size_t i = 0; i < 100; ++i) { + fcm_handler_.OnMessage(kSyncInvalidationsAppId, gcm_message); + } + + NiceMock<MockListener> mock_listener; + EXPECT_CALL(mock_listener, OnInvalidationReceived).Times(5); + fcm_handler_.AddListener(&mock_listener); + fcm_handler_.RemoveListener(&mock_listener); +} + +TEST_F(FCMHandlerTest, ShouldClearLastIncomingMessagesOnStopListening) { + EXPECT_CALL(mock_instance_id_, GetToken) + .WillRepeatedly( + WithArg<4>(Invoke([](InstanceID::GetTokenCallback callback) { + std::move(callback).Run("token", InstanceID::Result::SUCCESS); + }))); + fcm_handler_.StartListening(); + + gcm::IncomingMessage gcm_message; + gcm_message.raw_data = "payload"; + fcm_handler_.OnMessage(kSyncInvalidationsAppId, gcm_message); + + fcm_handler_.StopListening(); + fcm_handler_.StartListening(); + + NiceMock<MockListener> mock_listener; + EXPECT_CALL(mock_listener, OnInvalidationReceived).Times(0); + fcm_handler_.AddListener(&mock_listener); + fcm_handler_.RemoveListener(&mock_listener); +} + } // namespace } // namespace syncer
diff --git a/components/sync/protocol/data_type_progress_marker.proto b/components/sync/protocol/data_type_progress_marker.proto index 70bf7a4..89bb9a8 100644 --- a/components/sync/protocol/data_type_progress_marker.proto +++ b/components/sync/protocol/data_type_progress_marker.proto
@@ -44,13 +44,8 @@ reserved 3; reserved "timestamp_token_for_migration"; - // An opaque-to-the-client string of bytes, received through a notification, - // that the server may interpret as a hint about the location of the latest - // version of the data for this type. - // - // Deprecated in M29. We should use the repeated field version in the - // PerClientTypeState instead. - optional string notification_hint = 4 [deprecated = true]; + reserved 4; + reserved "notification_hint"; // This field will be included only in GetUpdates with origin GU_TRIGGER. optional GetUpdateTriggers get_update_triggers = 5;
diff --git a/components/sync/protocol/proto_visitors.h b/components/sync/protocol/proto_visitors.h index 07dc35d..4ea036f 100644 --- a/components/sync/protocol/proto_visitors.h +++ b/components/sync/protocol/proto_visitors.h
@@ -365,7 +365,6 @@ VISIT_PROTO_FIELDS(const sync_pb::DataTypeProgressMarker& proto) { VISIT(data_type_id); VISIT_BYTES(token); - VISIT(notification_hint); VISIT(get_update_triggers); VISIT(gc_directive); }
diff --git a/components/test/data/history/history.55.sql b/components/test/data/history/history.55.sql new file mode 100644 index 0000000..378304a --- /dev/null +++ b/components/test/data/history/history.55.sql
@@ -0,0 +1,35 @@ +PRAGMA foreign_keys=OFF; +BEGIN TRANSACTION; +CREATE TABLE meta(key LONGVARCHAR NOT NULL UNIQUE PRIMARY KEY, value LONGVARCHAR); +INSERT INTO meta VALUES('mmap_status','-1'); +INSERT INTO meta VALUES('version','55'); +INSERT INTO meta VALUES('last_compatible_version','16'); +CREATE TABLE urls(id INTEGER PRIMARY KEY AUTOINCREMENT,url LONGVARCHAR,title LONGVARCHAR,visit_count INTEGER DEFAULT 0 NOT NULL,typed_count INTEGER DEFAULT 0 NOT NULL,last_visit_time INTEGER NOT NULL,hidden INTEGER DEFAULT 0 NOT NULL); +CREATE TABLE visits(id INTEGER PRIMARY KEY AUTOINCREMENT,url INTEGER NOT NULL,visit_time INTEGER NOT NULL,from_visit INTEGER,transition INTEGER DEFAULT 0 NOT NULL,segment_id INTEGER,visit_duration INTEGER DEFAULT 0 NOT NULL,incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL,opener_visit INTEGER,originator_cache_guid TEXT,originator_visit_id INTEGER); +CREATE TABLE visit_source(id INTEGER PRIMARY KEY,source INTEGER NOT NULL); +CREATE TABLE keyword_search_terms (keyword_id INTEGER NOT NULL,url_id INTEGER NOT NULL,term LONGVARCHAR NOT NULL,normalized_term LONGVARCHAR NOT NULL); +CREATE TABLE downloads (id INTEGER PRIMARY KEY,guid VARCHAR NOT NULL,current_path LONGVARCHAR NOT NULL,target_path LONGVARCHAR NOT NULL,start_time INTEGER NOT NULL,received_bytes INTEGER NOT NULL,total_bytes INTEGER NOT NULL,state INTEGER NOT NULL,danger_type INTEGER NOT NULL,interrupt_reason INTEGER NOT NULL,hash BLOB NOT NULL,end_time INTEGER NOT NULL,opened INTEGER NOT NULL,last_access_time INTEGER NOT NULL,transient INTEGER NOT NULL,referrer VARCHAR NOT NULL,site_url VARCHAR NOT NULL,embedder_download_data VARCHAR NOT NULL,tab_url VARCHAR NOT NULL,tab_referrer_url VARCHAR NOT NULL,http_method VARCHAR NOT NULL,by_ext_id VARCHAR NOT NULL,by_ext_name VARCHAR NOT NULL,etag VARCHAR NOT NULL,last_modified VARCHAR NOT NULL,mime_type VARCHAR(255) NOT NULL,original_mime_type VARCHAR(255) NOT NULL); +CREATE TABLE downloads_url_chains (id INTEGER NOT NULL,chain_index INTEGER NOT NULL,url LONGVARCHAR NOT NULL, PRIMARY KEY (id, chain_index) ); +CREATE TABLE downloads_slices (download_id INTEGER NOT NULL,offset INTEGER NOT NULL,received_bytes INTEGER NOT NULL,finished INTEGER NOT NULL DEFAULT 0,PRIMARY KEY (download_id, offset) ); +CREATE TABLE downloads_reroute_info (download_id INTEGER NOT NULL,reroute_info_serialized VARCHAR NOT NULL,PRIMARY KEY (download_id) ); +CREATE TABLE segments (id INTEGER PRIMARY KEY,name VARCHAR,url_id INTEGER NON NULL); +CREATE TABLE segment_usage (id INTEGER PRIMARY KEY,segment_id INTEGER NOT NULL,time_slot INTEGER NOT NULL,visit_count INTEGER DEFAULT 0 NOT NULL); +CREATE TABLE typed_url_sync_metadata (storage_key INTEGER PRIMARY KEY NOT NULL,value BLOB); +CREATE TABLE content_annotations(visit_id INTEGER PRIMARY KEY,visibility_score NUMERIC,floc_protected_score NUMERIC,categories VARCHAR,page_topics_model_version INTEGER,annotation_flags INTEGER NOT NULL,entities VARCHAR,related_searches VARCHAR,search_normalized_url VARCHAR,search_terms LONGVARCHAR,alternative_title VARCHAR); +CREATE TABLE context_annotations(visit_id INTEGER PRIMARY KEY,context_annotation_flags INTEGER NOT NULL,duration_since_last_visit INTEGER,page_end_reason INTEGER,total_foreground_duration INTEGER); +CREATE TABLE clusters(cluster_id INTEGER PRIMARY KEY,score NUMERIC NOT NULL); +CREATE TABLE clusters_and_visits(cluster_id INTEGER NOT NULL,visit_id INTEGER NOT NULL,score NUMERIC NOT NULL,PRIMARY KEY(cluster_id,visit_id))WITHOUT ROWID; +DELETE FROM sqlite_sequence; +CREATE INDEX visits_url_index ON visits (url); +CREATE INDEX visits_from_index ON visits (from_visit); +CREATE INDEX visits_time_index ON visits (visit_time); +CREATE INDEX keyword_search_terms_index1 ON keyword_search_terms (keyword_id, normalized_term); +CREATE INDEX keyword_search_terms_index2 ON keyword_search_terms (url_id); +CREATE INDEX keyword_search_terms_index3 ON keyword_search_terms (term); +CREATE INDEX segments_name ON segments(name); +CREATE INDEX segments_url_id ON segments(url_id); +CREATE INDEX segment_usage_time_slot_segment_id ON segment_usage(time_slot, segment_id); +CREATE INDEX segments_usage_seg_id ON segment_usage(segment_id); +CREATE INDEX clusters_for_visit ON clusters_and_visits(visit_id); +CREATE INDEX urls_url_index ON urls (url); +COMMIT;
diff --git a/components/test/data/omnibox/in_memory_url_index_test.sql b/components/test/data/omnibox/in_memory_url_index_test.sql index 31b95b88..015f6df 100644 --- a/components/test/data/omnibox/in_memory_url_index_test.sql +++ b/components/test/data/omnibox/in_memory_url_index_test.sql
@@ -36,16 +36,17 @@ -- The schema of the visit database is defined by HISTORY_VISIT_ROW_FIELDS -- found in visit_database.h and is equivalent to: -- --- CREATE TABLE visits(visit_id INTEGER PRIMARY KEY, +-- CREATE TABLE visits(id INTEGER PRIMARY KEY AUTOINCREMENT, -- url_id INTEGER NOT NULL, -- visit_time INTEGER NOT NULL, -- from_visit INTEGER, -- transition INTEGER DEFAULT 0 NOT NULL, -- segment_id INTEGER, --- is_indexed BOOLEAN, -- visit_duration INTEGER DEFAULT 0 NOT NULL, -- incremented_omnibox_typed_score BOOLEAN DEFAULT FALSE NOT NULL, --- publicly_routable BOOLEAN DEFAULT FALSE NOT NULL) +-- opener_visit INTEGER, +-- originator_cache_guid TEXT, +-- originator_visit_id INTEGER) INSERT INTO "urls" VALUES(1,'http://www.reuters.com/article/idUSN0839880620100708','UPDATE 1-US 30-yr mortgage rate drops to new record low | Reuters',3,1,2,0); -- Qualifies INSERT INTO "urls" VALUES(2,'http://www.golfweek.com/news/2010/jul/08/goydos-opens-john-deere-classic-59/','Goydos opens John Deere Classic with 59',3,1,4,0); -- Qualifies INSERT INTO "urls" VALUES(3,'http://www.businessandmedia.org/articles/2010/20100708120415.aspx','LeBronomics: Could High Taxes Influence James'' Team Decision?',4,1,2,0); -- Qualifies @@ -86,25 +87,25 @@ -- This file creates some visits, enough to test (in InMemoryURLIndexTest) -- the visits functionality, certainly not as many visits as are implied -- by the visit counts associated with the URLs above. -INSERT INTO "visits" VALUES(1, 1, 2, 4, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(2, 1, 5, 0, 1, 0, 1, TRUE, FALSE); -INSERT INTO "visits" VALUES(3, 1, 12, 0, 0, 0, 1, FALSE, TRUE); -INSERT INTO "visits" VALUES(4, 32, 1, 0, 0, 0, 1, FALSE, TRUE); -INSERT INTO "visits" VALUES(5, 32, 2, 0, 0, 0, 1, FALSE, TRUE); -INSERT INTO "visits" VALUES(6, 32, 3, 0, 0, 0, 1, FALSE, TRUE); -INSERT INTO "visits" VALUES(7, 32, 4, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(8, 32, 5, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(9, 32, 6, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(10, 32, 7, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(11, 32, 8, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(12, 32, 9, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(13, 32, 10, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(14, 32, 11, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(15, 32, 12, 0, 0, 0, 1, FALSE, FALSE); -INSERT INTO "visits" VALUES(16, 32, 13, 0, 0, 0, 1, FALSE, TRUE); -INSERT INTO "visits" VALUES(17, 32, 14, 0, 0, 0, 1, FALSE, TRUE); -INSERT INTO "visits" VALUES(18, 32, 15, 0, 1, 0, 1, TRUE, TRUE); -INSERT INTO "visits" VALUES(19, 35, 0, 0, 1, 0, 1, TRUE, TRUE); -INSERT INTO "visits" VALUES(20, 35, 7, 0, 1, 0, 1, TRUE, TRUE); -INSERT INTO "visits" VALUES(21, 36, 1, 0, 1, 0, 1, TRUE, FALSE); -INSERT INTO "visits" VALUES(22, 36, 2, 0, 1, 0, 1, TRUE, FALSE); +INSERT INTO "visits" VALUES(1, 1, 2, 4, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(2, 1, 5, 0, 1, 0, 1, TRUE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(3, 1, 12, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(4, 32, 1, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(5, 32, 2, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(6, 32, 3, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(7, 32, 4, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(8, 32, 5, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(9, 32, 6, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(10, 32, 7, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(11, 32, 8, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(12, 32, 9, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(13, 32, 10, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(14, 32, 11, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(15, 32, 12, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(16, 32, 13, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(17, 32, 14, 0, 0, 0, 1, FALSE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(18, 32, 15, 0, 1, 0, 1, TRUE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(19, 35, 0, 0, 1, 0, 1, TRUE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(20, 35, 7, 0, 1, 0, 1, TRUE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(21, 36, 1, 0, 1, 0, 1, TRUE, 0, NULL, NULL); +INSERT INTO "visits" VALUES(22, 36, 2, 0, 1, 0, 1, TRUE, 0, NULL, NULL);
diff --git a/components/viz/service/display_embedder/image_context_impl.cc b/components/viz/service/display_embedder/image_context_impl.cc index ba9fadd..f214a58 100644 --- a/components/viz/service/display_embedder/image_context_impl.cc +++ b/components/viz/service/display_embedder/image_context_impl.cc
@@ -184,11 +184,7 @@ return false; set_paint_op_buffer(scoped_access->paint_op_buffer()); - // TODO(crbug.com/1308932) gpu/commmand_buffer should also store float colors. - absl::optional<SkColor4f> new_clear_color; - if (scoped_access->clear_color()) - new_clear_color = SkColor4f::FromColor(*scoped_access->clear_color()); - set_clear_color(new_clear_color); + set_clear_color(scoped_access->clear_color()); raster_representation_ = std::move(raster); representation_raster_scoped_access_ = std::move(scoped_access);
diff --git a/components/viz/test/data/oop_draw_rect_query.png b/components/viz/test/data/oop_draw_rect_query.png index 54557d8..437b6f2d 100644 --- a/components/viz/test/data/oop_draw_rect_query.png +++ b/components/viz/test/data/oop_draw_rect_query.png Binary files differ
diff --git a/components/viz/test/test_raster_interface.h b/components/viz/test/test_raster_interface.h index 2f039438..a47b8f1b 100644 --- a/components/viz/test/test_raster_interface.h +++ b/components/viz/test/test_raster_interface.h
@@ -98,7 +98,7 @@ const gpu::Mailbox yuva_plane_mailboxes[], const gpu::Mailbox& source_mailbox) override { } - void BeginRasterCHROMIUM(GLuint sk_color, + void BeginRasterCHROMIUM(SkColor4f sk_color_4f, GLboolean needs_clear, GLuint msaa_sample_count, gpu::raster::MsaaMode msaa_mode,
diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/client_hints/client_hints.cc index c6a04c61..b6dc7a9cb 100644 --- a/content/browser/client_hints/client_hints.cc +++ b/content/browser/client_hints/client_hints.cc
@@ -458,8 +458,9 @@ } // Returns true iff the `url` is embedded inside a frame that has the -// corresponding Sec-CH-UA-Reduced or Sec-CH-UA-Full client hint and thus, is -// enrolled in the UserAgentReduction or SendFullUserAgentAfterReduction +// corresponding Sec-CH-UA-Reduced, Sec-CH-UA-Full, or +// Sec-CH-Partitioned-Cookies client hint and thus, is enrolled in the +// UserAgentReduction, SendFullUserAgentAfterReduction, or PartitionedCookies // Origin Trial. // // TODO(crbug.com/1258063): Remove when the UserAgentReduction and @@ -509,7 +510,8 @@ for (auto it = accept_ch->begin(); it != accept_ch->end();) { if (*it == WebClientHintsType::kUAReduced || - *it == WebClientHintsType::kFullUserAgent) { + *it == WebClientHintsType::kFullUserAgent || + *it == WebClientHintsType::kPartitionedCookies) { ++it; } else { it = accept_ch->erase(it); @@ -584,6 +586,9 @@ is_embedder_ua_full = IsOriginTrialHintEnabledForFrame( trial_origin, outermost_main_frame_origin, frame_tree_node, delegate, WebClientHintsType::kFullUserAgent); + is_embedder_partitioned_cookies = IsOriginTrialHintEnabledForFrame( + trial_origin, outermost_main_frame_origin, frame_tree_node, delegate, + WebClientHintsType::kPartitionedCookies); } // Record the time spent getting the client hints. @@ -608,6 +613,12 @@ // receive the full User-Agent header, so we want to also send the full // User-Agent for the embedded request as well. bool is_embedder_ua_full = false; + // If true, one of the ancestor requests in the path to this request had + // Sec-CH-Partitioned-Cookies in their Accept-CH cache. Only appplies to + // embedded requests (top-level requests will always set this to false). + // + // If the embedder of the + bool is_embedder_partitioned_cookies = false; url::Origin resource_origin; bool is_outermost_main_frame = false; url::Origin outermost_main_frame_origin; @@ -617,7 +628,8 @@ bool SkipPermissionPolicyCheck(WebClientHintsType type) { return type == WebClientHintsType::kUAReduced || - type == WebClientHintsType::kFullUserAgent; + type == WebClientHintsType::kFullUserAgent || + type == WebClientHintsType::kPartitionedCookies; } bool IsClientHintEnabled(const ClientHintsExtendedData& data, @@ -626,7 +638,9 @@ (type == WebClientHintsType::kUAReduced && data.is_embedder_ua_reduced) || (type == WebClientHintsType::kFullUserAgent && - data.is_embedder_ua_full); + data.is_embedder_ua_full) || + (type == WebClientHintsType::kPartitionedCookies && + data.is_embedder_partitioned_cookies); } bool IsClientHintAllowed(const ClientHintsExtendedData& data, @@ -935,6 +949,11 @@ AddPrefersColorSchemeHeader(headers, frame_tree_node); } + if (ShouldAddClientHint(data, WebClientHintsType::kPartitionedCookies)) { + SetHeaderToString(headers, WebClientHintsType::kPartitionedCookies, + SerializeHeaderString(true)); + } + if (ShouldAddClientHint(data, WebClientHintsType::kSaveData)) AddSaveDataHeader(headers, context); @@ -1073,6 +1092,15 @@ enabled_hints.GetEnabledHints(); PersistAcceptCH(origin, frame_tree_node->GetParentOrOuterDocument(), delegate, persisted_hints); + if (std::find(persisted_hints.begin(), persisted_hints.end(), + WebClientHintsType::kPartitionedCookies) == + persisted_hints.end()) { + if (auto* cookie_manager = frame_tree_node->current_frame_host() + ->GetStoragePartition() + ->GetCookieManagerForBrowserProcess()) { + cookie_manager->ConvertPartitionedCookiesToUnpartitioned(origin.GetURL()); + } + } return persisted_hints; } @@ -1105,6 +1133,10 @@ !base::Contains(hints, WebClientHintsType::kFullUserAgent)) { hints.push_back(WebClientHintsType::kFullUserAgent); } + if (data.is_embedder_partitioned_cookies && + !base::Contains(hints, WebClientHintsType::kPartitionedCookies)) { + hints.push_back(WebClientHintsType::kPartitionedCookies); + } return hints; }
diff --git a/content/browser/net/http_cookie_browsertest.cc b/content/browser/net/http_cookie_browsertest.cc index eb1c217..4fea2384 100644 --- a/content/browser/net/http_cookie_browsertest.cc +++ b/content/browser/net/http_cookie_browsertest.cc
@@ -5,18 +5,14 @@ #include "base/strings/strcat.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" -#include "base/test/bind.h" #include "base/test/scoped_feature_list.h" #include "content/public/browser/browser_context.h" -#include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/content_browser_test.h" -#include "content/public/test/content_browser_test_utils.h" #include "content/public/test/frame_test_utils.h" #include "content/public/test/test_navigation_observer.h" -#include "content/public/test/url_loader_interceptor.h" #include "content/shell/browser/shell.h" #include "net/base/features.h" #include "net/cookies/canonical_cookie_test_helpers.h" @@ -759,551 +755,5 @@ HttpCookieBrowserTest, ::testing::Bool()); -struct OriginTrialTestOptions { - bool has_ot_token = true; - bool valid_ot_token = true; - bool has_set_cookie = true; - bool has_partitioned = true; -}; - -// This class tests the origin trial mechanism for partitioned cookies. -// Partitioned cookies should be reverted to unpartitioned if the navigation -// has a Set-Cookie header with the Partitioned attribute and the site does -// not send a valid Origin-Trial header. -// This test exercises the origin trial for top-level navigation requests. -class PartitionedCookiesOriginTrialBrowserTest : public ContentBrowserTest { - protected: - void SetUp() override { - scoped_feature_list_.InitWithFeatures({net::features::kPartitionedCookies}, - {}); - ContentBrowserTest::SetUp(); - } - - void SetUpOnMainThread() override { - url_loader_interceptor_ = - std::make_unique<URLLoaderInterceptor>(base::BindRepeating( - &PartitionedCookiesOriginTrialBrowserTest::InterceptRequest, - base::Unretained(this))); - } - - void TearDownOnMainThread() override { - url_loader_interceptor_.reset(); - ContentBrowserTest::TearDownOnMainThread(); - } - - void SetTestOptions(const OriginTrialTestOptions& test_setting, - const std::set<GURL>& expected_request_urls) { - test_options_ = test_setting; - expected_request_urls_ = expected_request_urls; - } - - virtual const char* OriginTrialToken() const { - // The test Origin Trial token was generated by running: - // python tools/origin_trials/generate_token.py https://127.0.0.1:44444 \ - // PartitionedCookies \ - // --expire-timestamp=2000000000 - return "A4s/" - "iPKfhEfgqQIIuz4zLuCpONpXOuYyJFBhBx1MfgS1aNhFujyhsg4lkfTRfjzQCI3aUbM" - "wtNm25elLTR4UIgAAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0ND" - "QiLCAiZmVhdHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMjAwM" - "DAwMDAwMH0="; - } - - // We use URLLoaderInterceptor because we cannot control which port that - // EmbeddedTestServer uses. Since origin trials depend on the entire origin - // (including port) we need to intercept the requests using - // URLLoaderInterceptor. - bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { - if (expected_request_urls_.find(params->url_request.url) == - expected_request_urls_.end()) { - return false; - } - - std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; - std::string body = "<html><body>Hello world!</body></html>"; - if (test_options_.has_set_cookie) { - base::StrAppend( - &headers, - {"Set-Cookie: __Host-foo=bar; Secure; Path=/; SameSite=None;", - test_options_.has_partitioned ? " Partitioned" : "", "\n"}); - } - if (test_options_.has_ot_token) { - base::StrAppend( - &headers, - {"Origin-Trial: ", - test_options_.valid_ot_token ? OriginTrialToken() : "invalid", - "\n"}); - } - URLLoaderInterceptor::WriteResponse(headers, body, params->client.get(), - absl::nullopt, - /*url=*/params->url_request.url); - return true; - } - - network::mojom::CookieManager* GetCookieManager() { - return shell() - ->web_contents() - ->GetBrowserContext() - ->GetDefaultStoragePartition() - ->GetCookieManagerForBrowserProcess(); - } - - void SetCookie(const std::string& name, - const std::string& value, - const GURL& url, - const absl::optional<net::CookiePartitionKey>& partition_key) { - auto cookie = net::CanonicalCookie::CreateUnsafeCookieForTesting( - name, value, url.host(), "/", base::Time::Now() - base::Days(1), - base::Time::Now() + base::Days(1), base::Time::Now(), base::Time::Now(), - /*secure=*/true, /*httponly=*/false, - net::CookieSameSite::NO_RESTRICTION, - net::CookiePriority::COOKIE_PRIORITY_DEFAULT, /*same_party=*/false, - partition_key); - EXPECT_TRUE(cookie->IsCanonical()); - - base::RunLoop run_loop; - GetCookieManager()->SetCanonicalCookie( - *cookie, url, net::CookieOptions::MakeAllInclusive(), - base::BindLambdaForTesting( - [&](net::CookieAccessResult set_cookie_result) { - EXPECT_TRUE(set_cookie_result.status.IsInclude()); - run_loop.Quit(); - })); - run_loop.Run(); - } - - std::vector<net::CanonicalCookie> GetCookies(const GURL& url) { - std::vector<net::CanonicalCookie> cookies; - - base::RunLoop run_loop; - GetCookieManager()->GetCookieList( - url, net::CookieOptions::MakeAllInclusive(), - net::CookiePartitionKeyCollection::ContainsAll(), - base::BindLambdaForTesting( - [&](const std::vector<::net::CookieWithAccessResult>& result, - const std::vector<::net::CookieWithAccessResult>& - excluded_cookies) { - EXPECT_TRUE(excluded_cookies.empty()); - for (const auto& el : result) { - cookies.push_back(el.cookie); - } - run_loop.Quit(); - })); - run_loop.Run(); - - return cookies; - } - - const GURL CookieUrl() { return GURL("https://127.0.0.1:44444"); } - - void WaitForPage(const GURL& url) { - EXPECT_TRUE(NavigateToURL(shell(), url)); - WebContents* contents = shell()->web_contents(); - EXPECT_TRUE(WaitForLoadStop(contents)); - EXPECT_TRUE(WaitForRenderFrameReady(contents->GetMainFrame())); - } - - protected: - std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_; - OriginTrialTestOptions test_options_; - std::set<GURL> expected_request_urls_; - base::test::ScopedFeatureList scoped_feature_list_; -}; - -// Test that the partitioned cookie set before the request remains partitioned -// when the site sends a Set-Cookie header with the Partitioned attribute -// and a valid OT token. -IN_PROC_BROWSER_TEST_F(PartitionedCookiesOriginTrialBrowserTest, - ValidParticipant) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions( - {/*has_ot_token=*/true, /*valid_ot_token=*/true, /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {CookieUrl()}); - - WaitForPage(CookieUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// Test that the partitioned cookie is reverted to unpartitioned if the site -// sends a Set-Cookie with Partitioned but an invalid OT token. -IN_PROC_BROWSER_TEST_F(PartitionedCookiesOriginTrialBrowserTest, InvalidToken) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions( - {/*has_ot_token=*/true, /*valid_ot_token=*/false, /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {CookieUrl()}); - - WaitForPage(CookieUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -// Test that the partitioned cookie is reverted to unpartitioned if the site -// sends a Set-Cookie with Partitioned but do not send an OT token. -IN_PROC_BROWSER_TEST_F(PartitionedCookiesOriginTrialBrowserTest, NoToken) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {CookieUrl()}); - - WaitForPage(CookieUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -// The partitioned cookie should stay partitioned since we should not check -// the OT token on responses with no Set-Cookie header. -IN_PROC_BROWSER_TEST_F(PartitionedCookiesOriginTrialBrowserTest, NoSetCookie) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/false, - /*has_partitioned=*/true}, - {CookieUrl()}); - - WaitForPage(CookieUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// The partitioned cookie should stay partitioned since we should not check -// the OT token on responses with a Set-Cookie header without Partitioned. -IN_PROC_BROWSER_TEST_F(PartitionedCookiesOriginTrialBrowserTest, - NoPartitioned) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/true, - /*has_partitioned=*/false}, - {CookieUrl()}); - - WaitForPage(CookieUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// This class tests the origin trial mechanism for partitioned cookies. -// Partitioned cookies should be reverted to unpartitioned if the navigation -// has a Set-Cookie header with the Partitioned attribute and the site does -// not send a valid Origin-Trial header. -// This test exercises navigation requests in <iframe> embeds. -class EmbedPartitionedCookiesOriginTrialBrowserTest - : public PartitionedCookiesOriginTrialBrowserTest { - public: - void SetUpOnMainThread() override { - url_loader_interceptor_ = - std::make_unique<URLLoaderInterceptor>(base::BindRepeating( - &EmbedPartitionedCookiesOriginTrialBrowserTest::InterceptRequest, - base::Unretained(this))); - } - - const char* OriginTrialToken() const override { - // The test Origin Trial token was generated by running: - // python tools/origin_trials/generate_token.py https://127.0.0.1:44444 \ - // PartitionedCookies \ - // --expire-timestamp=2000000000 - // --is-third-party - return "A1mBOyrOKGAaaoT8mjM1qSNrOSrdDUa9WyqicVLlDGW3feIBSdWqSiHDAXUeKkGKaVq" - "UiCX8avwCM0gpG5LtxgAAAAByeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6ND" - "Q0NDQiLCAiZmVhdHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogM" - "jAwMDAwMDAwMCwgImlzVGhpcmRQYXJ0eSI6IHRydWV9"; - } - - // We use URLLoaderInterceptor because we cannot control which port that - // EmbeddedTestServer uses. Since origin trials depend on the entire origin - // (including port) we need to intercept the requests using - // URLLoaderInterceptor. - bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { - if (expected_request_urls_.find(params->url_request.url) == - expected_request_urls_.end()) { - return false; - } - - if (params->url_request.url == TopLevelUrl()) { - std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; - std::string body = "<html><body><iframe src=\""; - base::StrAppend(&body, {CookieUrl().spec(), "\"></body></html>"}); - URLLoaderInterceptor::WriteResponse(headers, body, params->client.get(), - absl::nullopt, - /*url=*/params->url_request.url); - return true; - } - - return PartitionedCookiesOriginTrialBrowserTest::InterceptRequest(params); - } - - GURL TopLevelUrl() { return GURL("https://mysite.com:44444"); } -}; - -// Test that the partitioned cookie set before the request remains partitioned -// when the site sends a Set-Cookie header with the Partitioned attribute -// and a valid OT token. -IN_PROC_BROWSER_TEST_F(EmbedPartitionedCookiesOriginTrialBrowserTest, - ValidParticipant) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions( - {/*has_ot_token=*/true, /*valid_ot_token=*/true, /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// Test that the partitioned cookie is reverted to unpartitioned if the site -// sends a Set-Cookie with Partitioned but an invalid OT token. -IN_PROC_BROWSER_TEST_F(EmbedPartitionedCookiesOriginTrialBrowserTest, - InvalidToken) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions( - {/*has_ot_token=*/true, /*valid_ot_token=*/false, /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -// Test that the partitioned cookie is reverted to unpartitioned if the site -// sends a Set-Cookie with Partitioned but do not send an OT token. -IN_PROC_BROWSER_TEST_F(EmbedPartitionedCookiesOriginTrialBrowserTest, NoToken) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -// The partitioned cookie should stay partitioned since we should not check -// the OT token on responses with no Set-Cookie header. -IN_PROC_BROWSER_TEST_F(EmbedPartitionedCookiesOriginTrialBrowserTest, - NoSetCookie) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/false, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// The partitioned cookie should stay partitioned since we should not check -// the OT token on responses with a Set-Cookie header without Partitioned. -IN_PROC_BROWSER_TEST_F(EmbedPartitionedCookiesOriginTrialBrowserTest, - NoPartitioned) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/true, - /*has_partitioned=*/false}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// This test exercises the partitioned cookie origin trial for subresource -// requests. This browser test is meant to verify the feature works end-to-end -// though there is nothing about this test particularly related to navigation. -// -// I put the test here because I can subclass other partitioned cookies origin -// trial tests that do test navigation requests to reuse the test -// infrastructure. -// TODO(https://crbug.com/1296161): Move to another file/delete this test when -// OT is over. -class SubresourcePartitionedCookiesOriginTrialBrowserTest - : public EmbedPartitionedCookiesOriginTrialBrowserTest { - public: - void SetUpOnMainThread() override { - url_loader_interceptor_ = std::make_unique< - URLLoaderInterceptor>(base::BindRepeating( - &SubresourcePartitionedCookiesOriginTrialBrowserTest::InterceptRequest, - base::Unretained(this))); - } - - bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { - if (expected_request_urls_.find(params->url_request.url) == - expected_request_urls_.end()) { - return false; - } - - if (params->url_request.url == TopLevelUrl()) { - std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; - std::string body = "<html><body><script src=\""; - base::StrAppend(&body, - {CookieUrl().spec(), "\"></script></body></html>"}); - URLLoaderInterceptor::WriteResponse(headers, body, params->client.get(), - absl::nullopt, - /*url=*/params->url_request.url); - return true; - } - - std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/javascript\n"; - std::string body = "console.log('Hello world!');"; - if (test_options_.has_set_cookie) { - base::StrAppend( - &headers, - {"Set-Cookie: __Host-foo=bar; Secure; Path=/; SameSite=None;", - test_options_.has_partitioned ? " Partitioned" : "", "\n"}); - } - if (test_options_.has_ot_token) { - base::StrAppend( - &headers, - {"Origin-Trial: ", - test_options_.valid_ot_token ? OriginTrialToken() : "invalid", - "\n"}); - } - URLLoaderInterceptor::WriteResponse(headers, body, params->client.get(), - absl::nullopt, - /*url=*/params->url_request.url); - return true; - } -}; - -// Test that the partitioned cookie set before the request remains partitioned -// when the site sends a Set-Cookie header with the Partitioned attribute -// and a valid OT token. -IN_PROC_BROWSER_TEST_F(SubresourcePartitionedCookiesOriginTrialBrowserTest, - ValidParticipant) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions( - {/*has_ot_token=*/true, /*valid_ot_token=*/true, /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// Test that the partitioned cookie is reverted to unpartitioned if the site -// sends a Set-Cookie with Partitioned but an invalid OT token. -IN_PROC_BROWSER_TEST_F(SubresourcePartitionedCookiesOriginTrialBrowserTest, - InvalidToken) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions( - {/*has_ot_token=*/true, /*valid_ot_token=*/false, /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -// Test that the partitioned cookie is reverted to unpartitioned if the site -// sends a Set-Cookie with Partitioned but do not send an OT token. -IN_PROC_BROWSER_TEST_F(SubresourcePartitionedCookiesOriginTrialBrowserTest, - NoToken) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/true, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -// The partitioned cookie should stay partitioned since we should not check -// the OT token on responses with no Set-Cookie header. -IN_PROC_BROWSER_TEST_F(SubresourcePartitionedCookiesOriginTrialBrowserTest, - NoSetCookie) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/false, - /*has_partitioned=*/true}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - -// The partitioned cookie should stay partitioned since we should not check -// the OT token on responses with a Set-Cookie header without Partitioned. -IN_PROC_BROWSER_TEST_F(SubresourcePartitionedCookiesOriginTrialBrowserTest, - NoPartitioned) { - SetCookie( - "__Host-foo", "bar", CookieUrl(), - net::CookiePartitionKey::FromURLForTesting(GURL("https://example.com"))); - SetTestOptions({/*has_ot_token=*/false, /*valid_ot_token=*/false, - /*has_set_cookie=*/true, - /*has_partitioned=*/false}, - {TopLevelUrl(), CookieUrl()}); - - WaitForPage(TopLevelUrl()); - - auto cookies = GetCookies(CookieUrl()); - EXPECT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - } // namespace } // namespace content
diff --git a/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc index bc33049..b5428a75 100644 --- a/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc +++ b/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.cc
@@ -39,66 +39,70 @@ CreateForWebContents(web_contents); auto* controller = FromWebContents(web_contents); // The controller must not have pre-existing web content. It's supposed - // to have been destroyed by CloseInternal() if it's being reused. + // to have been destroyed by NotifyClosedAndStopObserving() if it's being + // reused. DCHECK(!controller->GetChildWebContents()); return controller; } + DocumentPictureInPictureWindowControllerImpl:: DocumentPictureInPictureWindowControllerImpl(WebContents* web_contents) : WebContentsUserData<DocumentPictureInPictureWindowControllerImpl>( *web_contents), - WebContentsObserver(web_contents) {} + opener_web_contents_(web_contents) {} DocumentPictureInPictureWindowControllerImpl:: ~DocumentPictureInPictureWindowControllerImpl() = default; void DocumentPictureInPictureWindowControllerImpl::SetChildWebContents( - std::unique_ptr<WebContents> child_contents) { + WebContents* child_contents) { // This method should only be called once for a given controller. DCHECK(!child_contents_); - child_contents_ = std::move(child_contents); + child_contents_ = child_contents; + // Start observing immediately, so that we don't miss a destruction event. child_contents_observer_ = std::make_unique<ChildContentsObserver>( GetChildWebContents(), + base::BindOnce(&DocumentPictureInPictureWindowControllerImpl::Close, + weak_factory_.GetWeakPtr(), /*should_pause_video=*/true), base::BindOnce(&DocumentPictureInPictureWindowControllerImpl:: - ForceClosePictureInPicture, + OnChildContentsDestroyed, weak_factory_.GetWeakPtr())); } WebContents* DocumentPictureInPictureWindowControllerImpl::GetChildWebContents() { - return child_contents_.get(); + return child_contents_; } void DocumentPictureInPictureWindowControllerImpl::Show() { - closing_ = false; + // It would nice if we were provided with the child WebContents, but this + // method is shared with non-WebContents video PiP. So, we just have to be + // confident that somebody has set it already. + DCHECK(child_contents_); - EnsureWindow(); - window_->ShowInactive(); + // Start observering our WebContents. Note that this is safe, since we're + // owned by the opener WebContents. + Observe(opener_web_contents_); + + // We're shown automatically by the browser that runs the Picture in Picture + // window, so nothing needs to happen for the window to show up. GetWebContentsImpl()->SetHasPictureInPictureDocument(true); } -void DocumentPictureInPictureWindowControllerImpl::EnsureWindow() { - if (window_) - return; - - window_ = - GetContentClient()->browser()->CreateWindowForDocumentPictureInPicture( - this); -} - void DocumentPictureInPictureWindowControllerImpl::FocusInitiator() { GetWebContentsImpl()->Activate(); } void DocumentPictureInPictureWindowControllerImpl::Close( bool should_pause_video) { - if (!window_ || closing_) + if (!child_contents_) return; - closing_ = true; - window_->Close(); + child_contents_->ClosePage(); - CloseInternal(should_pause_video); + NotifyClosedAndStopObserving(should_pause_video); + // Since we use `child_contents_` to gate everything, make sure it's null. + DCHECK(!child_contents_); } void DocumentPictureInPictureWindowControllerImpl::CloseAndFocusInitiator() { @@ -108,8 +112,8 @@ void DocumentPictureInPictureWindowControllerImpl::OnWindowDestroyed( bool should_pause_video) { - window_ = nullptr; - CloseInternal(should_pause_video); + // We instead watch for the WebContents. + NOTREACHED(); } WebContents* DocumentPictureInPictureWindowControllerImpl::GetWebContents() { @@ -117,44 +121,61 @@ } void DocumentPictureInPictureWindowControllerImpl::WebContentsDestroyed() { - ForceClosePictureInPicture(); + // The opener is being destroyed. + + // Stop observing, and forget `opener_web_contents_`. This will also prevent + // `NotifyAndStopObserving` not to try to send messages to the opener, which + // is not safe during teardown. + Observe(/*web_contents=*/nullptr); + opener_web_contents_ = nullptr; + Close(/*should_pause_video=*/true); } void DocumentPictureInPictureWindowControllerImpl::PrimaryPageChanged(Page&) { - ForceClosePictureInPicture(); + Close(/*should_pause_video=*/true); } -void DocumentPictureInPictureWindowControllerImpl::OnLeavingPictureInPicture( +void DocumentPictureInPictureWindowControllerImpl::NotifyClosedAndStopObserving( bool should_pause_video) { - // TODO(klausw): this method should be called when the parent web contents are - // about to be destroyed, but that currently doesn't seem to be happening. In - // any case, OnWindowDestroyed will do cleanup even when - // OnLeavingPictureInPicture didn't get triggered. - GetWebContentsImpl()->ExitPictureInPicture(); -} + // Do not ask `child_contents_` to close itself; we're called both when the + // opener wants to close and when the child wants to / is in the process of + // closing. In particular, we might be called synchronously from a + // WebContentsObserver. It's okay to unregister, though, since that's + // explicitly allowed by WebContentsObserver even during callbacks. Calling + // ClosePage is not be a good idea. -void DocumentPictureInPictureWindowControllerImpl:: - ForceClosePictureInPicture() { - if (window_) - window_->Close(); - CloseInternal(/*should_pause_video=*/true); -} - -void DocumentPictureInPictureWindowControllerImpl::CloseInternal( - bool should_pause_video) { - // Avoid issues in case `CloseInternal()` gets called twice. - // See PictureInPictureWindowControllerImpl::CloseInternal - if (!window_ || web_contents()->IsBeingDestroyed()) { - // Ensure the child web contents are destroyed even in case a previous - // destruction was incomplete. - child_contents_ = nullptr; + // Avoid issues in case `NotifyClosedAndStopObserving()` gets called twice. + // If we already have no child contents, then there's nothing to do. This is + // the only thing that clears it, so it's already been run. + if (!child_contents_) return; - } - GetWebContentsImpl()->SetHasPictureInPictureDocument(false); - OnLeavingPictureInPicture(should_pause_video); - window_ = nullptr; + // Forget about the child contents. Nothing else should clear + // `child_contents_`; all cleanup should end up going through here. child_contents_ = nullptr; + child_contents_observer_.reset(); + + // If the opener is being destroyed, then don't dispatch anything to it. + if (!GetWebContentsImpl()) + return; + + // Notify the opener, and stop observing it. + GetWebContentsImpl()->SetHasPictureInPictureDocument(false); + // Signal to the media player that |this| is leaving Picture-in-Picture mode. + // The should_pause_video argument signals the user's intent. If true, the + // user explicitly closed the window and any active media should be paused. + // If false, the user used a "return to tab" feature with the expectation + // that any active media will continue playing in the parent tab. + // TODO(klausw): connect this to the requestPictureInPicture API and/or + // onleavepictureinpicture event once that's implemented. + GetWebContentsImpl()->ExitPictureInPicture(); + Observe(/*web_contents=*/nullptr); +} + +void DocumentPictureInPictureWindowControllerImpl::OnChildContentsDestroyed() { + NotifyClosedAndStopObserving(true); + // Make extra sure that the raw pointer is cleared, to avoid UAF. + CHECK(!child_contents_); } WebContentsImpl* @@ -162,35 +183,23 @@ return static_cast<WebContentsImpl*>(web_contents()); } -DocumentOverlayWindow* -DocumentPictureInPictureWindowControllerImpl::GetWindowForTesting() { - return static_cast<DocumentOverlayWindow*>(window_.get()); -} - WEB_CONTENTS_USER_DATA_KEY_IMPL(DocumentPictureInPictureWindowControllerImpl); DocumentPictureInPictureWindowControllerImpl::ChildContentsObserver:: - ChildContentsObserver(WebContents* web_contents, base::OnceClosure close_cb) - : WebContentsObserver(web_contents), close_cb_(std::move(close_cb)) {} + ChildContentsObserver(WebContents* web_contents, + base::OnceClosure force_close_cb, + base::OnceClosure contents_destroyed_cb) + : WebContentsObserver(web_contents), + force_close_cb_(std::move(force_close_cb)), + contents_destroyed_cb_(std::move(contents_destroyed_cb)) {} DocumentPictureInPictureWindowControllerImpl::ChildContentsObserver:: ~ChildContentsObserver() = default; void DocumentPictureInPictureWindowControllerImpl::ChildContentsObserver:: - PrimaryPageChanged(Page&) { - // If we've already tried to close the window, then there's nothing to do. - if (!close_cb_) - return; - - // Don't run `close_cb` from within the observer, since closing `web_contents` - // is not allowed during an observer callback. - content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(close_cb_)); -} - -void DocumentPictureInPictureWindowControllerImpl::ChildContentsObserver:: DidStartNavigation(NavigationHandle* navigation_handle) { // If we've already tried to close the window, then there's nothing to do. - if (!close_cb_) + if (!force_close_cb_) return; // Only care if it's the root of the pip window. @@ -205,9 +214,18 @@ if (navigation_handle->GetURL().IsAboutBlank()) return; - // Don't run `close_cb` from within the observer, since closing `web_contents` - // is not allowed during an observer callback. - content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, std::move(close_cb_)); + // Don't run `force_close_cb` from within the observer, since closing + // `web_contents` is not allowed during an observer callback. + content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, + std::move(force_close_cb_)); +} + +void DocumentPictureInPictureWindowControllerImpl::ChildContentsObserver:: + WebContentsDestroyed() { + // Notify immediately that the child contents have been destroyed -- do not + // post, else something could reference the raw ptr. + if (contents_destroyed_cb_) + std::move(contents_destroyed_cb_).Run(); } } // namespace content
diff --git a/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.h b/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.h index 7482948..7b70416cb 100644 --- a/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.h +++ b/content/browser/picture_in_picture/document_picture_in_picture_window_controller_impl.h
@@ -18,8 +18,6 @@ namespace content { -class DocumentOverlayWindow; -class OverlayWindow; class WebContents; class WebContentsImpl; enum class PictureInPictureResult; @@ -56,10 +54,8 @@ WebContents* GetWebContents() override; // DocumentPictureInPictureWindowController: - void SetChildWebContents( - std::unique_ptr<WebContents> child_contents) override; + void SetChildWebContents(WebContents* child_contents) override; WebContents* GetChildWebContents() override; - DocumentOverlayWindow* GetWindowForTesting() override; // WebContentsObserver: void WebContentsDestroyed() override; @@ -74,54 +70,52 @@ explicit DocumentPictureInPictureWindowControllerImpl( WebContents* web_contents); - // Signal to the media player that |this| is leaving Picture-in-Picture mode. - // The should_pause_video argument signals the user's intent. If true, the - // user explicitly closed the window and any active media should be paused. - // If false, the user used a "return to tab" feature with the expectation - // that any active media will continue playing in the parent tab. - // TODO(klausw): connect this to the requestPictureInPicture API and/or - // onleavepictureinpicture event once that's implemented. - void OnLeavingPictureInPicture(bool should_pause_video); + // Internal method to set the states after the pip has been stopped, whether + // via the page or by the browser. Notifies the opener that pip has ended. + // This is the only thing that should clear `child_contents_`, and it should + // always clear `child_contents_`. + void NotifyClosedAndStopObserving(bool should_pause_video); - // Internal method to set the states after the window was closed, whether via - // the system or by the browser. - void CloseInternal(bool should_pause_video); + // Called when the child WebContents discovers that it's being deleted. + void OnChildContentsDestroyed(); // Returns the web_contents() as a WebContentsImpl*. WebContentsImpl* GetWebContentsImpl(); - void EnsureWindow(); - - // Convenience routine for cases in which we'd like to cause the picture in - // picture window to close. This will close the window, then clean up the - // internal state. - void ForceClosePictureInPicture(); - - // If true, the PiP window is currently in the process of being closed. - bool closing_ = false; - - // The controller owns both the overlay window and the child web contents - // shown within the overlay window. - std::unique_ptr<OverlayWindow> window_; - std::unique_ptr<WebContents> child_contents_; + // The WebContents for the PiP window. If this is null, then we have already + // closed / stopped Picture in Picture. + WebContents* child_contents_ = nullptr; class ChildContentsObserver : public WebContentsObserver { public: - // Will call `close_cb` when `web_contents` navigates. + // Will post `force_close_cb` when `web_contents` navigates, or at similar + // times when the PiP session should end. `contents_destroyed_cb` will be + // called in-line (not posted) when our WebContents has been destroyed and + // the pointer should be discarded. ChildContentsObserver(WebContents* web_contents, - base::OnceClosure close_cb); + base::OnceClosure force_close_cb, + base::OnceClosure contents_destroyed_cb); ~ChildContentsObserver() override; - // Check both `PrimaryPageChanged` and `DidStartNavigation`. We check - // navigations immediately to fail as sooner, rather than fetch and then - // fail on commit. We still check on commit as a fail-safe. - void PrimaryPageChanged(Page&) override; + // Watch for navigations in the child contents, so that we can close the PiP + // window if it navigates away. Some navigations (e.g., same-document) are + // allowed here. void DidStartNavigation(NavigationHandle*) override; + // If the PiP window is destroyed, notify the opener. + void WebContentsDestroyed() override; + private: - base::OnceClosure close_cb_; + // Called, via post, to request that the pip session end. + base::OnceClosure force_close_cb_; + + // Called, without posting, when the raw ptr to our WebContents is about to + // be invalidated. + base::OnceClosure contents_destroyed_cb_; }; + WebContents* opener_web_contents_ = nullptr; + // WebContentsObserver to watch for changes in `child_contents_`. std::unique_ptr<ChildContentsObserver> child_contents_observer_;
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc index bff670e..2d5acf78 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.cc
@@ -185,7 +185,7 @@ const blink::StreamControls& controls, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback, + GenerateStreamsCallback callback, MediaDeviceSaltAndOrigin salt_and_origin) : page_request_id(page_request_id), controls(controls), @@ -200,7 +200,7 @@ const blink::StreamControls controls; bool user_gesture; blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr; - GenerateStreamCallback callback; + GenerateStreamsCallback callback; MediaDeviceSaltAndOrigin salt_and_origin; }; @@ -299,7 +299,7 @@ while (!pending_requests_.empty()) { std::unique_ptr<PendingAccessRequest> request = std::move(pending_requests_.front()); - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id_, render_frame_id_, requester_id_, request->page_request_id, request->controls, std::move(request->salt_and_origin), request->user_gesture, @@ -350,7 +350,8 @@ for (auto& pending_request : pending_requests_) { std::move(pending_request->callback) .Run(blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, - /*label=*/std::string(), /*stream_devices=*/nullptr, + /*label=*/std::string(), + /*stream_devices_set=*/nullptr, /*pan_tilt_zoom_allowed=*/false); } pending_requests_.clear(); @@ -358,12 +359,12 @@ requester_id_); } -void MediaStreamDispatcherHost::GenerateStream( +void MediaStreamDispatcherHost::GenerateStreams( int32_t page_request_id, const blink::StreamControls& controls, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback) { + GenerateStreamsCallback callback) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (!AllowedStreamTypeCombination(controls.audio.stream_type, @@ -386,18 +387,18 @@ GetUIThreadTaskRunner({}).get(), FROM_HERE, base::BindOnce(salt_and_origin_callback_, render_process_id_, render_frame_id_), - base::BindOnce(&MediaStreamDispatcherHost::DoGenerateStream, + base::BindOnce(&MediaStreamDispatcherHost::DoGenerateStreams, weak_factory_.GetWeakPtr(), page_request_id, controls, user_gesture, std::move(audio_stream_selection_info_ptr), std::move(callback))); } -void MediaStreamDispatcherHost::DoGenerateStream( +void MediaStreamDispatcherHost::DoGenerateStreams( int32_t page_request_id, const blink::StreamControls& controls, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback, + GenerateStreamsCallback callback, MediaDeviceSaltAndOrigin salt_and_origin) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -405,7 +406,8 @@ salt_and_origin.origin)) { std::move(callback).Run( blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN, - /*label=*/std::string(), /*stream_devices=*/nullptr, + /*label=*/std::string(), + /*stream_devices_set=*/nullptr, /*pan_tilt_zoom_allowed=*/false); return; } @@ -428,7 +430,7 @@ return; } - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id_, render_frame_id_, requester_id_, page_request_id, controls, std::move(salt_and_origin), user_gesture, std::move(audio_stream_selection_info_ptr), std::move(callback),
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host.h b/content/browser/renderer_host/media/media_stream_dispatcher_host.h index 00162c9..67f7bed 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host.h +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host.h
@@ -74,12 +74,12 @@ void CancelAllRequests(); // mojom::MediaStreamDispatcherHost implementation - void GenerateStream( + void GenerateStreams( int32_t request_id, const blink::StreamControls& controls, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback) override; + GenerateStreamsCallback callback) override; void CancelRequest(int32_t request_id) override; void StopStreamDevice( const std::string& device_id, @@ -114,12 +114,12 @@ const base::UnguessableToken& session_id, GetOpenDeviceCallback callback, MediaDeviceSaltAndOrigin salt_and_origin); - void DoGenerateStream( + void DoGenerateStreams( int32_t request_id, const blink::StreamControls& controls, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback, + GenerateStreamsCallback callback, MediaDeviceSaltAndOrigin salt_and_origin); void DoOpenDevice(int32_t request_id, const std::string& device_id,
diff --git a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc index b1a8dcd..08629d4 100644 --- a/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc
@@ -19,6 +19,7 @@ #include "base/command_line.h" #include "base/containers/queue.h" #include "base/memory/raw_ptr.h" +#include "base/ranges/algorithm.h" #include "base/run_loop.h" #include "base/system/system_monitor.h" #include "base/task/single_thread_task_runner.h" @@ -45,6 +46,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/mediastream/media_stream_request.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "url/gurl.h" @@ -110,9 +112,9 @@ // Accessor to private functions. void CancelAllRequests() { MediaStreamDispatcherHost::CancelAllRequests(); } - void OnGenerateStream(int page_request_id, - const blink::StreamControls& controls) { - MediaStreamDispatcherHost::GenerateStream( + void OnGenerateStreams(int page_request_id, + const blink::StreamControls& controls) { + MediaStreamDispatcherHost::GenerateStreams( page_request_id, controls, false, blink::mojom::StreamSelectionInfo::New( blink::mojom::StreamSelectionStrategy::SEARCH_BY_DEVICE_ID, @@ -120,16 +122,16 @@ base::DoNothing()); } - void OnGenerateStream(int page_request_id, - const blink::StreamControls& controls, - base::OnceClosure quit_closure) { + void OnGenerateStreams(int page_request_id, + const blink::StreamControls& controls, + base::OnceClosure quit_closure) { quit_closures_.push(std::move(quit_closure)); - MediaStreamDispatcherHost::GenerateStream( + MediaStreamDispatcherHost::GenerateStreams( page_request_id, controls, false, blink::mojom::StreamSelectionInfo::New( blink::mojom::StreamSelectionStrategy::SEARCH_BY_DEVICE_ID, absl::nullopt), - base::BindOnce(&MockMediaStreamDispatcherHost::OnStreamGenerated, + base::BindOnce(&MockMediaStreamDispatcherHost::OnStreamsGenerated, base::Unretained(this), page_request_id)); } @@ -175,23 +177,37 @@ } std::string label_; - blink::mojom::StreamDevicesPtr devices_ = blink::mojom::StreamDevices::New(); + blink::mojom::StreamDevicesSetPtr stream_devices_set_; blink::MediaStreamDevice opened_device_; private: // These handler methods do minimal things and delegate to the mock methods. - void OnStreamGenerated(int request_id, - blink::mojom::MediaStreamRequestResult result, - const std::string& label, - blink::mojom::StreamDevicesPtr devices, - bool pan_tilt_zoom_allowed) { + void OnStreamsGenerated(int request_id, + blink::mojom::MediaStreamRequestResult result, + const std::string& label, + blink::mojom::StreamDevicesSetPtr stream_devices_set, + bool pan_tilt_zoom_allowed) { if (result != blink::mojom::MediaStreamRequestResult::OK) { + DCHECK(!stream_devices_set); OnStreamGenerationFailed(request_id, result); return; } - OnStreamGenerationSuccess(request_id, devices->audio_device.has_value(), - devices->video_device.has_value()); + DCHECK(stream_devices_set); + + size_t audio_devices_count = base::ranges::count_if( + stream_devices_set->stream_devices, + [](const blink::mojom::StreamDevicesPtr& devices) { + return devices->audio_device.has_value(); + }); + size_t video_devices_count = base::ranges::count_if( + stream_devices_set->stream_devices, + [](const blink::mojom::StreamDevicesPtr& devices) { + return devices->video_device.has_value(); + }); + + OnStreamGenerationSuccess(request_id, audio_devices_count, + video_devices_count); // Simulate the stream started event back to host for UI testing. OnStreamStarted(label); @@ -200,7 +216,7 @@ quit_closures_.pop(); label_ = label; - devices_ = std::move(devices); + stream_devices_set_ = std::move(stream_devices_set); } void OnStreamGenerationFailed(int request_id, @@ -217,9 +233,11 @@ void OnDeviceStoppedInternal(const std::string& label, const blink::MediaStreamDevice& device) { if (blink::IsVideoInputMediaType(device.type)) - EXPECT_TRUE(device.IsSameDevice(devices_->video_device.value())); + EXPECT_TRUE(device.IsSameDevice( + stream_devices_set_->stream_devices[0]->video_device.value())); if (blink::IsAudioInputMediaType(device.type)) - EXPECT_TRUE(device.IsSameDevice(devices_->audio_device.value())); + EXPECT_TRUE(device.IsSameDevice( + stream_devices_set_->stream_devices[0]->audio_device.value())); OnDeviceStopSuccess(); } @@ -379,14 +397,14 @@ EXPECT_CALL(*host_, OnStreamGenerationSuccess(page_request_id, expected_audio_array_size, expected_video_array_size)); - host_->OnGenerateStream(page_request_id, controls, run_loop.QuitClosure()); + host_->OnGenerateStreams(page_request_id, controls, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_FALSE(DoesContainRawIds(host_->devices_->audio_device)); - EXPECT_FALSE(DoesContainRawIds(host_->devices_->video_device)); + EXPECT_FALSE(DoesContainRawIds(audio_device(/*stream_index=*/0u))); + EXPECT_FALSE(DoesContainRawIds(video_device(/*stream_index=*/0u))); EXPECT_TRUE( - DoesEveryDeviceMapToRawId(host_->devices_->audio_device, origin_)); + DoesEveryDeviceMapToRawId(audio_device(/*stream_index=*/0u), origin_)); EXPECT_TRUE( - DoesEveryDeviceMapToRawId(host_->devices_->video_device, origin_)); + DoesEveryDeviceMapToRawId(video_device(/*stream_index=*/0u), origin_)); } void GenerateStreamAndWaitForFailure( @@ -396,7 +414,7 @@ base::RunLoop run_loop; EXPECT_CALL(*host_, OnStreamGenerationFailure(page_request_id, expected_result)); - host_->OnGenerateStream(page_request_id, controls, run_loop.QuitClosure()); + host_->OnGenerateStreams(page_request_id, controls, run_loop.QuitClosure()); run_loop.Run(); } @@ -408,9 +426,9 @@ blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_FALSE(DoesContainRawIds(host_->devices_->video_device.value())); - EXPECT_TRUE(DoesEveryDeviceMapToRawId(host_->devices_->video_device.value(), - origin_)); + EXPECT_FALSE(DoesContainRawIds(video_device(/*stream_index=*/0u).value())); + EXPECT_TRUE(DoesEveryDeviceMapToRawId( + video_device(/*stream_index=*/0u).value(), origin_)); } void OpenVideoDeviceAndWaitForFailure(int page_request_id, @@ -421,9 +439,9 @@ blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE, run_loop.QuitClosure()); run_loop.Run(); - EXPECT_FALSE(DoesContainRawIds(host_->devices_->video_device.value())); + EXPECT_FALSE(DoesContainRawIds(video_device(/*stream_index=*/0u).value())); EXPECT_FALSE(DoesEveryDeviceMapToRawId( - host_->devices_->video_device.value(), origin_)); + video_device(/*stream_index=*/0u).value(), origin_)); } bool DoesContainRawIds( @@ -478,6 +496,20 @@ host_->GetOpenDevice(request_id, session_id, std::move(callback)); } + const absl::optional<blink::MediaStreamDevice>& audio_device( + size_t stream_index) const { + DCHECK_LT(stream_index, host_->stream_devices_set_->stream_devices.size()); + return host_->stream_devices_set_->stream_devices[stream_index] + ->audio_device; + } + + const absl::optional<blink::MediaStreamDevice>& video_device( + size_t stream_index) const { + DCHECK_LT(stream_index, host_->stream_devices_set_->stream_devices.size()); + return host_->stream_devices_set_->stream_devices[stream_index] + ->video_device; + } + base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<MockMediaStreamDispatcherHost> host_; std::unique_ptr<MediaStreamManager> media_stream_manager_; @@ -499,8 +531,8 @@ SetupFakeUI(true); GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); } TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) { @@ -509,8 +541,8 @@ SetupFakeUI(true); GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_NE(host_->devices_->audio_device, absl::nullopt); - EXPECT_EQ(host_->devices_->video_device, absl::nullopt); + EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_FALSE(video_device(/*stream_index=*/0u).has_value()); } class MediaStreamDispatcherHostStreamTypeCombinationTest @@ -552,7 +584,7 @@ kProcessId, bad_message::MSDH_INVALID_STREAM_TYPE_COMBINATION)) .Times(!kValidCombinations.count(std::make_tuple( controls.audio.stream_type, controls.video.stream_type))); - host_->OnGenerateStream(kPageRequestId, controls); + host_->OnGenerateStreams(kPageRequestId, controls); } INSTANTIATE_TEST_SUITE_P( @@ -583,8 +615,8 @@ SetupFakeUI(true); GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_TRUE(host_->devices_->audio_device.has_value()); - EXPECT_TRUE(host_->devices_->video_device.has_value()); + EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); } TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithDepthVideo) { @@ -603,8 +635,8 @@ // We specified the generation and expect to get // one audio and one depth video stream. - EXPECT_TRUE(host_->devices_->audio_device.has_value()); - EXPECT_TRUE(host_->devices_->video_device.has_value()); + EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); } // This test generates two streams with video only using the same render frame @@ -618,23 +650,27 @@ GenerateStreamAndWaitForResult(kPageRequestId, controls); // Check the latest generated stream. - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label1 = host_->label_; - const std::string device_id1 = host_->devices_->video_device.value().id; + const std::string device_id1 = video_device(/*stream_index=*/0u).value().id; const base::UnguessableToken session_id1 = - host_->devices_->video_device.value().session_id(); + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id(); // Generate second stream. GenerateStreamAndWaitForResult(kPageRequestId + 1, controls); // Check the latest generated stream. - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label2 = host_->label_; - const std::string device_id2 = host_->devices_->video_device.value().id; + const std::string device_id2 = video_device(/*stream_index=*/0u).value().id; const base::UnguessableToken session_id2 = - host_->devices_->video_device.value().session_id(); + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id(); EXPECT_EQ(device_id1, device_id2); EXPECT_EQ(session_id1, session_id2); EXPECT_NE(label1, label2); @@ -648,12 +684,14 @@ // Generate first stream. GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label1 = host_->label_; - const std::string device_id1 = host_->devices_->video_device.value().id; + const std::string device_id1 = video_device(/*stream_index=*/0u).value().id; const base::UnguessableToken session_id1 = - host_->devices_->video_device.value().session_id(); + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id(); // Generate second stream. OpenVideoDeviceAndWaitForResult(kPageRequestId, device_id1); @@ -677,12 +715,14 @@ GenerateStreamAndWaitForResult(kPageRequestId, controls); // Check the latest generated stream. - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label1 = host_->label_; - const std::string device_id1 = host_->devices_->video_device.value().id; + const std::string device_id1 = video_device(/*stream_index=*/0u).value().id; const base::UnguessableToken session_id1 = - host_->devices_->video_device.value().session_id(); + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id(); // Generate second stream from another render frame. host_ = std::make_unique<MockMediaStreamDispatcherHost>( @@ -696,12 +736,14 @@ GenerateStreamAndWaitForResult(kPageRequestId + 1, controls); // Check the latest generated stream. - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label2 = host_->label_; - const std::string device_id2 = host_->devices_->video_device.value().id; + const std::string device_id2 = video_device(/*stream_index=*/0u).value().id; const base::UnguessableToken session_id2 = - host_->devices_->video_device.value().session_id(); + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id(); EXPECT_EQ(device_id1, device_id2); EXPECT_NE(session_id1, session_id2); EXPECT_NE(label1, label2); @@ -721,7 +763,7 @@ OnStreamGenerationFailure( kPageRequestId, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN)); - host_->OnGenerateStream(kPageRequestId, controls, run_loop.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); run_loop.RunUntilIdle(); } @@ -737,7 +779,7 @@ base::Unretained(this))); base::RunLoop run_loop; - host_->OnGenerateStream(kPageRequestId, controls, run_loop.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); int expected_audio_array_size = (controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 : 0; @@ -749,8 +791,8 @@ .Times(1); run_loop.Run(); - EXPECT_NE(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); } TEST_F(MediaStreamDispatcherHostTest, WebContentsFocused) { @@ -764,7 +806,7 @@ base::Unretained(this))); base::RunLoop run_loop; - host_->OnGenerateStream(kPageRequestId, controls, run_loop.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); run_loop.RunUntilIdle(); int expected_audio_array_size = @@ -783,8 +825,8 @@ host_->OnWebContentsFocused(); run_loop.Run(); - EXPECT_NE(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); } // This test request two streams with video only without waiting for the first @@ -804,9 +846,9 @@ } base::RunLoop run_loop1; base::RunLoop run_loop2; - host_->OnGenerateStream(kPageRequestId, controls, run_loop1.QuitClosure()); - host_->OnGenerateStream(kPageRequestId + 1, controls, - run_loop2.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId, controls, run_loop1.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId + 1, controls, + run_loop2.QuitClosure()); run_loop1.Run(); run_loop2.Run(); @@ -829,7 +871,7 @@ SetupFakeUI(true); GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_EQ(host_->devices_->audio_device.value().id, source_id); + EXPECT_EQ(audio_device(/*stream_index=*/0u).value().id, source_id); } for (const std::string& device_id : stub_video_device_ids_) { @@ -840,7 +882,7 @@ controls.video.device_id = source_id; GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_EQ(host_->devices_->video_device.value().id, source_id); + EXPECT_EQ(video_device(/*stream_index=*/0u).value().id, source_id); } } @@ -884,17 +926,19 @@ GenerateStreamAndWaitForResult(kPageRequestId, controls); std::string stream_request_label = host_->label_; - blink::MediaStreamDevice video_device = host_->devices_->video_device.value(); + blink::MediaStreamDevice current_video_device = + video_device(/*stream_index=*/0u).value(); ASSERT_EQ( 1u, media_stream_manager_->GetDevicesOpenedByRequest(stream_request_label) .size()); // Open the same device by Pepper. - OpenVideoDeviceAndWaitForResult(kPageRequestId, video_device.id); + OpenVideoDeviceAndWaitForResult(kPageRequestId, current_video_device.id); std::string open_device_request_label = host_->label_; // Stop the device in the MediaStream. - host_->OnStopStreamDevice(video_device.id, video_device.session_id()); + host_->OnStopStreamDevice(current_video_device.id, + current_video_device.session_id()); EXPECT_EQ( 0u, media_stream_manager_->GetDevicesOpenedByRequest(stream_request_label) @@ -911,13 +955,15 @@ GenerateStreamAndWaitForResult(kPageRequestId, controls); std::string request_label1 = host_->label_; - blink::MediaStreamDevice video_device = host_->devices_->video_device.value(); + blink::MediaStreamDevice current_video_device = + video_device(/*stream_index=*/0u).value(); // Expect that 1 audio and 1 video device has been opened. EXPECT_EQ( 2u, media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size()); - host_->OnStopStreamDevice(video_device.id, video_device.session_id()); + host_->OnStopStreamDevice(current_video_device.id, + current_video_device.session_id()); EXPECT_EQ( 1u, media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size()); @@ -944,22 +990,24 @@ SetupFakeUI(true); GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); // Generate a second stream. EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1)); base::RunLoop run_loop1; - host_->OnGenerateStream(kPageRequestId + 1, controls, - run_loop1.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId + 1, controls, + run_loop1.QuitClosure()); // Stop the video stream device from stream 1 while waiting for the // second stream to be generated. - host_->OnStopStreamDevice(host_->devices_->video_device.value().id, - host_->devices_->video_device.value().session_id()); + host_->OnStopStreamDevice(video_device(/*stream_index=*/0u).value().id, + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id()); run_loop1.Run(); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); } TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreams) { @@ -970,8 +1018,8 @@ // Create multiple GenerateStream requests. size_t streams = 5; for (size_t i = 1; i <= streams; ++i) { - host_->OnGenerateStream(kPageRequestId + i, controls, - run_loop.QuitClosure()); + host_->OnGenerateStreams(kPageRequestId + i, controls, + run_loop.QuitClosure()); } media_stream_manager_->CancelAllRequests(kProcessId, kRenderId, kRequesterId); @@ -1009,8 +1057,8 @@ GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); ASSERT_TRUE(close_callback); EXPECT_CALL(*host_, OnDeviceStopSuccess()); @@ -1024,8 +1072,8 @@ blink::StreamControls controls(true, true); SetupFakeUI(true); GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_NE(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); stub_video_device_ids_.clear(); @@ -1046,15 +1094,21 @@ // Generate first stream. GenerateStreamAndWaitForResult(kPageRequestId, controls); - EXPECT_EQ(host_->devices_->audio_device, absl::nullopt); - EXPECT_NE(host_->devices_->video_device, absl::nullopt); + EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); + EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); const std::string label1 = host_->label_; - const std::string device_id1 = host_->devices_->video_device.value().id; - EXPECT_TRUE(host_->devices_->video_device.value().group_id.has_value()); - const std::string group_id1 = *host_->devices_->video_device.value().group_id; + const std::string device_id1 = video_device(/*stream_index=*/0u).value().id; + EXPECT_TRUE(host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .group_id.has_value()); + const std::string group_id1 = *host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .group_id; EXPECT_FALSE(group_id1.empty()); const base::UnguessableToken session_id1 = - host_->devices_->video_device.value().session_id(); + host_->stream_devices_set_->stream_devices[0] + ->video_device.value() + .session_id(); // Generate second stream. OpenVideoDeviceAndWaitForResult(kPageRequestId, device_id1); @@ -1098,4 +1152,6 @@ loop.Run(); } +// TODO(crbug.com/1300883): Add test cases for multi stream generation. + } // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index 4353e964..35fce10 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -342,12 +342,12 @@ return "INVALID"; } -std::string GetGenerateStreamLogString(int render_process_id, - int render_frame_id, - int requester_id, - int page_request_id) { +std::string GetGenerateStreamsLogString(int render_process_id, + int render_frame_id, + int requester_id, + int page_request_id) { return base::StringPrintf( - "GenerateStream({render_process_id=%d}, {render_frame_id=%d}, " + "GenerateStreams({render_process_id=%d}, {render_frame_id=%d}, " "{requester_id=%d}, {page_request_id=%d})", render_process_id, render_frame_id, requester_id, page_request_id); } @@ -817,7 +817,7 @@ std::move(generate_stream_cb) .Run(MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, /*label=*/std::string(), - /*stream_devices=*/nullptr, + /*stream_devices_set=*/nullptr, /*pan_tilt_zoom_allowed=*/false); } @@ -872,7 +872,7 @@ // Currently it is only used by |DEVICE_ACCESS| type. MediaAccessRequestCallback media_access_request_cb; - GenerateStreamCallback generate_stream_cb; + GenerateStreamsCallback generate_stream_cb; // This callback is used by transferred MediaStreamTracks to access and clone // an existing open MediaStreamDevice (identified by its session_id). If the @@ -1109,7 +1109,7 @@ return label; } -void MediaStreamManager::GenerateStream( +void MediaStreamManager::GenerateStreams( int render_process_id, int render_frame_id, int requester_id, @@ -1118,14 +1118,14 @@ MediaDeviceSaltAndOrigin salt_and_origin, bool user_gesture, StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback generate_stream_cb, + GenerateStreamsCallback generate_stream_cb, DeviceStoppedCallback device_stopped_cb, DeviceChangedCallback device_changed_cb, DeviceRequestStateChangeCallback device_request_state_change_cb, DeviceCaptureHandleChangeCallback device_capture_handle_change_cb) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - SendLogMessage(GetGenerateStreamLogString(render_process_id, render_frame_id, - requester_id, page_request_id)); + SendLogMessage(GetGenerateStreamsLogString(render_process_id, render_frame_id, + requester_id, page_request_id)); std::unique_ptr<DeviceRequest> request = CreateDeviceRequest( render_process_id, render_frame_id, requester_id, page_request_id, controls, blink::MEDIA_GENERATE_STREAM, std::move(salt_and_origin), @@ -1142,7 +1142,7 @@ // as expected. Then we need to finish getUserMedia and let Javascript // access the result. if (std::move(generate_stream_test_callback_).Run(controls)) { - FinalizeGenerateStream(label, request_ptr); + FinalizeGenerateStreams(label, request_ptr); } else { FinalizeRequestFailed(label, request_ptr, MediaStreamRequestResult::INVALID_STATE); @@ -2196,13 +2196,13 @@ return false; } -void MediaStreamManager::FinalizeGenerateStream(const std::string& label, - DeviceRequest* request) { +void MediaStreamManager::FinalizeGenerateStreams(const std::string& label, + DeviceRequest* request) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(request); DCHECK(request->generate_stream_cb); SendLogMessage( - base::StringPrintf("FinalizeGenerateStream({label=%s}, {requester_id=" + base::StringPrintf("FinalizeGenerateStreams({label=%s}, {requester_id=" "%d}, {request_type=%s})", label.c_str(), request->requester_id, RequestTypeToString(request->request_type()))); @@ -2211,6 +2211,10 @@ // user denies mic/camera. SubscribeToPermissionController(label, request); + // TODO(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::StreamDevicesSetPtr stream_devices_set = + blink::mojom::StreamDevicesSet::New(); + stream_devices_set->stream_devices.emplace_back(request->devices.Clone()); // It is safe to bind base::Unretained(this) because MediaStreamManager is // owned by BrowserMainLoop and so outlives the IO thread. // TODO(crbug.com/1314741): Avoid using PTZ permission checks for non-gUM @@ -2226,7 +2230,7 @@ request->devices.video_device, base::BindOnce(std::move(request->generate_stream_cb), MediaStreamRequestResult::OK, label, - request->devices.Clone()))); + std::move(stream_devices_set)))); } void MediaStreamManager::FinalizeGetOpenDevice(const std::string& label, @@ -2342,7 +2346,8 @@ case blink::MEDIA_GENERATE_STREAM: { DCHECK(request->generate_stream_cb); std::move(request->generate_stream_cb) - .Run(result, std::string(), /*stream_devices=*/nullptr, + .Run(result, /*label=*/std::string(), + /*stream_devices_set=*/nullptr, /*pan_tilt_zoom_allowed=*/false); break; } @@ -2362,7 +2367,8 @@ case blink::MEDIA_DEVICE_ACCESS: { DCHECK(request->media_access_request_cb); std::move(request->media_access_request_cb) - .Run(blink::mojom::StreamDevices(), std::move(request->ui_proxy)); + .Run(/*stream_devices_set=*/blink::mojom::StreamDevicesSet(), + std::move(request->ui_proxy)); break; } case blink::MEDIA_DEVICE_UPDATE: { @@ -2467,8 +2473,11 @@ "%d}, {request_type=%s})", label.c_str(), request->requester_id, RequestTypeToString(request->request_type()))); + blink::mojom::StreamDevicesSetPtr cloned_devices = + blink::mojom::StreamDevicesSet::New(); + cloned_devices->stream_devices.emplace_back(devices.Clone()); std::move(request->media_access_request_cb) - .Run(devices, std::move(request->ui_proxy)); + .Run(std::move(*cloned_devices), std::move(request->ui_proxy)); // Delete the request since it is done. DeleteRequest(label); @@ -2596,7 +2605,7 @@ OnStreamStarted(label); break; case blink::MEDIA_GENERATE_STREAM: { - FinalizeGenerateStream(label, request); + FinalizeGenerateStreams(label, request); break; } case blink::MEDIA_GET_OPEN_DEVICE: { @@ -3206,7 +3215,7 @@ } } -void MediaStreamManager::SetGenerateStreamCallbackForTesting( +void MediaStreamManager::SetGenerateStreamsCallbackForTesting( GenerateStreamTestCallback test_callback) { generate_stream_test_callback_ = std::move(test_callback); }
diff --git a/content/browser/renderer_host/media/media_stream_manager.h b/content/browser/renderer_host/media/media_stream_manager.h index fa7774ae..700c42d 100644 --- a/content/browser/renderer_host/media/media_stream_manager.h +++ b/content/browser/renderer_host/media/media_stream_manager.h
@@ -90,15 +90,15 @@ public base::PowerThermalObserver { public: // Callback to deliver the result of a media access request. - using MediaAccessRequestCallback = - base::OnceCallback<void(const blink::mojom::StreamDevices& devices, - std::unique_ptr<MediaStreamUIProxy> ui)>; + using MediaAccessRequestCallback = base::OnceCallback<void( + const blink::mojom::StreamDevicesSet& stream_devices_set, + std::unique_ptr<MediaStreamUIProxy> ui)>; - using GenerateStreamCallback = - base::OnceCallback<void(blink::mojom::MediaStreamRequestResult result, - const std::string& label, - blink::mojom::StreamDevicesPtr stream_devices, - bool pan_tilt_zoom_allowed)>; + using GenerateStreamsCallback = base::OnceCallback<void( + blink::mojom::MediaStreamRequestResult result, + const std::string& label, + blink::mojom::StreamDevicesSetPtr stream_devices_set, + bool pan_tilt_zoom_allowed)>; using OpenDeviceCallback = base::OnceCallback<void(bool success, @@ -203,7 +203,7 @@ // notify clients about request state changes. // TODO(crbug.com/1288839): Package device-related callbacks into a single // struct. - void GenerateStream( + void GenerateStreams( int render_process_id, int render_frame_id, int requester_id, @@ -212,7 +212,7 @@ MediaDeviceSaltAndOrigin salt_and_origin, bool user_gesture, blink::mojom::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback generate_stream_cb, + GenerateStreamsCallback generate_stream_cb, DeviceStoppedCallback device_stopped_cb, DeviceChangedCallback device_changed_cb, DeviceRequestStateChangeCallback device_request_state_change_cb, @@ -408,7 +408,7 @@ void StopRemovedDevice(blink::mojom::MediaDeviceType type, const blink::WebMediaDeviceInfo& media_device_info); - void SetGenerateStreamCallbackForTesting( + void SetGenerateStreamsCallbackForTesting( GenerateStreamTestCallback test_callback); // This method is called when all tracks are started. @@ -574,7 +574,8 @@ blink::MediaStreamDevice* existing_device, MediaRequestState* existing_request_state) const; - void FinalizeGenerateStream(const std::string& label, DeviceRequest* request); + void FinalizeGenerateStreams(const std::string& label, + DeviceRequest* request); void FinalizeGetOpenDevice(const std::string& label, DeviceRequest* request); void PanTiltZoomPermissionChecked( const std::string& label,
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc index 0cd06491..89965452 100644 --- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc +++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -220,9 +220,10 @@ ~MediaStreamManagerTest() override { audio_manager_->Shutdown(); } MOCK_METHOD1(Response, void(int index)); - void ResponseCallback(int index, - const blink::mojom::StreamDevices& devices, - std::unique_ptr<MediaStreamUIProxy> ui_proxy) { + void ResponseCallback( + int index, + const blink::mojom::StreamDevicesSet& stream_devices_set, + std::unique_ptr<MediaStreamUIProxy> ui_proxy) { Response(index); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop_.QuitClosure()); @@ -265,8 +266,8 @@ blink::MediaStreamDevice video_device; blink::MediaStreamDevice audio_device; - MediaStreamManager::GenerateStreamCallback generate_stream_callback = - base::BindOnce(GenerateStreamCallback, &run_loop_, request_audio, + MediaStreamManager::GenerateStreamsCallback generate_stream_callback = + base::BindOnce(GenerateStreamsCallback, &run_loop_, request_audio, true /* request_video */, &audio_device, &video_device); base::MockCallback<MediaStreamManager::DeviceStoppedCallback> stopped_callback; @@ -293,7 +294,7 @@ OnMediaRequestStateChanged(_, _, _, _, expected_type, MEDIA_REQUEST_STATE_DONE)); } - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id, render_frame_id, requester_id, page_request_id, controls, MediaDeviceSaltAndOrigin(), false /* user_gesture */, StreamSelectionInfo::New( @@ -335,7 +336,7 @@ } } - static void GenerateStreamCallback( + static void GenerateStreamsCallback( base::RunLoop* wait_loop, bool request_audio, bool request_video, @@ -343,20 +344,28 @@ blink::MediaStreamDevice* video_device, blink::mojom::MediaStreamRequestResult result, const std::string& label, - const blink::mojom::StreamDevicesPtr devices, + blink::mojom::StreamDevicesSetPtr stream_devices_set, bool pan_tilt_zoom_allowed) { + // TODO(crbug.com/1300883): Generalize to multiple streams. + DCHECK_EQ(stream_devices_set->stream_devices.size(), 1u); if (request_audio) { - ASSERT_TRUE(devices->audio_device.has_value()); - *audio_device = devices->audio_device.value(); + ASSERT_TRUE( + stream_devices_set->stream_devices[0]->audio_device.has_value()); + *audio_device = + stream_devices_set->stream_devices[0]->audio_device.value(); } else { - ASSERT_FALSE(devices->audio_device.has_value()); + ASSERT_FALSE( + stream_devices_set->stream_devices[0]->audio_device.has_value()); } if (request_video) { - ASSERT_TRUE(devices->video_device.has_value()); - *video_device = devices->video_device.value(); + ASSERT_TRUE( + stream_devices_set->stream_devices[0]->video_device.has_value()); + *video_device = + stream_devices_set->stream_devices[0]->video_device.value(); } else { - ASSERT_FALSE(devices->video_device.has_value()); + ASSERT_FALSE( + stream_devices_set->stream_devices[0]->video_device.has_value()); } wait_loop->Quit(); @@ -386,8 +395,8 @@ base::RunLoop run_loop; blink::MediaStreamDevice audio_device; - MediaStreamManager::GenerateStreamCallback generate_stream_callback = - base::BindOnce(GenerateStreamCallback, &run_loop, true, false, + MediaStreamManager::GenerateStreamsCallback generate_stream_callback = + base::BindOnce(GenerateStreamsCallback, &run_loop, true, false, &audio_device, nullptr); MediaStreamManager::DeviceStoppedCallback stopped_callback; MediaStreamManager::DeviceChangedCallback changed_callback; @@ -398,7 +407,7 @@ StreamSelectionInfoPtr info = StreamSelectionInfo::New(strategy, session_id); - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id, render_frame_id, requester_id, page_request_id, controls, MediaDeviceSaltAndOrigin(), false /* user_gesture */, std::move(info), std::move(generate_stream_callback), @@ -737,10 +746,10 @@ controls.video.stream_type = blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE; - MediaStreamManager::GenerateStreamCallback generate_stream_callback = + MediaStreamManager::GenerateStreamsCallback generate_stream_callback = base::BindOnce([](blink::mojom::MediaStreamRequestResult result, const std::string& label, - blink::mojom::StreamDevicesPtr devices, + blink::mojom::StreamDevicesSetPtr stream_devices_set, bool pan_tilt_zoom_allowed) {}); EXPECT_CALL( *media_observer_, @@ -751,7 +760,7 @@ const int render_frame_id = 0; const int requester_id = 0; const int page_request_id = 0; - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id, render_frame_id, requester_id, page_request_id, controls, MediaDeviceSaltAndOrigin(), false /* user_gesture */, StreamSelectionInfo::New( @@ -785,8 +794,8 @@ const int page_request_id = 1; blink::MediaStreamDevice video_device; - MediaStreamManager::GenerateStreamCallback generate_stream_callback = - base::BindOnce(GenerateStreamCallback, &run_loop_, + MediaStreamManager::GenerateStreamsCallback generate_stream_callback = + base::BindOnce(GenerateStreamsCallback, &run_loop_, false /* request_audio */, true /* request_video */, nullptr, &video_device); MediaStreamManager::DeviceStoppedCallback stopped_callback = @@ -805,7 +814,7 @@ MediaStreamManager::DeviceCaptureHandleChangeCallback capture_handle_change_callback; - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id, render_frame_id, requester_id, page_request_id, controls, MediaDeviceSaltAndOrigin(), false /* user_gesture */, StreamSelectionInfo::New( @@ -844,8 +853,8 @@ const int page_request_id = 1; blink::MediaStreamDevice video_device; - MediaStreamManager::GenerateStreamCallback generate_stream_callback = - base::BindOnce(GenerateStreamCallback, &run_loop_, + MediaStreamManager::GenerateStreamsCallback generate_stream_callback = + base::BindOnce(GenerateStreamsCallback, &run_loop_, false /* request_audio */, true /* request_video */, nullptr, &video_device); MediaStreamManager::DeviceStoppedCallback stopped_callback; @@ -872,7 +881,7 @@ MediaStreamManager::DeviceCaptureHandleChangeCallback capture_handle_change_callback; - media_stream_manager_->GenerateStream( + media_stream_manager_->GenerateStreams( render_process_id, render_frame_id, requester_id, page_request_id, controls, MediaDeviceSaltAndOrigin(), false /* user_gesture */, StreamSelectionInfo::New( @@ -989,4 +998,6 @@ base::RunLoop().RunUntilIdle(); } +// TODO(crbug.com/1300883): Add test cases for multi stream generation. + } // namespace content
diff --git a/content/browser/renderer_host/media/media_stream_ui_proxy.h b/content/browser/renderer_host/media/media_stream_ui_proxy.h index 75ce303..0a261c7 100644 --- a/content/browser/renderer_host/media/media_stream_ui_proxy.h +++ b/content/browser/renderer_host/media/media_stream_ui_proxy.h
@@ -170,7 +170,7 @@ private: // This is used for RequestAccess(). - // TODO(crbug/1313021): Use blink::mojom::StreamDevices instead of + // TODO(crbug.com/1313021): Use blink::mojom::StreamDevices instead of // blink::MediaStreamDevices. blink::MediaStreamDevices devices_;
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 875b85e..c91c101 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -29,7 +29,6 @@ #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/system/sys_info.h" -#include "base/time/time.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_conversion_helper.h" #include "build/build_config.h" @@ -110,14 +109,12 @@ #include "content/public/common/url_constants.h" #include "content/public/common/url_utils.h" #include "mojo/public/cpp/system/data_pipe.h" -#include "net/base/features.h" #include "net/base/filename_util.h" #include "net/base/ip_endpoint.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" -#include "net/cookies/parsed_cookie.h" #include "net/http/http_request_headers.h" #include "net/http/http_status_code.h" #include "net/url_request/redirect_info.h" @@ -150,9 +147,6 @@ #include "third_party/blink/public/common/frame/frame_owner_element_type.h" #include "third_party/blink/public/common/navigation/navigation_params_mojom_traits.h" #include "third_party/blink/public/common/navigation/navigation_policy.h" -#include "third_party/blink/public/common/origin_trials/trial_token.h" -#include "third_party/blink/public/common/origin_trials/trial_token_result.h" -#include "third_party/blink/public/common/origin_trials/trial_token_validator.h" #include "third_party/blink/public/common/permissions_policy/document_policy.h" #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h" #include "third_party/blink/public/common/security/address_space_feature.h" @@ -948,10 +942,11 @@ } // If the response does not contain an Accept-CH header, then remove the -// Sec-CH-UA-Reduced or Sec-CH-UA-Full client hint from the Accept-CH cache, if -// it exists, for the response origin. The `client_hints` vector also has -// kUaReduced or kFullUserAgent removed from it if the Accept-CH response header -// doesn't exist, and cookies are un-partitioned if that feature is enabled. +// Sec-CH-UA-Reduced, Sec-CH-UA-Full, or Sec-CH-Partitioned-Cookies, client +// hint from the Accept-CH cache, if it exists, for the response origin. The +// `client_hints` vector also has kUaReduced or kFullUserAgent removed from it +// if the Accept-CH response header doesn't exist, and cookies are +// un-partitioned if that feature is enabled. void RemoveOriginTrialHintsFromAcceptCH( const GURL& url, ClientHintsControllerDelegate* delegate, @@ -963,16 +958,18 @@ if (!response || response->parsed_headers->accept_ch) return; - // For Chrome to continue to send Sec-CH-UA-Reduced or Sec-CH-UA-Full, the - // server must continue replying with: + // For Chrome to continue to send Sec-CH-UA-Reduced, Sec-CH-UA-Full, or + // Sec-CH-Partitioned-Cookies, the server must continue replying with: // - a valid Origin Trial token. - // - Accept-CH header with Sec-CH-UA-Reduced or Sec-CH-UA-Full as a value. + // - Accept-CH header with Sec-CH-UA-Reduced, Sec-CH-UA-Full, or + // Sec-CH-Partitioned-Cookies as a value. // // Here, it did not. So it gets removed from the persisted client hints // for the next request. std::vector<network::mojom::WebClientHintsType> hints_to_remove = { network::mojom::WebClientHintsType::kUAReduced, - network::mojom::WebClientHintsType::kFullUserAgent}; + network::mojom::WebClientHintsType::kFullUserAgent, + network::mojom::WebClientHintsType::kPartitionedCookies}; bool need_update_storage = false; for (const auto& hint : hints_to_remove) { if (base::Contains(client_hints, hint)) { @@ -985,46 +982,10 @@ frame_tree_node->GetParentOrOuterDocument(), delegate, client_hints); } -} -bool IsValidPartitionedCookiesOriginTrial( - const GURL& url, - const net::HttpResponseHeaders* response_headers) { - blink::TrialTokenValidator validator; - if (!validator.IsTrialPossibleOnOrigin(url)) - return false; - // Since third-party requests can participate in the CHIPS origin trial and - // typically the Origin-Trial header is reserved for requests from the - // top-level site, we cannot use validator.RequestEnablesFeature here. - url::Origin origin = url::Origin::Create(url); - url::Origin third_party_origins[] = {url::Origin::Create(url)}; - size_t iter = 0; - std::string token; - base::Time now(base::Time::Now()); - while (response_headers->EnumerateHeader(&iter, "Origin-Trial", &token)) { - blink::TrialTokenResult result = - validator.ValidateToken(token, origin, third_party_origins, now); - if (result.Status() == blink::OriginTrialTokenStatus::kSuccess) { - if (result.ParsedToken()->feature_name() == "PartitionedCookies") { - return true; - } - } - } - return false; -} - -// For the partitioned cookies OT, we check if the response has a Set-Cookie -// header with a partitioned cookie. If it does, we validate the OT token -// otherwise we convert the URL's partitioned cookies to unpartitioned. -void CheckPartitionedCookiesOriginTrial( - const network::mojom::URLResponseHead* response, - const GURL& url, - network::mojom::CookieManager* cookie_manager) { - if (!base::FeatureList::IsEnabled(net::features::kPartitionedCookies) || - !response || !cookie_manager || !response->has_partitioned_cookie) { - return; - } - if (!IsValidPartitionedCookiesOriginTrial(url, response->headers.get())) { + if (auto* cookie_manager = frame_tree_node->current_frame_host() + ->GetStoragePartition() + ->GetCookieManagerForBrowserProcess()) { cookie_manager->ConvertPartitionedCookiesToUnpartitioned(url); } } @@ -4754,11 +4715,6 @@ commit_params_->enabled_client_hints, frame_tree_node_); } - CheckPartitionedCookiesOriginTrial(response(), common_params_->url, - frame_tree_node_->current_frame_host() - ->GetStoragePartition() - ->GetCookieManagerForBrowserProcess()); - // Generate a UKM source and track it on NavigationRequest. This will be // passed down to the blink::Document to be created, if any, and used for UKM // source creation when navigation has successfully committed.
diff --git a/content/browser/speech/speech_recognition_manager_impl.cc b/content/browser/speech/speech_recognition_manager_impl.cc index 4e4a2880..63f4c65 100644 --- a/content/browser/speech/speech_recognition_manager_impl.cc +++ b/content/browser/speech/speech_recognition_manager_impl.cc
@@ -295,7 +295,7 @@ void SpeechRecognitionManagerImpl::MediaRequestPermissionCallback( int session_id, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, std::unique_ptr<MediaStreamUIProxy> stream_ui) { DCHECK_CURRENTLY_ON(BrowserThread::IO); @@ -303,8 +303,13 @@ if (iter == sessions_.end()) return; + // The SpeechRecognictionManager is not used with multiple streams + // which is only supported in combination with the getDisplayMediaSet API. + DCHECK_EQ(stream_devices_set.stream_devices.size(), 1u); + DCHECK(stream_devices_set.stream_devices[0]); blink::MediaStreamDevices devices_list = - blink::StreamDevicesToMediaStreamDevicesList(devices); + blink::StreamDevicesToMediaStreamDevicesList( + *stream_devices_set.stream_devices[0]); const bool is_allowed = !devices_list.empty(); if (is_allowed) { // Copy the approved devices array to the context for UI indication.
diff --git a/content/browser/speech/speech_recognition_manager_impl.h b/content/browser/speech/speech_recognition_manager_impl.h index 91affb4..50361b3 100644 --- a/content/browser/speech/speech_recognition_manager_impl.h +++ b/content/browser/speech/speech_recognition_manager_impl.h
@@ -145,7 +145,7 @@ // users deny the request. void MediaRequestPermissionCallback( int session_id, - const blink::mojom::StreamDevices& devices, + const blink::mojom::StreamDevicesSet& stream_devices_set, std::unique_ptr<MediaStreamUIProxy> stream_ui); // Entry point for pushing any external event into the session handling FSM.
diff --git a/content/browser/web_package/subresource_loading_origin_trial.md b/content/browser/web_package/subresource_loading_origin_trial.md index a04540d..7ad5dd7 100644 --- a/content/browser/web_package/subresource_loading_origin_trial.md +++ b/content/browser/web_package/subresource_loading_origin_trial.md
@@ -10,7 +10,9 @@ ## Origin Trial timeline -- Chrome M90-M101 +- Chrome M90-M101, M103-M104 + + Note: M102 is excluded. ## How to create a bundle @@ -58,15 +60,14 @@ [the latest Web Bundles format](https://wpack-wg.github.io/bundled-responses/draft-ietf-wpack-bundled-responses.html) (called as "b2"). -## What works in Chrome M90 or later. +## The old APIs -Chrome M90+ supports a `<link>`-based API, a `urn:uuid` URL and the old +Chrome M90 - M101 supported `<link>`-based API, a `urn:uuid` URL and the old WebBundle format ["b1"](https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html). -They are still supported in Chrome M97+, however, we strongly recommend origin -trial participants to use new APIs in Chrome M97+. +however, they were removed in M102. -This guide no longer covers the old APIs, which we plan to remove eventually. +This guide no longer covers the old APIs. If you are still using the old APIs, Please see [the previous revision of this guide](https://source.chromium.org/chromium/chromium/src/+/main:content/browser/web_package/subresource_loading_origin_trial.md;drc=1454cf984a485a136c4a525ab79f6cf0a3877504) for the old APIs and [the migration guide](https://docs.google.com/document/d/1hAl7jb-a9WET_mSeHBD9HxIBUwUe65Dbyn6u6LRB61s/edit?usp=sharing).
diff --git a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc index 7e28802..4cca073 100644 --- a/content/browser/webrtc/webrtc_getusermedia_browsertest.cc +++ b/content/browser/webrtc/webrtc_getusermedia_browsertest.cc
@@ -80,6 +80,9 @@ return function_name + "({" + audio_constraint + video_constraint + "});"; } +// TODO(crbug.com/1327666): Bring back when +// WebRtcGetUserMediaBrowserTest.DisableLocalEchoParameter is fixed. +#if 0 std::string GenerateGetUserMediaWithDisableLocalEcho( const std::string& function_name, const std::string& disable_local_echo) { @@ -96,6 +99,7 @@ const blink::StreamControls& controls) { return expect_value == controls.disable_local_echo; } +#endif } // namespace @@ -640,6 +644,10 @@ ExecuteJavascriptAndWaitForOk(call); } +// TODO(crbug.com/1327666): Fix this test. It seems to be broken (no audio / +// video tracks are requested; "uncaught (in promise) undefined)") and was false +// positive before disabling. +#if 0 IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, DisableLocalEchoParameter) { base::CommandLine::ForCurrentProcess()->AppendSwitch( @@ -652,21 +660,22 @@ MediaStreamManager* manager = BrowserMainLoop::GetInstance()->media_stream_manager(); - manager->SetGenerateStreamCallbackForTesting( + manager->SetGenerateStreamsCallbackForTesting( base::BindOnce(&VerifyDisableLocalEcho, false)); std::string call = GenerateGetUserMediaWithDisableLocalEcho( "getUserMediaAndExpectSuccess", "false"); ExecuteJavascriptAndWaitForOk(call); - manager->SetGenerateStreamCallbackForTesting( + manager->SetGenerateStreamsCallbackForTesting( base::BindOnce(&VerifyDisableLocalEcho, true)); call = GenerateGetUserMediaWithDisableLocalEcho( "getUserMediaAndExpectSuccess", "true"); ExecuteJavascriptAndWaitForOk(call); - manager->SetGenerateStreamCallbackForTesting( + manager->SetGenerateStreamsCallbackForTesting( MediaStreamManager::GenerateStreamTestCallback()); } +#endif IN_PROC_BROWSER_TEST_F(WebRtcGetUserMediaBrowserTest, GetAudioSettingsDefault) { ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index a5a33ea4..44b16d2 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -406,6 +406,8 @@ blink::features::kClientHintThirdPartyDelegation}, {"UserAgentReduction", blink::features::kReduceUserAgent}, {"UserAgentFull", blink::features::kFullUserAgent}, + {"ClientHintPartitiondCookies", + blink::features::kClientHintsPartitionedCookies}, {"WindowPlacement", blink::features::kWindowPlacement}, {"WindowPlacementFullscreenOnScreensChange", blink::features::kWindowPlacementFullscreenOnScreensChange},
diff --git a/content/public/browser/document_picture_in_picture_window_controller.h b/content/public/browser/document_picture_in_picture_window_controller.h index 0e7c5e79..8fc1e2a 100644 --- a/content/public/browser/document_picture_in_picture_window_controller.h +++ b/content/public/browser/document_picture_in_picture_window_controller.h
@@ -5,27 +5,21 @@ #ifndef CONTENT_PUBLIC_BROWSER_DOCUMENT_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_H_ #define CONTENT_PUBLIC_BROWSER_DOCUMENT_PICTURE_IN_PICTURE_WINDOW_CONTROLLER_H_ -#include <memory> // for std::unique_ptr - #include "content/common/content_export.h" #include "content/public/browser/picture_in_picture_window_controller.h" namespace content { -class DocumentOverlayWindow; class WebContents; class DocumentPictureInPictureWindowController : public PictureInPictureWindowController { public: - // Takes ownership of the WebContents for Document Picture-in-Picture. - virtual void SetChildWebContents( - std::unique_ptr<WebContents> child_contents) = 0; + // Sets the contents inside the Picture in Picture window. + virtual void SetChildWebContents(WebContents* child_contents) = 0; // Returns the child WebContents for DocumentPip virtual WebContents* GetChildWebContents() = 0; - virtual DocumentOverlayWindow* GetWindowForTesting() = 0; - protected: // Use PictureInPictureWindowController::GetOrCreateForWebContents() to // create an instance.
diff --git a/content/public/test/url_loader_interceptor.cc b/content/public/test/url_loader_interceptor.cc index 68ed149..5f951b0 100644 --- a/content/public/test/url_loader_interceptor.cc +++ b/content/public/test/url_loader_interceptor.cc
@@ -30,7 +30,6 @@ #include "content/public/test/mock_render_process_host.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" -#include "net/cookies/parsed_cookie.h" #include "net/http/http_util.h" #include "net/test/embedded_test_server/request_handler_util.h" #include "services/network/public/cpp/features.h" @@ -586,14 +585,6 @@ network::PopulateParsedHeaders(response->headers.get(), *url); } response->ssl_info = std::move(ssl_info); - size_t iter = 0; - std::string cookie_line; - while (info.headers->EnumerateHeader(&iter, "Set-Cookie", &cookie_line)) { - if (net::ParsedCookie(cookie_line).IsPartitioned()) { - response->has_partitioned_cookie = true; - break; - } - } mojo::ScopedDataPipeProducerHandle producer_handle; mojo::ScopedDataPipeConsumerHandle consumer_handle;
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index 47d92db5..3fa257f 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4 @@ -124,11 +123,6 @@ # since Windows 8 is no longer tested. crbug.com/524808 [ win8 nvidia ] ContextLost_WebGLContextLostFromSelectElement [ Skip ] -# Flaky on Mac 10.7 and 10.8 resulting in crashes during browser -# startup, so skip this test in those configurations. -crbug.com/497411 [ mountainlion debug ] ContextLost_WebGLContextLostFromSelectElement [ Skip ] -crbug.com/498149 [ lion debug ] ContextLost_WebGLContextLostFromSelectElement [ Skip ] - # Too difficult to make this test work on Mac and Android for now. Disabling # GLES3 support at the GL bindings level doesn't work there yet. crbug.com/923134 [ mac ] ContextLost_WebGL2Blocked [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt index b6389f0..d875dda4 100644 --- a/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/gpu_process_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt index 78f5010..01e4676 100644 --- a/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/hardware_accelerated_feature_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt index acd30df..bc6593b 100644 --- a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt index 78f5010..01e4676 100644 --- a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt index 23761a9..e73f76c 100644 --- a/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/mediapipe_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
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 4d79deb..9bf5d44 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4 @@ -175,9 +174,6 @@ crbug.com/852089 [ chromeos ] Pixel_WebGPU* [ Skip ] crbug.com/852089 [ fuchsia ] Pixel_WebGPU* [ Skip ] -# WebGPU's copyExternalImage is broken on mac10.12 -crbug.com/1311710 [ mac-10.12 ] Pixel_WebGPUCopyExternalImage* [ Failure ] - # WebGPU SwiftShader tests are only supported on Linux with SkiaRenderer Vulkan. crbug.com/1307787 [ linux skia-renderer-gl ] Pixel_WebGPUSwiftShader_WebGPU* [ Skip ] crbug.com/1307787 [ linux skia-renderer-dawn ] Pixel_WebGPUSwiftShader_WebGPU* [ Skip ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt index d3622e3..988133d4 100644 --- a/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/power_measurement_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt index 1b3a5bc..bb8b803 100644 --- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
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 c1b12e0..ef07ac3 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
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt index 3cf655f..226fb81d 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 6cc7670..dc76a97 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4 @@ -497,31 +496,6 @@ crbug.com/1230781 [ mac amd-0x679e ] conformance/canvas/to-data-url-test.html [ Failure ] crbug.com/1037958 [ mac amd-0x679e ] conformance2/transform_feedback/switching-objects.html [ RetryOnFailure ] -# The transformfeedback tests are specialized for two different AMD -# GPUs because of different failure modes on each. -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_lines.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_points.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_lines.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_points.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_triangles.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/point_size.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/position.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ RetryOnFailure ] -crbug.com/1027605 [ mac amd-0x6821 no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ RetryOnFailure ] crbug.com/636648 [ mac amd ] deqp/functional/gles3/shaderindexing/mat_01.html [ RetryOnFailure ] crbug.com/642822 [ mac amd ] conformance2/rendering/clipping-wide-points.html [ Failure ] @@ -566,12 +540,12 @@ crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-disabled ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html [ Failure ] crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-disabled ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html [ Failure ] crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-disabled ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html [ Failure ] -crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html [ Failure ] -crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html [ Failure ] -crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html [ Failure ] -crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html [ Failure ] -crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html [ Failure ] -crbug.com/1278935 [ monterey amd-0x6821 skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html [ Failure ] +crbug.com/1278935 [ monterey amd skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_00.html [ Failure ] +crbug.com/1278935 [ monterey amd skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_2d_array_01.html [ Failure ] +crbug.com/1278935 [ monterey amd skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_00.html [ Failure ] +crbug.com/1278935 [ monterey amd skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/teximage3d_pbo_3d_01.html [ Failure ] +crbug.com/1278935 [ monterey amd skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_00.html [ Failure ] +crbug.com/1278935 [ monterey amd skia-renderer-gl angle-opengl ] deqp/functional/gles3/texturespecification/texsubimage3d_pbo_3d_01.html [ Failure ] # Mac Intel crbug.com/678526 [ mac intel ] conformance2/rendering/framebuffer-texture-level1.html [ Failure ] @@ -628,30 +602,8 @@ # Mac Pro # AMD Radeon HD 7800 GPU (1002:679e) -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_lines.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_points.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/array_interleaved_triangles.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_lines.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_points.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/array_separate_triangles.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_lines.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_points.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_interleaved_triangles.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_lines.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_points.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/basic_types_separate_triangles.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_centroid.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_flat.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/interpolation_smooth.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/point_size.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/position.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_lines.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/random_interleaved_triangles.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_lines.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ] -crbug.com/1027605 [ mac amd-0x679e no-passthrough ] deqp/functional/gles3/transformfeedback/random_separate_triangles.html [ Failure ] -crbug.com/1276186 [ mac amd-0x679e no-passthrough ] conformance/rendering/clear-default-framebuffer-with-scissor-test.html [ Failure ] +crbug.com/1276186 [ mac amd-0x679e angle-opengl passthrough ] conformance/rendering/clear-default-framebuffer-with-scissor-test.html [ Failure ] +crbug.com/1240443 [ mac amd-0x679e angle-opengl passthrough ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ] # Mac / M1 / OpenGL crbug.com/1130112 [ mac apple-apple-m1 passthrough angle-opengl ] deqp/functional/gles3/texturefiltering/cube_combinations_00.html [ Failure ] @@ -938,7 +890,7 @@ #[ win nvidia-0x1 debug angle-opengl ] WebglExtension_test_9 [ Failure ] # Conflicts if between a generic os condition and a specific version -#[ sierra nvidia debug angle-opengl ] WebglExtension_test_10 [ Failure ] +#[ highsierra nvidia debug angle-opengl ] WebglExtension_test_10 [ Failure ] #[ mac nvidia debug angle-opengl ] WebglExtension_test_10 [ Failure ] #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index f35821c9..48e659d 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -5,8 +5,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4 @@ -470,7 +469,7 @@ # Mac AMD failures crbug.com/642822 [ mac amd ] conformance/rendering/clipping-wide-points.html [ Failure ] crbug.com/1230781 [ mac amd-0x679e ] conformance/canvas/to-data-url-test.html [ Failure ] -crbug.com/1236072 [ mac amd-0x679e angle-opengl ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ] +crbug.com/1240443 [ mac amd-0x679e angle-opengl ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ] crbug.com/1227774 [ mac amd angle-opengl ] conformance/glsl/misc/shader-with-non-reserved-words.html [ RetryOnFailure ] crbug.com/1276186 [ mac amd-0x679e angle-opengl ] conformance/rendering/clear-default-framebuffer-with-scissor-test.html [ Failure ]
diff --git a/content/test/gpu/validate_tag_consistency.py b/content/test/gpu/validate_tag_consistency.py index 7ad36140..eeb693a 100755 --- a/content/test/gpu/validate_tag_consistency.py +++ b/content/test/gpu/validate_tag_consistency.py
@@ -18,8 +18,7 @@ # chromeos # fuchsia # linux ubuntu -# mac bigsur catalina lion highsierra mac-10.12 mojave monterey -# mountainlion sierra +# mac highsierra mojave catalina bigsur monterey # win win8 win10 ] # Devices # tags: [ android-nexus-5 android-nexus-5x android-pixel-2 android-pixel-4
diff --git a/gpu/command_buffer/client/raster_cmd_helper_autogen.h b/gpu/command_buffer/client/raster_cmd_helper_autogen.h index e445c02..99d3cd2 100644 --- a/gpu/command_buffer/client/raster_cmd_helper_autogen.h +++ b/gpu/command_buffer/client/raster_cmd_helper_autogen.h
@@ -88,7 +88,10 @@ } } -void BeginRasterCHROMIUMImmediate(GLuint sk_color, +void BeginRasterCHROMIUMImmediate(GLfloat r, + GLfloat g, + GLfloat b, + GLfloat a, GLboolean needs_clear, GLuint msaa_sample_count, gpu::raster::MsaaMode msaa_mode, @@ -101,7 +104,7 @@ GetImmediateCmdSpaceTotalSize<raster::cmds::BeginRasterCHROMIUMImmediate>( size); if (c) { - c->Init(sk_color, needs_clear, msaa_sample_count, msaa_mode, + c->Init(r, g, b, a, needs_clear, msaa_sample_count, msaa_mode, can_use_lcd_text, visible, mailbox); } }
diff --git a/gpu/command_buffer/client/raster_implementation.cc b/gpu/command_buffer/client/raster_implementation.cc index c918aba..9aa9553 100644 --- a/gpu/command_buffer/client/raster_implementation.cc +++ b/gpu/command_buffer/client/raster_implementation.cc
@@ -1340,7 +1340,7 @@ } void RasterImplementation::BeginRasterCHROMIUM( - GLuint sk_color, + SkColor4f sk_color_4f, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode, @@ -1350,11 +1350,12 @@ const GLbyte* mailbox) { DCHECK(!raster_properties_); - helper_->BeginRasterCHROMIUMImmediate(sk_color, needs_clear, - msaa_sample_count, msaa_mode, - can_use_lcd_text, visible, mailbox); + helper_->BeginRasterCHROMIUMImmediate( + sk_color_4f.fR, sk_color_4f.fG, sk_color_4f.fB, sk_color_4f.fA, + needs_clear, msaa_sample_count, msaa_mode, can_use_lcd_text, visible, + mailbox); - raster_properties_.emplace(sk_color, can_use_lcd_text, + raster_properties_.emplace(sk_color_4f, can_use_lcd_text, color_space.ToSkColorSpace()); } @@ -1398,7 +1399,8 @@ preamble.post_translation = post_translate; preamble.post_scale = post_scale; preamble.requires_clear = requires_clear; - preamble.background_color = raster_properties_->background_color; + // TODO(aaronhk): change the preamble to float color + preamble.background_color = raster_properties_->background_color.toSkColor(); // Wrap the provided provider in a stashing provider so that we can delay // unrefing images until we have serialized dependent commands. @@ -1936,7 +1938,7 @@ } RasterImplementation::RasterProperties::RasterProperties( - SkColor background_color, + SkColor4f background_color, bool can_use_lcd_text, sk_sp<SkColorSpace> color_space) : background_color(background_color),
diff --git a/gpu/command_buffer/client/raster_implementation.h b/gpu/command_buffer/client/raster_implementation.h index d936b83..c3384db 100644 --- a/gpu/command_buffer/client/raster_implementation.h +++ b/gpu/command_buffer/client/raster_implementation.h
@@ -147,7 +147,7 @@ const gpu::Mailbox yuva_plane_mailboxes[], const gpu::Mailbox& source_mailbox) override; - void BeginRasterCHROMIUM(GLuint sk_color, + void BeginRasterCHROMIUM(SkColor4f sk_color_4f, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode, @@ -438,11 +438,11 @@ std::vector<size_t> temp_raster_offsets_; struct RasterProperties { - RasterProperties(SkColor background_color, + RasterProperties(SkColor4f background_color, bool can_use_lcd_text, sk_sp<SkColorSpace> color_space); ~RasterProperties(); - SkColor background_color = SK_ColorWHITE; + SkColor4f background_color = SkColors::kWhite; bool can_use_lcd_text = false; sk_sp<SkColorSpace> color_space; };
diff --git a/gpu/command_buffer/client/raster_implementation_gles.cc b/gpu/command_buffer/client/raster_implementation_gles.cc index 0adfbfe..71ea25c 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.cc +++ b/gpu/command_buffer/client/raster_implementation_gles.cc
@@ -216,7 +216,7 @@ } void RasterImplementationGLES::BeginRasterCHROMIUM( - GLuint sk_color, + SkColor4f sk_color_4f, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode,
diff --git a/gpu/command_buffer/client/raster_implementation_gles.h b/gpu/command_buffer/client/raster_implementation_gles.h index 1142dbd..11e8de5 100644 --- a/gpu/command_buffer/client/raster_implementation_gles.h +++ b/gpu/command_buffer/client/raster_implementation_gles.h
@@ -90,7 +90,7 @@ const gpu::Mailbox& source_mailbox) override; // OOP-Raster - void BeginRasterCHROMIUM(GLuint sk_color, + void BeginRasterCHROMIUM(SkColor4f sk_color_4f, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode,
diff --git a/gpu/command_buffer/client/raster_interface.h b/gpu/command_buffer/client/raster_interface.h index e43b373..e582b779 100644 --- a/gpu/command_buffer/client/raster_interface.h +++ b/gpu/command_buffer/client/raster_interface.h
@@ -13,6 +13,7 @@ #include "gpu/command_buffer/client/interface_base.h" #include "gpu/command_buffer/common/raster_cmd_enums.h" #include "gpu/command_buffer/common/sync_token.h" +#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkImageInfo.h" #include "third_party/skia/include/core/SkYUVAInfo.h" #include "third_party/skia/include/gpu/GrTypes.h" @@ -84,7 +85,7 @@ // OOP-Raster // msaa_sample_count has no effect unless msaa_mode is set to kMSAA - virtual void BeginRasterCHROMIUM(GLuint sk_color, + virtual void BeginRasterCHROMIUM(SkColor4f sk_color_4f, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode,
diff --git a/gpu/command_buffer/common/raster_cmd_format_autogen.h b/gpu/command_buffer/common/raster_cmd_format_autogen.h index 6351f48..ccc53daf 100644 --- a/gpu/command_buffer/common/raster_cmd_format_autogen.h +++ b/gpu/command_buffer/common/raster_cmd_format_autogen.h
@@ -388,7 +388,10 @@ void SetHeader() { header.SetCmdByTotalSize<ValueType>(ComputeSize()); } - void Init(GLuint _sk_color, + void Init(GLfloat _r, + GLfloat _g, + GLfloat _b, + GLfloat _a, GLboolean _needs_clear, GLuint _msaa_sample_count, gpu::raster::MsaaMode _msaa_mode, @@ -396,7 +399,10 @@ GLboolean _visible, const GLbyte* _mailbox) { SetHeader(); - sk_color = _sk_color; + r = _r; + g = _g; + b = _b; + a = _a; needs_clear = _needs_clear; msaa_sample_count = _msaa_sample_count; msaa_mode = _msaa_mode; @@ -406,14 +412,17 @@ } void* Set(void* cmd, - GLuint _sk_color, + GLfloat _r, + GLfloat _g, + GLfloat _b, + GLfloat _a, GLboolean _needs_clear, GLuint _msaa_sample_count, gpu::raster::MsaaMode _msaa_mode, GLboolean _can_use_lcd_text, GLboolean _visible, const GLbyte* _mailbox) { - static_cast<ValueType*>(cmd)->Init(_sk_color, _needs_clear, + static_cast<ValueType*>(cmd)->Init(_r, _g, _b, _a, _needs_clear, _msaa_sample_count, _msaa_mode, _can_use_lcd_text, _visible, _mailbox); const uint32_t size = ComputeSize(); @@ -421,7 +430,10 @@ } gpu::CommandHeader header; - uint32_t sk_color; + float r; + float g; + float b; + float a; uint32_t needs_clear; uint32_t msaa_sample_count; uint32_t msaa_mode; @@ -429,24 +441,31 @@ uint32_t visible; }; -static_assert(sizeof(BeginRasterCHROMIUMImmediate) == 28, - "size of BeginRasterCHROMIUMImmediate should be 28"); +static_assert(sizeof(BeginRasterCHROMIUMImmediate) == 40, + "size of BeginRasterCHROMIUMImmediate should be 40"); static_assert(offsetof(BeginRasterCHROMIUMImmediate, header) == 0, "offset of BeginRasterCHROMIUMImmediate header should be 0"); -static_assert(offsetof(BeginRasterCHROMIUMImmediate, sk_color) == 4, - "offset of BeginRasterCHROMIUMImmediate sk_color should be 4"); -static_assert(offsetof(BeginRasterCHROMIUMImmediate, needs_clear) == 8, - "offset of BeginRasterCHROMIUMImmediate needs_clear should be 8"); +static_assert(offsetof(BeginRasterCHROMIUMImmediate, r) == 4, + "offset of BeginRasterCHROMIUMImmediate r should be 4"); +static_assert(offsetof(BeginRasterCHROMIUMImmediate, g) == 8, + "offset of BeginRasterCHROMIUMImmediate g should be 8"); +static_assert(offsetof(BeginRasterCHROMIUMImmediate, b) == 12, + "offset of BeginRasterCHROMIUMImmediate b should be 12"); +static_assert(offsetof(BeginRasterCHROMIUMImmediate, a) == 16, + "offset of BeginRasterCHROMIUMImmediate a should be 16"); static_assert( - offsetof(BeginRasterCHROMIUMImmediate, msaa_sample_count) == 12, - "offset of BeginRasterCHROMIUMImmediate msaa_sample_count should be 12"); -static_assert(offsetof(BeginRasterCHROMIUMImmediate, msaa_mode) == 16, - "offset of BeginRasterCHROMIUMImmediate msaa_mode should be 16"); + offsetof(BeginRasterCHROMIUMImmediate, needs_clear) == 20, + "offset of BeginRasterCHROMIUMImmediate needs_clear should be 20"); static_assert( - offsetof(BeginRasterCHROMIUMImmediate, can_use_lcd_text) == 20, - "offset of BeginRasterCHROMIUMImmediate can_use_lcd_text should be 20"); -static_assert(offsetof(BeginRasterCHROMIUMImmediate, visible) == 24, - "offset of BeginRasterCHROMIUMImmediate visible should be 24"); + offsetof(BeginRasterCHROMIUMImmediate, msaa_sample_count) == 24, + "offset of BeginRasterCHROMIUMImmediate msaa_sample_count should be 24"); +static_assert(offsetof(BeginRasterCHROMIUMImmediate, msaa_mode) == 28, + "offset of BeginRasterCHROMIUMImmediate msaa_mode should be 28"); +static_assert( + offsetof(BeginRasterCHROMIUMImmediate, can_use_lcd_text) == 32, + "offset of BeginRasterCHROMIUMImmediate can_use_lcd_text should be 32"); +static_assert(offsetof(BeginRasterCHROMIUMImmediate, visible) == 36, + "offset of BeginRasterCHROMIUMImmediate visible should be 36"); struct RasterCHROMIUM { typedef RasterCHROMIUM ValueType;
diff --git a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h index 9ba27ca..9bb6228 100644 --- a/gpu/command_buffer/common/raster_cmd_format_test_autogen.h +++ b/gpu/command_buffer/common/raster_cmd_format_test_autogen.h
@@ -159,19 +159,24 @@ cmds::BeginRasterCHROMIUMImmediate& cmd = *GetBufferAs<cmds::BeginRasterCHROMIUMImmediate>(); void* next_cmd = - cmd.Set(&cmd, static_cast<GLuint>(11), static_cast<GLboolean>(12), - static_cast<GLuint>(13), static_cast<gpu::raster::MsaaMode>(14), - static_cast<GLboolean>(15), static_cast<GLboolean>(16), data); + cmd.Set(&cmd, static_cast<GLfloat>(11), static_cast<GLfloat>(12), + static_cast<GLfloat>(13), static_cast<GLfloat>(14), + static_cast<GLboolean>(15), static_cast<GLuint>(16), + static_cast<gpu::raster::MsaaMode>(17), + static_cast<GLboolean>(18), static_cast<GLboolean>(19), data); EXPECT_EQ(static_cast<uint32_t>(cmds::BeginRasterCHROMIUMImmediate::kCmdId), cmd.header.command); EXPECT_EQ(sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data)), cmd.header.size * 4u); - EXPECT_EQ(static_cast<GLuint>(11), cmd.sk_color); - EXPECT_EQ(static_cast<GLboolean>(12), cmd.needs_clear); - EXPECT_EQ(static_cast<GLuint>(13), cmd.msaa_sample_count); - EXPECT_EQ(static_cast<gpu::raster::MsaaMode>(14), cmd.msaa_mode); - EXPECT_EQ(static_cast<GLboolean>(15), cmd.can_use_lcd_text); - EXPECT_EQ(static_cast<GLboolean>(16), cmd.visible); + EXPECT_EQ(static_cast<GLfloat>(11), cmd.r); + EXPECT_EQ(static_cast<GLfloat>(12), cmd.g); + EXPECT_EQ(static_cast<GLfloat>(13), cmd.b); + EXPECT_EQ(static_cast<GLfloat>(14), cmd.a); + EXPECT_EQ(static_cast<GLboolean>(15), cmd.needs_clear); + EXPECT_EQ(static_cast<GLuint>(16), cmd.msaa_sample_count); + EXPECT_EQ(static_cast<gpu::raster::MsaaMode>(17), cmd.msaa_mode); + EXPECT_EQ(static_cast<GLboolean>(18), cmd.can_use_lcd_text); + EXPECT_EQ(static_cast<GLboolean>(19), cmd.visible); CheckBytesWrittenMatchesExpectedSize( next_cmd, sizeof(cmd) + RoundSizeToMultipleOfEntries(sizeof(data))); }
diff --git a/gpu/command_buffer/raster_cmd_buffer_functions.txt b/gpu/command_buffer/raster_cmd_buffer_functions.txt index b174fbc..739d0b1 100644 --- a/gpu/command_buffer/raster_cmd_buffer_functions.txt +++ b/gpu/command_buffer/raster_cmd_buffer_functions.txt
@@ -23,7 +23,7 @@ GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); // Extension CHROMIUM_raster_transport -GL_APICALL void GL_APIENTRY glBeginRasterCHROMIUM (GLuint sk_color, GLboolean needs_clear, GLuint msaa_sample_count, gpu::raster::MsaaMode msaa_mode, GLboolean can_use_lcd_text, GLboolean visible, const GLbyte* mailbox); +GL_APICALL void GL_APIENTRY glBeginRasterCHROMIUM (GLfloat r, GLfloat g, GLfloat b, GLfloat a, GLboolean needs_clear, GLuint msaa_sample_count, gpu::raster::MsaaMode msaa_mode, GLboolean can_use_lcd_text, GLboolean visible, const GLbyte* mailbox); GL_APICALL void GL_APIENTRY glRasterCHROMIUM (GLuint raster_shm_id, GLuint raster_shm_offset, GLuint raster_shm_size, GLuint font_shm_id, GLuint font_shm_offset, GLuint font_shm_size); GL_APICALL void GL_APIENTRY glEndRasterCHROMIUM (void); GL_APICALL void GL_APIENTRY glCreateTransferCacheEntryINTERNAL (GLuint entry_type, GLuint entry_id, GLuint handle_shm_id, GLuint handle_shm_offset, GLuint data_shm_id, GLuint data_shm_offset, GLuint data_size);
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc index 7d8bb49..cb6a735a 100644 --- a/gpu/command_buffer/service/raster_decoder.cc +++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -769,7 +769,10 @@ const volatile GLbyte* mailboxes); void DoLoseContextCHROMIUM(GLenum current, GLenum other); - void DoBeginRasterCHROMIUM(GLuint sk_color, + void DoBeginRasterCHROMIUM(GLfloat r, + GLfloat g, + GLfloat b, + GLfloat a, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode, @@ -3214,7 +3217,10 @@ paint_cache_->PurgeAll(); } -void RasterDecoderImpl::DoBeginRasterCHROMIUM(GLuint sk_color, +void RasterDecoderImpl::DoBeginRasterCHROMIUM(GLfloat r, + GLfloat g, + GLfloat b, + GLfloat a, GLboolean needs_clear, GLuint msaa_sample_count, MsaaMode msaa_mode, @@ -3306,10 +3312,11 @@ surface_props = skia::LegacyDisplayGlobals::GetSkSurfaceProps(flags); } + SkColor4f sk_color_4f = {r, g, b, a}; if (shared_image_raster_) { - absl::optional<SkColor> clear_color; + absl::optional<SkColor4f> clear_color; if (needs_clear) - clear_color.emplace(sk_color); + clear_color.emplace(sk_color_4f); scoped_shared_image_raster_write_ = shared_image_raster_->BeginScopedWriteAccess( shared_context_state_, final_msaa_count, surface_props, clear_color, @@ -3366,7 +3373,7 @@ // and so any extra pixels outside the raster area that get sampled may be // incorrect. if (needs_clear) { - raster_canvas_->drawColor(sk_color, SkBlendMode::kSrc); + raster_canvas_->drawColor(sk_color_4f, SkBlendMode::kSrc); shared_image_->SetCleared(); } DCHECK(shared_image_->IsCleared());
diff --git a/gpu/command_buffer/service/raster_decoder_autogen.h b/gpu/command_buffer/service/raster_decoder_autogen.h index c7a59c1..5a9b773 100644 --- a/gpu/command_buffer/service/raster_decoder_autogen.h +++ b/gpu/command_buffer/service/raster_decoder_autogen.h
@@ -111,7 +111,10 @@ const volatile raster::cmds::BeginRasterCHROMIUMImmediate& c = *static_cast<const volatile raster::cmds::BeginRasterCHROMIUMImmediate*>( cmd_data); - GLuint sk_color = static_cast<GLuint>(c.sk_color); + GLfloat r = static_cast<GLfloat>(c.r); + GLfloat g = static_cast<GLfloat>(c.g); + GLfloat b = static_cast<GLfloat>(c.b); + GLfloat a = static_cast<GLfloat>(c.a); GLboolean needs_clear = static_cast<GLboolean>(c.needs_clear); GLuint msaa_sample_count = static_cast<GLuint>(c.msaa_sample_count); gpu::raster::MsaaMode msaa_mode = @@ -131,7 +134,7 @@ if (mailbox == nullptr) { return error::kOutOfBounds; } - DoBeginRasterCHROMIUM(sk_color, needs_clear, msaa_sample_count, msaa_mode, + DoBeginRasterCHROMIUM(r, g, b, a, needs_clear, msaa_sample_count, msaa_mode, can_use_lcd_text, visible, mailbox); return error::kNoError; }
diff --git a/gpu/command_buffer/service/shared_image_backing_raw_draw.cc b/gpu/command_buffer/service/shared_image_backing_raw_draw.cc index f5966737..25b8e8b 100644 --- a/gpu/command_buffer/service/shared_image_backing_raw_draw.cc +++ b/gpu/command_buffer/service/shared_image_backing_raw_draw.cc
@@ -42,7 +42,7 @@ scoped_refptr<SharedContextState> context_state, int final_msaa_count, const SkSurfaceProps& surface_props, - const absl::optional<SkColor>& clear_color, + const absl::optional<SkColor4f>& clear_color, bool visible) override { return raw_draw_backing()->BeginRasterWriteAccess( std::move(context_state), final_msaa_count, surface_props, clear_color, @@ -54,7 +54,7 @@ } cc::PaintOpBuffer* BeginReadAccess( - absl::optional<SkColor>& clear_color) override { + absl::optional<SkColor4f>& clear_color) override { return raw_draw_backing()->BeginRasterReadAccess(clear_color); } @@ -272,7 +272,7 @@ scoped_refptr<SharedContextState> context_state, int final_msaa_count, const SkSurfaceProps& surface_props, - const absl::optional<SkColor>& clear_color, + const absl::optional<SkColor4f>& clear_color, bool visible) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); AutoLock auto_lock(this); @@ -337,7 +337,7 @@ } cc::PaintOpBuffer* SharedImageBackingRawDraw::BeginRasterReadAccess( - absl::optional<SkColor>& clear_color) { + absl::optional<SkColor4f>& clear_color) { // paint ops will be read on compositor thread, so do not check thread with // DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); AutoLock auto_lock(this);
diff --git a/gpu/command_buffer/service/shared_image_backing_raw_draw.h b/gpu/command_buffer/service/shared_image_backing_raw_draw.h index b7b4205..49df5f6 100644 --- a/gpu/command_buffer/service/shared_image_backing_raw_draw.h +++ b/gpu/command_buffer/service/shared_image_backing_raw_draw.h
@@ -62,17 +62,17 @@ scoped_refptr<SharedContextState> context_state, int final_msaa_count, const SkSurfaceProps& surface_props, - const absl::optional<SkColor>& clear_color, + const absl::optional<SkColor4f>& clear_color, bool visible); void EndRasterWriteAccess(base::OnceClosure callback); cc::PaintOpBuffer* BeginRasterReadAccess( - absl::optional<SkColor>& clear_color); + absl::optional<SkColor4f>& clear_color); sk_sp<SkPromiseImageTexture> BeginSkiaReadAccess(); void EndReadAccess(); int32_t final_msaa_count_ GUARDED_BY_CONTEXT(thread_checker_) = 0; SkSurfaceProps surface_props_ GUARDED_BY_CONTEXT(thread_checker_){}; - absl::optional<SkColor> clear_color_ GUARDED_BY(lock_); + absl::optional<SkColor4f> clear_color_ GUARDED_BY(lock_); bool visible_ GUARDED_BY(lock_) = false; sk_sp<cc::PaintOpBuffer> paint_op_buffer_ GUARDED_BY(lock_); base::OnceClosure paint_op_release_callback_
diff --git a/gpu/command_buffer/service/shared_image_representation.cc b/gpu/command_buffer/service/shared_image_representation.cc index c80f7fcc..3185b97 100644 --- a/gpu/command_buffer/service/shared_image_representation.cc +++ b/gpu/command_buffer/service/shared_image_representation.cc
@@ -429,7 +429,7 @@ base::PassKey<SharedImageRepresentationRaster> pass_key, SharedImageRepresentationRaster* representation, const cc::PaintOpBuffer* paint_op_buffer, - const absl::optional<SkColor>& clear_color) + const absl::optional<SkColor4f>& clear_color) : ScopedAccessBase(representation), paint_op_buffer_(paint_op_buffer), clear_color_(clear_color) {} @@ -450,7 +450,7 @@ std::unique_ptr<SharedImageRepresentationRaster::ScopedReadAccess> SharedImageRepresentationRaster::BeginScopedReadAccess() { - absl::optional<SkColor> clear_color; + absl::optional<SkColor4f> clear_color; auto* paint_op_buffer = BeginReadAccess(clear_color); if (!paint_op_buffer) return nullptr; @@ -464,7 +464,7 @@ scoped_refptr<SharedContextState> context_state, int final_msaa_count, const SkSurfaceProps& surface_props, - const absl::optional<SkColor>& clear_color, + const absl::optional<SkColor4f>& clear_color, bool visible) { return std::make_unique<ScopedWriteAccess>( base::PassKey<SharedImageRepresentationRaster>(), this,
diff --git a/gpu/command_buffer/service/shared_image_representation.h b/gpu/command_buffer/service/shared_image_representation.h index c7676a44..8bb02bf 100644 --- a/gpu/command_buffer/service/shared_image_representation.h +++ b/gpu/command_buffer/service/shared_image_representation.h
@@ -597,17 +597,19 @@ ScopedReadAccess(base::PassKey<SharedImageRepresentationRaster> pass_key, SharedImageRepresentationRaster* representation, const cc::PaintOpBuffer* paint_op_buffer, - const absl::optional<SkColor>& clear_color); + const absl::optional<SkColor4f>& clear_color); ~ScopedReadAccess(); const cc::PaintOpBuffer* paint_op_buffer() const { return paint_op_buffer_; } - const absl::optional<SkColor>& clear_color() const { return clear_color_; } + const absl::optional<SkColor4f>& clear_color() const { + return clear_color_; + } private: const raw_ptr<const cc::PaintOpBuffer> paint_op_buffer_; - absl::optional<SkColor> clear_color_; + absl::optional<SkColor4f> clear_color_; }; class GPU_GLES2_EXPORT ScopedWriteAccess @@ -643,18 +645,18 @@ scoped_refptr<SharedContextState> context_state, int final_msaa_count, const SkSurfaceProps& surface_props, - const absl::optional<SkColor>& clear_color, + const absl::optional<SkColor4f>& clear_color, bool visible); protected: virtual cc::PaintOpBuffer* BeginReadAccess( - absl::optional<SkColor>& clear_color) = 0; + absl::optional<SkColor4f>& clear_color) = 0; virtual void EndReadAccess() = 0; virtual cc::PaintOpBuffer* BeginWriteAccess( scoped_refptr<SharedContextState> context_state, int final_msaa_count, const SkSurfaceProps& surface_props, - const absl::optional<SkColor>& clear_color, + const absl::optional<SkColor4f>& clear_color, bool visible) = 0; virtual void EndWriteAccess(base::OnceClosure callback) = 0; };
diff --git a/gpu/ipc/client/raster_in_process_context_tests.cc b/gpu/ipc/client/raster_in_process_context_tests.cc index b77e9f2..fbaf3d2c 100644 --- a/gpu/ipc/client/raster_in_process_context_tests.cc +++ b/gpu/ipc/client/raster_in_process_context_tests.cc
@@ -105,9 +105,9 @@ // Call BeginRasterCHROMIUM. ri_->BeginRasterCHROMIUM( - /*sk_color=*/0, /*needs_clear=*/true, /*msaa_sample_count=*/0, - gpu::raster::kNoMSAA, /*can_use_lcd_text=*/false, /*visible=*/true, - color_space, mailbox.name); + /*sk_color_4f=*/{0, 0, 0, 0}, /*needs_clear=*/true, + /*msaa_sample_count=*/0, gpu::raster::kNoMSAA, + /*can_use_lcd_text=*/false, /*visible=*/true, color_space, mailbox.name); EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), ri_->GetError()); // Should flag an error this command is not allowed between a Begin and
diff --git a/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json b/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json new file mode 100644 index 0000000..48cd90f7 --- /dev/null +++ b/infra/config/generated/builders/ci/android-fieldtrial-rel/properties.json
@@ -0,0 +1,74 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "android-fieldtrial-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "x86_builder" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "android", + "target_bits": 32, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "android-fieldtrial-rel", + "project": "chromium" + } + ], + "mirroring_builder_group_and_names": [ + { + "builder": "android-fieldtrial-fyi-rel", + "group": "tryserver.chromium.android" + } + ] + } + }, + "$build/goma": { + "enable_ats": true, + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$build/reclient": { + "instance": "rbe-chromium-trusted", + "jobs": 250, + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.fyi", + "recipe": "chromium" +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/android-fieldtrial-fyi-rel/properties.json b/infra/config/generated/builders/try/android-fieldtrial-fyi-rel/properties.json new file mode 100644 index 0000000..f5c3264 --- /dev/null +++ b/infra/config/generated/builders/try/android-fieldtrial-fyi-rel/properties.json
@@ -0,0 +1,63 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "android-fieldtrial-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-android-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_android_config": { + "config": "x86_builder" + }, + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "android", + "target_bits": 32, + "target_platform": "android" + }, + "legacy_gclient_config": { + "apply_configs": [ + "android", + "enable_reclient" + ], + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "android-fieldtrial-rel", + "project": "chromium" + } + ] + } + }, + "$build/goma": { + "enable_ats": true, + "rpc_extra_params": "?prod", + "server_host": "goma.chromium.org", + "use_luci_auth": true + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "tryserver.chromium.android", + "recipe": "chromium_trybot" +} \ No newline at end of file
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index 9ab1e61..7d5707c 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -400,6 +400,10 @@ includable_only: true } builders { + name: "chromium/try/android-fieldtrial-fyi-rel" + includable_only: true + } + builders { name: "chromium/try/android-inverse-fieldtrials-pie-x86-fyi-rel" includable_only: true }
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 723a8ba..8ef4b20 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -24416,6 +24416,84 @@ } } builders { + name: "android-fieldtrial-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builder:android-fieldtrial-rel" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.ci" + 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/ci/android-fieldtrial-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.fyi",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + execution_timeout_secs: 36000 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_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_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://[^/]*blink_web_tests/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "android-marshmallow-arm64-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -47733,6 +47811,96 @@ } } builders { + name: "android-fieldtrial-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.try" + dimensions: "ssd:0" + 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/android-fieldtrial-fyi-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "tryserver.chromium.android",' + ' "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: "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/.+" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "android-inverse-fieldtrials-pie-x86-fyi-rel" 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 bb3a152..e5c2f8a 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -7889,6 +7889,10 @@ short_name: "64rel" } builders { + name: "buildbucket/luci.chromium.ci/android-fieldtrial-rel" + category: "android" + } + builders { name: "buildbucket/luci.chromium.ci/Comparison Android (reclient)" category: "android" short_name: "cmp" @@ -15577,6 +15581,9 @@ name: "buildbucket/luci.chromium.try/android-deterministic-rel" } builders { + name: "buildbucket/luci.chromium.try/android-fieldtrial-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/android-inverse-fieldtrials-pie-x86-fyi-rel" } builders { @@ -16684,6 +16691,9 @@ name: "buildbucket/luci.chromium.try/android-deterministic-rel" } builders { + name: "buildbucket/luci.chromium.try/android-fieldtrial-fyi-rel" + } + builders { name: "buildbucket/luci.chromium.try/android-inverse-fieldtrials-pie-x86-fyi-rel" } builders {
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index 3a0c3b3a..45660bd3 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -4308,6 +4308,16 @@ } } job { + id: "android-fieldtrial-rel" + realm: "ci" + acl_sets: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "android-fieldtrial-rel" + } +} +job { id: "android-marshmallow-arm64-rel" realm: "ci" acl_sets: "ci" @@ -6937,6 +6947,7 @@ triggers: "android-cronet-marshmallow-arm64-perf-rel" triggers: "android-cronet-x86-dbg" triggers: "android-cronet-x86-rel" + triggers: "android-fieldtrial-rel" triggers: "android-marshmallow-arm64-rel" triggers: "android-marshmallow-x86-rel" triggers: "android-marshmallow-x86-rel-non-cq"
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index ab4e502..7557b367 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -477,6 +477,39 @@ os = os.MAC_DEFAULT, ) +ci.builder( + name = "android-fieldtrial-rel", + builderless = False, + console_view_entry = consoles.console_view_entry( + category = "android", + ), + os = os.LINUX_BIONIC, + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "android", + "enable_reclient", + ], + ), + chromium_config = builder_config.chromium_config( + config = "android", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.RELEASE, + target_bits = 32, + target_platform = builder_config.target_platform.ANDROID, + ), + android_config = builder_config.android_config( + config = "x86_builder", + ), + build_gs_bucket = "chromium-android-archive", + ), + reclient_jobs = rbe_jobs.DEFAULT, + reclient_instance = rbe_instance.DEFAULT, +) + fyi_ios_builder( name = "ios-fieldtrial-rel", builderless = False,
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star index 50bb408..9e735e5 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.android.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.android.star
@@ -225,6 +225,11 @@ ) try_.builder( + name = "android-fieldtrial-fyi-rel", + mirrors = ["ci/android-fieldtrial-rel"], +) + +try_.builder( name = "android-inverse-fieldtrials-pie-x86-fyi-rel", mirrors = builder_config.copy_from("try/android-pie-x86-rel"), )
diff --git a/ios/chrome/browser/follow/BUILD.gn b/ios/chrome/browser/follow/BUILD.gn index a7d2f007..d98bf02 100644 --- a/ios/chrome/browser/follow/BUILD.gn +++ b/ios/chrome/browser/follow/BUILD.gn
@@ -11,7 +11,6 @@ ] deps = [ ":rss_link_js", - "//base", "//ios/chrome/browser/ui/follow", "//ios/web/public", "//ios/web/public/js_messaging",
diff --git a/ios/chrome/browser/follow/follow_java_script_feature.mm b/ios/chrome/browser/follow/follow_java_script_feature.mm index bd90472b..ff4b406 100644 --- a/ios/chrome/browser/follow/follow_java_script_feature.mm +++ b/ios/chrome/browser/follow/follow_java_script_feature.mm
@@ -8,7 +8,6 @@ #error "This file requires ARC support." #endif -#include "base/strings/sys_string_conversions.h" #import "ios/web/public/js_messaging/web_frame_util.h" #include "ios/web/public/web_state.h" #import "net/base/mac/url_conversions.h" @@ -66,8 +65,10 @@ NSMutableArray* rss_links = [[NSMutableArray alloc] init]; for (const auto& link : response->GetListDeprecated()) { if (link.is_string()) { - [rss_links addObject:[NSURL URLWithString:base::SysUTF8ToNSString( - *link.GetIfString())]]; + NSURL* url = net::NSURLWithGURL(GURL(link.GetString())); + if (url) { + [rss_links addObject:url]; + } } } std::move(callback).Run([[FollowWebPageURLs alloc]
diff --git a/ios/chrome/browser/prerender/prerender_service_factory.h b/ios/chrome/browser/prerender/prerender_service_factory.h index 527e391..156a6d17 100644 --- a/ios/chrome/browser/prerender/prerender_service_factory.h +++ b/ios/chrome/browser/prerender/prerender_service_factory.h
@@ -21,6 +21,9 @@ ChromeBrowserState* browser_state); static PrerenderServiceFactory* GetInstance(); + // Returns the default factory, useful in tests where it's null by default. + static TestingFactory GetDefaultFactory(); + PrerenderServiceFactory(const PrerenderServiceFactory&) = delete; PrerenderServiceFactory& operator=(const PrerenderServiceFactory&) = delete;
diff --git a/ios/chrome/browser/prerender/prerender_service_factory.mm b/ios/chrome/browser/prerender/prerender_service_factory.mm index 35c8778..a7b8b78 100644 --- a/ios/chrome/browser/prerender/prerender_service_factory.mm +++ b/ios/chrome/browser/prerender/prerender_service_factory.mm
@@ -4,17 +4,24 @@ #import "ios/chrome/browser/prerender/prerender_service_factory.h" -#include "base/no_destructor.h" -#include "components/keyed_service/ios/browser_state_dependency_manager.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/prerender/prerender_service_impl.h" -#include "ios/chrome/browser/signin/account_consistency_service_factory.h" -#include "ios/web/public/browser_state.h" +#import "base/no_destructor.h" +#import "components/keyed_service/ios/browser_state_dependency_manager.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/prerender/prerender_service_impl.h" +#import "ios/chrome/browser/signin/account_consistency_service_factory.h" +#import "ios/web/public/browser_state.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif +std::unique_ptr<KeyedService> BuildPrerenderService( + web::BrowserState* context) { + ChromeBrowserState* browser_state = + ChromeBrowserState::FromBrowserState(context); + return std::make_unique<PrerenderServiceImpl>(browser_state); +} + // static PrerenderService* PrerenderServiceFactory::GetForBrowserState( ChromeBrowserState* browser_state) { @@ -39,9 +46,13 @@ std::unique_ptr<KeyedService> PrerenderServiceFactory::BuildServiceInstanceFor( web::BrowserState* context) const { - ChromeBrowserState* browser_state = - ChromeBrowserState::FromBrowserState(context); - return std::make_unique<PrerenderServiceImpl>(browser_state); + return BuildPrerenderService(context); +} + +// static +PrerenderServiceFactory::TestingFactory +PrerenderServiceFactory::GetDefaultFactory() { + return base::BindRepeating(&BuildPrerenderService); } bool PrerenderServiceFactory::ServiceIsNULLWhileTesting() const {
diff --git a/ios/chrome/browser/providers/BUILD.gn b/ios/chrome/browser/providers/BUILD.gn index e96a148..2cf0235 100644 --- a/ios/chrome/browser/providers/BUILD.gn +++ b/ios/chrome/browser/providers/BUILD.gn
@@ -47,6 +47,7 @@ "//ios/chrome/browser/providers/omaha:chromium_omaha", "//ios/chrome/browser/providers/overrides:chromium_overrides", "//ios/chrome/browser/providers/password_auto_fill:chromium_password_auto_fill", + "//ios/chrome/browser/providers/push_notification:chromium_push_notification", "//ios/chrome/browser/providers/risk_data:chromium_risk_data", "//ios/chrome/browser/providers/signin:chromium_signin_error", "//ios/chrome/browser/providers/signin:chromium_signin_resources",
diff --git a/ios/chrome/browser/providers/push_notification/BUILD.gn b/ios/chrome/browser/providers/push_notification/BUILD.gn new file mode 100644 index 0000000..66abdc65 --- /dev/null +++ b/ios/chrome/browser/providers/push_notification/BUILD.gn
@@ -0,0 +1,9 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("chromium_push_notification") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ "chromium_push_notification.mm" ] + deps = [ "//ios/public/provider/chrome/browser/push_notification:push_notification_api" ] +}
diff --git a/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm b/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm new file mode 100644 index 0000000..36631e8 --- /dev/null +++ b/ios/chrome/browser/providers/push_notification/chromium_push_notification.mm
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/public/provider/chrome/browser/push_notification/push_notification_api.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace ios { +namespace provider { + +void InitializeConfiguration() { + // Chromium does not initialize push notification configurations +} + +void RegisterDevice() { + // Chromium does not register devices for push notifications +} + +} // namespace provider +} // namespace ios
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm index ea0821c0..1f7b479 100644 --- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm
@@ -122,7 +122,7 @@ ]]; } - self.bannerImage = [UIImage imageNamed:@"sync_screen_banner"]; + self.bannerName = @"sync_screen_banner"; self.secondaryActionString = l10n_util::GetNSString([self secondaryActionStringID]);
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 21e8fccd..96cb92bc8 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -256,6 +256,8 @@ "//ios/chrome/browser/favicon", "//ios/chrome/browser/history", "//ios/chrome/browser/main:test_support", + "//ios/chrome/browser/prerender", + "//ios/chrome/browser/prerender:test_support", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/sessions", "//ios/chrome/browser/sessions:restoration_agent", @@ -266,6 +268,7 @@ "//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/browser_container:ui", + "//ios/chrome/browser/ui/bubble", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen:feature_flags",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index b863cec..788f716c 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -4,7 +4,7 @@ #import "ios/chrome/browser/ui/browser_view/browser_coordinator.h" -#include <memory> +#import <memory> #import "base/metrics/histogram_functions.h" #import "base/scoped_observation.h" @@ -22,6 +22,7 @@ #import "ios/chrome/browser/follow/follow_tab_helper.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/ntp/features.h" +#import "ios/chrome/browser/prerender/preload_controller_delegate.h" #import "ios/chrome/browser/prerender/prerender_service.h" #import "ios/chrome/browser/prerender/prerender_service_factory.h" #import "ios/chrome/browser/signin/account_consistency_browser_agent.h" @@ -37,11 +38,13 @@ #import "ios/chrome/browser/ui/autofill/form_input_accessory/form_input_accessory_coordinator.h" #import "ios/chrome/browser/ui/badges/badge_popup_menu_coordinator.h" #import "ios/chrome/browser/ui/browser_container/browser_container_coordinator.h" +#import "ios/chrome/browser/ui/browser_container/browser_container_view_controller.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller+delegates.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller+private.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/ui/browser_view/tab_lifecycle_mediator.h" +#import "ios/chrome/browser/ui/bubble/bubble_presenter.h" #import "ios/chrome/browser/ui/commands/activity_service_commands.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h" @@ -113,7 +116,7 @@ #import "ios/chrome/browser/web/web_navigation_browser_agent.h" #import "ios/chrome/browser/web/web_state_delegate_browser_agent.h" #import "ios/chrome/browser/web_state_list/view_source_browser_agent.h" -#include "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #import "ios/chrome/browser/webui/net_export_tab_helper_delegate.h" #import "ios/chrome/grit/ios_strings.h" @@ -137,6 +140,7 @@ PasswordSuggestionCommands, PasswordSuggestionCoordinatorDelegate, PolicyChangeCommands, + PreloadControllerDelegate, RepostFormTabHelperDelegate, ToolbarAccessoryCoordinatorDelegate, URLLoadingDelegate, @@ -294,6 +298,8 @@ std::unique_ptr<WebStateListObserverBridge> _webStateListObserverBridge; std::unique_ptr<base::ScopedObservation<WebStateList, WebStateListObserver>> _scopedWebStateListObservation; + PrerenderService* _prerenderService; + BubblePresenter* _bubblePresenter; } #pragma mark - ChromeCoordinator @@ -459,17 +465,32 @@ // Instantiates a BrowserViewController. - (void)createViewController { DCHECK(self.browserContainerCoordinator.viewController); + BrowserViewControllerDependencyFactory* factory = [[BrowserViewControllerDependencyFactory alloc] initWithBrowser:self.browser]; + + ChromeBrowserState* browserState = self.browser->GetBrowserState(); + _prerenderService = PrerenderServiceFactory::GetForBrowserState(browserState); + if (!browserState->IsOffTheRecord()) { + DCHECK(_prerenderService); + _prerenderService->SetDelegate(self); + } + + _bubblePresenter = + [[BubblePresenter alloc] initWithBrowserState:browserState]; + _viewController = [[BrowserViewController alloc] initWithBrowser:self.browser dependencyFactory:factory browserContainerViewController:self.browserContainerCoordinator .viewController - dispatcher:self.dispatcher]; + dispatcher:self.dispatcher + prerenderService:_prerenderService + bubblePresenter:_bubblePresenter]; WebNavigationBrowserAgent::FromBrowser(self.browser) ->SetDelegate(_viewController); + self.contextMenuProvider = [[ContextMenuConfigurationProvider alloc] initWithBrowser:self.browser baseViewController:_viewController]; @@ -822,6 +843,18 @@ [self.readingListCoordinator start]; } +- (void)showReadingListIPH { + [_bubblePresenter presentReadingListBottomToolbarTipBubble]; +} + +- (void)showFollowWhileBrowsingIPH { + [_bubblePresenter presentFollowWhileBrowsingTipBubble]; +} + +- (void)showDefaultSiteViewIPH { + [_bubblePresenter presentDefaultSiteViewTipBubble]; +} + - (void)showDownloadsFolder { NSURL* URL = GetFilesAppUrl(); if (!URL) @@ -1466,4 +1499,15 @@ self.passwordSuggestionCoordinator = nil; } +#pragma mark - PreloadControllerDelegate methods + +- (web::WebState*)webStateToReplace { + return self.browser ? self.browser->GetWebStateList()->GetActiveWebState() + : nullptr; +} + +- (UIView*)webViewContainer { + return self.browserContainerCoordinator.viewController.view; +} + @end
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm index 22f78bf..f9f4ce2 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator_unittest.mm
@@ -4,16 +4,17 @@ #import "ios/chrome/browser/ui/browser_view/browser_coordinator.h" -#include "base/files/file_util.h" -#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#include "ios/chrome/browser/download/download_directory_util.h" +#import "base/files/file_util.h" +#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/download/download_directory_util.h" #import "ios/chrome/browser/download/external_app_util.h" -#include "ios/chrome/browser/favicon/favicon_service_factory.h" -#include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" -#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/history/history_service_factory.h" -#include "ios/chrome/browser/main/test_browser.h" -#include "ios/chrome/browser/search_engines/template_url_service_factory.h" +#import "ios/chrome/browser/favicon/favicon_service_factory.h" +#import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" +#import "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" +#import "ios/chrome/browser/history/history_service_factory.h" +#import "ios/chrome/browser/main/test_browser.h" +#import "ios/chrome/browser/prerender/prerender_service_factory.h" +#import "ios/chrome/browser/search_engines/template_url_service_factory.h" #import "ios/chrome/browser/ui/commands/activity_service_commands.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_coordinator_commands.h" @@ -31,12 +32,12 @@ #import "ios/chrome/browser/web/web_state_delegate_browser_agent.h" #import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h" #import "ios/chrome/common/ui/reauthentication/reauthentication_module.h" -#include "ios/web/public/test/web_task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/gtest_mac.h" -#include "testing/platform_test.h" +#import "ios/web/public/test/web_task_environment.h" +#import "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" +#import "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" -#include "third_party/ocmock/gtest_support.h" +#import "third_party/ocmock/gtest_support.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -67,6 +68,9 @@ test_cbs_builder.AddTestingFactory( ios::HistoryServiceFactory::GetInstance(), ios::HistoryServiceFactory::GetDefaultFactory()); + test_cbs_builder.AddTestingFactory( + PrerenderServiceFactory::GetInstance(), + PrerenderServiceFactory::GetDefaultFactory()); chrome_browser_state_ = test_cbs_builder.Build(); browser_ = std::make_unique<TestBrowser>(chrome_browser_state_.get());
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.h b/ios/chrome/browser/ui/browser_view/browser_view_controller.h index 52d1521..ae08460 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.h +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.h
@@ -24,10 +24,13 @@ class Browser; @class BrowserContainerViewController; @class BrowserViewControllerDependencyFactory; +@class BubblePresenter; @class CommandDispatcher; @protocol CRWResponderInputView; @class DefaultBrowserPromoNonModalScheduler; @protocol DefaultPromoNonModalPresentationDelegate; +// TODO(crbug.com/1328039): Remove all use of the prerender service from BVC +class PrerenderService; @class ToolbarAccessoryPresenter; @protocol IncognitoReauthCommands; @@ -54,12 +57,15 @@ // |dispatcher| is the dispatcher instance this BVC will use. // TODO(crbug.com/992582): Remove references to model objects -- including // |browser| and |dispatcher| -- from this class. +// TODO(crbug.com/1328039): Remove all use of the prerender service from BVC - (instancetype)initWithBrowser:(Browser*)browser dependencyFactory: (BrowserViewControllerDependencyFactory*)factory browserContainerViewController: (BrowserContainerViewController*)browserContainerViewController dispatcher:(CommandDispatcher*)dispatcher + prerenderService:(PrerenderService*)prerenderService + bubblePresenter:(BubblePresenter*)bubblePresenter NS_DESIGNATED_INITIALIZER; - (instancetype)initWithNibName:(NSString*)nibNameOrNil
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index fb05ed5..8a7a6f99 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -8,31 +8,31 @@ #import <MaterialComponents/MaterialSnackbar.h> -#include "base/mac/bundle_locations.h" -#include "base/mac/foundation_util.h" -#include "base/metrics/histogram_macros.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.h" -#include "base/strings/sys_string_conversions.h" -#include "components/feature_engagement/public/event_constants.h" -#include "components/feature_engagement/public/tracker.h" -#include "components/omnibox/browser/location_bar_model_impl.h" -#include "components/reading_list/core/reading_list_model.h" -#include "components/sessions/core/tab_restore_service_helper.h" -#include "components/signin/ios/browser/active_state_manager.h" -#include "components/strings/grit/components_strings.h" -#include "components/translate/core/browser/translate_manager.h" -#include "components/ukm/ios/ukm_url_recorder.h" +#import "base/mac/bundle_locations.h" +#import "base/mac/foundation_util.h" +#import "base/metrics/histogram_macros.h" +#import "base/metrics/user_metrics.h" +#import "base/metrics/user_metrics_action.h" +#import "base/strings/sys_string_conversions.h" +#import "components/feature_engagement/public/event_constants.h" +#import "components/feature_engagement/public/tracker.h" +#import "components/omnibox/browser/location_bar_model_impl.h" +#import "components/reading_list/core/reading_list_model.h" +#import "components/sessions/core/tab_restore_service_helper.h" +#import "components/signin/ios/browser/active_state_manager.h" +#import "components/strings/grit/components_strings.h" +#import "components/translate/core/browser/translate_manager.h" +#import "components/ukm/ios/ukm_url_recorder.h" #import "ios/chrome/app/application_delegate/app_state.h" -#include "ios/chrome/browser/application_context.h" -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/crash_report/crash_keys_helper.h" -#include "ios/chrome/browser/discover_feed/feed_constants.h" -#include "ios/chrome/browser/feature_engagement/tracker_factory.h" -#include "ios/chrome/browser/feature_engagement/tracker_util.h" +#import "ios/chrome/browser/application_context.h" +#import "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/crash_report/crash_keys_helper.h" +#import "ios/chrome/browser/discover_feed/feed_constants.h" +#import "ios/chrome/browser/feature_engagement/tracker_factory.h" +#import "ios/chrome/browser/feature_engagement/tracker_util.h" #import "ios/chrome/browser/find_in_page/find_tab_helper.h" -#include "ios/chrome/browser/infobars/infobar_manager_impl.h" +#import "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/metrics/new_tab_page_uma.h" #import "ios/chrome/browser/metrics/tab_usage_recorder_browser_agent.h" @@ -44,11 +44,11 @@ #import "ios/chrome/browser/prerender/prerender_service.h" #import "ios/chrome/browser/prerender/prerender_service_factory.h" #import "ios/chrome/browser/reading_list/offline_page_tab_helper.h" -#include "ios/chrome/browser/reading_list/reading_list_model_factory.h" -#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" +#import "ios/chrome/browser/reading_list/reading_list_model_factory.h" +#import "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" -#include "ios/chrome/browser/signin/authentication_service.h" -#include "ios/chrome/browser/signin/authentication_service_factory.h" +#import "ios/chrome/browser/signin/authentication_service.h" +#import "ios/chrome/browser/signin/authentication_service_factory.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" #import "ios/chrome/browser/ssl/captive_portal_tab_helper.h" #import "ios/chrome/browser/ssl/captive_portal_tab_helper_delegate.h" @@ -80,13 +80,13 @@ #import "ios/chrome/browser/ui/fullscreen/fullscreen_features.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_element.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_ui_updater.h" -#include "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" +#import "ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h" #import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h" #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_commands.h" #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h" #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_view.h" #import "ios/chrome/browser/ui/infobars/infobar_positioner.h" -#include "ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h" +#import "ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.h" #import "ios/chrome/browser/ui/main/scene_state.h" #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h" #import "ios/chrome/browser/ui/main_content/main_content_ui.h" @@ -133,7 +133,7 @@ #import "ios/chrome/browser/ui/util/url_with_title.h" #import "ios/chrome/browser/ui/voice/text_to_speech_playback_controller.h" #import "ios/chrome/browser/ui/voice/text_to_speech_playback_controller_factory.h" -#include "ios/chrome/browser/upgrade/upgrade_center.h" +#import "ios/chrome/browser/upgrade/upgrade_center.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" #import "ios/chrome/browser/url_loading/url_loading_notifier_browser_agent.h" #import "ios/chrome/browser/url_loading/url_loading_observer_bridge.h" @@ -153,17 +153,17 @@ #import "ios/chrome/common/ui/colors/semantic_color_names.h" #import "ios/chrome/common/ui/promo_style/promo_style_view_controller.h" #import "ios/chrome/common/ui/util/constraints_ui_util.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ios/public/provider/chrome/browser/voice_search/voice_search_api.h" -#include "ios/public/provider/chrome/browser/voice_search/voice_search_controller.h" +#import "ios/chrome/grit/ios_strings.h" +#import "ios/public/provider/chrome/browser/voice_search/voice_search_api.h" +#import "ios/public/provider/chrome/browser/voice_search/voice_search_controller.h" #import "ios/web/public/deprecated/crw_js_injection_receiver.h" -#include "ios/web/public/navigation/navigation_item.h" +#import "ios/web/public/navigation/navigation_item.h" #import "ios/web/public/ui/crw_web_view_proxy.h" #import "ios/web/public/web_state_observer_bridge.h" #import "net/base/mac/url_conversions.h" -#include "services/metrics/public/cpp/ukm_builders.h" -#include "ui/base/device_form_factor.h" -#include "ui/base/l10n/l10n_util.h" +#import "services/metrics/public/cpp/ukm_builders.h" +#import "ui/base/device_form_factor.h" +#import "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -268,7 +268,6 @@ KeyCommandsPlumbing, MainContentUI, OmniboxPopupPresenterDelegate, - PreloadControllerDelegate, SideSwipeControllerDelegate, TabStripPresentation, UIGestureRecognizerDelegate, @@ -294,6 +293,9 @@ // management off of the BVC. KeyCommandsProvider* _keyCommandsProvider; + // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC + PrerenderService* _prerenderService; + // Used to display the Voice Search UI. Nil if not visible. id<VoiceSearchController> _voiceSearchController; @@ -529,7 +531,9 @@ (BrowserViewControllerDependencyFactory*)factory browserContainerViewController: (BrowserContainerViewController*)browserContainerViewController - dispatcher:(CommandDispatcher*)dispatcher { + dispatcher:(CommandDispatcher*)dispatcher + prerenderService:(PrerenderService*)prerenderService + bubblePresenter:(BubblePresenter*)bubblePresenter { self = [super initWithNibName:nil bundle:base::mac::FrameworkBundle()]; if (self) { DCHECK(factory); @@ -538,6 +542,9 @@ _commandDispatcher = dispatcher; _browserContainerViewController = browserContainerViewController; _dependencyFactory = factory; + // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC + _prerenderService = prerenderService; + _bubblePresenter = bubblePresenter; self.textZoomHandler = HandlerForProtocol(self.commandDispatcher, TextZoomCommands); [self.commandDispatcher @@ -889,7 +896,7 @@ } - (void)userEnteredTabSwitcher { - [self.bubblePresenter userEnteredTabSwitcher]; + [_bubblePresenter userEnteredTabSwitcher]; } - (void)openNewTabFromOriginPoint:(CGPoint)originPoint @@ -1166,8 +1173,9 @@ self.tabStripView = nil; } - [self.commandDispatcher stopDispatchingToTarget:self.bubblePresenter]; - self.bubblePresenter = nil; + [self.commandDispatcher stopDispatchingToTarget:_bubblePresenter]; + [_bubblePresenter stop]; + _bubblePresenter = nil; [self.commandDispatcher stopDispatchingToTarget:self]; self.browser->GetWebStateList()->RemoveObserver(_webStateListObserver.get()); @@ -1288,15 +1296,12 @@ // Install fake status bar for iPad iOS7 [self installFakeStatusBar]; - // TODO(crbug.com/1272534): Move BubblePresenter to BrowserCoordinator. - self.bubblePresenter = - [[BubblePresenter alloc] initWithBrowserState:self.browserState - delegate:self - rootViewController:self]; - self.bubblePresenter.toolbarHandler = + _bubblePresenter.delegate = self; + _bubblePresenter.rootViewController = self; + _bubblePresenter.toolbarHandler = HandlerForProtocol(self.browser->GetCommandDispatcher(), ToolbarCommands); [self.browser->GetCommandDispatcher() - startDispatchingToTarget:self.bubblePresenter + startDispatchingToTarget:_bubblePresenter forProtocol:@protocol(HelpCommands)]; [self buildToolbarAndTabStrip]; @@ -1798,15 +1803,6 @@ DCHECK([self isViewLoaded]); DCHECK(!_locationBarModelDelegate); - // Initialize the prerender service before creating the toolbar controller. - // TODO(crbug.com/1272532): Move this to BrowserCoordinator, after creating - // the BVC. - PrerenderService* prerenderService = - PrerenderServiceFactory::GetForBrowserState(self.browserState); - if (prerenderService) { - prerenderService->SetDelegate(self); - } - // Create the location bar model and controller. _locationBarModelDelegate.reset( new LocationBarModelDelegateIOS(self.browser->GetWebStateList())); @@ -1817,7 +1813,7 @@ self.popupMenuCoordinator = [[PopupMenuCoordinator alloc] initWithBaseViewController:self browser:self.browser]; - self.popupMenuCoordinator.bubblePresenter = self.bubblePresenter; + self.popupMenuCoordinator.bubblePresenter = _bubblePresenter; self.popupMenuCoordinator.UIUpdater = _toolbarCoordinatorAdaptor; [self.popupMenuCoordinator start]; @@ -2347,10 +2343,9 @@ if (!webState) return; - PrerenderService* prerenderService = - PrerenderServiceFactory::GetForBrowserState(self.browserState); + // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC BOOL isPrerendered = - (prerenderService && prerenderService->IsLoadingPrerender()); + (_prerenderService && _prerenderService->IsLoadingPrerender()); if (isPrerendered && ![self.helper isToolbarLoading:self.currentWebState]) [self.primaryToolbarCoordinator showPrerenderingAnimation]; @@ -2529,11 +2524,10 @@ if (!webState->IsRealized()) return; + // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC // There should be no pre-rendered Tabs for this BrowserState. - PrerenderService* prerenderService = - PrerenderServiceFactory::GetForBrowserState(self.browserState); - DCHECK(!prerenderService || - !prerenderService->IsWebStatePrerendered(webState)); + DCHECK(!_prerenderService || + !_prerenderService->IsWebStatePrerendered(webState)); CaptivePortalTabHelper::CreateForWebState(webState, self); @@ -2990,17 +2984,17 @@ - (web::WebState*)currentWebStateForBubblePresenter: (BubblePresenter*)bubblePresenter { - DCHECK(bubblePresenter == self.bubblePresenter); + DCHECK(bubblePresenter == _bubblePresenter); return self.currentWebState; } - (BOOL)rootViewVisibleForBubblePresenter:(BubblePresenter*)bubblePresenter { - DCHECK(bubblePresenter == self.bubblePresenter); + DCHECK(bubblePresenter == _bubblePresenter); return self.viewVisible; } - (BOOL)isTabScrolledToTopForBubblePresenter:(BubblePresenter*)bubblePresenter { - DCHECK(bubblePresenter == self.bubblePresenter); + DCHECK(bubblePresenter == _bubblePresenter); // If NTP exists, use NTP coordinator's scroll offset. if (self.isNTPActiveForCurrentWebState) { @@ -3609,9 +3603,8 @@ // Prerender tab does not have a toolbar, return |headerHeight| as promised by // API documentation. - PrerenderService* prerenderService = - PrerenderServiceFactory::GetForBrowserState(self.browserState); - if (prerenderService && prerenderService->IsLoadingPrerender()) + // TODO(crbug.com/1328039): Remove all use of the prerender service from BVC + if (_prerenderService && _prerenderService->IsLoadingPrerender()) return self.headerHeight; UIView* topHeader = headers[0].view; @@ -3804,24 +3797,6 @@ [self addURLsToReadingList:command.URLs]; } -// TODO(crbug.com/1272534): Move this command implementation to -// BrowserCoordinator, which should be owning bubblePresenter. -- (void)showReadingListIPH { - [self.bubblePresenter presentReadingListBottomToolbarTipBubble]; -} - -// TODO(crbug.com/1272534): Move this command implementation to -// BrowserCoordinator, which should be owning bubblePresenter. -- (void)showFollowWhileBrowsingIPH { - [self.bubblePresenter presentFollowWhileBrowsingTipBubble]; -} - -// TODO(crbug.com/1272534): Move this command implementation to -// BrowserCoordinator, which should be owning bubblePresenter. -- (void)showDefaultSiteViewIPH { - [self.bubblePresenter presentDefaultSiteViewTipBubble]; -} - - (void)preloadVoiceSearch { // Preload VoiceSearchController and views and view controllers needed // for voice search. @@ -3909,7 +3884,7 @@ [self.nonModalPromoScheduler logPopupMenuEntered]; if (type == PopupMenuCommandTypeToolsMenu) { - [self.bubblePresenter toolsMenuDisplayed]; + [_bubblePresenter toolsMenuDisplayed]; } } @@ -4361,16 +4336,6 @@ return self.primaryToolbarCoordinator.viewController.view; } -#pragma mark - PreloadControllerDelegate methods - -- (web::WebState*)webStateToReplace { - return self.currentWebState; -} - -- (UIView*)webViewContainer { - return self.contentArea; -} - #pragma mark - LogoAnimationControllerOwnerOwner (Public) - (id<LogoAnimationControllerOwner>)logoAnimationControllerOwner { @@ -4547,7 +4512,7 @@ newTabPageCoordinator.panGestureHandler = self.thumbStripPanHandler; newTabPageCoordinator.toolbarDelegate = self.toolbarInterface; newTabPageCoordinator.webState = webState; - newTabPageCoordinator.bubblePresenter = self.bubblePresenter; + newTabPageCoordinator.bubblePresenter = _bubblePresenter; newTabPageCoordinator.selectedFeed = NTPHelper->GetNextNTPFeedType(); newTabPageCoordinator.shouldScrollIntoFeed = NTPHelper->GetNextNTPScrolledToFeed(); @@ -4583,7 +4548,7 @@ browser:self.browser]; _ntpCoordinator.panGestureHandler = self.thumbStripPanHandler; _ntpCoordinator.toolbarDelegate = self.toolbarInterface; - _ntpCoordinator.bubblePresenter = self.bubblePresenter; + _ntpCoordinator.bubblePresenter = _bubblePresenter; } return _ntpCoordinator; }
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm index a22067ee..862f2e3 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -8,18 +8,19 @@ #import <Foundation/Foundation.h> #import <PassKit/PassKit.h> -#include <memory> +#import <memory> -#include "components/open_from_clipboard/fake_clipboard_recent_content.h" -#include "components/search_engines/template_url_service.h" +#import "components/open_from_clipboard/fake_clipboard_recent_content.h" +#import "components/search_engines/template_url_service.h" #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#include "ios/chrome/browser/favicon/favicon_service_factory.h" -#include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" -#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/history/history_service_factory.h" +#import "ios/chrome/browser/favicon/favicon_service_factory.h" +#import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" +#import "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" +#import "ios/chrome/browser/history/history_service_factory.h" #import "ios/chrome/browser/main/test_browser.h" -#include "ios/chrome/browser/search_engines/template_url_service_factory.h" -#include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" +#import "ios/chrome/browser/prerender/fake_prerender_service.h" +#import "ios/chrome/browser/search_engines/template_url_service_factory.h" +#import "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" #import "ios/chrome/browser/sessions/test_session_service.h" #import "ios/chrome/browser/tabs/tab_helper_util.h" @@ -27,6 +28,7 @@ #import "ios/chrome/browser/ui/browser_view/browser_view_controller_dependency_factory.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller_helper.h" #import "ios/chrome/browser/ui/browser_view/key_commands_provider.h" +#import "ios/chrome/browser/ui/bubble/bubble_presenter.h" #import "ios/chrome/browser/ui/commands/activity_service_commands.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" @@ -35,22 +37,22 @@ #import "ios/chrome/browser/ui/commands/text_zoom_commands.h" #import "ios/chrome/browser/ui/main/scene_state.h" #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h" -#include "ios/chrome/browser/ui/util/ui_util.h" +#import "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/url_loading/url_loading_notifier_browser_agent.h" #import "ios/chrome/browser/web/web_navigation_browser_agent.h" -#include "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h" -#include "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.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/chrome/browser/web_state_list/web_usage_enabler/web_usage_enabler_browser_agent.h" -#include "ios/chrome/test/block_cleanup_test.h" -#include "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" -#include "ios/web/public/test/web_task_environment.h" +#import "ios/chrome/test/block_cleanup_test.h" +#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" +#import "ios/web/public/test/web_task_environment.h" #import "ios/web/public/web_state.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "testing/gtest_mac.h" +#import "testing/gmock/include/gmock/gmock.h" +#import "testing/gtest/include/gtest/gtest.h" +#import "testing/gtest_mac.h" #import "third_party/ocmock/OCMock/OCMock.h" -#include "third_party/ocmock/gtest_support.h" +#import "third_party/ocmock/gtest_support.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -180,12 +182,19 @@ ClipboardRecentContent::SetInstance( std::make_unique<FakeClipboardRecentContent>()); + fake_prerender_service_ = std::make_unique<FakePrerenderService>(); + + bubble_presenter_ = [[BubblePresenter alloc] + initWithBrowserState:chrome_browser_state_.get()]; + container_ = [[BrowserContainerViewController alloc] init]; bvc_ = [[BrowserViewController alloc] initWithBrowser:browser_.get() dependencyFactory:factory browserContainerViewController:container_ - dispatcher:browser_->GetCommandDispatcher()]; + dispatcher:browser_->GetCommandDispatcher() + prerenderService:fake_prerender_service_.get() + bubblePresenter:bubble_presenter_]; // Force the view to load. UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectZero]; @@ -210,10 +219,12 @@ IOSChromeScopedTestingLocalState local_state_; std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; std::unique_ptr<Browser> browser_; + std::unique_ptr<PrerenderService> fake_prerender_service_; BrowserViewControllerHelper* bvcHelper_; PKAddPassesViewController* passKitViewController_; OCMockObject* dependencyFactory_; CommandDispatcher* command_dispatcher_; + BubblePresenter* bubble_presenter_; BrowserContainerViewController* container_; BrowserViewController* bvc_; UIWindow* window_;
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.h b/ios/chrome/browser/ui/bubble/bubble_presenter.h index fe608c4..043d99e8 100644 --- a/ios/chrome/browser/ui/bubble/bubble_presenter.h +++ b/ios/chrome/browser/ui/bubble/bubble_presenter.h
@@ -20,8 +20,6 @@ // Initializes a BubblePresenter whose bubbles are presented on the // |rootViewController|. - (instancetype)initWithBrowserState:(ChromeBrowserState*)browserState - delegate:(id<BubblePresenterDelegate>)delegate - rootViewController:(UIViewController*)rootViewController NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @@ -30,8 +28,12 @@ @property(nonatomic, strong, readonly) BubbleViewControllerPresenter* incognitoTabTipBubblePresenter; +@property(nonatomic, weak) id<BubblePresenterDelegate> delegate; +@property(nonatomic, weak) UIViewController* rootViewController; @property(nonatomic, weak) id<ToolbarCommands> toolbarHandler; +- (void)stop; + // Notifies the presenter that the user entered the tab switcher. - (void)userEnteredTabSwitcher;
diff --git a/ios/chrome/browser/ui/bubble/bubble_presenter.mm b/ios/chrome/browser/ui/bubble/bubble_presenter.mm index 79502d7d..e98c8d4 100644 --- a/ios/chrome/browser/ui/bubble/bubble_presenter.mm +++ b/ios/chrome/browser/ui/bubble/bubble_presenter.mm
@@ -4,31 +4,31 @@ #import "ios/chrome/browser/ui/bubble/bubble_presenter.h" -#include "base/bind.h" -#include "base/metrics/histogram_functions.h" -#include "base/metrics/user_metrics.h" -#include "base/metrics/user_metrics_action.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 "ios/chrome/browser/browser_state/chrome_browser_state.h" -#include "ios/chrome/browser/chrome_url_constants.h" -#include "ios/chrome/browser/feature_engagement/tracker_factory.h" +#import "base/bind.h" +#import "base/metrics/histogram_functions.h" +#import "base/metrics/user_metrics.h" +#import "base/metrics/user_metrics_action.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 "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/feature_engagement/tracker_factory.h" #import "ios/chrome/browser/ui/bubble/bubble_presenter_delegate.h" #import "ios/chrome/browser/ui/bubble/bubble_util.h" #import "ios/chrome/browser/ui/bubble/bubble_view_controller_presenter.h" #import "ios/chrome/browser/ui/commands/toolbar_commands.h" #import "ios/chrome/browser/ui/util/named_guide.h" #import "ios/chrome/browser/ui/util/named_guide_util.h" -#include "ios/chrome/browser/ui/util/ui_util.h" +#import "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" -#include "ios/chrome/grit/ios_chromium_strings.h" -#include "ios/chrome/grit/ios_strings.h" +#import "ios/chrome/grit/ios_chromium_strings.h" +#import "ios/chrome/grit/ios_strings.h" #import "ios/web/public/ui/crw_web_view_proxy.h" #import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h" #import "ios/web/public/web_state.h" -#include "ui/base/device_form_factor.h" -#include "ui/base/l10n/l10n_util.h" +#import "ui/base/device_form_factor.h" +#import "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -68,8 +68,6 @@ BubbleViewControllerPresenter* defaultPageModeTipBubblePresenter; @property(nonatomic, assign) ChromeBrowserState* browserState; -@property(nonatomic, weak) id<BubblePresenterDelegate> delegate; -@property(nonatomic, weak) UIViewController* rootViewController; @end @@ -77,18 +75,18 @@ #pragma mark - Public -- (instancetype)initWithBrowserState:(ChromeBrowserState*)browserState - delegate:(id<BubblePresenterDelegate>)delegate - rootViewController:(UIViewController*)rootViewController { +- (instancetype)initWithBrowserState:(ChromeBrowserState*)browserState { self = [super init]; if (self) { _browserState = browserState; - _delegate = delegate; - _rootViewController = rootViewController; } return self; } +- (void)stop { + _browserState = nil; +} + - (void)showHelpBubbleIfEligible { DCHECK(self.browserState); // Waits to present the bubbles until the feature engagement tracker database @@ -484,7 +482,9 @@ // Returns whether the tab can present a bubble tip. - (BOOL)canPresentBubble { - DCHECK(self.browserState); + // If BubblePresenter has been stopped, do not present the bubble. + if (!self.browserState) + return NO; // If the BVC is not visible, do not present the bubble. if (![self.delegate rootViewVisibleForBubblePresenter:self]) return NO; @@ -524,12 +524,7 @@ __weak BubblePresenter* weakSelf = self; ProceduralBlockWithSnoozeAction dismissalCallback = ^(feature_engagement::Tracker::SnoozeAction snoozeAction) { - BubblePresenter* strongSelf = weakSelf; - if (strongSelf) { - feature_engagement::TrackerFactory::GetForBrowserState( - strongSelf.browserState) - ->DismissedWithSnooze(feature, snoozeAction); - } + [weakSelf featureDismissed:feature withSnooze:snoozeAction]; }; BubbleViewControllerPresenter* bubbleViewControllerPresenter = @@ -541,4 +536,13 @@ return bubbleViewControllerPresenter; } +- (void)featureDismissed:(const base::Feature&)feature + withSnooze: + (feature_engagement::Tracker::SnoozeAction)snoozeAction { + if (!self.browserState) + return; + feature_engagement::TrackerFactory::GetForBrowserState(self.browserState) + ->DismissedWithSnooze(feature, snoozeAction); +} + @end
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index e36d79a..3e20f48d9 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -50,18 +50,6 @@ // TODO(crbug.com/1272540): Remove this command. - (void)addToReadingList:(ReadingListAddCommand*)command; -// Shows an IPH pointing to where the Reading List entry point is, if -// applicable. -- (void)showReadingListIPH; - -// Shows an IPH pointing to where the Follow entry point is, if -// applicable. -- (void)showFollowWhileBrowsingIPH; - -// Shows an IPH to explain to the user how to change the default site view, if -// applicable. -- (void)showDefaultSiteViewIPH; - // Preloads voice search on the current BVC. - (void)preloadVoiceSearch;
diff --git a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h index e4299d8..9f985c9 100644 --- a/ios/chrome/browser/ui/commands/browser_coordinator_commands.h +++ b/ios/chrome/browser/ui/commands/browser_coordinator_commands.h
@@ -30,6 +30,18 @@ // Shows the Reading List UI. - (void)showReadingList; +// Shows an IPH pointing to where the Reading List entry point is, if +// applicable. +- (void)showReadingListIPH; + +// Shows an IPH pointing to where the Follow entry point is, if +// applicable. +- (void)showFollowWhileBrowsingIPH; + +// Shows an IPH to explain to the user how to change the default site view, if +// applicable. +- (void)showDefaultSiteViewIPH; + // Shows recent tabs. - (void)showRecentTabs;
diff --git a/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm index de5546f..bc438f0f 100644 --- a/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_view_controller.mm
@@ -24,7 +24,7 @@ - (void)viewDidLoad { self.view.accessibilityIdentifier = first_run::kFirstRunDefaultBrowserScreenAccessibilityIdentifier; - self.bannerImage = [UIImage imageNamed:@"default_browser_screen_banner"]; + self.bannerName = @"default_browser_screen_banner"; self.titleText = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_DEFAULT_BROWSER_SCREEN_TITLE); self.subtitleText =
diff --git a/ios/chrome/browser/ui/first_run/legacy_signin/legacy_signin_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/legacy_signin/legacy_signin_screen_view_controller.mm index 9db8e0e1..e16607d 100644 --- a/ios/chrome/browser/ui/first_run/legacy_signin/legacy_signin_screen_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/legacy_signin/legacy_signin_screen_view_controller.mm
@@ -110,9 +110,8 @@ bool signinRestricted = self.enterpriseSignInRestrictions || forceSignInEnabled; - self.bannerImage = [UIImage - imageNamed:signinRestricted ? @"legacy_forced_signin_screen_banner" - : @"legacy_signin_screen_banner"]; + self.bannerName = signinRestricted ? @"legacy_forced_signin_screen_banner" + : @"legacy_signin_screen_banner"; // Only add "Don't Sign In" button when signin is not required. if (!forceSignInEnabled) { self.secondaryActionString =
diff --git a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm index df9485c..51daf1c 100644 --- a/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/signin/signin_screen_view_controller.mm
@@ -65,7 +65,7 @@ l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SCREEN_READ_MORE); // Set banner. - self.bannerImage = [UIImage imageNamed:kSigninBannerName]; + self.bannerName = kSigninBannerName; // Set |self.titleText| and |self.subtitleText|. switch (self.signinStatus) {
diff --git a/ios/chrome/browser/ui/first_run/sync/sync_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/sync/sync_screen_view_controller.mm index 92ac6f0..a87cca25 100644 --- a/ios/chrome/browser/ui/first_run/sync/sync_screen_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/sync/sync_screen_view_controller.mm
@@ -68,7 +68,7 @@ self.primaryActionString = [self contentTextWithStringID:self.activateSyncButtonID]; - self.bannerImage = [UIImage imageNamed:@"sync_screen_banner"]; + self.bannerName = @"sync_screen_banner"; self.isTallBanner = NO; self.scrollToEndMandatory = YES; self.readMoreString =
diff --git a/ios/chrome/browser/ui/first_run/welcome/welcome_screen_view_controller.mm b/ios/chrome/browser/ui/first_run/welcome/welcome_screen_view_controller.mm index e6550bf4..3f1ced8 100644 --- a/ios/chrome/browser/ui/first_run/welcome/welcome_screen_view_controller.mm +++ b/ios/chrome/browser/ui/first_run/welcome/welcome_screen_view_controller.mm
@@ -69,7 +69,7 @@ [self configureLabels]; self.view.accessibilityIdentifier = first_run::kFirstRunWelcomeScreenAccessibilityIdentifier; - self.bannerImage = [UIImage imageNamed:@"welcome_screen_banner"]; + self.bannerName = @"welcome_screen_banner"; self.isTallBanner = YES; self.scrollToEndMandatory = YES; self.readMoreString =
diff --git a/ios/chrome/browser/ui/infobars/modals/infobar_translate_table_view_controller.mm b/ios/chrome/browser/ui/infobars/modals/infobar_translate_table_view_controller.mm index 160ef8b..b39cf6c8 100644 --- a/ios/chrome/browser/ui/infobars/modals/infobar_translate_table_view_controller.mm +++ b/ios/chrome/browser/ui/infobars/modals/infobar_translate_table_view_controller.mm
@@ -241,11 +241,16 @@ cellForRowAtIndexPath:indexPath]; ItemType itemType = static_cast<ItemType>( [self.tableViewModel itemTypeForIndexPath:indexPath]); + TableViewTextButtonCell* tableViewTextButtonCell = + base::mac::ObjCCast<TableViewTextButtonCell>(cell); + // Clear the existing targets before adding the new ones. + [tableViewTextButtonCell.button removeTarget:nil + action:nil + forControlEvents:UIControlEventAllEvents]; switch (itemType) { case ItemTypeTranslateButton: { - TableViewTextButtonCell* tableViewTextButtonCell = - base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell); + DCHECK(tableViewTextButtonCell); tableViewTextButtonCell.selectionStyle = UITableViewCellSelectionStyleNone; [tableViewTextButtonCell.button @@ -256,8 +261,7 @@ break; } case ItemTypeShowOriginalButton: { - TableViewTextButtonCell* tableViewTextButtonCell = - base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell); + DCHECK(tableViewTextButtonCell); tableViewTextButtonCell.selectionStyle = UITableViewCellSelectionStyleNone; [tableViewTextButtonCell.button addTarget:self.infobarModalDelegate @@ -266,8 +270,7 @@ break; } case ItemTypeAlwaysTranslateSource: { - TableViewTextButtonCell* tableViewTextButtonCell = - base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell); + DCHECK(tableViewTextButtonCell); tableViewTextButtonCell.selectionStyle = UITableViewCellSelectionStyleNone; if (self.shouldAlwaysTranslate) { @@ -284,8 +287,7 @@ break; } case ItemTypeNeverTranslateSource: { - TableViewTextButtonCell* tableViewTextButtonCell = - base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell); + DCHECK(tableViewTextButtonCell); tableViewTextButtonCell.selectionStyle = UITableViewCellSelectionStyleNone; if (self.isTranslatableLanguage) { @@ -302,8 +304,7 @@ break; } case ItemTypeNeverTranslateSite: { - TableViewTextButtonCell* tableViewTextButtonCell = - base::mac::ObjCCastStrict<TableViewTextButtonCell>(cell); + DCHECK(tableViewTextButtonCell); tableViewTextButtonCell.selectionStyle = UITableViewCellSelectionStyleNone; if (self.isSiteOnNeverPromptList) {
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index 0534f2f..c5962052 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -337,6 +337,7 @@ "//ios/chrome/browser/history", "//ios/chrome/browser/main", "//ios/chrome/browser/main:test_support", + "//ios/chrome/browser/prerender", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/sessions:restoration_agent", "//ios/chrome/browser/sessions:scene_util_test_support",
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm index 3888198f..aba04c7 100644 --- a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm +++ b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
@@ -6,25 +6,26 @@ #import <UIKit/UIKit.h> -#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" -#include "ios/chrome/browser/favicon/favicon_service_factory.h" -#include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" -#include "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" -#include "ios/chrome/browser/history/history_service_factory.h" +#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h" +#import "ios/chrome/browser/favicon/favicon_service_factory.h" +#import "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" +#import "ios/chrome/browser/favicon/ios_chrome_large_icon_service_factory.h" +#import "ios/chrome/browser/history/history_service_factory.h" #import "ios/chrome/browser/main/browser_list.h" #import "ios/chrome/browser/main/browser_list_factory.h" #import "ios/chrome/browser/main/test_browser_list_observer.h" -#include "ios/chrome/browser/search_engines/template_url_service_factory.h" +#import "ios/chrome/browser/prerender/prerender_service_factory.h" +#import "ios/chrome/browser/search_engines/template_url_service_factory.h" #import "ios/chrome/browser/sessions/scene_util_test_support.h" -#include "ios/chrome/browser/sessions/session_restoration_browser_agent.h" +#import "ios/chrome/browser/sessions/session_restoration_browser_agent.h" #import "ios/chrome/browser/sessions/test_session_service.h" #import "ios/chrome/browser/sync/send_tab_to_self_sync_service_factory.h" #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h" #import "ios/chrome/browser/ui/main/scene_state.h" #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h" #import "ios/testing/scoped_block_swizzler.h" -#include "ios/web/public/test/web_task_environment.h" -#include "testing/platform_test.h" +#import "ios/web/public/test/web_task_environment.h" +#import "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -78,6 +79,9 @@ test_cbs_builder.AddTestingFactory( ios::HistoryServiceFactory::GetInstance(), ios::HistoryServiceFactory::GetDefaultFactory()); + test_cbs_builder.AddTestingFactory( + PrerenderServiceFactory::GetInstance(), + PrerenderServiceFactory::GetDefaultFactory()); chrome_browser_state_ = test_cbs_builder.Build();
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_provider.swift b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_provider.swift index 9842f93..dab52776 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_provider.swift +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_provider.swift
@@ -72,8 +72,15 @@ // gets accurate spacing. let omniboxFrameInView = omniboxGuide.constrainedView.convert( omniboxGuide.constrainedView.bounds, to: view) - uiConfiguration.omniboxLeadingSpace = omniboxFrameInView.minX - uiConfiguration.omniboxTrailingSpace = view.bounds.width - omniboxFrameInView.maxX + + let isLTR = + UIApplication.shared.userInterfaceLayoutDirection + == UIUserInterfaceLayoutDirection.leftToRight + + uiConfiguration.omniboxLeadingSpace = + isLTR ? omniboxFrameInView.minX : view.frame.size.width - omniboxFrameInView.maxX + uiConfiguration.omniboxTrailingSpace = + isLTR ? view.bounds.width - omniboxFrameInView.maxX : omniboxFrameInView.minX let safeAreaFrame = safeAreaGuide.layoutFrame uiConfiguration.safeAreaTrailingSpace = view.bounds.width - safeAreaFrame.maxX @@ -81,12 +88,16 @@ let omniboxLeadingImageFrameInView = omniboxLeadingImageGuide.constrainedView.convert( omniboxLeadingImageGuide.constrainedView.bounds, to: view) uiConfiguration.omniboxLeadingImageLeadingSpace = - omniboxLeadingImageFrameInView.midX - omniboxFrameInView.minX + isLTR + ? omniboxLeadingImageFrameInView.minX - omniboxFrameInView.minX + : omniboxFrameInView.maxX - omniboxLeadingImageFrameInView.maxX let omniboxTextFieldFrameInView = omniboxTextFieldGuide.constrainedView.convert( omniboxTextFieldGuide.constrainedView.bounds, to: view) uiConfiguration.omniboxTextFieldLeadingSpace = - omniboxTextFieldFrameInView.minX - omniboxFrameInView.minX + isLTR + ? omniboxTextFieldFrameInView.minX - omniboxFrameInView.minX + : omniboxFrameInView.maxX - omniboxTextFieldFrameInView.maxX } var hasContent: Bool {
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/gradient_text_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/gradient_text_view.swift index 58b6e23..8012832e 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/gradient_text_view.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/gradient_text_view.swift
@@ -71,11 +71,11 @@ } - @Environment(\.popupUIVariation) var uiVariation: PopupUIVariation + @Environment(\.layoutDirection) var layoutDirection: LayoutDirection var body: some View { // This is equivalent to left/right since the locale is ignored below. - let variationTwoAlignment: Alignment = isTextLTR ? .leading : .trailing + let alignment: Alignment = layoutDirection == .leftToRight ? .leading : .trailing ZStack { // Render text at full size inside a fixed-size container. @@ -103,7 +103,7 @@ let contents = VStack { text } .frame( width: geometry.size.width, - alignment: uiVariation == .one ? .leading : variationTwoAlignment + alignment: alignment ) // Force LTR layout direction to prevent incorrect behavior in RTL locales. // The goal is to deal with the text language, not the user's locale.
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift index 9c6f094..c2963459 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_match_row_view.swift
@@ -82,7 +82,7 @@ Spacer().frame( width: leadingMarginForRowContent + spaceBetweenRowContentLeadingEdgeAndSuggestionText) customSeparatorColor.frame(height: 0.5) - }.environment(\.layoutDirection, .leftToRight) + } } @Environment(\.layoutDirection) var layoutDirection: LayoutDirection @@ -90,9 +90,9 @@ var leadingMarginForRowContent: CGFloat { switch uiVariation { case .one: - return uiConfiguration.omniboxLeadingSpace + return uiConfiguration.omniboxLeadingSpace + 7 case .two: - return 0 + return 8 } } @@ -114,6 +114,15 @@ } } + var spaceBetweenTextAndImage: CGFloat { + switch uiVariation { + case .one: + return 14 + case .two: + return 15 + } + } + var spaceBetweenRowContentLeadingEdgeAndSuggestionText: CGFloat { switch uiVariation { case .one: @@ -148,20 +157,18 @@ // The content is in front of the button, for proper hit testing. HStack(alignment: .center, spacing: 0) { Color.clear.frame(width: leadingMarginForRowContent) - HStack(alignment: .center, spacing: 0) { - Color.clear.frame( - width: spaceBetweenRowContentLeadingEdgeAndCenterOfSuggestionImage - - PopupMatchImageView.Dimension.image / 2) - match.image - .map { image in - PopupMatchImageView( - image: image, highlightColor: highlightColor - ) - .accessibilityHidden(true) - .clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous)) - } - Spacer() - }.frame(width: spaceBetweenRowContentLeadingEdgeAndSuggestionText) + + match.image + .map { image in + PopupMatchImageView( + image: image, highlightColor: highlightColor + ) + .accessibilityHidden(true) + .clipShape(RoundedRectangle(cornerRadius: 7, style: .continuous)) + } + + Color.clear.frame(width: spaceBetweenTextAndImage) + VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) { GradientTextView(match.text, highlightColor: highlightColor) @@ -190,14 +197,13 @@ if match.isAppendable || match.isTabMatch { PopupMatchTrailingButton(match: match, action: trailingButtonHandler) .foregroundColor(isHighlighted ? highlightColor : .chromeBlue) - .environment(\.layoutDirection, layoutDirection) } Color.clear.frame(width: trailingMarginForRowContent) } .padding( uiVariation == .one ? Dimensions.VariationOne.padding : Dimensions.VariationTwo.padding ) - .environment(\.layoutDirection, .leftToRight) + .environment(\.layoutDirection, layoutDirection) } .frame(maxWidth: .infinity, minHeight: Dimensions.minHeight) }
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_model.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_model.swift index d6189cc9..794607a 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_model.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_model.swift
@@ -20,6 +20,7 @@ @Published var sections: [PopupMatchSection] @Published var highlightedMatchIndexPath: IndexPath? + @Published var rtlContentAttribute: UISemanticContentAttribute = .forceLeftToRight /// Index of the preselected section when no row is highlighted. var preselectedSectionIndex: Int @@ -56,7 +57,9 @@ } public func setTextAlignment(_ alignment: NSTextAlignment) {} - public func setSemanticContentAttribute(_ semanticContentAttribute: UISemanticContentAttribute) {} + public func setSemanticContentAttribute(_ semanticContentAttribute: UISemanticContentAttribute) { + rtlContentAttribute = semanticContentAttribute + } } // MARK: OmniboxSuggestionCommands
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift index a9d028d0..e3efc02 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_ui_configuration.swift
@@ -116,4 +116,15 @@ UIConfiguration.omniboxTextFieldLeadingSpace = 140 return UIConfiguration } + + public override var description: String { + var description = "\(type(of: self)): " + description += "omniboxLeadingSpace=\(omniboxLeadingSpace), " + description += "omniboxTrailingSpace=\(omniboxTrailingSpace), " + description += "safeAreaTrailingSpace=\(safeAreaTrailingSpace), " + description += "omniboxLeadingImageLeadingSpace=\(omniboxLeadingImageLeadingSpace), " + description += "omniboxTextFieldLeadingSpace=\(omniboxTextFieldLeadingSpace), " + description += ";" + return description + } }
diff --git a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift index 4eaf25ab..820a35f 100644 --- a/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift +++ b/ios/chrome/browser/ui/omnibox/popup/shared/popup_view.swift
@@ -160,6 +160,15 @@ @ViewBuilder func sectionContents( _ sectionIndex: Int, _ section: PopupMatchSection, _ geometry: GeometryProxy ) -> some View { + + let layoutDirection = + (model.rtlContentAttribute == .unspecified) + ? (UIApplication.shared.userInterfaceLayoutDirection + == UIUserInterfaceLayoutDirection.leftToRight + ? LayoutDirection.leftToRight : LayoutDirection.rightToLeft) + : ((model.rtlContentAttribute == .forceLeftToRight) + ? LayoutDirection.leftToRight : LayoutDirection.rightToLeft) + ForEach(Array(zip(section.matches.indices, section.matches)), id: \.0) { matchIndex, match in let indexPath = IndexPath(row: matchIndex, section: sectionIndex) @@ -286,7 +295,6 @@ var body: some View { listView .onAppear(perform: onAppear) - .environment(\.layoutDirection, .leftToRight) } @ViewBuilder @@ -441,6 +449,12 @@ ).previewDevice(PreviewDevice(rawValue: "iPhone 13 mini")) sample.environment(\.popupUIVariation, .one) + .environment(\.locale, .init(identifier: "ar")) + + sample.environment(\.popupUIVariation, .two) + .environment(\.locale, .init(identifier: "ar")) + + sample.environment(\.popupUIVariation, .one) sample.environment(\.popupUIVariation, .two) sample.environment(\.locale, .init(identifier: "ar"))
diff --git a/ios/chrome/browser/ui/passwords/BUILD.gn b/ios/chrome/browser/ui/passwords/BUILD.gn index cad1aa1..ee3cf13 100644 --- a/ios/chrome/browser/ui/passwords/BUILD.gn +++ b/ios/chrome/browser/ui/passwords/BUILD.gn
@@ -30,6 +30,7 @@ "//components/password_manager/core/common:features", "//components/safe_browsing/core/browser/password_protection:password_protection_metrics_util", "//components/strings:components_strings_grit", + "//components/ukm/ios:ukm_url_recorder", "//ios/chrome/app/strings", "//ios/chrome/browser", "//ios/chrome/browser/autofill:autofill_shared",
diff --git a/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm b/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm index d051ed6..2faf39a 100644 --- a/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm +++ b/ios/chrome/browser/ui/passwords/password_breach_coordinator.mm
@@ -5,9 +5,12 @@ #import "ios/chrome/browser/ui/passwords/password_breach_coordinator.h" #include "base/metrics/histogram_macros.h" +#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/browser/manage_passwords_referrer.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #include "components/password_manager/core/browser/ui/password_check_referrer.h" #include "components/strings/grit/components_strings.h" +#import "components/ukm/ios/ukm_url_recorder.h" #import "ios/chrome/browser/main/browser.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" @@ -15,7 +18,9 @@ #import "ios/chrome/browser/ui/passwords/password_breach_mediator.h" #import "ios/chrome/browser/ui/passwords/password_breach_presenter.h" #import "ios/chrome/browser/ui/passwords/password_breach_view_controller.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/common/ui/elements/popover_label_view_controller.h" +#import "ios/web/public/web_state.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" @@ -37,6 +42,9 @@ // Main mediator for this coordinator. @property(nonatomic, strong) PasswordBreachMediator* mediator; +// UKM SourceId of the active WebState. +@property(nonatomic, assign) ukm::SourceId ukm_source_id; + // Leak type of the dialog. @property(nonatomic, assign) CredentialLeakType leakType; @@ -53,6 +61,9 @@ self = [super initWithBaseViewController:baseViewController browser:browser]; if (self) { _leakType = leakType; + web::WebState* web_state = browser->GetWebStateList()->GetActiveWebState(); + _ukm_source_id = web_state ? ukm::GetSourceIdForWebStateDocument(web_state) + : ukm::kInvalidSourceId; } return self; } @@ -61,9 +72,14 @@ self.viewController = [[PasswordBreachViewController alloc] init]; self.viewController.modalPresentationStyle = UIModalPresentationFormSheet; self.viewController.modalInPresentation = YES; + + auto recorder = std::make_unique< + password_manager::metrics_util::LeakDialogMetricsRecorder>( + self.ukm_source_id, password_manager::GetLeakDialogType(self.leakType)); self.mediator = [[PasswordBreachMediator alloc] initWithConsumer:self.viewController presenter:self + metrics_recorder:std::move(recorder) leakType:self.leakType]; self.viewController.actionHandler = self.mediator;
diff --git a/ios/chrome/browser/ui/passwords/password_breach_mediator.h b/ios/chrome/browser/ui/passwords/password_breach_mediator.h index e216004a..09180d7 100644 --- a/ios/chrome/browser/ui/passwords/password_breach_mediator.h +++ b/ios/chrome/browser/ui/passwords/password_breach_mediator.h
@@ -8,6 +8,7 @@ #import <Foundation/Foundation.h> #include "components/password_manager/core/browser/leak_detection_dialog_utils.h" +#include "components/password_manager/core/browser/password_manager_metrics_util.h" #import "ios/chrome/common/ui/confirmation_alert/confirmation_alert_action_handler.h" @protocol ApplicationCommands; @@ -17,9 +18,14 @@ // Manages the state and interactions of the consumer. @interface PasswordBreachMediator : NSObject <ConfirmationAlertActionHandler> -- (instancetype)initWithConsumer:(id<PasswordBreachConsumer>)consumer - presenter:(id<PasswordBreachPresenter>)presenter - leakType:(password_manager::CredentialLeakType)leakType; +- (instancetype) + initWithConsumer:(id<PasswordBreachConsumer>)consumer + presenter:(id<PasswordBreachPresenter>)presenter + metrics_recorder: + (std::unique_ptr< + password_manager::metrics_util::LeakDialogMetricsRecorder>) + metrics_recorder + leakType:(password_manager::CredentialLeakType)leakType; - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/passwords/password_breach_mediator.mm b/ios/chrome/browser/ui/passwords/password_breach_mediator.mm index aeebcefb..f50851da 100644 --- a/ios/chrome/browser/ui/passwords/password_breach_mediator.mm +++ b/ios/chrome/browser/ui/passwords/password_breach_mediator.mm
@@ -27,14 +27,17 @@ using password_manager::GetCancelButtonLabel; using password_manager::GetDescription; using password_manager::GetLeakDialogType; -using password_manager::GetTitle; using password_manager::GetPasswordCheckupURL; +using password_manager::GetTitle; using password_manager::ShouldCheckPasswords; using password_manager::metrics_util::LeakDialogDismissalReason; +using password_manager::metrics_util::LeakDialogMetricsRecorder; using password_manager::metrics_util::LeakDialogType; -using password_manager::metrics_util::LogLeakDialogTypeAndDismissalReason; -@interface PasswordBreachMediator () +@interface PasswordBreachMediator () { + // Metrics recorder for UMA and UKM + std::unique_ptr<LeakDialogMetricsRecorder> recorder; +} // Leak type of the dialog. @property(nonatomic, assign) LeakDialogType leakType; @@ -54,6 +57,8 @@ - (instancetype)initWithConsumer:(id<PasswordBreachConsumer>)consumer presenter:(id<PasswordBreachPresenter>)presenter + metrics_recorder: + (std::unique_ptr<LeakDialogMetricsRecorder>)metrics_recorder leakType:(CredentialLeakType)leakType { self = [super init]; if (self) { @@ -62,6 +67,8 @@ _leakType = GetLeakDialogType(leakType); _dismissReason = LeakDialogDismissalReason::kNoDirectInteraction; + recorder = std::move(metrics_recorder); + if (base::FeatureList::IsEnabled( password_manager::features:: kIOSEnablePasswordManagerBrandingUpdate)) { @@ -96,7 +103,7 @@ } - (void)disconnect { - LogLeakDialogTypeAndDismissalReason(self.leakType, self.dismissReason); + recorder->LogLeakDialogTypeAndDismissalReason(self.dismissReason); } #pragma mark - ConfirmationAlertActionHandler
diff --git a/ios/chrome/browser/ui/settings/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm index d99b4a7..1a9a54f 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_in_other_apps/passwords_in_other_apps_view_controller.mm
@@ -51,7 +51,9 @@ // Properties set on initialization. @property(nonatomic, copy, readonly) NSString* titleText; @property(nonatomic, copy, readonly) NSString* subtitleText; -@property(nonatomic, strong, readonly) UIImage* bannerImage; +// Whether banner is light or dark mode +@property(nonatomic, assign) UIUserInterfaceStyle bannerStyle; +@property(nonatomic, copy, readonly) NSString* bannerName; @property(nonatomic, copy, readonly) NSString* actionString; // Visible UI components. @@ -108,14 +110,13 @@ IDS_IOS_SETTINGS_PASSWORDS_IN_OTHER_APPS_SUBTITLE_IPHONE); } - _bannerImage = - [UIImage imageNamed:@"settings_passwords_in_other_apps_banner"]; + _bannerName = @"settings_passwords_in_other_apps_banner"; } else { _subtitleText = l10n_util::GetNSString( IDS_IOS_SETTINGS_PASSWORDS_IN_OTHER_APPS_SUBTITLE); - _bannerImage = [UIImage - imageNamed:@"legacy_settings_passwords_in_other_apps_banner"]; + _bannerName = @"legacy_settings_passwords_in_other_apps_banner"; } + self.bannerStyle = UIUserInterfaceStyleUnspecified; } return self; } @@ -400,6 +401,7 @@ _titleLabel.adjustsFontForContentSizeCategory = YES; _titleLabel.accessibilityIdentifier = kPasswordsInOtherAppsTitleAccessibilityIdentifier; + _titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader; } return _titleLabel; } @@ -725,11 +727,20 @@ if (IsCompactHeight(self)) { return nil; } + UIUserInterfaceStyle currentStyle = + UITraitCollection.currentTraitCollection.userInterfaceStyle; CGSize newSize = [self computeBannerImageSize]; - if (CGSizeEqualToSize(newSize, currentImage.size)) { + if (CGSizeEqualToSize(newSize, currentImage.size) && + self.bannerStyle == currentStyle) { return currentImage; } - return ResizeImage(self.bannerImage, newSize, ProjectionMode::kAspectFit); + self.bannerStyle = currentStyle; + return ResizeImage([self bannerImage], newSize, ProjectionMode::kAspectFit); +} + +// The banner image +- (UIImage*)bannerImage { + return [UIImage imageNamed:self.bannerName]; } // Computes banner's image size. @@ -737,7 +748,7 @@ CGFloat destinationHeight = roundf(self.view.bounds.size.height * kDefaultBannerMultiplier); CGFloat destinationWidth = - roundf(self.bannerImage.size.width / self.bannerImage.size.height * + roundf([self bannerImage].size.width / [self bannerImage].size.height * destinationHeight); CGSize newSize = CGSizeMake(destinationWidth, destinationHeight); return newSize;
diff --git a/ios/chrome/common/ui/promo_style/promo_style_view_controller.h b/ios/chrome/common/ui/promo_style/promo_style_view_controller.h index fe7ea54..b608a3e 100644 --- a/ios/chrome/common/ui/promo_style/promo_style_view_controller.h +++ b/ios/chrome/common/ui/promo_style/promo_style_view_controller.h
@@ -13,8 +13,8 @@ // Style screens. @interface PromoStyleViewController : UIViewController <UITextViewDelegate> -// The banner image. Must be set before the view is loaded. -@property(nonatomic, strong) UIImage* bannerImage; +// The name of the banner image. Must be set before the view is loaded. +@property(nonatomic, strong) NSString* bannerName; // When set to YES, the banner will be tall (35% of view height). When set to // NO, the banner will be of normal height (25% of view height). Defaults to NO.
diff --git a/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm b/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm index ca71420c..7d413445 100644 --- a/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm +++ b/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
@@ -40,6 +40,9 @@ @interface PromoStyleViewController () <UIScrollViewDelegate> +// Whether banner is light or dark mode +@property(nonatomic, assign) UIUserInterfaceStyle bannerStyle; + @property(nonatomic, strong) UIScrollView* scrollView; @property(nonatomic, strong) UIImageView* imageView; // UIView that wraps the scrollable content. @@ -89,6 +92,7 @@ UILayoutGuide* subtitleMarginLayoutGuide = [[UILayoutGuide alloc] init]; self.separator = [[UIView alloc] init]; + self.bannerStyle = UIUserInterfaceStyleUnspecified; self.separator.translatesAutoresizingMaskIntoConstraints = NO; self.separator.backgroundColor = [UIColor colorNamed:kSeparatorColor]; self.separator.hidden = YES; @@ -343,9 +347,9 @@ // Rescale image here as on iPad the view height isn't correctly set before // subviews are laid out. self.calculatingImageSize = YES; - self.imageView.image = [self scaleSourceImage:self.bannerImage - currentImage:self.imageView.image - toSize:[self computeBannerImageSize]]; + self.imageView.image = + [self scaleBannerWithCurrentImage:self.imageView.image + toSize:[self computeBannerImageSize]]; self.calculatingImageSize = NO; } @@ -406,9 +410,9 @@ - (UIImageView*)imageView { if (!_imageView) { _imageView = [[UIImageView alloc] - initWithImage:[self scaleSourceImage:self.bannerImage - currentImage:nil - toSize:[self computeBannerImageSize]]]; + initWithImage: + [self scaleBannerWithCurrentImage:nil + toSize:[self computeBannerImageSize]]]; _imageView.clipsToBounds = YES; _imageView.translatesAutoresizingMaskIntoConstraints = NO; } @@ -427,6 +431,7 @@ _titleLabel.adjustsFontForContentSizeCategory = YES; _titleLabel.accessibilityIdentifier = kPromoStyleTitleAccessibilityIdentifier; + _titleLabel.accessibilityTraits |= UIAccessibilityTraitHeader; } return _titleLabel; } @@ -587,6 +592,10 @@ #pragma mark - Private +- (UIImage*)bannerImage { + return [UIImage imageNamed:self.bannerName]; +} + // Computes banner's image size. - (CGSize)computeBannerImageSize { CGFloat bannerMultiplier = @@ -595,7 +604,7 @@ CGFloat destinationHeight = roundf(self.view.bounds.size.height * bannerMultiplier); CGFloat destinationWidth = - roundf(self.bannerImage.size.width / self.bannerImage.size.height * + roundf([self bannerImage].size.width / [self bannerImage].size.height * destinationHeight); CGSize newSize = CGSizeMake(destinationWidth, destinationHeight); return newSize; @@ -603,13 +612,17 @@ // Returns a new UIImage which is |sourceImage| resized to |newSize|. Returns // |currentImage| if it is already at the correct size. -- (UIImage*)scaleSourceImage:(UIImage*)sourceImage - currentImage:(UIImage*)currentImage - toSize:(CGSize)newSize { - if (CGSizeEqualToSize(newSize, currentImage.size)) { +- (UIImage*)scaleBannerWithCurrentImage:(UIImage*)currentImage + toSize:(CGSize)newSize { + UIUserInterfaceStyle currentStyle = + UITraitCollection.currentTraitCollection.userInterfaceStyle; + if (CGSizeEqualToSize(newSize, currentImage.size) && + self.bannerStyle == currentStyle) { return currentImage; } - return ResizeImage(sourceImage, newSize, ProjectionMode::kAspectFit); + + self.bannerStyle = currentStyle; + return ResizeImage([self bannerImage], newSize, ProjectionMode::kAspectFit); } // Determines which font text style to use depending on the device size, the
diff --git a/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm b/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm index d0c56582..088d60d 100644 --- a/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm +++ b/ios/chrome/credential_provider_extension/ui/consent_view_controller.mm
@@ -26,7 +26,7 @@ self.view.accessibilityIdentifier = kConsentViewControllerIdentifier; if (IsPasswordManagerBrandingUpdateEnable()) { - self.bannerImage = [UIImage imageNamed:@"consent_view_controller"]; + self.bannerName = @"consent_view_controller"; NSString* userEmail = [app_group::GetGroupUserDefaults() stringForKey:AppGroupUserDefaultsCredentialProviderUserEmail()]; @@ -44,7 +44,7 @@ @"The subtitle in the consent screen."); } } else { - self.bannerImage = [UIImage imageNamed:@"legacy_consent_view_controller"]; + self.bannerName = @"legacy_consent_view_controller"; self.subtitleText = NSLocalizedString(@"IDS_IOS_CREDENTIAL_PROVIDER_CONSENT_SUBTITLE", @"The subtitle in the consent screen.");
diff --git a/ios/chrome/test/providers/BUILD.gn b/ios/chrome/test/providers/BUILD.gn index 75ffbeb..7832d1a 100644 --- a/ios/chrome/test/providers/BUILD.gn +++ b/ios/chrome/test/providers/BUILD.gn
@@ -20,6 +20,7 @@ "//ios/chrome/test/providers/omaha", "//ios/chrome/test/providers/overrides", "//ios/chrome/test/providers/password_auto_fill", + "//ios/chrome/test/providers/push_notification", "//ios/chrome/test/providers/risk_data", "//ios/chrome/test/providers/signin", "//ios/chrome/test/providers/text_zoom",
diff --git a/ios/chrome/test/providers/push_notification/BUILD.gn b/ios/chrome/test/providers/push_notification/BUILD.gn new file mode 100644 index 0000000..af40bba9 --- /dev/null +++ b/ios/chrome/test/providers/push_notification/BUILD.gn
@@ -0,0 +1,9 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("push_notification") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ "test_push_notification.mm" ] + deps = [ "//ios/public/provider/chrome/browser/push_notification:push_notification_api" ] +}
diff --git a/ios/chrome/test/providers/push_notification/test_push_notification.mm b/ios/chrome/test/providers/push_notification/test_push_notification.mm new file mode 100644 index 0000000..ac80d90 --- /dev/null +++ b/ios/chrome/test/providers/push_notification/test_push_notification.mm
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/public/provider/chrome/browser/push_notification/push_notification_api.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace ios { +namespace provider { + +void InitializeConfiguration() { + // Test implementation does nothing. +} + +void RegisterDevice() { + // Test implementation does nothing. +} + +} // namespace provider +} // namespace ios
diff --git a/ios/public/provider/chrome/browser/BUILD.gn b/ios/public/provider/chrome/browser/BUILD.gn index 55cd0d13..cae26997 100644 --- a/ios/public/provider/chrome/browser/BUILD.gn +++ b/ios/public/provider/chrome/browser/BUILD.gn
@@ -35,6 +35,7 @@ "//ios/public/provider/chrome/browser/omaha:omaha_api", "//ios/public/provider/chrome/browser/overrides:overrides_api", "//ios/public/provider/chrome/browser/password_auto_fill:password_auto_fill_api", + "//ios/public/provider/chrome/browser/push_notification:push_notification_api", "//ios/public/provider/chrome/browser/risk_data:risk_data_api", "//ios/public/provider/chrome/browser/signin:signin_error_api", "//ios/public/provider/chrome/browser/signin:signin_resources_api",
diff --git a/ios/public/provider/chrome/browser/push_notification/BUILD.gn b/ios/public/provider/chrome/browser/push_notification/BUILD.gn new file mode 100644 index 0000000..91422a0c --- /dev/null +++ b/ios/public/provider/chrome/browser/push_notification/BUILD.gn
@@ -0,0 +1,8 @@ +# Copyright 2022 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("push_notification_api") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ "push_notification_api.h" ] +}
diff --git a/ios/public/provider/chrome/browser/push_notification/push_notification_api.h b/ios/public/provider/chrome/browser/push_notification/push_notification_api.h new file mode 100644 index 0000000..9cc56434 --- /dev/null +++ b/ios/public/provider/chrome/browser/push_notification/push_notification_api.h
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_PUBLIC_PROVIDER_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_API_H_ +#define IOS_PUBLIC_PROVIDER_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_API_H_ + +namespace ios { +namespace provider { + +// Initializes the device to handle push notifications +void InitializeConfiguration(); + +// Registers the device with the server to receive push notifications +void RegisterDevice(); + +} // namespace provider +} // namespace ios + +#endif // IOS_PUBLIC_PROVIDER_CHROME_BROWSER_PUSH_NOTIFICATION_PUSH_NOTIFICATION_API_H_
diff --git a/ios/showcase/first_run/sc_first_run_default_screen_view_controller.mm b/ios/showcase/first_run/sc_first_run_default_screen_view_controller.mm index 6da9afd..5a2346c 100644 --- a/ios/showcase/first_run/sc_first_run_default_screen_view_controller.mm +++ b/ios/showcase/first_run/sc_first_run_default_screen_view_controller.mm
@@ -28,7 +28,7 @@ self.primaryActionString = @"Accept and continue"; self.secondaryActionString = @"Not now"; self.tertiaryActionString = @"Customize sync"; - self.bannerImage = [UIImage imageNamed:@"Sample-banner"]; + self.bannerName = @"Sample-banner"; self.isTallBanner = NO; // Add some screen-specific content and its constraints.
diff --git a/ios/showcase/first_run/sc_first_run_hero_screen_view_controller.mm b/ios/showcase/first_run/sc_first_run_hero_screen_view_controller.mm index 2f993bd1..e245382 100644 --- a/ios/showcase/first_run/sc_first_run_hero_screen_view_controller.mm +++ b/ios/showcase/first_run/sc_first_run_hero_screen_view_controller.mm
@@ -31,7 +31,7 @@ @"and how to dynamically change the primary button label."; self.readMoreString = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SCREEN_READ_MORE); - self.bannerImage = [UIImage imageNamed:@"Sample-banner-tall"]; + self.bannerName = @"Sample-banner-tall"; self.isTallBanner = YES; self.scrollToEndMandatory = YES;
diff --git a/ios/showcase/first_run/sc_first_run_scrolling_screen_view_controller.mm b/ios/showcase/first_run/sc_first_run_scrolling_screen_view_controller.mm index bb0dbce..f25e85c 100644 --- a/ios/showcase/first_run/sc_first_run_scrolling_screen_view_controller.mm +++ b/ios/showcase/first_run/sc_first_run_scrolling_screen_view_controller.mm
@@ -42,7 +42,7 @@ self.primaryActionString = @"Continue"; self.readMoreString = l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SCREEN_READ_MORE); - self.bannerImage = [UIImage imageNamed:@"Sample-banner"]; + self.bannerName = @"Sample-banner"; self.isTallBanner = NO; self.scrollToEndMandatory = YES;
diff --git a/media/media_options.gni b/media/media_options.gni index b57e768..13c374b8 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -81,10 +81,10 @@ # Enable inclusion of the HEVC/H265 parser and also enable HEVC/H265 decoding # with hardware acceleration assist. Enabled by default for fuzzer builds, - # ChromeOS builds with protected content support, Windows and Mac. + # ChromeOS builds with protected content support and Windows. enable_hevc_parser_and_hw_decoder = proprietary_codecs && - (use_fuzzing_engine || use_chromeos_protected_media || is_win || is_mac) + (use_fuzzing_engine || use_chromeos_protected_media || is_win) } # Use another declare_args() to allow dependence on
diff --git a/net/http/http_response_headers.cc b/net/http/http_response_headers.cc index 0821f596..84cd546 100644 --- a/net/http/http_response_headers.cc +++ b/net/http/http_response_headers.cc
@@ -1401,4 +1401,4 @@ dict.Add("headers", parsed_); } -} // namespace net \ No newline at end of file +} // namespace net
diff --git a/net/proxy_resolution/proxy_config_service_linux.cc b/net/proxy_resolution/proxy_config_service_linux.cc index 16f3ca6..1a3b7d4 100644 --- a/net/proxy_resolution/proxy_config_service_linux.cc +++ b/net/proxy_resolution/proxy_config_service_linux.cc
@@ -23,6 +23,7 @@ #include "base/nix/xdg_util.h" #include "base/observer_list.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_split.h" #include "base/strings/string_tokenizer.h" #include "base/strings/string_util.h" #include "base/task/sequenced_task_runner.h" @@ -532,11 +533,11 @@ // This has to be called on the UI thread (http://crbug.com/69057). base::ThreadRestrictions::ScopedAllowIO allow_io; - // Derive the location of the kde config dir from the environment. + // Derive the location(s) of the kde config dir from the environment. std::string home; if (env_var_getter->GetVar("KDEHOME", &home) && !home.empty()) { // $KDEHOME is set. Use it unconditionally. - kde_config_dir_ = KDEHomeToConfigPath(base::FilePath(home)); + kde_config_dirs_.emplace_back(KDEHomeToConfigPath(base::FilePath(home))); } else { // $KDEHOME is unset. Try to figure out what to use. This seems to be // the common case on most distributions. @@ -547,7 +548,7 @@ base::nix::DESKTOP_ENVIRONMENT_KDE3) { // KDE3 always uses .kde for its configuration. base::FilePath kde_path = base::FilePath(home).Append(".kde"); - kde_config_dir_ = KDEHomeToConfigPath(kde_path); + kde_config_dirs_.emplace_back(KDEHomeToConfigPath(kde_path)); } else if (base::nix::GetDesktopEnvironment(env_var_getter) == base::nix::DESKTOP_ENVIRONMENT_KDE4) { // Some distributions patch KDE4 to use .kde4 instead of .kde, so that @@ -577,13 +578,27 @@ } } if (use_kde4) { - kde_config_dir_ = KDEHomeToConfigPath(kde4_path); + kde_config_dirs_.emplace_back(KDEHomeToConfigPath(kde4_path)); } else { - kde_config_dir_ = KDEHomeToConfigPath(kde3_path); + kde_config_dirs_.emplace_back(KDEHomeToConfigPath(kde3_path)); } } else { // KDE 5 migrated to ~/.config for storing kioslaverc. - kde_config_dir_ = base::FilePath(home).Append(".config"); + kde_config_dirs_.emplace_back(base::FilePath(home).Append(".config")); + + // kioslaverc also can be stored in any of XDG_CONFIG_DIRS + std::string config_dirs; + if (env_var_getter_->GetVar("XDG_CONFIG_DIRS", &config_dirs)) { + auto dirs = base::SplitString(config_dirs, ":", base::KEEP_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + for (const auto& dir : dirs) { + kde_config_dirs_.emplace_back(dir); + } + } + + // Reverses the order of paths to store them in ascending order of + // priority + std::reverse(kde_config_dirs_.begin(), kde_config_dirs_.end()); } } } @@ -652,8 +667,15 @@ // the first change, and it will never change again). So, we watch the // directory instead. We then act only on changes to the kioslaverc entry. // TODO(eroman): What if the file is deleted? (handle with IN_DELETE). - if (inotify_add_watch(inotify_fd_, kde_config_dir_.value().c_str(), - IN_MODIFY | IN_MOVED_TO) < 0) { + size_t failed_dirs = 0; + for (const auto& kde_config_dir : kde_config_dirs_) { + if (inotify_add_watch(inotify_fd_, kde_config_dir.value().c_str(), + IN_MODIFY | IN_MOVED_TO) < 0) { + ++failed_dirs; + } + } + // Fail if inotify_add_watch failed with every directory + if (failed_dirs == kde_config_dirs_.size()) { return false; } notify_delegate_ = delegate; @@ -840,81 +862,93 @@ } } - // Reads kioslaverc one line at a time and calls AddKDESetting() to add - // each relevant name-value pair to the appropriate value table. + // Reads kioslaverc from all paths one line at a time and calls + // AddKDESetting() to add each relevant name-value pair to the appropriate + // value table. Each value can be overwritten by values from configs from + // the following paths. void UpdateCachedSettings() { - base::FilePath kioslaverc = kde_config_dir_.Append("kioslaverc"); - base::ScopedFILE input(base::OpenFile(kioslaverc, "r")); - if (!input.get()) - return; - ResetCachedSettings(); - bool in_proxy_settings = false; - bool line_too_long = false; - char line[BUFFER_SIZE]; - // fgets() will return NULL on EOF or error. - while (fgets(line, sizeof(line), input.get())) { - // fgets() guarantees the line will be properly terminated. - size_t length = strlen(line); - if (!length) + bool at_least_one_kioslaverc_opened = false; + for (const auto& kde_config_dir : kde_config_dirs_) { + base::FilePath kioslaverc = kde_config_dir.Append("kioslaverc"); + base::ScopedFILE input(base::OpenFile(kioslaverc, "r")); + if (!input.get()) continue; - // This should be true even with CRLF endings. - if (line[length - 1] != '\n') { - line_too_long = true; - continue; + + // Reset cached settings once only if some config was successfully opened + if (!at_least_one_kioslaverc_opened) { + ResetCachedSettings(); } - if (line_too_long) { - // The previous line had no line ending, but this done does. This is - // the end of the line that was too long, so warn here and skip it. - LOG(WARNING) << "skipped very long line in " << kioslaverc.value(); - line_too_long = false; - continue; - } - // Remove the LF at the end, and the CR if there is one. - line[--length] = '\0'; - if (length && line[length - 1] == '\r') + at_least_one_kioslaverc_opened = true; + bool in_proxy_settings = false; + bool line_too_long = false; + char line[BUFFER_SIZE]; + // fgets() will return NULL on EOF or error. + while (fgets(line, sizeof(line), input.get())) { + // fgets() guarantees the line will be properly terminated. + size_t length = strlen(line); + if (!length) + continue; + // This should be true even with CRLF endings. + if (line[length - 1] != '\n') { + line_too_long = true; + continue; + } + if (line_too_long) { + // The previous line had no line ending, but this one does. This is + // the end of the line that was too long, so warn here and skip it. + LOG(WARNING) << "skipped very long line in " << kioslaverc.value(); + line_too_long = false; + continue; + } + // Remove the LF at the end, and the CR if there is one. line[--length] = '\0'; - // Now parse the line. - if (line[0] == '[') { - // Switching sections. All we care about is whether this is - // the (a?) proxy settings section, for both KDE3 and KDE4. - in_proxy_settings = !strncmp(line, "[Proxy Settings]", 16); - } else if (in_proxy_settings) { - // A regular line, in the (a?) proxy settings section. - char* split = strchr(line, '='); - // Skip this line if it does not contain an = sign. - if (!split) - continue; - // Split the line on the = and advance |split|. - *(split++) = 0; - std::string key = line; - std::string value = split; - base::TrimWhitespaceASCII(key, base::TRIM_ALL, &key); - base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); - // Skip this line if the key name is empty. - if (key.empty()) - continue; - // Is the value name localized? - if (key[key.length() - 1] == ']') { - // Find the matching bracket. - length = key.rfind('['); - // Skip this line if the localization indicator is malformed. - if (length == std::string::npos) + if (length && line[length - 1] == '\r') + line[--length] = '\0'; + // Now parse the line. + if (line[0] == '[') { + // Switching sections. All we care about is whether this is + // the (a?) proxy settings section, for both KDE3 and KDE4. + in_proxy_settings = !strncmp(line, "[Proxy Settings]", 16); + } else if (in_proxy_settings) { + // A regular line, in the (a?) proxy settings section. + char* split = strchr(line, '='); + // Skip this line if it does not contain an = sign. + if (!split) continue; - // Trim the localization indicator off. - key.resize(length); - // Remove any resulting trailing whitespace. - base::TrimWhitespaceASCII(key, base::TRIM_TRAILING, &key); - // Skip this line if the key name is now empty. + // Split the line on the = and advance |split|. + *(split++) = 0; + std::string key = line; + std::string value = split; + base::TrimWhitespaceASCII(key, base::TRIM_ALL, &key); + base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value); + // Skip this line if the key name is empty. if (key.empty()) continue; + // Is the value name localized? + if (key[key.length() - 1] == ']') { + // Find the matching bracket. + length = key.rfind('['); + // Skip this line if the localization indicator is malformed. + if (length == std::string::npos) + continue; + // Trim the localization indicator off. + key.resize(length); + // Remove any resulting trailing whitespace. + base::TrimWhitespaceASCII(key, base::TRIM_TRAILING, &key); + // Skip this line if the key name is now empty. + if (key.empty()) + continue; + } + // Now fill in the tables. + AddKDESetting(key, value); } - // Now fill in the tables. - AddKDESetting(key, value); } + if (ferror(input.get())) + LOG(ERROR) << "error reading " << kioslaverc.value(); } - if (ferror(input.get())) - LOG(ERROR) << "error reading " << kioslaverc.value(); - ResolveModeEffects(); + if (at_least_one_kioslaverc_opened) { + ResolveModeEffects(); + } } // This is the callback from the debounce timer. @@ -990,7 +1024,7 @@ std::unique_ptr<base::FileDescriptorWatcher::Controller> inotify_watcher_; ProxyConfigServiceLinux::Delegate* notify_delegate_; std::unique_ptr<base::OneShotTimer> debounce_timer_; - base::FilePath kde_config_dir_; + std::vector<base::FilePath> kde_config_dirs_; bool indirect_manual_; bool auto_no_pac_; bool reversed_bypass_list_;
diff --git a/net/proxy_resolution/proxy_config_service_linux_unittest.cc b/net/proxy_resolution/proxy_config_service_linux_unittest.cc index 386028ed..597a943 100644 --- a/net/proxy_resolution/proxy_config_service_linux_unittest.cc +++ b/net/proxy_resolution/proxy_config_service_linux_unittest.cc
@@ -56,6 +56,7 @@ const char* SOCKS_SERVER; const char* SOCKS_VERSION; const char* no_proxy; + const char* XDG_CONFIG_DIRS; }; // Undo macro pollution from GDK includes (from message_loop.h). @@ -123,6 +124,7 @@ ENTRY(no_proxy); ENTRY(SOCKS_SERVER); ENTRY(SOCKS_VERSION); + ENTRY(XDG_CONFIG_DIRS); #undef ENTRY Reset(); } @@ -429,6 +431,12 @@ kioslaverc4_ = kde4_config_.Append(FILE_PATH_LITERAL("kioslaverc")); // Set up paths for KDE 5 kioslaverc5_ = config_home_.Append(FILE_PATH_LITERAL("kioslaverc")); + config_xdg_home_ = user_home_.Append(FILE_PATH_LITERAL("xdg")); + config_kdedefaults_home_ = + config_home_.Append(FILE_PATH_LITERAL("kdedefaults")); + kioslaverc5_xdg_ = config_xdg_home_.Append(FILE_PATH_LITERAL("kioslaverc")); + kioslaverc5_kdedefaults_ = + config_kdedefaults_home_.Append(FILE_PATH_LITERAL("kioslaverc")); } void TearDown() override { @@ -439,6 +447,8 @@ base::FilePath user_home_; base::FilePath config_home_; + base::FilePath config_xdg_home_; + base::FilePath config_kdedefaults_home_; // KDE3 paths. base::FilePath kde_home_; base::FilePath kioslaverc_; @@ -448,6 +458,8 @@ base::FilePath kioslaverc4_; // KDE5 paths. base::FilePath kioslaverc5_; + base::FilePath kioslaverc5_xdg_; + base::FilePath kioslaverc5_kdedefaults_; }; // Builds an identifier for each test in an array. @@ -1932,6 +1944,94 @@ // doesn't trigger any notifications, but it probably should. } +TEST_F(ProxyConfigServiceLinuxTest, KDEMultipleKioslaverc) { + std::string xdg_config_dirs = config_kdedefaults_home_.value(); + xdg_config_dirs += ':'; + xdg_config_dirs += config_xdg_home_.value(); + + const struct { + // Short description to identify the test + std::string description; + + // Input. + std::string kioslaverc; + base::FilePath kioslaverc_path; + bool auto_detect; + GURL pac_url; + ProxyRulesExpectation proxy_rules; + } tests[] = { + { + TEST_DESC("Use xdg/kioslaverc"), + + // Input. + "[Proxy Settings]\nProxyType=3\n" + "Proxy Config Script=http://wpad/wpad.dat\n" + "httpsProxy=www.foo.com\n", + kioslaverc5_xdg_, // kioslaverc path + true, // auto_detect + GURL(), // pac_url + ProxyRulesExpectation::Empty(), + }, + { + TEST_DESC(".config/kdedefaults/kioslaverc overrides xdg/kioslaverc"), + + // Input. + "[Proxy Settings]\nProxyType=2\n" + "NoProxyFor=.google.com,.kde.org\n", + kioslaverc5_kdedefaults_, // kioslaverc path + false, // auto_detect + GURL("http://wpad/wpad.dat"), // pac_url + ProxyRulesExpectation::Empty(), + }, + { + TEST_DESC(".config/kioslaverc overrides others"), + + // Input. + "[Proxy Settings]\nProxyType=1\nhttpProxy=www.google.com 80\n" + "ReversedException=true\n", + kioslaverc5_, // kioslaverc path + false, // auto_detect + GURL(), // pac_url + ProxyRulesExpectation::PerSchemeWithBypassReversed( + "www.google.com:80", // http + "www.foo.com:80", // https + "", // ftp + "*.google.com,*.kde.org"), // bypass rules, + }, + }; + + // Create directories for all configs + base::CreateDirectory(config_home_); + base::CreateDirectory(config_xdg_home_); + base::CreateDirectory(config_kdedefaults_home_); + + for (size_t i = 0; i < std::size(tests); ++i) { + SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "] %s", i, + tests[i].description.c_str())); + std::unique_ptr<MockEnvironment> env(new MockEnvironment); + env->values.XDG_CURRENT_DESKTOP = "KDE"; + env->values.KDE_SESSION_VERSION = "5"; + env->values.HOME = user_home_.value().c_str(); + env->values.XDG_CONFIG_DIRS = xdg_config_dirs.c_str(); + SyncConfigGetter sync_config_getter(new ProxyConfigServiceLinux( + std::move(env), TRAFFIC_ANNOTATION_FOR_TESTS)); + ProxyConfigWithAnnotation config; + // Write the kioslaverc file to specified location. + base::WriteFile(tests[i].kioslaverc_path, tests[i].kioslaverc); + CHECK(base::PathExists(tests[i].kioslaverc_path)); + sync_config_getter.SetupAndInitialFetch(); + ProxyConfigService::ConfigAvailability availability = + sync_config_getter.SyncGetLatestProxyConfig(&config); + EXPECT_EQ(availability, ProxyConfigService::CONFIG_VALID); + + if (availability == ProxyConfigService::CONFIG_VALID) { + EXPECT_EQ(tests[i].auto_detect, config.value().auto_detect()); + EXPECT_EQ(tests[i].pac_url, config.value().pac_url()); + EXPECT_TRUE(tests[i].proxy_rules.Matches(config.value().proxy_rules())); + } + } +} + } // namespace } // namespace net
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc index fcea2dd..af554caa 100644 --- a/net/url_request/url_request.cc +++ b/net/url_request/url_request.cc
@@ -671,7 +671,6 @@ maybe_sent_cookies_.clear(); maybe_stored_cookies_.clear(); - has_partitioned_cookie_ = false; GURL referrer_url(referrer_); bool same_origin_for_metrics; @@ -875,7 +874,6 @@ maybe_sent_cookies_.clear(); maybe_stored_cookies_.clear(); - has_partitioned_cookie_ = false; status_ = ERR_IO_PENDING; job_->FollowDeferredRedirect(removed_headers, modified_headers); @@ -887,7 +885,6 @@ maybe_sent_cookies_.clear(); maybe_stored_cookies_.clear(); - has_partitioned_cookie_ = false; status_ = ERR_IO_PENDING; job_->SetAuth(credentials);
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h index 3b18dd178..0aeb701 100644 --- a/net/url_request/url_request.h +++ b/net/url_request/url_request.h
@@ -812,9 +812,6 @@ base::WeakPtr<URLRequest> GetWeakPtr(); - bool HasPartitionedCookie() { return has_partitioned_cookie_; } - void SetHasPartitionedCookie() { has_partitioned_cookie_ = true; } - protected: // Allow the URLRequestJob class to control the is_pending() flag. void set_is_pending(bool value) { is_pending_ = value; } @@ -1067,11 +1064,6 @@ bool send_client_certs_ = true; - // This boolean is set to true if the response has a Set-Cookie header with - // the Partitioned attribute. - // TODO(https://crbug.com/1296161): Delete this field. - bool has_partitioned_cookie_ = false; - // Idempotency of the request. Idempotency idempotency_ = DEFAULT_IDEMPOTENCY;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc index 619573f..e889bb0 100644 --- a/net/url_request/url_request_http_job.cc +++ b/net/url_request/url_request_http_job.cc
@@ -54,7 +54,6 @@ #include "net/cookies/cookie_store.h" #include "net/cookies/cookie_util.h" #include "net/cookies/first_party_set_metadata.h" -#include "net/cookies/parsed_cookie.h" #include "net/cookies/same_party_context.h" #include "net/filter/brotli_source_stream.h" #include "net/filter/filter_source_stream.h" @@ -930,12 +929,6 @@ num_cookie_lines_left_++; - // `cookie_partition_key_` is only non-null when partitioned cookie are - // enabled. - if (cookie_partition_key_ && ParsedCookie(cookie_string).IsPartitioned()) { - request_->SetHasPartitionedCookie(); - } - std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create( request_->url(), cookie_string, base::Time::Now(), server_time, cookie_partition_key_.value(), &returned_status);
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc index a53909f..d6e1d23 100644 --- a/net/url_request/url_request_http_job_unittest.cc +++ b/net/url_request/url_request_http_job_unittest.cc
@@ -2150,8 +2150,6 @@ ASSERT_TRUE(req->is_pending()); delegate.RunUntilComplete(); - ASSERT_TRUE(req->HasPartitionedCookie()); - { // Test request from the same top-level site. TestDelegate delegate; std::unique_ptr<URLRequest> req(context->CreateRequest(
diff --git a/services/network/public/cpp/client_hints.cc b/services/network/public/cpp/client_hints.cc index da24d493..c6ba0c5 100644 --- a/services/network/public/cpp/client_hints.cc +++ b/services/network/public/cpp/client_hints.cc
@@ -55,6 +55,8 @@ "sec-ch-ua-full-version-list"}, {network::mojom::WebClientHintsType::kFullUserAgent, "sec-ch-ua-full"}, {network::mojom::WebClientHintsType::kUAWoW64, "sec-ch-ua-wow64"}, + {network::mojom::WebClientHintsType::kPartitionedCookies, + "sec-ch-partitioned-cookies"}, {network::mojom::WebClientHintsType::kSaveData, "save-data"}, }; }
diff --git a/services/network/public/cpp/cors/cors.cc b/services/network/public/cpp/cors/cors.cc index 4a0b703..9b1aa04 100644 --- a/services/network/public/cpp/cors/cors.cc +++ b/services/network/public/cpp/cors/cors.cc
@@ -382,6 +382,12 @@ "sec-ch-ua-full", "sec-ch-ua-wow64", + + // The `Sec-CH-UA-Reduced` header field is a temporary client hint, which + // will only be sent in the presence of a valid Origin Trial token. It + // was introduced to enable safely experimenting with cookies set with the + // Partitioned attribute. + "sec-ch-partitioned-cookies", }); if (!base::Contains(safe_names, lower_name))
diff --git a/services/network/public/cpp/cors/cors_unittest.cc b/services/network/public/cpp/cors/cors_unittest.cc index 0d3a083e..aa97fb7 100644 --- a/services/network/public/cpp/cors/cors_unittest.cc +++ b/services/network/public/cpp/cors/cors_unittest.cc
@@ -292,6 +292,7 @@ EXPECT_TRUE(IsCorsSafelistedHeader("Sec-CH-UA-Model", "\"Model!\"")); EXPECT_TRUE(IsCorsSafelistedHeader("Sec-CH-UA-Reduced", "\"?1\"")); EXPECT_TRUE(IsCorsSafelistedHeader("Sec-CH-UA-Full", "\"?1\"")); + EXPECT_TRUE(IsCorsSafelistedHeader("Sec-CH-Partitioned-Cookies", "\"?1\"")); // TODO(mkwst): Validate that `Sec-CH-UA-*` is a structured header. // https://crbug.com/924969
diff --git a/services/network/public/mojom/restricted_cookie_manager.mojom b/services/network/public/mojom/restricted_cookie_manager.mojom index a9f50a4d..65dfeb8 100644 --- a/services/network/public/mojom/restricted_cookie_manager.mojom +++ b/services/network/public/mojom/restricted_cookie_manager.mojom
@@ -71,7 +71,7 @@ url.mojom.Url url, SiteForCookies site_for_cookies, url.mojom.Origin top_frame_origin, CookieManagerGetOptions options, - // TODO(https://crbug.com/1296161): Delete this arg when partitioned cookies + // TODO(crbug.com/1296161): Delete this arg when partitioned cookies // Origin Trial is over. bool partitioned_cookies_runtime_feature_enabled) => ( array<CookieWithAccessResult> cookies); @@ -104,7 +104,7 @@ SetCookieFromString(url.mojom.Url url, SiteForCookies site_for_cookies, url.mojom.Origin top_frame_origin, string cookie, - // TODO(https://crbug.com/1296161): Delete this arg when + // TODO(crbug.com/1296161): Delete this arg when // partitioned cookies Origin Trial is over. bool partitioned_cookies_runtime_feature_enabled) => (); @@ -119,7 +119,7 @@ GetCookiesString(url.mojom.Url url, SiteForCookies site_for_cookies, url.mojom.Origin top_frame_origin, - // TODO(https://crbug.com/1296161): Delete this arg when + // TODO(crbug.com/1296161): Delete this arg when // partitioned cookies Origin Trial is over. bool partitioned_cookies_runtime_feature_enabled) => ( string cookies); @@ -134,8 +134,4 @@ url.mojom.Url url, SiteForCookies site_for_cookies, url.mojom.Origin top_frame_origin) => (bool cookies_enabled); - - // TODO(https://crbug.com/1296161): Delete this method when the partitioned cookies - // Origin Trial is over. - ConvertPartitionedCookiesToUnpartitioned(url.mojom.Url url); };
diff --git a/services/network/public/mojom/url_response_head.mojom b/services/network/public/mojom/url_response_head.mojom index 5a0cc45..4c4cc16d 100644 --- a/services/network/public/mojom/url_response_head.mojom +++ b/services/network/public/mojom/url_response_head.mojom
@@ -239,8 +239,4 @@ // algorithm. // See: https://fetch.spec.whatwg.org/#concept-http-network-fetch bool request_include_credentials = true; - - // This boolean is set to true if the response has a Set-Cookie header with the Partitioned attribute. - // TODO(https://crbug.com/1296161): Delete this field. - bool has_partitioned_cookie = false; };
diff --git a/services/network/public/mojom/web_client_hints_types.mojom b/services/network/public/mojom/web_client_hints_types.mojom index 903c76d8..9f356155 100644 --- a/services/network/public/mojom/web_client_hints_types.mojom +++ b/services/network/public/mojom/web_client_hints_types.mojom
@@ -51,7 +51,9 @@ // header contains the full user agent string. kFullUserAgent = 24, kUAWoW64 = 25, - // kPartitionedCookies = 26, Removed in M103. + // A client hint which, if set, signifies to the origin that the client + // supports the Partitioned cookie attribute. + kPartitionedCookies = 26, // Indicates the client wants to minimize data transfer if set to 'on'. kSaveData = 27,
diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc index cee388b..5b0677e1 100644 --- a/services/network/restricted_cookie_manager.cc +++ b/services/network/restricted_cookie_manager.cc
@@ -905,14 +905,4 @@ return false; } -void RestrictedCookieManager::ConvertPartitionedCookiesToUnpartitioned( - const GURL& url) { - DCHECK(base::FeatureList::IsEnabled(net::features::kPartitionedCookies)); - if (base::FeatureList::IsEnabled( - net::features::kPartitionedCookiesBypassOriginTrial)) { - return; - } - cookie_store_->ConvertPartitionedCookiesToUnpartitioned(url); -} - } // namespace network
diff --git a/services/network/restricted_cookie_manager.h b/services/network/restricted_cookie_manager.h index 158a6fc..3b4d5116 100644 --- a/services/network/restricted_cookie_manager.h +++ b/services/network/restricted_cookie_manager.h
@@ -146,20 +146,6 @@ const net::IsolationInfo& isolation_info, base::OnceCallback<void(net::FirstPartySetMetadata)> callback); - // This is a temporary method for the partitioned cookies (aka CHIPS) origin - // trial. - // - // This method allows RCM to convert any sites' partitioned cookies to - // unpartitioned. It should only exist for the duration of the CHIPS OT and - // should be deleted shortly after, since it gives untrusted processes the - // ability to convert any site's partitioned cookies to unpartitioned. - // - // Since CHIPS is still an experimental API, giving RCM this privilege should - // not be a major risk. However, before CHIPS goes live this method should be - // deleted. - // TODO(https://crbug.com/1296161): Delete this function. - void ConvertPartitionedCookiesToUnpartitioned(const GURL& url) override; - private: // The state associated with a CookieChangeListener. class Listener;
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc index 7ca5b6f..aefc211 100644 --- a/services/network/restricted_cookie_manager_unittest.cc +++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -2453,91 +2453,6 @@ EXPECT_TRUE(cookies[0].IsPartitioned()); } -TEST_P(PartitionedCookiesRestrictedCookieManagerTest, - ConvertPartitionedCookiesToUnpartitioned) { - const GURL kCookieURL("https://example.com"); - const GURL kTopFrameURL("https://sub.foo.com"); - const net::SiteForCookies kSiteForCookies = - net::SiteForCookies::FromUrl(kTopFrameURL); - const url::Origin kTopFrameOrigin = url::Origin::Create(kTopFrameURL); - const net::IsolationInfo kIsolationInfo = - net::IsolationInfo::CreateForInternalRequest(kTopFrameOrigin); - - service_->OverrideIsolationInfoForTesting(kIsolationInfo); - - sync_service_->SetCookieFromString( - kCookieURL, kSiteForCookies, kTopFrameOrigin, - "__Host-foo=bar; Secure; SameSite=None; Path=/; Partitioned", - /*partitioned_cookies_runtime_feature_enabled=*/true); - - auto options = mojom::CookieManagerGetOptions::New(); - options->name = ""; - options->match_type = mojom::CookieMatchType::STARTS_WITH; - auto cookies = sync_service_->GetAllForUrl( - kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options), - /*partitioned_cookies_runtime_feature_enabled=*/true); - ASSERT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); - - service_->ConvertPartitionedCookiesToUnpartitioned(kCookieURL); - - // The partitioned cookie should now be unpartitioned. - options = mojom::CookieManagerGetOptions::New(); - options->name = ""; - options->match_type = mojom::CookieMatchType::STARTS_WITH; - cookies = sync_service_->GetAllForUrl( - kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options), - /*partitioned_cookies_runtime_feature_enabled=*/true); - ASSERT_EQ(1u, cookies.size()); - EXPECT_FALSE(cookies[0].IsPartitioned()); -} - -TEST_P(PartitionedCookiesRestrictedCookieManagerTest, - ConvertPartitionedCookiesToUnpartitioned_BypassOriginTrial) { - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {net::features::kPartitionedCookies, - net::features::kPartitionedCookiesBypassOriginTrial}, - {}); - - const GURL kCookieURL("https://example.com"); - const GURL kTopFrameURL("https://sub.foo.com"); - const net::SiteForCookies kSiteForCookies = - net::SiteForCookies::FromUrl(kTopFrameURL); - const url::Origin kTopFrameOrigin = url::Origin::Create(kTopFrameURL); - const net::IsolationInfo kIsolationInfo = - net::IsolationInfo::CreateForInternalRequest(kTopFrameOrigin); - - service_->OverrideIsolationInfoForTesting(kIsolationInfo); - - sync_service_->SetCookieFromString( - kCookieURL, kSiteForCookies, kTopFrameOrigin, - "__Host-foo=bar; Secure; SameSite=None; Path=/; Partitioned", - /*partitioned_cookies_runtime_feature_enabled=*/false); - - auto options = mojom::CookieManagerGetOptions::New(); - options->name = ""; - options->match_type = mojom::CookieMatchType::STARTS_WITH; - auto cookies = sync_service_->GetAllForUrl( - kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options), - /*partitioned_cookies_runtime_feature_enabled=*/true); - ASSERT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); - - service_->ConvertPartitionedCookiesToUnpartitioned(kCookieURL); - - // The partitioned cookie should remain partitioned if the origin trial bypass - // is enabled. - options = mojom::CookieManagerGetOptions::New(); - options->name = ""; - options->match_type = mojom::CookieMatchType::STARTS_WITH; - cookies = sync_service_->GetAllForUrl( - kCookieURL, kSiteForCookies, kTopFrameOrigin, std::move(options), - /*partitioned_cookies_runtime_feature_enabled=*/true); - ASSERT_EQ(1u, cookies.size()); - EXPECT_TRUE(cookies[0].IsPartitioned()); -} - INSTANTIATE_TEST_SUITE_P( PartitionedCookies, PartitionedCookiesRestrictedCookieManagerTest,
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 1ef7c93..4ea824c 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -494,7 +494,8 @@ const auto version_string = split[0]; int version_number = 0; if (StringToInt(version_string, &version_number)) { - // TODO(ricea): Do something useful with the version number. + base::UmaHistogramExactLinear("Network.CacheTransparency.ListVersion", + version_number, 101); } else { LOG(WARNING) << "Could not parse pervasive payload version number"; } @@ -1398,8 +1399,6 @@ response->client_address_space = private_network_access_checker_.ClientAddressSpace(); - response->has_partitioned_cookie = url_request_->HasPartitionedCookie(); - return response; }
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 9232834..8a77c0d 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -7303,14 +7303,6 @@ #endif // BUILDFLAG(IS_ANDROID) -TEST_F(URLLoaderTest, HasPartitionedCookie) { - TestURLLoaderClient loader_client; - ResourceRequest request = CreateResourceRequest( - "GET", test_server()->GetURL("/set-cookie?a=b;Partitioned;")); - EXPECT_EQ(net::OK, LoadRequest(request)); - EXPECT_TRUE(client_.response_head()->has_partitioned_cookie); -} - class URLLoaderCacheTransparencyTest : public URLLoaderTest { public: void SetUp() override {
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc index 02a11d5..6d938049 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_mac.cc
@@ -17,6 +17,7 @@ #include "base/numerics/safe_math.h" #include "base/process/process_metrics.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" namespace memory_instrumentation { @@ -205,8 +206,11 @@ char buffer[MAXPATHLEN]; int length = proc_regionfilename(pid, address, buffer, MAXPATHLEN); - if (length != 0) + if (length > 0) { region.mapped_file.assign(buffer, length); + if (!base::IsStringUTF8AllowingNoncharacters(region.mapped_file)) + region.mapped_file = "region file name is not UTF-8"; + } // There's no way to get swapped or clean bytes without doing a // very expensive syscalls that crawls every single page in the memory
diff --git a/services/tracing/public/cpp/perfetto/perfetto_config.cc b/services/tracing/public/cpp/perfetto/perfetto_config.cc index 7575306b..890ec1d 100644 --- a/services/tracing/public/cpp/perfetto/perfetto_config.cc +++ b/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -155,6 +155,13 @@ json_agent_label_filter); } + if (source_names.count(tracing::mojom::kSamplerProfilerSourceName) == 1) { + AddDataSourceConfig( + perfetto_config, tracing::mojom::kSamplerProfilerSourceName, + chrome_config_string, privacy_filtering_enabled, convert_to_legacy_json, + client_priority, json_agent_label_filter); + } + if (stripped_config.IsCategoryGroupEnabled( TRACE_DISABLED_BY_DEFAULT("cpu_profiler"))) { DCHECK_EQ(
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc index ca843b55..a846e65 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
@@ -60,6 +60,7 @@ using StreamingProfilePacketHandle = protozero::MessageHandle<perfetto::protos::pbzero::StreamingProfilePacket>; +using TracePacketHandle = perfetto::TraceWriter::TracePacketHandle; namespace tracing { @@ -96,7 +97,14 @@ } TracingSamplerProfilerDataSource() - : DataSourceBase(mojom::kSamplerProfilerSourceName) {} + : DataSourceBase(mojom::kSamplerProfilerSourceName) { + PerfettoTracedProcess::Get()->AddDataSource(this); +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + perfetto::DataSourceDescriptor dsd; + dsd.set_name(mojom::kSamplerProfilerSourceName); + DataSourceProxy::Register(dsd, this); +#endif + } ~TracingSamplerProfilerDataSource() override { NOTREACHED(); } @@ -108,10 +116,16 @@ if (is_started_) { profiler->StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) producer_->CreateTraceWriter(data_source_config_.target_buffer()), +#endif data_source_config_.chrome_config().privacy_filtering_enabled()); } else if (is_startup_tracing_) { - profiler->StartTracing(nullptr, /*should_enable_filtering=*/true); + profiler->StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + nullptr, +#endif + /*should_enable_filtering=*/true); } } @@ -142,7 +156,9 @@ for (auto* profiler : profilers_) { profiler->StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) producer->CreateTraceWriter(data_source_config.target_buffer()), +#endif should_enable_filtering); } } @@ -180,7 +196,11 @@ is_startup_tracing_ = true; for (auto* profiler : profilers_) { // Enable filtering for startup tracing always to be safe. - profiler->StartTracing(nullptr, /*should_enable_filtering=*/true); + profiler->StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + nullptr, +#endif + /*should_enable_filtering=*/true); } } @@ -191,7 +211,11 @@ } for (auto* profiler : profilers_) { // Enable filtering for startup tracing always to be safe. - profiler->StartTracing(nullptr, /*should_enable_filtering=*/true); + profiler->StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + nullptr, +#endif + /*should_enable_filtering=*/true); } is_startup_tracing_ = false; } @@ -203,6 +227,10 @@ static uint32_t GetIncrementalStateResetID() { return incremental_state_reset_id_.load(std::memory_order_relaxed); } +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + using DataSourceProxy = + PerfettoTracedProcess::DataSourceProxy<TracingSamplerProfilerDataSource>; +#endif private: // TODO(eseckler): Use GUARDED_BY annotations for all members below. @@ -216,6 +244,10 @@ static std::atomic<uint32_t> incremental_state_reset_id_; }; +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) +using DataSourceProxy = TracingSamplerProfilerDataSource::DataSourceProxy; +#endif + // static std::atomic<uint32_t> TracingSamplerProfilerDataSource::incremental_state_reset_id_{0}; @@ -340,15 +372,21 @@ TracingSamplerProfiler::TracingProfileBuilder::TracingProfileBuilder( base::PlatformThreadId sampled_thread_id, +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) std::unique_ptr<perfetto::TraceWriter> trace_writer, +#endif bool should_enable_filtering, const base::RepeatingClosure& sample_callback_for_testing) : sampled_thread_id_(sampled_thread_id), +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) trace_writer_(std::move(trace_writer)), +#endif stack_profile_writer_(should_enable_filtering), - sample_callback_for_testing_(sample_callback_for_testing) {} + sample_callback_for_testing_(sample_callback_for_testing) { +} TracingSamplerProfiler::TracingProfileBuilder::~TracingProfileBuilder() { +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) // Deleting a TraceWriter can end up triggering a Mojo call which calls // TaskRunnerHandle::Get() and isn't safe on thread shutdown, which is when // TracingProfileBuilder gets destructed, so we make sure this happens on @@ -362,6 +400,7 @@ ANNOTATE_LEAKING_OBJECT_PTR(trace_writer_.get()); trace_writer_.release(); } +#endif } base::ModuleCache* @@ -375,6 +414,7 @@ void TracingSamplerProfiler::TracingProfileBuilder::OnSampleCompleted( std::vector<base::Frame> frames, base::TimeTicks sample_timestamp) { +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) base::AutoLock l(trace_writer_lock_); if (!trace_writer_) { if (buffered_samples_.size() < kMaxBufferedSamples) { @@ -389,8 +429,8 @@ } buffered_samples_.clear(); } +#endif WriteSampleToTrace(BufferedSample(sample_timestamp, std::move(frames))); - if (sample_callback_for_testing_) { sample_callback_for_testing_.Run(); } @@ -410,47 +450,67 @@ if (reset_incremental_state_) { stack_profile_writer_.ResetEmittedState(); - auto trace_packet = trace_writer_->NewTracePacket(); - trace_packet->set_sequence_flags( - perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED); + auto update_packet = [&](TracePacketHandle trace_packet) { + trace_packet->set_sequence_flags( + perfetto::protos::pbzero::TracePacket::SEQ_INCREMENTAL_STATE_CLEARED); - // Note: Make sure ThreadDescriptors we emit here won't cause - // metadata events to be emitted from the JSON exporter which conflict - // with the metadata events emitted by the regular TrackEventDataSource. - auto* thread_descriptor = trace_packet->set_thread_descriptor(); - thread_descriptor->set_pid(base::GetCurrentProcId()); - thread_descriptor->set_tid(sampled_thread_id_); - last_timestamp_ = sample.timestamp; - thread_descriptor->set_reference_timestamp_us( - last_timestamp_.since_origin().InMicroseconds()); + // Note: Make sure ThreadDescriptors we emit here won't cause + // metadata events to be emitted from the JSON exporter which conflict + // with the metadata events emitted by the regular TrackEventDataSource. + auto* thread_descriptor = trace_packet->set_thread_descriptor(); + thread_descriptor->set_pid(base::GetCurrentProcId()); + thread_descriptor->set_tid(sampled_thread_id_); + last_timestamp_ = sample.timestamp; + thread_descriptor->set_reference_timestamp_us( + last_timestamp_.since_origin().InMicroseconds()); + }; + +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + DataSourceProxy::Trace([&](DataSourceProxy::TraceContext ctx) { + update_packet(ctx.NewTracePacket()); + }); +#else + update_packet(trace_writer_->NewTracePacket()); +#endif reset_incremental_state_ = false; } + auto update_packet = [&](TracePacketHandle trace_packet) { + // Delta encoded timestamps and interned data require incremental state. + trace_packet->set_sequence_flags( + perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE); + auto callstack_id = + stack_profile_writer_.GetCallstackIDAndMaybeEmit(frames, &trace_packet); + auto* streaming_profile_packet = + trace_packet->set_streaming_profile_packet(); + streaming_profile_packet->add_callstack_iid(callstack_id); - auto trace_packet = trace_writer_->NewTracePacket(); - // Delta encoded timestamps and interned data require incremental state. - trace_packet->set_sequence_flags( - perfetto::protos::pbzero::TracePacket::SEQ_NEEDS_INCREMENTAL_STATE); - auto callstack_id = - stack_profile_writer_.GetCallstackIDAndMaybeEmit(frames, &trace_packet); - auto* streaming_profile_packet = trace_packet->set_streaming_profile_packet(); - streaming_profile_packet->add_callstack_iid(callstack_id); + int32_t current_process_priority = base::Process::Current().GetPriority(); + if (current_process_priority != 0) { + streaming_profile_packet->set_process_priority(current_process_priority); + } - int32_t current_process_priority = base::Process::Current().GetPriority(); - if (current_process_priority != 0) { - streaming_profile_packet->set_process_priority(current_process_priority); - } + streaming_profile_packet->add_timestamp_delta_us( + (sample.timestamp - last_timestamp_).InMicroseconds()); + last_timestamp_ = sample.timestamp; + }; - streaming_profile_packet->add_timestamp_delta_us( - (sample.timestamp - last_timestamp_).InMicroseconds()); - last_timestamp_ = sample.timestamp; +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + DataSourceProxy::Trace([&](DataSourceProxy::TraceContext ctx) { + update_packet(ctx.NewTracePacket()); + }); +#else + update_packet(trace_writer_->NewTracePacket()); +#endif } +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) void TracingSamplerProfiler::TracingProfileBuilder::SetTraceWriter( std::unique_ptr<perfetto::TraceWriter> writer) { base::AutoLock l(trace_writer_lock_); trace_writer_ = std::move(writer); } +#endif TracingSamplerProfiler::StackProfileWriter::StackProfileWriter( bool enable_filtering) @@ -718,13 +778,17 @@ } void TracingSamplerProfiler::StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) std::unique_ptr<perfetto::TraceWriter> trace_writer, +#endif bool should_enable_filtering) { base::AutoLock lock(lock_); if (profiler_) { +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) if (trace_writer) { profile_builder_->SetTraceWriter(std::move(trace_writer)); } +#endif return; } @@ -748,7 +812,10 @@ params.sampling_interval = base::Milliseconds(50); auto profile_builder = std::make_unique<TracingProfileBuilder>( - sampled_thread_token_.id, std::move(trace_writer), + sampled_thread_token_.id, +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + std::move(trace_writer), +#endif should_enable_filtering, sample_callback_for_testing_); profile_builder_ = profile_builder.get(); @@ -805,3 +872,8 @@ } } // namespace tracing + +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS( + tracing::TracingSamplerProfilerDataSource::DataSourceProxy); +#endif // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h index 9cc6bf1c..6e9d52e 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
@@ -96,7 +96,9 @@ public: TracingProfileBuilder( base::PlatformThreadId sampled_thread_id, +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) std::unique_ptr<perfetto::TraceWriter> trace_writer, +#endif bool should_enable_filtering, const base::RepeatingClosure& sample_callback_for_testing = base::RepeatingClosure()); @@ -109,7 +111,9 @@ void OnProfileCompleted(base::TimeDelta profile_duration, base::TimeDelta sampling_period) override {} +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) void SetTraceWriter(std::unique_ptr<perfetto::TraceWriter> trace_writer); +#endif private: struct BufferedSample { @@ -144,8 +148,10 @@ base::ModuleCache module_cache_; const base::PlatformThreadId sampled_thread_id_; +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) base::Lock trace_writer_lock_; std::unique_ptr<perfetto::TraceWriter> trace_writer_; +#endif StackProfileWriter stack_profile_writer_; bool reset_incremental_state_ = true; uint32_t last_incremental_state_reset_id_ = 0; @@ -208,8 +214,11 @@ void SetSampleCallbackForTesting( const base::RepeatingClosure& sample_callback_for_testing); - void StartTracing(std::unique_ptr<perfetto::TraceWriter> trace_writer, - bool should_enable_filtering); + void StartTracing( +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + std::unique_ptr<perfetto::TraceWriter> trace_writer, +#endif + bool should_enable_filtering); void StopTracing(); private:
diff --git a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc index da1f535..d6054546 100644 --- a/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc +++ b/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
@@ -12,6 +12,7 @@ #include "base/profiler/module_cache.h" #include "base/profiler/stack_sampling_profiler_test_util.h" #include "base/run_loop.h" +#include "base/test/test_simple_task_runner.h" #include "base/threading/thread.h" #include "base/trace_event/trace_buffer.h" #include "base/trace_event/trace_event.h" @@ -19,6 +20,7 @@ #include "services/tracing/perfetto/test_utils.h" #include "services/tracing/public/cpp/buildflags.h" #include "services/tracing/public/cpp/perfetto/producer_test_utils.h" +#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h" @@ -39,6 +41,11 @@ using base::trace_event::TraceLog; using ::testing::Invoke; using ::testing::Return; +using PacketVector = TestProducerClient::PacketVector; + +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) +std::unique_ptr<perfetto::TracingSession> g_tracing_session; +#endif #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) @@ -70,7 +77,13 @@ #endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) -class TracingSampleProfilerTest : public TracingUnitTest { +class TracingSampleProfilerTest +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + : public testing::Test +#else + : public TracingUnitTest +#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) +{ public: TracingSampleProfilerTest() = default; @@ -81,7 +94,9 @@ ~TracingSampleProfilerTest() override = default; void SetUp() override { +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) TracingUnitTest::SetUp(); +#endif #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) // Override the default LoaderLockSampler because in production it is @@ -95,34 +110,98 @@ events_stack_received_count_ = 0u; +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + PerfettoTracedProcess::GetTaskRunner()->ResetTaskRunnerForTesting( + base::ThreadTaskRunnerHandle::Get()); + TraceEventDataSource::GetInstance()->ResetForTesting(); +#else auto perfetto_wrapper = std::make_unique<base::tracing::PerfettoTaskRunner>( base::ThreadTaskRunnerHandle::Get()); producer_ = std::make_unique<TestProducerClient>(std::move(perfetto_wrapper), /*log_only_main_thread=*/false); +#endif } void TearDown() override { +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) producer_.reset(); +#endif #if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING) LoaderLockSamplingThread::SetLoaderLockSamplerForTesting(nullptr); #endif +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) TracingUnitTest::TearDown(); +#endif } void BeginTrace() { +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + perfetto::TraceConfig trace_config; + trace_config.add_buffers()->set_size_kb(1024); + auto* ds_cfg = trace_config.add_data_sources()->mutable_config(); + ds_cfg->set_name(mojom::kSamplerProfilerSourceName); + ds_cfg = trace_config.add_data_sources()->mutable_config(); + ds_cfg->set_name("track_event"); + + g_tracing_session = perfetto::Tracing::NewTrace(); + g_tracing_session->Setup(trace_config); + g_tracing_session->StartBlocking(); + // Make sure TraceEventMetadataSource::StartTracingImpl gets run. + base::RunLoop().RunUntilIdle(); +#else TracingSamplerProfiler::StartTracingForTesting(producer_.get()); +#endif } void WaitForEvents() { base::PlatformThread::Sleep(base::Milliseconds(200)); } +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + void EnsureTraceStopped() { + if (!g_tracing_session) + return; + + perfetto::TrackEvent::Flush(); + + base::RunLoop wait_for_stop; + g_tracing_session->SetOnStopCallback( + [&wait_for_stop] { wait_for_stop.Quit(); }); + g_tracing_session->Stop(); + wait_for_stop.Run(); + + std::vector<char> serialized_data = g_tracing_session->ReadTraceBlocking(); + g_tracing_session.reset(); + + perfetto::protos::Trace trace; + EXPECT_TRUE( + trace.ParseFromArray(serialized_data.data(), serialized_data.size())); + for (const auto& packet : trace.packet()) { + auto proto = std::make_unique<perfetto::protos::TracePacket>(); + *proto = packet; + finalized_packets_.push_back(std::move(proto)); + } + } +#endif + + const PacketVector& GetFinalizedPackets() { +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + EnsureTraceStopped(); + return finalized_packets_; +#else // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + return producer_->finalized_packets(); +#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + } + void EndTracing() { +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + EnsureTraceStopped(); +#else TracingSamplerProfiler::StopTracingForTesting(); base::RunLoop().RunUntilIdle(); - - auto& packets = producer_->finalized_packets(); +#endif + auto& packets = GetFinalizedPackets(); for (auto& packet : packets) { if (packet->has_streaming_profile_packet()) { events_stack_received_count_++; @@ -140,7 +219,7 @@ uint32_t FindProfilerSequenceId() { uint32_t profile_sequence_id = std::numeric_limits<uint32_t>::max(); - auto& packets = producer_->finalized_packets(); + auto& packets = GetFinalizedPackets(); for (auto& packet : packets) { if (packet->has_streaming_profile_packet()) { profile_sequence_id = packet->trusted_packet_sequence_id(); @@ -151,14 +230,23 @@ return profile_sequence_id; } +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) TestProducerClient* producer() const { return producer_.get(); } +#endif protected: // We want our singleton torn down after each test. base::ShadowingAtExitManager at_exit_manager_; base::trace_event::TraceResultBuffer trace_buffer_; - std::unique_ptr<TestProducerClient> producer_; +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + base::test::TaskEnvironment task_environment_; + base::test::TracingEnvironment tracing_environment_; + std::vector<std::unique_ptr<perfetto::protos::TracePacket>> + finalized_packets_; +#else // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + std::unique_ptr<tracing::TestProducerClient> producer_; +#endif // !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) // Number of stack sampling events received. size_t events_stack_received_count_ = 0; @@ -190,7 +278,11 @@ ValidateReceivedEvents(); } +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) +TEST_F(TracingSampleProfilerTest, DISABLED_TestStartupTracing) { +#else TEST_F(TracingSampleProfilerTest, TestStartupTracing) { +#endif auto profiler = TracingSamplerProfiler::CreateOnMainThread(); TracingSamplerProfiler::SetupStartupTracingForTesting(); base::RunLoop().RunUntilIdle(); @@ -203,7 +295,7 @@ base::RunLoop().RunUntilIdle(); if (TracingSamplerProfiler::IsStackUnwindingSupported()) { uint32_t seq_id = FindProfilerSequenceId(); - auto& packets = producer()->finalized_packets(); + auto& packets = GetFinalizedPackets(); int64_t reference_ts = 0; int64_t first_profile_ts = 0; for (auto& packet : packets) { @@ -224,7 +316,11 @@ } } +#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) +TEST_F(TracingSampleProfilerTest, DISABLED_JoinStartupTracing) { +#else TEST_F(TracingSampleProfilerTest, JoinStartupTracing) { +#endif TracingSamplerProfiler::SetupStartupTracingForTesting(); base::RunLoop().RunUntilIdle(); auto profiler = TracingSamplerProfiler::CreateOnMainThread(); @@ -237,7 +333,7 @@ base::RunLoop().RunUntilIdle(); if (TracingSamplerProfiler::IsStackUnwindingSupported()) { uint32_t seq_id = FindProfilerSequenceId(); - auto& packets = producer()->finalized_packets(); + auto& packets = GetFinalizedPackets(); int64_t reference_ts = 0; int64_t first_profile_ts = 0; for (auto& packet : packets) { @@ -403,7 +499,10 @@ TEST_F(TracingProfileBuilderTest, ValidModule) { base::TestModule module; TracingSamplerProfiler::TracingProfileBuilder profile_builder( - base::PlatformThreadId(), std::make_unique<TestTraceWriter>(producer()), + base::PlatformThreadId(), +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + std::make_unique<TestTraceWriter>(producer()), +#endif false); profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)}, base::TimeTicks()); @@ -411,12 +510,16 @@ TEST_F(TracingProfileBuilderTest, InvalidModule) { TracingSamplerProfiler::TracingProfileBuilder profile_builder( - base::PlatformThreadId(), std::make_unique<TestTraceWriter>(producer()), + base::PlatformThreadId(), +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) + std::make_unique<TestTraceWriter>(producer()), +#endif false); profile_builder.OnSampleCompleted({base::Frame(0x1010, nullptr)}, base::TimeTicks()); } +#if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY) #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) TEST_F(TracingProfileBuilderTest, MangleELFModuleID) { base::TestModule module; @@ -432,6 +535,7 @@ producer()->FlushPacketIfPossible(); bool found_build_id = false; + EXPECT_GT(producer()->GetFinalizedPacketCount(), 0u); for (unsigned i = 0; i < producer()->GetFinalizedPacketCount(); ++i) { const perfetto::protos::TracePacket* packet = producer()->GetFinalizedPacket(i); @@ -447,5 +551,6 @@ EXPECT_TRUE(found_build_id); } #endif +#endif } // namespace tracing
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index c2bd3cf..befddf8c 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -7036,7 +7036,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -8240,15 +8240,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8325,15 +8325,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8750,15 +8750,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -8835,15 +8835,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -9371,7 +9371,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -9445,7 +9445,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index cddef88f..bb6ae54 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -83,7 +83,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -142,7 +142,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -411,7 +411,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -471,7 +471,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -851,7 +851,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -911,7 +911,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1289,7 +1289,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -1348,7 +1348,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -14755,7 +14755,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -19565,7 +19565,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -40947,7 +40947,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -45642,7 +45642,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -46214,15 +46214,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46299,15 +46299,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46724,15 +46724,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -46809,15 +46809,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47238,15 +47238,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47323,15 +47323,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47748,15 +47748,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -47833,15 +47833,15 @@ { "args": [ "--additional-apk=apks/ChromePublic.apk", - "--webview-apk-path=apks/AOSP_SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/AOSP_SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48330,15 +48330,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48415,15 +48415,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48840,15 +48840,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -48925,15 +48925,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49422,15 +49422,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--client-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49507,15 +49507,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", - "--client-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--implementation-outdir", ".", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--client-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--client-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -49932,15 +49932,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M102/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M102/out/Release", "--impl-version=102", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -50017,15 +50017,15 @@ { "args": [ "--additional-apk=apks/WebLayerShellSystemWebView.apk", - "--webview-apk-path=apks/SystemWebView.apk", "--test-runner-outdir", ".", "--client-outdir", ".", - "--implementation-outdir", - "../../weblayer_instrumentation_test_M103/out/Release", "--test-expectations", "../../weblayer/browser/android/javatests/skew/expectations.txt", + "--webview-apk-path=apks/SystemWebView.apk", + "--implementation-outdir", + "../../weblayer_instrumentation_test_M103/out/Release", "--impl-version=103", "--gs-results-bucket=chromium-result-details", "--recover-devices", @@ -50298,7 +50298,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index bf8ec99..8a8a719 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5865,21 +5865,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5082.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -5892,7 +5892,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "isolate_profile_data": true, @@ -6030,21 +6030,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -6056,7 +6056,7 @@ }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "args": [ @@ -6176,21 +6176,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -6202,7 +6202,7 @@ }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "isolate_profile_data": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 7790f1f..a957f96 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -16066,7 +16066,7 @@ { "cipd_package": "chromium/android_webview/tools/cts_archive", "location": "android_webview/tools/cts_archive", - "revision": "T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC" + "revision": "qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -19688,6 +19688,75 @@ } ] }, + "android-fieldtrial-rel": { + "gtest_tests": [ + { + "args": [ + "--disable-field-trial-config", + "--gs-results-bucket=chromium-result-details", + "--recover-devices", + "--avd-config=../../tools/android/avd/proto/generic_android28.textpb" + ], + "merge": { + "args": [ + "--bucket", + "chromium-result-details", + "--test-name", + "android_browsertests_no_fieldtrial" + ], + "script": "//build/android/pylib/results/presentation/test_results_presentation.py" + }, + "name": "android_browsertests_no_fieldtrial", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/luci/logdog/butler/${platform}", + "location": "bin", + "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.finch" + } + ], + "named_caches": [ + { + "name": "generic_android28", + "path": ".android_emulator/generic_android28" + } + ], + "optional_dimensions": { + "60": [ + { + "caches": "generic_android28" + } + ] + }, + "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_browsertests", + "test_id_prefix": "ninja://chrome/test:android_browsertests/" + } + ] + }, "chromeos-amd64-generic-rel (goma cache silo)": { "additional_compile_targets": [ "chromiumos_preflight" @@ -87946,21 +88015,21 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5082.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -87968,7 +88037,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "isolate_profile_data": true, @@ -88081,28 +88150,28 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "args": [ @@ -88202,28 +88271,28 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "isolate_profile_data": true, "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "isolate_profile_data": true, @@ -89561,20 +89630,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5082.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -89588,7 +89657,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "merge": { @@ -89726,20 +89795,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -89752,7 +89821,7 @@ }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "args": [ @@ -89872,20 +89941,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -89898,7 +89967,7 @@ }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "merge": { @@ -91394,20 +91463,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5082.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -91421,7 +91490,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "merge": { @@ -91559,20 +91628,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -91585,7 +91654,7 @@ }, "test": "lacros_chrome_browsertests", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "args": [ @@ -91705,20 +91774,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5082.0", + "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -91731,7 +91800,7 @@ }, "test": "lacros_chrome_browsertests_run_in_series", "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" }, { "merge": { @@ -92466,20 +92535,20 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome" ], "merge": { "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, - "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5082.0", + "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5083.0", "swarming": { "can_use_on_swarming_builders": true, "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v104.0.5082.0", - "revision": "version:104.0.5082.0" + "location": "lacros_version_skew_tests_v104.0.5083.0", + "revision": "version:104.0.5083.0" } ], "dimension_sets": [ @@ -92492,7 +92561,7 @@ }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/", - "variant_id": "Lacros version skew testing ash 104.0.5082.0" + "variant_id": "Lacros version skew testing ash 104.0.5083.0" } ] },
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 27b181e6..280fe840 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -16811,7 +16811,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -16842,7 +16842,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -16871,7 +16871,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -16884,34 +16884,6 @@ }, { "args": [ - "--use-cmd-decoder=validating", - "--use-gpu-in-tests" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "name": "gl_tests_validating", - "swarming": { - "can_use_on_swarming_builders": true, - "containment_type": "AUTO", - "dimension_sets": [ - { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:679e", - "os": "Mac-10.12.6", - "pool": "chromium.tests.gpu" - } - ], - "expiration": 21600, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test": "gl_tests", - "test_id_prefix": "ninja://gpu:gl_tests/" - }, - { - "args": [ "--use-gpu-in-tests" ], "merge": { @@ -16926,7 +16898,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -16952,7 +16924,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -16975,7 +16947,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17015,45 +16987,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", - "pool": "chromium.tests.gpu" - } - ], - "expiration": 21600, - "idempotent": false, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" - }, - { - "args": [ - "context_lost", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating" - ], - "isolate_name": "telemetry_gpu_integration_test", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "context_lost_validating_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "containment_type": "AUTO", - "dimension_sets": [ - { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17091,7 +17025,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17129,7 +17063,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17171,7 +17105,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17218,54 +17152,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", - "pool": "chromium.tests.gpu" - } - ], - "expiration": 21600, - "idempotent": false, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" - }, - { - "args": [ - "maps", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", - "--dont-restore-color-profile-after-test", - "--test-machine-name", - "${buildername}", - "--git-revision=${got_revision}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "maps_pixel_validating_test", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}" - ], - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "containment_type": "AUTO", - "dimension_sets": [ - { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17312,54 +17199,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", - "pool": "chromium.tests.gpu" - } - ], - "expiration": 21600, - "idempotent": false, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" - }, - { - "args": [ - "pixel", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", - "--dont-restore-color-profile-after-test", - "--test-machine-name", - "${buildername}", - "--git-revision=${got_revision}" - ], - "isolate_name": "telemetry_gpu_integration_test", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "pixel_skia_gold_validating_test", - "precommit_args": [ - "--gerrit-issue=${patch_issue}", - "--gerrit-patchset=${patch_set}", - "--buildbucket-id=${buildbucket_build_id}" - ], - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "containment_type": "AUTO", - "dimension_sets": [ - { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17398,46 +17238,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", - "pool": "chromium.tests.gpu" - } - ], - "expiration": 21600, - "idempotent": false, - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, - "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/" - }, - { - "args": [ - "screenshot_sync", - "--show-stdout", - "--browser=release", - "--passthrough", - "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating", - "--dont-restore-color-profile-after-test" - ], - "isolate_name": "telemetry_gpu_integration_test", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "screenshot_sync_validating_tests", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "should_retry_with_patch": false, - "swarming": { - "can_use_on_swarming_builders": true, - "containment_type": "AUTO", - "dimension_sets": [ - { - "cpu": "x86-64", - "display_attached": "1", - "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17475,7 +17276,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17492,7 +17293,7 @@ "--browser=release", "--passthrough", "-v", - "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" ], @@ -17501,7 +17302,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "webgl2_conformance_validating_tests", + "name": "webgl2_conformance_gl_passthrough_tests", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17515,7 +17316,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ], @@ -17555,7 +17356,7 @@ "cpu": "x86-64", "display_attached": "1", "gpu": "1002:679e", - "os": "Mac-10.12.6", + "os": "Mac-12.4", "pool": "chromium.tests.gpu" } ],
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 399bf5f..680e908 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -840,7 +840,7 @@ 'dimensions': { 'cpu': 'x86-64', 'gpu': '1002:679e', - 'os': 'Mac-10.12.6', + 'os': 'Mac-12.4', 'pool': 'chromium.tests.gpu', 'display_attached': '1', },
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 0a964dd..da3bee8 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3284,7 +3284,6 @@ 'webgl2_conformance_gl_passthrough_tests': { 'remove_from': [ # Not enough capacity. https://crbug.com/982294 - 'Mac Pro FYI Release (AMD)', 'Mac FYI Retina Release (NVIDIA)', ], },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index b3defca..0809f259 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1687,6 +1687,14 @@ }, }, + 'fieldtrial_android_tests': { + 'android_browsertests_no_fieldtrial': { + 'args': [ + '--disable-field-trial-config', + ], + 'test': 'android_browsertests', + } + }, 'fieldtrial_browser_tests': { 'browser_tests_no_field_trial': { 'args': [ @@ -5398,7 +5406,7 @@ { "cipd_package": 'chromium/android_webview/tools/cts_archive', 'location': 'android_webview/tools/cts_archive', - 'revision': 'T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC', + 'revision': 'qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C', } ] }, @@ -5435,7 +5443,7 @@ { "cipd_package": 'chromium/android_webview/tools/cts_archive', 'location': 'android_webview/tools/cts_archive', - 'revision': 'T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC', + 'revision': 'qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C', } ] }, @@ -5453,7 +5461,7 @@ { "cipd_package": 'chromium/android_webview/tools/cts_archive', 'location': 'android_webview/tools/cts_archive', - 'revision': 'T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC', + 'revision': 'qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C', } ] }, @@ -5469,7 +5477,7 @@ { "cipd_package": 'chromium/android_webview/tools/cts_archive', 'location': 'android_webview/tools/cts_archive', - 'revision': 'T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC', + 'revision': 'qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C', } ] }, @@ -5484,7 +5492,7 @@ { "cipd_package": 'chromium/android_webview/tools/cts_archive', 'location': 'android_webview/tools/cts_archive', - 'revision': 'T4HLqIHU4KwoyPjGSDGrJe-FlDBIEGRLG0Uh-CghvpwC', + 'revision': 'qF6dhyFMW7qFOzHo_Lu-bWxpbe-zRfL1KvHPQtQA3d0C', } ] }, @@ -6524,8 +6532,7 @@ 'gpu_fyi_mac_pro_release_telemetry_tests': [ 'gpu_common_and_optional_telemetry_tests', 'gpu_passthrough_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webgl2_conformance_validating_telemetry_tests', + 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests', 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', ],
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 8a0228c..186ca758 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,15 +22,15 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5082.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5083.0/test_ash_chrome', ], - 'identifier': 'Lacros version skew testing ash 104.0.5082.0', + 'identifier': 'Lacros version skew testing ash 104.0.5083.0', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v104.0.5082.0', - 'revision': 'version:104.0.5082.0', + 'location': 'lacros_version_skew_tests_v104.0.5083.0', + 'revision': 'version:104.0.5083.0', }, ], }, @@ -462,16 +462,16 @@ }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': { 'args': [ - '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=103', + '--webview-apk-path=apks/AOSP_SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', + '--impl-version=103' ], 'identifier': 'with_impl_from_103', 'swarming': { @@ -479,23 +479,23 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.24', + 'revision': 'version:103.0.5060.24' } - ], - }, + ] + } }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ - '--webview-apk-path=apks/AOSP_SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=102', + '--webview-apk-path=apks/AOSP_SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', + '--impl-version=102' ], 'identifier': 'with_impl_from_102', 'swarming': { @@ -503,10 +503,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.74', + 'revision': 'version:102.0.5005.74' } - ], - }, + ] + } }, 'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -606,16 +606,16 @@ }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=103', + '--webview-apk-path=apks/SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', + '--impl-version=103' ], 'identifier': 'with_impl_from_103', 'swarming': { @@ -623,23 +623,23 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.24', + 'revision': 'version:103.0.5060.24' } - ], - }, + ] + } }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', '--client-outdir', '.', - '--implementation-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--impl-version=102', + '--webview-apk-path=apks/SystemWebView.apk', + '--implementation-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', + '--impl-version=102' ], 'identifier': 'with_impl_from_102', 'swarming': { @@ -647,10 +647,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.74', + 'revision': 'version:102.0.5005.74' } - ], - }, + ] + } }, 'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [ @@ -750,16 +750,16 @@ }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', - '--client-outdir', - '../../weblayer_instrumentation_test_M103/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--client-version=103', + '--webview-apk-path=apks/SystemWebView.apk', + '--client-outdir', + '../../weblayer_instrumentation_test_M103/out/Release', + '--client-version=103' ], 'identifier': 'with_client_from_103', 'swarming': { @@ -767,23 +767,23 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M103', - 'revision': 'version:103.0.5060.24', + 'revision': 'version:103.0.5060.24' } - ], - }, + ] + } }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': { 'args': [ - '--webview-apk-path=apks/SystemWebView.apk', '--test-runner-outdir', '.', - '--client-outdir', - '../../weblayer_instrumentation_test_M102/out/Release', '--implementation-outdir', '.', '--test-expectations', '../../weblayer/browser/android/javatests/skew/expectations.txt', - '--client-version=102', + '--webview-apk-path=apks/SystemWebView.apk', + '--client-outdir', + '../../weblayer_instrumentation_test_M102/out/Release', + '--client-version=102' ], 'identifier': 'with_client_from_102', 'swarming': { @@ -791,10 +791,10 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M102', - 'revision': 'version:102.0.5005.74', + 'revision': 'version:102.0.5005.74' } - ], - }, + ] + } }, 'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': { 'args': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index a776680..42d5b59 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3017,6 +3017,25 @@ 'use_swarming': True, 'os_type': 'android', }, + 'android-fieldtrial-rel': { + 'mixins': [ + 'has_native_resultdb_integration', + 'pie-x86-emulator', + 'linux-bionic', + 'x86-64', + ], + 'os_type': 'android', + 'swarming': { + 'dimension_sets': [ + { + 'pool': 'chromium.tests.finch', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'fieldtrial_android_tests', + }, + }, 'chromeos-amd64-generic-rel (goma cache silo)': { 'additional_compile_targets': [ 'chromiumos_preflight', @@ -4675,7 +4694,7 @@ 'mac_pro_amd_gpu', ], 'test_suites': { - 'gtest_tests': 'gpu_fyi_mac_release_gtests', + 'gtest_tests': 'gpu_fyi_mac_amd_release_gtests', 'gpu_telemetry_tests': 'gpu_fyi_mac_pro_release_telemetry_tests', }, },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 68699bd..9c1b636c 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -6990,24 +6990,6 @@ ] } ], - "SRTPromptFieldTrial": [ - { - "platforms": [ - "windows" - ], - "experiments": [ - { - "name": "NewCleanerUIExperiment", - "params": { - "Seed": "20171002" - }, - "enable_features": [ - "InBrowserCleanerUI" - ] - } - ] - } - ], "SafeBrowsingCSDAndroid": [ { "platforms": [
diff --git a/third_party/abseil-cpp/CMake/AbseilHelpers.cmake b/third_party/abseil-cpp/CMake/AbseilHelpers.cmake index ed87dde..6d03381b 100644 --- a/third_party/abseil-cpp/CMake/AbseilHelpers.cmake +++ b/third_party/abseil-cpp/CMake/AbseilHelpers.cmake
@@ -170,6 +170,7 @@ set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") endif() endforeach() + string(REPLACE ";" " " PC_LINKOPTS "${ABSL_CC_LIB_LINKOPTS}") FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\ prefix=${CMAKE_INSTALL_PREFIX}\n\ exec_prefix=\${prefix}\n\ @@ -181,7 +182,7 @@ URL: https://abseil.io/\n\ Version: ${PC_VERSION}\n\ Requires:${PC_DEPS}\n\ -Libs: -L\${libdir} $<JOIN:${ABSL_CC_LIB_LINKOPTS}, > $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-labsl_${_NAME}>\n\ +Libs: -L\${libdir} ${PC_LINKOPTS} $<$<NOT:$<BOOL:${ABSL_CC_LIB_IS_INTERFACE}>>:-labsl_${_NAME}>\n\ Cflags: -I\${includedir}${PC_CFLAGS}\n") INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
diff --git a/third_party/abseil-cpp/README.chromium b/third_party/abseil-cpp/README.chromium index 37d9a18..97472dc5 100644 --- a/third_party/abseil-cpp/README.chromium +++ b/third_party/abseil-cpp/README.chromium
@@ -4,7 +4,7 @@ License: Apache 2.0 License File: LICENSE Version: 0 -Revision: 9df63a8beaae53802109346f0a20328140a7cb8e +Revision: 1963f10ae5cb32a7ea6d96b928f69d3c7fba0139 Security Critical: yes Description:
diff --git a/third_party/abseil-cpp/absl/base/config.h b/third_party/abseil-cpp/absl/base/config.h index 3f5ace3..a0d599f 100644 --- a/third_party/abseil-cpp/absl/base/config.h +++ b/third_party/abseil-cpp/absl/base/config.h
@@ -837,6 +837,21 @@ #define ABSL_INTERNAL_HAS_RTTI 1 #endif // !defined(__GNUC__) || defined(__GXX_RTTI) +// ABSL_INTERNAL_HAVE_SSE is used for compile-time detection of SSE support. +// See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of +// which architectures support the various x86 instruction sets. +#ifdef ABSL_INTERNAL_HAVE_SSE +#error ABSL_INTERNAL_HAVE_SSE cannot be directly set +#elif defined(__SSE__) +#define ABSL_INTERNAL_HAVE_SSE 1 +#elif defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1) +// MSVC only defines _M_IX86_FP for x86 32-bit code, and _M_IX86_FP >= 1 +// indicates that at least SSE was targeted with the /arch:SSE option. +// All x86-64 processors support SSE, so support can be assumed. +// https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros +#define ABSL_INTERNAL_HAVE_SSE 1 +#endif + // ABSL_INTERNAL_HAVE_SSE2 is used for compile-time detection of SSE2 support. // See https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html for an overview of // which architectures support the various x86 instruction sets.
diff --git a/third_party/abseil-cpp/absl/base/internal/prefetch.h b/third_party/abseil-cpp/absl/base/internal/prefetch.h index a71b389..0641928 100644 --- a/third_party/abseil-cpp/absl/base/internal/prefetch.h +++ b/third_party/abseil-cpp/absl/base/internal/prefetch.h
@@ -17,6 +17,15 @@ #include "absl/base/config.h" +#ifdef __SSE__ +#include <xmmintrin.h> +#endif + +#if defined(_MSC_VER) && defined(ABSL_INTERNAL_HAVE_SSE) +#include <intrin.h> +#pragma intrinsic(_mm_prefetch) +#endif + // Compatibility wrappers around __builtin_prefetch, to prefetch data // for read if supported by the toolchain. @@ -72,6 +81,8 @@ #if ABSL_HAVE_BUILTIN(__builtin_prefetch) || defined(__GNUC__) +#define ABSL_INTERNAL_HAVE_PREFETCH 1 + // See __builtin_prefetch: // https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html. // @@ -95,6 +106,24 @@ // Note: this uses prefetchtnta on Intel. __builtin_prefetch(addr, 0, 0); } + +#elif defined(ABSL_INTERNAL_HAVE_SSE) + +#define ABSL_INTERNAL_HAVE_PREFETCH 1 + +inline void PrefetchT0(const void* addr) { + _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T0); +} +inline void PrefetchT1(const void* addr) { + _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T1); +} +inline void PrefetchT2(const void* addr) { + _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_T2); +} +inline void PrefetchNta(const void* addr) { + _mm_prefetch(reinterpret_cast<const char*>(addr), _MM_HINT_NTA); +} + #else inline void PrefetchT0(const void*) {} inline void PrefetchT1(const void*) {}
diff --git a/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h b/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h index a435140..2cbeae3 100644 --- a/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h +++ b/third_party/abseil-cpp/absl/base/internal/unscaledcycleclock.h
@@ -59,8 +59,7 @@ // CycleClock that runs at atleast 1 MHz. We've found some Android // ARM64 devices where this is not the case, so we disable it by // default on Android ARM64. -#if defined(__native_client__) || \ - (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || \ +#if defined(__native_client__) || (defined(__APPLE__)) || \ (defined(__ANDROID__) && defined(__aarch64__)) #define ABSL_USE_UNSCALED_CYCLECLOCK_DEFAULT 0 #else
diff --git a/third_party/abseil-cpp/absl/container/BUILD.bazel b/third_party/abseil-cpp/absl/container/BUILD.bazel index d733cb2..9ef7066 100644 --- a/third_party/abseil-cpp/absl/container/BUILD.bazel +++ b/third_party/abseil-cpp/absl/container/BUILD.bazel
@@ -589,6 +589,7 @@ "//absl/base:config", "//absl/base:core_headers", "//absl/base:endian", + "//absl/base:prefetch", "//absl/memory", "//absl/meta:type_traits", "//absl/numeric:bits", @@ -611,6 +612,7 @@ "//absl/base", "//absl/base:config", "//absl/base:core_headers", + "//absl/base:prefetch", "//absl/base:raw_logging_internal", "//absl/strings", "@com_google_googletest//:gtest_main",
diff --git a/third_party/abseil-cpp/absl/container/BUILD.gn b/third_party/abseil-cpp/absl/container/BUILD.gn index b4167aa..6afb390 100644 --- a/third_party/abseil-cpp/absl/container/BUILD.gn +++ b/third_party/abseil-cpp/absl/container/BUILD.gn
@@ -230,6 +230,7 @@ "//third_party/abseil-cpp/absl/base:config", "//third_party/abseil-cpp/absl/base:core_headers", "//third_party/abseil-cpp/absl/base:endian", + "//third_party/abseil-cpp/absl/base:prefetch", "//third_party/abseil-cpp/absl/memory", "//third_party/abseil-cpp/absl/meta:type_traits", "//third_party/abseil-cpp/absl/numeric:bits",
diff --git a/third_party/abseil-cpp/absl/container/CMakeLists.txt b/third_party/abseil-cpp/absl/container/CMakeLists.txt index aad69fa..9b5c59a 100644 --- a/third_party/abseil-cpp/absl/container/CMakeLists.txt +++ b/third_party/abseil-cpp/absl/container/CMakeLists.txt
@@ -681,6 +681,7 @@ absl::memory absl::meta absl::optional + absl::prefetch absl::utility absl::hashtablez_sampler PUBLIC @@ -702,6 +703,7 @@ absl::base absl::config absl::core_headers + absl::prefetch absl::raw_logging_internal absl::strings GTest::gmock_main
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h index 56251b2..769af50 100644 --- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h +++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set.h
@@ -197,6 +197,7 @@ #include "absl/base/config.h" #include "absl/base/internal/endian.h" +#include "absl/base/internal/prefetch.h" #include "absl/base/optimization.h" #include "absl/base/port.h" #include "absl/container/internal/common.h" @@ -1636,12 +1637,13 @@ template <class K = key_type> void prefetch(const key_arg<K>& key) const { (void)key; -#if defined(__GNUC__) + // Avoid probing if we won't be able to prefetch the addresses received. +#ifdef ABSL_INTERNAL_HAVE_PREFETCH prefetch_heap_block(); auto seq = probe(ctrl_, hash_ref()(key), capacity_); - __builtin_prefetch(static_cast<const void*>(ctrl_ + seq.offset())); - __builtin_prefetch(static_cast<const void*>(slots_ + seq.offset())); -#endif // __GNUC__ + base_internal::PrefetchT0(ctrl_ + seq.offset()); + base_internal::PrefetchT0(slots_ + seq.offset()); +#endif // ABSL_INTERNAL_HAVE_PREFETCH } // The API of find() has two extensions. @@ -2159,9 +2161,7 @@ // This is intended to overlap with execution of calculating the hash for a // key. void prefetch_heap_block() const { -#if defined(__GNUC__) - __builtin_prefetch(static_cast<const void*>(ctrl_), 0, 1); -#endif // __GNUC__ + base_internal::PrefetchT2(ctrl_); } HashtablezInfoHandle& infoz() { return settings_.template get<1>(); }
diff --git a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc index 9cd88a2..914ec0c 100644 --- a/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc +++ b/third_party/abseil-cpp/absl/container/internal/raw_hash_set_test.cc
@@ -31,6 +31,7 @@ #include "absl/base/attributes.h" #include "absl/base/config.h" #include "absl/base/internal/cycleclock.h" +#include "absl/base/internal/prefetch.h" #include "absl/base/internal/raw_logging.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/hash_function_defaults.h"
diff --git a/third_party/abseil-cpp/absl/strings/internal/cord_internal.h b/third_party/abseil-cpp/absl/strings/internal/cord_internal.h index 6ae418e7..b50fb79 100644 --- a/third_party/abseil-cpp/absl/strings/internal/cord_internal.h +++ b/third_party/abseil-cpp/absl/strings/internal/cord_internal.h
@@ -632,7 +632,9 @@ } inline CordRep* CordRep::Ref(CordRep* rep) { - assert(rep != nullptr); + // ABSL_ASSUME is a workaround for + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105585 + ABSL_ASSUME(rep != nullptr); rep->refcount.Increment(); return rep; }
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc index 6487fa9..f1f79a2 100644 --- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc +++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_format_test.cc
@@ -18,11 +18,15 @@ #include <sstream> #include <string> +#include "absl/base/config.h" +#include "absl/time/internal/cctz/include/cctz/time_zone.h" +#if defined(__linux__) +#include <features.h> +#endif + #include "gmock/gmock.h" #include "gtest/gtest.h" -#include "absl/base/config.h" #include "absl/time/internal/cctz/include/cctz/civil_time.h" -#include "absl/time/internal/cctz/include/cctz/time_zone.h" namespace chrono = std::chrono; @@ -183,8 +187,10 @@ TestFormatSpecifier(tp, tz, "%F", "1970-01-01"); TestFormatSpecifier(tp, tz, "%g", "70"); TestFormatSpecifier(tp, tz, "%G", "1970"); +#if defined(__GLIBC__) TestFormatSpecifier(tp, tz, "%k", " 0"); TestFormatSpecifier(tp, tz, "%l", "12"); +#endif TestFormatSpecifier(tp, tz, "%n", "\n"); TestFormatSpecifier(tp, tz, "%R", "00:00"); TestFormatSpecifier(tp, tz, "%t", "\t"); @@ -216,7 +222,9 @@ #if defined(__linux__) // SU/C99/TZ extensions TestFormatSpecifier(tp, tz, "%h", "Jan"); // Same as %b +#if defined(__GLIBC__) TestFormatSpecifier(tp, tz, "%P", "am"); +#endif TestFormatSpecifier(tp, tz, "%r", "12:00:00 AM"); // Modified conversion specifiers %E_ @@ -1045,9 +1053,11 @@ EXPECT_TRUE(parse("%h", "Feb", tz, &tp)); EXPECT_EQ(2, convert(tp, tz).month()); // Equivalent to %b +#if defined(__GLIBC__) tp = reset; EXPECT_TRUE(parse("%l %p", "5 PM", tz, &tp)); EXPECT_EQ(17, convert(tp, tz).hour()); +#endif tp = reset; EXPECT_TRUE(parse("%r", "03:44:55 PM", tz, &tp)); @@ -1055,6 +1065,7 @@ EXPECT_EQ(44, convert(tp, tz).minute()); EXPECT_EQ(55, convert(tp, tz).second()); +#if defined(__GLIBC__) tp = reset; EXPECT_TRUE(parse("%Ec", "Tue Nov 19 05:06:07 2013", tz, &tp)); EXPECT_EQ(convert(civil_second(2013, 11, 19, 5, 6, 7), tz), tp); @@ -1126,6 +1137,7 @@ EXPECT_TRUE(parse("%Oy", "04", tz, &tp)); EXPECT_EQ(2004, convert(tp, tz).year()); #endif +#endif } TEST(Parse, ExtendedSeconds) {
diff --git a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc index 134d1430..27a53c5 100644 --- a/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc +++ b/third_party/abseil-cpp/absl/time/internal/cctz/src/time_zone_lookup_test.cc
@@ -21,10 +21,14 @@ #include <thread> #include <vector> -#include "gtest/gtest.h" #include "absl/base/config.h" -#include "absl/time/internal/cctz/include/cctz/civil_time.h" #include "absl/time/internal/cctz/include/cctz/time_zone.h" +#if defined(__linux__) +#include <features.h> +#endif + +#include "gtest/gtest.h" +#include "absl/time/internal/cctz/include/cctz/civil_time.h" namespace chrono = std::chrono; @@ -1043,7 +1047,7 @@ // 1) we know how to change the time zone used by localtime()/mktime(), // 2) cctz and localtime()/mktime() will use similar-enough tzdata, and // 3) we have some idea about how mktime() behaves during transitions. -#if defined(__linux__) && !defined(__ANDROID__) +#if defined(__linux__) && defined(__GLIBC__) && !defined(__ANDROID__) const char* const ep = getenv("TZ"); std::string tz_name = (ep != nullptr) ? ep : ""; for (const char* const* np = kTimeZoneNames; *np != nullptr; ++np) {
diff --git a/third_party/abseil-cpp/absl/time/time.h b/third_party/abseil-cpp/absl/time/time.h index 69d7220..f284aa3 100644 --- a/third_party/abseil-cpp/absl/time/time.h +++ b/third_party/abseil-cpp/absl/time/time.h
@@ -162,7 +162,7 @@ constexpr Duration() : rep_hi_(0), rep_lo_(0) {} // zero-length duration // Copyable. -#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1910 +#if !defined(__clang__) && defined(_MSC_VER) && _MSC_VER < 1930 // Explicitly defining the constexpr copy constructor avoids an MSVC bug. constexpr Duration(const Duration& d) : rep_hi_(d.rep_hi_), rep_lo_(d.rep_lo_) {}
diff --git a/third_party/abseil-cpp/ci/macos_xcode_bazel.sh b/third_party/abseil-cpp/ci/macos_xcode_bazel.sh index 1e29311..8d69f1dee 100755 --- a/third_party/abseil-cpp/ci/macos_xcode_bazel.sh +++ b/third_party/abseil-cpp/ci/macos_xcode_bazel.sh
@@ -24,7 +24,7 @@ fi # If we are running on Kokoro, check for a versioned Bazel binary. -KOKORO_GFILE_BAZEL_BIN="bazel-3.7.0-darwin-x86_64" +KOKORO_GFILE_BAZEL_BIN="bazel-5.1.1-darwin-x86_64" if [[ ${KOKORO_GFILE_DIR:-} ]] && [[ -f ${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN} ]]; then BAZEL_BIN="${KOKORO_GFILE_DIR}/${KOKORO_GFILE_BAZEL_BIN}" chmod +x ${BAZEL_BIN}
diff --git a/third_party/blink/common/client_hints/client_hints.cc b/third_party/blink/common/client_hints/client_hints.cc index fb72470..373c3d9 100644 --- a/third_party/blink/common/client_hints/client_hints.cc +++ b/third_party/blink/common/client_hints/client_hints.cc
@@ -76,6 +76,8 @@ mojom::PermissionsPolicyFeature::kClientHintUAFull}, {network::mojom::WebClientHintsType::kUAWoW64, mojom::PermissionsPolicyFeature::kClientHintUAWoW64}, + {network::mojom::WebClientHintsType::kPartitionedCookies, + mojom::PermissionsPolicyFeature::kClientHintPartitionedCookies}, {network::mojom::WebClientHintsType::kSaveData, mojom::PermissionsPolicyFeature::kClientHintSaveData}, };
diff --git a/third_party/blink/common/client_hints/client_hints_unittest.cc b/third_party/blink/common/client_hints/client_hints_unittest.cc index 171a887..046a865a 100644 --- a/third_party/blink/common/client_hints/client_hints_unittest.cc +++ b/third_party/blink/common/client_hints/client_hints_unittest.cc
@@ -33,7 +33,8 @@ "sec-ch-prefers-color-scheme", "sec-ch-ua-bitness", "sec-ch-ua-reduced", "sec-ch-viewport-height", "sec-ch-device-memory", "sec-ch-dpr", "sec-ch-width", "sec-ch-viewport-width", - "sec-ch-ua-full-version-list", "sec-ch-ua-full", "sec-ch-ua-wow64")); + "sec-ch-ua-full-version-list", "sec-ch-ua-full", "sec-ch-ua-wow64", + "sec-ch-partitioned-cookies")); } // Checks that the removed header list includes legacy headers but not the @@ -53,6 +54,6 @@ "sec-ch-ua-bitness", "sec-ch-ua-reduced", "sec-ch-viewport-height", "sec-ch-device-memory", "sec-ch-dpr", "sec-ch-width", "sec-ch-viewport-width", "sec-ch-ua-full-version-list", - "sec-ch-ua-full", "sec-ch-ua-wow64")); + "sec-ch-ua-full", "sec-ch-ua-wow64", "sec-ch-partitioned-cookies")); } } // namespace blink
diff --git a/third_party/blink/common/client_hints/enabled_client_hints.cc b/third_party/blink/common/client_hints/enabled_client_hints.cc index b8bd0e4..075e1382 100644 --- a/third_party/blink/common/client_hints/enabled_client_hints.cc +++ b/third_party/blink/common/client_hints/enabled_client_hints.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "base/time/time.h" +#include "net/base/features.h" #include "net/http/http_response_headers.h" #include "services/network/public/cpp/client_hints.h" #include "third_party/blink/public/common/features.h" @@ -84,6 +85,10 @@ features::kClientHintsViewportWidth_DEPRECATED)) return true; break; + case WebClientHintsType::kPartitionedCookies: + if (!base::FeatureList::IsEnabled(net::features::kPartitionedCookies)) + return true; + break; case WebClientHintsType::kSaveData: if (!base::FeatureList::IsEnabled(features::kClientHintsSaveData)) return true; @@ -155,6 +160,10 @@ enabled = IsOriginTrialEnabled(url, third_party_url, response_headers, "SendFullUserAgentAfterReduction"); } + if (enabled && type == WebClientHintsType::kPartitionedCookies) { + enabled = IsOriginTrialEnabled(url, third_party_url, response_headers, + "PartitionedCookies"); + } SetIsEnabled(type, enabled); }
diff --git a/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc b/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc index ef0438f2..26101764 100644 --- a/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc +++ b/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc
@@ -7,6 +7,7 @@ #include "absl/types/optional.h" #include "base/memory/scoped_refptr.h" #include "base/test/scoped_feature_list.h" +#include "net/base/features.h" #include "net/http/http_response_headers.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -321,4 +322,128 @@ WebClientHintsType::kUAFullVersionList)); } +// TODO(crbug.com/1296161): Delete this when partitioned cookies Origin Trial is +// over. +class PartitionedCookiesEnabledClientHintsTest + : public testing::TestWithParam<bool> { + protected: + PartitionedCookiesEnabledClientHintsTest() + : response_headers_(base::MakeRefCounted<net::HttpResponseHeaders>("")) { + TrialTokenValidator::SetOriginTrialPolicyGetter( + base::BindRepeating([](OriginTrialPolicy* policy) { return policy; }, + base::Unretained(&policy_))); + policy_.SetPublicKeys({kTestPublicKey}); + } + + void SetUp() override { + std::vector<base::Feature> enabled_features = { + blink::features::kUserAgentClientHint, + blink::features::kUserAgentClientHintFullVersionList}; + std::vector<base::Feature> disabled_features = { + blink::features::kPrefersColorSchemeClientHintHeader}; + if (PartitionedCookiesEnabled()) { + enabled_features.push_back(net::features::kPartitionedCookies); + } else { + disabled_features.push_back(net::features::kPartitionedCookies); + } + + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + testing::TestWithParam<bool>::SetUp(); + } + + bool PartitionedCookiesEnabled() { return GetParam(); } + + void VerifyClientHintEnabledWithOriginTrialToken( + const std::string& token, + const GURL* third_party_url, + const WebClientHintsType client_hint_type, + bool expected_client_hint_enabled) { + VerifyClientHintEnabledWithOriginTrialTokenInner( + response_headers_.get(), token, third_party_url, client_hint_type, + expected_client_hint_enabled); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + scoped_refptr<net::HttpResponseHeaders> response_headers_; + TestOriginTrialPolicy policy_; +}; + +INSTANTIATE_TEST_SUITE_P(/* no label */, + PartitionedCookiesEnabledClientHintsTest, + testing::Bool()); + +TEST_P(PartitionedCookiesEnabledClientHintsTest, + EnabledPartitionedCookiesClientHintWithValidOriginTrialToken) { + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 PartitionedCookies + // --expire-timestamp=2000000000 + // + // The Origin Trial token expires in 2033. Generate a new token by then, or + // find a better way to re-generate a test trial token. + static constexpr char kValidOriginTrialToken[] = + "A4s/" + "iPKfhEfgqQIIuz4zLuCpONpXOuYyJFBhBx1MfgS1aNhFujyhsg4lkfTRfjzQCI3aUbMwtNm2" + "5elLTR4UIgAAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVh" + "dHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; + + VerifyClientHintEnabledWithOriginTrialToken( + kValidOriginTrialToken, + /*third_party_url=*/nullptr, WebClientHintsType::kPartitionedCookies, + /*expected_client_hint_enabled=*/PartitionedCookiesEnabled()); +} + +TEST_P(PartitionedCookiesEnabledClientHintsTest, + EnabledPartitionedCookiesClientHintWithInvalidOriginTrialToken) { + // Changed the first character of the token in the last test. + static constexpr char kValidOriginTrialToken[] = + "B4s/" + "iPKfhEfgqQIIuz4zLuCpONpXOuYyJFBhBx1MfgS1aNhFujyhsg4lkfTRfjzQCI3aUbMwtNm2" + "5elLTR4UIgAAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVh" + "dHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; + + VerifyClientHintEnabledWithOriginTrialToken( + kValidOriginTrialToken, + /*third_party_url=*/nullptr, WebClientHintsType::kPartitionedCookies, + /*expected_client_hint_enabled=*/false); +} + +TEST_P(PartitionedCookiesEnabledClientHintsTest, + EnabledPartitionedCookiesClientHintWithValidThirdPartyOriginTrialToken) { + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44445 PartitionedCookies + // --expire-timestamp=2000000000 --is-third-party + // + // The Origin Trial token expires in 2033. Generate a new token by then, or + // find a better way to re-generate a test trial token. + static constexpr char kValidThirdPartyOriginTrialToken[] = + "A2VMEbGkZuIokMW5yBD0YFxwr8cyNw8iqteLIH7mv2bbKdoyIe4IFNC9G/" + "Fk7sfN5gcwcwtSJEYsMp2e6ol6cQgAAAByeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLj" + "E6NDQ0NDUiLCAiZmVhdHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMj" + "AwMDAwMDAwMCwgImlzVGhpcmRQYXJ0eSI6IHRydWV9"; + + const GURL third_party_url = GURL(kThirdPartyOriginUrl); + VerifyClientHintEnabledWithOriginTrialToken( + kValidThirdPartyOriginTrialToken, &third_party_url, + WebClientHintsType::kPartitionedCookies, + /*expected_client_hint_enabled=*/PartitionedCookiesEnabled()); +} + +TEST_P( + PartitionedCookiesEnabledClientHintsTest, + EnabledPartitionedCookiesClientHintWithInvalidThirdPartyOriginTrialToken) { + // Changed the first character of the token in the last test. + static constexpr char kValidThirdPartyOriginTrialToken[] = + "B2VMEbGkZuIokMW5yBD0YFxwr8cyNw8iqteLIH7mv2bbKdoyIe4IFNC9G/" + "Fk7sfN5gcwcwtSJEYsMp2e6ol6cQgAAAByeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLj" + "E6NDQ0NDUiLCAiZmVhdHVyZSI6ICJQYXJ0aXRpb25lZENvb2tpZXMiLCAiZXhwaXJ5IjogMj" + "AwMDAwMDAwMCwgImlzVGhpcmRQYXJ0eSI6IHRydWV9"; + + const GURL third_party_url = GURL(kThirdPartyOriginUrl); + VerifyClientHintEnabledWithOriginTrialToken( + kValidThirdPartyOriginTrialToken, &third_party_url, + WebClientHintsType::kPartitionedCookies, + /*expected_client_hint_enabled=*/false); +} + } // namespace blink
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 3bfefe2..c0fa03ed 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1357,6 +1357,9 @@ const base::Feature kElementSuperRareData{"ElementSuperRareData", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kClientHintsPartitionedCookies{ + "ClientHintsPartitionedCookies", base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kDurableClientHintsCache{"DurableClientHintsCache", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/third_party/blink/common/mediastream/media_stream_request.cc b/third_party/blink/common/mediastream/media_stream_request.cc index 6637eb60..6f4537e 100644 --- a/third_party/blink/common/mediastream/media_stream_request.cc +++ b/third_party/blink/common/mediastream/media_stream_request.cc
@@ -144,8 +144,8 @@ session_id_ == other_device.session_id_; } -// TODO(crbug/1313021): Remove this function and use blink::mojom::StreaDevices -// directly everywhere. +// TODO(crbug.com/1313021): Remove this function and use +// blink::mojom::StreaDevices directly everywhere. blink::MediaStreamDevices StreamDevicesToMediaStreamDevicesList( const blink::mojom::StreamDevices& devices) { blink::MediaStreamDevices all_devices;
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index 508f218..459c42e 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -659,9 +659,6 @@ BLINK_COMMON_EXPORT extern const base::Feature kElementSuperRareData; BLINK_COMMON_EXPORT extern const base::Feature kClientHintsPartitionedCookies; -BLINK_COMMON_EXPORT extern const base::Feature kScaleTileMemoryLimit; -BLINK_COMMON_EXPORT -extern const base::FeatureParam<double> kScaleTileMemoryLimitFactor; // If enabled, the client hints cache will be loaded on browser restarts. BLINK_COMMON_EXPORT extern const base::Feature kDurableClientHintsCache;
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 2f1befd..e889a0e 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -6999,6 +6999,7 @@ ch-device-memory ch-downlink ch-ect + ch-partitioned-cookies ch-prefers-color-scheme ch-rtt ch-save-data
diff --git a/third_party/blink/public/mojom/mediastream/media_stream.mojom b/third_party/blink/public/mojom/mediastream/media_stream.mojom index ea74498..33cf4c3 100644 --- a/third_party/blink/public/mojom/mediastream/media_stream.mojom +++ b/third_party/blink/public/mojom/mediastream/media_stream.mojom
@@ -142,12 +142,17 @@ MediaStreamDevice device); }; -// Contains devices that are assigned to a specific stream. +// Contains devices that are assigned to a specific stream. At least one of +// audio_device / video_device must be set. struct StreamDevices { MediaStreamDevice? audio_device; MediaStreamDevice? video_device; }; +struct StreamDevicesSet { + array<StreamDevices> stream_devices; +}; + // Per-frame browser-side interface that is used by the renderer process to // make media stream requests. interface MediaStreamDispatcherHost { @@ -165,10 +170,18 @@ // finally, when it is SEARCH_BY_DEVICE_ID, an existing stream is used if the // device associated to the request already has an opened stream available, or // a new one otherwise. - GenerateStream(int32 request_id, StreamControls controls, bool user_gesture, + // The result callback provides: + // |result|: The overall result of the stream generation. + // |label|: The request label. + // |stream_devices|: A list of devices per stream. If |result| is not ok, this + // list may be null. + // |pan_tilt_zoom_allowed|: A flag indicating whether pan / tilt / zoom is + // allowed. + // TODO(crbug.com/1327958): Use expected<T,E> for the return values. + GenerateStreams(int32 request_id, StreamControls controls, bool user_gesture, StreamSelectionInfo audio_stream_selection_info) => (MediaStreamRequestResult result, string label, - StreamDevices? stream_devices, + StreamDevicesSet? stream_devices, bool pan_tilt_zoom_allowed); // The |focus| bit is |true| if focus should be switched to
diff --git a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom index b67a678..c9232f4 100644 --- a/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom +++ b/third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom
@@ -193,6 +193,21 @@ // Client Hint for Sec-CH-UA-WoW64. kClientHintUAWoW64 = 95, + // Client hint for indicating that the client supports the Partitioned cookie + // attribute. + // + // The `Sec-CH-Partitioned-Cookies` header field is a temporary client hint, + // which will only be sent in the presence of a valid Origin Trial token. It + // was introduced to enable safely experimenting with cookies set with the + // Partitioned attribute. + // + // See https://chromestatus.com/feature/5179189105786880 for the Partitioned + // cookie attribute (a.k.a. Cookies Having Independent Partitioned State, + // CHIPS) Chrome feature and the explainer at https://github.com/WICG/CHIPS + // for details about the design of the Partitioned attribute and partitioned + // cookies. + kClientHintPartitionedCookies = 96, + // "browsing-topics" permissions policy that controls the use of Topics API. // https://github.com/jkarlin/topics kBrowsingTopics = 97,
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index 2d09efc..464dc967c 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3478,7 +3478,7 @@ kV8UDPSocket_RemotePort_AttributeGetter = 4157, kV8UDPSocket_Writable_AttributeGetter = 4158, kAbortSignalTimeout = 4159, - kOBSOLETE_ClientHintsPartitionedCookies = 4160, + kClientHintsPartitionedCookies = 4160, kV8Document_Prerendering_AttributeGetter = 4161, kV8Document_Onprerenderingchange_AttributeGetter = 4162, kV8Document_Onprerenderingchange_AttributeSetter = 4163,
diff --git a/third_party/blink/public/platform/web_url_response.h b/third_party/blink/public/platform/web_url_response.h index 1b0e7314..bce15a98 100644 --- a/third_party/blink/public/platform/web_url_response.h +++ b/third_party/blink/public/platform/web_url_response.h
@@ -284,9 +284,6 @@ BLINK_PLATFORM_EXPORT void SetWasFetchedViaCache(bool); BLINK_PLATFORM_EXPORT void SetArrivalTimeAtRenderer(base::TimeTicks arrival); - BLINK_PLATFORM_EXPORT void SetHasPartitionedCookie( - bool has_partitioned_cookie); - #if INSIDE_BLINK protected: // Permit subclasses to set arbitrary ResourceResponse pointer as
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni index a4a8f4f..a8ee0f9 100644 --- a/third_party/blink/renderer/core/css/build.gni +++ b/third_party/blink/renderer/core/css/build.gni
@@ -256,6 +256,8 @@ "css_timing_function_value.h", "css_to_length_conversion_data.cc", "css_to_length_conversion_data.h", + "css_length_resolver.cc", + "css_length_resolver.h", "css_unicode_range_value.cc", "css_unicode_range_value.h", "css_unset_value.cc",
diff --git a/third_party/blink/renderer/core/css/css_length_resolver.cc b/third_party/blink/renderer/core/css/css_length_resolver.cc new file mode 100644 index 0000000..393a1117 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_length_resolver.cc
@@ -0,0 +1,286 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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/css/css_length_resolver.h" + +#include "third_party/blink/renderer/core/css/css_resolution_units.h" + +namespace blink { + +double CSSLengthResolver::ViewportWidthPercent() const { + return ViewportWidth() / 100; +} + +double CSSLengthResolver::ViewportHeightPercent() const { + return ViewportHeight() / 100; +} + +double CSSLengthResolver::ViewportInlineSizePercent() const { + return (IsHorizontalWritingMode() ? ViewportWidth() : ViewportHeight()) / 100; +} + +double CSSLengthResolver::ViewportBlockSizePercent() const { + return (IsHorizontalWritingMode() ? ViewportHeight() : ViewportWidth()) / 100; +} + +double CSSLengthResolver::ViewportMinPercent() const { + return std::min(ViewportWidth(), ViewportHeight()) / 100; +} + +double CSSLengthResolver::ViewportMaxPercent() const { + return std::max(ViewportWidth(), ViewportHeight()) / 100; +} + +double CSSLengthResolver::SmallViewportWidthPercent() const { + return SmallViewportWidth() / 100; +} + +double CSSLengthResolver::SmallViewportHeightPercent() const { + return SmallViewportHeight() / 100; +} + +double CSSLengthResolver::SmallViewportInlineSizePercent() const { + return (IsHorizontalWritingMode() ? SmallViewportWidth() + : SmallViewportHeight()) / + 100; +} + +double CSSLengthResolver::SmallViewportBlockSizePercent() const { + return (IsHorizontalWritingMode() ? SmallViewportHeight() + : SmallViewportWidth()) / + 100; +} + +double CSSLengthResolver::SmallViewportMinPercent() const { + return std::min(SmallViewportWidth(), SmallViewportHeight()) / 100; +} + +double CSSLengthResolver::SmallViewportMaxPercent() const { + return std::max(SmallViewportWidth(), SmallViewportHeight()) / 100; +} + +double CSSLengthResolver::LargeViewportWidthPercent() const { + return LargeViewportWidth() / 100; +} + +double CSSLengthResolver::LargeViewportHeightPercent() const { + return LargeViewportHeight() / 100; +} + +double CSSLengthResolver::LargeViewportInlineSizePercent() const { + return (IsHorizontalWritingMode() ? LargeViewportWidth() + : LargeViewportHeight()) / + 100; +} + +double CSSLengthResolver::LargeViewportBlockSizePercent() const { + return (IsHorizontalWritingMode() ? LargeViewportHeight() + : LargeViewportWidth()) / + 100; +} + +double CSSLengthResolver::LargeViewportMinPercent() const { + return std::min(LargeViewportWidth(), LargeViewportHeight()) / 100; +} + +double CSSLengthResolver::LargeViewportMaxPercent() const { + return std::max(LargeViewportWidth(), LargeViewportHeight()) / 100; +} + +double CSSLengthResolver::DynamicViewportWidthPercent() const { + return DynamicViewportWidth() / 100; +} + +double CSSLengthResolver::DynamicViewportHeightPercent() const { + return DynamicViewportHeight() / 100; +} + +double CSSLengthResolver::DynamicViewportInlineSizePercent() const { + return (IsHorizontalWritingMode() ? DynamicViewportWidth() + : DynamicViewportHeight()) / + 100; +} + +double CSSLengthResolver::DynamicViewportBlockSizePercent() const { + return (IsHorizontalWritingMode() ? DynamicViewportHeight() + : DynamicViewportWidth()) / + 100; +} + +double CSSLengthResolver::DynamicViewportMinPercent() const { + return std::min(DynamicViewportWidth(), DynamicViewportHeight()) / 100; +} + +double CSSLengthResolver::DynamicViewportMaxPercent() const { + return std::max(DynamicViewportWidth(), DynamicViewportHeight()) / 100; +} + +double CSSLengthResolver::ContainerWidthPercent() const { + return ContainerWidth() / 100; +} + +double CSSLengthResolver::ContainerHeightPercent() const { + return ContainerHeight() / 100; +} + +double CSSLengthResolver::ContainerInlineSizePercent() const { + return IsHorizontalWritingMode() ? ContainerWidthPercent() + : ContainerHeightPercent(); +} + +double CSSLengthResolver::ContainerBlockSizePercent() const { + return IsHorizontalWritingMode() ? ContainerHeightPercent() + : ContainerWidthPercent(); +} + +double CSSLengthResolver::ContainerMinPercent() const { + return std::min(ContainerWidthPercent(), ContainerHeightPercent()); +} + +double CSSLengthResolver::ContainerMaxPercent() const { + return std::max(ContainerWidthPercent(), ContainerHeightPercent()); +} + +double CSSLengthResolver::ZoomedComputedPixels( + double value, + CSSPrimitiveValue::UnitType type) const { + // The logic in this function is duplicated in MediaValues::ComputeLength() + // because MediaValues::ComputeLength() needs nearly identical logic, but we + // haven't found a way to make ZoomedComputedPixels() more generic (to solve + // both cases) without hurting performance. + switch (type) { + case CSSPrimitiveValue::UnitType::kPixels: + case CSSPrimitiveValue::UnitType::kUserUnits: + return value * Zoom(); + + case CSSPrimitiveValue::UnitType::kCentimeters: + return value * kCssPixelsPerCentimeter * Zoom(); + + case CSSPrimitiveValue::UnitType::kMillimeters: + return value * kCssPixelsPerMillimeter * Zoom(); + + case CSSPrimitiveValue::UnitType::kQuarterMillimeters: + return value * kCssPixelsPerQuarterMillimeter * Zoom(); + + case CSSPrimitiveValue::UnitType::kInches: + return value * kCssPixelsPerInch * Zoom(); + + case CSSPrimitiveValue::UnitType::kPoints: + return value * kCssPixelsPerPoint * Zoom(); + + case CSSPrimitiveValue::UnitType::kPicas: + return value * kCssPixelsPerPica * Zoom(); + + case CSSPrimitiveValue::UnitType::kViewportWidth: + return value * ViewportWidthPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kViewportHeight: + return value * ViewportHeightPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kViewportInlineSize: + return value * ViewportInlineSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kViewportBlockSize: + return value * ViewportBlockSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kViewportMin: + return value * ViewportMinPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kViewportMax: + return value * ViewportMaxPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kSmallViewportWidth: + return value * SmallViewportWidthPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kSmallViewportHeight: + return value * SmallViewportHeightPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kSmallViewportInlineSize: + return value * SmallViewportInlineSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kSmallViewportBlockSize: + return value * SmallViewportBlockSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kSmallViewportMin: + return value * SmallViewportMinPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kSmallViewportMax: + return value * SmallViewportMaxPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kLargeViewportWidth: + return value * LargeViewportWidthPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kLargeViewportHeight: + return value * LargeViewportHeightPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kLargeViewportInlineSize: + return value * LargeViewportInlineSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kLargeViewportBlockSize: + return value * LargeViewportBlockSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kLargeViewportMin: + return value * LargeViewportMinPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kLargeViewportMax: + return value * LargeViewportMaxPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kDynamicViewportWidth: + return value * DynamicViewportWidthPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kDynamicViewportHeight: + return value * DynamicViewportHeightPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kDynamicViewportInlineSize: + return value * DynamicViewportInlineSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kDynamicViewportBlockSize: + return value * DynamicViewportBlockSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kDynamicViewportMin: + return value * DynamicViewportMinPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kDynamicViewportMax: + return value * DynamicViewportMaxPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kContainerWidth: + return value * ContainerWidthPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kContainerHeight: + return value * ContainerHeightPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kContainerInlineSize: + return value * ContainerInlineSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kContainerBlockSize: + return value * ContainerBlockSizePercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kContainerMin: + return value * ContainerMinPercent() * Zoom(); + + case CSSPrimitiveValue::UnitType::kContainerMax: + return value * ContainerMaxPercent() * Zoom(); + + // Note that functions for font-relative units already account for the + // zoom factor. + case CSSPrimitiveValue::UnitType::kEms: + case CSSPrimitiveValue::UnitType::kQuirkyEms: + return value * EmFontSize(); + + case CSSPrimitiveValue::UnitType::kExs: + return value * ExFontSize(); + + case CSSPrimitiveValue::UnitType::kRems: + return value * RemFontSize(); + + case CSSPrimitiveValue::UnitType::kChs: + return value * ChFontSize(); + + default: + NOTREACHED(); + return 0; + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_length_resolver.h b/third_party/blink/renderer/core/css/css_length_resolver.h new file mode 100644 index 0000000..65fa220 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_length_resolver.h
@@ -0,0 +1,89 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// 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_CSS_CSS_LENGTH_RESOLVER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LENGTH_RESOLVER_H_ + +#include <limits> +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_primitive_value.h" +#include "third_party/blink/renderer/platform/text/writing_mode.h" +#include "third_party/blink/renderer/platform/wtf/math_extras.h" + +namespace blink { + +class CORE_EXPORT CSSLengthResolver { + public: + explicit CSSLengthResolver(float zoom) : zoom_(zoom) {} + + // Font-relative must be pre-zoomed. + virtual float EmFontSize() const = 0; + virtual float RemFontSize() const = 0; + virtual float ExFontSize() const = 0; + virtual float ChFontSize() const = 0; + + // Other sizes must not be pre-zoomed. + virtual double ViewportWidth() const = 0; + virtual double ViewportHeight() const = 0; + virtual double SmallViewportWidth() const = 0; + virtual double SmallViewportHeight() const = 0; + virtual double LargeViewportWidth() const = 0; + virtual double LargeViewportHeight() const = 0; + virtual double DynamicViewportWidth() const = 0; + virtual double DynamicViewportHeight() const = 0; + virtual double ContainerWidth() const = 0; + virtual double ContainerHeight() const = 0; + + virtual WritingMode GetWritingMode() const = 0; + + float Zoom() const { return zoom_; } + void SetZoom(float zoom) { + DCHECK(std::isfinite(zoom)); + DCHECK_GT(zoom, 0); + zoom_ = zoom; + } + + double ZoomedComputedPixels(double value, CSSPrimitiveValue::UnitType) const; + + private: + bool IsHorizontalWritingMode() const { + return blink::IsHorizontalWritingMode(GetWritingMode()); + } + double ViewportWidthPercent() const; + double ViewportHeightPercent() const; + double ViewportInlineSizePercent() const; + double ViewportBlockSizePercent() const; + double ViewportMinPercent() const; + double ViewportMaxPercent() const; + double SmallViewportWidthPercent() const; + double SmallViewportHeightPercent() const; + double SmallViewportInlineSizePercent() const; + double SmallViewportBlockSizePercent() const; + double SmallViewportMinPercent() const; + double SmallViewportMaxPercent() const; + double LargeViewportWidthPercent() const; + double LargeViewportHeightPercent() const; + double LargeViewportInlineSizePercent() const; + double LargeViewportBlockSizePercent() const; + double LargeViewportMinPercent() const; + double LargeViewportMaxPercent() const; + double DynamicViewportWidthPercent() const; + double DynamicViewportHeightPercent() const; + double DynamicViewportInlineSizePercent() const; + double DynamicViewportBlockSizePercent() const; + double DynamicViewportMinPercent() const; + double DynamicViewportMaxPercent() const; + double ContainerWidthPercent() const; + double ContainerHeightPercent() const; + double ContainerInlineSizePercent() const; + double ContainerBlockSizePercent() const; + double ContainerMinPercent() const; + double ContainerMaxPercent() const; + + float zoom_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_LENGTH_RESOLVER_H_
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc index d7872d4..80fc2e52 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.cc +++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -227,7 +227,7 @@ absl::optional<PixelsAndPercent> CSSMathExpressionNumericLiteral::ToPixelsAndPercent( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { PixelsAndPercent value(0, 0); switch (category_) { case kCalcLength: @@ -235,9 +235,9 @@ // PixelsAndPercent. Therefore, we need to use a function that doesn't // internally clamp the result to the float range. if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) - value.pixels = value_->ComputeLengthPx(conversion_data); + value.pixels = value_->ComputeLengthPx(length_resolver); else - value.pixels = value_->ComputeLength<float>(conversion_data); + value.pixels = value_->ComputeLength<float>(length_resolver); break; case kCalcPercent: DCHECK(value_->IsPercentage()); @@ -253,7 +253,7 @@ // TODO(alancutter): Stop treating numbers like pixels unconditionally // in calcs to be able to accomodate border-image-width // https://drafts.csswg.org/css-backgrounds-3/#the-border-image-width - value.pixels = value_->GetFloatValue() * conversion_data.Zoom(); + value.pixels = value_->GetFloatValue() * length_resolver.Zoom(); break; default: NOTREACHED(); @@ -263,9 +263,9 @@ scoped_refptr<const CalculationExpressionNode> CSSMathExpressionNumericLiteral::ToCalculationExpression( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { return base::MakeRefCounted<CalculationExpressionPixelsAndPercentNode>( - *ToPixelsAndPercent(conversion_data)); + *ToPixelsAndPercent(length_resolver)); } double CSSMathExpressionNumericLiteral::DoubleValue() const { @@ -297,15 +297,15 @@ } double CSSMathExpressionNumericLiteral::ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { switch (category_) { case kCalcLength: // When CSSCalcInfinityAndNaN is enabled, we allow infinity and NaN in // PixelsAndPercent. Therefore, we need to use a function that doesn't // internally clamp the result to the float range. if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) - return value_->ComputeLengthPx(conversion_data); - return value_->ComputeLength<double>(conversion_data); + return value_->ComputeLengthPx(length_resolver); + return value_->ComputeLength<double>(length_resolver); case kCalcNumber: case kCalcPercent: case kCalcAngle: @@ -585,18 +585,18 @@ } absl::optional<PixelsAndPercent> CSSMathExpressionOperation::ToPixelsAndPercent( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { absl::optional<PixelsAndPercent> result; switch (operator_) { case CSSMathOperator::kAdd: case CSSMathOperator::kSubtract: { DCHECK_EQ(operands_.size(), 2u); - result = operands_[0]->ToPixelsAndPercent(conversion_data); + result = operands_[0]->ToPixelsAndPercent(length_resolver); if (!result) return absl::nullopt; absl::optional<PixelsAndPercent> other_side = - operands_[1]->ToPixelsAndPercent(conversion_data); + operands_[1]->ToPixelsAndPercent(length_resolver); if (!other_side) return absl::nullopt; if (operator_ == CSSMathOperator::kAdd) { @@ -615,7 +615,7 @@ GetNumberSide(operands_[0], operands_[1]); const CSSMathExpressionNode* other_side = operands_[0] == number_side ? operands_[1] : operands_[0]; - result = other_side->ToPixelsAndPercent(conversion_data); + result = other_side->ToPixelsAndPercent(length_resolver); if (!result) return absl::nullopt; float number = number_side->DoubleValue(); @@ -637,21 +637,21 @@ scoped_refptr<const CalculationExpressionNode> CSSMathExpressionOperation::ToCalculationExpression( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { switch (operator_) { case CSSMathOperator::kAdd: DCHECK_EQ(operands_.size(), 2u); return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {operands_[0]->ToCalculationExpression(conversion_data), - operands_[1]->ToCalculationExpression(conversion_data)}), + {operands_[0]->ToCalculationExpression(length_resolver), + operands_[1]->ToCalculationExpression(length_resolver)}), CalculationOperator::kAdd); case CSSMathOperator::kSubtract: DCHECK_EQ(operands_.size(), 2u); return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {operands_[0]->ToCalculationExpression(conversion_data), - operands_[1]->ToCalculationExpression(conversion_data)}), + {operands_[0]->ToCalculationExpression(length_resolver), + operands_[1]->ToCalculationExpression(length_resolver)}), CalculationOperator::kSubtract); case CSSMathOperator::kMultiply: DCHECK_EQ(operands_.size(), 2u); @@ -660,14 +660,14 @@ if (operands_[0]->Category() == kCalcNumber) { return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {operands_[1]->ToCalculationExpression(conversion_data), + {operands_[1]->ToCalculationExpression(length_resolver), base::MakeRefCounted<CalculationExpressionNumberNode>( operands_[0]->DoubleValue())}), CalculationOperator::kMultiply); } return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {operands_[0]->ToCalculationExpression(conversion_data), + {operands_[0]->ToCalculationExpression(length_resolver), base::MakeRefCounted<CalculationExpressionNumberNode>( operands_[1]->DoubleValue())}), CalculationOperator::kMultiply); @@ -676,7 +676,7 @@ DCHECK_EQ(operands_[1]->Category(), kCalcNumber); return CalculationExpressionOperationNode::CreateSimplified( CalculationExpressionOperationNode::Children( - {operands_[0]->ToCalculationExpression(conversion_data), + {operands_[0]->ToCalculationExpression(length_resolver), base::MakeRefCounted<CalculationExpressionNumberNode>( 1.0 / operands_[1]->DoubleValue())}), CalculationOperator::kMultiply); @@ -685,7 +685,7 @@ Vector<scoped_refptr<const CalculationExpressionNode>> operands; operands.ReserveCapacity(operands_.size()); for (const CSSMathExpressionNode* operand : operands_) - operands.push_back(operand->ToCalculationExpression(conversion_data)); + operands.push_back(operand->ToCalculationExpression(length_resolver)); auto expression_operator = operator_ == CSSMathOperator::kMin ? CalculationOperator::kMin : CalculationOperator::kMax; @@ -696,7 +696,7 @@ Vector<scoped_refptr<const CalculationExpressionNode>> operands; operands.ReserveCapacity(operands_.size()); for (const CSSMathExpressionNode* operand : operands_) - operands.push_back(operand->ToCalculationExpression(conversion_data)); + operands.push_back(operand->ToCalculationExpression(length_resolver)); return CalculationExpressionOperationNode::CreateSimplified( std::move(operands), CalculationOperator::kClamp); } @@ -738,13 +738,13 @@ } double CSSMathExpressionOperation::ComputeLengthPx( - const CSSToLengthConversionData& data) const { + const CSSLengthResolver& length_resolver) const { DCHECK_EQ(kCalcLength, Category()); Vector<double> double_values; double_values.ReserveCapacity(operands_.size()); for (const CSSMathExpressionNode* operand : operands_) { if (operand->Category() == kCalcLength) { - double_values.push_back(operand->ComputeLengthPx(data)); + double_values.push_back(operand->ComputeLengthPx(length_resolver)); } else { DCHECK_EQ(operand->Category(), kCalcNumber); double_values.push_back(operand->DoubleValue()); @@ -1076,7 +1076,7 @@ scoped_refptr<const CalculationExpressionNode> CSSMathExpressionAnchorQuery::ToCalculationExpression( - const CSSToLengthConversionData&) const { + const CSSLengthResolver&) const { // TODO(crbug.com/1309178): Implement. return base::MakeRefCounted<CalculationExpressionPixelsAndPercentNode>( PixelsAndPercent(0, 0)); @@ -1388,10 +1388,10 @@ }; scoped_refptr<const CalculationValue> CSSMathExpressionNode::ToCalcValue( - const CSSToLengthConversionData& conversion_data, + const CSSLengthResolver& length_resolver, Length::ValueRange range, bool allows_negative_percentage_reference) const { - if (auto maybe_pixels_and_percent = ToPixelsAndPercent(conversion_data)) { + if (auto maybe_pixels_and_percent = ToPixelsAndPercent(length_resolver)) { // Clamping if pixels + percent could result in NaN. In special case, // inf px + inf % could evaluate to nan when // allows_negative_percentage_reference is true. @@ -1408,7 +1408,7 @@ return CalculationValue::Create(*maybe_pixels_and_percent, range); } - auto value = ToCalculationExpression(conversion_data); + auto value = ToCalculationExpression(length_resolver); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) { absl::optional<PixelsAndPercent> evaluated_value = EvaluateValueIfNaNorInfinity(value,
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.h b/third_party/blink/renderer/core/css/css_math_expression_node.h index 52a846d9..c6a39c3 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.h +++ b/third_party/blink/renderer/core/css/css_math_expression_node.h
@@ -92,18 +92,18 @@ // Hits DCHECK if type conversion is required. virtual double DoubleValue() const = 0; - virtual double ComputeLengthPx(const CSSToLengthConversionData&) const = 0; + virtual double ComputeLengthPx(const CSSLengthResolver&) const = 0; virtual bool AccumulateLengthArray(CSSLengthArray&, double multiplier) const = 0; virtual void AccumulateLengthUnitTypes( CSSPrimitiveValue::LengthTypeFlags& types) const = 0; virtual scoped_refptr<const CalculationExpressionNode> - ToCalculationExpression(const CSSToLengthConversionData&) const = 0; + ToCalculationExpression(const CSSLengthResolver&) const = 0; virtual absl::optional<PixelsAndPercent> ToPixelsAndPercent( - const CSSToLengthConversionData&) const = 0; + const CSSLengthResolver&) const = 0; scoped_refptr<const CalculationValue> ToCalcValue( - const CSSToLengthConversionData& conversion_data, + const CSSLengthResolver& length_resolver, Length::ValueRange range, bool allows_negative_percentage_reference) const; @@ -180,13 +180,12 @@ bool IsZero() const final; String CustomCSSText() const final; scoped_refptr<const CalculationExpressionNode> ToCalculationExpression( - const CSSToLengthConversionData&) const final; + const CSSLengthResolver&) const final; absl::optional<PixelsAndPercent> ToPixelsAndPercent( - const CSSToLengthConversionData&) const final; + const CSSLengthResolver&) const final; double DoubleValue() const final; absl::optional<double> ComputeValueInCanonicalUnit() const final; - double ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const final; + double ComputeLengthPx(const CSSLengthResolver& length_resolver) const final; bool AccumulateLengthArray(CSSLengthArray& length_array, double multiplier) const final; void AccumulateLengthUnitTypes( @@ -255,13 +254,12 @@ bool IsZero() const final; scoped_refptr<const CalculationExpressionNode> ToCalculationExpression( - const CSSToLengthConversionData&) const final; + const CSSLengthResolver&) const final; absl::optional<PixelsAndPercent> ToPixelsAndPercent( - const CSSToLengthConversionData&) const final; + const CSSLengthResolver&) const final; double DoubleValue() const final; absl::optional<double> ComputeValueInCanonicalUnit() const final; - double ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const final; + double ComputeLengthPx(const CSSLengthResolver& length_resolver) const final; bool AccumulateLengthArray(CSSLengthArray& length_array, double multiplier) const final; void AccumulateLengthUnitTypes( @@ -332,7 +330,7 @@ return absl::nullopt; } absl::optional<PixelsAndPercent> ToPixelsAndPercent( - const CSSToLengthConversionData&) const final { + const CSSLengthResolver&) const final { return absl::nullopt; } bool AccumulateLengthArray(CSSLengthArray& length_array, @@ -345,8 +343,7 @@ NOTREACHED(); return 0; } - double ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const final { + double ComputeLengthPx(const CSSLengthResolver& length_resolver) const final { // We can't resolve an anchor query until layout time. NOTREACHED(); return 0; @@ -361,7 +358,7 @@ String CustomCSSText() const final; scoped_refptr<const CalculationExpressionNode> ToCalculationExpression( - const CSSToLengthConversionData&) const final; + const CSSLengthResolver&) const final; bool operator==(const CSSMathExpressionNode& other) const final; void Trace(Visitor* visitor) const final;
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.cc b/third_party/blink/renderer/core/css/css_math_function_value.cc index f281ee28..40aba330 100644 --- a/third_party/blink/renderer/core/css/css_math_function_value.cc +++ b/third_party/blink/renderer/core/css/css_math_function_value.cc
@@ -76,11 +76,11 @@ } double CSSMathFunctionValue::ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { // |CSSToLengthConversionData| only resolves relative length units, but not // percentages. DCHECK_EQ(kCalcLength, expression_->Category()); - return ClampToPermittedRange(expression_->ComputeLengthPx(conversion_data)); + return ClampToPermittedRange(expression_->ComputeLengthPx(length_resolver)); } bool CSSMathFunctionValue::AccumulateLengthArray(CSSLengthArray& length_array, @@ -89,10 +89,10 @@ } Length CSSMathFunctionValue::ConvertToLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { if (IsLength()) - return Length::Fixed(ComputeLengthPx(conversion_data)); - return Length(ToCalcValue(conversion_data)); + return Length::Fixed(ComputeLengthPx(length_resolver)); + return Length(ToCalcValue(length_resolver)); } static String BuildCSSText(const String& expression) { @@ -150,7 +150,7 @@ } scoped_refptr<const CalculationValue> CSSMathFunctionValue::ToCalcValue( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { DCHECK_NE(value_range_in_target_context_, CSSPrimitiveValue::ValueRange::kInteger); DCHECK_NE(value_range_in_target_context_, @@ -158,7 +158,7 @@ DCHECK_NE(value_range_in_target_context_, CSSPrimitiveValue::ValueRange::kPositiveInteger); return expression_->ToCalcValue( - conversion_data, + length_resolver, CSSPrimitiveValue::ConversionToLengthValueRange(PermittedValueRange()), AllowsNegativePercentageReference()); }
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.h b/third_party/blink/renderer/core/css/css_math_function_value.h index 7752232f..904cd4b 100644 --- a/third_party/blink/renderer/core/css/css_math_function_value.h +++ b/third_party/blink/renderer/core/css/css_math_function_value.h
@@ -26,7 +26,7 @@ const CSSMathExpressionNode* ExpressionNode() const { return expression_; } scoped_refptr<const CalculationValue> ToCalcValue( - const CSSToLengthConversionData& conversion_data) const; + const CSSLengthResolver&) const; bool MayHaveRelativeUnit() const; @@ -72,13 +72,11 @@ double ComputeSeconds() const; double ComputeDegrees() const; - double ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const; + double ComputeLengthPx(const CSSLengthResolver&) const; bool AccumulateLengthArray(CSSLengthArray& length_array, double multiplier) const; - Length ConvertToLength( - const CSSToLengthConversionData& conversion_data) const; + Length ConvertToLength(const CSSLengthResolver&) const; void AccumulateLengthUnitTypes(LengthTypeFlags& types) const { expression_->AccumulateLengthUnitTypes(types);
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc index 1f2452e1..eb5fe81a 100644 --- a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc +++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "build/build_config.h" -#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" +#include "third_party/blink/renderer/core/css/css_length_resolver.h" #include "third_party/blink/renderer/core/css/css_value_pool.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/size_assertions.h" @@ -118,9 +118,9 @@ } double CSSNumericLiteralValue::ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { DCHECK(IsLength()); - return conversion_data.ZoomedComputedPixels(num_, GetType()); + return length_resolver.ZoomedComputedPixels(num_, GetType()); } bool CSSNumericLiteralValue::AccumulateLengthArray(CSSLengthArray& length_array,
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.h b/third_party/blink/renderer/core/css/css_numeric_literal_value.h index a7f2b00..c9c52a1f 100644 --- a/third_party/blink/renderer/core/css/css_numeric_literal_value.h +++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.h
@@ -10,6 +10,8 @@ namespace blink { +class CSSLengthResolver; + // Numeric values that can be expressed as a single unit (or a naked number or // percentage). The equivalence of CSS Typed OM's |CSSUnitValue| in the // |CSSValue| class hierarchy. @@ -55,8 +57,7 @@ double ComputeDegrees() const; double ComputeDotsPerPixel() const; - double ComputeLengthPx( - const CSSToLengthConversionData& conversion_data) const; + double ComputeLengthPx(const CSSLengthResolver&) const; bool AccumulateLengthArray(CSSLengthArray& length_array, double multiplier) const; void AccumulateLengthUnitTypes(LengthTypeFlags& types) const;
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.cc b/third_party/blink/renderer/core/css/css_primitive_value.cc index 31e5d9f..85463a3 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value.cc +++ b/third_party/blink/renderer/core/css/css_primitive_value.cc
@@ -24,12 +24,12 @@ #include <cmath> #include "build/build_config.h" +#include "third_party/blink/renderer/core/css/css_length_resolver.h" #include "third_party/blink/renderer/core/css/css_markup.h" #include "third_party/blink/renderer/core/css/css_math_expression_node.h" #include "third_party/blink/renderer/core/css/css_math_function_value.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #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/css/css_value_clamping_utils.h" #include "third_party/blink/renderer/core/css/css_value_pool.h" #include "third_party/blink/renderer/platform/geometry/layout_unit.h" @@ -279,49 +279,49 @@ template <> int CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { - return RoundForImpreciseConversion<int>(ComputeLengthDouble(conversion_data)); + const CSSLengthResolver& length_resolver) const { + return RoundForImpreciseConversion<int>(ComputeLengthDouble(length_resolver)); } template <> unsigned CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { return RoundForImpreciseConversion<unsigned>( - ComputeLengthDouble(conversion_data)); + ComputeLengthDouble(length_resolver)); } template <> Length CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { return Length::Fixed( - ClampToCSSLengthRange(ComputeLengthDouble(conversion_data))); + ClampToCSSLengthRange(ComputeLengthDouble(length_resolver))); } template <> int16_t CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { return RoundForImpreciseConversion<int16_t>( - ComputeLengthDouble(conversion_data)); + ComputeLengthDouble(length_resolver)); } template <> uint16_t CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { return RoundForImpreciseConversion<uint16_t>( - ComputeLengthDouble(conversion_data)); + ComputeLengthDouble(length_resolver)); } template <> uint8_t CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { return RoundForImpreciseConversion<uint8_t>( - ComputeLengthDouble(conversion_data)); + ComputeLengthDouble(length_resolver)); } template <> float CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { - double value = ComputeLengthDouble(conversion_data); + const CSSLengthResolver& length_resolver) const { + double value = ComputeLengthDouble(length_resolver); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) { value = CSSValueClampingUtils::ClampLength(value); } @@ -330,8 +330,8 @@ template <> double CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData& conversion_data) const { - double value = ComputeLengthDouble(conversion_data); + const CSSLengthResolver& length_resolver) const { + double value = ComputeLengthDouble(length_resolver); if (RuntimeEnabledFeatures::CSSCalcInfinityAndNaNEnabled()) { return CSSValueClampingUtils::ClampLength(value); } @@ -339,10 +339,10 @@ } double CSSPrimitiveValue::ComputeLengthDouble( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { if (IsCalculated()) - return To<CSSMathFunctionValue>(this)->ComputeLengthPx(conversion_data); - return To<CSSNumericLiteralValue>(this)->ComputeLengthPx(conversion_data); + return To<CSSMathFunctionValue>(this)->ComputeLengthPx(length_resolver); + return To<CSSNumericLiteralValue>(this)->ComputeLengthPx(length_resolver); } bool CSSPrimitiveValue::AccumulateLengthArray(CSSLengthArray& length_array, @@ -422,9 +422,9 @@ } Length CSSPrimitiveValue::ConvertToLength( - const CSSToLengthConversionData& conversion_data) const { + const CSSLengthResolver& length_resolver) const { if (IsLength()) - return ComputeLength<Length>(conversion_data); + return ComputeLength<Length>(length_resolver); if (IsPercentage()) { if (IsNumericLiteralValue() || !To<CSSMathFunctionValue>(this)->AllowsNegativePercentageReference()) { @@ -436,7 +436,7 @@ } } DCHECK(IsCalculated()); - return To<CSSMathFunctionValue>(this)->ConvertToLength(conversion_data); + return To<CSSMathFunctionValue>(this)->ConvertToLength(length_resolver); } double CSSPrimitiveValue::GetDoubleValue() const {
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.h b/third_party/blink/renderer/core/css/css_primitive_value.h index 857f49b..67210a2 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value.h +++ b/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -35,7 +35,7 @@ namespace blink { -class CSSToLengthConversionData; +class CSSLengthResolver; // Dimension calculations are imprecise, often resulting in values of e.g. // 44.99998. We need to go ahead and round if we're really close to the next @@ -322,10 +322,10 @@ // Computes a length in pixels, resolving relative lengths template <typename T> - T ComputeLength(const CSSToLengthConversionData&) const; + T ComputeLength(const CSSLengthResolver&) const; // Converts to a Length (Fixed, Percent or Calculated) - Length ConvertToLength(const CSSToLengthConversionData&) const; + Length ConvertToLength(const CSSLengthResolver&) const; bool IsZero() const; @@ -376,7 +376,7 @@ static UnitType StringToUnitType(const LChar*, unsigned length); static UnitType StringToUnitType(const UChar*, unsigned length); - double ComputeLengthDouble(const CSSToLengthConversionData&) const; + double ComputeLengthDouble(const CSSLengthResolver&) const; }; using CSSLengthArray = CSSPrimitiveValue::CSSLengthArray; @@ -389,26 +389,24 @@ }; template <> -int CSSPrimitiveValue::ComputeLength(const CSSToLengthConversionData&) const; +int CSSPrimitiveValue::ComputeLength(const CSSLengthResolver&) const; template <> -Length CSSPrimitiveValue::ComputeLength(const CSSToLengthConversionData&) const; +Length CSSPrimitiveValue::ComputeLength(const CSSLengthResolver&) const; template <> -unsigned CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData&) const; +unsigned CSSPrimitiveValue::ComputeLength(const CSSLengthResolver&) const; template <> -int16_t CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData&) const; +int16_t CSSPrimitiveValue::ComputeLength(const CSSLengthResolver&) const; template <> CORE_EXPORT float CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData&) const; + const CSSLengthResolver&) const; template <> CORE_EXPORT double CSSPrimitiveValue::ComputeLength( - const CSSToLengthConversionData&) const; + const CSSLengthResolver&) const; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_PRIMITIVE_VALUE_H_
diff --git a/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc b/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc index d2fcee6..3653c70 100644 --- a/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc +++ b/third_party/blink/renderer/core/css/css_to_length_conversion_data.cc
@@ -196,14 +196,15 @@ const ViewportSize& viewport_size, const ContainerSizes& container_sizes, float zoom) - : style_(style), + : CSSLengthResolver( + ClampTo<float>(zoom, std::numeric_limits<float>::denorm_min())), + style_(style), writing_mode_(writing_mode), font_sizes_(font_sizes), viewport_size_(viewport_size), - container_sizes_(container_sizes), - zoom_(ClampTo<float>(zoom, std::numeric_limits<float>::denorm_min())) { - if (zoom_ != font_sizes_.zoom_) - font_sizes_ = font_sizes.CopyWithAdjustedZoom(zoom_); + container_sizes_(container_sizes) { + if (Zoom() != font_sizes_.zoom_) + font_sizes_ = font_sizes.CopyWithAdjustedZoom(Zoom()); } CSSToLengthConversionData::CSSToLengthConversionData( @@ -219,208 +220,11 @@ container_sizes, zoom) {} -double CSSToLengthConversionData::ViewportWidthPercent() const { - // FIXME: Remove style_ from this class. Plumb viewport and rem unit +float CSSToLengthConversionData::EmFontSize() const { + // FIXME: Remove style_ from this class. Plumb viewport and font unit // information through as output parameters on functions involved in length // resolution. if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return viewport_size_.Width() / 100; -} -double CSSToLengthConversionData::ViewportHeightPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return viewport_size_.Height() / 100; -} -double CSSToLengthConversionData::ViewportInlineSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.Width() - : viewport_size_.Height()) / - 100; -} -double CSSToLengthConversionData::ViewportBlockSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.Height() - : viewport_size_.Width()) / - 100; -} -double CSSToLengthConversionData::ViewportMinPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return std::min(viewport_size_.Width(), viewport_size_.Height()) / 100; -} -double CSSToLengthConversionData::ViewportMaxPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return std::max(viewport_size_.Width(), viewport_size_.Height()) / 100; -} - -double CSSToLengthConversionData::SmallViewportWidthPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return viewport_size_.SmallWidth() / 100; -} - -double CSSToLengthConversionData::SmallViewportHeightPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return viewport_size_.SmallHeight() / 100; -} - -double CSSToLengthConversionData::SmallViewportInlineSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.SmallWidth() - : viewport_size_.SmallHeight()) / - 100; -} - -double CSSToLengthConversionData::SmallViewportBlockSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.SmallHeight() - : viewport_size_.SmallWidth()) / - 100; -} - -double CSSToLengthConversionData::SmallViewportMinPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return std::min(viewport_size_.SmallWidth(), viewport_size_.SmallHeight()) / - 100; -} - -double CSSToLengthConversionData::SmallViewportMaxPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return std::max(viewport_size_.SmallWidth(), viewport_size_.SmallHeight()) / - 100; -} - -double CSSToLengthConversionData::LargeViewportWidthPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return viewport_size_.LargeWidth() / 100; -} - -double CSSToLengthConversionData::LargeViewportHeightPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return viewport_size_.LargeHeight() / 100; -} - -double CSSToLengthConversionData::LargeViewportInlineSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.LargeWidth() - : viewport_size_.LargeHeight()) / - 100; -} - -double CSSToLengthConversionData::LargeViewportBlockSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.LargeHeight() - : viewport_size_.LargeWidth()) / - 100; -} - -double CSSToLengthConversionData::LargeViewportMinPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return std::min(viewport_size_.LargeWidth(), viewport_size_.LargeHeight()) / - 100; -} - -double CSSToLengthConversionData::LargeViewportMaxPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); - return std::max(viewport_size_.LargeWidth(), viewport_size_.LargeHeight()) / - 100; -} - -double CSSToLengthConversionData::DynamicViewportWidthPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); - return viewport_size_.DynamicWidth() / 100; -} - -double CSSToLengthConversionData::DynamicViewportHeightPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); - return viewport_size_.DynamicHeight() / 100; -} - -double CSSToLengthConversionData::DynamicViewportInlineSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.DynamicWidth() - : viewport_size_.DynamicHeight()) / - 100; -} - -double CSSToLengthConversionData::DynamicViewportBlockSizePercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); - return (IsHorizontalWritingMode() ? viewport_size_.DynamicHeight() - : viewport_size_.DynamicWidth()) / - 100; -} - -double CSSToLengthConversionData::DynamicViewportMinPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); - return std::min(viewport_size_.DynamicWidth(), - viewport_size_.DynamicHeight()) / - 100; -} - -double CSSToLengthConversionData::DynamicViewportMaxPercent() const { - if (style_) - const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); - return std::max(viewport_size_.DynamicWidth(), - viewport_size_.DynamicHeight()) / - 100; -} - -double CSSToLengthConversionData::ContainerWidthPercent() const { - if (style_) - SetHasContainerRelativeUnits(style_); - if (absl::optional<double> size = container_sizes_.Width()) - return *size / 100; - return SmallViewportWidthPercent(); -} - -double CSSToLengthConversionData::ContainerHeightPercent() const { - if (style_) - SetHasContainerRelativeUnits(style_); - if (absl::optional<double> size = container_sizes_.Height()) - return *size / 100; - return SmallViewportHeightPercent(); -} - -double CSSToLengthConversionData::ContainerInlineSizePercent() const { - return IsHorizontalWritingMode() ? ContainerWidthPercent() - : ContainerHeightPercent(); -} - -double CSSToLengthConversionData::ContainerBlockSizePercent() const { - return IsHorizontalWritingMode() ? ContainerHeightPercent() - : ContainerWidthPercent(); -} - -double CSSToLengthConversionData::ContainerMinPercent() const { - return std::min(ContainerWidthPercent(), ContainerHeightPercent()); -} - -double CSSToLengthConversionData::ContainerMaxPercent() const { - return std::max(ContainerWidthPercent(), ContainerHeightPercent()); -} - -float CSSToLengthConversionData::EmFontSize() const { - if (style_) const_cast<ComputedStyle*>(style_)->SetHasEmUnits(); return font_sizes_.Em(); } @@ -443,151 +247,72 @@ return font_sizes_.Ch(); } +double CSSToLengthConversionData::ViewportWidth() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); + return viewport_size_.LargeWidth(); +} + +double CSSToLengthConversionData::ViewportHeight() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); + return viewport_size_.LargeHeight(); +} + +double CSSToLengthConversionData::SmallViewportWidth() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); + return viewport_size_.SmallWidth(); +} + +double CSSToLengthConversionData::SmallViewportHeight() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); + return viewport_size_.SmallHeight(); +} + +double CSSToLengthConversionData::LargeViewportWidth() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); + return viewport_size_.LargeWidth(); +} + +double CSSToLengthConversionData::LargeViewportHeight() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasStaticViewportUnits(); + return viewport_size_.LargeHeight(); +} + +double CSSToLengthConversionData::DynamicViewportWidth() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); + return viewport_size_.DynamicWidth(); +} + +double CSSToLengthConversionData::DynamicViewportHeight() const { + if (style_) + const_cast<ComputedStyle*>(style_)->SetHasDynamicViewportUnits(); + return viewport_size_.DynamicHeight(); +} + +double CSSToLengthConversionData::ContainerWidth() const { + SetHasContainerRelativeUnits(style_); + return container_sizes_.Width().value_or(SmallViewportWidth()); +} + +double CSSToLengthConversionData::ContainerHeight() const { + SetHasContainerRelativeUnits(style_); + return container_sizes_.Height().value_or(SmallViewportHeight()); +} + +WritingMode CSSToLengthConversionData::GetWritingMode() const { + return writing_mode_; +} + CSSToLengthConversionData::ContainerSizes CSSToLengthConversionData::PreCachedContainerSizesCopy() const { SetHasContainerRelativeUnits(style_); return container_sizes_.PreCachedCopy(); } -double CSSToLengthConversionData::ZoomedComputedPixels( - double value, - CSSPrimitiveValue::UnitType type) const { - // The logic in this function is duplicated in MediaValues::ComputeLength() - // because MediaValues::ComputeLength() needs nearly identical logic, but we - // haven't found a way to make ZoomedComputedPixels() more generic (to solve - // both cases) without hurting performance. - switch (type) { - case CSSPrimitiveValue::UnitType::kPixels: - case CSSPrimitiveValue::UnitType::kUserUnits: - return value * Zoom(); - - case CSSPrimitiveValue::UnitType::kCentimeters: - return value * kCssPixelsPerCentimeter * Zoom(); - - case CSSPrimitiveValue::UnitType::kMillimeters: - return value * kCssPixelsPerMillimeter * Zoom(); - - case CSSPrimitiveValue::UnitType::kQuarterMillimeters: - return value * kCssPixelsPerQuarterMillimeter * Zoom(); - - case CSSPrimitiveValue::UnitType::kInches: - return value * kCssPixelsPerInch * Zoom(); - - case CSSPrimitiveValue::UnitType::kPoints: - return value * kCssPixelsPerPoint * Zoom(); - - case CSSPrimitiveValue::UnitType::kPicas: - return value * kCssPixelsPerPica * Zoom(); - - case CSSPrimitiveValue::UnitType::kViewportWidth: - return value * ViewportWidthPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kViewportHeight: - return value * ViewportHeightPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kViewportInlineSize: - return value * ViewportInlineSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kViewportBlockSize: - return value * ViewportBlockSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kViewportMin: - return value * ViewportMinPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kViewportMax: - return value * ViewportMaxPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kSmallViewportWidth: - return value * SmallViewportWidthPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kSmallViewportHeight: - return value * SmallViewportHeightPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kSmallViewportInlineSize: - return value * SmallViewportInlineSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kSmallViewportBlockSize: - return value * SmallViewportBlockSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kSmallViewportMin: - return value * SmallViewportMinPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kSmallViewportMax: - return value * SmallViewportMaxPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kLargeViewportWidth: - return value * LargeViewportWidthPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kLargeViewportHeight: - return value * LargeViewportHeightPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kLargeViewportInlineSize: - return value * LargeViewportInlineSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kLargeViewportBlockSize: - return value * LargeViewportBlockSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kLargeViewportMin: - return value * LargeViewportMinPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kLargeViewportMax: - return value * LargeViewportMaxPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kDynamicViewportWidth: - return value * DynamicViewportWidthPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kDynamicViewportHeight: - return value * DynamicViewportHeightPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kDynamicViewportInlineSize: - return value * DynamicViewportInlineSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kDynamicViewportBlockSize: - return value * DynamicViewportBlockSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kDynamicViewportMin: - return value * DynamicViewportMinPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kDynamicViewportMax: - return value * DynamicViewportMaxPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kContainerWidth: - return value * ContainerWidthPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kContainerHeight: - return value * ContainerHeightPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kContainerInlineSize: - return value * ContainerInlineSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kContainerBlockSize: - return value * ContainerBlockSizePercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kContainerMin: - return value * ContainerMinPercent() * Zoom(); - - case CSSPrimitiveValue::UnitType::kContainerMax: - return value * ContainerMaxPercent() * Zoom(); - - // Note that functions for font-relative units already account for the - // zoom factor. - case CSSPrimitiveValue::UnitType::kEms: - case CSSPrimitiveValue::UnitType::kQuirkyEms: - return value * EmFontSize(); - - case CSSPrimitiveValue::UnitType::kExs: - return value * ExFontSize(); - - case CSSPrimitiveValue::UnitType::kRems: - return value * RemFontSize(); - - case CSSPrimitiveValue::UnitType::kChs: - return value * ChFontSize(); - - default: - NOTREACHED(); - return 0; - } -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_to_length_conversion_data.h b/third_party/blink/renderer/core/css/css_to_length_conversion_data.h index eb106aa2..b8c6da4 100644 --- a/third_party/blink/renderer/core/css/css_to_length_conversion_data.h +++ b/third_party/blink/renderer/core/css/css_to_length_conversion_data.h
@@ -31,9 +31,9 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TO_LENGTH_CONVERSION_DATA_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_TO_LENGTH_CONVERSION_DATA_H_ -#include <limits> #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_length_resolver.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/layout/geometry/axis.h" #include "third_party/blink/renderer/platform/text/writing_mode.h" @@ -47,7 +47,7 @@ class Font; class Element; -class CORE_EXPORT CSSToLengthConversionData { +class CORE_EXPORT CSSToLengthConversionData : public CSSLengthResolver { STACK_ALLOCATED(); public: @@ -159,7 +159,8 @@ mutable absl::optional<double> cached_height_; }; - CSSToLengthConversionData() : style_(nullptr), zoom_(1) {} + CSSToLengthConversionData() + : CSSLengthResolver(1 /* zoom */), style_(nullptr) {} CSSToLengthConversionData(const ComputedStyle*, WritingMode, const FontSizes&, @@ -172,53 +173,23 @@ const ContainerSizes&, float zoom); - float Zoom() const { return zoom_; } - - float EmFontSize() const; - float RemFontSize() const; - float ExFontSize() const; - float ChFontSize() const; - - // Accessing these marks the style as having viewport units - double ViewportWidthPercent() const; - double ViewportHeightPercent() const; - double ViewportInlineSizePercent() const; - double ViewportBlockSizePercent() const; - double ViewportMinPercent() const; - double ViewportMaxPercent() const; - double SmallViewportWidthPercent() const; - double SmallViewportHeightPercent() const; - double SmallViewportInlineSizePercent() const; - double SmallViewportBlockSizePercent() const; - double SmallViewportMinPercent() const; - double SmallViewportMaxPercent() const; - double LargeViewportWidthPercent() const; - double LargeViewportHeightPercent() const; - double LargeViewportInlineSizePercent() const; - double LargeViewportBlockSizePercent() const; - double LargeViewportMinPercent() const; - double LargeViewportMaxPercent() const; - double DynamicViewportWidthPercent() const; - double DynamicViewportHeightPercent() const; - double DynamicViewportInlineSizePercent() const; - double DynamicViewportBlockSizePercent() const; - double DynamicViewportMinPercent() const; - double DynamicViewportMaxPercent() const; - - // Accessing these marks the style as having container relative units. - double ContainerWidthPercent() const; - double ContainerHeightPercent() const; - double ContainerInlineSizePercent() const; - double ContainerBlockSizePercent() const; - double ContainerMinPercent() const; - double ContainerMaxPercent() const; + float EmFontSize() const override; + float RemFontSize() const override; + float ExFontSize() const override; + float ChFontSize() const override; + double ViewportWidth() const override; + double ViewportHeight() const override; + double SmallViewportWidth() const override; + double SmallViewportHeight() const override; + double LargeViewportWidth() const override; + double LargeViewportHeight() const override; + double DynamicViewportWidth() const override; + double DynamicViewportHeight() const override; + double ContainerWidth() const override; + double ContainerHeight() const override; + WritingMode GetWritingMode() const override; void SetFontSizes(const FontSizes& font_sizes) { font_sizes_ = font_sizes; } - void SetZoom(float zoom) { - DCHECK(std::isfinite(zoom)); - DCHECK_GT(zoom, 0); - zoom_ = zoom; - } // See ContainerSizes::PreCachedCopy. // @@ -235,19 +206,12 @@ return CopyWithAdjustedZoom(1.0f); } - double ZoomedComputedPixels(double value, CSSPrimitiveValue::UnitType) const; - private: - bool IsHorizontalWritingMode() const { - return blink::IsHorizontalWritingMode(writing_mode_); - } - const ComputedStyle* style_; WritingMode writing_mode_; FontSizes font_sizes_; ViewportSize viewport_size_; ContainerSizes container_sizes_; - float zoom_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc index 80fb7de..882aab24 100644 --- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc +++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -564,6 +564,9 @@ bool IsPseudoClassValidWithinHasArgument(CSSParserSelector& selector) { DCHECK_EQ(selector.Match(), CSSSelector::kPseudoClass); switch (selector.GetPseudoType()) { + // TODO(blee@igalia.com) Additional limitations may be added later after + // related issues are resolved in csswg. (e.g. issues/7211, issues/7212) + // Limited nested :has() to avoid increasing :has() invalidation complexity. case CSSSelector::kPseudoHas: return false;
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 95a6ab4a..5e21ca3 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -5591,12 +5591,8 @@ CSSValueList* list = CSSValueList::CreateSpaceSeparated(); - while (true) { - CSSValue* value = ConsumeSingleContainerName(range, context); - if (!value) - break; + while (CSSValue* value = ConsumeSingleContainerName(range, context)) list->Append(*value); - } return list->length() ? list : nullptr; }
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 87c44bf5..ca8a357 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
@@ -2292,7 +2292,6 @@ Vector<AtomicString> StyleBuilderConverter::ConvertContainerName( StyleResolverState& state, const CSSValue& value) { - HashSet<AtomicString> seen; Vector<AtomicString> names; if (auto* ident = DynamicTo<CSSIdentifierValue>(value)) { @@ -2300,12 +2299,8 @@ return names; } - for (const auto& item : To<CSSValueList>(value)) { - const AtomicString& value = To<CSSCustomIdentValue>(item.Get())->Value(); - if (!seen.insert(value).is_new_entry) - continue; - names.push_back(value); - } + for (const auto& item : To<CSSValueList>(value)) + names.push_back(To<CSSCustomIdentValue>(item.Get())->Value()); return names; }
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 0381065b..a633014 100644 --- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc +++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -199,21 +199,29 @@ ApplyCascadeAffecting(resolver); - // Affects the computed value of 'color', hence needs to happen before - // high-priority properties. - LookupAndApply(GetCSSPropertyColorScheme(), resolver); + if (map_.NativeBitset().Has(CSSPropertyID::kColorScheme)) { + // Affects the computed value of 'color', hence needs to happen before + // high-priority properties. + LookupAndApply(GetCSSPropertyColorScheme(), resolver); + } - // Affects the computed value of 'font-size', hence needs to happen before - // high-priority properties. - LookupAndApply(GetCSSPropertyMathDepth(), resolver); + if (map_.NativeBitset().Has(CSSPropertyID::kMathDepth)) { + // Affects the computed value of 'font-size', hence needs to happen before + // high-priority properties. + LookupAndApply(GetCSSPropertyMathDepth(), resolver); + } - // -webkit-mask-image needs to be applied before -webkit-mask-composite, - // otherwise -webkit-mask-composite has no effect. - LookupAndApply(GetCSSPropertyWebkitMaskImage(), resolver); + if (map_.NativeBitset().Has(CSSPropertyID::kWebkitMaskImage)) { + // -webkit-mask-image needs to be applied before -webkit-mask-composite, + // otherwise -webkit-mask-composite has no effect. + LookupAndApply(GetCSSPropertyWebkitMaskImage(), resolver); + } - // Affects the computed value of color when it is inherited and forced-color- - // adjust is set to preserve-parent-color. - LookupAndApply(GetCSSPropertyForcedColorAdjust(), resolver); + if (map_.NativeBitset().Has(CSSPropertyID::kForcedColorAdjust)) { + // Affects the computed value of color when it is inherited and + // forced-color- adjust is set to preserve-parent-color. + LookupAndApply(GetCSSPropertyForcedColorAdjust(), resolver); + } ApplyHighPriority(resolver); @@ -394,8 +402,12 @@ auto direction = state_.Style()->Direction(); auto writing_mode = state_.Style()->GetWritingMode(); - LookupAndApply(GetCSSPropertyDirection(), resolver); - LookupAndApply(GetCSSPropertyWritingMode(), resolver); + if (map_.NativeBitset().Has(CSSPropertyID::kDirection)) { + LookupAndApply(GetCSSPropertyDirection(), resolver); + } + if (map_.NativeBitset().Has(CSSPropertyID::kWritingMode)) { + LookupAndApply(GetCSSPropertyWritingMode(), resolver); + } if (depends_on_cascade_affecting_property_) { if (direction != state_.Style()->Direction() ||
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 37035de9..8e3b874 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8416,13 +8416,6 @@ Document::PendingJavascriptUrl::~PendingJavascriptUrl() = default; -void Document::CheckPartitionedCookiesOriginTrial( - const ResourceResponse& response) { - // if (!cookie_jar_) - // return; - cookie_jar_->CheckPartitionedCookiesOriginTrial(response); -} - template class CORE_TEMPLATE_EXPORT Supplement<Document>; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index c2503dfd..f171d4b 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -205,7 +205,6 @@ class RenderBlockingResourceManager; class ResizeObserver; class ResourceFetcher; -class ResourceResponse; class RootScrollerController; class SVGDocumentExtensions; class SVGUseElement; @@ -1875,9 +1874,6 @@ void WriteIntoTrace(perfetto::TracedValue ctx) const; - // TODO(https://crbug.com/1296161): Delete this function. - void CheckPartitionedCookiesOriginTrial(const ResourceResponse& response); - protected: void ClearXMLVersion() { xml_version_ = String(); }
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index fa3bf343..6b2bc3bf2 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -4300,7 +4300,7 @@ struct Element::AffectedByPseudoStateChange { bool children_or_siblings{true}; - bool ancestors_or_siblings{false}; + bool ancestors_or_siblings{true}; AffectedByPseudoStateChange(CSSSelector::PseudoType pseudo_type, Element& element) { @@ -4332,27 +4332,18 @@ ancestors_or_siblings = element.AncestorsOrSiblingsAffectedByActiveInHas(); break; - - case CSSSelector::kPseudoAnyLink: - case CSSSelector::kPseudoChecked: - case CSSSelector::kPseudoDefault: - case CSSSelector::kPseudoDisabled: - case CSSSelector::kPseudoEnabled: - case CSSSelector::kPseudoIndeterminate: - case CSSSelector::kPseudoInRange: - case CSSSelector::kPseudoInvalid: - case CSSSelector::kPseudoLink: - case CSSSelector::kPseudoOutOfRange: - case CSSSelector::kPseudoOptional: - case CSSSelector::kPseudoPlaceholderShown: - case CSSSelector::kPseudoReadOnly: - case CSSSelector::kPseudoReadWrite: - case CSSSelector::kPseudoRequired: - case CSSSelector::kPseudoTarget: - case CSSSelector::kPseudoValid: - ancestors_or_siblings = true; - break; default: + // Activate :has() invalidation for all allowed pseudo classes. + // + // IsPseudoClassValidWithinHasArgument() in css_selector_parser.cc + // maintains the disallowed pseudo classes inside :has(). + // If a :has() argument contains any of the disallowed pseudo, + // CSSSelectorParser will drop the argument. If the argument is + // dropped, RuleFeatureSet will not maintain the pseudo type for + // :has() invalidation. So, StyleEngine will not do :has() + // invalidation for the disallowed pseudo type changes even if + // the Element::PseudoStateChanged() was called with the disallowed + // pseudo type. break; } }
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 2bdec47..f8b2285f 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -669,9 +669,8 @@ /*record_uma=*/true)) { lazy_load_frame_observer_->DeferLoadUntilNearViewport(request, frame_load_type); - if (IsAdRelated()) { - SetTimeoutToStartAdFrameLoading(); - } + MaybeSetTimeoutToStartAdFrameLoading( + /*is_loading_attr_lazy=*/loading_lazy_set); return true; } @@ -873,9 +872,18 @@ LoadImmediatelyIfLazy(); } -void HTMLFrameOwnerElement::SetTimeoutToStartAdFrameLoading() { - if (!IsAdRelated() || !base::FeatureList::IsEnabled( - features::kAutomaticLazyFrameLoadingToAds)) { +void HTMLFrameOwnerElement::MaybeSetTimeoutToStartAdFrameLoading( + bool is_loading_attr_lazy) { + if (!base::FeatureList::IsEnabled( + features::kAutomaticLazyFrameLoadingToAds)) { + return; + } + if (!IsAdRelated()) { + return; + } + // Even if the frame is ad related, respect the explicit loading="lazy" + // attribute and won't set a timeout if the attribute exists. + if (is_loading_attr_lazy) { return; }
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index 50dc637..6248c41 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -199,7 +199,7 @@ is_swapping_frames_ = is_swapping; } - void SetTimeoutToStartAdFrameLoading(); + void MaybeSetTimeoutToStartAdFrameLoading(bool is_loading_attr_lazy); // This function is used for the call back of idle task. // Trigger loading if the frame is lazy-loaded but not started yet. void LoadIfLazyOnIdle(base::TimeTicks deadline);
diff --git a/third_party/blink/renderer/core/layout/line/root_inline_box.cc b/third_party/blink/renderer/core/layout/line/root_inline_box.cc index c97279f..42b0774a 100644 --- a/third_party/blink/renderer/core/layout/line/root_inline_box.cc +++ b/third_party/blink/renderer/core/layout/line/root_inline_box.cc
@@ -41,8 +41,8 @@ struct SameSizeAsRootInlineBox : public InlineFlowBox { unsigned unsigned_variable; Member<void*> member1; - void* pointers[1]; Member<void*> member2; + void* pointers[1]; LayoutUnit layout_variables[6]; };
diff --git a/third_party/blink/renderer/core/layout/line/root_inline_box.h b/third_party/blink/renderer/core/layout/line/root_inline_box.h index afbc41e..8a256ac6 100644 --- a/third_party/blink/renderer/core/layout/line/root_inline_box.h +++ b/third_party/blink/renderer/core/layout/line/root_inline_box.h
@@ -222,15 +222,15 @@ // Where this line ended. The exact object and the position within that // object are stored so that we can create an InlineIterator beginning just // after the end of this line. - // RootInlineBox cannot have LineLayoutBox itself bacuse it consists of + // RootInlineBox cannot have LineLayoutBox itself because it consists of // WeakPersistent. Use LineBreakObj() to create LineLayoutBox. Member<LayoutObject> line_break_obj_; - scoped_refptr<BidiContext> line_break_context_; - // Floats hanging off the line are pushed into this vector during layout. It // is only good for as long as the line has not been marked dirty. Member<HeapVector<Member<LayoutBox>>> floats_; + scoped_refptr<BidiContext> line_break_context_; + LayoutUnit line_top_; LayoutUnit line_bottom_; LayoutUnit line_top_with_leading_;
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index 9e44eb1..94a6c6c 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -480,6 +480,17 @@ prefers_color_scheme.value()); } + if (ShouldSendClientHint( + ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin, + network::mojom::blink::WebClientHintsType::kPartitionedCookies, + hints_preferences)) { + request.SetHttpHeaderField( + network::GetClientHintToNameMap() + .at(network::mojom::blink::WebClientHintsType::kPartitionedCookies) + .c_str(), + SerializeBoolHeader(true)); + } + if (ShouldSendClientHint(ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin, network::mojom::blink::WebClientHintsType::kSaveData, @@ -697,12 +708,14 @@ base::FeatureList::IsEnabled(features::kAllowClientHintsToThirdParty)) { origin_ok = true; } else { - // For subresource requests, if the parent frame has Sec-CH-UA-Reduced or - // Sec-CH-UA-Full then send the hint in the fetch request, regardless of the - // permissions policy. + // For subresource requests, if the parent frame has Sec-CH-UA-Reduced, + // Sec-CH-UA-Full, or Sec-CH-Partitioned-Cookies, then send the hint in the + // fetch request, regardless of the permissions policy. origin_ok = type == network::mojom::blink::WebClientHintsType::kUAReduced || type == network::mojom::blink::WebClientHintsType::kFullUserAgent || + type == + network::mojom::blink::WebClientHintsType::kPartitionedCookies || (policy && policy->IsFeatureEnabledForOrigin( GetClientHintToPolicyFeatureMap().at(type), resource_origin));
diff --git a/third_party/blink/renderer/core/loader/cookie_jar.cc b/third_party/blink/renderer/core/loader/cookie_jar.cc index ddc73a1..05c4d24 100644 --- a/third_party/blink/renderer/core/loader/cookie_jar.cc +++ b/third_party/blink/renderer/core/loader/cookie_jar.cc
@@ -4,15 +4,9 @@ #include "third_party/blink/renderer/core/loader/cookie_jar.h" -#include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" -#include "net/base/features.h" -#include "net/cookies/parsed_cookie.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" -#include "third_party/blink/public/common/origin_trials/trial_token.h" -#include "third_party/blink/public/common/origin_trials/trial_token_result.h" -#include "third_party/blink/public/common/origin_trials/trial_token_validator.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/frame/local_frame.h" @@ -38,30 +32,6 @@ return c == '\0' || c == '\r' || c == '\n'; } -bool ValidPartitionedCookiesOriginTrial(const ResourceResponse& response) { - // This should never be called if partitioned cookies are disabled. - DCHECK(base::FeatureList::IsEnabled(net::features::kPartitionedCookies)); - - if (!response.HttpHeaderFields().Contains("origin-trial")) - return false; - - blink::TrialTokenValidator validator; - base::Time now(base::Time::Now()); - - GURL url(response.ResponseUrl()); - if (!validator.IsTrialPossibleOnOrigin(url)) - return false; - - url::Origin origin = url::Origin::Create(url); - url::Origin third_party_origins[] = {origin}; - StringUTF8Adaptor token_adaptor(response.HttpHeaderField("origin-trial")); - TrialTokenResult result = validator.ValidateToken( - token_adaptor.AsStringPiece(), origin, third_party_origins, now); - - return result.Status() == blink::OriginTrialTokenStatus::kSuccess && - result.ParsedToken()->feature_name() == "PartitionedCookies"; -} - } // namespace CookieJar::CookieJar(blink::Document* document) @@ -145,19 +115,4 @@ return false; } -void CookieJar::CheckPartitionedCookiesOriginTrial( - const ResourceResponse& response) { - if (!response.HasPartitionedCookie() || - !base::FeatureList::IsEnabled(net::features::kPartitionedCookies)) { - return; - } - if (!ValidPartitionedCookiesOriginTrial(response)) { - base::ElapsedTimer timer; - bool requested = RequestRestrictedCookieManagerIfNeeded(); - LogCookieHistogram("Blink.CookiesEnabledTime.", requested, - timer.Elapsed()); - backend_->ConvertPartitionedCookiesToUnpartitioned(response.ResponseUrl()); - } -} - } // namespace blink
diff --git a/third_party/blink/renderer/core/loader/cookie_jar.h b/third_party/blink/renderer/core/loader/cookie_jar.h index ecaa64d..e91c441 100644 --- a/third_party/blink/renderer/core/loader/cookie_jar.h +++ b/third_party/blink/renderer/core/loader/cookie_jar.h
@@ -8,7 +8,6 @@ #include "services/network/public/mojom/restricted_cookie_manager.mojom-blink.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/loader/fetch/resource_response.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -28,16 +27,6 @@ mojo::PendingRemote<network::mojom::blink::RestrictedCookieManager> cookie_manager); - // This function checks subresource requests for the partitioned cookies - // origin trial. We only consider requests that: - // - have a Set-Cookie header - // - have Partitioned in the cookie line - // If both of these conditions are met, we check if the response contains an - // Origin-Trial header with a valid token. If it does not, we revert that - // URL's partitioned cookies to unpartitioned. - // TODO(https://crbug.com/1296161): Delete this function. - void CheckPartitionedCookiesOriginTrial(const ResourceResponse& response); - private: bool RequestRestrictedCookieManagerIfNeeded();
diff --git a/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc b/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc index dfa347d..5755fb6 100644 --- a/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc +++ b/third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.cc
@@ -72,6 +72,8 @@ WebFeature::kClientHintsUAFull}, {network::mojom::WebClientHintsType::kUAWoW64, WebFeature::kClientHintsUAWoW64}, + {network::mojom::WebClientHintsType::kPartitionedCookies, + WebFeature::kClientHintsPartitionedCookies}, {network::mojom::WebClientHintsType::kSaveData, WebFeature::kClientHintsSaveData}, };
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc index c7d6ed6f..02a7f71e 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -315,8 +315,6 @@ // It is essential that inspector gets resource response BEFORE console. frame->Console().ReportResourceResponseReceived(document_loader_, identifier, response); - - document_->CheckPartitionedCookiesOriginTrial(response); } void ResourceLoadObserverForFrame::DidReceiveData(
diff --git a/third_party/blink/renderer/core/mathml/mathml_element.cc b/third_party/blink/renderer/core/mathml/mathml_element.cc index 8136498..c840950 100644 --- a/third_party/blink/renderer/core/mathml/mathml_element.cc +++ b/third_party/blink/renderer/core/mathml/mathml_element.cc
@@ -6,6 +6,7 @@ #include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.h" #include "third_party/blink/renderer/core/css/css_property_name.h" +#include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" #include "third_party/blink/renderer/core/css_value_keywords.h" #include "third_party/blink/renderer/core/dom/document.h"
diff --git a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 index 6ef895fe..26f3a5c 100644 --- a/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5 +++ b/third_party/blink/renderer/core/permissions_policy/permissions_policy_features.json5
@@ -109,6 +109,11 @@ permissions_policy_name: "ch-ect", }, { + name: "ClientHintPartitionedCookies", + permissions_policy_name: "ch-partitioned-cookies", + depends_on: ["PartitionedCookies"], + }, + { name: "ClientHintPrefersColorScheme", permissions_policy_name: "ch-prefers-color-scheme", },
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc index fc55ee10..53529e3f 100644 --- a/third_party/blink/renderer/core/script/script_loader.cc +++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -25,6 +25,7 @@ #include "third_party/blink/renderer/core/script/script_loader.h" #include "base/feature_list.h" +#include "base/metrics/histogram_functions.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/permissions_policy/permissions_policy.h" @@ -67,7 +68,6 @@ #include "third_party/blink/renderer/core/trustedtypes/trusted_types_util.h" #include "third_party/blink/renderer/platform/bindings/parkable_string.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" -#include "third_party/blink/renderer/platform/instrumentation/histogram.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object_snapshot.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" @@ -1114,6 +1114,12 @@ ScriptSchedulingType scheduling_type) { CHECK(prepared_pending_script_); + // Record usage histograms per script tag. + if (element_->GetDocument().Url().ProtocolIsInHTTPFamily()) { + base::UmaHistogramEnumeration("Blink.Script.SchedulingType", + scheduling_type); + } + PendingScript* pending_script = prepared_pending_script_; prepared_pending_script_ = nullptr; pending_script->SetSchedulingType(scheduling_type);
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index b479f44c..5e6a5da 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -500,6 +500,7 @@ "mediastream/media_stream_constraints_util_video_content_test.cc", "mediastream/media_stream_constraints_util_video_device_test.cc", "mediastream/media_stream_device_observer_test.cc", + "mediastream/media_stream_set_test.cc", "mediastream/media_stream_track_impl_test.cc", "mediastream/media_stream_video_capturer_source_test.cc", "mediastream/media_stream_video_renderer_sink_test.cc",
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 4f0af5a1..7a4d440 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -3886,24 +3886,6 @@ HasAttribute(html_names::kTitleAttr); } -String AXObject::TextFromAriaLabelledby(AXObjectSet& visited, - AXRelatedObjectVector* related_objects, - Vector<String>& ids) const { - HeapVector<Member<Element>> elements; - AriaLabelledbyElementVector(GetElement(), elements, ids); - return TextFromElements(true, visited, elements, related_objects); -} - -String AXObject::TextFromAriaDescribedby(AXRelatedObjectVector* related_objects, - Vector<String>& ids) const { - AXObjectSet visited; - - HeapVector<Member<Element>> elements; - ElementsFromAttribute(GetElement(), elements, - html_names::kAriaDescribedbyAttr, ids); - return TextFromElements(true, visited, elements, related_objects); -} - AccessibilityOrientation AXObject::Orientation() const { // In ARIA 1.1, the default value for aria-orientation changed from // horizontal to undefined.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index c2bc2cd..dd7c420 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -1376,11 +1376,6 @@ static bool IsNameFromAriaAttribute(Element* element); // Return true if the name is from @aria-label / @aria-labelledby / @title. bool IsNameFromAuthorAttribute() const; - String TextFromAriaLabelledby(AXObjectSet& visited, - AXRelatedObjectVector* related_objects, - Vector<String>& ids) const; - String TextFromAriaDescribedby(AXRelatedObjectVector* related_objects, - Vector<String>& ids) const; ax::mojom::blink::Role ButtonRoleType() const;
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn index a107753..19a9a56f 100644 --- a/third_party/blink/renderer/modules/mediastream/BUILD.gn +++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -55,6 +55,8 @@ "media_stream_local_frame_wrapper.h", "media_stream_renderer_factory.cc", "media_stream_renderer_factory.h", + "media_stream_set.cc", + "media_stream_set.h", "media_stream_track.cc", "media_stream_track.h", "media_stream_track_content_hint.h",
diff --git a/third_party/blink/renderer/modules/mediastream/media_devices.cc b/third_party/blink/renderer/modules/mediastream/media_devices.cc index a48737ff..55d888d 100644 --- a/third_party/blink/renderer/modules/mediastream/media_devices.cc +++ b/third_party/blink/renderer/modules/mediastream/media_devices.cc
@@ -69,8 +69,10 @@ on_success_follow_up_(std::move(on_success_follow_up)) {} ~PromiseResolverCallbacks() override = default; - void OnSuccess(MediaStream* stream) override { - DCHECK(stream); + void OnSuccess(const MediaStreamVector& streams) override { + // TODO(crbug.com/1300883): Generalize to multiple streams. + DCHECK_EQ(streams.size(), 1u); + MediaStream* stream = streams[0]; MediaStreamTrack* video_track = nullptr;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_set.cc b/third_party/blink/renderer/modules/mediastream/media_stream_set.cc new file mode 100644 index 0000000..e9b05b29 --- /dev/null +++ b/third_party/blink/renderer/modules/mediastream/media_stream_set.cc
@@ -0,0 +1,61 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/mediastream/media_stream_set.h" + +#include "third_party/blink/renderer/modules/mediastream/media_stream.h" +#include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +MediaStreamSet* MediaStreamSet::Create( + ExecutionContext* context, + const MediaStreamDescriptorVector& stream_descriptors, + MediaStreamSetInitializedCallback callback) { + return MakeGarbageCollected<MediaStreamSet>(context, stream_descriptors, + std::move(callback)); +} + +MediaStreamSet::MediaStreamSet( + ExecutionContext* context, + const MediaStreamDescriptorVector& stream_descriptors, + MediaStreamSetInitializedCallback callback) + : ExecutionContextClient(context), + media_streams_to_initialize_count_(stream_descriptors.size()), + media_streams_initialized_callback_(std::move(callback)) { + if (!stream_descriptors.IsEmpty()) { + for (MediaStreamDescriptor* descriptor : stream_descriptors) { + MediaStream::Create(context, descriptor, /*track=*/nullptr, + WTF::Bind(&MediaStreamSet::OnMediaStreamInitialized, + WrapPersistent(this))); + } + } else { + std::move(media_streams_initialized_callback_) + .Run(initialized_media_streams_); + } +} + +// TODO(crbug.com/1300883): Clean up other streams if one stream capture +// results in an error. This is only required for getDisplayMediaSet. +// Currently existing functionality generates only one stream which is not +// affected by this change. +void MediaStreamSet::OnMediaStreamInitialized( + MediaStream* initialized_media_stream) { + DCHECK_LT(initialized_media_streams_.size(), + media_streams_to_initialize_count_); + initialized_media_streams_.push_back(initialized_media_stream); + if (initialized_media_streams_.size() == media_streams_to_initialize_count_) { + std::move(std::move(media_streams_initialized_callback_)) + .Run(initialized_media_streams_); + } +} + +void MediaStreamSet::Trace(Visitor* visitor) const { + visitor->Trace(initialized_media_streams_); + ExecutionContextClient::Trace(visitor); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_set.h b/third_party/blink/renderer/modules/mediastream/media_stream_set.h new file mode 100644 index 0000000..40ae253 --- /dev/null +++ b/third_party/blink/renderer/modules/mediastream/media_stream_set.h
@@ -0,0 +1,44 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_SET_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_SET_H_ + +#include "third_party/blink/renderer/modules/mediastream/media_stream.h" +#include "third_party/blink/renderer/modules/modules_export.h" +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +using MediaStreamSetInitializedCallback = + base::OnceCallback<void(MediaStreamVector)>; + +class MODULES_EXPORT MediaStreamSet final + : public GarbageCollected<MediaStreamSet>, + public ExecutionContextClient { + public: + static MediaStreamSet* Create( + ExecutionContext* context, + const MediaStreamDescriptorVector& stream_descriptors, + MediaStreamSetInitializedCallback callback); + + MediaStreamSet(ExecutionContext* context, + const MediaStreamDescriptorVector& stream_descriptors, + MediaStreamSetInitializedCallback callback); + virtual ~MediaStreamSet() = default; + + void Trace(Visitor*) const override; + + private: + void OnMediaStreamInitialized(MediaStream*); + + const size_t media_streams_to_initialize_count_; + MediaStreamVector initialized_media_streams_; + MediaStreamSetInitializedCallback media_streams_initialized_callback_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_MEDIA_STREAM_SET_H_
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc new file mode 100644 index 0000000..73fc9934 --- /dev/null +++ b/third_party/blink/renderer/modules/mediastream/media_stream_set_test.cc
@@ -0,0 +1,143 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/mediastream/media_stream_set.h" + +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/gmock_callback_support.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/modules/mediastream/web_platform_media_stream_source.h" +#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" +#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h" +#include "third_party/blink/public/web/web_heap.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" +#include "third_party/blink/renderer/platform/heap/garbage_collected.h" +#include "third_party/blink/renderer/platform/testing/io_task_runner_testing_platform_support.h" + +using testing::_; + +namespace blink { + +namespace { + +class MockLocalMediaStreamVideoSource : public blink::MediaStreamVideoSource { + public: + MockLocalMediaStreamVideoSource() + : blink::MediaStreamVideoSource( + blink::scheduler::GetSingleThreadTaskRunnerForTesting()) {} + + private: + base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() const override { + return weak_factory_.GetWeakPtr(); + } + + void StartSourceImpl(VideoCaptureDeliverFrameCB frame_callback, + EncodedVideoFrameCB encoded_frame_callback) override {} + + void StopSourceImpl() override {} + + base::WeakPtrFactory<MockLocalMediaStreamVideoSource> weak_factory_{this}; +}; + +class MediaStreamSetTest : public testing::Test { + public: + MediaStreamSetTest() = default; + ~MediaStreamSetTest() override { WebHeap::CollectAllGarbageForTesting(); } +}; + +TEST_F(MediaStreamSetTest, SingleMediaStreamInitialized) { + V8TestingScope v8_scope; + Member<MediaStreamSource> test_video_source = + MakeGarbageCollected<MediaStreamSource>( + "test_source_1", MediaStreamSource::StreamType::kTypeVideo, + "test_source_1", false, + std::make_unique<MockLocalMediaStreamVideoSource>()); + MediaStreamSourceVector audio_source_vector = {}; + MediaStreamSourceVector video_source_vector = {test_video_source}; + Member<MediaStreamDescriptor> descriptor = + MakeGarbageCollected<MediaStreamDescriptor>(audio_source_vector, + video_source_vector); + MediaStreamDescriptorVector descriptors = {descriptor}; + base::RunLoop run_loop; + Member<MediaStreamSet> media_stream_set = + MakeGarbageCollected<MediaStreamSet>( + v8_scope.GetExecutionContext(), descriptors, + base::BindLambdaForTesting([&run_loop](MediaStreamVector streams) { + ASSERT_EQ(streams.size(), 1u); + run_loop.Quit(); + })); + DCHECK(media_stream_set); + run_loop.Run(); +} + +TEST_F(MediaStreamSetTest, MultipleMediaStreamsInitialized) { + V8TestingScope v8_scope; + Member<MediaStreamSource> test_video_source = + MakeGarbageCollected<MediaStreamSource>( + "test_source_1", MediaStreamSource::StreamType::kTypeVideo, + "test_source_1", false, + std::make_unique<MockLocalMediaStreamVideoSource>()); + MediaStreamSourceVector audio_source_vector = {}; + MediaStreamSourceVector video_source_vector = {test_video_source}; + Member<MediaStreamDescriptor> descriptor = + MakeGarbageCollected<MediaStreamDescriptor>(audio_source_vector, + video_source_vector); + MediaStreamDescriptorVector descriptors = {descriptor, descriptor, descriptor, + descriptor}; + base::RunLoop run_loop; + Member<MediaStreamSet> media_stream_set = + MakeGarbageCollected<MediaStreamSet>( + v8_scope.GetExecutionContext(), descriptors, + base::BindLambdaForTesting([&run_loop](MediaStreamVector streams) { + ASSERT_EQ(streams.size(), 4u); + run_loop.Quit(); + })); + DCHECK(media_stream_set); + run_loop.Run(); +} + +TEST_F(MediaStreamSetTest, NoTracksInStream) { + V8TestingScope v8_scope; + MediaStreamSourceVector audio_source_vector = {}; + MediaStreamSourceVector video_source_vector = {}; + Member<MediaStreamDescriptor> descriptor = + MakeGarbageCollected<MediaStreamDescriptor>(audio_source_vector, + video_source_vector); + MediaStreamDescriptorVector descriptors = {descriptor}; + base::RunLoop run_loop; + Member<MediaStreamSet> media_stream_set = + MakeGarbageCollected<MediaStreamSet>( + v8_scope.GetExecutionContext(), descriptors, + base::BindLambdaForTesting([&run_loop](MediaStreamVector streams) { + ASSERT_EQ(streams.size(), 1u); + ASSERT_EQ(streams[0]->getVideoTracks().size(), 0u); + ASSERT_EQ(streams[0]->getAudioTracks().size(), 0u); + run_loop.Quit(); + })); + DCHECK(media_stream_set); + run_loop.Run(); +} + +TEST_F(MediaStreamSetTest, NoMediaStreamInitialized) { + V8TestingScope v8_scope; + MediaStreamSourceVector audio_source_vector = {}; + MediaStreamSourceVector video_source_vector = {}; + MediaStreamDescriptorVector descriptors; + base::RunLoop run_loop; + Member<MediaStreamSet> media_stream_set = + MakeGarbageCollected<MediaStreamSet>( + v8_scope.GetExecutionContext(), descriptors, + base::BindLambdaForTesting([&run_loop](MediaStreamVector streams) { + ASSERT_TRUE(streams.IsEmpty()); + run_loop.Quit(); + })); + DCHECK(media_stream_set); + run_loop.Run(); +} + +} // namespace + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc index d33abf89..92c833b 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_track.cc
@@ -19,7 +19,7 @@ public: ~GetOpenDeviceRequestCallbacks() override = default; - void OnSuccess(MediaStream* stream) override {} + void OnSuccess(const MediaStreamVector& streams) override {} void OnError(ScriptWrappable* callback_this_value, const V8MediaStreamError* error) override {} };
diff --git a/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.cc b/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.cc index c5e5f07..82dc307 100644 --- a/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.cc +++ b/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.cc
@@ -17,12 +17,12 @@ return receiver_.BindNewPipeAndPassRemote(); } -void MockMojoMediaStreamDispatcherHost::GenerateStream( +void MockMojoMediaStreamDispatcherHost::GenerateStreams( int32_t request_id, const StreamControls& controls, bool user_gesture, mojom::blink::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback) { + GenerateStreamsCallback callback) { request_id_ = request_id; ++request_stream_counter_; stream_devices_ = blink::mojom::blink::StreamDevices(); @@ -52,9 +52,13 @@ if (do_not_run_cb_) { generate_stream_cb_ = std::move(callback); } else { + // TODO(crbug.com/1300883): Generalize to multiple streams. + blink::mojom::blink::StreamDevicesSetPtr stream_devices_set = + blink::mojom::blink::StreamDevicesSet::New(); + stream_devices_set->stream_devices.emplace_back(stream_devices_.Clone()); std::move(callback).Run(mojom::blink::MediaStreamRequestResult::OK, String("dummy") + String::Number(request_id_), - stream_devices_.Clone(), + std::move(stream_devices_set), /*pan_tilt_zoom_allowed=*/false); } }
diff --git a/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h b/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h index 25b41b1..28139f6 100644 --- a/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h +++ b/third_party/blink/renderer/modules/mediastream/mock_mojo_media_stream_dispatcher_host.h
@@ -30,12 +30,12 @@ mojo::PendingRemote<mojom::blink::MediaStreamDispatcherHost> CreatePendingRemoteAndBind(); - void GenerateStream( + void GenerateStreams( int32_t request_id, const StreamControls& controls, bool user_gesture, mojom::blink::StreamSelectionInfoPtr audio_stream_selection_info_ptr, - GenerateStreamCallback callback) override; + GenerateStreamsCallback callback) override; void CancelRequest(int32_t request_id) override; void StopStreamDevice( const WTF::String& device_id, @@ -84,7 +84,7 @@ base::UnguessableToken session_id_ = base::UnguessableToken::Create(); bool do_not_run_cb_ = false; blink::mojom::blink::StreamDevices stream_devices_; - GenerateStreamCallback generate_stream_cb_; + GenerateStreamsCallback generate_stream_cb_; mojo::Receiver<mojom::blink::MediaStreamDispatcherHost> receiver_{this}; };
diff --git a/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc b/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc index 3938e294..cdce230 100644 --- a/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc +++ b/third_party/blink/renderer/modules/mediastream/navigator_media_stream.cc
@@ -58,9 +58,11 @@ UserMediaRequest::Callbacks::Trace(visitor); } - void OnSuccess(MediaStream* stream) override { - success_callback_->InvokeAndReportException(nullptr, stream); + void OnSuccess(const MediaStreamVector& streams) override { + DCHECK_EQ(streams.size(), 1u); + success_callback_->InvokeAndReportException(nullptr, streams[0]); } + void OnError(ScriptWrappable* callback_this_value, const V8MediaStreamError* error) override { error_callback_->InvokeAndReportException(callback_this_value, error);
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc b/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc index 53e1b73..6efdb3b 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_client_test.cc
@@ -421,9 +421,11 @@ return source; } - void GetUserMediaRequestSucceeded(MediaStreamDescriptor* descriptor, + void GetUserMediaRequestSucceeded(MediaStreamDescriptorVector* descriptors, UserMediaRequest* request_info) override { - last_generated_descriptor_ = descriptor; + // TODO(crbug.com/1300883): Generalize to multiple streams. + DCHECK_EQ(descriptors->size(), 1u); + last_generated_descriptor_ = (*descriptors)[0]; *state_ = kRequestSucceeded; }
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc index 18659c3..9f59e52 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
@@ -14,6 +14,7 @@ #include "base/containers/contains.h" #include "base/location.h" #include "base/logging.h" +#include "base/ranges/algorithm.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" #include "base/task/single_thread_task_runner.h" @@ -24,6 +25,7 @@ #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/mediastream/media_stream_controls.h" #include "third_party/blink/public/common/mediastream/media_stream_request.h" +#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-blink.h" #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_source.h" #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_track.h" #include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h" @@ -385,8 +387,9 @@ video_capture_settings_ = settings; } - void SetDevices(mojom::blink::StreamDevicesPtr stream_devices) { - stream_devices_ = std::move(stream_devices); + void SetDevices(mojom::blink::StreamDevicesSetPtr stream_devices_set) { + stream_devices_set_.stream_devices = + std::move(stream_devices_set->stream_devices); } void AddNativeVideoFormats(const String& device_id, @@ -402,25 +405,37 @@ return &it->value; } - void InitializeWebStream(const String& label, - const MediaStreamComponentVector& audios, - const MediaStreamComponentVector& videos) { - descriptor_ = - MakeGarbageCollected<MediaStreamDescriptor>(label, audios, videos); - } + void InitializeWebStreams( + const String& label, + const MediaStreamsComponentsVector& streams_components) { + DCHECK(!streams_components.IsEmpty()); - const mojom::blink::StreamDevices& devices() const { - return *stream_devices_; + // TODO(crbug.com/1313021): Refactor descriptors to make the assumption of + // at most one audio and video track explicit. + descriptors_ = MakeGarbageCollected<MediaStreamDescriptorVector>(); + for (const MediaStreamComponents* tracks : streams_components) { + descriptors_->push_back(MakeGarbageCollected<MediaStreamDescriptor>( + label, + !tracks->audio_track_ + ? MediaStreamComponentVector() + : MediaStreamComponentVector{tracks->audio_track_}, + !tracks->video_track_ + ? MediaStreamComponentVector() + : MediaStreamComponentVector{tracks->video_track_})); + } } bool CanStartTracks() const { - return video_formats_map_.size() == - (stream_devices_->video_device.has_value() ? 1u : 0u); + return video_formats_map_.size() == count_video_devices(); } - MediaStreamDescriptor* descriptor() { - DCHECK(descriptor_); - return descriptor_; + MediaStreamDescriptorVector* descriptors() { + DCHECK(descriptors_); + return descriptors_; + } + + const mojom::blink::StreamDevicesSet& devices_set() const { + return stream_devices_set_; } StreamControls* stream_controls() { return &stream_controls_; } @@ -436,7 +451,7 @@ void Trace(Visitor* visitor) const { visitor->Trace(request_); - visitor->Trace(descriptor_); + visitor->Trace(descriptors_); visitor->Trace(sources_); } @@ -450,13 +465,15 @@ // that |this| might be deleted when the function returns. void CheckAllTracksStarted(); + size_t count_video_devices() const; + Member<UserMediaRequest> request_; State state_ = State::kNotSentForGeneration; blink::AudioCaptureSettings audio_capture_settings_; bool is_audio_content_capture_ = false; blink::VideoCaptureSettings video_capture_settings_; bool is_video_content_capture_ = false; - Member<MediaStreamDescriptor> descriptor_; + Member<MediaStreamDescriptorVector> descriptors_; StreamControls stream_controls_; ResourcesReady ready_callback_; MediaStreamRequestResult request_result_ = MediaStreamRequestResult::OK; @@ -465,7 +482,7 @@ HeapVector<Member<MediaStreamSource>> sources_; Vector<blink::WebPlatformMediaStreamSource*> sources_waiting_for_callback_; HashMap<String, Vector<media::VideoCaptureFormat>> video_formats_map_; - mojom::blink::StreamDevicesPtr stream_devices_; + mojom::blink::StreamDevicesSet stream_devices_set_; bool pan_tilt_zoom_allowed_ = false; }; @@ -556,6 +573,15 @@ } } +size_t UserMediaProcessor::RequestInfo::count_video_devices() const { + return base::ranges::count_if( + stream_devices_set_.stream_devices.begin(), + stream_devices_set_.stream_devices.end(), + [](const mojom::blink::StreamDevicesPtr& stream_devices) { + return stream_devices->video_device.has_value(); + }); +} + void UserMediaProcessor::RequestInfo::OnAudioSourceStarted( blink::WebPlatformMediaStreamSource* source, MediaStreamRequestResult result, @@ -960,7 +986,7 @@ current_request_info_->request_id())); } else { // The browser replies to this request by invoking OnStreamGenerated(). - GetMediaStreamDispatcherHost()->GenerateStream( + GetMediaStreamDispatcherHost()->GenerateStreams( current_request_info_->request_id(), *current_request_info_->stream_controls(), current_request_info_->is_processing_user_gesture(), @@ -1010,7 +1036,11 @@ NOTREACHED(); } - OnStreamGenerated(request_id, result, response->label, std::move(devices), + mojom::blink::StreamDevicesSetPtr stream_devices_set = + mojom::blink::StreamDevicesSet::New(); + stream_devices_set->stream_devices.emplace_back(std::move(devices)); + OnStreamGenerated(request_id, result, response->label, + std::move(stream_devices_set), response->pan_tilt_zoom_allowed); } @@ -1018,35 +1048,47 @@ int32_t request_id, MediaStreamRequestResult result, const String& label, - mojom::blink::StreamDevicesPtr stream_devices, + mojom::blink::StreamDevicesSetPtr stream_devices_set, bool pan_tilt_zoom_allowed) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); if (result != MediaStreamRequestResult::OK) { + DCHECK(!stream_devices_set); OnStreamGenerationFailed(request_id, result); return; } - DCHECK(stream_devices); + // TODO(crbug.com/1300883): Generalize to multiple streams. + DCHECK(stream_devices_set && stream_devices_set->stream_devices.size() == 1u); if (!IsCurrentRequestInfo(request_id)) { // This can happen if the request is canceled or the frame reloads while // MediaStreamDispatcherHost is processing the request. SendLogMessage(base::StringPrintf( "OnStreamGenerated([request_id=%d]) => (ERROR: invalid request ID)", request_id)); - OnStreamGeneratedForCancelledRequest(*stream_devices); + for (const mojom::blink::StreamDevicesPtr& stream_devices : + stream_devices_set->stream_devices) { + OnStreamGeneratedForCancelledRequest(*stream_devices); + } return; } current_request_info_->set_state(RequestInfo::State::kGenerated); current_request_info_->set_pan_tilt_zoom_allowed(pan_tilt_zoom_allowed); - MaybeLogStreamDevice(request_id, label, stream_devices->audio_device); - MaybeLogStreamDevice(request_id, label, stream_devices->video_device); + for (const mojom::blink::StreamDevicesPtr& stream_devices : + stream_devices_set->stream_devices) { + MaybeLogStreamDevice(request_id, label, stream_devices->audio_device); + MaybeLogStreamDevice(request_id, label, stream_devices->video_device); + } - current_request_info_->SetDevices(stream_devices->Clone()); + current_request_info_->SetDevices(stream_devices_set->Clone()); - if (!stream_devices->video_device.has_value()) { + if (base::ranges::none_of( + stream_devices_set->stream_devices, + [](const mojom::blink::StreamDevicesPtr& stream_devices) { + return stream_devices->video_device.has_value(); + })) { StartTracks(label); return; } @@ -1054,20 +1096,23 @@ if (current_request_info_->is_video_content_capture()) { media::VideoCaptureFormat format = current_request_info_->video_capture_settings().Format(); - if (stream_devices->video_device.has_value()) { - String video_device_id(stream_devices->video_device.value().id.data()); - current_request_info_->AddNativeVideoFormats( - video_device_id, - {media::VideoCaptureFormat(GetScreenSize(), format.frame_rate, - format.pixel_format)}); + for (const mojom::blink::StreamDevicesPtr& stream_devices : + stream_devices_set->stream_devices) { + if (stream_devices->video_device.has_value()) { + String video_device_id(stream_devices->video_device.value().id.data()); + current_request_info_->AddNativeVideoFormats( + video_device_id, + {media::VideoCaptureFormat(GetScreenSize(), format.frame_rate, + format.pixel_format)}); + } } StartTracks(label); return; } - if (stream_devices->video_device.has_value()) { + if (stream_devices_set->stream_devices[0]->video_device.has_value()) { const MediaStreamDevice& video_device = - stream_devices->video_device.value(); + stream_devices_set->stream_devices[0]->video_device.value(); SendLogMessage(base::StringPrintf( "OnStreamGenerated({request_id=%d}, {label=%s}, {device=[id: %s, " "name: %s]}) => (Requesting video device formats)", @@ -1523,99 +1568,94 @@ SendLogMessage(base::StringPrintf("StartTracks({request_id=%d}, {label=%s})", current_request_info_->request_id(), label.Utf8().c_str())); - WTF::Vector<blink::MediaStreamDevice> audio_devices; - if (current_request_info_->devices().audio_device.has_value()) { - audio_devices.push_back( - current_request_info_->devices().audio_device.value()); - } - WTF::Vector<blink::MediaStreamDevice> video_devices; - if (current_request_info_->devices().video_device.has_value()) { - video_devices.push_back( - current_request_info_->devices().video_device.value()); - } - if (auto* media_stream_device_observer = GetMediaStreamDeviceObserver()) { - // TODO(crbug/1313021): audio_devices and video_devices only contain one - // device. Change the AddStream interface to make this explicit. - media_stream_device_observer->AddStream( - blink::WebString(label), ToStdVector(audio_devices), - ToStdVector(video_devices), - WTF::BindRepeating(&UserMediaProcessor::OnDeviceStopped, - WrapWeakPersistent(this)), - WTF::BindRepeating(&UserMediaProcessor::OnDeviceChanged, - WrapWeakPersistent(this)), - WTF::BindRepeating(&UserMediaProcessor::OnDeviceRequestStateChange, - WrapWeakPersistent(this)), - WTF::BindRepeating(&UserMediaProcessor::OnDeviceCaptureHandleChange, - WrapWeakPersistent(this))); - } - HeapVector<Member<MediaStreamComponent>> audio_tracks(audio_devices.size()); - CreateAudioTracks(audio_devices, &audio_tracks); - - HeapVector<Member<MediaStreamComponent>> video_tracks(video_devices.size()); - CreateVideoTracks(video_devices, &video_tracks); + WebMediaStreamDeviceObserver* media_stream_device_observer = + GetMediaStreamDeviceObserver(); + MediaStreamsComponentsVector stream_components_set; + for (const mojom::blink::StreamDevicesPtr& stream_devices : + current_request_info_->devices_set().stream_devices) { + if (media_stream_device_observer) { + // TODO(crbug.com/1300883): Change the interface to use a single optional + // MediaStream instead of a vector. + MediaStreamDevices audio_devices; + if (stream_devices->audio_device) + audio_devices.emplace_back(*stream_devices->audio_device); + MediaStreamDevices video_devices; + if (stream_devices->video_device) + video_devices.emplace_back(*stream_devices->video_device); + // TODO(crbug.com/1327960): Introduce interface to replace the four + // separate callbacks. + media_stream_device_observer->AddStream( + WebString(label), audio_devices, video_devices, + WTF::BindRepeating(&UserMediaProcessor::OnDeviceStopped, + WrapWeakPersistent(this)), + WTF::BindRepeating(&UserMediaProcessor::OnDeviceChanged, + WrapWeakPersistent(this)), + WTF::BindRepeating(&UserMediaProcessor::OnDeviceRequestStateChange, + WrapWeakPersistent(this)), + WTF::BindRepeating(&UserMediaProcessor::OnDeviceCaptureHandleChange, + WrapWeakPersistent(this))); + } + stream_components_set.push_back(MakeGarbageCollected<MediaStreamComponents>( + CreateAudioTrack(stream_devices->audio_device), + CreateVideoTrack(stream_devices->video_device))); + } String blink_id = label; - current_request_info_->InitializeWebStream(blink_id, audio_tracks, - video_tracks); - + current_request_info_->InitializeWebStreams(blink_id, stream_components_set); // Wait for the tracks to be started successfully or to fail. current_request_info_->CallbackOnTracksStarted( WTF::Bind(&UserMediaProcessor::OnCreateNativeTracksCompleted, WrapWeakPersistent(this), label)); } -void UserMediaProcessor::CreateVideoTracks( - const Vector<MediaStreamDevice>& devices, - HeapVector<Member<MediaStreamComponent>>* components) { +MediaStreamComponent* UserMediaProcessor::CreateVideoTrack( + const absl::optional<MediaStreamDevice>& device) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(current_request_info_); - DCHECK_EQ(devices.size(), components->size()); - SendLogMessage(base::StringPrintf("UMP::CreateVideoTracks({request_id=%d})", - current_request_info_->request_id())); - - for (WTF::wtf_size_t i = 0; i < devices.size(); ++i) { - MediaStreamSource* source = InitializeVideoSourceObject(devices[i]); - (*components)[i] = current_request_info_->CreateAndStartVideoTrack(source); - } + if (!device) + return nullptr; + MediaStreamSource* source = InitializeVideoSourceObject(*device); + return current_request_info_->CreateAndStartVideoTrack(source); } -void UserMediaProcessor::CreateAudioTracks( - const Vector<MediaStreamDevice>& devices, - HeapVector<Member<MediaStreamComponent>>* components) { +MediaStreamComponent* UserMediaProcessor::CreateAudioTrack( + const absl::optional<MediaStreamDevice>& device) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(current_request_info_); - DCHECK_EQ(devices.size(), components->size()); - - Vector<MediaStreamDevice> overridden_audio_devices = devices; + if (!device) + return nullptr; + MediaStreamDevice overriden_audio_device = *device; bool render_to_associated_sink = current_request_info_->audio_capture_settings().HasValue() && current_request_info_->audio_capture_settings() .render_to_associated_sink(); + SendLogMessage( - base::StringPrintf("CreateAudioTracks({render_to_associated_sink=%d})", + base::StringPrintf("CreateAudioTrack({render_to_associated_sink=%d})", render_to_associated_sink)); + if (!render_to_associated_sink) { // If the GetUserMedia request did not explicitly set the constraint // kMediaStreamRenderToAssociatedSink, the output device id must // be removed. - for (auto& device : overridden_audio_devices) - device.matched_output_device_id.reset(); + overriden_audio_device.matched_output_device_id.reset(); } - for (WTF::wtf_size_t i = 0; i < overridden_audio_devices.size(); ++i) { - bool is_pending = false; - MediaStreamSource* source = - InitializeAudioSourceObject(overridden_audio_devices[i], &is_pending); - (*components)[i] = MakeGarbageCollected<MediaStreamComponent>( - source, - std::make_unique<MediaStreamAudioTrack>(true /* is_local_track */)); - current_request_info_->StartAudioTrack((*components)[i], is_pending); - // At this point the source has started, and its audio parameters have been - // set. Thus, all audio processing properties are known and can be surfaced - // to |source|. - SurfaceAudioProcessingSettings(source); - } + bool is_pending = false; + MediaStreamSource* source = + InitializeAudioSourceObject(overriden_audio_device, &is_pending); + Member<MediaStreamComponent> component = + MakeGarbageCollected<MediaStreamComponent>( + source, + std::make_unique<MediaStreamAudioTrack>(true /* is_local_track */)); + current_request_info_->StartAudioTrack(component, is_pending); + + // At this point the source has started, and its audio parameters have been + // set. Thus, all audio processing properties are known and can be surfaced + // to |source|. + SurfaceAudioProcessingSettings(source); + return component; } void UserMediaProcessor::OnCreateNativeTracksCompleted( @@ -1628,24 +1668,27 @@ "UMP::OnCreateNativeTracksCompleted({request_id=%d}, {label=%s})", request_info->request_id(), label.Utf8().c_str())); if (result == MediaStreamRequestResult::OK) { - GetUserMediaRequestSucceeded(request_info->descriptor(), + GetUserMediaRequestSucceeded(request_info->descriptors(), request_info->request()); GetMediaStreamDispatcherHost()->OnStreamStarted(label); } else { GetUserMediaRequestFailed(result, constraint_name); - for (auto web_track : request_info->descriptor()->AudioComponents()) { - MediaStreamTrackPlatform* track = - MediaStreamTrackPlatform::GetTrack(WebMediaStreamTrack(web_track)); - if (track) - track->Stop(); - } + for (const MediaStreamDescriptor* descriptor : + *request_info->descriptors()) { + for (auto web_track : descriptor->AudioComponents()) { + MediaStreamTrackPlatform* track = + MediaStreamTrackPlatform::GetTrack(WebMediaStreamTrack(web_track)); + if (track) + track->Stop(); + } - for (auto web_track : request_info->descriptor()->VideoComponents()) { - MediaStreamTrackPlatform* track = - MediaStreamTrackPlatform::GetTrack(WebMediaStreamTrack(web_track)); - if (track) - track->Stop(); + for (auto web_track : descriptor->VideoComponents()) { + MediaStreamTrackPlatform* track = + MediaStreamTrackPlatform::GetTrack(WebMediaStreamTrack(web_track)); + if (track) + track->Stop(); + } } } @@ -1653,7 +1696,7 @@ } void UserMediaProcessor::GetUserMediaRequestSucceeded( - MediaStreamDescriptor* descriptor, + MediaStreamDescriptorVector* descriptors, UserMediaRequest* user_media_request) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK(IsCurrentRequestInfo(user_media_request)); @@ -1669,13 +1712,13 @@ FROM_HERE, WTF::Bind(&UserMediaProcessor::DelayedGetUserMediaRequestSucceeded, WrapWeakPersistent(this), current_request_info_->request_id(), - WrapPersistent(descriptor), + WrapPersistent(descriptors), WrapPersistent(user_media_request))); } void UserMediaProcessor::DelayedGetUserMediaRequestSucceeded( int32_t request_id, - MediaStreamDescriptor* component, + MediaStreamDescriptorVector* components, UserMediaRequest* user_media_request) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); SendLogMessage(base::StringPrintf( @@ -1684,7 +1727,7 @@ MediaStreamRequestResultToString(MediaStreamRequestResult::OK))); blink::LogUserMediaRequestResult(MediaStreamRequestResult::OK); DeleteUserMediaRequest(user_media_request); - user_media_request->Succeed(component); + user_media_request->Succeed(*components); } void UserMediaProcessor::GetUserMediaRequestFailed(
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.h b/third_party/blink/renderer/modules/mediastream/user_media_processor.h index 7ef98a0..e8cbdb8 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_processor.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.h
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/modules/mediastream/user_media_request.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h" +#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h" #include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -114,7 +115,7 @@ // test requesting local media streams. The function notifies WebKit that the // |request| have completed. virtual void GetUserMediaRequestSucceeded( - MediaStreamDescriptor* descriptor, + MediaStreamDescriptorVector* descriptors, UserMediaRequest* user_media_request); virtual void GetUserMediaRequestFailed( blink::mojom::blink::MediaStreamRequestResult result, @@ -154,7 +155,7 @@ void OnStreamGenerated(int32_t request_id, blink::mojom::blink::MediaStreamRequestResult result, const String& label, - blink::mojom::blink::StreamDevicesPtr stream_devices, + mojom::blink::StreamDevicesSetPtr streams_devices_set, bool pan_tilt_zoom_allowed); void GotAllVideoInputFormatsForDevice( @@ -173,7 +174,7 @@ bool IsCurrentRequestInfo(UserMediaRequest* user_media_request) const; void DelayedGetUserMediaRequestSucceeded( int32_t request_id, - MediaStreamDescriptor* descriptor, + MediaStreamDescriptorVector* descriptors, UserMediaRequest* user_media_request); void DelayedGetUserMediaRequestFailed( int32_t request_id, @@ -195,11 +196,11 @@ void StartTracks(const String& label); - void CreateVideoTracks(const Vector<blink::MediaStreamDevice>& devices, - HeapVector<Member<MediaStreamComponent>>* components); + blink::MediaStreamComponent* CreateVideoTrack( + const absl::optional<blink::MediaStreamDevice>& device); - void CreateAudioTracks(const Vector<blink::MediaStreamDevice>& devices, - HeapVector<Member<MediaStreamComponent>>* components); + blink::MediaStreamComponent* CreateAudioTrack( + const absl::optional<blink::MediaStreamDevice>& device); // Callback function triggered when all native versions of the // underlying media sources and tracks have been created and started.
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.cc b/third_party/blink/renderer/modules/mediastream/user_media_request.cc index 2d725776..2e7fd8e 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_request.cc +++ b/third_party/blink/renderer/modules/mediastream/user_media_request.cc
@@ -50,6 +50,7 @@ #include "third_party/blink/renderer/modules/mediastream/media_constraints_impl.h" #include "third_party/blink/renderer/modules/mediastream/media_error_state.h" #include "third_party/blink/renderer/modules/mediastream/media_stream.h" +#include "third_party/blink/renderer/modules/mediastream/media_stream_set.h" #include "third_party/blink/renderer/modules/mediastream/overconstrained_error.h" #include "third_party/blink/renderer/modules/mediastream/transferred_media_stream_track.h" #include "third_party/blink/renderer/modules/mediastream/user_media_controller.h" @@ -501,35 +502,52 @@ controller_->RequestUserMedia(this); } -void UserMediaRequest::Succeed(MediaStreamDescriptor* stream_descriptor) { +void UserMediaRequest::Succeed( + const MediaStreamDescriptorVector& streams_descriptors) { DCHECK(!is_resolved_); + DCHECK(transferred_track_ == nullptr || streams_descriptors.size() == 1u); if (!GetExecutionContext()) return; - MediaStream::Create(GetExecutionContext(), stream_descriptor, - transferred_track_, - WTF::Bind(&UserMediaRequest::OnMediaStreamInitialized, - WrapPersistent(this))); + if (transferred_track_) { + MediaStream::Create(GetExecutionContext(), streams_descriptors[0], + transferred_track_, + WTF::Bind(&UserMediaRequest::OnMediaStreamInitialized, + WrapPersistent(this))); + } else { + MediaStreamSet::Create( + GetExecutionContext(), streams_descriptors, + WTF::Bind(&UserMediaRequest::OnMediaStreamsInitialized, + WrapPersistent(this))); + } } void UserMediaRequest::OnMediaStreamInitialized(MediaStream* stream) { + OnMediaStreamsInitialized({stream}); +} + +void UserMediaRequest::OnMediaStreamsInitialized(MediaStreamVector streams) { DCHECK(!is_resolved_); - MediaStreamTrackVector audio_tracks = stream->getAudioTracks(); - for (const auto& audio_track : audio_tracks) - audio_track->SetConstraints(audio_); + for (const Member<MediaStream>& stream : streams) { + MediaStreamTrackVector audio_tracks = stream->getAudioTracks(); + for (const auto& audio_track : audio_tracks) + audio_track->SetConstraints(audio_); - MediaStreamTrackVector video_tracks = stream->getVideoTracks(); - for (const auto& video_track : video_tracks) - video_track->SetConstraints(video_); + MediaStreamTrackVector video_tracks = stream->getVideoTracks(); + for (const auto& video_track : video_tracks) + video_track->SetConstraints(video_); - RecordIdentifiabilityMetric(surface_, GetExecutionContext(), - IdentifiabilityBenignStringToken(g_empty_string)); - if (auto* window = GetWindow()) { - PeerConnectionTracker::From(*window).TrackGetUserMediaSuccess(this, stream); + RecordIdentifiabilityMetric( + surface_, GetExecutionContext(), + IdentifiabilityBenignStringToken(g_empty_string)); + if (auto* window = GetWindow()) { + PeerConnectionTracker::From(*window).TrackGetUserMediaSuccess(this, + stream); + } } // After this call, the execution context may be invalid. - callbacks_->OnSuccess(stream); + callbacks_->OnSuccess(streams); is_resolved_ = true; }
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_request.h b/third_party/blink/renderer/modules/mediastream/user_media_request.h index 44dcf9b0..8d7d0747 100644 --- a/third_party/blink/renderer/modules/mediastream/user_media_request.h +++ b/third_party/blink/renderer/modules/mediastream/user_media_request.h
@@ -34,6 +34,7 @@ #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/mediastream/media_stream.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/mediastream/media_constraints.h" #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h" @@ -43,9 +44,7 @@ class LocalDOMWindow; class MediaErrorState; -class MediaStream; class MediaStreamConstraints; -class MediaStreamDescriptor; class ScriptWrappable; class TransferredMediaStreamTrack; class UserMediaController; @@ -77,7 +76,7 @@ public: virtual ~Callbacks() = default; - virtual void OnSuccess(MediaStream*) = 0; + virtual void OnSuccess(const MediaStreamVector&) = 0; virtual void OnError(ScriptWrappable* callback_this_value, const V8MediaStreamError* error) = 0; @@ -113,8 +112,9 @@ void Start(); - void Succeed(MediaStreamDescriptor*); + void Succeed(const MediaStreamDescriptorVector& streams); void OnMediaStreamInitialized(MediaStream* stream); + void OnMediaStreamsInitialized(MediaStreamVector streams); void FailConstraint(const String& constraint_name, const String& message); void Fail(Error name, const String& message);
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc index 133c9533..30e5b6b 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -1137,7 +1137,7 @@ void PeerConnectionTracker::TrackGetUserMediaSuccess( UserMediaRequest* user_media_request, - MediaStream* stream) { + const MediaStream* stream) { DCHECK_CALLED_ON_VALID_THREAD(main_thread_); // Serialize audio and video track information (id and label) or an
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h index 29ea5d1..477dfc3 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
@@ -242,7 +242,7 @@ virtual void TrackGetUserMedia(UserMediaRequest* user_media_request); // Sends an update when getUserMedia resolveѕ with a stream. virtual void TrackGetUserMediaSuccess(UserMediaRequest* user_media_request, - MediaStream* stream); + const MediaStream* stream); // Sends an update when getUserMedia fails with an error. virtual void TrackGetUserMediaFailure(UserMediaRequest* user_media_request, const String& error,
diff --git a/third_party/blink/renderer/platform/exported/web_url_response.cc b/third_party/blink/renderer/platform/exported/web_url_response.cc index d390aad..67fb80e4 100644 --- a/third_party/blink/renderer/platform/exported/web_url_response.cc +++ b/third_party/blink/renderer/platform/exported/web_url_response.cc
@@ -490,8 +490,4 @@ WebURLResponse::WebURLResponse(ResourceResponse& r) : resource_response_(&r) {} -void WebURLResponse::SetHasPartitionedCookie(bool has_partitioned_cookie) { - resource_response_->SetHasPartitionedCookie(has_partitioned_cookie); -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc index 4e1dd6f3..4898084 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -1460,7 +1460,7 @@ const bool can_use_lcd_text = GetSkImageInfo().alphaType() == kOpaque_SkAlphaType; - ri->BeginRasterCHROMIUM(background_color.toSkColor(), needs_clear, + ri->BeginRasterCHROMIUM(background_color, needs_clear, /*msaa_sample_count=*/oopr_uses_dmsaa_ ? 1 : 0, oopr_uses_dmsaa_ ? gpu::raster::MsaaMode::kDMSAA : gpu::raster::MsaaMode::kNoMSAA,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_response.h b/third_party/blink/renderer/platform/loader/fetch/resource_response.h index 6042a852..ceccaa9ac 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_response.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_response.h
@@ -431,11 +431,6 @@ request_include_credentials_ = request_include_credentials; } - bool HasPartitionedCookie() const { return has_partitioned_cookie_; } - void SetHasPartitionedCookie(bool has_partitioned_cookie) { - has_partitioned_cookie_ = has_partitioned_cookie; - } - private: void UpdateHeaderParsedState(const AtomicString& name); @@ -630,10 +625,6 @@ absl::optional<net::AuthChallengeInfo> auth_challenge_info_; bool emitted_extra_info_ = false; - - // See URLResponseHead.has_partitioned_cookie. - // TODO(https://crbug.com/1296161): Delete this field. - bool has_partitioned_cookie_; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc index b960c7a8..2af5816 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
@@ -29,7 +29,6 @@ #include "base/time/time.h" #include "build/build_config.h" #include "mojo/public/cpp/bindings/pending_remote.h" -#include "net/base/features.h" #include "net/base/filename_util.h" #include "net/base/host_port_pair.h" #include "net/base/ip_endpoint.h" @@ -40,7 +39,6 @@ #include "net/cert/ct_sct_to_string.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" -#include "net/cookies/parsed_cookie.h" #include "net/http/http_request_headers.h" #include "net/http/http_response_headers.h" #include "net/ssl/ssl_cipher_suite_names.h" @@ -791,8 +789,6 @@ response->AddHttpHeaderField(WebString::FromLatin1(name), WebString::FromLatin1(value)); } - - response->SetHasPartitionedCookie(head.has_partitioned_cookie); } // static
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_component.cc b/third_party/blink/renderer/platform/mediastream/media_stream_component.cc index fe99dafc..d149a99c 100644 --- a/third_party/blink/renderer/platform/mediastream/media_stream_component.cc +++ b/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
@@ -197,4 +197,15 @@ visitor->Trace(source_); } +MediaStreamComponents::MediaStreamComponents(MediaStreamComponent* audio_track, + MediaStreamComponent* video_track) + : audio_track_(audio_track), video_track_(video_track) { + DCHECK(audio_track_ || video_track_); +} + +void MediaStreamComponents::Trace(Visitor* visitor) const { + visitor->Trace(audio_track_); + visitor->Trace(video_track_); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_component.h b/third_party/blink/renderer/platform/mediastream/media_stream_component.h index bbd3f54d..572b972a 100644 --- a/third_party/blink/renderer/platform/mediastream/media_stream_component.h +++ b/third_party/blink/renderer/platform/mediastream/media_stream_component.h
@@ -168,7 +168,21 @@ WebLocalFrame* creation_frame_ = nullptr; }; -typedef HeapVector<Member<MediaStreamComponent>> MediaStreamComponentVector; +class PLATFORM_EXPORT MediaStreamComponents final + : public GarbageCollected<MediaStreamComponents> { + public: + // At least one of audio_track / video_track must be non-null. + MediaStreamComponents(MediaStreamComponent* audio_track, + MediaStreamComponent* video_track); + + void Trace(Visitor*) const; + + Member<MediaStreamComponent> audio_track_; + Member<MediaStreamComponent> video_track_; +}; + +using MediaStreamComponentVector = HeapVector<Member<MediaStreamComponent>>; +using MediaStreamsComponentsVector = HeapVector<Member<MediaStreamComponents>>; } // namespace blink
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index f047a35..7c9bb3a 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -4634,6 +4634,10 @@ # Sheriff 2019-03-05 crbug.com/938200 http/tests/devtools/network/network-blocked-reason.js [ Pass Timeout ] +# Skip before rebaselining expectations +crbug.com/v8/12808 external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html [ Skip ] +crbug.com/v8/12808 virtual/v8-off-thread-finalization/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache.html [ Skip ] + # Caused a revert of a good change. crbug.com/931533 media/video-played-collapse.html [ Failure Pass ] @@ -6679,6 +6683,10 @@ crbug.com/1313894 [ Mac10.14 ] rootscroller/root-scroller-paint-order.html [ Failure Pass ] crbug.com/1314130 [ Mac ] fast/events/touch/gesture/touch-gesture-scroll-listbox.html [ Failure Pass ] +# Temporarily disabled to unblock https://crrev.com/c/3666176 +crbug.com/1329040 http/tests/devtools/sources/snippet-overrides.js [ Timeout Pass ] +crbug.com/1329040 http/tests/devtools/sources/debugger/network-uisourcecode-provider.js [ Failure Pass ] + # Sheriff 2022-04-07 crbug.com/1314314 virtual/percent-based-scrolling/fast/scrolling/scrollbars/mouse-autoscrolling-on-deleted-scrollbar.html [ Skip ] crbug.com/1314323 [ Win ] virtual/compositor-threaded-percent-based-scrolling/fast/scrolling/wheel-scrolling-over-custom-scrollbar.html [ Skip ] @@ -6802,9 +6810,6 @@ # Disabled to allow a DevTools roll crbug.com/1325751 http/tests/devtools/extensions/extensions-api.js [ Failure Pass ] -crbug.com/1328014 http/tests/devtools/sources/debugger-ui/debugger-expand-scope.js [ Failure Pass ] -crbug.com/1328014 http/tests/devtools/sources/debugger/debugger-es6-harmony-scopes.js [ Failure Pass ] -crbug.com/1328014 http/tests/devtools/sources/debugger/debugger-scope-minified-variables.js [ Failure Pass ] # Throttling a hidden-cross origin frame may stall animations. crbug.com/1323246 external/wpt/web-animations/timing-model/timelines/sibling-iframe-timeline.html [ Failure Pass ] @@ -6819,6 +6824,3 @@ # Sheriff 2022-05-20 crbug.com/1291841 external/wpt/scroll-to-text-fragment/scroll-to-text-fragment-security.sub.html [ Pass Timeout ] crbug.com/1327764 inspector-protocol/overlay/overlay-persistent-overlays.js [ Failure Pass ] - -# Disabled to land a change -crbug.com/1297439 http/tests/devtools/tracing/timeline-js/timeline-stack-trace.js [ Skip ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-cue-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-cue-ref.html new file mode 100644 index 0000000..48b2622 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-cue-ref.html
@@ -0,0 +1,23 @@ +<!doctype html> +<html class="reftest-wait"> +<head> + <title>CSS Test Reference</title> + <script src="/common/reftest-wait.js"></script> + <style> + video { + contain: size; + width: 200px; + height: 200px; + } + video::cue { background-color: green } + video::cue(b) { color: lime } + </style> +</head> +<body> + <video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();"> + <track default src="support/test.vtt"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + </video> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-cue.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-cue.html new file mode 100644 index 0000000..f53d161d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-cue.html
@@ -0,0 +1,27 @@ +<!doctype html> +<html class="reftest-wait"> +<head> + <title>CSS Container Queries Test: Container for pseudo elements</title> + <link rel="help" href="https://drafts.csswg.org/css-contain-3/#container-queries"> + <link rel="match" href="container-for-cue-ref.html"> + <script src="/common/reftest-wait.js"></script> + <style> + video { + container-type: size; + width: 200px; + height: 200px; + } + @container (width = 200px) { + video::cue { background-color: green } + video::cue(b) { color: lime } + } + </style> +</head> +<body> + <video autoplay onplaying="this.onplaying = null; this.pause(); takeScreenshot();"> + <source src="/media/white.webm" type="video/webm"> + <source src="/media/white.mp4" type="video/mp4"> + <track default src="support/test.vtt"> + </video> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-computed.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-computed.html index 94e1737..f58d547 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-name-computed.html
@@ -16,8 +16,8 @@ test_computed_value('container-name', 'FoO'); test_computed_value('container-name', 'foo bar'); test_computed_value('container-name', 'bar foo'); -test_computed_value('container-name', 'foo foo bar', 'foo bar'); -test_computed_value('container-name', 'foo bar foo', 'foo bar'); -test_computed_value('container-name', 'bar foo foo', 'bar foo'); +test_computed_value('container-name', 'foo foo bar'); +test_computed_value('container-name', 'foo bar foo'); +test_computed_value('container-name', 'bar foo foo'); test_computed_value('container-name', '\\!escaped'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/test.vtt b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/test.vtt new file mode 100644 index 0000000..ffd1d4c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/support/test.vtt
@@ -0,0 +1,4 @@ +WEBVTT + +00:00:00.000 --> 00:00:10.000 +Sub-<b>title</b>
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache-expected.txt index 85cfb60..63bda116 100644 --- a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache-expected.txt +++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/v8-code-cache-expected.txt
@@ -7,7 +7,7 @@ PASS module: Run #1 PASS module: Run #2 PASS module: Run #3 -PASS module: Run #4 +FAIL module: Run #4 promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/imports-a.js" FAIL module: Run #5 promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch dynamically imported module: http://web-platform.test:8001/html/semantics/scripting-1/the-script-element/module/imports-a.js" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/platform/generic/http/tests/devtools/tracing/timeline-js/timeline-stack-trace-expected.txt b/third_party/blink/web_tests/platform/generic/http/tests/devtools/tracing/timeline-js/timeline-stack-trace-expected.txt index 813fd5c..11e15bbc 100644 --- a/third_party/blink/web_tests/platform/generic/http/tests/devtools/tracing/timeline-js/timeline-stack-trace-expected.txt +++ b/third_party/blink/web_tests/platform/generic/http/tests/devtools/tracing/timeline-js/timeline-stack-trace-expected.txt
@@ -1,7 +1,7 @@ Test that checks whether the returned stackTrace of a timeline correctly formats the scriptId as a string. Stack trace for: TimerInstall -[{"columnNumber":19,"functionName":"performActions","lineNumber":31,"scriptId":"6","url":"performActions.js"}] +[{"columnNumber":19,"functionName":"performActions","lineNumber":31,"scriptId":"7","url":"performActions.js"}] Stack trace for: TimerRemove -[{"columnNumber":7,"functionName":"intervalTimerWork","lineNumber":38,"scriptId":"6","url":"performActions.js"}] +[{"columnNumber":7,"functionName":"intervalTimerWork","lineNumber":38,"scriptId":"7","url":"performActions.js"}]
diff --git a/third_party/blink/web_tests/platform/generic/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/platform/generic/webexposed/feature-policy-features-expected.txt index 8c63591..4c2b438 100644 --- a/third_party/blink/web_tests/platform/generic/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/platform/generic/webexposed/feature-policy-features-expected.txt
@@ -10,6 +10,7 @@ ch-downlink ch-dpr ch-ect +ch-partitioned-cookies ch-prefers-color-scheme ch-rtt ch-save-data
diff --git a/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/frame-lazyload-no-timeout.html b/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/frame-lazyload-no-timeout.html new file mode 100644 index 0000000..6c97882 --- /dev/null +++ b/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/frame-lazyload-no-timeout.html
@@ -0,0 +1,49 @@ +<!DOCTYPE html> + +<title>Makes sure that the ad iframe with loading="lazy" loading are not triggered</title> +<script src="../../../../../resources/testharness.js"></script> +<script src="../../../../../resources/testharnessreport.js"></script> +<script src="../../../../../http/tests/resources/get-host-info.js"></script> +<script src="./resources/lazyload-helper.js"></script> + +<body> + <div id="atf_div"></div> + <div style="height:1000vh;"></div> + <div id="btf_div"></div> + + <script> + window.addEventListener('DOMContentLoaded', () => { + promise_test(async t => { + const btf = document.querySelector('#btf_div'); + appendAdFrame('btf', btf, 'lazy'); + + const timeoutMs = 1000; + + let result = isElementLoaded('btf'); + await new Promise(resolve => { + t.step_timeout(() => { + result = isElementLoaded('btf') + resolve(); + }, timeoutMs); + }); + assert_false(result, "iframe is not loaded until the timeout"); + + await waitUntilIdle(); + await new Promise(resolve => { + t.step_timeout(() => { + result = isElementLoaded('btf') + resolve(); + }, timeoutMs); + }); + assert_false(result, "iframe is not loaded after the timeout and became idle"); + + // Then scroll to below the fold. + btf.scrollIntoView(); + + // If viewport is close to the frame, then start loading. + result = await waitForElementLoad("btf"); + assert_true(result, "iframe below the fold is loaded when close to the element"); + }, "Timeout doen't trigger if loading=lazy is specified"); + }) + </script> +</body>
diff --git a/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/resources/lazyload-helper.js b/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/resources/lazyload-helper.js index 785ce1f..02204838 100644 --- a/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/resources/lazyload-helper.js +++ b/third_party/blink/web_tests/virtual/automatic-lazy-frame-loading-ads/http/tests/subresource_filter/resources/lazyload-helper.js
@@ -4,11 +4,14 @@ }); }; const loaded_ids = []; -const appendAdFrame = (id, elm) => { +const appendAdFrame = (id, elm, loadingAttr) => { const frame = document.createElement('iframe'); frame.width = 300; frame.height = 300; frame.id = id; + if (loadingAttr) { + frame.loading = loadingAttr; + } elm.appendChild(frame); internals.setIsAdSubframe(frame);
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 924c40c17..92cd647 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-12-1-6-ga4c4566b6 -Revision: a4c4566b6d51a0bd60133e1e1a7fcc19e8fcba9e +Version: VER-2-12-1-8-g7838c78f5 +Revision: 7838c78f53f206ac5b8e9cefde548aa81cb00cf4 CPEPrefix: cpe:/a:freetype:freetype:2.11.1 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses"
diff --git a/third_party/polymer/v3_0/BUILD.gn b/third_party/polymer/v3_0/BUILD.gn index 3fbb6a52..b1f40ee 100644 --- a/third_party/polymer/v3_0/BUILD.gn +++ b/third_party/polymer/v3_0/BUILD.gn
@@ -18,7 +18,6 @@ "iron-collapse/iron-collapse.js", "iron-fit-behavior/iron-fit-behavior.js", "iron-flex-layout/iron-flex-layout-classes.js", - "iron-flex-layout/iron-flex-layout.js", "iron-icon/iron-icon.js", "iron-iconset-svg/iron-iconset-svg.js", "iron-list/iron-list.js", @@ -82,7 +81,6 @@ "components-chromium/iron-collapse/iron-collapse.d.ts", "components-chromium/iron-fit-behavior/iron-fit-behavior.d.ts", "components-chromium/iron-flex-layout/iron-flex-layout-classes.d.ts", - "components-chromium/iron-flex-layout/iron-flex-layout.d.ts", "components-chromium/iron-icon/iron-icon.d.ts", "components-chromium/iron-iconset-svg/iron-iconset-svg.d.ts", "components-chromium/iron-list/iron-list.d.ts",
diff --git a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn index 8b6c2f6a..a50af9bb 100644 --- a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn +++ b/third_party/polymer/v3_0/components-chromium/iron-flex-layout/BUILD.gn
@@ -6,10 +6,6 @@ import("//third_party/closure_compiler/compile_js.gni") -js_library("iron-flex-layout") { - deps = [ "../polymer:polymer_bundled" ] -} - js_library("iron-flex-layout-classes") { deps = [ "../polymer:polymer_bundled" ] }
diff --git a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/iron-flex-layout.d.ts b/third_party/polymer/v3_0/components-chromium/iron-flex-layout/iron-flex-layout.d.ts deleted file mode 100644 index 1eae95f..0000000 --- a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/iron-flex-layout.d.ts +++ /dev/null
@@ -1,11 +0,0 @@ -/** - * DO NOT EDIT - * - * This file was automatically generated by - * https://github.com/Polymer/tools/tree/master/packages/gen-typescript-declarations - * - * To modify these typings, edit the source file(s): - * iron-flex-layout.js - */ - -import {html} from '../polymer/lib/utils/html-tag.js';
diff --git a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/iron-flex-layout.js b/third_party/polymer/v3_0/components-chromium/iron-flex-layout/iron-flex-layout.js deleted file mode 100644 index 37ca84e..0000000 --- a/third_party/polymer/v3_0/components-chromium/iron-flex-layout/iron-flex-layout.js +++ /dev/null
@@ -1,347 +0,0 @@ -/** -@license -Copyright (c) 2015 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at -http://polymer.github.io/LICENSE.txt The complete set of authors may be found at -http://polymer.github.io/AUTHORS.txt The complete set of contributors may be -found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as -part of the polymer project is also subject to an additional IP rights grant -found at http://polymer.github.io/PATENTS.txt -*/ -import '../polymer/polymer_bundled.min.js'; -import {html} from '../polymer/polymer_bundled.min.js'; - -/** -The `<iron-flex-layout>` component provides simple ways to use -[CSS flexible box -layout](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes), -also known as flexbox. Note that this is an old element, that was written -before all modern browsers had non-prefixed flex styles. As such, nowadays you -don't really need to use this element anymore, and can use CSS flex styles -directly in your code. - -This component provides two different ways to use flexbox: - -1. [Layout -classes](https://github.com/PolymerElements/iron-flex-layout/tree/master/iron-flex-layout-classes.html). -The layout class stylesheet provides a simple set of class-based flexbox rules, -that let you specify layout properties directly in markup. You must include this -file in every element that needs to use them. - - Sample use: - - ``` - <custom-element-demo> - <template> - <script src="../webcomponentsjs/webcomponents-lite.js"></script> - <next-code-block></next-code-block> - </template> - </custom-element-demo> - ``` - - ```js - import {html} from '../polymer/polymer_bundled.min.js'; - import '../iron-flex-layout/iron-flex-layout-classes.js'; - - const template = html` - <style is="custom-style" include="iron-flex iron-flex-alignment"></style> - <style> - .test { width: 100px; } - </style> - <div class="layout horizontal center-center"> - <div class="test">horizontal layout center alignment</div> - </div> - `; - document.body.appendChild(template.content); - ``` - -2. [Custom CSS -mixins](https://github.com/PolymerElements/iron-flex-layout/blob/master/iron-flex-layout.html). -The mixin stylesheet includes custom CSS mixins that can be applied inside a CSS -rule using the `@apply` function. - -Please note that the old [/deep/ layout -classes](https://github.com/PolymerElements/iron-flex-layout/tree/master/classes) -are deprecated, and should not be used. To continue using layout properties -directly in markup, please switch to using the new `dom-module`-based -[layout -classes](https://github.com/PolymerElements/iron-flex-layout/tree/master/iron-flex-layout-classes.html). -Please note that the new version does not use `/deep/`, and therefore requires -you to import the `dom-modules` in every element that needs to use them. - -@group Iron Elements -@pseudoElement iron-flex-layout -@demo demo/index.html -*/ -const template = html` -<custom-style> - <style is="custom-style"> - [hidden] { - display: none !important; - } - </style> -</custom-style> -<custom-style> - <style is="custom-style"> - html { - - --layout: { - display: flex; - }; - - --layout-inline: { - display: inline-flex; - }; - - --layout-horizontal: { - @apply --layout; - - flex-direction: row; - }; - - --layout-horizontal-reverse: { - @apply --layout; - - flex-direction: row-reverse; - }; - - --layout-vertical: { - @apply --layout; - - flex-direction: column; - }; - - --layout-vertical-reverse: { - @apply --layout; - - flex-direction: column-reverse; - }; - - --layout-wrap: { - flex-wrap: wrap; - }; - - --layout-wrap-reverse: { - flex-wrap: wrap-reverse; - }; - - --layout-flex-auto: { - flex: 1 1 auto; - }; - - --layout-flex-none: { - flex: none; - }; - - --layout-flex: { - flex: 1; - flex-basis: 0.000000001px; - }; - - --layout-flex-2: { - flex: 2; - }; - - --layout-flex-3: { - flex: 3; - }; - - --layout-flex-4: { - flex: 4; - }; - - --layout-flex-5: { - flex: 5; - }; - - --layout-flex-6: { - flex: 6; - }; - - --layout-flex-7: { - flex: 7; - }; - - --layout-flex-8: { - flex: 8; - }; - - --layout-flex-9: { - flex: 9; - }; - - --layout-flex-10: { - flex: 10; - }; - - --layout-flex-11: { - flex: 11; - }; - - --layout-flex-12: { - flex: 12; - }; - - /* alignment in cross axis */ - - --layout-start: { - align-items: flex-start; - }; - - --layout-center: { - align-items: center; - }; - - --layout-end: { - align-items: flex-end; - }; - - --layout-baseline: { - align-items: baseline; - }; - - /* alignment in main axis */ - - --layout-start-justified: { - justify-content: flex-start; - }; - - --layout-center-justified: { - justify-content: center; - }; - - --layout-end-justified: { - justify-content: flex-end; - }; - - --layout-around-justified: { - justify-content: space-around; - }; - - --layout-justified: { - justify-content: space-between; - }; - - --layout-center-center: { - @apply --layout-center; - @apply --layout-center-justified; - }; - - /* self alignment */ - - --layout-self-start: { - align-self: flex-start; - }; - - --layout-self-center: { - align-self: center; - }; - - --layout-self-end: { - align-self: flex-end; - }; - - --layout-self-stretch: { - align-self: stretch; - }; - - --layout-self-baseline: { - align-self: baseline; - }; - - /* multi-line alignment in main axis */ - - --layout-start-aligned: { - align-content: flex-start; - }; - - --layout-end-aligned: { - align-content: flex-end; - }; - - --layout-center-aligned: { - align-content: center; - }; - - --layout-between-aligned: { - align-content: space-between; - }; - - --layout-around-aligned: { - align-content: space-around; - }; - - /******************************* - Other Layout - *******************************/ - - --layout-block: { - display: block; - }; - - --layout-invisible: { - visibility: hidden !important; - }; - - --layout-relative: { - position: relative; - }; - - --layout-fit: { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - }; - - --layout-scroll: { - -webkit-overflow-scrolling: touch; - overflow: auto; - }; - - --layout-fullbleed: { - margin: 0; - height: 100vh; - }; - - /* fixed position */ - - --layout-fixed-top: { - position: fixed; - top: 0; - left: 0; - right: 0; - }; - - --layout-fixed-right: { - position: fixed; - top: 0; - right: 0; - bottom: 0; - }; - - --layout-fixed-bottom: { - position: fixed; - right: 0; - bottom: 0; - left: 0; - }; - - --layout-fixed-left: { - position: fixed; - top: 0; - bottom: 0; - left: 0; - }; - - } - </style> -</custom-style>`; - -template.setAttribute('style', 'display: none;'); -document.head.appendChild(template.content); - -var style = document.createElement('style'); -style.textContent = '[hidden] { display: none !important; }'; -document.head.appendChild(style);
diff --git a/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn b/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn index 76749c0..d8986bf 100644 --- a/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn +++ b/third_party/polymer/v3_0/components-chromium/iron-icon/BUILD.gn
@@ -8,7 +8,6 @@ js_library("iron-icon") { deps = [ - "../iron-flex-layout:iron-flex-layout", "../iron-meta:iron-meta", "../polymer:polymer_bundled", ]
diff --git a/third_party/polymer/v3_0/components-chromium/iron-icon/iron-icon.js b/third_party/polymer/v3_0/components-chromium/iron-icon/iron-icon.js index 35835d2b..2a647f1 100644 --- a/third_party/polymer/v3_0/components-chromium/iron-icon/iron-icon.js +++ b/third_party/polymer/v3_0/components-chromium/iron-icon/iron-icon.js
@@ -8,8 +8,6 @@ part of the polymer project is also subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt */ -import '../iron-flex-layout/iron-flex-layout.js'; - import {IronMeta} from '../iron-meta/iron-meta.js'; import {Polymer} from '../polymer/polymer_bundled.min.js'; import {dom} from '../polymer/polymer_bundled.min.js'; @@ -89,8 +87,9 @@ _template: html` <style> :host { - @apply --layout-inline; - @apply --layout-center-center; + align-items: center; + display: inline-flex; + justify-content: center; position: relative; vertical-align: middle; @@ -100,7 +99,6 @@ width: var(--iron-icon-width, 24px); height: var(--iron-icon-height, 24px); - @apply --iron-icon; } :host([hidden]) {
diff --git a/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn b/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn index 9114437..39ecb37 100644 --- a/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn +++ b/third_party/polymer/v3_0/components-chromium/paper-progress/BUILD.gn
@@ -8,7 +8,6 @@ js_library("paper-progress") { deps = [ - "../iron-flex-layout:iron-flex-layout", "../iron-range-behavior:iron-range-behavior", "../paper-styles:color", "../polymer:polymer_bundled",
diff --git a/third_party/polymer/v3_0/components-chromium/paper-progress/paper-progress.js b/third_party/polymer/v3_0/components-chromium/paper-progress/paper-progress.js index 17ac1b7f..51fa62ba 100644 --- a/third_party/polymer/v3_0/components-chromium/paper-progress/paper-progress.js +++ b/third_party/polymer/v3_0/components-chromium/paper-progress/paper-progress.js
@@ -9,7 +9,6 @@ found at http://polymer.github.io/PATENTS.txt */ import '../polymer/polymer_bundled.min.js'; -import '../iron-flex-layout/iron-flex-layout.js'; import '../paper-styles/color.js'; import {IronRangeBehavior} from '../iron-range-behavior/iron-range-behavior.js'; @@ -74,7 +73,6 @@ Custom property | Description | Default ----------------|-------------|--------- -`--paper-progress-container` | Mixin applied to container | `{}` `--paper-progress-transition-duration` | Duration of the transition | `0.08s` `--paper-progress-transition-timing-function` | The timing function for the transition | `ease` `--paper-progress-transition-delay` | delay for the transition | `0s` @@ -105,7 +103,6 @@ } #progressContainer { - @apply --paper-progress-container; position: relative; } @@ -118,7 +115,11 @@ #primaryProgress, #secondaryProgress, .indeterminate::after { - @apply --layout-fit; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; } #progressContainer, @@ -142,7 +143,6 @@ #primaryProgress, #secondaryProgress { - @apply --layout-fit; transform-origin: left center; transform: scaleX(0); will-change: transform;
diff --git a/third_party/polymer/v3_0/components-chromium/paper-tooltip/paper-tooltip.js b/third_party/polymer/v3_0/components-chromium/paper-tooltip/paper-tooltip.js index 96a81a5..1b36aa4 100644 --- a/third_party/polymer/v3_0/components-chromium/paper-tooltip/paper-tooltip.js +++ b/third_party/polymer/v3_0/components-chromium/paper-tooltip/paper-tooltip.js
@@ -46,7 +46,6 @@ `--paper-tooltip-delay-out` | Delay before tooltip starts to fade out | `0` `--paper-tooltip-duration-in` | Timing for animation when showing tooltip | `500` `--paper-tooltip-duration-out` | Timing for animation when hiding tooltip | `0` -`--paper-tooltip-animation` | Mixin applied to the tooltip animation | `{}` Also prefer using the exposed CSS part as follows where possible paper-tooltip::part(tooltip) {...} @@ -70,7 +69,6 @@ #tooltip { display: block; outline: none; - @apply --paper-font-common-base; font-size: 10px; line-height: 1; background-color: var(--paper-tooltip-background, #616161);
diff --git a/third_party/polymer/v3_0/iron_icon.patch b/third_party/polymer/v3_0/iron_icon.patch new file mode 100644 index 0000000..f24f98b --- /dev/null +++ b/third_party/polymer/v3_0/iron_icon.patch
@@ -0,0 +1,33 @@ +diff --git a/components-chromium/iron-icon/iron-icon.js b/components-chromium/iron-icon/iron-icon.js +index 35835d2b5c484..2a647f13b3e55 100644 +--- a/components-chromium/iron-icon/iron-icon.js ++++ b/components-chromium/iron-icon/iron-icon.js +@@ -8,8 +8,6 @@ found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by Google as + part of the polymer project is also subject to an additional IP rights grant + found at http://polymer.github.io/PATENTS.txt + */ +-import '../iron-flex-layout/iron-flex-layout.js'; +- + import {IronMeta} from '../iron-meta/iron-meta.js'; + import {Polymer} from '../polymer/polymer_bundled.min.js'; + import {dom} from '../polymer/polymer_bundled.min.js'; +@@ -89,8 +87,9 @@ Polymer({ + _template: html` + <style> + :host { +- @apply --layout-inline; +- @apply --layout-center-center; ++ align-items: center; ++ display: inline-flex; ++ justify-content: center; + position: relative; + + vertical-align: middle; +@@ -100,7 +99,6 @@ Polymer({ + + width: var(--iron-icon-width, 24px); + height: var(--iron-icon-height, 24px); +- @apply --iron-icon; + } + + :host([hidden]) {
diff --git a/third_party/polymer/v3_0/paper_progress.patch b/third_party/polymer/v3_0/paper_progress.patch new file mode 100644 index 0000000..89e92b0c --- /dev/null +++ b/third_party/polymer/v3_0/paper_progress.patch
@@ -0,0 +1,49 @@ +diff --git a/components-chromium/paper-progress/paper-progress.js b/components-chromium/paper-progress/paper-progress.js +index fdb26f773b1e3..51b5a814601ac 100644 +--- a/components-chromium/paper-progress/paper-progress.js ++++ b/components-chromium/paper-progress/paper-progress.js +@@ -9,7 +9,6 @@ part of the polymer project is also subject to an additional IP rights grant + found at http://polymer.github.io/PATENTS.txt + */ + import '../polymer/polymer-legacy.js'; +-import '../iron-flex-layout/iron-flex-layout.js'; + import '../paper-styles/color.js'; + + import {IronRangeBehavior} from '../iron-range-behavior/iron-range-behavior.js'; +@@ -74,7 +73,6 @@ The following mixins are available for styling: + + Custom property | Description | Default + ----------------|-------------|--------- +-`--paper-progress-container` | Mixin applied to container | `{}` + `--paper-progress-transition-duration` | Duration of the transition | `0.08s` + `--paper-progress-transition-timing-function` | The timing function for the transition | `ease` + `--paper-progress-transition-delay` | delay for the transition | `0s` +@@ -105,7 +103,6 @@ Polymer({ + } + + #progressContainer { +- @apply --paper-progress-container; + position: relative; + } + +@@ -118,7 +115,11 @@ Polymer({ + #primaryProgress, + #secondaryProgress, + .indeterminate::after { +- @apply --layout-fit; ++ position: absolute; ++ top: 0; ++ right: 0; ++ bottom: 0; ++ left: 0; + } + + #progressContainer, +@@ -146,7 +147,6 @@ Polymer({ + + #primaryProgress, + #secondaryProgress { +- @apply --layout-fit; + -webkit-transform-origin: left center; + transform-origin: left center; + -webkit-transform: scaleX(0);
diff --git a/third_party/polymer/v3_0/paper_tooltip.patch b/third_party/polymer/v3_0/paper_tooltip.patch index fcc0d7c..03934ac 100644 --- a/third_party/polymer/v3_0/paper_tooltip.patch +++ b/third_party/polymer/v3_0/paper_tooltip.patch
@@ -1,8 +1,8 @@ diff --git a/components-chromium/paper-tooltip/paper-tooltip.js b/components-chromium/paper-tooltip/paper-tooltip.js -index 853eee1990258..96a81a5a903b9 100644 +index 853eee1990258..1b36aa4c38b3f 100644 --- a/components-chromium/paper-tooltip/paper-tooltip.js +++ b/components-chromium/paper-tooltip/paper-tooltip.js -@@ -42,12 +42,15 @@ Custom property | Description | Default +@@ -42,12 +42,14 @@ Custom property | Description | Default `--paper-tooltip-background` | The background color of the tooltip | `#616161` `--paper-tooltip-opacity` | The opacity of the tooltip | `0.9` `--paper-tooltip-text-color` | The text color of the tooltip | `white` @@ -11,7 +11,7 @@ `--paper-tooltip-delay-out` | Delay before tooltip starts to fade out | `0` `--paper-tooltip-duration-in` | Timing for animation when showing tooltip | `500` `--paper-tooltip-duration-out` | Timing for animation when hiding tooltip | `0` - `--paper-tooltip-animation` | Mixin applied to the tooltip animation | `{}` +-`--paper-tooltip-animation` | Mixin applied to the tooltip animation | `{}` + +Also prefer using the exposed CSS part as follows where possible +paper-tooltip::part(tooltip) {...} @@ -19,7 +19,14 @@ @group Paper Elements @element paper-tooltip @demo demo/index.html -@@ -74,7 +77,6 @@ Polymer({ +@@ -67,14 +69,12 @@ Polymer({ + #tooltip { + display: block; + outline: none; +- @apply --paper-font-common-base; + font-size: 10px; + line-height: 1; + background-color: var(--paper-tooltip-background, #616161); color: var(--paper-tooltip-text-color, white); padding: 8px; border-radius: 2px; @@ -27,7 +34,7 @@ } @keyframes keyFrameScaleUp { -@@ -149,7 +151,6 @@ Polymer({ +@@ -149,7 +149,6 @@ Polymer({ animation-timing-function: ease-in; animation-duration: var(--paper-tooltip-duration-in, 500ms); animation-fill-mode: forwards; @@ -35,7 +42,7 @@ } .fade-out-animation { -@@ -160,7 +161,6 @@ Polymer({ +@@ -160,7 +159,6 @@ Polymer({ animation-timing-function: ease-in; animation-duration: var(--paper-tooltip-duration-out, 500ms); animation-fill-mode: forwards; @@ -43,7 +50,7 @@ } .scale-up-animation { -@@ -172,7 +172,6 @@ Polymer({ +@@ -172,7 +170,6 @@ Polymer({ animation-timing-function: ease-in; animation-duration: var(--paper-tooltip-duration-in, 500ms); animation-fill-mode: forwards; @@ -51,7 +58,7 @@ } .scale-down-animation { -@@ -184,7 +183,6 @@ Polymer({ +@@ -184,7 +181,6 @@ Polymer({ animation-timing-function: ease-in; animation-duration: var(--paper-tooltip-duration-out, 500ms); animation-fill-mode: forwards; @@ -59,7 +66,7 @@ } .slide-down-animation { -@@ -196,7 +194,6 @@ Polymer({ +@@ -196,7 +192,6 @@ Polymer({ animation-timing-function: cubic-bezier(0.0, 0.0, 0.2, 1); animation-duration: var(--paper-tooltip-duration-out, 500ms); animation-fill-mode: forwards; @@ -67,7 +74,7 @@ } .slide-down-animation-out { -@@ -208,7 +205,6 @@ Polymer({ +@@ -208,7 +203,6 @@ Polymer({ animation-timing-function: cubic-bezier(0.4, 0.0, 1, 1); animation-duration: var(--paper-tooltip-duration-out, 500ms); animation-fill-mode: forwards; @@ -75,7 +82,7 @@ } .cancel-animation { -@@ -222,7 +218,7 @@ Polymer({ +@@ -222,7 +216,7 @@ Polymer({ } </style> @@ -84,7 +91,7 @@ <slot></slot> </div> `, -@@ -282,8 +278,8 @@ Polymer({ +@@ -282,8 +276,8 @@ Polymer({ */ animationExit: {type: String, value: ''}, /** @@ -95,7 +102,7 @@ * and hiding the tooltip. If you want to override this, you must ensure * that your animationConfig has the exact format below. * @deprecated since version -@@ -311,12 +307,16 @@ Polymer({ +@@ -311,12 +305,16 @@ Polymer({ /** * Returns the target element that this tooltip is anchored to. It is @@ -114,7 +121,7 @@ var parentNode = dom(this).parentNode; // If the parentNode is a document fragment, then we need to use the host. var ownerRoot = dom(this).getOwnerRoot(); -@@ -331,6 +331,15 @@ Polymer({ +@@ -331,6 +329,15 @@ Polymer({ return target; }, @@ -130,7 +137,7 @@ /** * @return {void} */ -@@ -429,13 +438,16 @@ Polymer({ +@@ -429,13 +436,16 @@ Polymer({ * @return {void} */ updatePosition: function() { @@ -149,7 +156,7 @@ var targetRect = this._target.getBoundingClientRect(); var thisRect = this.getBoundingClientRect(); var horizontalCenterOffset = (targetRect.width - thisRect.width) / 2; -@@ -581,5 +593,45 @@ Polymer({ +@@ -581,5 +591,45 @@ Polymer({ } this.unlisten(this.$.tooltip, 'animationend', '_onAnimationEnd'); this.unlisten(this, 'mouseenter', 'hide');
diff --git a/third_party/polymer/v3_0/reproduce.sh b/third_party/polymer/v3_0/reproduce.sh index 79085688..1578e71 100755 --- a/third_party/polymer/v3_0/reproduce.sh +++ b/third_party/polymer/v3_0/reproduce.sh
@@ -17,6 +17,8 @@ fi } +set -e + check_dep "which npm" "npm" "visiting https://nodejs.org/en/" check_dep "which rsync" "rsync" "apt-get install rsync" check_dep "sed --version | grep GNU" \ @@ -50,9 +52,11 @@ -exec sed -i 's/@webcomponents\//..\/..\/..\//g' {} + # Apply additional chrome specific patches. -patch -p1 --forward -r - < chromium.patch -patch -p1 --forward -r - < iron_list.patch -patch -p1 --forward -r - < paper_tooltip.patch +patch -p1 --forward < chromium.patch +patch -p1 --forward < iron_icon.patch +patch -p1 --forward < iron_list.patch +patch -p1 --forward < paper_progress.patch +patch -p1 --forward < paper_tooltip.patch echo 'Minifying Polymer 3, since it comes non-minified from NPM.' python minify_polymer.py
diff --git a/third_party/polymer/v3_0/rsync_exclude.txt b/third_party/polymer/v3_0/rsync_exclude.txt index f99fe8cb..c158438 100644 --- a/third_party/polymer/v3_0/rsync_exclude.txt +++ b/third_party/polymer/v3_0/rsync_exclude.txt
@@ -36,6 +36,9 @@ # iron-checked-element-behavior iron-checked-element-behavior/* +# iron-flex-layout +iron-flex-layout/iron-flex-layout.* + # iron-form-element-behavior iron-form-element-behavior/*
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 4ee3588..8a07ea6 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -362,6 +362,7 @@ 'android-backuprefptr-arm64-fyi-rel': 'release_trybot_backuprefptr_arm64_reclient', 'android-code-coverage': 'gpu_tests_android_release_bot_minimal_symbols_arm64_fastbuild_java_coverage_reclient', 'android-code-coverage-native': 'gpu_tests_android_release_bot_no_symbols_arm64_fastbuild_native_coverage_reclient', + 'android-fieldtrial-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome_reclient', 'chromeos-amd64-generic-rel (goma cache silo)': 'chromeos_amd64-generic_use_fake_dbus_clients', # TODO(crbug.com/1235218): remove after the migration. 'chromeos-amd64-generic-rel (reclient compare)': 'chromeos_amd64-generic-vm_use_fake_dbus_clients_reclient', @@ -908,6 +909,7 @@ 'android-cronet-x86-rel-kitkat-tests': 'android_cronet_release_bot_minimal_symbols_x86', 'android-deterministic-dbg': 'android_debug_bot', 'android-deterministic-rel': 'android_without_codecs_release_trybot', + 'android-fieldtrial-fyi-rel': 'android_release_bot_minimal_symbols_x86_fastbuild_webview_monochrome_reclient', 'android-inverse-fieldtrials-pie-x86-fyi-rel': 'android_release_trybot_x86_fastbuild_webview_google_invert_fieldtrials', 'android-marshmallow-arm64-rel': 'gpu_tests_android_release_trybot_arm64_fastbuild_java_coverage', 'android-marshmallow-x86-fyi-rel-reviver': 'android_release_trybot_x86_fastbuild_webview_google',
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json index ac1fd0df..595ef63 100644 --- a/tools/mb/mb_config_expectations/chromium.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -557,6 +557,24 @@ "use_static_angle": true } }, + "android-fieldtrial-rel": { + "gn_args": { + "dcheck_always_on": false, + "disable_android_lint": true, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "strip_debug_info": true, + "symbol_level": 1, + "system_webview_package_name": "com.google.android.apps.chrome", + "target_cpu": "x86", + "target_os": "android", + "use_errorprone_java_compiler": false, + "use_rbe": true, + "use_remoteexec": true + } + }, "chromeos-amd64-generic-rel (goma cache silo)": { "args_file": "//build/args/chromeos/amd64-generic.gni", "gn_args": {
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json index eb26099b..537db75d 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -531,6 +531,24 @@ "use_goma": true } }, + "android-fieldtrial-fyi-rel": { + "gn_args": { + "dcheck_always_on": false, + "disable_android_lint": true, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "strip_debug_info": true, + "symbol_level": 1, + "system_webview_package_name": "com.google.android.apps.chrome", + "target_cpu": "x86", + "target_os": "android", + "use_errorprone_java_compiler": false, + "use_rbe": true, + "use_remoteexec": true + } + }, "android-inverse-fieldtrials-pie-x86-fyi-rel": { "gn_args": { "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index c1ed6d8..ee2924e 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -40076,7 +40076,7 @@ <int value="4157" label="V8UDPSocket_RemotePort_AttributeGetter"/> <int value="4158" label="V8UDPSocket_Writable_AttributeGetter"/> <int value="4159" label="AbortSignalTimeout"/> - <int value="4160" label="OBSOLETE_ClientHintsPartitionedCookies"/> + <int value="4160" label="ClientHintsPartitionedCookies"/> <int value="4161" label="V8Document_Prerendering_AttributeGetter"/> <int value="4162" label="V8Document_Onprerenderingchange_AttributeGetter"/> <int value="4163" label="V8Document_Onprerenderingchange_AttributeSetter"/> @@ -40272,7 +40272,7 @@ <int value="93" label="ClientHintUAFullVersionList"/> <int value="94" label="ClientHintUAFull"/> <int value="95" label="ClientHintUAWoW64"/> - <int value="96" label="Deprecated: ClientHintPartitionedCookies"/> + <int value="96" label="ClientHintPartitionedCookies"/> <int value="97" label="BrowsingTopics"/> <int value="98" label="BrowsingTopicsBackwardCompatible"/> <int value="99" label="ClientHintSaveData"/> @@ -73115,6 +73115,13 @@ <int value="4" label="Clicked Change password automatically"/> </enum> +<enum name="PasswordLeakDetectionDialogType"> + <int value="0" label="Password checkup offered"/> + <int value="1" label="Manual password change offered"/> + <int value="2" label="Password checkup and manual password change offered"/> + <int value="3" label="Automatic and manual password change offered"/> +</enum> + <enum name="PasswordLeakDetectionError"> <int value="0" label="Not signed in"/> <int value="1" label="Token request error"/> @@ -74310,6 +74317,11 @@ <int value="11004" label="ACCESS_DENIED"/> <int value="11005" label="AUTH_ERROR_RESOLVABLE"/> <int value="11006" label="AUTH_ERROR_UNRESOLVABLE"/> + <int value="43502" label="CHROME_SYNC_API_CALL_ERROR"/> + <int value="43504" label="ERROR_WHILE_DOING_LEAK_CHECK_SERVICE_GRPC"/> + <int value="43507" label="REQUIRED_SYNCED_ACCOUNT_MISSING"/> + <int value="43508" label="LEAK_CHECK_SERVICE_AUTH_ERROR"/> + <int value="43509" label="LEAK_CHECK_SERVICE_RESOURCE_EXHAUSTED"/> </enum> <enum name="PasswordStoreAndroidBackendError"> @@ -87944,6 +87956,7 @@ <int value="0" label="Bad tag"/> <int value="1" label="Bad parameters"/> <int value="2" label="Missing parameters"/> + <int value="3" label="Missing prompt seed"/> </enum> <enum name="SoftwareReporterIPCDisconnected">
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index f3bd20d..02d4647 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -2447,8 +2447,8 @@ </histogram> <histogram name="Apps.NoteTakingApp.DefaultLaunchResult" - enum="NoteTakingAppLaunchResult" expires_after="2022-06-01"> - <owner>dstockwell@chromium.org</owner> + enum="NoteTakingAppLaunchResult" expires_after="2022-12-01"> + <owner>glenrob@chromium.org</owner> <owner>tbuckley@chromium.org</owner> <summary> The result of attempting to launch a default note-taking app on Chrome OS. @@ -2457,8 +2457,8 @@ </histogram> <histogram name="Apps.NoteTakingApp.PreferredLaunchResult" - enum="NoteTakingAppLaunchResult" expires_after="2022-10-04"> - <owner>dstockwell@chromium.org</owner> + enum="NoteTakingAppLaunchResult" expires_after="2022-12-01"> + <owner>glenrob@chromium.org</owner> <owner>tbuckley@chromium.org</owner> <summary> The result of attempting to launch the user-specified preferred note-taking
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index 8d4db544..c06114a 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -2158,6 +2158,21 @@ </summary> </histogram> +<histogram name="Blink.Script.SchedulingType" enum="ScriptSchedulingType" + expires_after="2022-11-25"> + <owner>kouhei@chromium.org</owner> + <owner>hiroshige@chromium.org</owner> + <owner>chikamune@chromium.org</owner> + <summary> + Number of script elements for each scheduling type, recorded when each + script loading reaches the #prepare-a-script state defined in the spec, with + http or https request. + + Warning: this histogram was expired from 2018-12-31 to 2022-05-25; data may + be missing. + </summary> +</histogram> + <histogram name="Blink.Script.SourceTextTime" units="microseconds" expires_after="2022-10-18"> <owner>cduvall@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml index bd2b3eb..052f6dc 100644 --- a/tools/metrics/histograms/metadata/network/histograms.xml +++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -144,6 +144,16 @@ </summary> </histogram> +<histogram name="Network.CacheTransparency.ListVersion" units="version" + expires_after="2022-11-01"> + <owner>nidhijaju@chromium.org</owner> + <owner>ricea@chromium.org</owner> + <summary> + Records the version number of the pervasive payloads list, when the list is + parsed the first time a URL request is made. + </summary> +</histogram> + <histogram name="Network.CacheTransparency.MarkedUnusable" units="list index" expires_after="2022-11-01"> <owner>nidhijaju@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index fb1569b..d739ef4 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -29,6 +29,13 @@ <variant name=".WithoutCustomPassphrase" summary="regularly encrypted"/> </variants> +<variants name="PasswordCheckupOperation"> + <variant name="GetBreachedCredentialsCount" + summary="get breached credentials count"/> + <variant name="GetIntent" summary="get password checkup UI intent"/> + <variant name="RunPasswordCheckup" summary="run password checkup"/> +</variants> + <variants name="PasswordManagerSetting"> <variant name="AutoSignIn" summary="auto sign in preference"/> <variant name="OfferToSavePasswords" @@ -1948,18 +1955,6 @@ </token> </histogram> -<histogram name="PasswordManager.PasswordCheckup.GetIntent.Error" - enum="CredentialManagerError" expires_after="M105"> - <owner>ioanap@chromium.org</owner> - <owner>vsemeniuk@google.com</owner> - <summary> - Records the error encountered while attempting to fetch the Password Checkup - launch intent from Google Play Services. This is recorded either before - making the actual request (if the preconditions are not met) or after the - asynchronous call comes back with an error. - </summary> -</histogram> - <histogram name="PasswordManager.PasswordCheckup.GetIntent.Latency" units="ms" expires_after="M105"> <owner>ioanap@chromium.org</owner> @@ -1996,6 +1991,34 @@ </summary> </histogram> +<histogram name="PasswordManager.PasswordCheckup.{Operation}.APIError" + enum="PasswordStoreAndroidBackendAPIError" expires_after="M105"> + <owner>ioanap@chromium.org</owner> + <owner>maxan@google.com</owner> + <summary> + Records the error code returned by the GMS Password Checkup 1P API while + attempting to {Operation}. This is recorded after the asynchronous call + comes back with an error. This is only recorded for GMS API errors on + Android. + </summary> + <token key="Operation" variants="PasswordCheckupOperation"/> +</histogram> + +<histogram name="PasswordManager.PasswordCheckup.{Operation}.Error" + enum="CredentialManagerError" expires_after="M105"> + <owner>ioanap@chromium.org</owner> + <owner>maxan@google.com</owner> + <owner>vsemeniuk@google.com</owner> + <summary> + Records the backend error code encountered while attempting to {Operation}. + If the code is equal to 2 (API_ERROR), GMS 1P API error code is additionally + reported. This is recorded either before making the actual request (if the + preconditions are not met) or after the asynchronous call comes back with an + error. This is currently only recorded on Android. + </summary> + <token key="Operation" variants="PasswordCheckupOperation"/> +</histogram> + <histogram name="PasswordManager.PasswordDropdownItemSelected" enum="PasswordDropdownSelectedOption" expires_after="2022-10-30"> <owner>kazinova@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml index 2265d7f..a859fa5 100644 --- a/tools/metrics/histograms/metadata/sync/histograms.xml +++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -492,7 +492,7 @@ </histogram> <histogram name="Sync.KeystoreDecryptionFailed" - enum="SyncKeystoreDecryptionFailure" expires_after="2022-07-03"> + enum="SyncKeystoreDecryptionFailure" expires_after="2023-01-03"> <owner>mmoskvitin@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 65d3011..ab61caa5 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -15187,6 +15187,29 @@ </metric> </event> +<event name="PasswordManager.LeakWarningDialog"> + <owner>jkeitel@google.com</owner> + <owner>chrome-duplex@google.com</owner> + <summary> + Metrics related to leak warnings shown on login and password reset. Leak + warning dialogs in Chrome aim to inform users about leaked credentials and + advise to change them. We collect type of the dialog that is shown and the + response of the user to it. + </summary> + <metric name="PasswordLeakDetectionDialogDismissalReason" + enum="PasswordLeakDetectionDialogDismissalReason"> + <summary> + Records the response to the password leak dialog. + </summary> + </metric> + <metric name="PasswordLeakDetectionDialogType" + enum="PasswordLeakDetectionDialogType"> + <summary> + Records the type of the password leak dialog. + </summary> + </metric> +</event> + <event name="PasswordManager.PasswordChangeFlowDuration"> <owner>kolos@chromium.org</owner> <owner>jkeitel@google.com</owner>
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index ce55e0ca..38cacc0 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -435,6 +435,7 @@ "javatests/src/org/chromium/ui/test/util/UiRestriction.java", "javatests/src/org/chromium/ui/test/util/UiRestrictionSkipCheck.java", "javatests/src/org/chromium/ui/test/util/ViewUtils.java", + "javatests/src/org/chromium/ui/test/util/modaldialog/FakeModalDialogManager.java", "javatests/src/org/chromium/ui/test/util/modelutil/FakeViewProvider.java", "junit/src/org/chromium/ui/base/TestActivity.java", ] @@ -446,6 +447,8 @@ "//third_party/androidx:androidx_appcompat_appcompat_java", "//third_party/androidx:androidx_appcompat_appcompat_resources_java", "//third_party/androidx:androidx_vectordrawable_vectordrawable_animated_java", + "//third_party/mockito:mockito_java", + "//ui/android:ui_no_recycler_view_java", # For androidx.test.espresso.ViewInteraction "//third_party/android_deps:espresso_java",
diff --git a/chrome/browser/ui/android/autofill/test/java/src/org/chromium/chrome/browser/ui/autofill/FakeModalDialogManager.java b/ui/android/javatests/src/org/chromium/ui/test/util/modaldialog/FakeModalDialogManager.java similarity index 96% rename from chrome/browser/ui/android/autofill/test/java/src/org/chromium/chrome/browser/ui/autofill/FakeModalDialogManager.java rename to ui/android/javatests/src/org/chromium/ui/test/util/modaldialog/FakeModalDialogManager.java index 4f09d5d..9418c87b 100644 --- a/chrome/browser/ui/android/autofill/test/java/src/org/chromium/chrome/browser/ui/autofill/FakeModalDialogManager.java +++ b/ui/android/javatests/src/org/chromium/ui/test/util/modaldialog/FakeModalDialogManager.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.ui.autofill; +package org.chromium.ui.test.util.modaldialog; import org.mockito.Mockito;
diff --git a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js index 69bc1b69..e9e4e27 100644 --- a/ui/file_manager/file_manager/foreground/js/file_manager_commands.js +++ b/ui/file_manager/file_manager/foreground/js/file_manager_commands.js
@@ -689,9 +689,11 @@ try { await fileManager.volumeManager.unmount(volume); } catch (error) { - console.error(`Cannot unmount (redacted)':`, error); + console.error(`Cannot unmount (redacted):`, error); console.debug(`Cannot unmount '${volume.volumeId}':`, error); - errorCallback(volume.volumeType); + if (error != VolumeManagerCommon.VolumeError.PATH_NOT_MOUNTED) { + errorCallback(volume.volumeType); + } } });
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html index da3132b4..d4f1204 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/button_bar.html
@@ -7,11 +7,10 @@ <link rel="import" href="../../../cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/assert.html"> <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> <dom-module id="button-bar"> <template> - <style include="iron-flex"> + <style> :host { display: flex; justify-content: flex-end;
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html index 809db7d..d38a6324 100644 --- a/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html +++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/psim_flow_ui.html
@@ -9,14 +9,12 @@ <link rel="import" href="cellular_types.html"> <link rel="import" href="cellular_setup_delegate.html"> <link rel="import" href="chrome://resources/html/assert.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html"> <dom-module id="psim-flow-ui"> <template> - <style include="iron-flex"> + <style> :host { display: flex; flex: 1 1 auto;
diff --git a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html index d838a258..4455851 100644 --- a/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html +++ b/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html
@@ -4,7 +4,6 @@ <link rel="import" href="../../../cr_elements/shared_vars_css.html"> <link rel="import" href="../../../cr_elements/md_select_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html"> <custom-style> <style is="custom-style">
diff --git a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn index 61ff21c..52ddb70 100644 --- a/ui/webui/resources/cr_components/chromeos/network/BUILD.gn +++ b/ui/webui/resources/cr_components/chromeos/network/BUILD.gn
@@ -366,7 +366,7 @@ deps = [ ":network_shared_css.m", "//chromeos/services/network_config/public/mojom:mojom_js_library_for_compile", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", + "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_button:cr_button.m", "//ui/webui/resources/js:i18n_behavior.m", @@ -385,7 +385,7 @@ ":network_password_input.m", ":network_shared_css.m", "//chrome/browser/ui/webui/settings/chromeos/search:mojo_bindings_js_library_for_compile", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", + "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", "//third_party/polymer/v3_0/components-chromium/iron-icon:iron-icon", "//third_party/polymer/v3_0/components-chromium/paper-spinner:paper-spinner-lite", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", @@ -517,7 +517,7 @@ deps = [ ":cr_policy_network_behavior_mojo.m", ":network_shared_css.m", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout", + "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/cr_elements/cr_input:cr_input.m", "//ui/webui/resources/cr_elements/cr_radio_button:cr_radio_button.m",