diff --git a/DEPS b/DEPS index f26b324..fa2f95f 100644 --- a/DEPS +++ b/DEPS
@@ -300,19 +300,19 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': 'c5094c5d2f1a8fa1706e553bda59c9c91eefb82e', + 'src_internal_revision': '71e803fdda2777c37207dab5209d5d7765620a1a', # 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': 'ac897edeb16a449c6e519e13ddf3decd8a6cb763', + 'skia_revision': 'f4e943ffc6ce1175c37128dc6b0988cf54a27202', # 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': 'aeb46da61fe9bf6544f0cec9e082817d6c30b8eb', + 'v8_revision': 'e438515e8357757c725cd50e598c546cdda00d22', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '4dcfd08c07842e5f4aef044c6e2aa92b6020f8fe', + 'angle_revision': 'ff110417bb04e9bc13079eeed99940009d9c3ce1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -320,7 +320,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '72b0518387821b29d4edcea69b7911097636f743', + 'pdfium_revision': '6e653ec0cf27cbaf0ff204aeed5d5747dd85da33', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -375,7 +375,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'a8f1b417bdecdb677fe7a447ab715e482e2def97', + 'catapult_revision': '44beba1e6d819a2154b069bc1fd76878b47f33d1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -391,7 +391,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '12d5ea5cb8149e7dfce7c8395c81b7909401500a', + 'devtools_frontend_revision': '9215bd9a9bdff053660d7ebdd5a8a5bdcb8157e5', # 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. @@ -431,7 +431,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': '2ef42221d4b3d803be4d663ded04b6158d9546b3', + 'dawn_revision': 'f75e5c07b0678bc2d9caaa3601867a6acbd41634', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -451,11 +451,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libavif # and whatever else without interference from each other. - 'libavif_revision': 'd3d2abaab160f2c1a85bc2adf3e43cac4cad00f8', + 'libavif_revision': '781d6a6467d82d8ba36256f31b6593a33c03345d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '55750a0843e7c972fc9d4820b450a62b651eaa0b', + 'nearby_revision': '9c09f325e0fc3c96791020f99d0ecaba8714b4d7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -502,7 +502,7 @@ 'libcxx_revision': 'f8279b01085b800724f5c5629dc365b9f040dc53', # GN CIPD package version. - 'gn_version': 'git_revision:e9e83d9095d3234adf68f3e2866f25daf766d5c7', + 'gn_version': 'git_revision:e3978de3e8dafb50a2b11efa784e08699a43faf8', # ninja CIPD package version. # https://chrome-infra-packages.appspot.com/p/infra/3pp/tools/ninja @@ -812,7 +812,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '68a9b496f1f87816f7c9b115123489f8e73913d1', + '47d843578dc8bdb4952b313d8b597d0d7e9d9e12', 'condition': 'checkout_android and checkout_src_internal', }, @@ -911,7 +911,7 @@ 'packages': [ { 'package': 'chromium/rts/model/linux-amd64', - 'version': 'h89kXCr9vv-wtdasE63EWszGJvp3wn0mYCUh1S-NPZIC', + 'version': 'FMWls2ahHgWI-Ba_TqxcqGj9el_9e9BFO8qgzlyql2wC', }, ], 'dep_type': 'cipd', @@ -922,7 +922,7 @@ 'packages': [ { 'package': 'chromium/rts/model/mac-amd64', - 'version': 'uKswKt2iZ1YHXNChvWoHOALg6qic2pmg1c7AsD2NPgMC', + 'version': 'xUaI7iwbas5hD4CAFYVUitiCmd_QZPb1YwkzRRUIEsEC', }, ], 'dep_type': 'cipd', @@ -933,7 +933,7 @@ 'packages': [ { 'package': 'chromium/rts/model/windows-amd64', - 'version': 'n5hg1tdODa_W76meKnwvjDsmrnGYRqLdpEN3QZ6NhSYC', + 'version': '6Da4qLnxG15UJgIXWyEVoxRHGphwD5MG1ys1aai-tLcC', }, ], 'dep_type': 'cipd', @@ -1001,7 +1001,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': '0HbW5xCesKg0FE8eo-l2o-QEEBDbzJsHbbhtvIEQPfQC', + 'version': '4SUfq6Z07erzQpU25SW1RpyFHQCWuItCDAuNoTM-DEkC', }, ], 'condition': 'checkout_android', @@ -1207,7 +1207,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b393c91b0765aa6446d91b03589412b7eb4fede2', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'cbfa217773d754a09d9d2c480a110f6d41dbda33', 'condition': 'checkout_chromeos', }, @@ -1217,6 +1217,9 @@ 'src/third_party/colorama/src': Var('chromium_git') + '/external/colorama.git' + '@' + '3de9f013df4b470069d03d250224062e8cf15c49', + 'src/third_party/cpu_features/src': + Var('chromium_git') + '/external/github.com/google/cpu_features.git' + '@' + '936b9ab5515dead115606559502e3864958f7f6e', + 'src/third_party/cpuinfo/src': Var('chromium_git') + '/external/github.com/pytorch/cpuinfo.git' + '@' + 'f44a9dabb2192ffb203ddd0c71f6373c7d82faed', @@ -1239,13 +1242,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '4dfbc0a3a9d6a8865925ce287e161433ecc19b74', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '04afb4b256a1aab562b0fcfaf7cd9ffe4ec42c1b', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'c83926ec9864b787378bb241359c595f11c81e31', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + 'a314fc21810a828962258d6d258c4bdecfd28ce7', 'condition': 'checkout_src_internal', }, @@ -1356,7 +1359,7 @@ }, 'src/third_party/cardboard/src' : { - 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + '407fffc4b0c984fef821db51e04c151d691c02a8', + 'url': Var('chromium_git') + '/external/github.com/googlevr/cardboard/' + '@' + '80170209084b10860c76ea95a008875ff2a46bd4', 'condition': 'checkout_android', }, @@ -1857,7 +1860,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@b5740c8560dfa6e130dcc9fba3db45f84988af68', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@a73a454216a189fb9debfc6f1ebb1d4682f55fa4', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907', @@ -1897,7 +1900,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '1585e66de78d0d2e600f467eddafc445eaff1c90', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '9caef2a8b88f389af10cee841732c42a98d3d45d', + Var('webrtc_git') + '/src.git' + '@' + '2bb686dbc0becdc7c535032eb333d65d3baa394c', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -2017,7 +2020,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'ITFNdvDmlF5T_4bCtaYRoxFNAX60JhxYav5yvsoK1MAC', + 'version': 'MfMXXV6UoUsKNUBvHqdspgBhMfcAAOms1el88hvXCqwC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -2028,7 +2031,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'EAzl5NafyfvjwyjuFFRR_gqLdkMqYPvC09EvPMsKo-oC', + 'version': 'QWD1zQcFupAjvLzrn4AJAOA09lPdRY2gytkRrC-Nwx8C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4138,7 +4141,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '904523c3b136396429a4ddf000696eaf4c1d710b', + '15a8ac31d8c154261e8e937c18a4fcf3a76ec22f', 'condition': 'checkout_src_internal', }, @@ -4186,7 +4189,7 @@ 'src/ios_internal': { 'url': '{chrome_git}/chrome/ios_internal.git' + '@' + - '729bafca3520d7cc4471b3e822f7dc9759a0257b', + '54f95381e5235973ac005341348704e27c665e6f', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 16cf53f8..d2ce0244 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -990,6 +990,8 @@ r'net/der/.*', # Needed to use APIs from the above. r'net/cert/.*', + # Needed by Caspian, which compiles to WASM. + r'tools/binary_size/libsupersize/viewer/caspian/.*', # Not an error in third_party folders. _THIRD_PARTY_EXCEPT_BLINK ],
diff --git a/android_webview/browser/gfx/aw_draw_fn_impl.cc b/android_webview/browser/gfx/aw_draw_fn_impl.cc index a536ecd..9731992f 100644 --- a/android_webview/browser/gfx/aw_draw_fn_impl.cc +++ b/android_webview/browser/gfx/aw_draw_fn_impl.cc
@@ -30,7 +30,7 @@ BASE_FEATURE(kCheckDrawFunctorThread, "CheckDrawFunctorThread", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); // Set once during process-wide initialization. AwDrawFnFunctionTable* g_draw_fn_function_table = nullptr;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 7bc1401c..3f88eab 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1414,8 +1414,15 @@ "system/hotspot/hotspot_detailed_view_controller.h", "system/hotspot/hotspot_feature_pod_controller.cc", "system/hotspot/hotspot_feature_pod_controller.h", + "system/hotspot/hotspot_icon.cc", + "system/hotspot/hotspot_icon.h", + "system/hotspot/hotspot_icon_animation.cc", + "system/hotspot/hotspot_icon_animation.h", + "system/hotspot/hotspot_icon_animation_observer.h", "system/hotspot/hotspot_info_cache.cc", "system/hotspot/hotspot_info_cache.h", + "system/hotspot/hotspot_notifier.cc", + "system/hotspot/hotspot_notifier.h", "system/hotspot/hotspot_tray_view.cc", "system/hotspot/hotspot_tray_view.h", "system/human_presence/human_presence_metrics.h", @@ -1601,8 +1608,6 @@ "system/network/fake_network_list_network_header_view_delegate.h", "system/network/fake_network_list_wifi_header_view.cc", "system/network/fake_network_list_wifi_header_view.h", - "system/network/hotspot_notifier.cc", - "system/network/hotspot_notifier.h", "system/network/managed_sim_lock_notifier.cc", "system/network/managed_sim_lock_notifier.h", "system/network/network_detailed_network_view.cc", @@ -3279,7 +3284,9 @@ "system/hotspot/hotspot_detailed_view_controller_unittest.cc", "system/hotspot/hotspot_detailed_view_unittest.cc", "system/hotspot/hotspot_feature_pod_controller_unittest.cc", + "system/hotspot/hotspot_icon_unittest.cc", "system/hotspot/hotspot_info_cache_unittest.cc", + "system/hotspot/hotspot_notifier_unittest.cc", "system/hotspot/hotspot_tray_view_unittest.cc", "system/human_presence/human_presence_orientation_controller_unittest.cc", "system/human_presence/lock_on_leave_controller_unittest.cc", @@ -3328,7 +3335,6 @@ "system/network/active_network_icon_unittest.cc", "system/network/auto_connect_notifier_unittest.cc", "system/network/cellular_setup_notifier_unittest.cc", - "system/network/hotspot_notifier_unittest.cc", "system/network/managed_sim_lock_notifier_unittest.cc", "system/network/network_detailed_network_view_unittest.cc", "system/network/network_detailed_view_controller_unittest.cc",
diff --git a/ash/app_list/app_list_bubble_presenter.cc b/ash/app_list/app_list_bubble_presenter.cc index 1d57bde..3fb0a0df 100644 --- a/ash/app_list/app_list_bubble_presenter.cc +++ b/ash/app_list/app_list_bubble_presenter.cc
@@ -7,7 +7,6 @@ #include <algorithm> #include <memory> #include <utility> -#include <vector> #include "ash/app_list/app_list_bubble_event_filter.h" #include "ash/app_list/app_list_controller_impl.h" @@ -43,7 +42,6 @@ #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/wm/core/coordinate_conversion.h" -#include "ui/wm/core/transient_window_manager.h" #include "ui/wm/public/activation_client.h" namespace ash { @@ -316,22 +314,6 @@ if (bubble_view_) { aura::Window* bubble_window = bubble_view_->GetWidget()->GetNativeWindow(); DCHECK(bubble_window); - - // Close all transient child windows in the app list (e.g. uninstall dialog) - // when the app list is dismissed. - auto* manager = ::wm::TransientWindowManager::GetOrCreate(bubble_window); - if (manager) { - std::vector<aura::Window*> children = manager->transient_children(); - for (auto* child : children) { - views::Widget* child_widget = - views::Widget::GetWidgetForNativeWindow(child); - if (child_widget) { - child_widget->CloseWithReason( - views::Widget::ClosedReason::kUnspecified); - } - } - } - Shelf* shelf = Shelf::ForWindow(bubble_window); const bool is_side_shelf = !shelf->IsHorizontalAlignment(); bubble_view_->StartHideAnimation(
diff --git a/ash/app_list/app_list_bubble_presenter_unittest.cc b/ash/app_list/app_list_bubble_presenter_unittest.cc index 9870be3..ded22f4 100644 --- a/ash/app_list/app_list_bubble_presenter_unittest.cc +++ b/ash/app_list/app_list_bubble_presenter_unittest.cc
@@ -41,7 +41,6 @@ #include "ui/gfx/geometry/vector2d.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/widget/widget.h" -#include "ui/wm/core/window_util.h" using views::Widget; @@ -636,35 +635,6 @@ EXPECT_TRUE(presenter->IsShowing()); } -TEST_F(AppListBubblePresenterTest, ClosingBubbleAlsoCloseChildWidget) { - AppListBubblePresenter* presenter = GetBubblePresenter(); - presenter->Show(GetPrimaryDisplay().id()); - - // Create a new widget parented to the bubble, similar to an app uninstall - // confirmation dialog. - aura::Window* bubble_window = - presenter->bubble_widget_for_test()->GetNativeWindow(); - std::unique_ptr<views::Widget> widget = TestWidgetBuilder() - .SetShow(true) - .SetParent(bubble_window) - .BuildOwnsNativeWidget(); - - // Open the bubble launcher and check the widget is showing. - EXPECT_TRUE(presenter->IsShowing()); - EXPECT_TRUE(base::Contains(wm::GetTransientChildren(bubble_window), - widget->GetNativeWindow())); - - // Close the bubble and reopen it. - presenter->Dismiss(); - base::RunLoop().RunUntilIdle(); - - presenter->Show(GetPrimaryDisplay().id()); - // The child widget is closed now. - EXPECT_TRUE(presenter->IsShowing()); - EXPECT_FALSE(base::Contains(wm::GetTransientChildren(bubble_window), - widget->GetNativeWindow())); -} - // Regression test for https://crbug.com/1285443. TEST_F(AppListBubblePresenterTest, CanOpenBubbleThenOpenSystemTray) { // Enable animations.
diff --git a/ash/app_list/views/app_list_item_view.cc b/ash/app_list/views/app_list_item_view.cc index a6ef3e3..f2bdf6a 100644 --- a/ash/app_list/views/app_list_item_view.cc +++ b/ash/app_list/views/app_list_item_view.cc
@@ -30,6 +30,8 @@ #include "ash/style/dot_indicator.h" #include "ash/style/style_util.h" #include "ash/style/typography.h" +#include "ash/user_education/user_education_class_properties.h" +#include "ash/user_education/user_education_controller.h" #include "base/auto_reset.h" #include "base/check.h" #include "base/functional/bind.h" @@ -40,6 +42,7 @@ #include "base/time/time.h" #include "cc/paint/paint_flags.h" #include "chromeos/constants/chromeos_features.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/accessibility/ax_node_data.h" @@ -73,6 +76,7 @@ #include "ui/views/controls/label.h" #include "ui/views/controls/menu/menu_runner.h" #include "ui/views/focus/focus_manager.h" +#include "ui/views/view_class_properties.h" #include "ui/views/view_utils.h" #include "ui/views/widget/widget.h" @@ -606,6 +610,17 @@ SetAnimationDuration(base::TimeDelta()); preview_circle_radius_ = 0; + + if (features::IsUserEducationEnabled() && context == Context::kAppsGridView) { + if (absl::optional<ui::ElementIdentifier> element_identifier = + UserEducationController::Get()->GetElementIdentifierForAppId( + item->id())) { + // NOTE: Set `kHelpBubbleContextKey` before `views::kElementIdentifierKey` + // in case registration causes a help bubble to be created synchronously. + SetProperty(kHelpBubbleContextKey, HelpBubbleContext::kAsh); + SetProperty(views::kElementIdentifierKey, *element_identifier); + } + } } void AppListItemView::InitializeIconLoader() {
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc index e04c9a4..6a6c993 100644 --- a/ash/app_list/views/apps_grid_view_unittest.cc +++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -309,12 +309,6 @@ disabled_features.push_back(features::kAppCollectionFolderRefresh); } - if (enable_shelf_party_) { - enabled_features.push_back(features::kShelfParty); - } else { - disabled_features.push_back(features::kShelfParty); - } - scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); AshTestBase::SetUp(); @@ -750,8 +744,6 @@ bool use_drag_drop_refactor_ = false; // True if the folder icon refresh feature is enabled. bool folder_icon_refresh_ = false; - // True shelf part feature is enabled. - bool enable_shelf_party_ = true; std::unique_ptr<PageFlipWaiter> page_flip_waiter_; @@ -866,20 +858,6 @@ INSTANTIATE_TEST_SUITE_P(All, AppsGridViewDragLegacyTest, testing::Bool()); -class AppsGridViewDragWithShelfPartyTest : public AppsGridViewDragLegacyTest { - public: - AppsGridViewDragWithShelfPartyTest() { enable_shelf_party_ = true; } - AppsGridViewDragWithShelfPartyTest( - const AppsGridViewDragWithShelfPartyTest&) = delete; - AppsGridViewDragWithShelfPartyTest& operator=( - const AppsGridViewDragWithShelfPartyTest&) = delete; - ~AppsGridViewDragWithShelfPartyTest() override = default; -}; - -INSTANTIATE_TEST_SUITE_P(All, - AppsGridViewDragWithShelfPartyTest, - testing::Bool()); - // Test suite for clamshell mode, parameterized by RTL. class AppsGridViewClamshellTest : public AppsGridViewTest, public testing::WithParamInterface<bool> { @@ -4699,39 +4677,6 @@ EXPECT_TRUE(ShelfModel::Get()->items().empty()); } -TEST_P(AppsGridViewDragWithShelfPartyTest, DragAndPinItemToEmptyShelf) { - GetTestModel()->PopulateApps(2); - UpdateLayout(); - - ShelfModel::Get()->ToggleShelfParty(); - - AppListItemView* const item_view = GetItemViewInTopLevelGrid(1); - - InitiateDragForItemAtCurrentPageAt(AppsGridView::MOUSE, 0, 1, - apps_grid_view_); - - MaybeCheckHaptickEventsCount(1); - - // Verify that item drag has started. - ASSERT_TRUE(apps_grid_view_->drag_item()); - ASSERT_TRUE(apps_grid_view_->IsDragging()); - ASSERT_EQ(item_view->item(), apps_grid_view_->drag_item()); - - // Shelf should start handling the drag if it moves within its bounds. - auto* shelf_view = GetPrimaryShelf()->GetShelfViewForTesting(); - UpdateDragInScreen(AppsGridView::MOUSE, - shelf_view->GetBoundsInScreen().left_center()); - ASSERT_TRUE(apps_grid_view_->FireDragToShelfTimerForTest()); - - EXPECT_EQ("Item 1", shelf_view->drag_and_drop_shelf_id().app_id); - - // Releasing drag over shelf should pin the dragged app. - EndDrag(); - EXPECT_TRUE(ShelfModel::Get()->IsAppPinned("Item 1")); - EXPECT_EQ("Item 1", ShelfModel::Get()->items()[0].id.app_id); - MaybeCheckHaptickEventsCount(1); -} - TEST_P(AppsGridViewDragTest, MousePointerIsGrabbingDuringDrag) { auto* cursor_manager = Shell::Get()->cursor_manager(); auto previous_cursor_type = cursor_manager->GetCursor().type();
diff --git a/ash/capture_mode/capture_mode_behavior.cc b/ash/capture_mode/capture_mode_behavior.cc index 018b2cb0..3adb2cc 100644 --- a/ash/capture_mode/capture_mode_behavior.cc +++ b/ash/capture_mode/capture_mode_behavior.cc
@@ -235,15 +235,21 @@ bool ShouldGifBeSupported() const override { return false; } bool ShouldShowUserNudge() const override { return false; } bool ShouldAutoSelectFirstCamera() const override { return true; } + std::unique_ptr<CaptureModeBarView> CreateCaptureModeBarView() override { return std::make_unique<GameCaptureBarView>(); } + void SetPreSelectedWindow(aura::Window* pre_selected_window) override { CHECK(!pre_selected_window_); pre_selected_window_ = pre_selected_window; pre_selected_window_->AddObserver(this); } + const char* GetClientMetricComponent() const override { + return "GameDashboard."; + } + std::vector<message_center::ButtonInfo> GetNotificationButtonsInfo( bool for_video) const override { CHECK(for_video);
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index 8c06a43..6b876c8 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -1417,10 +1417,13 @@ CopyImageToClipboard(image); // TODO(michelefan): Do not hard-code `BehaviorType::kDefault`. Screenshot // notification should be separated among different behaviors. + CaptureModeBehavior* behavior = GetBehavior(BehaviorType::kDefault); ShowPreviewNotification(file_saved_path, image, CaptureModeType::kImage, - GetBehavior(BehaviorType::kDefault)); - if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) - RecordSaveToLocation(GetSaveToOption(file_saved_path)); + behavior); + if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) { + RecordSaveToLocation(GetSaveToOption(file_saved_path), behavior); + } + // NOTE: Holding space `client` may be `nullptr` in tests. if (auto* client = HoldingSpaceController::Get()->client()) { client->AddItemOfType(HoldingSpaceItem::Type::kScreenshot, file_saved_path); @@ -1454,14 +1457,15 @@ // DriveFs. blocking_task_runner_->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&GetFileSizeInKB, saved_video_file_path), - base::BindOnce(&RecordVideoFileSizeKB, is_gif)); + base::BindOnce(&RecordVideoFileSizeKB, is_gif, behavior)); } CHECK(!recording_start_time_.is_null()); RecordCaptureModeRecordingDuration( (base::TimeTicks::Now() - recording_start_time_), behavior, is_gif); } - if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) - RecordSaveToLocation(GetSaveToOption(saved_video_file_path)); + if (Shell::Get()->session_controller()->IsActiveUserSessionStarted()) { + RecordSaveToLocation(GetSaveToOption(saved_video_file_path), behavior); + } if (on_file_saved_callback_for_test_) std::move(on_file_saved_callback_for_test_).Run(saved_video_file_path);
diff --git a/ash/capture_mode/capture_mode_game_dashboard_unittests.cc b/ash/capture_mode/capture_mode_game_dashboard_unittests.cc index 994bf2f..33945a2 100644 --- a/ash/capture_mode/capture_mode_game_dashboard_unittests.cc +++ b/ash/capture_mode/capture_mode_game_dashboard_unittests.cc
@@ -21,6 +21,7 @@ #include "ash/style/pill_button.h" #include "ash/test/ash_test_base.h" #include "base/system/sys_info.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "chromeos/ui/base/window_properties.h" #include "ui/base/l10n/l10n_util.h" @@ -407,4 +408,197 @@ controller->Stop(); } +// ----------------------------------------------------------------------------- +// GameDashboardCaptureModeHistogramTest: +// Test fixture to verify game dashboard initiated screen capture histograms +// depending on the test param (true for tablet mode, false for clamshell mode). + +class GameDashboardCaptureModeHistogramTest + : public GameDashboardCaptureModeTest, + public ::testing::WithParamInterface<bool> { + public: + GameDashboardCaptureModeHistogramTest() = default; + ~GameDashboardCaptureModeHistogramTest() override = default; + + // GameDashboardCaptureModeTest: + void SetUp() override { + GameDashboardCaptureModeTest::SetUp(); + if (GetParam()) { + SwitchToTabletMode(); + } + } + + protected: + base::HistogramTester histogram_tester_; +}; + +TEST_P(GameDashboardCaptureModeHistogramTest, + GameCaptureConfigurationHistogram) { + constexpr char kCaptureConfigurationBase[] = "CaptureConfiguration"; + CaptureModeTestApi test_api; + + // TODO(michelefan): Add metric test for `kImage` capture configuration for + // game dashboard capture mode once the default and game capture behaviors for + // taking instant screenshot APIs are separated. + const std::string histogram_name = + BuildHistogramName(kCaptureConfigurationBase, + test_api.GetBehavior(BehaviorType::kGameDashboard), + /*append_ui_mode_suffix=*/true); + histogram_tester_.ExpectBucketCount( + histogram_name, + GetConfiguration(CaptureModeType::kVideo, CaptureModeSource::kWindow, + RecordingType::kWebM), + 0); + auto* controller = StartGameCaptureModeSession(); + StartVideoRecordingImmediately(); + EXPECT_TRUE(controller->is_recording_in_progress()); + test_api.StopVideoRecording(); + WaitForCaptureFileToBeSaved(); + EXPECT_FALSE(controller->is_recording_in_progress()); + histogram_tester_.ExpectBucketCount( + histogram_name, + GetConfiguration(CaptureModeType::kVideo, CaptureModeSource::kWindow, + RecordingType::kWebM), + 1); +} + +TEST_P(GameDashboardCaptureModeHistogramTest, + GameScreenRecordingLengthHistogram) { + constexpr char kRecordLenthHistogramBase[] = "ScreenRecordingLength"; + + auto* controller = StartGameCaptureModeSession(); + StartVideoRecordingImmediately(); + EXPECT_TRUE(controller->is_recording_in_progress()); + WaitForSeconds(/*seconds=*/1); + + CaptureModeTestApi test_api; + test_api.StopVideoRecording(); + EXPECT_FALSE(controller->is_recording_in_progress()); + WaitForCaptureFileToBeSaved(); + + histogram_tester_.ExpectUniqueSample( + BuildHistogramName(kRecordLenthHistogramBase, + test_api.GetBehavior(BehaviorType::kGameDashboard), + /*append_ui_mode_suffix=*/true), + /*sample=*/1, /*expected_bucket_count=*/1); +} + +TEST_P(GameDashboardCaptureModeHistogramTest, + GameScreenRecordingFileSizeHistogram) { + constexpr char kHistogramNameBase[] = "ScreenRecordingFileSize"; + + CaptureModeTestApi test_api; + const auto histogram_name = BuildHistogramName( + kHistogramNameBase, test_api.GetBehavior(BehaviorType::kGameDashboard), + /*append_ui_mode_suffix=*/true); + histogram_tester_.ExpectTotalCount(histogram_name, /*expected_count=*/0); + + StartGameCaptureModeSession(); + StartVideoRecordingImmediately(); + test_api.StopVideoRecording(); + WaitForCaptureFileToBeSaved(); + + // Since getting the file size is an async operation, we have to run a loop + // until the task that records the file size is done. + base::RunLoop().RunUntilIdle(); + histogram_tester_.ExpectTotalCount(histogram_name, + /*expected_count=*/1); +} + +TEST_P(GameDashboardCaptureModeHistogramTest, GameSaveToLocationHistogram) { + constexpr char kHistogramNameBase[] = "SaveLocation"; + + CaptureModeTestApi test_api; + const auto histogram_name = BuildHistogramName( + kHistogramNameBase, test_api.GetBehavior(BehaviorType::kGameDashboard), + /*append_ui_mode_suffix=*/true); + + auto* test_delegate = CaptureModeController::Get()->delegate_for_testing(); + + // Initialize four different save-to locations for screen capture that + // includes default downloads folder, local customized folder, root drive and + // a specific folder on drive. + const auto downloads_folder = test_delegate->GetUserDefaultDownloadsFolder(); + const base::FilePath custom_folder = + CreateCustomFolderInUserDownloadsPath("test"); + base::FilePath mount_point_path; + test_delegate->GetDriveFsMountPointPath(&mount_point_path); + const auto root_drive_folder = mount_point_path.Append("root"); + const base::FilePath non_root_drive_folder = CreateFolderOnDriveFS("test"); + + struct { + base::FilePath set_save_file_folder; + CaptureModeSaveToLocation save_location; + } kTestCases[] = { + {downloads_folder, CaptureModeSaveToLocation::kDefault}, + {custom_folder, CaptureModeSaveToLocation::kCustomizedFolder}, + {root_drive_folder, CaptureModeSaveToLocation::kDrive}, + {non_root_drive_folder, CaptureModeSaveToLocation::kDriveFolder}, + }; + + for (auto test_case : kTestCases) { + histogram_tester_.ExpectBucketCount(histogram_name, test_case.save_location, + 0); + auto* controller = StartGameCaptureModeSession(); + controller->SetCustomCaptureFolder(test_case.set_save_file_folder); + StartVideoRecordingImmediately(); + test_api.StopVideoRecording(); + auto file_saved_path = WaitForCaptureFileToBeSaved(); + histogram_tester_.ExpectBucketCount(histogram_name, test_case.save_location, + 1); + } +} + +TEST_P(GameDashboardCaptureModeHistogramTest, + GameRecordingStartsWithCameraHistogram) { + UpdateDisplay("1000x700"); + constexpr char kHistogramNameBase[] = "RecordingStartsWithCamera"; + AddDefaultCamera(); + + for (const auto camera_on : {true, false}) { + CaptureModeTestApi test_api; + const std::string histogram_name = BuildHistogramName( + kHistogramNameBase, test_api.GetBehavior(BehaviorType::kGameDashboard), + /*append_ui_mode_suffix=*/true); + histogram_tester_.ExpectBucketCount(histogram_name, camera_on, 0); + + auto* controller = StartGameCaptureModeSession(); + EXPECT_EQ(controller->type(), CaptureModeType::kVideo); + auto* camera_controller = controller->camera_controller(); + if (!camera_on) { + camera_controller->SetSelectedCamera(CameraId()); + } + test_api.PerformCapture(); + WaitForRecordingToStart(); + EXPECT_TRUE(controller->is_recording_in_progress()); + + test_api.StopVideoRecording(); + EXPECT_FALSE(controller->is_recording_in_progress()); + WaitForCaptureFileToBeSaved(); + histogram_tester_.ExpectBucketCount(histogram_name, camera_on, 1); + } +} + +TEST_P(GameDashboardCaptureModeHistogramTest, + GameDemoToolsEnabledOnRecordingHistogram) { + constexpr char kHistogramNameBase[] = "DemoToolsEnabledOnRecordingStart"; + CaptureModeTestApi test_api; + for (const auto enable_demo_tools : {false, true}) { + const auto histogram_name = BuildHistogramName( + kHistogramNameBase, test_api.GetBehavior(BehaviorType::kGameDashboard), + /*append_ui_mode_suffix=*/true); + histogram_tester_.ExpectBucketCount(histogram_name, enable_demo_tools, 0); + auto* controller = StartGameCaptureModeSession(); + controller->EnableDemoTools(enable_demo_tools); + StartVideoRecordingImmediately(); + test_api.StopVideoRecording(); + WaitForCaptureFileToBeSaved(); + histogram_tester_.ExpectBucketCount(histogram_name, enable_demo_tools, 1); + } +} + +INSTANTIATE_TEST_SUITE_P(All, + GameDashboardCaptureModeHistogramTest, + ::testing::Bool()); + } // namespace ash
diff --git a/ash/capture_mode/capture_mode_metrics.cc b/ash/capture_mode/capture_mode_metrics.cc index 94dffac..fd5bbd3 100644 --- a/ash/capture_mode/capture_mode_metrics.cc +++ b/ash/capture_mode/capture_mode_metrics.cc
@@ -126,7 +126,9 @@ recording_duration); } -void RecordVideoFileSizeKB(bool is_gif, int size_in_kb) { +void RecordVideoFileSizeKB(bool is_gif, + const CaptureModeBehavior* behavior, + int size_in_kb) { if (!Shell::HasInstance()) { // This function can be called asynchronously after the `Shell` instance had // already been destroyed. @@ -141,7 +143,7 @@ base::UmaHistogramMemoryKB( BuildHistogramName(is_gif ? kGifRecordingFileSizeRootWord : kScreenRecordingFileSizeRootWord, - /*behavior=*/nullptr, /*append_ui_mode_suffix=*/true), + behavior, /*append_ui_mode_suffix=*/true), size_in_kb); } @@ -193,9 +195,15 @@ action); } -void RecordSaveToLocation(CaptureModeSaveToLocation save_location) { +void RecordSaveToLocation(CaptureModeSaveToLocation save_location, + const CaptureModeBehavior* behavior) { + // Save-to location metrics should not be recorded for the + // projector-inititated capture mode session. + const CaptureModeBehavior* modified_behavior = + behavior->behavior_type() == BehaviorType::kProjector ? nullptr + : behavior; base::UmaHistogramEnumeration( - BuildHistogramName(kSaveToLocationHistogramRootWord, /*behavior=*/nullptr, + BuildHistogramName(kSaveToLocationHistogramRootWord, modified_behavior, /*append_ui_mode_suffix=*/true), save_location); }
diff --git a/ash/capture_mode/capture_mode_metrics.h b/ash/capture_mode/capture_mode_metrics.h index 5237d1a..d24861b 100644 --- a/ash/capture_mode/capture_mode_metrics.h +++ b/ash/capture_mode/capture_mode_metrics.h
@@ -155,7 +155,9 @@ // Records the given video file `size_in_kb`. The used histogram will depend on // whether this video file was GIF or WebM. -void RecordVideoFileSizeKB(bool is_gif, int size_in_kb); +void RecordVideoFileSizeKB(bool is_gif, + const CaptureModeBehavior* behavior, + int size_in_kb); // Records if the user has switched modes during a capture session. void RecordCaptureModeSwitchesFromInitialMode(bool switched); @@ -185,7 +187,8 @@ void RecordScreenshotNotificationQuickAction(CaptureQuickAction action); // Records the location where screen capture is saved. -void RecordSaveToLocation(CaptureModeSaveToLocation save_location); +void RecordSaveToLocation(CaptureModeSaveToLocation save_location, + const CaptureModeBehavior* behavior); // Records the `reason` for which the capture folder is switched to default // downloads folder.
diff --git a/ash/capture_mode/capture_mode_test_util.cc b/ash/capture_mode/capture_mode_test_util.cc index 1bee8bf..14da397 100644 --- a/ash/capture_mode/capture_mode_test_util.cc +++ b/ash/capture_mode/capture_mode_test_util.cc
@@ -144,6 +144,18 @@ return custom_folder; } +base::FilePath CreateFolderOnDriveFS(const std::string& custom_folder_name) { + auto* test_delegate = CaptureModeController::Get()->delegate_for_testing(); + base::FilePath mount_point_path; + EXPECT_TRUE(test_delegate->GetDriveFsMountPointPath(&mount_point_path)); + base::FilePath folder_on_drive_fs = + mount_point_path.Append("root").Append(custom_folder_name); + base::ScopedAllowBlockingForTesting allow_blocking; + const bool result = base::CreateDirectory(folder_on_drive_fs); + EXPECT_TRUE(result); + return folder_on_drive_fs; +} + void SendKey(ui::KeyboardCode key_code, ui::test::EventGenerator* event_generator, int flags,
diff --git a/ash/capture_mode/capture_mode_test_util.h b/ash/capture_mode/capture_mode_test_util.h index f2df8f7..d757efad 100644 --- a/ash/capture_mode/capture_mode_test_util.h +++ b/ash/capture_mode/capture_mode_test_util.h
@@ -89,6 +89,10 @@ base::FilePath CreateCustomFolderInUserDownloadsPath( const std::string& custom_folder_name); +// Creates and returns the custom folder path on driveFS. The custom folder is +// created in the root folder with given `custom_folder_name`. +base::FilePath CreateFolderOnDriveFS(const std::string& custom_folder_name); + // Sends a press release key combo `count` times. void SendKey(ui::KeyboardCode key_code, ui::test::EventGenerator* event_generator,
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc index 74dd8fe9e..f28fd20 100644 --- a/ash/capture_mode/capture_mode_unittests.cc +++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -332,18 +332,6 @@ session_controller->SwitchActiveUser(AccountId::FromUserEmail(kUserEmail)); } - base::FilePath CreateFolderOnDriveFS(const std::string& custom_folder_name) { - auto* test_delegate = CaptureModeController::Get()->delegate_for_testing(); - base::FilePath mount_point_path; - EXPECT_TRUE(test_delegate->GetDriveFsMountPointPath(&mount_point_path)); - base::FilePath folder_on_drive_fs = - mount_point_path.Append("root").Append(custom_folder_name); - base::ScopedAllowBlockingForTesting allow_blocking; - const bool result = base::CreateDirectory(folder_on_drive_fs); - EXPECT_TRUE(result); - return folder_on_drive_fs; - } - void OpenSettingsView() { CaptureModeSession* session = CaptureModeController::Get()->capture_mode_session();
diff --git a/ash/clipboard/clipboard_nudge_constants.cc b/ash/clipboard/clipboard_nudge_constants.cc index 891d52c9..f079553 100644 --- a/ash/clipboard/clipboard_nudge_constants.cc +++ b/ash/clipboard/clipboard_nudge_constants.cc
@@ -26,4 +26,27 @@ "Ash.ClipboardHistory.Nudges.ScreenshotNotificationNudge." "ToFeaturePasteTime"; +const char* GetClipboardHistoryPasteTimeDeltaHistogram( + ClipboardNudgeType type) { + switch (type) { + case ClipboardNudgeType::kOnboardingNudge: + return kClipboardHistoryOnboardingNudgePasteTime; + case ClipboardNudgeType::kZeroStateNudge: + return kClipboardHistoryZeroStateNudgePasteTime; + case ClipboardNudgeType::kScreenshotNotificationNudge: + return kClipboardHistoryScreenshotNotificationPasteTime; + } +} + +const char* GetMenuOpenTimeDeltaHistogram(ClipboardNudgeType type) { + switch (type) { + case ClipboardNudgeType::kOnboardingNudge: + return kClipboardHistoryOnboardingNudgeOpenTime; + case ClipboardNudgeType::kZeroStateNudge: + return kClipboardHistoryZeroStateNudgeOpenTime; + case ClipboardNudgeType::kScreenshotNotificationNudge: + return kClipboardHistoryScreenshotNotificationOpenTime; + } +} + } // namespace ash
diff --git a/ash/clipboard/clipboard_nudge_constants.h b/ash/clipboard/clipboard_nudge_constants.h index 92584aa9..a186df3 100644 --- a/ash/clipboard/clipboard_nudge_constants.h +++ b/ash/clipboard/clipboard_nudge_constants.h
@@ -14,12 +14,17 @@ // Onboarding nudge. Shows when a user copy and pastes repeatedly within a // time frame. kOnboardingNudge = 0, + // Shows when the keyboard shortcut for clipboard is pressed with no items // in the history. kZeroStateNudge = 1, + // Shows the keyboard shortcut for clipboard history in the screenshot // notification nudge. kScreenshotNotificationNudge = 2, + + // NOTE: Need to update when adding a new nudge type. + kMax = kScreenshotNotificationNudge, }; ASH_EXPORT extern const char* const kClipboardHistoryOnboardingNudgeShowCount; @@ -35,6 +40,15 @@ ASH_EXPORT extern const char* const kClipboardHistoryScreenshotNotificationPasteTime; +// Returns the histogram that records the time delta between showing the nudge +// of `type` and pasting clipboard history data. +ASH_EXPORT const char* GetClipboardHistoryPasteTimeDeltaHistogram( + ClipboardNudgeType type); + +// Returns the histogram that records the time delta between showing the nudge +// of `type` and showing the clipboard history menu. +ASH_EXPORT const char* GetMenuOpenTimeDeltaHistogram(ClipboardNudgeType type); + constexpr int kNotificationLimit = 3; constexpr int kContextMenuBadgeShowLimit = 3; constexpr base::TimeDelta kMinInterval = base::Days(1);
diff --git a/ash/clipboard/clipboard_nudge_controller.cc b/ash/clipboard/clipboard_nudge_controller.cc index 4b6e142..4763c84 100644 --- a/ash/clipboard/clipboard_nudge_controller.cc +++ b/ash/clipboard/clipboard_nudge_controller.cc
@@ -42,33 +42,6 @@ return g_clock_override ? g_clock_override->Now() : base::Time::Now(); } -// Returns the histogram that records the time delta between showing the nudge -// of `type` and pasting clipboard history data. -const char* GetClipboardHistoryPasteTimeDeltaHistogram( - ClipboardNudgeType type) { - switch (type) { - case ClipboardNudgeType::kOnboardingNudge: - return kClipboardHistoryOnboardingNudgePasteTime; - case ClipboardNudgeType::kZeroStateNudge: - return kClipboardHistoryZeroStateNudgePasteTime; - case ClipboardNudgeType::kScreenshotNotificationNudge: - return kClipboardHistoryScreenshotNotificationPasteTime; - } -} - -// Returns the histogram that records the time delta between showing the nudge -// of `type` and showing the clipboard history menu. -const char* GetMenuOpenTimeDeltaHistogram(ClipboardNudgeType type) { - switch (type) { - case ClipboardNudgeType::kOnboardingNudge: - return kClipboardHistoryOnboardingNudgeOpenTime; - case ClipboardNudgeType::kZeroStateNudge: - return kClipboardHistoryZeroStateNudgeOpenTime; - case ClipboardNudgeType::kScreenshotNotificationNudge: - return kClipboardHistoryScreenshotNotificationOpenTime; - } -} - NudgeCatalogName GetCatalogName(ClipboardNudgeType type) { switch (type) { case kOnboardingNudge: @@ -282,11 +255,9 @@ zero_state_nudge_recorder_.OnClipboardHistoryMenuShown(); screenshot_nudge_recorder_.OnClipboardHistoryMenuShown(); - // These metrics will not be recorded if the respective nudges have not been - // shown before. - SystemNudgeController::RecordNudgeAction( + SystemNudgeController::MaybeRecordNudgeAction( NudgeCatalogName::kClipboardHistoryOnboarding); - SystemNudgeController::RecordNudgeAction( + SystemNudgeController::MaybeRecordNudgeAction( NudgeCatalogName::kClipboardHistoryZeroState); }
diff --git a/ash/clipboard/clipboard_nudge_controller_unittest.cc b/ash/clipboard/clipboard_nudge_controller_unittest.cc index 619dc2e1..c36bf02 100644 --- a/ash/clipboard/clipboard_nudge_controller_unittest.cc +++ b/ash/clipboard/clipboard_nudge_controller_unittest.cc
@@ -4,6 +4,10 @@ #include "ash/clipboard/clipboard_nudge_controller.h" +#include <array> +#include <memory> +#include <utility> + #include "ash/clipboard/clipboard_history.h" #include "ash/clipboard/clipboard_history_controller_impl.h" #include "ash/clipboard/clipboard_nudge.h" @@ -32,6 +36,13 @@ using crosapi::mojom::ClipboardHistoryControllerShowSource::kAccelerator; +// The array of all clipboard nudge types. +constexpr std::array<ClipboardNudgeType, ClipboardNudgeType::kMax + 1> + kAllClipboardNudgeTypes = { + ClipboardNudgeType::kOnboardingNudge, + ClipboardNudgeType::kZeroStateNudge, + ClipboardNudgeType::kScreenshotNotificationNudge}; + } // namespace class ClipboardNudgeControllerTest : public AshTestBase { @@ -266,190 +277,6 @@ kClipboardHistoryScreenshotNotificationPasteTime, 0); } -// Tests that opening the clipboard history after showing the nudges logs only -// the metrics for the open time histograms. -TEST_F(ClipboardNudgeControllerTest, ShowMenuAfterNudges_LogsOpenNudgeMetrics) { - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - - constexpr int kFastForwardSeconds = 2; - clock()->Advance(base::Seconds(kFastForwardSeconds)); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - - histograms().ExpectBucketCount(kClipboardHistoryOnboardingNudgeOpenTime, - kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount(kClipboardHistoryZeroStateNudgeOpenTime, - kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount( - kClipboardHistoryScreenshotNotificationOpenTime, kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 0); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 0); -} - -// Tests that pasting something from the clipboard history after showing the -// nudges only the metrics for the paste time histograms. -TEST_F(ClipboardNudgeControllerTest, PasteAfterNudges_LogsPasteNudgeMetrics) { - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - - constexpr int kFastForwardSeconds = 2; - clock()->Advance(base::Seconds(kFastForwardSeconds)); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - - histograms().ExpectBucketCount(kClipboardHistoryOnboardingNudgeOpenTime, - kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount(kClipboardHistoryZeroStateNudgeOpenTime, - kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount( - kClipboardHistoryScreenshotNotificationOpenTime, kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount(kClipboardHistoryOnboardingNudgePasteTime, - kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount(kClipboardHistoryZeroStateNudgePasteTime, - kFastForwardSeconds, - /*expected_count=*/1); - histograms().ExpectBucketCount( - kClipboardHistoryScreenshotNotificationPasteTime, kFastForwardSeconds, - /*expected_count=*/1); -} - -// Tests that the onboarding nudge being shown only logs the metrics for the -// onboarding nudge histograms. -TEST_F(ClipboardNudgeControllerTest, OnboardingNudge_DoesNotLogOtherMetrics) { - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgeOpenTime, 1); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgeOpenTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryScreenshotNotificationOpenTime, - 0); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 1); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 0); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 0); -} - -// Tests that the zero state nudge being shown only logs the metrics for the -// zero state nudge histograms. -TEST_F(ClipboardNudgeControllerTest, ZeroStateNudge_DoesNotLogOtherMetrics) { - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgeOpenTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgeOpenTime, 1); - histograms().ExpectTotalCount(kClipboardHistoryScreenshotNotificationOpenTime, - 0); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 1); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 0); -} - -// Tests that the screenshot notification nudge being shown only logs the -// metrics for the screenshot notification nudge histograms. -TEST_F(ClipboardNudgeControllerTest, - ScreenshotNotification_DoesNotLogOtherMetrics) { - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgeOpenTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgeOpenTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryScreenshotNotificationOpenTime, - 1); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 0); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 1); -} - -// Tests that nudge metrics will not log multiple times if the nudges are not -// shown before. -TEST_F(ClipboardNudgeControllerTest, SecondTimeAction_DoesNotLogNudgeMetrics) { - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgeOpenTime, 1); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgeOpenTime, 1); - histograms().ExpectTotalCount(kClipboardHistoryScreenshotNotificationOpenTime, - 1); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 1); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 1); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 1); -} - -// Tests that nudge metrics can log more times as the nudges are shown before. -TEST_F(ClipboardNudgeControllerTest, ShowNudgeTwice_LogsMetricsTwoTimes) { - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); - nudge_controller_->OnClipboardHistoryPasted(); - - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgeOpenTime, 2); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgeOpenTime, 2); - histograms().ExpectTotalCount(kClipboardHistoryScreenshotNotificationOpenTime, - 2); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 2); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 2); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 2); -} - -// Tests that showing clipboard history from a source other than the accelerator -// does not log any metrics, because the nudge only mentions the accelerator as -// an option for opening the menu. -TEST_F(ClipboardNudgeControllerTest, - NonAcceleratorShowMenuAfterNudges_DoesNotLogNudgeMetrics) { - using crosapi::mojom::ClipboardHistoryControllerShowSource; - - ShowNudgeForType(ClipboardNudgeType::kOnboardingNudge); - ShowNudgeForType(ClipboardNudgeType::kZeroStateNudge); - ShowNudgeForType(ClipboardNudgeType::kScreenshotNotificationNudge); - for (size_t i = - static_cast<size_t>(ClipboardHistoryControllerShowSource::kMinValue); - i < static_cast<size_t>(ClipboardHistoryControllerShowSource::kMaxValue); - ++i) { - auto show_source = static_cast<ClipboardHistoryControllerShowSource>(i); - if (show_source != kAccelerator) { - nudge_controller_->OnClipboardHistoryMenuShown(show_source); - } - } - - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgeOpenTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgeOpenTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryScreenshotNotificationOpenTime, - 0); - histograms().ExpectTotalCount(kClipboardHistoryOnboardingNudgePasteTime, 0); - histograms().ExpectTotalCount(kClipboardHistoryZeroStateNudgePasteTime, 0); - histograms().ExpectTotalCount( - kClipboardHistoryScreenshotNotificationPasteTime, 0); -} - // Tests that nudge `TimeToAction` metric is logged after the nudge has been // shown and clipboard history is opened through the accelerator. TEST_F(ClipboardNudgeControllerTest, TimeToActionMetric) { @@ -481,4 +308,153 @@ kOnboardingCatalogName, 1); } +// A parameterized test base to verify metric recording for each type of nudge. +class ClipboardNudgeMetricTest + : public ClipboardNudgeControllerTest, + public testing::WithParamInterface<ClipboardNudgeType> { + public: + ClipboardNudgeType GetNudgeType() const { return GetParam(); } +}; + +INSTANTIATE_TEST_SUITE_P( + All, + ClipboardNudgeMetricTest, + /*nudge_type=*/testing::ValuesIn(kAllClipboardNudgeTypes)); + +// Tests that the metrics are recorded as expected when opening the standalone +// clipboard history menu after a nudge shown. +TEST_P(ClipboardNudgeMetricTest, ShowMenuAfterNudgeShown) { + const ClipboardNudgeType type_being_tested = GetNudgeType(); + ShowNudgeForType(type_being_tested); + + constexpr int kFastForwardSeconds = 2; + clock()->Advance(base::Seconds(kFastForwardSeconds)); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); + + // Only the metric that records the time delta between the nudge shown and + // the menu opening for `type_being_tested` should be recorded. + for (const auto nudge_type : kAllClipboardNudgeTypes) { + histograms().ExpectBucketCount(GetMenuOpenTimeDeltaHistogram(nudge_type), + kFastForwardSeconds, + nudge_type == type_being_tested ? 1 : 0); + histograms().ExpectTotalCount( + GetClipboardHistoryPasteTimeDeltaHistogram(nudge_type), 0); + } +} + +// Tests that the metrics are recorded as expected when pasting the clipboard +// history data after a nudge shown. +TEST_P(ClipboardNudgeMetricTest, PasteAfterNudgeShown) { + const ClipboardNudgeType type_being_tested = GetNudgeType(); + ShowNudgeForType(type_being_tested); + + constexpr int kFastForwardSeconds = 2; + clock()->Advance(base::Seconds(kFastForwardSeconds)); + nudge_controller_->OnClipboardHistoryPasted(); + + // Only the metric that records the time delta between the nudge shown and the + // clipboard data paste for `type_being_tested` should be recorded. + for (const auto nudge_type : kAllClipboardNudgeTypes) { + histograms().ExpectTotalCount(GetMenuOpenTimeDeltaHistogram(nudge_type), 0); + histograms().ExpectBucketCount( + GetClipboardHistoryPasteTimeDeltaHistogram(nudge_type), + kFastForwardSeconds, nudge_type == type_being_tested ? 1 : 0); + } +} + +// Tests that showing a nudge once allows at most one histogram entry to be +// recorded. +TEST_P(ClipboardNudgeMetricTest, LogOnceForSingleNudgeShown) { + const ClipboardNudgeType type_being_tested = GetNudgeType(); + ShowNudgeForType(type_being_tested); + + constexpr int kFastForwardSeconds = 2; + clock()->Advance(base::Seconds(kFastForwardSeconds)); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); + nudge_controller_->OnClipboardHistoryPasted(); + + for (const auto nudge_type : kAllClipboardNudgeTypes) { + histograms().ExpectBucketCount(GetMenuOpenTimeDeltaHistogram(nudge_type), + kFastForwardSeconds, + nudge_type == type_being_tested ? 1 : 0); + histograms().ExpectBucketCount( + GetClipboardHistoryPasteTimeDeltaHistogram(nudge_type), + kFastForwardSeconds, nudge_type == type_being_tested ? 1 : 0); + } + + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); + nudge_controller_->OnClipboardHistoryPasted(); + + // The metrics should not be recorded for the second menu shown or clipboard + // data paste. + for (const auto nudge_type : kAllClipboardNudgeTypes) { + histograms().ExpectBucketCount(GetMenuOpenTimeDeltaHistogram(nudge_type), + kFastForwardSeconds, + nudge_type == type_being_tested ? 1 : 0); + histograms().ExpectBucketCount( + GetClipboardHistoryPasteTimeDeltaHistogram(nudge_type), + kFastForwardSeconds, nudge_type == type_being_tested ? 1 : 0); + } +} + +// Tests that new histogram entries can be recorded each time a nudge is shown. +TEST_P(ClipboardNudgeMetricTest, LogTwiceAfterShowingTwice) { + const ClipboardNudgeType nudge_type = GetNudgeType(); + ShowNudgeForType(nudge_type); + + constexpr int kFirstFastForwardSeconds = 2; + clock()->Advance(base::Seconds(kFirstFastForwardSeconds)); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); + nudge_controller_->OnClipboardHistoryPasted(); + + ShowNudgeForType(nudge_type); + + // Perform menu shown and data paste but with a different fast forward time + // delta. + constexpr int kSecondFastForwardSeconds = 5; + clock()->Advance(base::Seconds(kSecondFastForwardSeconds)); + nudge_controller_->OnClipboardHistoryMenuShown(/*show_source=*/kAccelerator); + nudge_controller_->OnClipboardHistoryPasted(); + + const char* menu_shown_time_delta_histogram = + GetMenuOpenTimeDeltaHistogram(nudge_type); + histograms().ExpectTotalCount(menu_shown_time_delta_histogram, 2); + histograms().ExpectBucketCount(menu_shown_time_delta_histogram, + kFirstFastForwardSeconds, 1); + histograms().ExpectBucketCount(menu_shown_time_delta_histogram, + kSecondFastForwardSeconds, 1); + + const char* paste_time_delta_histogram = + GetClipboardHistoryPasteTimeDeltaHistogram(nudge_type); + histograms().ExpectTotalCount(paste_time_delta_histogram, 2); + histograms().ExpectBucketCount(paste_time_delta_histogram, + kFirstFastForwardSeconds, 1); + histograms().ExpectBucketCount(paste_time_delta_histogram, + kSecondFastForwardSeconds, 1); +} + +// Tests that showing the standalone clipboard history menu from a source other +// than the accelerator does not log any metrics, because the nudge only +// mentions the accelerator as an option for opening the menu. +TEST_P(ClipboardNudgeMetricTest, NotLogForNonAcceleratorMenuShown) { + using crosapi::mojom::ClipboardHistoryControllerShowSource; + + const ClipboardNudgeType nudge_type = GetNudgeType(); + ShowNudgeForType(nudge_type); + + for (size_t i = + static_cast<size_t>(ClipboardHistoryControllerShowSource::kMinValue); + i < static_cast<size_t>(ClipboardHistoryControllerShowSource::kMaxValue); + ++i) { + auto show_source = static_cast<ClipboardHistoryControllerShowSource>(i); + if (show_source != kAccelerator) { + nudge_controller_->OnClipboardHistoryMenuShown(show_source); + } + } + + histograms().ExpectTotalCount(GetMenuOpenTimeDeltaHistogram(nudge_type), 0); + histograms().ExpectTotalCount( + GetClipboardHistoryPasteTimeDeltaHistogram(nudge_type), 0); +} + } // namespace ash
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 2fd83bb..a2410474 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -882,6 +882,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeTouchpadScrollEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOobeDisplaySizeEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOsSettingsAppBadgingToggleEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOsSettingsRevampWayfindingEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOsSettingsSearchFeedbackEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOsSyncConsentRevampEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsOverviewDeskNavigationEnabled();
diff --git a/ash/controls/contextual_nudge.cc b/ash/controls/contextual_nudge.cc index 81f085a..c808fca 100644 --- a/ash/controls/contextual_nudge.cc +++ b/ash/controls/contextual_nudge.cc
@@ -7,10 +7,14 @@ #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/shelf/shelf.h" +#include "ash/style/ash_color_id.h" #include "ash/style/ash_color_provider.h" +#include "ash/style/typography.h" #include "ash/system/tray/tray_constants.h" #include "ash/wm/collision_detection/collision_detection_utils.h" +#include "chromeos/constants/chromeos_features.h" #include "ui/aura/window.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/color_palette.h" @@ -70,6 +74,13 @@ label_->SetHorizontalAlignment(gfx::ALIGN_CENTER); label_->SetBackgroundColor(SK_ColorTRANSPARENT); label_->SetBorder(views::CreateEmptyBorder(margins)); + if (chromeos::features::IsJellyEnabled()) { + label_->SetEnabledColorId(cros_tokens::kCrosSysSecondary); + TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosAnnotation1, + *label_); + } else { + label_->SetEnabledColorId(kColorAshTextColorPrimary); + } views::BubbleDialogDelegateView::CreateBubble(this); @@ -116,10 +127,4 @@ views::BubbleDialogDelegateView::OnGestureEvent(event); } -void ContextualNudge::OnThemeChanged() { - views::BubbleDialogDelegateView::OnThemeChanged(); - label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); -} - } // namespace ash
diff --git a/ash/controls/contextual_nudge.h b/ash/controls/contextual_nudge.h index 31f610e..392e8391 100644 --- a/ash/controls/contextual_nudge.h +++ b/ash/controls/contextual_nudge.h
@@ -53,7 +53,6 @@ // BubbleDialogDelegateView: ui::LayerType GetLayerType() const override; void OnGestureEvent(ui::GestureEvent* event) override; - void OnThemeChanged() override; private: base::RepeatingClosure tap_callback_;
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index d015a87..ab1539bb 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -115,8 +115,10 @@ "holding_space_download.icon", "holding_space_refresh.icon", "hollow_check_circle.icon", + "hotspot_dot.icon", "hotspot_off.icon", "hotspot_on.icon", + "hotspot_one_arc.icon", "ime_menu_emoticon.icon", "ime_menu_microphone.icon", "ime_menu_on_screen_keyboard.icon",
diff --git a/ash/resources/vector_icons/hotspot_dot.icon b/ash/resources/vector_icons/hotspot_dot.icon new file mode 100644 index 0000000..417d7f5 --- /dev/null +++ b/ash/resources/vector_icons/hotspot_dot.icon
@@ -0,0 +1,11 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 10.5f, 12, +CUBIC_TO, 11.33f, 12, 12, 11.33f, 12, 10.5f, +CUBIC_TO, 12, 9.67f, 11.33f, 9, 10.5f, 9, +CUBIC_TO, 9.67f, 9, 9, 9.67f, 9, 10.5f, +CUBIC_TO, 9, 11.33f, 9.67f, 12, 10.5f, 12, +CLOSE \ No newline at end of file
diff --git a/ash/resources/vector_icons/hotspot_one_arc.icon b/ash/resources/vector_icons/hotspot_one_arc.icon new file mode 100644 index 0000000..93f3f31a --- /dev/null +++ b/ash/resources/vector_icons/hotspot_one_arc.icon
@@ -0,0 +1,24 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 20, +MOVE_TO, 15.5f, 10.5f, +CUBIC_TO, 15.5f, 7.78f, 13.26f, 5.5f, 10.5f, 5.5f, +CUBIC_TO, 7.74f, 5.5f, 5.5f, 7.78f, 5.5f, 10.5f, +CUBIC_TO, 5.5f, 12.48f, 6.51f, 14.12f, 8, 15, +LINE_TO, 9, 13.5f, +CUBIC_TO, 7.84f, 12.93f, 7.17f, 11.85f, 7, 10.5f, +CUBIC_TO, 7.17f, 8.72f, 8.66f, 7.2f, 10.5f, 7, +CUBIC_TO, 12.34f, 7.2f, 13.83f, 8.72f, 14, 10.5f, +CUBIC_TO, 13.83f, 11.85f, 13.16f, 12.93f, 12, 13.5f, +LINE_TO, 13, 15, +CUBIC_TO, 14.49f, 14.12f, 15.5f, 12.48f, 15.5f, 10.5f, +CLOSE, +NEW_PATH, +MOVE_TO, 10.5f, 12, +CUBIC_TO, 11.33f, 12, 12, 11.33f, 12, 10.5f, +CUBIC_TO, 12, 9.67f, 11.33f, 9, 10.5f, 9, +CUBIC_TO, 9.67f, 9, 9, 9.67f, 9, 10.5f, +CUBIC_TO, 9, 11.33f, 9.67f, 12, 10.5f, 12, +CLOSE \ No newline at end of file
diff --git a/ash/shelf/drag_handle.cc b/ash/shelf/drag_handle.cc index 50a7d0e..953e250 100644 --- a/ash/shelf/drag_handle.cc +++ b/ash/shelf/drag_handle.cc
@@ -24,9 +24,11 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "base/timer/timer.h" +#include "chromeos/constants/chromeos_features.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/accessibility/ax_node_data.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/views/accessibility/view_accessibility.h" @@ -240,7 +242,12 @@ } void DragHandle::UpdateColor() { - layer()->SetColor(GetColorProvider()->GetColor(kColorAshShelfHandleColor)); + if (chromeos::features::IsJellyEnabled()) { + layer()->SetColor( + GetColorProvider()->GetColor(cros_tokens::kCrosSysOnSurface)); + } else { + layer()->SetColor(GetColorProvider()->GetColor(kColorAshShelfHandleColor)); + } } void DragHandle::OnGestureEvent(ui::GestureEvent* event) {
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc index 3ae7c5721..c1f87279 100644 --- a/ash/shelf/home_button.cc +++ b/ash/shelf/home_button.cc
@@ -25,6 +25,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" #include "ash/style/ash_color_provider.h" +#include "ash/style/typography.h" #include "ash/user_education/user_education_class_properties.h" #include "ash/user_education/user_education_constants.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" @@ -37,6 +38,7 @@ #include "chromeos/strings/grit/chromeos_strings.h" #include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/canvas.h" @@ -147,10 +149,7 @@ cc::PaintFlags fg_flags; fg_flags.setAntiAlias(true); fg_flags.setStyle(cc::PaintFlags::kStroke_Style); - fg_flags.setColor(GetColorProvider()->GetColor( - chromeos::features::IsJellyEnabled() - ? static_cast<ui::ColorId>(cros_tokens::kCrosSysOnSurface) - : kColorAshButtonIconColor)); + fg_flags.setColor(GetColorProvider()->GetColor(GetIconColorId())); if (is_assistant_available) { // active: 100% alpha, inactive: 54% alpha @@ -191,6 +190,16 @@ UpdateBackground(); } + void SetToggled(bool toggled) { + if (toggled_ == toggled) { + return; + } + + toggled_ = toggled; + UpdateBackground(); + SchedulePaint(); + } + private: // Updates the view background to match the current shelf config. void UpdateBackground() { @@ -210,11 +219,8 @@ shelf_config->control_border_radius())); } } else { - const ui::ColorId color_id = shelf_config->in_tablet_mode() - ? cros_tokens::kCrosSysSystemBaseElevated - : cros_tokens::kCrosSysSystemOnBase; SetBackground(views::CreateThemedRoundedRectBackground( - color_id, shelf_config->control_border_radius())); + GetBackgroundColorId(), shelf_config->control_border_radius())); } if (shelf_config->in_tablet_mode() && !shelf_config->is_in_app()) { @@ -228,7 +234,28 @@ } } + ui::ColorId GetIconColorId() { + if (!chromeos::features::IsJellyEnabled()) { + return kColorAshButtonIconColor; + } + + return toggled_ && !ShelfConfig::Get()->in_tablet_mode() + ? cros_tokens::kCrosSysSystemOnPrimaryContainer + : cros_tokens::kCrosSysOnSurface; + } + + ui::ColorId GetBackgroundColorId() { + if (ShelfConfig::Get()->in_tablet_mode()) { + return cros_tokens::kCrosSysSystemBaseElevated; + } + + return toggled_ ? cros_tokens::kCrosSysSystemPrimaryContainer + : cros_tokens::kCrosSysSystemOnBase; + } + HomeButtonController* const button_controller_; + + bool toggled_ = false; }; // static @@ -253,7 +280,10 @@ // HomeButton::ScopedNoClipRect ------------------------------------------------ HomeButton::HomeButton(Shelf* shelf) - : ShelfControlButton(shelf, this), shelf_(shelf), controller_(this) { + : ShelfControlButton(shelf, this), + jelly_enabled_(chromeos::features::IsJellyEnabled()), + shelf_(shelf), + controller_(this) { SetAccessibleName( l10n_util::GetStringUTF16(IDS_ASH_SHELF_APP_LIST_LAUNCHER_TITLE)); button_controller()->set_notify_action( @@ -553,6 +583,10 @@ AnimateNudgeRipple(builder); } +void HomeButton::SetToggled(bool toggled) { + button_image_view_->SetToggled(toggled); +} + void HomeButton::AddNudgeAnimationObserverForTest( NudgeAnimationObserver* observer) { observers_.AddObserver(observer); @@ -564,20 +598,18 @@ void HomeButton::OnThemeChanged() { ShelfControlButton::OnThemeChanged(); + if (ripple_layer_delegate_) { - ripple_layer_delegate_->set_color( - GetColorProvider()->GetColor(kColorAshInkDropOpaqueColor)); + ripple_layer_delegate_->set_color(GetColorProvider()->GetColor( + jelly_enabled_ ? static_cast<ui::ColorId>( + cros_tokens::kCrosSysRippleNeutralOnSubtle) + : kColorAshInkDropOpaqueColor)); } if (expandable_container_) { - expandable_container_->layer()->SetColor( - AshColorProvider::Get()->GetControlsLayerColor( - AshColorProvider::ControlsLayerType:: - kControlBackgroundColorInactive)); - if (nudge_label_) { - nudge_label_->SetEnabledColor( - AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - } + expandable_container_->layer()->SetColor(GetColorProvider()->GetColor( + jelly_enabled_ + ? static_cast<ui::ColorId>(cros_tokens::kCrosSysSystemOnBase) + : kColorAshControlBackgroundColorInactive)); } } @@ -592,10 +624,12 @@ std::make_unique<views::FillLayout>()); expandable_container_->SetPaintToLayer(ui::LAYER_SOLID_COLOR); expandable_container_->layer()->SetMasksToBounds(true); - expandable_container_->layer()->SetColor( - AshColorProvider::Get()->GetControlsLayerColor( - AshColorProvider::ControlsLayerType:: - kControlBackgroundColorInactive)); + if (GetColorProvider()) { + expandable_container_->layer()->SetColor(GetColorProvider()->GetColor( + jelly_enabled_ + ? static_cast<ui::ColorId>(cros_tokens::kCrosSysSystemOnBase) + : kColorAshControlBackgroundColorInactive)); + } expandable_container_->layer()->SetRoundedCornerRadius( gfx::RoundedCornersF(home_button_width / 2.f)); expandable_container_->layer()->SetName("NudgeLabelContainer"); @@ -626,9 +660,13 @@ nudge_label_->layer()->SetFillsBoundsOpaquely(false); nudge_label_->SetTextContext(CONTEXT_LAUNCHER_NUDGE_LABEL); nudge_label_->SetTextStyle(views::style::STYLE_EMPHASIZED); - nudge_label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kTextColorPrimary)); - + nudge_label_->SetEnabledColorId( + jelly_enabled_ ? static_cast<ui::ColorId>(cros_tokens::kCrosSysOnSurface) + : kColorAshTextColorPrimary); + if (jelly_enabled_) { + TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosButton2, + *nudge_label_); + } expandable_container_->SetVisible(false); Layout(); }
diff --git a/ash/shelf/home_button.h b/ash/shelf/home_button.h index a672c4e..ec39393b 100644 --- a/ash/shelf/home_button.h +++ b/ash/shelf/home_button.h
@@ -141,6 +141,10 @@ // Starts the launcher nudge animation. void StartNudgeAnimation(); + // Sets the button's "toggled" state - the button is toggled when the bubble + // launcher is shown. + void SetToggled(bool toggled); + void AddNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); void RemoveNudgeAnimationObserverForTest(NudgeAnimationObserver* observer); @@ -226,6 +230,8 @@ // bounds of the home button. gfx::Rect GetExpandableContainerClipRectToHomeButton(); + const bool jelly_enabled_; + base::ScopedObservation<QuickAppAccessModel, QuickAppAccessModel::Observer> quick_app_model_observation_{this};
diff --git a/ash/shelf/home_button_controller.cc b/ash/shelf/home_button_controller.cc index 5573159..a3976251 100644 --- a/ash/shelf/home_button_controller.cc +++ b/ash/shelf/home_button_controller.cc
@@ -18,6 +18,7 @@ #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" +#include "chromeos/constants/chromeos_features.h" #include "components/account_id/account_id.h" #include "ui/display/screen.h" #include "ui/views/animation/ink_drop.h" @@ -176,23 +177,31 @@ } void HomeButtonController::OnAppListShown() { - // Do not show a highlight in tablet mode, since the home screen view is - // always open in the background. + // Do not show the button as toggled in tablet mode, since the home screen + // view is always open in the background. if (!Shell::Get()->IsInTabletMode()) { - views::InkDrop::Get(button_)->AnimateToState(views::InkDropState::ACTIVATED, - nullptr); + button_->SetToggled(true); + if (!chromeos::features::IsJellyEnabled()) { + views::InkDrop::Get(button_)->AnimateToState( + views::InkDropState::ACTIVATED, nullptr); + } } } void HomeButtonController::OnAppListDismissed() { - // If ink drop is not hidden already, snap it to active state, so animation to - // DEACTIVATED state starts immediately (the animation would otherwise wait - // for the current animation to finish). - views::InkDrop* const ink_drop = views::InkDrop::Get(button_)->GetInkDrop(); - if (ink_drop->GetTargetInkDropState() != views::InkDropState::HIDDEN) - ink_drop->SnapToActivated(); - views::InkDrop::Get(button_)->AnimateToState(views::InkDropState::DEACTIVATED, - nullptr); + button_->SetToggled(false); + + if (!chromeos::features::IsJellyEnabled()) { + // If ink drop is not hidden already, snap it to active state, so animation + // to DEACTIVATED state starts immediately (the animation would otherwise + // wait for the current animation to finish). + views::InkDrop* const ink_drop = views::InkDrop::Get(button_)->GetInkDrop(); + if (ink_drop->GetTargetInkDropState() != views::InkDropState::HIDDEN) { + ink_drop->SnapToActivated(); + } + views::InkDrop::Get(button_)->AnimateToState( + views::InkDropState::DEACTIVATED, nullptr); + } } void HomeButtonController::InitializeAssistantOverlay() {
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc index 7f167a9..27d0603 100644 --- a/ash/shelf/shelf_app_button.cc +++ b/ash/shelf/shelf_app_button.cc
@@ -16,6 +16,7 @@ #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_id.h" #include "ash/style/dot_indicator.h" +#include "ash/style/style_util.h" #include "ash/wm/desks/desks_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/functional/bind.h" @@ -164,7 +165,8 @@ public: METADATA_HEADER(AppStatusIndicatorView); - AppStatusIndicatorView() { + AppStatusIndicatorView() + : jelly_enabled_(chromeos::features::IsJellyEnabled()) { // Make sure the events reach the parent view for handling. SetCanProcessEventsWithinSubtree(false); status_change_animation_ = std::make_unique<gfx::SlideAnimation>(this); @@ -186,17 +188,25 @@ } void OnPaint(gfx::Canvas* canvas) override { + if (!GetColorProvider()) { + return; + } + gfx::ScopedCanvas scoped(canvas); - canvas->SaveLayerAlpha(GetAlpha()); + if (!jelly_enabled_) { + canvas->SaveLayerAlpha(GetAlpha()); + } const float dsf = canvas->UndoDeviceScaleFactor(); gfx::PointF center = gfx::RectF(GetLocalBounds()).CenterPoint(); cc::PaintFlags flags; + if (jelly_enabled_) { + flags.setColor(GetJellyColor()); + } else { + flags.setColor( + GetColorProvider()->GetColor(kColorAshAppStateIndicatorColor)); + } // Active and running indicators look a little different in the new UI. - flags.setColor(GetColorProvider()->GetColor( - chromeos::features::IsJellyEnabled() - ? static_cast<ui::ColorId>(cros_tokens::kCrosSysOnSurface) - : kColorAshAppStateIndicatorColor)); flags.setAntiAlias(true); flags.setStrokeCap(cc::PaintFlags::Cap::kRound_Cap); flags.setStrokeJoin(cc::PaintFlags::Join::kRound_Join); @@ -238,6 +248,27 @@ : status_indicator_running_size; } + SkColor GetJellyColor() { + const SkColor active_color = + GetColorProvider()->GetColor(cros_tokens::kCrosSysOnSurface); + const SkColor inactive_color = + GetColorProvider()->GetColor(cros_tokens::kCrosSysSecondary); + if (show_attention_) { + if (!ShelfAppButtonAnimation::GetInstance()->HasObserver(this)) { + return active_color; + } + return SkColorSetA(active_color, + ShelfAppButtonAnimation::GetInstance()->GetAlpha()); + } + + if (status_change_animation_->is_animating()) { + return gfx::Tween::ColorValueBetween( + status_change_animation_->GetCurrentValue(), inactive_color, + active_color); + } + return active_ ? active_color : inactive_color; + } + SkAlpha GetAlpha() { if (show_attention_) { return ShelfAppButtonAnimation::GetInstance()->HasObserver(this) @@ -306,6 +337,7 @@ ShelfAppButtonAnimation::GetInstance()->RemoveObserver(this); } + const bool jelly_enabled_; bool show_attention_ = false; bool active_ = false; bool horizontal_shelf_ = true; @@ -391,7 +423,11 @@ views::InstallEmptyHighlightPathGenerator(this); SetFocusBehavior(FocusBehavior::ALWAYS); SetInstallFocusRingOnFocus(true); - views::FocusRing::Get(this)->SetColorId(ui::kColorAshFocusRing); + if (chromeos::features::IsJellyEnabled()) { + views::FocusRing::Get(this)->SetColorId(cros_tokens::kCrosSysFocusRing); + } else { + views::FocusRing::Get(this)->SetColorId(ui::kColorAshFocusRing); + } // The focus ring should have an inset of half the focus border thickness, so // the parent view won't clip it. views::FocusRing::Get(this)->SetPathGenerator(
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc index 860b65ec..5670aca 100644 --- a/ash/shelf/shelf_button.cc +++ b/ash/shelf/shelf_button.cc
@@ -8,8 +8,10 @@ #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_button_delegate.h" #include "ash/style/style_util.h" +#include "chromeos/constants/chromeos_features.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/views/animation/ink_drop.h" #include "ui/views/controls/highlight_path_generator.h" @@ -41,8 +43,14 @@ void ShelfButton::OnThemeChanged() { views::Button::OnThemeChanged(); - StyleUtil::ConfigureInkDropAttributes( - this, StyleUtil::kBaseColor | StyleUtil::kInkDropOpacity); + if (chromeos::features::IsJellyEnabled()) { + auto* ink_drop = views::InkDrop::Get(this); + ink_drop->SetBaseColorId(cros_tokens::kCrosSysRippleNeutralOnSubtle); + ink_drop->SetVisibleOpacity(1.0f); + } else { + StyleUtil::ConfigureInkDropAttributes( + this, StyleUtil::kBaseColor | StyleUtil::kInkDropOpacity); + } } const char* ShelfButton::GetClassName() const {
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc index 0b9a5219..8ab697d 100644 --- a/ash/shelf/shelf_control_button.cc +++ b/ash/shelf/shelf_control_button.cc
@@ -8,9 +8,10 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shelf/shelf_button_delegate.h" #include "ash/shell.h" -#include "ash/style/ash_color_provider.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "chromeos/constants/chromeos_features.h" #include "ui/accessibility/ax_node_data.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/color/color_id.h" #include "ui/gfx/canvas.h" #include "ui/gfx/paint_vector_icon.h" @@ -58,7 +59,10 @@ : ShelfButton(shelf, shelf_button_delegate) { SetHasInkDropActionOnClick(true); SetInstallFocusRingOnFocus(true); - views::FocusRing::Get(this)->SetColorId(ui::kColorAshFocusRing); + views::FocusRing::Get(this)->SetColorId( + chromeos::features::IsJellyEnabled() + ? static_cast<ui::ColorId>(cros_tokens::kCrosSysFocusRing) + : ui::kColorAshFocusRing); views::HighlightPathGenerator::Install( this, std::make_unique<ShelfControlButtonHighlightPathGenerator>()); SetPaintToLayer();
diff --git a/ash/shelf/shelf_controller_unittest.cc b/ash/shelf/shelf_controller_unittest.cc index 341a45a..62dc14a5 100644 --- a/ash/shelf/shelf_controller_unittest.cc +++ b/ash/shelf/shelf_controller_unittest.cc
@@ -546,31 +546,4 @@ EXPECT_EQ(ShelfAutoHideBehavior::kAlwaysHidden, shelf->auto_hide_behavior()); } -using ShelfControllerShelfPartyTest = NoSessionAshTestBase; - -TEST_F(ShelfControllerShelfPartyTest, ShelfPartyEndedOnLockScreen) { - auto* session_controller = GetSessionControllerClient(); - session_controller->SetSessionState(session_manager::SessionState::ACTIVE); - ShelfModel* model = Shell::Get()->shelf_controller()->model(); - model->ToggleShelfParty(); - EXPECT_TRUE(model->in_shelf_party()); - session_controller->SetSessionState(session_manager::SessionState::LOCKED); - EXPECT_FALSE(model->in_shelf_party()); -} - -TEST_F(ShelfControllerShelfPartyTest, ShelfPartyEndedOnSwitchUsers) { - auto* session_controller = GetSessionControllerClient(); - constexpr char kEmail1[] = "user1@gmail.com"; - session_controller->AddUserSession(kEmail1); - constexpr char kEmail2[] = "user2@gmail.com"; - session_controller->AddUserSession(kEmail2); - session_controller->SwitchActiveUser(AccountId::FromUserEmail(kEmail1)); - session_controller->SetSessionState(session_manager::SessionState::ACTIVE); - ShelfModel* model = Shell::Get()->shelf_controller()->model(); - model->ToggleShelfParty(); - EXPECT_TRUE(model->in_shelf_party()); - session_controller->SwitchActiveUser(AccountId::FromUserEmail(kEmail2)); - EXPECT_FALSE(model->in_shelf_party()); -} - } // namespace ash
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 89c60e2a..1dc40d78 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -3562,134 +3562,6 @@ EXPECT_EQ(views::InkDropState::HIDDEN, GetInkDropStateOfAppIcon1()); } -class ShelfPartyTest : public ShelfViewTest, - public testing::WithParamInterface< - std::pair<ShelfAlignment, ShelfAutoHideBehavior>> { - public: - ShelfPartyTest() - : ShelfViewTest(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { - scoped_feature_list_.InitAndEnableFeature(features::kShelfParty); - } - ShelfPartyTest(const ShelfPartyTest&) = delete; - ShelfPartyTest& operator=(const ShelfPartyTest&) = delete; - ~ShelfPartyTest() override = default; - - void SetUp() override { - ShelfViewTest::SetUp(); - shelf_view_->shelf()->SetAlignment(GetParam().first); - shelf_view_->shelf()->SetAutoHideBehavior(GetParam().second); - } - - private: - base::test::ScopedFeatureList scoped_feature_list_; -}; - -INSTANTIATE_TEST_SUITE_P( - All, - ShelfPartyTest, - testing::Values( - std::make_pair(ShelfAlignment::kBottom, ShelfAutoHideBehavior::kAlways), - std::make_pair(ShelfAlignment::kBottom, ShelfAutoHideBehavior::kNever), - std::make_pair(ShelfAlignment::kLeft, ShelfAutoHideBehavior::kNever), - std::make_pair(ShelfAlignment::kRight, ShelfAutoHideBehavior::kNever), - std::make_pair(ShelfAlignment::kBottomLocked, - ShelfAutoHideBehavior::kNever), - std::make_pair(ShelfAlignment::kBottom, - ShelfAutoHideBehavior::kAlwaysHidden))); - -// Exercises the party animation. -TEST_P(ShelfPartyTest, PartyAnimation) { - for (int i = 0; i < 16; ++i) { - AddAppShortcut(); - } - model_->ToggleShelfParty(); - task_environment()->FastForwardBy(base::Seconds(2)); - model_->ToggleShelfParty(); - test_api_->RunMessageLoopUntilAnimationsDone(); -} - -// Verifies that partying items are hidden from the shelf. -TEST_P(ShelfPartyTest, PartyingItemsHiddenFromShelf) { - AddAppShortcut(); - AddAppShortcut(); - AddApp(); - ShelfItem item = model_->items()[1u]; - item.status = STATUS_RUNNING; - model_->Set(1, item); - const gfx::Rect initial_bounds0 = test_api_->GetBoundsByIndex(0); - const gfx::Rect initial_bounds2 = test_api_->GetBoundsByIndex(2); - - // Start shelf party. - model_->ToggleShelfParty(); - { - const std::vector<size_t> not_partying = {1, 3}; - EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); - } - task_environment()->FastForwardBy(base::Seconds(1)); - EXPECT_TRUE(test_api_->GetBoundsByIndex(0).IsEmpty()); - EXPECT_TRUE(test_api_->GetBoundsByIndex(2).IsEmpty()); - - // End shelf party. - model_->ToggleShelfParty(); - { - const std::vector<size_t> not_partying = {0, 1, 2, 3}; - EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); - } - test_api_->RunMessageLoopUntilAnimationsDone(); - EXPECT_EQ(initial_bounds0, test_api_->GetBoundsByIndex(0)); - EXPECT_EQ(initial_bounds2, test_api_->GetBoundsByIndex(2)); -} - -// Verifies that the feature that enables dragging unpinned apps to pin works -// with shelf party. -TEST_P(ShelfPartyTest, DragUnpinnedAppToPin) { - AddAppShortcut(); - AddAppShortcut(); - const ShelfID running_unpinned_app = AddApp(); - - ShelfItem item = model_->items()[1u]; - item.status = STATUS_RUNNING; - model_->Set(1, item); - const ShelfID running_pinned_app = item.id; - - // Start shelf party. - model_->ToggleShelfParty(); - { - const std::vector<size_t> not_partying = {1, 3}; - EXPECT_EQ(not_partying, shelf_view_->visible_views_indices()); - } - task_environment()->FastForwardBy(base::Seconds(1)); - - // At this point, there should be only 1 pinned app and 1 unpinned app on the - // shelf. - const gfx::Point unpinned_app_center = GetButtonCenter(running_unpinned_app); - const gfx::Point pinned_app_center = GetButtonCenter(running_pinned_app); - auto* generator = GetEventGenerator(); - - // Drag the unpinned app to the front. - generator->MoveMouseTo(unpinned_app_center); - generator->PressLeftButton(); - generator->MoveMouseTo(pinned_app_center); - - // The first visible item, which is the dragged item, should not be pinned. - const size_t first_visible_index = - shelf_view_->visible_views_indices().front(); - EXPECT_TRUE(!IsAppPinned(model_->items()[first_visible_index].id)); - - // Drag the unpinned app back to its original position and release it. - generator->MoveMouseTo(unpinned_app_center); - generator->ReleaseLeftButton(); - - // The last visible item, which is the dragged item, should still be an - // unpinned one. - const size_t last_visible_index = shelf_view_->visible_views_indices().back(); - EXPECT_TRUE(!IsAppPinned(model_->items()[last_visible_index].id)); - - // End shelf party. - model_->ToggleShelfParty(); - test_api_->RunMessageLoopUntilAnimationsDone(); -} - // Test class to test the desk button. class ShelfViewDeskButtonTest : public ShelfViewTest { public:
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc index fcf5c9f..2596323e 100644 --- a/ash/shelf/shelf_widget.cc +++ b/ash/shelf/shelf_widget.cc
@@ -40,6 +40,7 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" #include "chromeos/constants/chromeos_features.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/compositor/layer.h" #include "ui/compositor/layer_delegate.h" #include "ui/compositor/layer_owner.h" @@ -458,13 +459,20 @@ void ShelfWidget::DelegateView::OnThemeChanged() { views::AccessiblePaneView::OnThemeChanged(); - animating_background_.SetColor( - ShelfConfig::Get()->GetMaximizedShelfColor(GetWidget())); shelf_widget_->background_animator_.PaintBackground( shelf_widget_->shelf_layout_manager()->GetShelfBackgroundType(), AnimationChangeType::IMMEDIATE); - animating_drag_handle_.SetColor( - GetColorProvider()->GetColor(kColorAshShelfHandleColor)); + if (chromeos::features::IsJellyEnabled()) { + animating_background_.SetColor( + GetColorProvider()->GetColor(cros_tokens::kCrosSysSystemBase)); + animating_drag_handle_.SetColor( + GetColorProvider()->GetColor(cros_tokens::kCrosSysOnSurface)); + } else { + animating_background_.SetColor( + ShelfConfig::Get()->GetMaximizedShelfColor(GetWidget())); + animating_drag_handle_.SetColor( + GetColorProvider()->GetColor(kColorAshShelfHandleColor)); + } } bool ShelfWidget::DelegateView::CanActivate() const {
diff --git a/ash/shell.cc b/ash/shell.cc index 66f57bc3..ceea101 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -135,6 +135,7 @@ #include "ash/system/federated/federated_service_controller_impl.h" #include "ash/system/firmware_update/firmware_update_notification_controller.h" #include "ash/system/geolocation/geolocation_controller.h" +#include "ash/system/hotspot/hotspot_icon_animation.h" #include "ash/system/hotspot/hotspot_info_cache.h" #include "ash/system/human_presence/human_presence_orientation_controller.h" #include "ash/system/human_presence/snooping_protection_controller.h" @@ -1571,6 +1572,7 @@ } if (features::IsHotspotEnabled()) { + hotspot_icon_animation_ = std::make_unique<HotspotIconAnimation>(); hotspot_info_cache_ = std::make_unique<HotspotInfoCache>(); }
diff --git a/ash/shell.h b/ash/shell.h index e8d5f1f7..262a460 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -156,6 +156,7 @@ class GlanceablesV2Controller; class ColorEnhancementController; class HoldingSpaceController; +class HotspotIconAnimation; class HotspotInfoCache; class HumanPresenceOrientationController; class ImeControllerImpl; @@ -558,6 +559,9 @@ ColorEnhancementController* color_enhancement_controller() { return color_enhancement_controller_.get(); } + HotspotIconAnimation* hotspot_icon_animation() { + return hotspot_icon_animation_.get(); + } HotspotInfoCache* hotspot_info_cache() { return hotspot_info_cache_.get(); } HumanPresenceOrientationController* human_presence_orientation_controller() { return human_presence_orientation_controller_.get(); @@ -1107,6 +1111,7 @@ std::unique_ptr<DisplayColorManager> display_color_manager_; std::unique_ptr<DisplayErrorObserver> display_error_observer_; std::unique_ptr<ProjectingObserver> projecting_observer_; + std::unique_ptr<HotspotIconAnimation> hotspot_icon_animation_; std::unique_ptr<HotspotInfoCache> hotspot_info_cache_; std::unique_ptr<display::DisplayPortObserver> display_port_observer_;
diff --git a/ash/system/camera/autozoom_controller_impl.cc b/ash/system/camera/autozoom_controller_impl.cc index e43db5a..f4e8e54 100644 --- a/ash/system/camera/autozoom_controller_impl.cc +++ b/ash/system/camera/autozoom_controller_impl.cc
@@ -70,7 +70,7 @@ SetState(state_ == cros::mojom::CameraAutoFramingState::OFF ? cros::mojom::CameraAutoFramingState::ON_SINGLE : cros::mojom::CameraAutoFramingState::OFF); - SystemNudgeController::RecordNudgeAction(NudgeCatalogName::kAutozoom); + SystemNudgeController::MaybeRecordNudgeAction(NudgeCatalogName::kAutozoom); } void AutozoomControllerImpl::AddObserver(AutozoomObserver* observer) {
diff --git a/ash/system/hotspot/hotspot_detailed_view.cc b/ash/system/hotspot/hotspot_detailed_view.cc index 51008934..f55206c1 100644 --- a/ash/system/hotspot/hotspot_detailed_view.cc +++ b/ash/system/hotspot/hotspot_detailed_view.cc
@@ -12,6 +12,8 @@ #include "ash/style/rounded_container.h" #include "ash/style/switch.h" #include "ash/style/typography.h" +#include "ash/system/hotspot/hotspot_icon.h" +#include "ash/system/hotspot/hotspot_icon_animation.h" #include "ash/system/model/system_tray_model.h" #include "ash/system/tray/detailed_view_delegate.h" #include "ash/system/tray/hover_highlight_view.h" @@ -59,14 +61,21 @@ CreateContainer(); } -HotspotDetailedView::~HotspotDetailedView() = default; +HotspotDetailedView::~HotspotDetailedView() { + Shell::Get()->hotspot_icon_animation()->RemoveObserver(this); +} void HotspotDetailedView::UpdateViewForHotspot(HotspotInfoPtr hotspot_info) { - // Update the Hotspot icon. - hotspot_icon_->SetImage(ui::ImageModel::FromVectorIcon( - IsEnabledOrEnabling(hotspot_info->state) ? kHotspotOnIcon - : kHotspotOffIcon, - cros_tokens::kCrosSysOnSurface)); + if (hotspot_info->state == HotspotState::kEnabling) { + Shell::Get()->hotspot_icon_animation()->AddObserver(this); + } else if (state_ == HotspotState::kEnabling) { + Shell::Get()->hotspot_icon_animation()->RemoveObserver(this); + } + + if (state_ != hotspot_info->state) { + state_ = hotspot_info->state; + UpdateIcon(); + } UpdateSubText(hotspot_info); UpdateToggleState(hotspot_info->state, hotspot_info->allow_status); @@ -117,6 +126,8 @@ auto hotspot_icon = std::make_unique<views::ImageView>(); hotspot_icon->SetID( static_cast<int>(HotspotDetailedViewChildId::kHotspotIcon)); + hotspot_icon->SetImage(ui::ImageModel::FromVectorIcon( + kHotspotOffIcon, cros_tokens::kCrosSysOnSurface)); hotspot_icon_ = hotspot_icon.get(); entry_row_->AddViewAndLabel(std::move(hotspot_icon), u""); entry_row_->text_label()->SetText(l10n_util::GetStringFUTF16( @@ -158,6 +169,15 @@ delegate_->OnToggleClicked(new_state); } +void HotspotDetailedView::HotspotIconChanged() { + UpdateIcon(); +} + +void HotspotDetailedView::UpdateIcon() { + hotspot_icon_->SetImage(ui::ImageModel::FromVectorIcon( + hotspot_icon::GetIconForHotspot(state_), cros_tokens::kCrosSysOnSurface)); +} + void HotspotDetailedView::UpdateToggleState( const HotspotState& state, const HotspotAllowStatus& allow_status) {
diff --git a/ash/system/hotspot/hotspot_detailed_view.h b/ash/system/hotspot/hotspot_detailed_view.h index a78e5b8..e96a1ae 100644 --- a/ash/system/hotspot/hotspot_detailed_view.h +++ b/ash/system/hotspot/hotspot_detailed_view.h
@@ -6,6 +6,7 @@ #define ASH_SYSTEM_HOTSPOT_HOTSPOT_DETAILED_VIEW_H_ #include "ash/ash_export.h" +#include "ash/system/hotspot/hotspot_icon_animation_observer.h" #include "ash/system/tray/tray_detailed_view.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" @@ -27,7 +28,8 @@ // This class defines both the interface used to interact with the detailed // Hotspot page within the quick settings. This class includes the declaration // for the delegate interface it uses to propagate user interactions. -class ASH_EXPORT HotspotDetailedView : public TrayDetailedView { +class ASH_EXPORT HotspotDetailedView : public TrayDetailedView, + public HotspotIconAnimationObserver { public: METADATA_HEADER(HotspotDetailedView); @@ -54,6 +56,9 @@ void HandleViewClicked(views::View* view) override; void CreateExtraTitleRowButtons() override; + // HotspotIconAnimationObserver: + void HotspotIconChanged() override; + private: friend class HotspotDetailedViewControllerTest; friend class HotspotDetailedViewTest; @@ -80,6 +85,7 @@ // Handles toggling Hotspot via the UI to `new_state`. void ToggleHotspot(bool new_state); + void UpdateIcon(); void UpdateToggleState( const hotspot_config::mojom::HotspotState& state, const hotspot_config::mojom::HotspotAllowStatus& allow_status); @@ -87,6 +93,9 @@ void UpdateExtraIcon( const hotspot_config::mojom::HotspotAllowStatus& allow_status); + hotspot_config::mojom::HotspotState state_ = + hotspot_config::mojom::HotspotState::kDisabled; + const raw_ptr<Delegate, ExperimentalAsh> delegate_; // Owned by views hierarchy.
diff --git a/ash/system/hotspot/hotspot_detailed_view_unittest.cc b/ash/system/hotspot/hotspot_detailed_view_unittest.cc index f44c448..b784b329 100644 --- a/ash/system/hotspot/hotspot_detailed_view_unittest.cc +++ b/ash/system/hotspot/hotspot_detailed_view_unittest.cc
@@ -4,7 +4,9 @@ #include "ash/system/hotspot/hotspot_detailed_view.h" +#include "ash/constants/ash_features.h" #include "ash/public/cpp/test/test_system_tray_client.h" +#include "ash/resources/vector_icons/vector_icons.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/rounded_container.h" #include "ash/style/switch.h" @@ -12,6 +14,11 @@ #include "ash/system/tray/hover_highlight_view.h" #include "ash/test/ash_test_base.h" #include "base/memory/raw_ptr.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h" +#include "ui/chromeos/styles/cros_tokens_color_mappings.h" +#include "ui/gfx/image/image_unittest_util.h" #include "ui/views/controls/image_view.h" #include "ui/views/controls/label.h" #include "ui/views/test/views_test_utils.h" @@ -59,10 +66,18 @@ class HotspotDetailedViewTest : public AshTestBase { public: - HotspotDetailedViewTest() = default; + HotspotDetailedViewTest() + : AshTestBase(std::make_unique<base::test::TaskEnvironment>( + base::test::TaskEnvironment::MainThreadType::UI, + base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {} ~HotspotDetailedViewTest() override = default; void SetUp() override { + scoped_feature_list_.InitWithFeatures( + {features::kHotspot, features::kQsRevamp}, {}); + cros_hotspot_config_test_helper_ = + std::make_unique<hotspot_config::CrosHotspotConfigTestHelper>( + /*use_fake_implementation=*/true); AshTestBase::SetUp(); auto hotspot_detailed_view = std::make_unique<HotspotDetailedView>( @@ -78,6 +93,7 @@ widget_.reset(); AshTestBase::TearDown(); + cros_hotspot_config_test_helper_.reset(); } void UpdateHotspotView(HotspotState state, @@ -105,6 +121,11 @@ HotspotDetailedView::HotspotDetailedViewChildId::kToggle); } + views::ImageView* GetHotspotIcon() { + return FindViewById<views::ImageView*>( + HotspotDetailedView::HotspotDetailedViewChildId::kHotspotIcon); + } + views::ImageView* GetExtraIcon() { return FindViewById<views::ImageView*>( HotspotDetailedView::HotspotDetailedViewChildId::kExtraIcon); @@ -154,6 +175,9 @@ hotspot_detailed_view_->GetViewByID(static_cast<int>(id))); } + base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<hotspot_config::CrosHotspotConfigTestHelper> + cros_hotspot_config_test_helper_; std::unique_ptr<views::Widget> widget_; FakeHotspotDetailedViewDelegate hotspot_detailed_view_delegate_; FakeDetailedViewDelegate detailed_view_delegate_; @@ -191,6 +215,11 @@ AssertToggleOn(/*expected_toggle_on=*/true); views::ImageView* extra_icon = GetExtraIcon(); EXPECT_FALSE(extra_icon->GetVisible()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotOnIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); UpdateHotspotView(HotspotState::kEnabled, HotspotAllowStatus::kAllowed, 1); AssertSubtextLabel(u"1 device connected"); @@ -209,6 +238,20 @@ AssertToggleOn(/*expected_toggle_on=*/true); views::ImageView* extra_icon = GetExtraIcon(); EXPECT_FALSE(extra_icon->GetVisible()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotDotIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); + // Verifies the hotspot icon is animating when enabling. + task_environment()->FastForwardBy(base::Milliseconds(500)); + image_model = ui::ImageModel::FromVectorIcon(kHotspotOneArcIcon, + cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); + task_environment()->FastForwardBy(base::Milliseconds(500)); + image_model = ui::ImageModel::FromVectorIcon(kHotspotOnIcon, + cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); } TEST_F(HotspotDetailedViewTest, HotspotDisablingUI) { @@ -221,6 +264,11 @@ AssertToggleOn(/*expected_toggle_on=*/false); views::ImageView* extra_icon = GetExtraIcon(); EXPECT_FALSE(extra_icon->GetVisible()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotOffIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); } TEST_F(HotspotDetailedViewTest, HotspotDisabledAndAllowedUI) { @@ -233,6 +281,11 @@ AssertToggleOn(/*expected_toggle_on=*/false); views::ImageView* extra_icon = GetExtraIcon(); EXPECT_FALSE(extra_icon->GetVisible()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotOffIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); } TEST_F(HotspotDetailedViewTest, HotspotDisabledAndNoMobileNetworkUI) { @@ -246,6 +299,11 @@ AssertToggleOn(/*expected_toggle_on=*/false); views::ImageView* extra_icon = GetExtraIcon(); EXPECT_FALSE(extra_icon->GetVisible()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotOffIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); } TEST_F(HotspotDetailedViewTest, @@ -262,6 +320,11 @@ EXPECT_TRUE(extra_icon->GetVisible()); EXPECT_EQ(u"Your mobile network doesn't support hotspot", extra_icon->GetTooltipText()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotOffIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); } TEST_F(HotspotDetailedViewTest, HotspotDisabledAndBlockedByPolicyUI) { @@ -277,6 +340,11 @@ EXPECT_TRUE(extra_icon->GetVisible()); EXPECT_EQ(u"This setting is managed by your administrator", extra_icon->GetTooltipText()); + views::ImageView* hotspot_icon = GetHotspotIcon(); + ASSERT_TRUE(hotspot_icon); + ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( + kHotspotOffIcon, cros_tokens::kCrosSysOnSurface); + EXPECT_EQ(image_model, hotspot_icon->GetImageModel()); } TEST_F(HotspotDetailedViewTest, PressingEntryRowNotifiesDelegate) {
diff --git a/ash/system/hotspot/hotspot_feature_pod_controller.cc b/ash/system/hotspot/hotspot_feature_pod_controller.cc index bc3f28f..ef54342 100644 --- a/ash/system/hotspot/hotspot_feature_pod_controller.cc +++ b/ash/system/hotspot/hotspot_feature_pod_controller.cc
@@ -9,6 +9,8 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" +#include "ash/system/hotspot/hotspot_icon.h" +#include "ash/system/hotspot/hotspot_icon_animation.h" #include "ash/system/hotspot/hotspot_info_cache.h" #include "ash/system/unified/feature_tile.h" #include "ash/system/unified/unified_system_tray_controller.h" @@ -34,7 +36,9 @@ hotspot_config_observer_receiver_.BindNewPipeAndPassRemote()); } -HotspotFeaturePodController::~HotspotFeaturePodController() = default; +HotspotFeaturePodController::~HotspotFeaturePodController() { + Shell::Get()->hotspot_icon_animation()->RemoveObserver(this); +} FeaturePodButton* HotspotFeaturePodController::CreateButton() { NOTREACHED(); @@ -96,6 +100,11 @@ void HotspotFeaturePodController::OnGetHotspotInfo( HotspotInfoPtr hotspot_info) { + if (hotspot_info->state == HotspotState::kEnabling) { + Shell::Get()->hotspot_icon_animation()->AddObserver(this); + } else if (hotspot_info_ && hotspot_info_->state == HotspotState::kEnabling) { + Shell::Get()->hotspot_icon_animation()->RemoveObserver(this); + } hotspot_info_ = std::move(hotspot_info); UpdateTileState(); @@ -118,10 +127,14 @@ tile_->SetVisible(true); tile_->SetEnabled(true); tile_->SetToggled(hotspot_info_->state != HotspotState::kDisabled); - tile_->SetVectorIcon(ComputeIcon()); tile_->SetSubLabel(ComputeSublabel()); tile_->SetIconButtonTooltipText(ComputeIconTooltip()); tile_->SetTooltipText(ComputeTileTooltip()); + tile_->SetVectorIcon(hotspot_icon::GetIconForHotspot(hotspot_info_->state)); +} + +void HotspotFeaturePodController::HotspotIconChanged() { + tile_->SetVectorIcon(hotspot_icon::GetIconForHotspot(hotspot_info_->state)); } void HotspotFeaturePodController::EnableHotspotIfAllowedAndDiveIn() {
diff --git a/ash/system/hotspot/hotspot_feature_pod_controller.h b/ash/system/hotspot/hotspot_feature_pod_controller.h index 2ece4cdb..08b5588 100644 --- a/ash/system/hotspot/hotspot_feature_pod_controller.h +++ b/ash/system/hotspot/hotspot_feature_pod_controller.h
@@ -9,6 +9,7 @@ #include "ash/ash_export.h" #include "ash/constants/quick_settings_catalogs.h" +#include "ash/system/hotspot/hotspot_icon_animation_observer.h" #include "ash/system/unified/feature_pod_controller_base.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" @@ -29,6 +30,7 @@ // detailed page with a Hotspot info. class ASH_EXPORT HotspotFeaturePodController : public FeaturePodControllerBase, + public HotspotIconAnimationObserver, public hotspot_config::mojom::CrosHotspotConfigObserver { public: explicit HotspotFeaturePodController( @@ -45,6 +47,9 @@ void OnIconPressed() override; void OnLabelPressed() override; + // HotspotIconAnimationObserver: + void HotspotIconChanged() override; + private: // mojom::CrosHotspotConfigObserver: void OnHotspotInfoChanged() override;
diff --git a/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc b/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc index 38914e2..bba6c89 100644 --- a/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc +++ b/ash/system/hotspot/hotspot_feature_pod_controller_unittest.cc
@@ -17,6 +17,7 @@ #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" #include "ui/base/l10n/l10n_util.h" @@ -39,7 +40,10 @@ class HotspotFeaturePodControllerTest : public AshTestBase { public: - HotspotFeaturePodControllerTest() = default; + HotspotFeaturePodControllerTest() + : AshTestBase(std::make_unique<base::test::TaskEnvironment>( + base::test::TaskEnvironment::MainThreadType::UI, + base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {} ~HotspotFeaturePodControllerTest() override = default; void SetUp() override { @@ -107,6 +111,10 @@ base::RunLoop().RunUntilIdle(); } + const char* GetVectorIconName() { + return hotspot_feature_tile_->vector_icon_->name; + } + void ExpectHotspotDetailedViewShown() { TrayDetailedView* detailed_view = GetPrimaryUnifiedSystemTray() ->bubble() @@ -144,6 +152,7 @@ UpdateHotspotInfo(HotspotState::kEnabled, HotspotAllowStatus::kAllowed, 2); EXPECT_EQ(u"Toggle Hotspot. Hotspot is on, 2 devices connected.", hotspot_feature_tile_->icon_button()->GetTooltipText()); + EXPECT_STREQ(kHotspotOnIcon.name, GetVectorIconName()); // Press on the label should navigate to the detailed page without toggle // hotspot. @@ -165,6 +174,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Show hotspot details. Hotspot is on.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOnIcon.name, GetVectorIconName()); // Press on the icon should toggle hotspot. PressIcon(); @@ -187,6 +197,12 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Show hotspot details. Hotspot is enabling.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotDotIcon.name, GetVectorIconName()); + // Verifies the hotspot icon is animating when enabling. + task_environment()->FastForwardBy(base::Milliseconds(500)); + EXPECT_STREQ(kHotspotOneArcIcon.name, GetVectorIconName()); + task_environment()->FastForwardBy(base::Milliseconds(500)); + EXPECT_STREQ(kHotspotOnIcon.name, GetVectorIconName()); // Press on the icon should navigate to the detailed page but not to toggle // hotspot. @@ -210,6 +226,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Show hotspot details. Hotspot is disabling.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the icon should navigate to the detailed page but not to toggle // hotspot. @@ -234,6 +251,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Toggle Hotspot. Hotspot is off.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the icon should toggle hotspot and navigate to the detailed page. PressIcon(); @@ -257,6 +275,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Toggle Hotspot. Hotspot is off.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the drive in label should toggle hotspot and navigate to the // detailed page. @@ -282,6 +301,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Show hotspot details. Hotspot is off.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the icon should navigate to the detailed page but not to toggle // hotspot. @@ -308,6 +328,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Show hotspot details. Hotspot is off.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the icon should navigate to the detailed page but not to toggle // hotspot. @@ -332,6 +353,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Show hotspot details. Hotspot is off.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the icon should navigate to the detailed page but not to toggle // hotspot. @@ -356,6 +378,7 @@ hotspot_feature_tile_->icon_button()->GetTooltipText()); EXPECT_EQ(u"Toggle Hotspot. Hotspot is off.", hotspot_feature_tile_->GetTooltipText()); + EXPECT_STREQ(kHotspotOffIcon.name, GetVectorIconName()); // Press on the icon should toggle hotspot and navigate to the detailed page. PressIcon();
diff --git a/ash/system/hotspot/hotspot_icon.cc b/ash/system/hotspot/hotspot_icon.cc new file mode 100644 index 0000000..5c1e94d --- /dev/null +++ b/ash/system/hotspot/hotspot_icon.cc
@@ -0,0 +1,48 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/hotspot/hotspot_icon.h" + +#include <utility> + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/shell.h" +#include "ash/system/hotspot/hotspot_icon_animation.h" +#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" + +namespace ash { + +using hotspot_config::mojom::HotspotState; + +namespace { + +constexpr int kNumEnablingImages = 3; + +} // namespace + +namespace hotspot_icon { + +const gfx::VectorIcon& GetIconForHotspot(const HotspotState& hotspot_state) { + if (hotspot_state == HotspotState::kEnabling) { + double animation = Shell::Get()->hotspot_icon_animation()->GetAnimation(); + int index = + animation * nextafter(static_cast<float>(kNumEnablingImages), 0); + index = std::clamp(index, 0, kNumEnablingImages - 1); + if (index == 0) { + return kHotspotDotIcon; + } + if (index == 1) { + return kHotspotOneArcIcon; + } + return kHotspotOnIcon; + } + + if (hotspot_state == HotspotState::kEnabled) { + return kHotspotOnIcon; + } + return kHotspotOffIcon; +} + +} // namespace hotspot_icon +} // namespace ash
diff --git a/ash/system/hotspot/hotspot_icon.h b/ash/system/hotspot/hotspot_icon.h new file mode 100644 index 0000000..4383370 --- /dev/null +++ b/ash/system/hotspot/hotspot_icon.h
@@ -0,0 +1,23 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_H_ +#define ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_H_ + +#include "ash/ash_export.h" +#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-forward.h" + +namespace gfx { +struct VectorIcon; +} // namespace gfx + +namespace ash::hotspot_icon { + +// Get the hotspot icon for the given `hotspot_state`. +ASH_EXPORT const gfx::VectorIcon& GetIconForHotspot( + const hotspot_config::mojom::HotspotState& hotspot_state); + +} // namespace ash::hotspot_icon + +#endif // ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_H_
diff --git a/ash/system/hotspot/hotspot_icon_animation.cc b/ash/system/hotspot/hotspot_icon_animation.cc new file mode 100644 index 0000000..10a3fb2 --- /dev/null +++ b/ash/system/hotspot/hotspot_icon_animation.cc
@@ -0,0 +1,56 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/hotspot/hotspot_icon_animation.h" + +#include "ash/system/hotspot/hotspot_icon_animation_observer.h" + +namespace ash { + +HotspotIconAnimation::HotspotIconAnimation() { + // Set up the animation throbber. + animation_.SetThrobDuration(base::Seconds(1)); + animation_.SetTweenType(gfx::Tween::LINEAR); +} + +HotspotIconAnimation::~HotspotIconAnimation() { + CHECK(observers_.empty()); +} + +void HotspotIconAnimation::AnimationProgressed( + const gfx::Animation* animation) { + if (animation != &animation_) { + return; + } + for (HotspotIconAnimationObserver& observer : observers_) { + observer.HotspotIconChanged(); + } +} + +double HotspotIconAnimation::GetAnimation() { + if (!animation_.is_animating()) { + animation_.Reset(); + animation_.StartThrobbing(/*throb indefinitely=*/-1); + return 0; + } + return animation_.GetCurrentValue(); +} + +void HotspotIconAnimation::AddObserver(HotspotIconAnimationObserver* observer) { + if (!observers_.HasObserver(observer)) { + observers_.AddObserver(observer); + } +} + +void HotspotIconAnimation::RemoveObserver( + HotspotIconAnimationObserver* observer) { + if (observers_.HasObserver(observer)) { + observers_.RemoveObserver(observer); + } + if (observers_.empty()) { + animation_.Reset(); // Stops the animation and resets the current value. + } +} + +} // namespace ash
diff --git a/ash/system/hotspot/hotspot_icon_animation.h b/ash/system/hotspot/hotspot_icon_animation.h new file mode 100644 index 0000000..83a61a5 --- /dev/null +++ b/ash/system/hotspot/hotspot_icon_animation.h
@@ -0,0 +1,41 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_H_ +#define ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_H_ + +#include "ash/ash_export.h" +#include "base/observer_list.h" +#include "ui/gfx/animation/animation_delegate.h" +#include "ui/gfx/animation/throb_animation.h" + +namespace ash { + +class HotspotIconAnimationObserver; + +// Single instance class to handle icon animations and keep them in sync. +class ASH_EXPORT HotspotIconAnimation : public gfx::AnimationDelegate { + public: + HotspotIconAnimation(); + ~HotspotIconAnimation() override; + + // Returns the current animation value, [0-1]. + double GetAnimation(); + + // The animation stops when all observers have been removed. + // Be sure to remove observers when no associated icons are animating. + void AddObserver(HotspotIconAnimationObserver* observer); + void RemoveObserver(HotspotIconAnimationObserver* observer); + + // gfx::AnimationDelegate: + void AnimationProgressed(const gfx::Animation* animation) override; + + private: + gfx::ThrobAnimation animation_{this}; + base::ObserverList<HotspotIconAnimationObserver> observers_; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_H_
diff --git a/ash/system/hotspot/hotspot_icon_animation_observer.h b/ash/system/hotspot/hotspot_icon_animation_observer.h new file mode 100644 index 0000000..56e3c79 --- /dev/null +++ b/ash/system/hotspot/hotspot_icon_animation_observer.h
@@ -0,0 +1,26 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_OBSERVER_H_ +#define ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_OBSERVER_H_ + +#include "ash/ash_export.h" +#include "base/observer_list_types.h" + +namespace ash { + +// Observer interface class for animating network icons. +class ASH_EXPORT HotspotIconAnimationObserver : public base::CheckedObserver { + public: + // Called when the image has changed due to animation. + virtual void HotspotIconChanged() = 0; + + protected: + HotspotIconAnimationObserver() = default; + ~HotspotIconAnimationObserver() override = default; +}; + +} // namespace ash + +#endif // ASH_SYSTEM_HOTSPOT_HOTSPOT_ICON_ANIMATION_OBSERVER_H_
diff --git a/ash/system/hotspot/hotspot_icon_unittest.cc b/ash/system/hotspot/hotspot_icon_unittest.cc new file mode 100644 index 0000000..ad14280 --- /dev/null +++ b/ash/system/hotspot/hotspot_icon_unittest.cc
@@ -0,0 +1,77 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/hotspot/hotspot_icon.h" + +#include "ash/constants/ash_features.h" +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/test/ash_test_base.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h" +#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" +#include "ui/gfx/vector_icon_types.h" + +namespace ash::hotspot_icon { + +using hotspot_config::mojom::HotspotState; + +class HotspotIconTest : public AshTestBase { + public: + HotspotIconTest() + : AshTestBase(std::make_unique<base::test::TaskEnvironment>( + base::test::TaskEnvironment::MainThreadType::UI, + base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {} + ~HotspotIconTest() override = default; + + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature(features::kHotspot); + cros_hotspot_config_test_helper_ = + std::make_unique<hotspot_config::CrosHotspotConfigTestHelper>( + /*use_fake_implementation=*/true); + AshTestBase::SetUp(); + } + + void TearDown() override { + AshTestBase::TearDown(); + cros_hotspot_config_test_helper_.reset(); + } + + protected: + base::test::ScopedFeatureList scoped_feature_list_; + std::unique_ptr<hotspot_config::CrosHotspotConfigTestHelper> + cros_hotspot_config_test_helper_; +}; + +TEST_F(HotspotIconTest, HotspotEnabledIcon) { + const gfx::VectorIcon& icon = + hotspot_icon::GetIconForHotspot(HotspotState::kEnabled); + EXPECT_STREQ(kHotspotOnIcon.name, icon.name); +} + +TEST_F(HotspotIconTest, HotspotDisabledIcon) { + const gfx::VectorIcon& icon = + hotspot_icon::GetIconForHotspot(HotspotState::kDisabled); + EXPECT_STREQ(kHotspotOffIcon.name, icon.name); +} + +TEST_F(HotspotIconTest, HotspotEnablingIcon) { + const gfx::VectorIcon& icon = + hotspot_icon::GetIconForHotspot(HotspotState::kEnabling); + EXPECT_STREQ(kHotspotDotIcon.name, icon.name); + task_environment()->FastForwardBy(base::Milliseconds(500)); + EXPECT_STREQ(kHotspotOneArcIcon.name, + hotspot_icon::GetIconForHotspot(HotspotState::kEnabling).name); + task_environment()->FastForwardBy(base::Milliseconds(500)); + EXPECT_STREQ(kHotspotOnIcon.name, + hotspot_icon::GetIconForHotspot(HotspotState::kEnabling).name); +} + +TEST_F(HotspotIconTest, HotspotDisablingIcon) { + const gfx::VectorIcon& icon = + hotspot_icon::GetIconForHotspot(HotspotState::kDisabling); + EXPECT_STREQ(kHotspotOffIcon.name, icon.name); +} + +} // namespace ash::hotspot_icon
diff --git a/ash/system/network/hotspot_notifier.cc b/ash/system/hotspot/hotspot_notifier.cc similarity index 99% rename from ash/system/network/hotspot_notifier.cc rename to ash/system/hotspot/hotspot_notifier.cc index b0e9452..0535800e 100644 --- a/ash/system/network/hotspot_notifier.cc +++ b/ash/system/hotspot/hotspot_notifier.cc
@@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/network/hotspot_notifier.h" +#include "ash/system/hotspot/hotspot_notifier.h" + #include "ash/public/cpp/hotspot_config_service.h" #include "ash/public/cpp/network_config_service.h" #include "ash/public/cpp/notification_utils.h" @@ -284,4 +285,4 @@ return notification; } -} // namespace ash \ No newline at end of file +} // namespace ash
diff --git a/ash/system/network/hotspot_notifier.h b/ash/system/hotspot/hotspot_notifier.h similarity index 95% rename from ash/system/network/hotspot_notifier.h rename to ash/system/hotspot/hotspot_notifier.h index 8b96dccd..602ed727 100644 --- a/ash/system/network/hotspot_notifier.h +++ b/ash/system/hotspot/hotspot_notifier.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef ASH_SYSTEM_NETWORK_HOTSPOT_NOTIFIER_H_ -#define ASH_SYSTEM_NETWORK_HOTSPOT_NOTIFIER_H_ +#ifndef ASH_SYSTEM_HOTSPOT_HOTSPOT_NOTIFIER_H_ +#define ASH_SYSTEM_HOTSPOT_HOTSPOT_NOTIFIER_H_ #include "ash/ash_export.h" #include "base/memory/weak_ptr.h" @@ -91,4 +91,4 @@ } // namespace ash -#endif // ASH_SYSTEM_NETWORK_HOTSPOT_NOTIFIER_H_ \ No newline at end of file +#endif // ASH_SYSTEM_HOTSPOT_HOTSPOT_NOTIFIER_H_
diff --git a/ash/system/network/hotspot_notifier_unittest.cc b/ash/system/hotspot/hotspot_notifier_unittest.cc similarity index 99% rename from ash/system/network/hotspot_notifier_unittest.cc rename to ash/system/hotspot/hotspot_notifier_unittest.cc index f96d828..e33c6b2bf 100644 --- a/ash/system/network/hotspot_notifier_unittest.cc +++ b/ash/system/hotspot/hotspot_notifier_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ash/system/network/hotspot_notifier.h" +#include "ash/system/hotspot/hotspot_notifier.h" #include "ash/constants/ash_features.h" #include "ash/test/ash_test_base.h" #include "base/test/bind.h"
diff --git a/ash/system/hotspot/hotspot_tray_view.cc b/ash/system/hotspot/hotspot_tray_view.cc index 85094ec..3a1f62d 100644 --- a/ash/system/hotspot/hotspot_tray_view.cc +++ b/ash/system/hotspot/hotspot_tray_view.cc
@@ -9,7 +9,8 @@ #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" -#include "ash/style/ash_color_provider.h" +#include "ash/system/hotspot/hotspot_icon.h" +#include "ash/system/hotspot/hotspot_icon_animation.h" #include "ash/system/tray/tray_constants.h" #include "chromeos/constants/chromeos_features.h" #include "ui/base/l10n/l10n_util.h" @@ -59,6 +60,7 @@ HotspotTrayView::~HotspotTrayView() { Shell::Get()->session_controller()->RemoveObserver(this); + Shell::Get()->hotspot_icon_animation()->RemoveObserver(this); } const char* HotspotTrayView::GetClassName() const { @@ -112,25 +114,33 @@ } void HotspotTrayView::UpdateIconImage() { - SkColor color; - if (chromeos::features::IsJellyEnabled()) { - color = GetColorProvider()->GetColor(cros_tokens::kCrosSysPrimary); - } else { - color = AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kIconColorPrimary); - } - image_view()->SetImage( - gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize, color)); + image_view()->SetImage(ui::ImageModel::FromVectorIcon( + hotspot_icon::GetIconForHotspot(state_), cros_tokens::kCrosSysOnSurface, + kUnifiedTrayIconSize)); +} + +void HotspotTrayView::HotspotIconChanged() { + UpdateIconImage(); } void HotspotTrayView::OnGetHotspotInfo(HotspotInfoPtr hotspot_info) { - if (hotspot_info->state != HotspotState::kEnabled) { + if (hotspot_info->state == HotspotState::kDisabled) { SetVisible(false); return; } SetVisible(true); tooltip_ = ComputeHotspotTooltip(hotspot_info->client_count); + + if (hotspot_info->state == HotspotState::kEnabling) { + Shell::Get()->hotspot_icon_animation()->AddObserver(this); + } else if (state_ == HotspotState::kEnabling) { + Shell::Get()->hotspot_icon_animation()->RemoveObserver(this); + } + if (state_ != hotspot_info->state) { + state_ = hotspot_info->state; + UpdateIconImage(); + } } } // namespace ash
diff --git a/ash/system/hotspot/hotspot_tray_view.h b/ash/system/hotspot/hotspot_tray_view.h index 2a76a485..71f500d 100644 --- a/ash/system/hotspot/hotspot_tray_view.h +++ b/ash/system/hotspot/hotspot_tray_view.h
@@ -9,6 +9,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/session/session_observer.h" +#include "ash/system/hotspot/hotspot_icon_animation_observer.h" #include "ash/system/tray/tray_item_view.h" #include "base/memory/weak_ptr.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" @@ -22,6 +23,7 @@ class ASH_EXPORT HotspotTrayView : public TrayItemView, public SessionObserver, + public HotspotIconAnimationObserver, public hotspot_config::mojom::CrosHotspotConfigObserver { public: explicit HotspotTrayView(Shelf* shelf); @@ -50,6 +52,9 @@ // mojom::CrosHotspotConfigObserver: void OnHotspotInfoChanged() override; + // HotspotIconAnimationObserver: + void HotspotIconChanged() override; + void OnGetHotspotInfo(hotspot_config::mojom::HotspotInfoPtr hotspot_info); void UpdateIconImage(); @@ -58,6 +63,9 @@ // The tooltip and accessible name string used for the icon. std::u16string tooltip_; + hotspot_config::mojom::HotspotState state_ = + hotspot_config::mojom::HotspotState::kDisabled; + mojo::Remote<hotspot_config::mojom::CrosHotspotConfig> remote_cros_hotspot_config_; mojo::Receiver<hotspot_config::mojom::CrosHotspotConfigObserver>
diff --git a/ash/system/hotspot/hotspot_tray_view_unittest.cc b/ash/system/hotspot/hotspot_tray_view_unittest.cc index f7a9627..6ffb843 100644 --- a/ash/system/hotspot/hotspot_tray_view_unittest.cc +++ b/ash/system/hotspot/hotspot_tray_view_unittest.cc
@@ -8,12 +8,12 @@ #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shelf/shelf.h" #include "ash/strings/grit/ash_strings.h" -#include "ash/style/ash_color_provider.h" #include "ash/system/tray/tray_constants.h" #include "ash/test/ash_test_base.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "chromeos/ash/services/hotspot_config/public/cpp/cros_hotspot_config_test_helper.h" #include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h" #include "chromeos/constants/chromeos_features.h" @@ -40,14 +40,16 @@ } // namespace -class HotspotTrayViewTest : public NoSessionAshTestBase, +class HotspotTrayViewTest : public AshTestBase, public testing::WithParamInterface<bool> { public: - HotspotTrayViewTest() = default; + HotspotTrayViewTest() + : AshTestBase(std::make_unique<base::test::TaskEnvironment>( + base::test::TaskEnvironment::MainThreadType::UI, + base::test::TaskEnvironment::TimeSource::MOCK_TIME)) {} ~HotspotTrayViewTest() override = default; void SetUp() override { - AshTestBase::SetUp(); if (IsJellyEnabled()) { scoped_feature_list_.InitWithFeatures( {features::kHotspot, chromeos::features::kJelly}, {}); @@ -57,12 +59,12 @@ cros_hotspot_config_test_helper_ = std::make_unique<hotspot_config::CrosHotspotConfigTestHelper>( /*use_fake_implementation=*/true); + AshTestBase::SetUp(); std::unique_ptr<HotspotTrayView> hotspot_tray_view = std::make_unique<HotspotTrayView>(GetPrimaryShelf()); widget_ = CreateFramelessTestWidget(); widget_->SetFullscreen(true); hotspot_tray_view_ = widget_->SetContentsView(std::move(hotspot_tray_view)); - LogIn(); // Spin the runloop to sync up the latest hotspot info. base::RunLoop().RunUntilIdle(); @@ -74,8 +76,6 @@ AshTestBase::TearDown(); } - void LogIn() { SimulateUserLogin("user1@test.com"); } - void SetHotspotStateAndClientCount(HotspotState state, size_t client_count) { auto hotspot_info = HotspotInfo::New(); hotspot_info->state = state; @@ -108,21 +108,39 @@ INSTANTIATE_TEST_SUITE_P(Jelly, HotspotTrayViewTest, testing::Bool()); TEST_P(HotspotTrayViewTest, HotspotIconImage) { + SetHotspotStateAndClientCount(HotspotState::kDisabled, 0); + EXPECT_TRUE(AreImagesEqual( + hotspot_tray_view_->image_view()->GetImage(), + gfx::CreateVectorIcon(kHotspotOffIcon, kUnifiedTrayIconSize, + widget_->GetColorProvider()->GetColor( + cros_tokens::kCrosSysOnSurface)))); + SetHotspotStateAndClientCount(HotspotState::kEnabled, 0); - if (IsJellyEnabled()) { - EXPECT_TRUE(AreImagesEqual( - hotspot_tray_view_->image_view()->GetImage(), - gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize, - widget_->GetColorProvider()->GetColor( - cros_tokens::kCrosSysPrimary)))); - } else { - EXPECT_TRUE(AreImagesEqual( - hotspot_tray_view_->image_view()->GetImage(), - gfx::CreateVectorIcon( - kHotspotOnIcon, kUnifiedTrayIconSize, - AshColorProvider::Get()->GetContentLayerColor( - AshColorProvider::ContentLayerType::kIconColorPrimary)))); - } + EXPECT_TRUE(AreImagesEqual( + hotspot_tray_view_->image_view()->GetImage(), + gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize, + widget_->GetColorProvider()->GetColor( + cros_tokens::kCrosSysOnSurface)))); + + SetHotspotStateAndClientCount(HotspotState::kEnabling, 0); + EXPECT_TRUE(AreImagesEqual( + hotspot_tray_view_->image_view()->GetImage(), + gfx::CreateVectorIcon(kHotspotDotIcon, kUnifiedTrayIconSize, + widget_->GetColorProvider()->GetColor( + cros_tokens::kCrosSysOnSurface)))); + // Verifies the hotspot icon is animating when enabling. + task_environment()->FastForwardBy(base::Milliseconds(500)); + EXPECT_TRUE(AreImagesEqual( + hotspot_tray_view_->image_view()->GetImage(), + gfx::CreateVectorIcon(kHotspotOneArcIcon, kUnifiedTrayIconSize, + widget_->GetColorProvider()->GetColor( + cros_tokens::kCrosSysOnSurface)))); + task_environment()->FastForwardBy(base::Milliseconds(500)); + EXPECT_TRUE(AreImagesEqual( + hotspot_tray_view_->image_view()->GetImage(), + gfx::CreateVectorIcon(kHotspotOnIcon, kUnifiedTrayIconSize, + widget_->GetColorProvider()->GetColor( + cros_tokens::kCrosSysOnSurface)))); } TEST_P(HotspotTrayViewTest, HotspotIconVisibility) { @@ -133,6 +151,9 @@ SetHotspotStateAndClientCount(HotspotState::kDisabled, 0); EXPECT_FALSE(IsIconVisible()); + + SetHotspotStateAndClientCount(HotspotState::kEnabling, 0); + EXPECT_TRUE(IsIconVisible()); } TEST_P(HotspotTrayViewTest, HotspotIconTooltip) {
diff --git a/ash/system/network/network_feature_tile_pixeltest.cc b/ash/system/network/network_feature_tile_pixeltest.cc index 0d617e9..b3cb8ec 100644 --- a/ash/system/network/network_feature_tile_pixeltest.cc +++ b/ash/system/network/network_feature_tile_pixeltest.cc
@@ -35,7 +35,8 @@ "GUID": "%s", "Type": "ethernet", "State": "online"})"; constexpr char kServicePatternWiFi[] = R"({ - "GUID": "%s", "Type": "wifi", "State": "online", "Strength": 100})"; + "GUID": "%s", "Type": "wifi", "State": "online", + "Strength": 100, "SecurityClass": "%s"})"; } // namespace // Pixel test for the quick settings network feature tile view. @@ -109,10 +110,11 @@ base::RunLoop().RunUntilIdle(); } - void SetupWiFi() { + void SetupWiFi(const std::string& security) { ASSERT_TRUE(wifi_path_.empty()); - wifi_path_ = ConfigureService( - base::StringPrintf(kServicePatternWiFi, kNetworkGuidWifi)); + wifi_path_ = ConfigureService(base::StringPrintf( + kServicePatternWiFi, kNetworkGuidWifi, security.c_str())); + base::RunLoop().RunUntilIdle(); } @@ -163,7 +165,7 @@ ASSERT_TRUE( network_state_handler()->IsTechnologyEnabled(NetworkTypePattern::WiFi())); - SetupWiFi(); + SetupWiFi("None"); auto* tile_view = feature_tile(); ASSERT_TRUE(tile_view); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( @@ -171,6 +173,18 @@ /*revision_number=*/1, tile_view)); } +TEST_F(NetworkFeatureTilePixelTest, WifiSecurity) { + ASSERT_TRUE( + network_state_handler()->IsTechnologyEnabled(NetworkTypePattern::WiFi())); + + SetupWiFi("wep"); + auto* tile_view = feature_tile(); + ASSERT_TRUE(tile_view); + EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( + "check_tile_view", + /*revision_number=*/0, tile_view)); +} + TEST_F(NetworkFeatureTilePixelTest, Cellular) { ASSERT_TRUE(network_state_handler()->IsTechnologyEnabled( NetworkTypePattern::Cellular()));
diff --git a/ash/system/notification_center/notification_center_test_api.cc b/ash/system/notification_center/notification_center_test_api.cc index 74cc498..7feab12f 100644 --- a/ash/system/notification_center/notification_center_test_api.cc +++ b/ash/system/notification_center/notification_center_test_api.cc
@@ -138,9 +138,16 @@ } bool NotificationCenterTestApi::IsPinnedIconShown() { - return notification_center_tray_->notification_icons_controller_->tray_items() - .back() - ->GetVisible(); + return IsPinnedIconShownOnDisplay(primary_display_id_); +} + +bool NotificationCenterTestApi::IsPinnedIconShownOnDisplay(int64_t display_id) { + auto* notification_center_tray = GetTrayOnDisplay(display_id); + CHECK(notification_center_tray); + auto tray_items = + notification_center_tray->notification_icons_controller_->tray_items(); + CHECK(!tray_items.empty()); + return tray_items.back()->GetVisible(); } bool NotificationCenterTestApi::IsPopupShown(const std::string& id) { @@ -188,7 +195,19 @@ } NotificationCenterTray* NotificationCenterTestApi::GetTray() { - return notification_center_tray_; + return features::IsQsRevampEnabled() ? notification_center_tray_ : nullptr; +} + +NotificationCenterTray* NotificationCenterTestApi::GetTrayOnDisplay( + int64_t display_id) { + auto* root_window_controller = + Shell::Get()->GetRootWindowControllerWithDisplayId(display_id); + if (!root_window_controller || !features::IsQsRevampEnabled()) { + return nullptr; + } + return root_window_controller->shelf() + ->status_area_widget() + ->notification_center_tray(); } views::Widget* NotificationCenterTestApi::GetWidget() {
diff --git a/ash/system/notification_center/notification_center_test_api.h b/ash/system/notification_center/notification_center_test_api.h index 488640a..6fe66f48 100644 --- a/ash/system/notification_center/notification_center_test_api.h +++ b/ash/system/notification_center/notification_center_test_api.h
@@ -93,9 +93,15 @@ // Returns true if `NotificationCenterBubble` is shown, false otherwise. bool IsBubbleShown(); - // Returns true if a pinned icons is shown in the `NotificationCenterTray`. + // Returns true if a pinned icon is shown in the primary display's + // `NotificationCenterTray`. bool IsPinnedIconShown(); + // Returns true if a pinned icon is shown in the `NotificationCenterTray` + // associated with the display having an id of `display_id`. `CHECK()`s that + // there exists a notification center tray associated with that display. + bool IsPinnedIconShownOnDisplay(int64_t display_id); + // Returns true if a popup associated with the provided `id` exists, false // otherwise. bool IsPopupShown(const std::string& id); @@ -122,9 +128,15 @@ // nullptr otherwise. message_center::MessagePopupView* GetPopupViewForId(const std::string& id); - // Returns the `NotificationCenterTray` in the shelf. + // Returns the `NotificationCenterTray` for the primary display, or nullptr if + // QS revamp is not enabled. NotificationCenterTray* GetTray(); + // Returns the `NotificationCenterTray` associated with the display having an + // id of `display_id`, or nullptr if there is no display with that id. Also + // returns nullptr if QS revamp is not enabled. + NotificationCenterTray* GetTrayOnDisplay(int64_t display_id); + // Returns the widget that owns the `TrayBubbleView` for the notification // center. views::Widget* GetWidget();
diff --git a/ash/system/notification_center/notification_center_tray_unittest.cc b/ash/system/notification_center/notification_center_tray_unittest.cc index 522fce9e..c70d6732 100644 --- a/ash/system/notification_center/notification_center_tray_unittest.cc +++ b/ash/system/notification_center/notification_center_tray_unittest.cc
@@ -16,12 +16,15 @@ #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" #include "ash/system/tray/tray_constants.h" +#include "ash/system/unified/notification_counter_view.h" #include "ash/system/unified/unified_system_tray.h" #include "ash/test/ash_test_base.h" #include "base/command_line.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" +#include "chromeos/ash/components/login/auth/auth_events_recorder.h" #include "ui/base/accelerators/accelerator.h" +#include "ui/compositor/scoped_animation_duration_scale_mode.h" namespace ash { @@ -289,6 +292,52 @@ test_api()->GetTray()->size() + kTrayBackgroundFocusPadding.size()); } +// Tests that `NotificationCounterView` is not still visible on secondary +// display after logging in with a pinned notification present. This covers +// b/284139989. +TEST_F(NotificationCenterTrayTest, + NotificationCounterVisibilityForMultiDisplay) { + // The behavior under test relies on `TrayItemView` animations being + // scheduled, but `TrayItemView` animations are bypassed when the animation + // duration scale mode is set to ZERO_DURATION. Hence, set the animation + // duration scale mode to something else for this test. + ui::ScopedAnimationDurationScaleMode test_duration_mode( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + + // This test relies on the lock screen actually being created (and creating + // the lock screen requires the existence of an `AuthEventsRecorder`). + std::unique_ptr<AuthEventsRecorder> auth_events_recorder = + AuthEventsRecorder::CreateForTesting(); + GetSessionControllerClient()->set_show_lock_screen_views(true); + + // Create two displays. + UpdateDisplay("800x799,800x799"); + auto secondary_display_id = display_manager()->GetDisplayAt(1).id(); + auto* secondary_notification_center_tray = + test_api()->GetTrayOnDisplay(secondary_display_id); + auto* secondary_notification_counter_view = + secondary_notification_center_tray->notification_icons_controller() + ->notification_counter_view(); + + // Add a pinned notification. + test_api()->AddPinnedNotification(); + + // Verify that the secondary display's notification center tray shows an icon + // for the pinned notification and not the `NotificationCounterView`. + ASSERT_TRUE(test_api()->IsPinnedIconShownOnDisplay(secondary_display_id)); + ASSERT_FALSE(secondary_notification_counter_view->GetVisible()); + + // Go to the lock screen. + GetSessionControllerClient()->LockScreen(); + + // Log back in. + GetSessionControllerClient()->UnlockScreen(); + + // Verify that the `NotificationCounterView` on the secondary display is not + // visible. + EXPECT_FALSE(secondary_notification_counter_view->GetVisible()); +} + // Test suite for the notification center when `kPrivacyIndicators` is enabled. class NotificationCenterTrayPrivacyIndicatorsTest : public AshTestBase { public:
diff --git a/ash/system/status_area_animation_controller.cc b/ash/system/status_area_animation_controller.cc index bb81663..ab9baf2 100644 --- a/ash/system/status_area_animation_controller.cc +++ b/ash/system/status_area_animation_controller.cc
@@ -89,11 +89,20 @@ views::AnimationBuilder() .SetPreemptionStrategy(ui::LayerAnimator::PreemptionStrategy:: IMMEDIATELY_ANIMATE_TO_NEW_TARGET) + .OnScheduled(base::BindOnce( + [](base::WeakPtr<StatusAreaAnimationController> ptr) { + if (!ptr) { + return; + } + ptr->is_hide_animation_scheduled_ = true; + }, + weak_factory_.GetWeakPtr())) .OnAborted(base::BindOnce( [](base::WeakPtr<StatusAreaAnimationController> ptr) { if (!ptr) { return; } + ptr->is_hide_animation_scheduled_ = false; ptr->notification_center_tray_->OnAnimationAborted(); ptr->ImmediatelyUpdateTrayItemVisibilities(); }, @@ -103,6 +112,7 @@ if (!ptr) { return; } + ptr->is_hide_animation_scheduled_ = false; ptr->notification_center_tray_->OnAnimationEnded(); ptr->ImmediatelyUpdateTrayItemVisibilities(); },
diff --git a/ash/system/status_area_animation_controller.h b/ash/system/status_area_animation_controller.h index fd2440d8..1d58948 100644 --- a/ash/system/status_area_animation_controller.h +++ b/ash/system/status_area_animation_controller.h
@@ -28,6 +28,9 @@ const StatusAreaAnimationController&) = delete; ~StatusAreaAnimationController() override; + // Returns true if the "hide" animation is scheduled to run, false otherwise. + bool is_hide_animation_scheduled() { return is_hide_animation_scheduled_; } + private: // Starts running the visibility animation sequence. This will be the "show" // animation sequence if `visible` is true, otherwise it will be the "hide" @@ -65,6 +68,9 @@ notification_center_tray_item_animation_enablers_; raw_ptr<NotificationCenterTray, ExperimentalAsh> notification_center_tray_; + // Whether the "hide" animation is scheduled to be run. + bool is_hide_animation_scheduled_ = false; + base::WeakPtrFactory<StatusAreaAnimationController> weak_factory_{this}; };
diff --git a/ash/system/status_area_widget.h b/ash/system/status_area_widget.h index e0170efd..9682a59 100644 --- a/ash/system/status_area_widget.h +++ b/ash/system/status_area_widget.h
@@ -199,6 +199,10 @@ collapse_state_ = state; } + StatusAreaAnimationController* animation_controller() { + return animation_controller_.get(); + } + private: friend class MediaTrayTest; friend class TrayBackgroundViewTest;
diff --git a/ash/system/system_notification_controller.cc b/ash/system/system_notification_controller.cc index 782ed5a..17761da 100644 --- a/ash/system/system_notification_controller.cc +++ b/ash/system/system_notification_controller.cc
@@ -11,10 +11,10 @@ #include "ash/system/cast/cast_notification_controller.h" #include "ash/system/do_not_disturb_notification_controller.h" #include "ash/system/gesture_education/gesture_education_notification_controller.h" +#include "ash/system/hotspot/hotspot_notifier.h" #include "ash/system/lock_screen_notification_controller.h" #include "ash/system/network/auto_connect_notifier.h" #include "ash/system/network/cellular_setup_notifier.h" -#include "ash/system/network/hotspot_notifier.h" #include "ash/system/network/managed_sim_lock_notifier.h" #include "ash/system/network/wifi_toggle_notification_controller.h" #include "ash/system/power/power_notification_controller.h"
diff --git a/ash/system/tray/system_nudge_controller.cc b/ash/system/tray/system_nudge_controller.cc index 4e3a9541..22d4a1d 100644 --- a/ash/system/tray/system_nudge_controller.cc +++ b/ash/system/tray/system_nudge_controller.cc
@@ -84,7 +84,8 @@ } // static -void SystemNudgeController::RecordNudgeAction(NudgeCatalogName catalog_name) { +void SystemNudgeController::MaybeRecordNudgeAction( + NudgeCatalogName catalog_name) { auto& nudge_registry = GetNudgeRegistry(); auto it = std::find_if( std::begin(nudge_registry), std::end(nudge_registry),
diff --git a/ash/system/tray/system_nudge_controller.h b/ash/system/tray/system_nudge_controller.h index 31c80ed..d8dc1db 100644 --- a/ash/system/tray/system_nudge_controller.h +++ b/ash/system/tray/system_nudge_controller.h
@@ -31,8 +31,8 @@ // Records Nudge "TimeToAction" metric, which tracks the time from when a // nudge was shown to when the nudge's suggested action was performed. - // The metric is not recorded if the nudge hasn't been shown before. - static void RecordNudgeAction(NudgeCatalogName catalog_name); + // No op if the nudge specified by `catalog_name` hasn't been shown before. + static void MaybeRecordNudgeAction(NudgeCatalogName catalog_name); // Shows the nudge widget. void ShowNudge();
diff --git a/ash/system/tray/system_nudge_unittest.cc b/ash/system/tray/system_nudge_unittest.cc index 91d7f2f..b4061d5 100644 --- a/ash/system/tray/system_nudge_unittest.cc +++ b/ash/system/tray/system_nudge_unittest.cc
@@ -150,20 +150,20 @@ nudge_controller->ResetNudgeRegistryForTesting(); // Metric is not recorded if nudge has not been shown. - SystemNudgeController::RecordNudgeAction(kTestCatalogName); + SystemNudgeController::MaybeRecordNudgeAction(kTestCatalogName); histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1m, kTestCatalogName, 0); // Metric is recorded after nudge is shown. nudge_controller->ShowNudge(); task_environment()->FastForwardBy(base::Seconds(1)); - SystemNudgeController::RecordNudgeAction(kTestCatalogName); + SystemNudgeController::MaybeRecordNudgeAction(kTestCatalogName); histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1m, kTestCatalogName, 1); // Metric is not recorded if the nudge action is performed again without // another nudge being shown. - SystemNudgeController::RecordNudgeAction(kTestCatalogName); + SystemNudgeController::MaybeRecordNudgeAction(kTestCatalogName); histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1m, kTestCatalogName, 1); @@ -171,13 +171,13 @@ // and waiting the time to fall into the next time bucket. nudge_controller->ShowNudge(); task_environment()->FastForwardBy(base::Minutes(2)); - SystemNudgeController::RecordNudgeAction(kTestCatalogName); + SystemNudgeController::MaybeRecordNudgeAction(kTestCatalogName); histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithin1h, kTestCatalogName, 1); nudge_controller->ShowNudge(); task_environment()->FastForwardBy(base::Hours(2)); - SystemNudgeController::RecordNudgeAction(kTestCatalogName); + SystemNudgeController::MaybeRecordNudgeAction(kTestCatalogName); histogram_tester.ExpectBucketCount(kNudgeTimeToActionWithinSession, kTestCatalogName, 1); }
diff --git a/ash/system/tray/tray_item_view.cc b/ash/system/tray/tray_item_view.cc index 86fdbe8..64c79ff 100644 --- a/ash/system/tray/tray_item_view.cc +++ b/ash/system/tray/tray_item_view.cc
@@ -7,6 +7,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/shelf_types.h" #include "ash/shelf/shelf.h" +#include "ash/system/status_area_animation_controller.h" #include "ash/system/tray/tray_constants.h" #include "base/metrics/histogram_functions.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -173,13 +174,16 @@ // Immediately progress to the end of the animation if animation is disabled. if (!ShouldVisibilityChangeBeAnimated()) { - // Tray items need to stay visible during the notification center tray's - // hide animation, so don't do anything here. + // Tray items need to stay visible if the notification center tray's hide + // animation is going to run, so don't hide the tray item here. // `StatusAreaAnimationController` will call `ImmediatelyUpdateVisibility()` // once the hide animation is over to ensure that all tray items are given a // chance to properly update their visibilities. Only applicable when the // QS revamp is enabled. - if (features::IsQsRevampEnabled() && !target_visible_) { + if (features::IsQsRevampEnabled() && !target_visible_ && + shelf_->status_area_widget() + ->animation_controller() + ->is_hide_animation_scheduled()) { return; } animation_->SetSlideDuration(base::TimeDelta());
diff --git a/ash/system/unified/feature_tile.cc b/ash/system/unified/feature_tile.cc index 4e7636a..7c1c7ed 100644 --- a/ash/system/unified/feature_tile.cc +++ b/ash/system/unified/feature_tile.cc
@@ -271,6 +271,7 @@ toggled_ = toggled; UpdateColors(); + views::InkDrop::Get(this)->GetInkDrop()->SnapToHidden(); } bool FeatureTile::IsToggled() const {
diff --git a/ash/system/unified/feature_tile.h b/ash/system/unified/feature_tile.h index b1bde23..182b7fc 100644 --- a/ash/system/unified/feature_tile.h +++ b/ash/system/unified/feature_tile.h
@@ -124,6 +124,7 @@ private: friend class BluetoothFeaturePodControllerTest; + friend class HotspotFeaturePodControllerTest; friend class NotificationCounterViewTest; // views::View:
diff --git a/ash/system/unified/feature_tile_unittest.cc b/ash/system/unified/feature_tile_unittest.cc index 52fb04a..af05266 100644 --- a/ash/system/unified/feature_tile_unittest.cc +++ b/ash/system/unified/feature_tile_unittest.cc
@@ -19,6 +19,7 @@ #include "components/vector_icons/vector_icons.h" #include "ui/chromeos/styles/cros_tokens_color_mappings.h" #include "ui/views/animation/ink_drop.h" +#include "ui/views/animation/ink_drop_state.h" #include "ui/views/controls/image_view.h" #include "ui/views/test/views_test_utils.h" @@ -356,4 +357,16 @@ color_provider->GetColor(cros_tokens::kCrosSysRippleNeutralOnSubtle)); } +// Regression test for http://b/284318391 +TEST_F(FeatureTileTest, TogglingTileHidesInkDrop) { + auto mock_controller = std::make_unique<MockFeaturePodController>( + /*togglable=*/true); + auto* tile = widget_->SetContentsView(mock_controller->CreateTile()); + + LeftClickOn(tile); + ASSERT_TRUE(tile->IsToggled()); + EXPECT_EQ(views::InkDrop::Get(tile)->GetInkDrop()->GetTargetInkDropState(), + views::InkDropState::HIDDEN); +} + } // namespace ash
diff --git a/ash/user_education/welcome_tour/welcome_tour_controller.cc b/ash/user_education/welcome_tour/welcome_tour_controller.cc index bd0bb7df..627bfd5 100644 --- a/ash/user_education/welcome_tour/welcome_tour_controller.cc +++ b/ash/user_education/welcome_tour/welcome_tour_controller.cc
@@ -103,7 +103,6 @@ GetMatchingViewInPrimaryRootWindow(kShelfViewElementId)); } -// TODO(http://b/275616974): Implement tutorial descriptions. std::map<TutorialId, user_education::TutorialDescription> WelcomeTourController::GetTutorialDescriptions() { std::map<TutorialId, user_education::TutorialDescription> @@ -132,7 +131,8 @@ user_education::kHelpBubbleNextButtonClickedEvent, kShelfViewElementId) .NameElements(NameMatchingElementInPrimaryRootWindowCallback( - kUnifiedSystemTrayElementId, kUnifiedSystemTrayElementName))); + kUnifiedSystemTrayElementId, kUnifiedSystemTrayElementName)) + .InSameContext()); // Step 2: Status area. tutorial_description.steps.emplace_back( @@ -141,7 +141,8 @@ .SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT) .SetExtendedProperties(user_education_util::CreateExtendedProperties( HelpBubbleId::kWelcomeTourStatusArea)) - .AddDefaultNextButton()); + .AddDefaultNextButton() + .InAnyContext()); // Wait for "Next" button click before proceeding to the next bubble step. // NOTE: This event step also ensures that the next bubble step will show on @@ -151,7 +152,8 @@ user_education::kHelpBubbleNextButtonClickedEvent, kUnifiedSystemTrayElementName) .NameElements(NameMatchingElementInPrimaryRootWindowCallback( - kHomeButtonElementId, kHomeButtonElementName))); + kHomeButtonElementId, kHomeButtonElementName)) + .InSameContext()); // Step 3: Home button. tutorial_description.steps.emplace_back( @@ -162,8 +164,10 @@ .AddCustomNextButton(base::BindRepeating([](ui::TrackedElement*) { Shell::Get()->app_list_controller()->Show( GetPrimaryDisplayId(), AppListShowSource::kWelcomeTour, - ui::EventTimeForNow(), /*should_record_metrics=*/true); - }))); + ui::EventTimeForNow(), + /*should_record_metrics=*/true); + })) + .InAnyContext()); // Step 4: Search box. tutorial_description.steps.emplace_back( @@ -174,20 +178,36 @@ .AddDefaultNextButton() .InAnyContext()); + // Wait for "Next" button click before proceeding to the next bubble step. + tutorial_description.steps.emplace_back( + user_education::TutorialDescription::EventStep( + user_education::kHelpBubbleNextButtonClickedEvent, + kSearchBoxViewElementId) + .InSameContext()); + // Step 5: Settings app. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kSettingsAppElementId) .SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_BODY_TEXT) .SetExtendedProperties(user_education_util::CreateExtendedProperties( HelpBubbleId::kWelcomeTourSettingsApp)) - .AddDefaultNextButton()); + .AddDefaultNextButton() + .InSameContext()); + + // Wait for "Next" button click before proceeding to the next bubble step. + tutorial_description.steps.emplace_back( + user_education::TutorialDescription::EventStep( + user_education::kHelpBubbleNextButtonClickedEvent, + kSettingsAppElementId) + .InSameContext()); // Step 6: Explore app. tutorial_description.steps.emplace_back( user_education::TutorialDescription::BubbleStep(kExploreAppElementId) .SetBubbleBodyText(IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT) .SetExtendedProperties(user_education_util::CreateExtendedProperties( - HelpBubbleId::kWelcomeTourExploreApp))); + HelpBubbleId::kWelcomeTourExploreApp)) + .InSameContext()); return tutorial_descriptions_by_id; }
diff --git a/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc b/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc index 28cdcd74..3c4108d 100644 --- a/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc +++ b/ash/user_education/welcome_tour/welcome_tour_controller_unittest.cc
@@ -38,10 +38,12 @@ using ::testing::ElementsAre; using ::testing::Eq; using ::testing::Field; +using ::testing::Matches; using ::testing::Pair; using ::testing::StrictMock; using ::user_education::TutorialDescription; +using ContextMode = TutorialDescription::ContextMode; using ElementSpecifier = TutorialDescription::ElementSpecifier; // Actions --------------------------------------------------------------------- @@ -60,18 +62,8 @@ // Matchers -------------------------------------------------------------------- -MATCHER_P4(BubbleStep, - help_bubble_id, - element_specifier, - body_text_id, - has_next_button, - "") { - namespace util = user_education_util; - return arg.step_type == ui::InteractionSequence::StepType::kShown && - util::GetHelpBubbleId(arg.extended_properties) == help_bubble_id && - arg.body_text_id == body_text_id && - arg.next_button_callback.is_null() != has_next_button && - absl::visit(base::Overloaded{ +MATCHER_P(ElementSpecifierEq, element_specifier, "") { + return absl::visit(base::Overloaded{ [&](const ui::ElementIdentifier& element_id) { return arg.element_id == element_id && arg.element_name.empty(); @@ -84,20 +76,31 @@ element_specifier); } -MATCHER_P2(EventStep, element_specifier, has_name_elements_callback, "") { +MATCHER_P5(BubbleStep, + element_specifier, + context_mode, + help_bubble_id, + body_text_id, + has_next_button, + "") { + namespace util = user_education_util; + return arg.step_type == ui::InteractionSequence::StepType::kShown && + Matches(ElementSpecifierEq(element_specifier))(arg) && + arg.context_mode == context_mode && + util::GetHelpBubbleId(arg.extended_properties) == help_bubble_id && + arg.body_text_id == body_text_id && + arg.next_button_callback.is_null() != has_next_button; +} + +MATCHER_P3(EventStep, + element_specifier, + context_mode, + has_name_elements_callback, + "") { return arg.step_type == ui::InteractionSequence::StepType::kCustomEvent && - arg.name_elements_callback.is_null() != has_name_elements_callback && - absl::visit(base::Overloaded{ - [&](const ui::ElementIdentifier& element_id) { - return arg.element_id == element_id && - arg.element_name.empty(); - }, - [&](const std::string& element_name) { - return arg.element_name == element_name && - arg.element_id == ui::ElementIdentifier(); - }, - }, - element_specifier); + Matches(ElementSpecifierEq(element_specifier))(arg) && + arg.context_mode == context_mode && + arg.name_elements_callback.is_null() != has_name_elements_callback; } } // namespace @@ -138,32 +141,46 @@ Field( &TutorialDescription::steps, ElementsAre( - BubbleStep(HelpBubbleId::kWelcomeTourShelf, - ElementSpecifier(kShelfViewElementId), + BubbleStep(ElementSpecifier(kShelfViewElementId), + ContextMode::kInitial, + HelpBubbleId::kWelcomeTourShelf, IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT, /*has_next_button=*/true), EventStep(ElementSpecifier(kShelfViewElementId), + ContextMode::kFromPreviousStep, /*has_name_elements_callback=*/true), - BubbleStep(HelpBubbleId::kWelcomeTourStatusArea, - ElementSpecifier(kUnifiedSystemTrayElementName), + BubbleStep(ElementSpecifier(kUnifiedSystemTrayElementName), + ContextMode::kAny, + HelpBubbleId::kWelcomeTourStatusArea, IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT, /*has_next_button=*/true), EventStep(ElementSpecifier(kUnifiedSystemTrayElementName), + ContextMode::kFromPreviousStep, /*has_name_elements_callback=*/true), - BubbleStep(HelpBubbleId::kWelcomeTourHomeButton, - ElementSpecifier(kHomeButtonElementName), + BubbleStep(ElementSpecifier(kHomeButtonElementName), + ContextMode::kAny, + HelpBubbleId::kWelcomeTourHomeButton, IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT, /*has_next_button=*/true), - BubbleStep(HelpBubbleId::kWelcomeTourSearchBox, - ElementSpecifier(kSearchBoxViewElementId), + BubbleStep(ElementSpecifier(kSearchBoxViewElementId), + ContextMode::kAny, + HelpBubbleId::kWelcomeTourSearchBox, IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_BODY_TEXT, /*has_next_button=*/true), - BubbleStep(HelpBubbleId::kWelcomeTourSettingsApp, - ElementSpecifier(kSettingsAppElementId), + EventStep(ElementSpecifier(kSearchBoxViewElementId), + ContextMode::kFromPreviousStep, + /*has_name_elements_callback=*/false), + BubbleStep(ElementSpecifier(kSettingsAppElementId), + ContextMode::kFromPreviousStep, + HelpBubbleId::kWelcomeTourSettingsApp, IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_BODY_TEXT, /*has_next_button=*/true), - BubbleStep(HelpBubbleId::kWelcomeTourExploreApp, - ElementSpecifier(kExploreAppElementId), + EventStep(ElementSpecifier(kSettingsAppElementId), + ContextMode::kFromPreviousStep, + /*has_name_elements_callback=*/false), + BubbleStep(ElementSpecifier(kExploreAppElementId), + ContextMode::kFromPreviousStep, + HelpBubbleId::kWelcomeTourExploreApp, IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT, /*has_next_button=*/false)))))); }
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc index 9be1e2a..73a057d 100644 --- a/ash/wallpaper/wallpaper_controller_impl.cc +++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -1816,10 +1816,28 @@ WallpaperInfo local_info; WallpaperInfo synced_info; + bool has_synced_info = + pref_manager_->GetSyncedWallpaperInfo(account_id, &synced_info); + bool has_local_info = + pref_manager_->GetLocalWallpaperInfo(account_id, &local_info); + session_manager::SessionState session_state = + Shell::Get()->session_controller()->GetSessionState(); + if (session_state == session_manager::SessionState::OOBE && + !has_synced_info && has_local_info && + local_info.type == WallpaperType::kDefault && + features::IsTimeOfDayWallpaperEnabled()) { + // Sets the time of day wallpaper as the default wallpaper on active user + // pref changed during OOBE flow. + SetTimeOfDayWallpaper( + account_id, + base::BindOnce( + &WallpaperControllerImpl::OnTimeOfDayWallpaperSetAfterOobe, + weak_factory_.GetWeakPtr())); + return; + } // Migrate wallpaper info to syncable prefs. - if (!pref_manager_->GetSyncedWallpaperInfo(account_id, &synced_info) && - pref_manager_->GetLocalWallpaperInfo(account_id, &local_info) && + if (!has_synced_info && has_local_info && WallpaperPrefManager::ShouldSyncOut(local_info)) { if (local_info.type == WallpaperType::kCustomized) { base::FilePath source = GetCustomWallpaperDir(kOriginalWallpaperSubDir) @@ -2970,6 +2988,10 @@ variant_to_use); } +void WallpaperControllerImpl::OnTimeOfDayWallpaperSetAfterOobe(bool success) { + wallpaper_metrics_manager_->LogSettingTimeOfDayWallpaperAfterOobe(success); +} + void WallpaperControllerImpl::SetDailyRefreshCollectionId( const AccountId& account_id, const std::string& collection_id) {
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h index d863015..ba09222 100644 --- a/ash/wallpaper/wallpaper_controller_impl.h +++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -707,6 +707,9 @@ const OnlineWallpaperParams& params, SetWallpaperCallback callback); + // Called as a callback for `SetTimeOfDayWallpaper`. + void OnTimeOfDayWallpaperSetAfterOobe(bool success); + // If daily refresh wallpapers is enabled by the user. bool IsDailyRefreshEnabled() const;
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc index 810454f..8b0a0882 100644 --- a/ash/wallpaper/wallpaper_controller_unittest.cc +++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -9,6 +9,7 @@ #include <memory> #include <vector> +#include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/constants/ash_switches.h" #include "ash/public/cpp/schedule_enums.h" @@ -400,7 +401,9 @@ class WallpaperControllerTest : public AshTestBase { public: WallpaperControllerTest() - : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {} + : AshTestBase(base::test::TaskEnvironment::TimeSource::MOCK_TIME) { + scoped_feature_list_.InitAndEnableFeature(features::kTimeOfDayWallpaper); + } WallpaperControllerTest(const WallpaperControllerTest&) = delete; WallpaperControllerTest& operator=(const WallpaperControllerTest&) = delete; @@ -778,6 +781,7 @@ // TODO(esum): Use ash::InProcessImageDecoder here instead and exercise actual // decoding in these tests. data_decoder::test::InProcessDataDecoder in_process_data_decoder_; + base::test::ScopedFeatureList scoped_feature_list_; }; TEST_F(WallpaperControllerTest, Client) { @@ -1419,6 +1423,45 @@ GURL(images[1].image_url()).ExtractFileName()))); } +TEST_F(WallpaperControllerTest, + ActiveUserPrefServiceChanged_SetTimeOfDayWallpaper) { + SetBypassDecode(); + auto images = TimeOfDayImageSet(); + client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId, + images); + WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault); + pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info); + SetSessionState(SessionState::OOBE); + // Log in and trigger `OnActiveUserPrefServiceChange`. + SimulateUserLogin(kAccountId1); + RunAllTasksUntilIdle(); + WallpaperInfo actual_info; + EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info)); + EXPECT_EQ(WallpaperType::kOnline, actual_info.type); + EXPECT_EQ(wallpaper_constants::kTimeOfDayWallpaperCollectionId, + actual_info.collection_id); + histogram_tester().ExpectTotalCount("Ash.Wallpaper.IsSetToTimeOfDayAfterOobe", + 1); +} + +TEST_F(WallpaperControllerTest, + ActiveUserPrefServiceChanged_NonOOBE_SetTimeOfDayWallpaper) { + SetBypassDecode(); + auto images = TimeOfDayImageSet(); + client_.AddCollection(wallpaper_constants::kTimeOfDayWallpaperCollectionId, + images); + WallpaperInfo local_info = InfoWithType(WallpaperType::kDefault); + pref_manager_->SetLocalWallpaperInfo(kAccountId1, local_info); + // Log in and trigger `OnActiveUserPrefServiceChange`. + SimulateUserLogin(kAccountId1); + RunAllTasksUntilIdle(); + WallpaperInfo actual_info; + EXPECT_TRUE(pref_manager_->GetUserWallpaperInfo(kAccountId1, &actual_info)); + EXPECT_TRUE(local_info.MatchesAsset(actual_info)); + histogram_tester().ExpectTotalCount("Ash.Wallpaper.IsSetToTimeOfDayAfterOobe", + 0); +} + TEST_F(WallpaperControllerTest, SetAndRemovePolicyWallpaper) { SetBypassDecode(); // Simulate the login screen.
diff --git a/ash/wallpaper/wallpaper_metrics_manager.cc b/ash/wallpaper/wallpaper_metrics_manager.cc index 77e9141..a842e1da 100644 --- a/ash/wallpaper/wallpaper_metrics_manager.cc +++ b/ash/wallpaper/wallpaper_metrics_manager.cc
@@ -47,4 +47,9 @@ base::UmaHistogramBoolean("Ash.Wallpaper.Preview.Show", true); } +void WallpaperMetricsManager::LogSettingTimeOfDayWallpaperAfterOobe( + bool success) { + base::UmaHistogramBoolean("Ash.Wallpaper.IsSetToTimeOfDayAfterOobe", success); +} + } // namespace ash
diff --git a/ash/wallpaper/wallpaper_metrics_manager.h b/ash/wallpaper/wallpaper_metrics_manager.h index 63f7d4a..7230c6af 100644 --- a/ash/wallpaper/wallpaper_metrics_manager.h +++ b/ash/wallpaper/wallpaper_metrics_manager.h
@@ -28,6 +28,8 @@ void OnWallpaperChanged() override; void OnWallpaperPreviewStarted() override; + void LogSettingTimeOfDayWallpaperAfterOobe(bool success); + private: base::ScopedObservation<WallpaperController, WallpaperControllerObserver> wallpaper_controller_observation_{this};
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn index 6d02969..1787c62 100644 --- a/ash/webui/common/resources/BUILD.gn +++ b/ash/webui/common/resources/BUILD.gn
@@ -289,6 +289,10 @@ "cellular_setup/default_esim_profile_dark.svg", "cellular_setup/spinner.json", "cellular_setup/spinner_dark.json", + "hotspot/hotspot_dot.svg", + "hotspot/hotspot_inner.svg", + "hotspot/hotspot-off.svg", + "hotspot/hotspot.svg", "multidevice_setup/all_set_1x_dark.svg", "multidevice_setup/all_set_1x_light.svg", "multidevice_setup/all_set_2x_dark.svg",
diff --git a/ash/webui/common/resources/hotspot/hotspot-off.svg b/ash/webui/common/resources/hotspot/hotspot-off.svg new file mode 100644 index 0000000..b26b3525 --- /dev/null +++ b/ash/webui/common/resources/hotspot/hotspot-off.svg
@@ -0,0 +1 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M3.18333 2L2 3.175L4.24167 5.41667C3.15833 6.825 2.50833 8.58333 2.50833 10.4917C2.50833 12.7917 3.44167 14.875 4.95 16.3833L6.13333 15.2C4.925 14 4.175 12.3333 4.175 10.4917C4.175 9.03333 4.65 7.7 5.43333 6.60833L6.625 7.8C6.13333 8.575 5.84167 9.5 5.84167 10.4917C5.84167 11.875 6.40833 13.1167 7.30833 14.025L8.49167 12.8417C7.88333 12.2417 7.50833 11.4167 7.50833 10.4917C7.50833 9.96666 7.63333 9.46667 7.85 9.025L9.19167 10.3667C9.19167 10.3875 9.1875 10.4083 9.18333 10.4292C9.17917 10.45 9.175 10.4708 9.175 10.4917C9.175 10.95 9.36667 11.3667 9.66667 11.6667C9.96667 11.9667 10.3833 12.1583 10.8417 12.1583C10.8773 12.1583 10.9128 12.1523 10.9536 12.1453L10.975 12.1417L17.325 18.4917L18.5 17.3167L3.18333 2ZM15.5917 12.05C15.75 11.5583 15.8417 11.0333 15.8417 10.4917C15.8417 7.73333 13.6 5.49167 10.8417 5.49167C10.3 5.49167 9.775 5.575 9.28333 5.74167L10.7083 7.16667C10.75 7.15833 10.8 7.15833 10.8417 7.15833C12.6833 7.15833 14.175 8.65 14.175 10.4917C14.175 10.5333 14.175 10.5833 14.1667 10.625L15.5917 12.05ZM17.5083 10.4917C17.5083 6.80833 14.525 3.825 10.8417 3.825C9.825 3.825 8.86667 4.05 8 4.45833L6.76667 3.225C7.975 2.54167 9.35833 2.15833 10.8417 2.15833C15.4417 2.15833 19.175 5.89167 19.175 10.4917C19.175 11.975 18.7833 13.3667 18.1083 14.5667L16.8667 13.325C17.2833 12.4667 17.5083 11.5083 17.5083 10.4917Z" fill="#1B1B1F"/></svg>
diff --git a/ash/webui/common/resources/hotspot/hotspot.svg b/ash/webui/common/resources/hotspot/hotspot.svg new file mode 100644 index 0000000..75abbe7 --- /dev/null +++ b/ash/webui/common/resources/hotspot/hotspot.svg
@@ -0,0 +1 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 10.5C2 5.84343 5.808 2 10.5 2C15.192 2 19 5.84343 19 10.5C19 13.7534 17.2915 16.5158 15 18L14 16.5C15.9315 15.3233 17.3 13.1185 17.5 10.5C17.3 6.78713 14.257 3.71582 10.5 3.5C6.743 3.71582 3.7 6.78713 3.5 10.5C3.7 13.1185 5.0685 15.3233 7 16.5L6 18C3.7085 16.5158 2 13.7534 2 10.5Z" fill="#1B1B1F"/><path d="M15.5 10.5C15.5 7.78374 13.2583 5.5 10.5 5.5C7.74167 5.5 5.5 7.78374 5.5 10.5C5.5 12.4786 6.50833 14.1171 8 15L9 13.5C7.84167 12.9285 7.16667 11.8503 7 10.5C7.16667 8.71761 8.65833 7.19794 10.5 7C12.3417 7.19794 13.8333 8.71761 14 10.5C13.8333 11.8503 13.1583 12.9285 12 13.5L13 15C14.4917 14.1171 15.5 12.4786 15.5 10.5Z" fill="#1B1B1F"/><path d="M10.5 12C11.3284 12 12 11.3284 12 10.5C12 9.67157 11.3284 9 10.5 9C9.67157 9 9 9.67157 9 10.5C9 11.3284 9.67157 12 10.5 12Z" fill="#1B1B1F"/></svg>
diff --git a/ash/webui/common/resources/hotspot/hotspot_dot.svg b/ash/webui/common/resources/hotspot/hotspot_dot.svg new file mode 100644 index 0000000..755a7cb --- /dev/null +++ b/ash/webui/common/resources/hotspot/hotspot_dot.svg
@@ -0,0 +1 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.5 12C11.3284 12 12 11.3284 12 10.5C12 9.67157 11.3284 9 10.5 9C9.67157 9 9 9.67157 9 10.5C9 11.3284 9.67157 12 10.5 12Z" fill="#1B1B1F"/></svg>
diff --git a/ash/webui/common/resources/hotspot/hotspot_inner.svg b/ash/webui/common/resources/hotspot/hotspot_inner.svg new file mode 100644 index 0000000..2bc0380 --- /dev/null +++ b/ash/webui/common/resources/hotspot/hotspot_inner.svg
@@ -0,0 +1 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.5 10.5C15.5 7.78374 13.2583 5.5 10.5 5.5C7.74167 5.5 5.5 7.78374 5.5 10.5C5.5 12.4786 6.50833 14.1171 8 15L9 13.5C7.84167 12.9285 7.16667 11.8503 7 10.5C7.16667 8.71761 8.65833 7.19794 10.5 7C12.3417 7.19794 13.8333 8.71761 14 10.5C13.8333 11.8503 13.1583 12.9285 12 13.5L13 15C14.4917 14.1171 15.5 12.4786 15.5 10.5Z" fill="#1B1B1F"/><path d="M10.5 12C11.3284 12 12 11.3284 12 10.5C12 9.67157 11.3284 9 10.5 9C9.67157 9 9 9.67157 9 10.5C9 11.3284 9.67157 12 10.5 12Z" fill="#1B1B1F"/></svg>
diff --git a/ash/webui/common/resources/network/network_icon.html b/ash/webui/common/resources/network/network_icon.html index bd213dd2..166e249 100644 --- a/ash/webui/common/resources/network/network_icon.html +++ b/ash/webui/common/resources/network/network_icon.html
@@ -121,6 +121,45 @@ } } + /* Hotspot images */ + #icon.hotspot-on { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot.svg); + } + + #icon.hotspot-off { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot-off.svg); + } + + #icon.hotspot-0 { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot_dot.svg); + } + + #icon.hotspot-1 { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot_inner.svg); + } + + #icon.hotspot-2 { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot.svg); + } + + #icon.hotspot-connecting { + animation: hotspot-levels 1500ms infinite; + animation-direction: alternate; + animation-timing-function: steps(4, end); + } + + @keyframes hotspot-levels { + 0% { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot_dot.svg); + } + 50% { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot_inner.svg); + } + 100% { + -webkit-mask: url(chrome://resources/ash/common/hotspot/hotspot.svg); + } + } + /* Cellular images */ #icon.cellular-not-connected { -webkit-mask: url(chrome://resources/ash/common/network/cellular_0_with_x.svg); @@ -183,16 +222,16 @@ } } </style> -<template is="dom-if" if="[[showIcon_(networkState)]]" restamp> +<template is="dom-if" if="[[showIcon_(networkState, hotspotInfo)]]" restamp> <div id="icon" - class$="[[getIconClass_(networkState, deviceState, isListItem)]]"> + class$="[[getIconClass_(networkState, deviceState, isListItem, hotspotInfo)]]"> </div> <iron-icon id="technology" - hidden="[[!showTechnology_(networkState, showTechnologyBadge)]]" - icon="[[getTechnology_(networkState)]]"> + hidden="[[!showTechnology_(networkState, showTechnologyBadge, hotspotInfo)]]" + icon="[[getTechnology_(networkState, hotspotInfo)]]"> </iron-icon> - <iron-icon id="secure" hidden="[[!showSecure_(networkState)]]" + <iron-icon id="secure" hidden="[[!showSecure_(networkState, hotspotInfo)]]" icon="network8:badge-secure"> </iron-icon> - <div id="roaming" hidden="[[!showRoaming_(networkState)]]"></div> + <div id="roaming" hidden="[[!showRoaming_(networkState, hotspotInfo)]]"></div> </template>
diff --git a/ash/webui/common/resources/network/network_icon.js b/ash/webui/common/resources/network/network_icon.js index 788e94d..8d7cb88f 100644 --- a/ash/webui/common/resources/network/network_icon.js +++ b/ash/webui/common/resources/network/network_icon.js
@@ -14,6 +14,7 @@ import {I18nBehavior} from '//resources/ash/common/i18n_behavior.js'; import {loadTimeData} from '//resources/ash/common/load_time_data.m.js'; import {Polymer} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {HotspotState} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js'; import {ActivationStateType, SecurityType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {ConnectionStateType, DeviceStateType, NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; @@ -38,6 +39,12 @@ networkState: Object, /** + * If set, hotspot state within this object will be used to update the + * hotspot icon. + */ + hotspotInfo: Object, + + /** * If set, the device state for the network type. Otherwise it defaults to * null rather than undefined so that it does not block computed bindings. * @type {?OncMojo.DeviceStateProperties} @@ -73,7 +80,7 @@ ariaLabel: { type: String, reflectToAttribute: true, - computed: 'computeAriaLabel_(locale, networkState)', + computed: 'computeAriaLabel_(locale, networkState, hotspotInfo)', }, /** @private {boolean} */ @@ -101,9 +108,20 @@ // NOTE: computeAriaLabel_() follows a very similar logic structure and both // functions should be updated together. - if (!this.networkState) { + if (!this.networkState && !this.hotspotInfo) { return ''; } + + if (this.hotspotInfo) { + if (this.hotspotInfo.state === HotspotState.kEnabled) { + return 'hotspot-on'; + } + if (this.hotspotInfo.state === HotspotState.kEnabling) { + return 'hotspot-connecting'; + } + return 'hotspot-off'; + } + const type = this.networkState.type; if (type === NetworkType.kEthernet) { return 'ethernet'; @@ -158,6 +176,12 @@ // NOTE: getIconClass_() follows a very similar logic structure and both // functions should be updated together. + if (this.hotspotInfo) { + // TODO(b/284324373): Finalize aria labels for hotspot and update them + // here. + return 'hotspot'; + } + if (!this.networkState) { return ''; } @@ -247,7 +271,7 @@ * @private */ showTechnology_() { - if (!this.networkState) { + if (!this.networkState || this.hotspotInfo) { return false; } return !this.showRoaming_() && @@ -260,7 +284,7 @@ * @private */ getTechnology_() { - if (!this.networkState) { + if (!this.networkState || this.hotspotInfo) { return ''; } if (this.networkState.type === NetworkType.kCellular) { @@ -310,7 +334,7 @@ * @private */ showSecure_() { - if (!this.networkState) { + if (!this.networkState || this.hotspotInfo) { return false; } if (!this.isListItem && @@ -339,7 +363,7 @@ * @private */ showIcon_() { - return !!this.networkState; + return !!this.networkState || !!this.hotspotInfo; }, /**
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h index 55e58e79..5c4223b 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_layout_table.h
@@ -318,12 +318,6 @@ mojom::AcceleratorSubcategory::kGeneralControls, /*locked=*/false, mojom::AcceleratorLayoutStyle::kDefault, mojom::AcceleratorSource::kAsh}, - {AcceleratorAction::kFocusCameraPreview, - IDS_ASH_ACCELERATOR_DESCRIPTION_FOCUS_CAMERA_PREVIEW, - mojom::AcceleratorCategory::kGeneral, - mojom::AcceleratorSubcategory::kGeneralControls, - /*locked=*/false, mojom::AcceleratorLayoutStyle::kDefault, - mojom::AcceleratorSource::kAsh}, {AcceleratorAction::kToggleDictation, IDS_ASH_ACCELERATOR_DESCRIPTION_TOGGLE_DICTATION, mojom::AcceleratorCategory::kGeneral,
diff --git a/ash/webui/shortcut_customization_ui/resources/js/accelerator_edit_dialog.ts b/ash/webui/shortcut_customization_ui/resources/js/accelerator_edit_dialog.ts index 7a915070..dd7e0fff 100644 --- a/ash/webui/shortcut_customization_ui/resources/js/accelerator_edit_dialog.ts +++ b/ash/webui/shortcut_customization_ui/resources/js/accelerator_edit_dialog.ts
@@ -186,7 +186,8 @@ protected getFilteredAccelerators(accelerators: AcceleratorInfo[]): AcceleratorInfo[] { return accelerators.filter( - accel => accel.state !== AcceleratorState.kDisabledByUser); + accel => accel.state !== AcceleratorState.kDisabledByUser && + accel.state !== AcceleratorState.kDisabledByUnavailableKeys); } }
diff --git a/base/allocator/partition_alloc_support.cc b/base/allocator/partition_alloc_support.cc index d3d892e2..9d827464 100644 --- a/base/allocator/partition_alloc_support.cc +++ b/base/allocator/partition_alloc_support.cc
@@ -500,8 +500,6 @@ // Windows signatures "internal::RawPtrBackupRefImpl<0>::ReleaseInternal", "_free_base", - // Windows stack traces are prefixed with "Backtrace:" - "Backtrace:", // Mac signatures "internal::RawPtrBackupRefImpl<false>::ReleaseInternal",
diff --git a/base/allocator/partition_alloc_support_unittest.cc b/base/allocator/partition_alloc_support_unittest.cc index 591297a1..b3990376 100644 --- a/base/allocator/partition_alloc_support_unittest.cc +++ b/base/allocator/partition_alloc_support_unittest.cc
@@ -381,7 +381,6 @@ TEST(PartitionAllocDanglingPtrChecks, ExtractDanglingPtrSignatureWindowsStackTrace) { const std::string stack_trace_output = - "Backtrace:\r\n" "\tbase::F1 [0x055643C3+19] (o:\\base\\F1.cc:329)\r\n" "\tallocator_shim::internal::PartitionFree [0x0648F87B+5243] " "(o:\\path.cc:441)\r\n" @@ -397,7 +396,6 @@ ExtractDanglingPtrSignatureWindowsTaskTrace) { const std::string task_trace_output = "Task trace:\r\n" - "Backtrace:\r\n" "\tbase::F1 [0x049068A3+813] (o:\\base\\F1.cc:207)\r\n" "\tbase::F2 [0x0490614C+192] (o:\\base\\F2.cc:116)\r\n"; EXPECT_EQ("base::F1",
diff --git a/base/android/jni_generator/jni_registration_generator.py b/base/android/jni_generator/jni_registration_generator.py index 4784989c..2d40f80 100755 --- a/base/android/jni_generator/jni_registration_generator.py +++ b/base/android/jni_generator/jni_registration_generator.py
@@ -40,6 +40,11 @@ 'REGISTER_NATIVES', ] +# Classes here will be removed from the java side of registration. +PERMANENTLY_IGNORED_JAVA_ONLY_FILES = [r'\W+third_party/cardboard/'] +PERMANENTLY_IGNORED_JAVA_ONLY_FILES_RE = re.compile( + '|'.join(PERMANENTLY_IGNORED_JAVA_ONLY_FILES)) + def _Generate(options, native_sources, java_sources): """Generates files required to perform JNI registration. @@ -998,6 +1003,11 @@ set(action_helpers.parse_gn_list(args.java_sources_files))) java_sources = _GetFilesSetFromSources(java_sources_files, args.file_exclusions) + java_sources = { + j + for j in java_sources + if not PERMANENTLY_IGNORED_JAVA_ONLY_FILES_RE.match(j) + } if args.native_sources_file: native_sources = _GetFilesSetFromSources([args.native_sources_file], args.file_exclusions) @@ -1011,6 +1021,14 @@ # when only looking at java. native_sources = java_sources + native_ignored = { + j + for j in native_sources if PERMANENTLY_IGNORED_JAVA_ONLY_FILES_RE.match(j) + } + assert not native_ignored, ( + f'''Permanently ignored java files shouldn't be in a generate_jni target: + {native_ignored} + ''') _Generate(args, native_sources, java_sources=java_sources) if args.depfile:
diff --git a/base/debug/stack_trace_win.cc b/base/debug/stack_trace_win.cc index d0c4259..e7328d6 100644 --- a/base/debug/stack_trace_win.cc +++ b/base/debug/stack_trace_win.cc
@@ -399,7 +399,6 @@ (*os) << "\t" << trace_[i] << "\n"; } } else { - (*os) << "Backtrace:\n"; context->OutputTraceToStream(trace_, count_, os, prefix_string); } }
diff --git a/base/observer_list_internal.h b/base/observer_list_internal.h index 5909cb1..fb903e8f 100644 --- a/base/observer_list_internal.h +++ b/base/observer_list_internal.h
@@ -48,7 +48,9 @@ } #if DCHECK_IS_ON() - std::string GetCreationStackString() const { return stack_.ToString(); } + std::string GetCreationStackString() const { + return "Observer created at:\n" + stack_.ToString(); + } #endif // DCHECK_IS_ON() private:
diff --git a/base/test/task_environment.h b/base/test/task_environment.h index b5ed0f9c..fa2d43b4 100644 --- a/base/test/task_environment.h +++ b/base/test/task_environment.h
@@ -252,13 +252,15 @@ // possible. void RunUntilIdle(); - // Only valid for instances using TimeSource::MOCK_TIME. Fast-forwards + // Only valid for instances using |TimeSource::MOCK_TIME|. Fast-forwards // virtual time by |delta|, causing all tasks on the main thread and thread - // pool with a remaining delay less than or equal to |delta| to be executed in - // their natural order before this returns. |delta| must be non-negative. Upon - // returning from this method, NowTicks() will be >= the initial |NowTicks() + - // delta|. It is guaranteed to be == iff tasks executed in this - // FastForwardBy() didn't result in nested calls to time-advancing-methods. + // pool with a remaining delay less than or equal to |delta| to be executed + // in their natural order before this method returns. Undelayed tasks are just + // delayed tasks with a delay of 0, so they are also executed. |delta| must be + // non-negative. Upon returning from this method, NowTicks() will be >= the + // initial |NowTicks() + delta|. It is guaranteed to be == iff tasks executed + // in this FastForwardBy() didn't result in nested calls to + // time-advancing-methods. void FastForwardBy(TimeDelta delta); // Similar to `FastForwardBy` but doesn't advance `base::LiveTicks`, behaving
diff --git a/build/fuchsia/test/common.py b/build/fuchsia/test/common.py index 595e571..0f8af33 100644 --- a/build/fuchsia/test/common.py +++ b/build/fuchsia/test/common.py
@@ -179,14 +179,6 @@ return 'Running' in _get_daemon_status() -def check_ssh_config_file() -> None: - """Checks for ssh keys and generates them if they are missing.""" - - script_path = os.path.join(SDK_ROOT, 'bin', 'fuchsia-common.sh') - check_cmd = ['bash', '-c', f'. {script_path}; check-fuchsia-ssh-config'] - subprocess.run(check_cmd, check=True) - - def _wait_for_daemon(start=True, timeout_seconds=100): """Waits for daemon to reach desired state in a polling loop.
diff --git a/build/fuchsia/test/compatible_utils.py b/build/fuchsia/test/compatible_utils.py index b917a65..12904094 100644 --- a/build/fuchsia/test/compatible_utils.py +++ b/build/fuchsia/test/compatible_utils.py
@@ -122,11 +122,8 @@ """Get the prefix of a barebone ssh command.""" ssh_addr, ssh_port = parse_host_port(host_port_pair) - return [ - 'ssh', '-F', - os.path.expanduser('~/.fuchsia/sshconfig'), ssh_addr, '-p', - str(ssh_port) - ] + sshconfig = os.path.join(os.path.dirname(__file__), 'sshconfig') + return ['ssh', '-F', sshconfig, ssh_addr, '-p', str(ssh_port)] def install_symbols(package_paths: Iterable[str],
diff --git a/build/fuchsia/test/ffx_emulator.py b/build/fuchsia/test/ffx_emulator.py index 63b4c31..5c0f6f0 100644 --- a/build/fuchsia/test/ffx_emulator.py +++ b/build/fuchsia/test/ffx_emulator.py
@@ -13,8 +13,8 @@ from contextlib import AbstractContextManager -from common import check_ssh_config_file, find_image_in_sdk, get_system_info, \ - run_ffx_command, SDK_ROOT +from common import find_image_in_sdk, get_system_info, run_ffx_command, \ + SDK_ROOT from compatible_utils import get_host_arch, get_sdk_hash _EMU_COMMAND_RETRIES = 3 @@ -55,7 +55,6 @@ def _start_emulator(self) -> None: """Start the emulator.""" logging.info('Starting emulator %s', self._node_name) - check_ssh_config_file() emu_command = [ 'emu', 'start', self._product_bundle, '--name', self._node_name ]
diff --git a/build/fuchsia/test/flash_device.py b/build/fuchsia/test/flash_device.py index ba38ca6..2b415c05 100755 --- a/build/fuchsia/test/flash_device.py +++ b/build/fuchsia/test/flash_device.py
@@ -14,8 +14,8 @@ from typing import Optional, Tuple import common -from common import BootMode, boot_device, check_ssh_config_file, \ - get_system_info, find_image_in_sdk, register_device_args +from common import BootMode, boot_device, get_system_info, find_image_in_sdk, \ + register_device_args from compatible_utils import get_sdk_hash, pave, running_unattended from lockfile import lock @@ -144,7 +144,6 @@ system_image_dir = actual_image_dir if needs_update: - check_ssh_config_file() if should_pave: if running_unattended(): assert target, ('Target ID must be specified on swarming when'
diff --git a/build/fuchsia/test/flash_device_unittests.py b/build/fuchsia/test/flash_device_unittests.py index afacc6b..252eacf 100755 --- a/build/fuchsia/test/flash_device_unittests.py +++ b/build/fuchsia/test/flash_device_unittests.py
@@ -34,16 +34,13 @@ _TEST_VERSION)) swarming_patcher = mock.patch('flash_device.running_unattended', return_value=False) - check_patcher = mock.patch('flash_device.check_ssh_config_file') time_sleep = mock.patch('time.sleep') self._ffx_mock = ffx_patcher.start() self._sdk_hash_mock = sdk_hash_patcher.start() - self._check_patcher_mock = check_patcher.start() self._swarming_mock = swarming_patcher.start() self._time_sleep = time_sleep.start() self.addCleanup(self._ffx_mock.stop) self.addCleanup(self._sdk_hash_mock.stop) - self.addCleanup(self._check_patcher_mock.stop) self.addCleanup(self._swarming_mock.stop) self.addCleanup(self._time_sleep.stop)
diff --git a/build/fuchsia/test/sshconfig b/build/fuchsia/test/sshconfig new file mode 100644 index 0000000..59313f5 --- /dev/null +++ b/build/fuchsia/test/sshconfig
@@ -0,0 +1,48 @@ +# Configure port 8022 for connecting to a device with the local address. +# This makes it possible to forward 8022 to a device connected remotely. +# The fuchsia private key is used for the identity. +Host 127.0.0.1 + Port 8022 + +Host ::1 + Port 8022 + +Host * +# Turn off refusing to connect to hosts whose key has changed +StrictHostKeyChecking no +CheckHostIP no + +# Disable recording the known hosts +UserKnownHostsFile=/dev/null + +# Do not forward auth agent connection to remote, no X11 +ForwardAgent no +ForwardX11 no + +# Connection timeout in seconds +ConnectTimeout=10 + +# Check for server alive in seconds, max count before disconnecting +ServerAliveInterval 1 +ServerAliveCountMax 10 + +# Try to keep the master connection open to speed reconnecting. +ControlMaster auto +ControlPersist yes + +# When expanded, the ControlPath below cannot have more than 90 characters +# (total of 108 minus 18 used by a random suffix added by ssh). +# '%C' expands to 40 chars and there are 9 fixed chars, so '~' can expand to +# up to 41 chars, which is a reasonable limit for a user's home in most +# situations. If '~' expands to more than 41 chars, the ssh connection +# will fail with an error like: +# unix_listener: path "..." too long for Unix domain socket +# A possible solution is to use /tmp instead of ~, but it has +# its own security concerns. +ControlPath=~/.ssh/fx-%C + +# Connect with user, use the identity specified. +User fuchsia +IdentitiesOnly yes +IdentityFile ~/.ssh/fuchsia_ed25519 +GSSAPIDelegateCredentials no
diff --git a/build/rust/std/remap_alloc.cc b/build/rust/std/remap_alloc.cc index 1a9d226..f12ef53 100644 --- a/build/rust/std/remap_alloc.cc +++ b/build/rust/std/remap_alloc.cc
@@ -75,6 +75,11 @@ #define REMAP_ALLOC_ATTRIBUTES __attribute__((weak)) #endif // COMPONENT_BUILD +// This must exist as the stdlib depends on it to prove that we know the +// alloc shims below are unstable. In the future we may be required to replace +// them with a #[global_allocator] crate (see file comment above for more). +[[maybe_unused]] unsigned char __rust_no_alloc_shim_is_unstable; + REMAP_ALLOC_ATTRIBUTES void* __rust_alloc(size_t size, size_t align) { // This mirrors kMaxSupportedAlignment from // base/allocator/partition_allocator/partition_alloc_constants.h.
diff --git a/cc/layers/mirror_layer_impl.cc b/cc/layers/mirror_layer_impl.cc index c1cda40..b796a458 100644 --- a/cc/layers/mirror_layer_impl.cc +++ b/cc/layers/mirror_layer_impl.cc
@@ -10,6 +10,8 @@ #include "cc/trees/layer_tree_impl.h" #include "cc/trees/occlusion.h" #include "components/viz/common/quads/compositor_render_pass_draw_quad.h" +#include "components/viz/common/quads/solid_color_draw_quad.h" +#include "third_party/skia/include/core/SkColor.h" namespace cc { @@ -29,6 +31,24 @@ // opacity) are ignored. Consider applying them here. auto* mirrored_layer = layer_tree_impl()->LayerById(mirrored_layer_id_); + + if (!mirrored_layer) { + // If the mirrored layer is missing then just fill in layer as opaque black. + // This isn't supposed to happen but is happening in + // https://crbug.com/1423091. + viz::SharedQuadState* shared_quad_state = + render_pass->CreateAndAppendSharedQuadState(); + PopulateSharedQuadState(shared_quad_state, /*contents_opaque=*/false); + + auto* quad = + render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>(); + quad->SetNew(shared_quad_state, shared_quad_state->quad_layer_rect, + shared_quad_state->visible_quad_layer_rect, SkColors::kBlack, + /*anti_aliasing_off=*/false); + + return; + } + auto* mirrored_render_surface = GetEffectTree().GetRenderSurface(mirrored_layer->effect_tree_index()); gfx::Rect content_rect = mirrored_render_surface->content_rect(); @@ -78,10 +98,10 @@ } gfx::Rect MirrorLayerImpl::GetEnclosingVisibleRectInTargetSpace() const { - const LayerImpl* mirrored_layer = - layer_tree_impl()->LayerById(mirrored_layer_id_); - return GetScaledEnclosingVisibleRectInTargetSpace( - mirrored_layer->GetIdealContentsScaleKey()); + LayerImpl* mirrored_layer = layer_tree_impl()->LayerById(mirrored_layer_id_); + float scale = + mirrored_layer ? mirrored_layer->GetIdealContentsScaleKey() : 1.0f; + return GetScaledEnclosingVisibleRectInTargetSpace(scale); } const char* MirrorLayerImpl::LayerTypeAsString() const {
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 3d6b6cd..a0db274 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1176,7 +1176,6 @@ "//build:chromeos_buildflags", "//chrome/app:command_ids", "//chrome/app:notification_metrics", - "//chrome/browser:browser_noarc", "//chrome/common:buildflags", "//chrome/common/profiler", "//components/crash/core/app",
diff --git a/chrome/VERSION b/chrome/VERSION index 393399a0..ebcc242 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=116 MINOR=0 -BUILD=5795 +BUILD=5796 PATCH=0
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceOnTabletTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceOnTabletTest.java index 3aa17ae..5c9c4a04 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceOnTabletTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceOnTabletTest.java
@@ -681,13 +681,14 @@ / (mvTilesItemWidth + minHorizontalSpacing), 1, MostVisitedTilesCoordinator.MAX_TILE_COLUMNS_FOR_GRID); int expectedIntervalPadding = - (mvTilesLayoutWidth - mvTilesItemWidth * numColumns - expectedEdgeMargin * 2) - / (numColumns - 1); + Math.round((float) (mvTilesLayoutWidth - mvTilesItemWidth * numColumns + - expectedEdgeMargin * 2) + / (numColumns - 1)); if (expectedIntervalPadding >= minHorizontalSpacing && expectedIntervalPadding <= maxHorizontalSpacing) { Assert.assertEquals("The edge margin of the most visited tiles element to " + "the MV tiles layout is wrong.", - mvt1LeftMargin, expectedEdgeMargin); + expectedEdgeMargin, mvt1LeftMargin, 1); Assert.assertEquals( "The padding between each element of the most visited tiles is incorrect.", expectedIntervalPadding,
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 801ce88..d84e796 100644 --- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -671,56 +671,6 @@ @Test @MediumTest @Feature({"StartSurface"}) - @DisableFeatures({ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT}) - @CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS}) - public void testShow_SingleAsHomepage_BottomSheet() { - if (!mImmediateReturn) { - StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity()); - } - - ChromeTabbedActivity cta = mActivityTestRule.getActivity(); - BottomSheetTestSupport bottomSheetTestSupport = new BottomSheetTestSupport( - cta.getRootUiCoordinatorForTesting().getBottomSheetController()); - StartSurfaceTestUtils.waitForStartSurfaceVisible( - mLayoutChangedCallbackHelper, mCurrentlyActiveLayout, cta); - TabUiTestHelper.verifyTabModelTabCount(cta, 1, 0); - assertFalse(bottomSheetTestSupport.hasSuppressionTokens()); - - if (isInstantReturn()) { - // TODO(crbug.com/1076274): fix toolbar to avoid wrongly focusing on the toolbar - // omnibox. - return; - } - - /** Verifies the case of start surface -> a tab -> tab switcher -> start surface. */ - StartSurfaceTestUtils.clickFirstTabInCarousel(); - assertFalse(bottomSheetTestSupport.hasSuppressionTokens()); - - TabUiTestHelper.enterTabSwitcher(cta); - StartSurfaceTestUtils.waitForTabSwitcherVisible(cta); - assertTrue(bottomSheetTestSupport.hasSuppressionTokens()); - - TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(false).launchNTP()); - onViewWaiting(withId(R.id.primary_tasks_surface_view)); - assertFalse(bottomSheetTestSupport.hasSuppressionTokens()); - - /** Verifies the case of navigating to a tab -> start surface -> tab switcher. */ - StartSurfaceTestUtils.clickFirstTabInCarousel(); - assertFalse(bottomSheetTestSupport.hasSuppressionTokens()); - - StartSurfaceTestUtils.pressHomePageButton(cta); - StartSurfaceTestUtils.waitForStartSurfaceVisible(cta); - assertFalse(bottomSheetTestSupport.hasSuppressionTokens()); - - StartSurfaceTestUtils.clickTabSwitcherButton(cta); - StartSurfaceTestUtils.waitForTabSwitcherVisible(cta); - assertTrue(bottomSheetTestSupport.hasSuppressionTokens()); - } - - @Test - @MediumTest - @Feature({"StartSurface"}) - @EnableFeatures({ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT}) @CommandLineFlags.Add({START_SURFACE_TEST_SINGLE_ENABLED_PARAMS}) public void testShow_SingleAsHomepage_BottomSheet_WithBottomSheetGtsSupport() { if (!mImmediateReturn) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowViewBinder.java index 2a075d6..ce55104 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowViewBinder.java
@@ -12,7 +12,7 @@ import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; -/** Binds model properties to view methods for ImprovedBookmarkRow. */ +/** Binds model properties to view methods for ImprovedBookmarkRow. */ class ImprovedBookmarkRowViewBinder { static void bind(PropertyModel model, View view, PropertyKey key) { ImprovedBookmarkRow row = (ImprovedBookmarkRow) view;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ShoppingAccessoryViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ShoppingAccessoryViewBinder.java index 2d50f783..784e2ad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ShoppingAccessoryViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ShoppingAccessoryViewBinder.java
@@ -9,7 +9,7 @@ import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; -/** Binds model properties to view methods for ShoppingAccessoryView. */ +/** Binds model properties to view methods for ShoppingAccessoryView. */ class ShoppingAccessoryViewBinder { static void bind(PropertyModel model, View view, PropertyKey key) { ShoppingAccessoryView shoppingView = (ShoppingAccessoryView) view;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java index cc0ed05..6d736ef 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesGridLayout.java
@@ -163,7 +163,8 @@ == Configuration.ORIENTATION_LANDSCAPE ? mTileViewLandscapeEdgePaddingTablet : mTileViewPortraitEdgePaddingTablet; - horizontalSpacing = (availableWidth - gridStart * 2) / (numColumns - 1); + horizontalSpacing = + (float) (availableWidth - gridStart * 2) / Math.max(1, numColumns - 1); } else { // Identically sized spacers are added both between and around the tiles. int spacerCount = numColumns + 1;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java index 183e543..eea84da7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.browser.ui; -import androidx.annotation.Nullable; - import org.chromium.base.Callback; import org.chromium.base.CallbackController; import org.chromium.base.supplier.ObservableSupplier; @@ -15,7 +13,6 @@ import org.chromium.chrome.browser.browser_controls.BrowserControlsVisibilityManager; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.layouts.LayoutStateProvider; import org.chromium.chrome.browser.layouts.LayoutStateProvider.LayoutStateObserver; import org.chromium.chrome.browser.layouts.LayoutType; @@ -26,12 +23,8 @@ import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; -import org.chromium.chrome.features.start_surface.StartSurface; -import org.chromium.chrome.features.start_surface.StartSurface.StateObserver; -import org.chromium.chrome.features.start_surface.StartSurfaceState; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; -import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; import org.chromium.components.browser_ui.bottomsheet.ManagedBottomSheetController; import org.chromium.content_public.browser.SelectionPopupController; @@ -59,11 +52,6 @@ private final CallbackController mCallbackController; - /** The supplier of {@link StartSurface} instance. */ - private final OneshotSupplier<StartSurface> mStartSurfaceSupplier; - private StateObserver mStartSurfaceStateObserver; - - private final boolean mIsStartSurfaceRefactorEnabled; private final OneshotSupplier<LayoutStateProvider> mLayoutStateProviderSupplier; private LayoutStateProvider.LayoutStateObserver mLayoutStateObserver; @@ -112,9 +100,6 @@ /** The token used to enable browser controls persistence. */ private int mPersistentControlsToken; - /** A token used to suppress the bottom sheet in Tab switcher. */ - private int mTabSwitcherToken; - public BottomSheetManager(ManagedBottomSheetController controller, ActivityTabProvider tabProvider, BrowserControlsVisibilityManager controlsVisibilityManager, @@ -123,9 +108,7 @@ TabObscuringHandler obscuringDelegate, ObservableSupplier<Boolean> omniboxFocusStateSupplier, Supplier<OverlayPanelManager> overlayManager, - OneshotSupplier<StartSurface> startSurfaceSupplier, - OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier, - boolean isStartSurfaceRefactorEnabled) { + OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier) { mSheetController = controller; mTabProvider = tabProvider; mBrowserControlsVisibilityManager = controlsVisibilityManager; @@ -135,18 +118,6 @@ mOmniboxFocusStateSupplier = omniboxFocusStateSupplier; mOverlayPanelManager = overlayManager; mCallbackController = new CallbackController(); - mIsStartSurfaceRefactorEnabled = isStartSurfaceRefactorEnabled; - - // TODO(https://crbug.com/1315679): Remove |mStartSurfaceSupplier|, |mStartSurfaceState| and - // |mStartSurfaceStateObserver| after the refactor is enabled by default. - mStartSurfaceSupplier = startSurfaceSupplier; - - // With BottomSheetGtsSupport observing the StartSurface state is not necessary. - if (!ChromeFeatureList.sBottomSheetGtsSupport.isEnabled() - && !mIsStartSurfaceRefactorEnabled) { - mStartSurfaceSupplier.onAvailable( - mCallbackController.makeCancelable(this::addStartSurfaceStateObserver)); - } mLayoutStateProviderSupplier = layoutStateProviderSupplier; mLayoutStateProviderSupplier.onAvailable( @@ -208,19 +179,6 @@ } private void setActivityTab(Tab tab) { - if (!ChromeFeatureList.sBottomSheetGtsSupport.isEnabled()) { - // Temporarily suppress the sheet if entering a state where there is no activity - // tab and the Start surface homepage isn't showing. Otherwise unsuppress the - // sheet. - updateSuppressionForTabSwitcher(tab, - mStartSurfaceSupplier.get() == null - ? null - : mStartSurfaceSupplier.get().getStartSurfaceState(), - mLayoutStateProviderSupplier.get() == null - ? null - : mLayoutStateProviderSupplier.get().getActiveLayoutType()); - } - if (tab == null) return; if (mLastActivityTab == tab) return; @@ -232,126 +190,20 @@ mSheetController.clearRequestsAndHide(); } - /** - * Called by both {@link StateObserver} and {@link HintlessActivityTabObserver} to update the - * suppression of the bottom sheet for Tab switcher. - * @param tab The current tab. It might be null when the Start surface or the Tab switcher is - * showing. - * @param startSurfaceState The current state surface state when the Start surface is enabled, - * null otherwise. It's also null when the refactor is enabled. - * @param layoutType The current layout type, currently only used when the refactor is enabled. - */ - private void updateSuppressionForTabSwitcher(@Nullable Tab tab, - @Nullable @StartSurfaceState Integer startSurfaceState, - @Nullable @LayoutType Integer layoutType) { - assert !ChromeFeatureList.sBottomSheetGtsSupport.isEnabled() - : "Bottom Sheet GTS support removes tab switcher suppression."; - if (shouldSuppressForTabSwitcher(tab, startSurfaceState, layoutType)) { - if (mTabSwitcherToken == 0) { - mTabSwitcherToken = mSheetController.suppressSheet(StateChangeReason.COMPOSITED_UI); - } - } else { - mSheetController.unsuppressSheet(mTabSwitcherToken); - /** - * Reset the token after unsuppression. Without resetting the token, the bottom sheet - * won't be suppress again the next time entering Tab switcher. This is because the - * bottom sheet is only suppressed in Tab switcher if {@link mTabSwitcherToken} is 0 by - * the first observer who notices the event. - */ - mTabSwitcherToken = 0; - } - } - - private boolean shouldSuppressForTabSwitcher(Tab tab, - @StartSurfaceState Integer startSurfaceState, - @Nullable @LayoutType Integer layoutType) { - assert !ChromeFeatureList.sBottomSheetGtsSupport.isEnabled() - : "Bottom Sheet GTS support removes tab switcher suppression."; - StartSurface startSurface = mStartSurfaceSupplier.get(); - - if (mIsStartSurfaceRefactorEnabled) { - if (layoutType == null) return tab == null; - if (layoutType == LayoutType.START_SURFACE) { - return false; - } else if (layoutType == LayoutType.TAB_SWITCHER) { - // If startSurface is not null, start surface is enabled. - return startSurface != null; - } - } else { - if (startSurface == null || startSurfaceState == null) return tab == null; - if (startSurfaceState == StartSurfaceState.SHOWING_HOMEPAGE - || startSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE) { - return false; - } else if (startSurfaceState != StartSurfaceState.NOT_SHOWN - && startSurfaceState != StartSurfaceState.DISABLED) { - return true; - } - } - return tab == null; - } - - private void addStartSurfaceStateObserver(StartSurface startSurface) { - mStartSurfaceStateObserver = new StateObserver() { - private int mStartSurfaceState; + private void addLayoutStateObserver(LayoutStateProvider layoutStateProvider) { + mLayoutStateObserver = new LayoutStateObserver() { + // On switching to a new layout act as though this is a tab switch by clearing all + // state. Use onStartedHiding to avoid the bottom sheet being visible during the + // transition if there is one. @Override - public void onStateChanged( - int startSurfaceState, boolean shouldShowTabSwitcherToolbar) { - if (mStartSurfaceState == startSurfaceState) return; - - assert startSurfaceState == startSurface.getStartSurfaceState(); - mStartSurfaceState = startSurfaceState; - updateSuppressionForTabSwitcher(mTabProvider.get(), startSurfaceState, null); - - if (startSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE) { + public void onStartedHiding(int layoutType) { + if (layoutType != LayoutType.SIMPLE_ANIMATION) { mSheetController.clearRequestsAndHide(); } } }; - startSurface.addStateChangeObserver(mStartSurfaceStateObserver); - } - - private void addLayoutStateObserver(LayoutStateProvider layoutStateProvider) { - if (mIsStartSurfaceRefactorEnabled - && !ChromeFeatureList.sBottomSheetGtsSupport.isEnabled()) { - mLayoutStateObserver = new LayoutStateObserver() { - private @LayoutType int mLayoutType; - - @Override - public void onFinishedShowing(int layoutType) { - if (mLayoutType == layoutType) return; - - mLayoutType = layoutType; - updateSuppressionForTabSwitcher(mTabProvider.get(), null, mLayoutType); - if (mLayoutType == LayoutType.START_SURFACE) { - mSheetController.clearRequestsAndHide(); - } - } - }; - } else if (ChromeFeatureList.sBottomSheetGtsSupport.isEnabled()) { - mLayoutStateObserver = new LayoutStateObserver() { - // On switching to a new layout act as though this is a tab switch by clearing all - // state. Use onStartedHiding to avoid the bottom sheet being visible during the - // transition if there is one. - @Override - public void onStartedHiding(int layoutType) { - if (layoutType != LayoutType.SIMPLE_ANIMATION) { - mSheetController.clearRequestsAndHide(); - } - } - }; - } - - if (mLayoutStateObserver == null) return; layoutStateProvider.addObserver(mLayoutStateObserver); - // It is possible that the observer missed the first layout change event due to the - // layoutStateProvider being initialized too late during the startup. Call the observer's - // handling function now. - @LayoutType - int layout = layoutStateProvider.getActiveLayoutType(); - if (layout != LayoutType.NONE) { - mLayoutStateObserver.onFinishedShowing(layout); - } } @Override @@ -458,9 +310,6 @@ mSheetController.removeObserver(this); mBrowserControlsVisibilityManager.removeObserver(mBrowserControlsObserver); mOmniboxFocusStateSupplier.removeObserver(mOmniboxFocusObserver); - if (mStartSurfaceSupplier.get() != null) { - mStartSurfaceSupplier.get().removeStateChangeObserver(mStartSurfaceStateObserver); - } if (mLayoutStateProviderSupplier.get() != null) { mLayoutStateProviderSupplier.get().removeObserver(mLayoutStateObserver); }
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 7e57ff6..108b53a 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
@@ -120,7 +120,6 @@ import org.chromium.chrome.browser.tab.TabUtils.LoadIfNeededCaller; import org.chromium.chrome.browser.tabmodel.TabCreatorManager; import org.chromium.chrome.browser.tabmodel.TabModelSelector; -import org.chromium.chrome.browser.tasks.ReturnToChromeUtil; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; import org.chromium.chrome.browser.theme.TopUiThemeColorProvider; import org.chromium.chrome.browser.toolbar.ButtonDataProvider; @@ -1472,9 +1471,8 @@ mBottomSheetManager = new BottomSheetManager(mBottomSheetController, mActivityTabProvider, mBrowserControlsManager, mModalDialogManagerSupplier, this::getBottomSheetSnackbarManager, mTabObscuringHandlerSupplier.get(), - mOmniboxFocusStateSupplier, panelManagerSupplier, mStartSurfaceSupplier, - mLayoutStateProviderOneShotSupplier, - ReturnToChromeUtil.isStartSurfaceRefactorEnabled(mActivity)); + mOmniboxFocusStateSupplier, panelManagerSupplier, + mLayoutStateProviderOneShotSupplier); // TODO(crbug.com/1279941): Consider moving handler registration to feature code. if (BackPressManager.isEnabled()) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java index ab8c24a..7cfe410 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxActionsTest.java
@@ -4,6 +4,10 @@ package org.chromium.chrome.browser.omnibox.suggestions; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; + import android.app.Activity; import androidx.annotation.Nullable; @@ -29,7 +33,6 @@ import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.HistogramWatcher; import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -53,8 +56,8 @@ import org.chromium.components.omnibox.AutocompleteResult; import org.chromium.components.omnibox.EntityInfoProto.ActionInfo; import org.chromium.components.omnibox.OmniboxSuggestionType; -import org.chromium.components.omnibox.action.ActionInSuggestUmaType; import org.chromium.components.omnibox.action.OmniboxAction; +import org.chromium.components.omnibox.action.OmniboxActionJni; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.test.util.DisableAnimationsTestRule; @@ -81,6 +84,7 @@ public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); public @Rule TestRule mFeaturesProcessor = new Features.JUnitProcessor(); private @Mock AutocompleteController.Natives mAutocompleteControllerJniMock; + private @Mock OmniboxActionJni mOmniboxActionJni; private OmniboxTestUtils mOmniboxUtils; private Activity mTargetActivity; @@ -97,6 +101,7 @@ sActivityTestRule.loadUrl("about:blank"); mOmniboxUtils = new OmniboxTestUtils(sActivityTestRule.getActivity()); mJniMocker.mock(AutocompleteControllerJni.TEST_HOOKS, mAutocompleteControllerJniMock); + mJniMocker.mock(OmniboxActionJni.TEST_HOOKS, mOmniboxActionJni); } @After @@ -109,7 +114,9 @@ if (mTargetActivity != null) { ApplicationTestUtils.finishActivity(mTargetActivity); } + verifyNoMoreInteractions(mOmniboxActionJni); mJniMocker.mock(AutocompleteControllerJni.TEST_HOOKS, null); + mJniMocker.mock(OmniboxActionJni.TEST_HOOKS, null); } /** @@ -124,7 +131,7 @@ CriteriaHelper.pollUiThread(() -> { var adapter = (ActionChipsAdapter) info.view.getActionChipsView().getAdapter(); if (adapter.getItemCount() < actionIndex) return false; - adapter.setSelectedItem(ActionChipsAdapter.FIRST_CHIP_INDEX + actionIndex); + adapter.setSelectedItem(actionIndex); return adapter.getSelectedView().performClick(); }); } @@ -138,6 +145,10 @@ */ private void setSuggestions(AutocompleteMatch... matches) { mOmniboxUtils.requestFocus(); + // Ensure we start from empty suggestions list; don't carry over suggestions from previous + // run. + mOmniboxUtils.setSuggestions(AutocompleteResult.fromCache(null, null), ""); + mOmniboxUtils.setSuggestions( AutocompleteResult.fromCache(Arrays.asList(matches), null), ""); mOmniboxUtils.checkSuggestionsShown(); @@ -154,14 +165,14 @@ } private AutocompleteMatch createDummyHistoryClustersAction(String name) { - return createDummySuggestion(List.of(new HistoryClustersAction("hint", name))); + return createDummySuggestion(List.of(new HistoryClustersAction(0, "hint", name))); } private AutocompleteMatch createDummyActionInSuggest(ActionInfo.ActionType... types) { var actions = new ArrayList<OmniboxAction>(); for (var type : types) { - actions.add( - new OmniboxActionInSuggest("hint", type.getNumber(), "https://www.google.com")); + actions.add(new OmniboxActionInSuggest( + type.getNumber(), "hint", type.getNumber(), "https://www.google.com")); } return createDummySuggestion(actions); @@ -198,14 +209,14 @@ createDummyActionInSuggest(ActionInfo.ActionType.CALL), createDummyActionInSuggest(ActionInfo.ActionType.DIRECTIONS)); - var histogramWatcher = HistogramWatcher.newBuilder() - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.CALL) - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.DIRECTIONS) - .build(); mOmniboxUtils.clearFocus(); - histogramWatcher.assertExpected(); + + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.CALL_VALUE, /*position=*/1, /*executed=*/false); + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.DIRECTIONS_VALUE, /*position=*/2, /*executed=*/false); } @Test @@ -216,16 +227,14 @@ createDummyActionInSuggest(ActionInfo.ActionType.CALL), createDummyActionInSuggest(ActionInfo.ActionType.DIRECTIONS)); - var histogramWatcher = HistogramWatcher.newBuilder() - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.CALL) - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.DIRECTIONS) - .expectIntRecord("Omnibox.ActionInSuggest.Used", - ActionInSuggestUmaType.CALL) - .build(); clickOnAction(0); - histogramWatcher.assertExpected(); + + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.CALL_VALUE, /*position=*/1, /*executed=*/true); + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.DIRECTIONS_VALUE, /*position=*/2, /*executed=*/false); } @Test @@ -236,17 +245,16 @@ createDummyActionInSuggest(ActionInfo.ActionType.CALL, ActionInfo.ActionType.DIRECTIONS, ActionInfo.ActionType.REVIEWS)); - var histogramWatcher = HistogramWatcher.newBuilder() - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.CALL) - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.DIRECTIONS) - .expectIntRecord("Omnibox.ActionInSuggest.Used", - ActionInSuggestUmaType.REVIEWS) - .expectIntRecord("Omnibox.ActionInSuggest.Shown", - ActionInSuggestUmaType.REVIEWS) - .build(); clickOnAction(2); - histogramWatcher.assertExpected(); + + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.CALL_VALUE, /*position=*/1, /*executed=*/false); + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.DIRECTIONS_VALUE, /*position=*/1, /*executed=*/false); + verify(mOmniboxActionJni, times(1)) + .recordActionShown( + ActionInfo.ActionType.REVIEWS_VALUE, /*position=*/1, /*executed=*/true); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java index cc8238c1..fee9951 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsRenderTest.java
@@ -109,7 +109,7 @@ private AutocompleteMatch createDummyPedalSuggestion(String name, @OmniboxPedalId int id) { return AutocompleteMatchBuilder.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) .setDisplayText(name) - .setActions(List.of(new OmniboxPedal("hint", id))) + .setActions(List.of(new OmniboxPedal(0, "hint", id))) .build(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java index 5a97985..06def94 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/suggestions/OmniboxPedalsTest.java
@@ -257,7 +257,7 @@ private AutocompleteMatch createDummyPedalSuggestion(String name, @OmniboxPedalId int id) { return AutocompleteMatchBuilder.searchWithType(OmniboxSuggestionType.SEARCH_SUGGEST) .setDisplayText(name) - .setActions(List.of(new OmniboxPedal("hint", id))) + .setActions(List.of(new OmniboxPedal(0, "hint", id))) .build(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java index c787ddd..1b7c4720 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
@@ -18,7 +18,6 @@ import androidx.test.filters.SmallTest; import androidx.test.platform.app.InstrumentationRegistry; -import org.hamcrest.Matchers; import org.junit.After; import org.junit.Before; import org.junit.ClassRule; @@ -26,15 +25,11 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Criteria; -import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; -import org.chromium.base.test.util.RequiresRestart; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.flags.CachedFeatureFlags; @@ -48,12 +43,10 @@ import org.chromium.chrome.browser.tab.TabSelectionType; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.chrome.browser.tabmodel.TabModelObserver; -import org.chromium.chrome.features.start_surface.StartSurfaceState; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; import org.chromium.chrome.test.util.ChromeTabUtils; -import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; @@ -261,34 +254,10 @@ mSheetController.getSheetState()); } - // TODO(https://crbug.com/1434474): Remove this test (and flag) once it is safe. @Test @MediumTest @Feature({"BottomSheetController"}) - @Features.DisableFeatures({ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT}) - @RequiresRestart("Requires re-creating BottomSheetManager for flag change.") - public void testSheetPeekAfterTabSwitcher() throws Exception { - requestContentInSheet(mLowPriorityContent, true); - enterAndExitTabSwitcher(); - BottomSheetTestSupport.waitForState(mSheetController, SheetState.PEEK); - assertEquals("The bottom sheet is showing incorrect content.", mLowPriorityContent, - mSheetController.getCurrentSheetContent()); - - // TODO(https://crbug.com/1434471): Finish activity early. During teardown - // BOTTOM_SHEET_GTS_SUPPORT may revert to enabled before the activity is finished. If this - // happens it is possible that BottomSheetManager's StartSurface StateObserver will trigger - // an assert to check that the flag is disabled during shutdown. - ApplicationTestUtils.finishActivity(mActivity); - mActivity = null; - } - - @Test - @MediumTest - @Feature({"BottomSheetController"}) - @Features.EnableFeatures( - {ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT, ChromeFeatureList.START_SURFACE_REFACTOR}) - public void - testSheetGoneAfterTabSwitcher_withStartSurfaceRefactor() throws TimeoutException { + public void testSheetGoneAfterTabSwitcher() throws TimeoutException { requestContentInSheet(mLowPriorityContent, true); enterAndExitTabSwitcher(); BottomSheetTestSupport.waitForState(mSheetController, SheetState.HIDDEN); @@ -299,67 +268,7 @@ @Test @MediumTest @Feature({"BottomSheetController"}) - @Features.DisableFeatures({ChromeFeatureList.START_SURFACE_REFACTOR}) - @Features.EnableFeatures({ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT}) - public void testSheetGoneAfterTabSwitcher_withoutStartSurfaceRefactor() - throws TimeoutException { - requestContentInSheet(mLowPriorityContent, true); - enterAndExitTabSwitcher(); - BottomSheetTestSupport.waitForState(mSheetController, SheetState.HIDDEN); - assertNull("The bottom sheet is unexpectedly showing content.", - mSheetController.getCurrentSheetContent()); - } - - // TODO(https://crbug.com/1434474): Remove this test (and flag) once it is safe. - @Test - @MediumTest - @Feature({"BottomSheetController"}) - @Features.DisableFeatures({ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT}) - @RequiresRestart("Requires re-creating BottomSheetManager for flag change.") - public void testSheetHiddenAfterTabSwitcher() throws Exception { - // Open a second tab. - Tab tab1 = mActivity.getActivityTab(); - openNewTabInForeground(); - Tab tab2 = mActivity.getActivityTab(); - - requestContentInSheet(mLowPriorityContent, true); - - // Enter the tab switcher and select a different tab. - setTabSwitcherState(true); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - assertEquals("The bottom sheet should be hidden.", SheetState.HIDDEN, - mSheetController.getSheetState()); - assertEquals("The bottom sheet contains the incorrect content.", mLowPriorityContent, - mSheetController.getCurrentSheetContent()); - mActivity.getTabModelSelector().getCurrentModel().setIndex( - 0, TabSelectionType.FROM_USER, false); - }); - - setTabSwitcherState(false); - - BottomSheetTestSupport.waitForContentChange(mSheetController, null); - assertEquals("The bottom sheet still should be hidden.", SheetState.HIDDEN, - mSheetController.getSheetState()); - assertNull("The bottom sheet is unexpectedly has content.", - mSheetController.getCurrentSheetContent()); - - // TODO(https://crbug.com/1434471): Finish activity early. During teardown - // BOTTOM_SHEET_GTS_SUPPORT may revert to enabled before the activity is finished. If this - // happens it is possible that BottomSheetManager's StartSurface StateObserver will trigger - // an assert to check that the flag is disabled during shutdown. - ApplicationTestUtils.finishActivity(mActivity); - mActivity = null; - } - - @Test - @MediumTest - @Feature({"BottomSheetController"}) - @Features.EnableFeatures( - {ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT, ChromeFeatureList.START_SURFACE_REFACTOR}) - public void - testSheetGoneAfterTransitioningToAndFromSwitcher_withStartSurfaceRefactor() - throws TimeoutException { + public void testSheetGoneAfterTransitioningToAndFromSwitcher() throws TimeoutException { // Open a second tab. Tab tab1 = mActivity.getActivityTab(); openNewTabInForeground(); @@ -407,61 +316,6 @@ @Test @MediumTest @Feature({"BottomSheetController"}) - @Features.DisableFeatures({ChromeFeatureList.START_SURFACE_REFACTOR}) - @Features.EnableFeatures({ChromeFeatureList.BOTTOM_SHEET_GTS_SUPPORT}) - public void testSheetGoneAfterTransitioningToAndFromSwitcher_withoutStartSurfaceRefactor() - throws TimeoutException { - // Open a second tab. - Tab tab1 = mActivity.getActivityTab(); - openNewTabInForeground(); - Tab tab2 = mActivity.getActivityTab(); - - requestContentInSheet(mLowPriorityContent, true); - assertEquals("The tab bottom sheet should be visible.", SheetState.PEEK, - mSheetController.getSheetState()); - assertEquals("The tab bottom sheet contains the incorrect content.", mLowPriorityContent, - mSheetController.getCurrentSheetContent()); - - // Enter the tab switcher. - setTabSwitcherState(true); - CriteriaHelper.pollUiThread( - () - -> Criteria.checkThat(mActivity.getStartSurface().getStartSurfaceState(), - Matchers.is(StartSurfaceState.SHOWN_TABSWITCHER))); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - assertEquals("The tab bottom sheet should be hidden.", SheetState.HIDDEN, - mSheetController.getSheetState()); - assertNull("The bottom sheet is unexpectedly showing content.", - mSheetController.getCurrentSheetContent()); - }); - - // Show a sheet in the tab switcher. - requestContentInSheet(mHighPriorityContent, true); - BottomSheetTestSupport.waitForState(mSheetController, SheetState.PEEK); - - TestThreadUtils.runOnUiThreadBlocking(() -> { - assertEquals("The GTS bottom sheet should be visible.", SheetState.PEEK, - mSheetController.getSheetState()); - assertEquals("The GTS bottom sheet contains the incorrect content.", - mHighPriorityContent, mSheetController.getCurrentSheetContent()); - mActivity.getTabModelSelector().getCurrentModel().setIndex( - 0, TabSelectionType.FROM_USER, false); - }); - - // Exit tab switcher. - setTabSwitcherState(false); - - BottomSheetTestSupport.waitForContentChange(mSheetController, null); - assertEquals("The GTS bottom sheet should be hidden.", SheetState.HIDDEN, - mSheetController.getSheetState()); - assertNull("The bottom sheet is unexpectedly showing content.", - mSheetController.getCurrentSheetContent()); - } - - @Test - @MediumTest - @Feature({"BottomSheetController"}) public void testContentDestroyedOnHidden() throws TimeoutException { requestContentInSheet(mLowPriorityContent, true); int destroyCallCount = mLowPriorityContent.destroyCallbackHelper.getCallCount();
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn index 4203f77e..d7531ca 100644 --- a/chrome/app/BUILD.gn +++ b/chrome/app/BUILD.gn
@@ -227,10 +227,7 @@ sources += [ "chrome_main_mac.mm" ] configs += [ "//build/config/compiler:enable_arc" ] - deps += [ - "//chrome:chrome_framework", - "//chrome/browser:browser_noarc", - ] + deps += [ "//chrome:chrome_framework" ] } if (is_win) {
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 0141f1f..86d465f 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -217,6 +217,7 @@ #endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON) #if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "base/scoped_add_feature_flags.h" #include "chrome/common/chrome_paths_lacros.h" #include "chromeos/crosapi/cpp/crosapi_constants.h" // nogncheck #include "chromeos/crosapi/mojom/crosapi.mojom.h" // nogncheck @@ -230,6 +231,7 @@ #include "content/public/browser/zygote_host/zygote_host_linux.h" #include "media/base/media_switches.h" #include "ui/base/resource/data_pack_with_resource_sharing_lacros.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/switches.h" #endif @@ -842,6 +844,12 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kEnableNativeGpuMemoryBuffers); } + + if (init_params->IsVariableRefreshRateEnabled()) { + base::ScopedAddFeatureFlags add_feature_flags( + base::CommandLine::ForCurrentProcess()); + add_feature_flags.EnableIfNotSet(::features::kEnableVariableRefreshRate); + } } #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index b092bbff..6ff88501 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -3861,6 +3861,9 @@ <message name="IDS_CERT_X509_CERT_POLICIES" desc="description of extension Certificate Policies"> Certificate Policies </message> + <message name="IDS_CERT_X509_SCT_LIST" desc="description of extension Signed Certificate Timestamp List"> + Signed Certificate Timestamp List + </message> <message name="IDS_CERT_X509_POLICY_MAPPINGS" desc="description of extension Certificate Policy Mappings"> Certificate Policy Mappings </message> @@ -3981,6 +3984,12 @@ <message name="IDS_CERT_GENERAL_NAME_REGISTERED_ID" desc="label for the certRegisteredID general name type"> Registered OID </message> + <message name="IDS_CERT_EXT_MS_APP_POLICIES" desc="description of extension Microsoft Application Policies"> + Microsoft Application Policies + </message> + <message name="IDS_CERT_EXT_MS_CERT_TEMPLATE" desc="description of extension Microsoft Certificate Template"> + Microsoft Certificate Template + </message> <message name="IDS_CERT_EXT_MS_CERT_TYPE" desc="description of extension Microsoft Certificate Template Name"> Microsoft Certificate Template Name </message> @@ -7684,6 +7693,12 @@ <message name="IDS_BOOKMARKS_EMPTY_STATE_BODY" desc="Body text for the bookmarks side panel empty state"> Bookmark things you want to come back to later </message> + <message name="IDS_BOOKMARKS_EMPTY_STATE_TITLE_FOLDER" desc="Title for the bookmarks side panel empty state in a folder view"> + Nothing to show yet + </message> + <message name="IDS_BOOKMARKS_EMPTY_STATE_BODY_FOLDER" desc="Body text for the bookmarks side panel empty state in a folder view"> + Add a bookmark to this folder + </message> <message name="IDS_BOOKMARKS_EMPTY_STATE_TITLE_GUEST" desc="Title for the bookmarks side panel empty state in guest mode"> Sign in to see your bookmarks </message>
diff --git a/chrome/app/generated_resources_grd/IDS_BOOKMARKS_EMPTY_STATE_BODY_FOLDER.png.sha1 b/chrome/app/generated_resources_grd/IDS_BOOKMARKS_EMPTY_STATE_BODY_FOLDER.png.sha1 new file mode 100644 index 0000000..aeb7dae --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_BOOKMARKS_EMPTY_STATE_BODY_FOLDER.png.sha1
@@ -0,0 +1 @@ +264bfe39594df448cf7bb9408af59d6f4646dfee \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_BOOKMARKS_EMPTY_STATE_TITLE_FOLDER.png.sha1 b/chrome/app/generated_resources_grd/IDS_BOOKMARKS_EMPTY_STATE_TITLE_FOLDER.png.sha1 new file mode 100644 index 0000000..aeb7dae --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_BOOKMARKS_EMPTY_STATE_TITLE_FOLDER.png.sha1
@@ -0,0 +1 @@ +264bfe39594df448cf7bb9408af59d6f4646dfee \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_EXT_MS_APP_POLICIES.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_EXT_MS_APP_POLICIES.png.sha1 new file mode 100644 index 0000000..28ab4e8 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_CERT_EXT_MS_APP_POLICIES.png.sha1
@@ -0,0 +1 @@ +8611ddb9c8ba953ea16f2b25d1f184d7a8f20d96 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_EXT_MS_CERT_TEMPLATE.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_EXT_MS_CERT_TEMPLATE.png.sha1 new file mode 100644 index 0000000..28ab4e8 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_CERT_EXT_MS_CERT_TEMPLATE.png.sha1
@@ -0,0 +1 @@ +8611ddb9c8ba953ea16f2b25d1f184d7a8f20d96 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_CERT_X509_SCT_LIST.png.sha1 b/chrome/app/generated_resources_grd/IDS_CERT_X509_SCT_LIST.png.sha1 new file mode 100644 index 0000000..28ab4e8 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_CERT_X509_SCT_LIST.png.sha1
@@ -0,0 +1 @@ +8611ddb9c8ba953ea16f2b25d1f184d7a8f20d96 \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index 8f5913f..44eb0ec 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1555,6 +1555,15 @@ <message name="IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADDITIONAL_SITES" desc="Label for button that expands the tab discarding exceptions list to show all entries. Sites added to the list will not be discarded by memory saver."> Additional sites </message> + <message name="IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADD_DIALOG_CURRENT_TABS" desc="Label for the first tab of the tab discarding exception list add dialog, that allows users to pick sites from currently opened tabs to add to the list." translateable="false"> + Add open tabs + </message> + <message name="IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADD_DIALOG_MANUAL" desc="Label for the second tab of the tab discarding exception list add dialog, where users can manually input a site to be added to the list." translateable="false"> + Add sites manually + </message> + <message name="IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADD_DIALOG_HELP" desc="Label for button that expands the tab discarding exceptions list to show all entries. Sites added to the list will not be discarded by memory saver." translateable="false"> + Sites you add remain active and won't be used to give active tabs and other apps more resources. <ph name="BEGIN_LINK"><a href="$1" target="_blank"></ph>Learn more about site exclusion<ph name="END_LINK"></a></ph> + </message> <message name="IDS_SETTINGS_BATTERY_PAGE_TITLE" desc="Title of the power section of the performance settings page"> Power </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index dbbd9dd..1c302ba 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -134,60 +134,6 @@ ] } -if (is_mac) { - source_set("browser_noarc") { - # TODO(https://crbug.com/1280317): Merge back into the `browser` target. - sources = [ - "app_controller_mac.h", - "app_controller_mac.mm", - "browser_process_platform_part_mac.h", - "browser_process_platform_part_mac.mm", - "chrome_browser_application_mac.h", - "chrome_browser_application_mac.mm", - "chrome_browser_main_mac.h", - "chrome_browser_main_mac.mm", - "mac/auth_session_request.h", - "mac/auth_session_request.mm", - ] - if (enable_service_discovery) { - sources += [ - # TODO(https://crbug.com/1280317): When merging back, search for - # `enable_service_discovery` to put these back. - "local_discovery/service_discovery_client_mac.h", - "local_discovery/service_discovery_client_mac.mm", - ] - } - deps = [ - ":browser_process", - "//base", - "//build:branding_buildflags", - "//chrome/app:command_ids", - "//chrome/app:notification_metrics", - "//chrome/browser:buildflags", - "//chrome/browser/apps/app_shim", - "//chrome/browser/apps/platform_apps", - "//chrome/browser/extensions", - "//chrome/browser/mac:keystone_glue", - "//chrome/browser/profiles", - "//chrome/browser/profiles:profile", - "//chrome/browser/ui/tabs:tab_enums", - "//chrome/browser/updater:browser_updater_client", - "//chrome/browser/updater:scheduler", - "//chrome/browser/web_applications", - "//chrome/common", - "//components/enterprise", - "//components/handoff", - "//components/keep_alive_registry", - "//components/os_crypt/sync", - "//components/prefs", - "//components/sessions", - "//components/sessions:session_id", - "//extensions/browser", - "//services/device/public/cpp/geolocation", - ] - } -} - # Use a static library here because many test binaries depend on this but don't # require many files from it. This makes linking more efficient. static_library("browser") { @@ -2127,7 +2073,6 @@ "//components/commerce/core:pref_names", "//components/commerce/core:shopping_service", "//components/component_updater", - "//components/component_updater:crl_set_remover", "//components/component_updater/installer_policies", "//components/consent_auditor", "//components/content_capture/browser", @@ -5971,18 +5916,23 @@ } } - if (is_apple) { - configs += [ "//build/config/compiler:enable_arc" ] - } - if (is_mac) { + allow_circular_includes_from += [ "//chrome/browser/apps/app_shim" ] sources += [ "accessibility/caption_settings_dialog.h", "accessibility/caption_settings_dialog_mac.cc", + "app_controller_mac.h", + "app_controller_mac.mm", "apps/intent_helper/mac_intent_picker_helpers.h", "apps/intent_helper/mac_intent_picker_helpers.mm", "badging/badge_manager_delegate_mac.cc", "badging/badge_manager_delegate_mac.h", + "browser_process_platform_part_mac.h", + "browser_process_platform_part_mac.mm", + "chrome_browser_application_mac.h", + "chrome_browser_application_mac.mm", + "chrome_browser_main_mac.h", + "chrome_browser_main_mac.mm", "component_updater/recovery_improved_component_installer_mac.cc", "device_reauth/mac/authenticator_mac.h", "device_reauth/mac/authenticator_mac.mm", @@ -6001,6 +5951,8 @@ "hang_monitor/hang_crash_dump_mac.cc", "icon_loader_mac.mm", "lifetime/application_lifetime_mac.mm", + "mac/auth_session_request.h", + "mac/auth_session_request.mm", "mac/bluetooth_utility.h", "mac/bluetooth_utility.mm", "mac/chrome_browser_main_extra_parts_mac.h", @@ -6061,7 +6013,6 @@ "webshare/mac/sharing_service_operation.mm", ] deps += [ - ":browser_noarc", "//chrome/app:notification_metrics", "//chrome/app_shim", "//chrome/browser/apps/app_shim", @@ -6083,11 +6034,7 @@ "//third_party/crashpad/crashpad/client", "//third_party/google_toolbox_for_mac", ] - allow_circular_includes_from += [ - ":browser_noarc", - "//chrome/browser/apps/app_shim", - "//chrome/browser/ui:ui_arc", - ] + allow_circular_includes_from += [ "//chrome/browser/ui:ui_arc" ] frameworks = [ "Accelerate.framework", "AudioUnit.framework", @@ -7416,8 +7363,8 @@ if (is_mac) { sources += [ - # TODO(https://crbug.com/1280317): Put service_discovery_client_mac files - # back here. + "local_discovery/service_discovery_client_mac.h", + "local_discovery/service_discovery_client_mac.mm", "local_discovery/service_discovery_client_mac_factory.h", "local_discovery/service_discovery_client_mac_factory.mm", ]
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 16f19a91..b982eff 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3222,14 +3222,34 @@ }; #if BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) -constexpr FeatureEntry::FeatureParam kCscVariation[] = { +constexpr FeatureEntry::FeatureParam kCscStagingEnvVariation[] = { {"companion-homepage-url", "https://lens-staging.corp.google.com/companion"}, {"companion-image-upload-url", "https://lens-staging.corp.google.com/v2/upload"}}; +constexpr FeatureEntry::FeatureParam kCscClobberVariation[] = { + {"open-links-in-current-tab", "true"}, +}; +constexpr FeatureEntry::FeatureParam kCscNewTabVariation[] = { + {"open-links-in-current-tab", "false"}, +}; constexpr FeatureEntry::FeatureVariation kCscVariations[] = { - {"with staging URL", kCscVariation, std::size(kCscVariation), nullptr}}; + {"with staging URL", kCscStagingEnvVariation, + std::size(kCscStagingEnvVariation), nullptr}, + {"with clobber", kCscClobberVariation, std::size(kCscClobberVariation), + nullptr}, + {"with new tab", kCscNewTabVariation, std::size(kCscNewTabVariation), + nullptr}, +}; + +const FeatureEntry::Choice kSidePanelPinnedStateChoices[] = { + {flags_ui::kGenericExperimentChoiceDefault, "", ""}, + {"Forced Pinned", companion::switches::kForceCompanionPinnedState, + "pinned"}, + {"Forced Unpinned", companion::switches::kForceCompanionPinnedState, + "unpinned"}, +}; #endif // BUILDFLAG(ENABLE_LENS_DESKTOP_GOOGLE_BRANDED_FEATURES) #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -7502,16 +7522,6 @@ FEATURE_VALUE_TYPE(media::kGlobalMediaControlsCrOSUpdatedUI)}, #endif // BUILDFLAG(IS_CHROMEOS) -#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) - {"global-media-controls-modern-ui", - flag_descriptions::kGlobalMediaControlsModernUIName, - flag_descriptions::kGlobalMediaControlsModernUIDescription, - kOsWin | kOsMac | kOsLinux | kOsLacros | kOsCrOS | kOsFuchsia, - FEATURE_VALUE_TYPE(media::kGlobalMediaControlsModernUI)}, -#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || - // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA) - {"turn-off-streaming-media-caching-on-battery", flag_descriptions::kTurnOffStreamingMediaCachingOnBatteryName, flag_descriptions::kTurnOffStreamingMediaCachingOnBatteryDescription, @@ -8001,14 +8011,10 @@ flag_descriptions::kShortcutCustomizationJellyName, flag_descriptions::kShortcutCustomizationJellyDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kShortcutCustomizationJelly)}, - {"nearby-sharing-self-share-auto-accept", - flag_descriptions::kNearbySharingSelfShareAutoAcceptName, - flag_descriptions::kNearbySharingSelfShareAutoAcceptDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kNearbySharingSelfShareAutoAccept)}, - {"nearby-sharing-self-share-ui", - flag_descriptions::kNearbySharingSelfShareUIName, - flag_descriptions::kNearbySharingSelfShareUIDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kNearbySharingSelfShareUI)}, + {"nearby-sharing-self-share", + flag_descriptions::kNearbySharingSelfShareName, + flag_descriptions::kNearbySharingSelfShareDescription, kOsCrOS, + FEATURE_VALUE_TYPE(features::kNearbySharingSelfShare)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -8804,6 +8810,10 @@ kCscVariations, "CSC")}, + {"csc-pinned-state", flag_descriptions::kCscPinnedName, + flag_descriptions::kCscPinnedDescription, kOsDesktop, + MULTI_VALUE_TYPE(kSidePanelPinnedStateChoices)}, + {"csc-vss", flag_descriptions::kCscVssName, flag_descriptions::kCscVssDescription, kOsDesktop, FEATURE_VALUE_TYPE(visual_search::features::kVisualSearchSuggestions)},
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h index 6b8be9d2..a91b5d0 100644 --- a/chrome/browser/app_controller_mac.h +++ b/chrome/browser/app_controller_mac.h
@@ -61,7 +61,7 @@ // build the user-data specific main menu items. raw_ptr<Profile, DanglingUntriaged> _lastProfile; - // The ProfileObserver observes the ProfileAttrbutesStorage and gets notified + // The ProfileObserver observes the ProfileAttributesStorage and gets notified // when a profile has been deleted. std::unique_ptr<AppControllerProfileObserver> _profileAttributesStorageObserver; @@ -100,7 +100,7 @@ BOOL _startupComplete; // Outlets for the close tab/window menu items so that we can adjust the - // commmand-key equivalent depending on the kind of window and how many + // command-key equivalent depending on the kind of window and how many // tabs it has. NSMenuItem* _closeTabMenuItem; NSMenuItem* _closeWindowMenuItem; @@ -136,6 +136,10 @@ // The color provider associated with the last active browser view. raw_ptr<const ui::ColorProvider, DanglingUntriaged> _lastActiveColorProvider; } +// The app-wide singleton AppController. Guaranteed to be the delegate of NSApp +// inside of Chromium (not inside of app shims; see AppShimDelegate). Guaranteed +// to not be nil. +@property(readonly, nonatomic, class) AppController* sharedController; @property(readonly, nonatomic) BOOL startupComplete; @property(readonly, nonatomic) Profile* lastProfileIfLoaded; @@ -145,6 +149,11 @@ // |-lastProfileIfLoaded|. @property(readonly, nonatomic) Profile* lastProfile; +// Do not create new instances of AppController; use the `sharedController` +// property so that the invariants of there always being exactly one +// AppController and that that instance is the NSApp delegate always hold true. +- (instancetype)init NS_UNAVAILABLE; + // This method is called very early in application startup after the main menu // has been created. - (void)mainMenuCreated;
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index fa0edb3..340ee8dd 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -11,6 +11,7 @@ #include <vector> #include "base/auto_reset.h" +#include "base/check_op.h" #include "base/command_line.h" #include "base/debug/dump_without_crashing.h" #include "base/files/file_path.h" @@ -560,6 +561,18 @@ @synthesize startupComplete = _startupComplete; ++ (AppController*)sharedController { + static AppController* sharedController = []() -> AppController* { + AppController* sharedController = [[AppController alloc] init]; + NSApp.delegate = sharedController; + return sharedController; + }(); + + CHECK_NE(nil, sharedController); + CHECK_EQ(NSApp.delegate, sharedController); + return sharedController; +} + - (instancetype)init { if (self = [super init]) { // -[NSMenu cr_menuItemForKeyEquivalentEvent:] lives in /content, but @@ -568,18 +581,15 @@ [NSMenu cr_setMenuItemForKeyEquivalentEventPreSearchBlock:^{ // We avoid calling -[NSMenuDelegate menuNeedsUpdate:] on each submenu's // delegate as that can be slow. Instead, we update the relevant - // NSMenuItems if [NSApp delegate] is an instance of AppController. See - // https://crbug.com/851260#c4 . - [base::mac::ObjCCast<AppController>([NSApp delegate]) - updateMenuItemKeyEquivalents]; + // NSMenuItems. + [AppController.sharedController updateMenuItemKeyEquivalents]; }]; } return self; } - (void)dealloc { - [[_closeTabMenuItem menu] setDelegate:nil]; - [NSMenu cr_setMenuItemForKeyEquivalentEventPreSearchBlock:nil]; + NOTREACHED(); [super dealloc]; } @@ -919,7 +929,7 @@ _quitWithAppsController = new QuitWithAppsController(); // Dynamically update shortcuts for "Close Window" and "Close Tab" menu items. - [[_closeTabMenuItem menu] setDelegate:self]; + _closeTabMenuItem.menu.delegate = self; // Instantiate the ProfileAttributesStorage observer so that we can get // notified when a profile is deleted. @@ -2017,11 +2027,10 @@ namespace { void UpdateProfileInUse(Profile* profile) { - if (!profile) + if (!profile) { return; - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - [controller setLastProfile:profile]; + } + [AppController.sharedController setLastProfile:profile]; } void OpenUrlsInBrowserWithProfile(const std::vector<GURL>& urls, @@ -2066,14 +2075,9 @@ // Returns the profile to be used for new windows (or nullptr if it fails). Profile* GetSafeProfile(Profile* loaded_profile) { - if (!loaded_profile) - return nullptr; - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - if (!controller) - return nullptr; DCHECK(loaded_profile); - return [controller safeProfileForNewWindows:loaded_profile]; + return + [AppController.sharedController safeProfileForNewWindows:loaded_profile]; } // Called when the profile has been loaded for RunIn*ProfileSafely(). This @@ -2111,26 +2115,16 @@ } void EnterpriseStartupDialogClosed() { - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - if (controller != nil) { - NSNotification* notify = [NSNotification - notificationWithName:NSApplicationDidFinishLaunchingNotification - object:NSApp]; - [controller applicationDidFinishLaunching:notify]; - } + NSNotification* notify = [NSNotification + notificationWithName:NSApplicationDidFinishLaunchingNotification + object:NSApp]; + [AppController.sharedController applicationDidFinishLaunching:notify]; } void RunInLastProfileSafely(base::OnceCallback<void(Profile*)> callback, ProfileLoadFailureBehavior on_failure) { DCHECK(callback); - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - if (!controller) { - OnProfileLoaded(std::move(callback), on_failure, nullptr); - return; - } - if (Profile* profile = [controller lastProfileIfLoaded]) { + if (Profile* profile = [AppController.sharedController lastProfileIfLoaded]) { OnProfileLoaded(std::move(callback), on_failure, profile); return; }
diff --git a/chrome/browser/app_controller_mac_browsertest.mm b/chrome/browser/app_controller_mac_browsertest.mm index 8a315ea..1c7cd8e 100644 --- a/chrome/browser/app_controller_mac_browsertest.mm +++ b/chrome/browser/app_controller_mac_browsertest.mm
@@ -121,15 +121,13 @@ } void SetGuestProfileAsLastProfile() { - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; // Create the guest profile, and set it as the last used profile. Profile& guest_profile = CreateAndWaitForGuestProfile(); - [ac setLastProfile:&guest_profile]; + [app_controller setLastProfile:&guest_profile]; - Profile* profile = [ac lastProfileIfLoaded]; + Profile* profile = [app_controller lastProfileIfLoaded]; ASSERT_TRUE(profile); EXPECT_EQ(guest_profile.GetPath(), profile->GetPath()); EXPECT_TRUE(profile->IsGuestSession()); @@ -141,14 +139,14 @@ } // Key for ProfileDestroyedData user data. -const char kProfileDestrictionWaiterUserDataKey = 0; +const char kProfileDestructionWaiterUserDataKey = 0; // Waits until the Profile instance is destroyed. class ProfileDestructionWaiter { public: explicit ProfileDestructionWaiter(Profile* profile) { profile->SetUserData( - &kProfileDestrictionWaiterUserDataKey, + &kProfileDestructionWaiterUserDataKey, std::make_unique<ProfileDestroyedData>(run_loop_.QuitClosure())); } @@ -249,16 +247,14 @@ EXPECT_EQ(1u, chrome::GetTotalBrowserCount()); Profile* profile = browser()->profile(); // Activate the first profile. - [[NSNotificationCenter defaultCenter] + [NSNotificationCenter.defaultCenter postNotificationName:NSWindowDidBecomeMainNotification object:browser() ->window() ->GetNativeWindow() .GetNativeNSWindow()]; - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - ASSERT_EQ(profile, [ac lastProfileIfLoaded]); + AppController* app_controller = AppController.sharedController; + ASSERT_EQ(profile, app_controller.lastProfileIfLoaded); // Mark the profile as ephemeral. profile->GetPrefs()->SetBoolean(prefs::kForceEphemeralProfiles, true); @@ -288,7 +284,7 @@ object:browser2->window() ->GetNativeWindow() .GetNativeNSWindow()]; - ASSERT_EQ(&profile2, [ac lastProfileIfLoaded]); + ASSERT_EQ(&profile2, app_controller.lastProfileIfLoaded); } class AppControllerKeepAliveBrowserTest : public InProcessBrowserTest { @@ -319,27 +315,20 @@ // open then a reopen event does nothing. IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest, DISABLED_PlatformAppReopenWithWindows) { - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - - NSUInteger old_window_count = [[NSApp windows] count]; + NSUInteger old_window_count = NSApp.windows.count; EXPECT_EQ(1u, active_browser_list_->size()); - [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:YES]; + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:YES]; // We do not EXPECT_TRUE the result here because the method // deminiaturizes windows manually rather than return YES and have // AppKit do it. - EXPECT_EQ(old_window_count, [[NSApp windows] count]); + EXPECT_EQ(old_window_count, NSApp.windows.count); EXPECT_EQ(1u, active_browser_list_->size()); } IN_PROC_BROWSER_TEST_F(AppControllerPlatformAppBrowserTest, DISABLED_ActivationFocusesBrowserWindow) { - AppController* app_controller = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(app_controller); - ExtensionTestMessageListener listener("Launched"); const extensions::Extension* app = InstallAndLaunchPlatformApp("minimal"); @@ -354,13 +343,13 @@ browser()->window()->GetNativeWindow().GetNativeNSWindow(); chrome::testing::NSRunLoopRunAllPending(); - EXPECT_LE([[NSApp orderedWindows] indexOfObject:app_window], - [[NSApp orderedWindows] indexOfObject:browser_window]); - [app_controller applicationShouldHandleReopen:NSApp - hasVisibleWindows:YES]; + EXPECT_LE([NSApp.orderedWindows indexOfObject:app_window], + [NSApp.orderedWindows indexOfObject:browser_window]); + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:YES]; chrome::testing::NSRunLoopRunAllPending(); - EXPECT_LE([[NSApp orderedWindows] indexOfObject:browser_window], - [[NSApp orderedWindows] indexOfObject:app_window]); + EXPECT_LE([NSApp.orderedWindows indexOfObject:browser_window], + [NSApp.orderedWindows indexOfObject:app_window]); } class AppControllerWebAppBrowserTest : public InProcessBrowserTest { @@ -382,12 +371,10 @@ // Test that in web app mode a reopen event opens the app URL. IN_PROC_BROWSER_TEST_F(AppControllerWebAppBrowserTest, WebAppReopenWithNoWindows) { - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - EXPECT_EQ(1u, active_browser_list_->size()); - BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO]; + BOOL result = + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:NO]; EXPECT_FALSE(result); EXPECT_EQ(2u, active_browser_list_->size()); @@ -431,16 +418,14 @@ PrefService* local_state = g_browser_process->local_state(); local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, false); - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - NSMenu* menu = [ac applicationDockMenu:NSApp]; + AppController* app_controller = AppController.sharedController; + NSMenu* menu = [app_controller applicationDockMenu:NSApp]; ASSERT_TRUE(menu); NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW]; ASSERT_TRUE(item); EXPECT_EQ(1u, active_browser_list()->size()); - [ac commandDispatch:item]; + [app_controller commandDispatch:item]; base::RunLoop().RunUntilIdle(); @@ -449,7 +434,7 @@ ProfilePicker::Hide(); local_state->SetBoolean(prefs::kBrowserGuestModeEnabled, true); - [ac commandDispatch:item]; + [app_controller commandDispatch:item]; base::RunLoop().RunUntilIdle(); EXPECT_EQ(2u, active_browser_list()->size()); EXPECT_FALSE(ProfilePicker::IsOpen()); @@ -467,21 +452,17 @@ [[[[NSApp mainMenu] itemWithTag:IDC_CHROME_MENU] submenu] itemWithTag:IDC_ABOUT], base::scoped_policy::RETAIN); - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - EXPECT_FALSE([ac validateUserInterfaceItem:about_menu_item]); + EXPECT_FALSE([AppController.sharedController + validateUserInterfaceItem:about_menu_item]); } // Test that for a regular last profile, a reopen event opens a browser. IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest, RegularProfileReopenWithNoWindows) { - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - EXPECT_EQ(1u, active_browser_list()->size()); - BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO]; + BOOL result = + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:NO]; EXPECT_FALSE(result); EXPECT_EQ(2u, active_browser_list()->size()); @@ -496,12 +477,10 @@ // minimize flakiness due to the scheduling/descheduling of tasks on the // different threads, pre-initialize the guest profile before it is needed. CreateAndWaitForSystemProfile(); - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; // Lock the active profile. - Profile* profile = [ac lastProfileIfLoaded]; + Profile* profile = [app_controller lastProfileIfLoaded]; ProfileAttributesEntry* entry = g_browser_process->profile_manager() ->GetProfileAttributesStorage() @@ -511,7 +490,8 @@ EXPECT_TRUE(entry->IsSigninRequired()); EXPECT_EQ(1u, active_browser_list()->size()); - BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO]; + BOOL result = [app_controller applicationShouldHandleReopen:NSApp + hasVisibleWindows:NO]; EXPECT_FALSE(result); base::RunLoop().RunUntilIdle(); @@ -529,11 +509,9 @@ // minimize flakiness due to the scheduling/descheduling of tasks on the // different threads, pre-initialize the guest profile before it is needed. CreateAndWaitForSystemProfile(); - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; // Lock the active profile. - Profile* profile = [ac lastProfileIfLoaded]; + Profile* profile = [app_controller lastProfileIfLoaded]; ProfileAttributesEntry* entry = g_browser_process->profile_manager() ->GetProfileAttributesStorage() @@ -546,11 +524,11 @@ EXPECT_FALSE(browser->profile()->IsGuestSession()); // "About Chrome" is not available in the menu. base::scoped_nsobject<NSMenu> chrome_submenu( - [[[NSApp mainMenu] itemWithTag:IDC_CHROME_MENU] submenu], + [[NSApp.mainMenu itemWithTag:IDC_CHROME_MENU] submenu], base::scoped_policy::RETAIN); base::scoped_nsobject<NSMenuItem> about_menu_item( [chrome_submenu itemWithTag:IDC_ABOUT], base::scoped_policy::RETAIN); - EXPECT_FALSE([ac validateUserInterfaceItem:about_menu_item]); + EXPECT_FALSE([app_controller validateUserInterfaceItem:about_menu_item]); [chrome_submenu update]; EXPECT_FALSE([about_menu_item isEnabled]); } @@ -561,10 +539,9 @@ SetGuestProfileAsLastProfile(); EXPECT_EQ(1u, active_browser_list()->size()); - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO]; + BOOL result = + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:NO]; EXPECT_FALSE(result); base::RunLoop().RunUntilIdle(); @@ -578,9 +555,6 @@ IN_PROC_BROWSER_TEST_F(AppControllerProfilePickerBrowserTest, MultiProfilePickerShown) { CreateAndWaitForSystemProfile(); - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); // Add a profile in the cache (simulate another profile on disk). ProfileManager* profile_manager = g_browser_process->profile_manager(); @@ -594,7 +568,9 @@ profile_storage->AddProfile(std::move(params)); EXPECT_EQ(1u, active_browser_list()->size()); - BOOL result = [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO]; + BOOL result = + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:NO]; EXPECT_FALSE(result); base::RunLoop().RunUntilIdle(); @@ -609,17 +585,15 @@ ProfilePicker::Show(ProfilePicker::Params::FromEntryPoint( ProfilePicker::EntryPoint::kProfileMenuManageProfiles)); - AppController* ac = base::mac::ObjCCastStrict<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; // Unhandled menu items are disabled. base::scoped_nsobject<NSMenu> file_submenu( - [[[NSApp mainMenu] itemWithTag:IDC_FILE_MENU] submenu], + [[NSApp.mainMenu itemWithTag:IDC_FILE_MENU] submenu], base::scoped_policy::RETAIN); base::scoped_nsobject<NSMenuItem> close_tab_menu_item( [file_submenu itemWithTag:IDC_CLOSE_TAB], base::scoped_policy::RETAIN); - EXPECT_FALSE([ac validateUserInterfaceItem:close_tab_menu_item]); + EXPECT_FALSE([app_controller validateUserInterfaceItem:close_tab_menu_item]); [file_submenu update]; EXPECT_FALSE([close_tab_menu_item isEnabled]); @@ -627,7 +601,7 @@ base::scoped_nsobject<NSMenuItem> new_window_menu_item( [file_submenu itemWithTag:IDC_NEW_WINDOW], base::scoped_policy::RETAIN); EXPECT_TRUE([new_window_menu_item isEnabled]); - EXPECT_TRUE([ac validateUserInterfaceItem:new_window_menu_item]); + EXPECT_TRUE([app_controller validateUserInterfaceItem:new_window_menu_item]); // Click on the item and checks that a new browser is opened. ui_test_utils::BrowserChangeObserver browser_added_observer( nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded); @@ -652,15 +626,13 @@ OpenNewWindowWhileFreIsRunning) { EXPECT_TRUE(ProfilePicker::IsFirstRunOpen()); EXPECT_EQ(BrowserList::GetInstance()->size(), 0u); - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - NSMenu* menu = [ac applicationDockMenu:NSApp]; + AppController* app_controller = AppController.sharedController; + NSMenu* menu = [app_controller applicationDockMenu:NSApp]; ASSERT_TRUE(menu); NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW]; ASSERT_TRUE(item); - [ac commandDispatch:item]; + [app_controller commandDispatch:item]; profiles::testing::WaitForPickerClosed(); EXPECT_FALSE(ProfilePicker::IsFirstRunOpen()); @@ -671,10 +643,8 @@ ClickingChromeDockIconDoesNotOpenBrowser) { EXPECT_TRUE(ProfilePicker::IsFirstRunOpen()); EXPECT_EQ(BrowserList::GetInstance()->size(), 0u); - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - [ac applicationShouldHandleReopen:NSApp hasVisibleWindows:NO]; + [AppController.sharedController applicationShouldHandleReopen:NSApp + hasVisibleWindows:NO]; EXPECT_EQ(BrowserList::GetInstance()->size(), 0u); ProfilePicker::Hide(); @@ -857,9 +827,7 @@ IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest, HistoryMenuResetAfterProfileDeletion) { ProfileManager* profile_manager = g_browser_process->profile_manager(); - AppController* ac = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; // Use the existing profile as profile 1. Profile* profile1 = browser()->profile(); @@ -876,14 +844,14 @@ ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile( profile1, ServiceAccessType::EXPLICIT_ACCESS)); // Switch the controller to profile1. - [ac setLastProfile:profile1]; + [app_controller setLastProfile:profile1]; base::RunLoop().RunUntilIdle(); // Verify the controller's History Menu corresponds to profile1. - EXPECT_TRUE([ac historyMenuBridge]->service()); - EXPECT_EQ([ac historyMenuBridge]->service(), - HistoryServiceFactory::GetForProfile(profile1, - ServiceAccessType::EXPLICIT_ACCESS)); + EXPECT_TRUE([app_controller historyMenuBridge]->service()); + EXPECT_EQ([app_controller historyMenuBridge]->service(), + HistoryServiceFactory::GetForProfile( + profile1, ServiceAccessType::EXPLICIT_ACCESS)); // Load profile2's History Service backend so it will be assigned to the // HistoryMenuBridge when setLastProfile is called, or else this test will @@ -891,12 +859,12 @@ ui_test_utils::WaitForHistoryToLoad(HistoryServiceFactory::GetForProfile( &profile2, ServiceAccessType::EXPLICIT_ACCESS)); // Switch the controller to profile2. - [ac setLastProfile:&profile2]; + [app_controller setLastProfile:&profile2]; base::RunLoop().RunUntilIdle(); // Verify the controller's History Menu has changed. - EXPECT_TRUE([ac historyMenuBridge]->service()); - EXPECT_EQ([ac historyMenuBridge]->service(), + EXPECT_TRUE([app_controller historyMenuBridge]->service()); + EXPECT_EQ([app_controller historyMenuBridge]->service(), HistoryServiceFactory::GetForProfile( &profile2, ServiceAccessType::EXPLICIT_ACCESS)); EXPECT_NE(HistoryServiceFactory::GetForProfile( @@ -911,54 +879,50 @@ content::RunAllTasksUntilIdle(); // Verify the controller's history is back to profile1. - EXPECT_EQ([ac historyMenuBridge]->service(), - HistoryServiceFactory::GetForProfile(profile1, - ServiceAccessType::EXPLICIT_ACCESS)); + EXPECT_EQ([app_controller historyMenuBridge]->service(), + HistoryServiceFactory::GetForProfile( + profile1, ServiceAccessType::EXPLICIT_ACCESS)); } // Disabled because of flakiness. See crbug.com/1278031. IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest, DISABLED_ReloadingDestroyedProfileDoesNotCrash) { ProfileManager* profile_manager = g_browser_process->profile_manager(); - AppController* ac = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; Profile* profile = browser()->profile(); base::FilePath profile_path = profile->GetPath(); // Switch the controller to |profile|. - [ac setLastProfile:profile]; + [app_controller setLastProfile:profile]; base::RunLoop().RunUntilIdle(); - EXPECT_EQ(profile, [ac lastProfileIfLoaded]); + EXPECT_EQ(profile, [app_controller lastProfileIfLoaded]); // Trigger Profile* destruction. Note that this event (destruction from // memory) is a separate event from profile deletion (from disk). chrome::CloseAllBrowsers(); ProfileDestructionWaiter(profile).Wait(); - EXPECT_EQ(nullptr, [ac lastProfileIfLoaded]); + EXPECT_EQ(nullptr, [app_controller lastProfileIfLoaded]); // Re-open the profile. Since the Profile* is destroyed, this involves loading // it from disk. base::ScopedAllowBlockingForTesting allow_blocking; profile = profile_manager->GetProfile(profile_path); - [ac setLastProfile:profile]; + [app_controller setLastProfile:profile]; base::RunLoop().RunUntilIdle(); // We mostly want to make sure re-loading the same profile didn't cause a // crash. This means we didn't have e.g. a dangling ProfilePrefRegistrar, or // observers pointing to the old (now dead) Profile. - EXPECT_EQ(profile, [ac lastProfileIfLoaded]); + EXPECT_EQ(profile, [app_controller lastProfileIfLoaded]); } IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest, BookmarksMenuIsRestoredAfterProfileSwitch) { ProfileManager* profile_manager = g_browser_process->profile_manager(); - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; - [ac mainMenuCreated]; + [app_controller mainMenuCreated]; // Constants for bookmarks that we will create later. const std::u16string title1(u"Dinosaur Comics"); @@ -983,39 +947,44 @@ BookmarkModelFactory::GetForBrowserContext(profile2_ptr)); // Switch to profile 1, create bookmark 1 and force the menu to build. - [ac setLastProfile:profile1]; - [ac bookmarkMenuBridge]->GetBookmarkModel()->AddURL( - [ac bookmarkMenuBridge]->GetBookmarkModel()->bookmark_bar_node(), - 0, title1, url1); - NSMenu* profile1_submenu = [ac bookmarkMenuBridge]->BookmarkMenu(); + [app_controller setLastProfile:profile1]; + [app_controller bookmarkMenuBridge]->GetBookmarkModel() + -> AddURL([app_controller bookmarkMenuBridge]->GetBookmarkModel() + -> bookmark_bar_node(), + 0, title1, url1); + NSMenu* profile1_submenu = + [app_controller bookmarkMenuBridge]->BookmarkMenu(); [[profile1_submenu delegate] menuNeedsUpdate:profile1_submenu]; // Switch to profile 2, create bookmark 2 and force the menu to build. - [ac setLastProfile:profile2_ptr]; - [ac bookmarkMenuBridge]->GetBookmarkModel()->AddURL( - [ac bookmarkMenuBridge]->GetBookmarkModel()->bookmark_bar_node(), - 0, title2, url2); - NSMenu* profile2_submenu = [ac bookmarkMenuBridge]->BookmarkMenu(); + [app_controller setLastProfile:profile2_ptr]; + [app_controller bookmarkMenuBridge]->GetBookmarkModel() + -> AddURL([app_controller bookmarkMenuBridge]->GetBookmarkModel() + -> bookmark_bar_node(), + 0, title2, url2); + NSMenu* profile2_submenu = + [app_controller bookmarkMenuBridge]->BookmarkMenu(); [[profile2_submenu delegate] menuNeedsUpdate:profile2_submenu]; EXPECT_NE(profile1_submenu, profile2_submenu); // Test that only bookmark 2 is shown. - EXPECT_FALSE([[ac bookmarkMenuBridge]->BookmarkMenu() + EXPECT_FALSE([[app_controller bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:base::SysUTF16ToNSString(title1)]); - EXPECT_TRUE([[ac bookmarkMenuBridge]->BookmarkMenu() + EXPECT_TRUE([[app_controller bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:base::SysUTF16ToNSString(title2)]); // Switch *back* to profile 1 and *don't* force the menu to build. - [ac setLastProfile:profile1]; + [app_controller setLastProfile:profile1]; // Test that only bookmark 1 is shown in the restored menu. - EXPECT_TRUE([[ac bookmarkMenuBridge]->BookmarkMenu() + EXPECT_TRUE([[app_controller bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:base::SysUTF16ToNSString(title1)]); - EXPECT_FALSE([[ac bookmarkMenuBridge]->BookmarkMenu() + EXPECT_FALSE([[app_controller bookmarkMenuBridge]->BookmarkMenu() itemWithTitle:base::SysUTF16ToNSString(title2)]); // Ensure a cached menu was used. - EXPECT_EQ(profile1_submenu, [ac bookmarkMenuBridge]->BookmarkMenu()); + EXPECT_EQ(profile1_submenu, + [app_controller bookmarkMenuBridge]->BookmarkMenu()); } // Tests opening a new window from a browser command while incognito is forced. @@ -1034,14 +1003,12 @@ // Simulate click on "New window". ui_test_utils::BrowserChangeObserver browser_added_observer( nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded); - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - NSMenu* menu = [ac applicationDockMenu:NSApp]; + AppController* app_controller = AppController.sharedController; + NSMenu* menu = [app_controller applicationDockMenu:NSApp]; ASSERT_TRUE(menu); NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW]; ASSERT_TRUE(item); - [ac commandDispatch:item]; + [app_controller commandDispatch:item]; // Check that a new incognito browser is opened. Browser* new_browser = browser_added_observer.Wait(); EXPECT_EQ(BrowserList::GetInstance()->size(), 1u); @@ -1070,14 +1037,12 @@ // Simulate click on "New Window". ui_test_utils::BrowserChangeObserver browser_added_observer( nullptr, ui_test_utils::BrowserChangeObserver::ChangeType::kAdded); - AppController* ac = base::mac::ObjCCast<AppController>( - [[NSApplication sharedApplication] delegate]); - ASSERT_TRUE(ac); - NSMenu* menu = [ac applicationDockMenu:NSApp]; + AppController* app_controller = AppController.sharedController; + NSMenu* menu = [app_controller applicationDockMenu:NSApp]; ASSERT_TRUE(menu); NSMenuItem* item = [menu itemWithTag:IDC_NEW_WINDOW]; ASSERT_TRUE(item); - [ac commandDispatch:item]; + [app_controller commandDispatch:item]; // Check that a new non-incognito browser is opened. Browser* new_browser = browser_added_observer.Wait(); @@ -1090,9 +1055,7 @@ IN_PROC_BROWSER_TEST_F(AppControllerMainMenuBrowserTest, SwitchToIncognitoRemovesHistoryItems) { ASSERT_TRUE(embedded_test_server()->Start()); - AppController* ac = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; GURL simple(embedded_test_server()->GetURL("/simple.html")); SendOpenUrlToAppController(simple); @@ -1106,7 +1069,7 @@ profile, ServiceAccessType::EXPLICIT_ACCESS)); // Verify that history bridge service is available for regular profiles. - EXPECT_TRUE([ac historyMenuBridge]->service()); + EXPECT_TRUE([app_controller historyMenuBridge]->service()); // Open a URL in Incognito window. ui_test_utils::NavigateToURLWithDisposition( @@ -1117,15 +1080,15 @@ BrowserList* active_browser_list = BrowserList::GetInstance(); EXPECT_EQ(2u, active_browser_list->size()); - // Verify that history beidge service is not available in Incognito. - EXPECT_FALSE([ac historyMenuBridge]->service()); + // Verify that history bridge service is not available in Incognito. + EXPECT_FALSE([app_controller historyMenuBridge]->service()); // Switch back to the regular profile window. Browser* browser1 = active_browser_list->get(0); browser1->window()->Show(); // Verify that history bridge service is available again. - EXPECT_TRUE([ac historyMenuBridge]->service()); + EXPECT_TRUE([app_controller historyMenuBridge]->service()); } class AppControllerIncognitoSwitchTest : public InProcessBrowserTest { @@ -1144,9 +1107,7 @@ EXPECT_EQ(otr_profile, otr_profile->GetPrimaryOTRProfile(/*create_if_needed=*/false)); EXPECT_EQ(BrowserList::GetInstance()->size(), 1u); - AppController* ac = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - ASSERT_TRUE(ac); + AppController* app_controller = AppController.sharedController; [[NSNotificationCenter defaultCenter] postNotificationName:NSWindowDidBecomeMainNotification object:browser() @@ -1154,13 +1115,13 @@ ->GetNativeWindow() .GetNativeNSWindow()]; // The last profile is the incognito profile. - EXPECT_EQ([ac lastProfileIfLoaded], otr_profile); + EXPECT_EQ([app_controller lastProfileIfLoaded], otr_profile); // Destroy the incognito profile. ProfileDestructionWaiter waiter(otr_profile); CloseBrowserSynchronously(browser()); waiter.Wait(); // Check that |-lastProfileIfLoaded| is not pointing to released memory. - EXPECT_NE([ac lastProfileIfLoaded], otr_profile); + EXPECT_NE([app_controller lastProfileIfLoaded], otr_profile); } } // namespace
diff --git a/chrome/browser/app_controller_mac_unittest.mm b/chrome/browser/app_controller_mac_unittest.mm index 46d83d39..548529a 100644 --- a/chrome/browser/app_controller_mac_unittest.mm +++ b/chrome/browser/app_controller_mac_unittest.mm
@@ -85,7 +85,7 @@ class AppControllerKeyEquivalentTest : public PlatformTest { protected: - AppControllerKeyEquivalentTest() {} + AppControllerKeyEquivalentTest() = default; void SetUp() override { PlatformTest::SetUp(); @@ -99,15 +99,15 @@ [AppController class], [AppControllerKeyEquivalentTestHelper class], @selector(windowHasBrowserTabs:)); - appController_.reset([[AppController alloc] init]); + appController_ = AppController.sharedController; closeWindowMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" - action:0 + action:nullptr keyEquivalent:@""]); [appController_ setCloseWindowMenuItemForTesting:closeWindowMenuItem_]; closeTabMenuItem_.reset([[NSMenuItem alloc] initWithTitle:@"" - action:0 + action:nullptr keyEquivalent:@""]); [appController_ setCloseTabMenuItemForTesting:closeTabMenuItem_]; } @@ -151,16 +151,16 @@ std::unique_ptr<base::mac::ScopedObjCClassSwizzler> nsAppTargetForActionSwizzler_; std::unique_ptr<base::mac::ScopedObjCClassSwizzler> appControllerSwizzler_; - base::scoped_nsobject<AppController> appController_; + AppController* appController_; base::scoped_nsobject<NSMenuItem> closeWindowMenuItem_; base::scoped_nsobject<NSMenuItem> closeTabMenuItem_; }; TEST_F(AppControllerTest, DockMenuProfileNotLoaded) { - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); - NSMenu* menu = [ac applicationDockMenu:NSApp]; + AppController* app_controller = AppController.sharedController; + NSMenu* menu = [app_controller applicationDockMenu:NSApp]; // Incognito item is hidden when the profile is not loaded. - EXPECT_EQ(nil, [ac lastProfileIfLoaded]); + EXPECT_EQ(nil, [app_controller lastProfileIfLoaded]); EXPECT_EQ(-1, [menu indexOfItemWithTag:IDC_NEW_INCOGNITO_WINDOW]); } @@ -169,19 +169,19 @@ local_state->SetString(prefs::kProfileLastUsed, profile_->GetPath().BaseName().MaybeAsASCII()); - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); - NSMenu* menu = [ac applicationDockMenu:NSApp]; + AppController* app_controller = AppController.sharedController; + NSMenu* menu = [app_controller applicationDockMenu:NSApp]; NSMenuItem* item; EXPECT_TRUE(menu); EXPECT_NE(-1, [menu indexOfItemWithTag:IDC_NEW_WINDOW]); // Incognito item is shown when the profile is loaded. - EXPECT_EQ(profile_, [ac lastProfileIfLoaded]); + EXPECT_EQ(profile_, [app_controller lastProfileIfLoaded]); EXPECT_NE(-1, [menu indexOfItemWithTag:IDC_NEW_INCOGNITO_WINDOW]); for (item in [menu itemArray]) { - EXPECT_EQ(ac.get(), [item target]); + EXPECT_EQ(app_controller, [item target]); EXPECT_EQ(@selector(commandFromDock:), [item action]); } } @@ -198,7 +198,7 @@ local_state->SetString(prefs::kProfileLastUsed, dest_path1.BaseName().MaybeAsASCII()); - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); + AppController* app_controller = AppController.sharedController; // Delete the active profile. profile_manager_.profile_manager() @@ -209,7 +209,7 @@ base::RunLoop().RunUntilIdle(); - EXPECT_EQ(dest_path2, [ac lastProfileIfLoaded]->GetPath()); + EXPECT_EQ(dest_path2, app_controller.lastProfileIfLoaded->GetPath()); } // Tests key equivalents for Close Window when target is a child window (like a @@ -302,8 +302,6 @@ protected: AppControllerSafeProfileTest() = default; ~AppControllerSafeProfileTest() override = default; - - void TearDown() override { [NSApp setDelegate:nil]; } }; // Tests that RunInLastProfileSafely() works with an already-loaded @@ -313,9 +311,8 @@ local_state->SetString(prefs::kProfileLastUsed, profile_->GetPath().BaseName().MaybeAsASCII()); - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); - [NSApp setDelegate:ac]; - ASSERT_EQ(profile_, [ac lastProfileIfLoaded]); + AppController* app_controller = AppController.sharedController; + ASSERT_EQ(profile_, app_controller.lastProfileIfLoaded); base::RunLoop run_loop; app_controller_mac::RunInLastProfileSafely( @@ -333,9 +330,8 @@ PrefService* local_state = g_browser_process->local_state(); local_state->SetString(prefs::kProfileLastUsed, "New Profile 2"); - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); - [NSApp setDelegate:ac]; - ASSERT_EQ(nil, [ac lastProfileIfLoaded]); + AppController* app_controller = AppController.sharedController; + ASSERT_EQ(nil, app_controller.lastProfileIfLoaded); base::RunLoop run_loop; app_controller_mac::RunInLastProfileSafely( @@ -356,9 +352,8 @@ local_state->SetString(prefs::kProfileLastUsed, profile_->GetPath().BaseName().MaybeAsASCII()); - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); - [NSApp setDelegate:ac]; - ASSERT_EQ(profile_, [ac lastProfileIfLoaded]); + AppController* app_controller = AppController.sharedController; + ASSERT_EQ(profile_, app_controller.lastProfileIfLoaded); TestingProfile* profile2 = profile_manager_.CreateTestingProfile("New Profile 2"); @@ -383,9 +378,8 @@ local_state->SetString(prefs::kProfileLastUsed, profile_->GetPath().BaseName().MaybeAsASCII()); - base::scoped_nsobject<AppController> ac([[AppController alloc] init]); - [NSApp setDelegate:ac]; - ASSERT_EQ(profile_, [ac lastProfileIfLoaded]); + AppController* app_controller = AppController.sharedController; + ASSERT_EQ(profile_, app_controller.lastProfileIfLoaded); base::RunLoop run_loop; app_controller_mac::RunInProfileSafely(
diff --git a/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm b/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm index 167328d..1c129ff 100644 --- a/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm +++ b/chrome/browser/apps/intent_helper/mac_intent_picker_helpers.mm
@@ -16,10 +16,6 @@ #include "net/base/mac/url_conversions.h" #include "ui/base/models/image_model.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace apps { namespace { @@ -79,7 +75,8 @@ if (!nsurl) return absl::nullopt; - SFUniversalLink* link = [[SFUniversalLink alloc] initWithWebpageURL:nsurl]; + SFUniversalLink* link = + [[[SFUniversalLink alloc] initWithWebpageURL:nsurl] autorelease]; if (link) return AppInfoForAppUrl(link.applicationURL);
diff --git a/chrome/browser/ash/app_list/app_list_client_impl_browsertest.cc b/chrome/browser/ash/app_list/app_list_client_impl_browsertest.cc index 14343f10..999768e 100644 --- a/chrome/browser/ash/app_list/app_list_client_impl_browsertest.cc +++ b/chrome/browser/ash/app_list/app_list_client_impl_browsertest.cc
@@ -82,7 +82,6 @@ #include "ui/display/scoped_display_for_new_windows.h" #include "ui/display/screen.h" #include "ui/display/test/display_manager_test_api.h" -#include "ui/views/native_window_tracker.h" #include "ui/wm/core/window_util.h" #include "ui/wm/public/activation_change_observer.h" #include "ui/wm/public/activation_client.h" @@ -214,54 +213,6 @@ EXPECT_TRUE(client->GetAppListWindow()); } -// TODO(crbug.com/1444649): Test is flaky. -IN_PROC_BROWSER_TEST_F(AppListClientImplBrowserTest, - DISABLED_HidingBubbleLauncherCancelsAppUninstall) { - AppListClientImpl* client = AppListClientImpl::GetInstance(); - const extensions::Extension* app = InstallPlatformApp("minimal"); - - // Show the app list and request app uninstall. - EXPECT_FALSE(client->GetAppListWindow()); - client->ShowAppList(ash::AppListShowSource::kSearchKey); - ash::AppListTestApi().WaitForBubbleWindow( - /*wait_for_opening_animation=*/false); - // Open the uninstall dialog. - client->UninstallApp(profile(), app->id()); - base::RunLoop().RunUntilIdle(); - - aura::Window* app_list_window = client->GetAppListWindow(); - std::unique_ptr<views::NativeWindowTracker> app_list_tracker = - views::NativeWindowTracker::Create(app_list_window); - auto transient_children = wm::GetTransientChildren(app_list_window); - ASSERT_FALSE(transient_children.empty()); - - aura::Window* dialog_window = transient_children[0]; - std::unique_ptr<views::NativeWindowTracker> dialog_tracker = - views::NativeWindowTracker::Create(dialog_window); - - // Hide the app list, and verify that the dialog window was closed. - ASSERT_TRUE(client->app_list_visible()); - client->DismissView(); - base::RunLoop().RunUntilIdle(); - - EXPECT_FALSE(client->app_list_visible()); - - ASSERT_FALSE(app_list_tracker->WasNativeWindowDestroyed()); - EXPECT_TRUE(wm::GetTransientChildren(app_list_window).empty()); - - EXPECT_TRUE(dialog_tracker->WasNativeWindowDestroyed()); - - // Reopen the app list, and verify that request to uninstall the app shows the - // uninstall dialog. - client->ShowAppList(ash::AppListShowSource::kSearchKey); - ash::AppListTestApi().WaitForBubbleWindow( - /*wait_for_opening_animation=*/false); - EXPECT_TRUE(client->GetAppListWindow()); - client->UninstallApp(profile(), app->id()); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(wm::GetTransientChildren(client->GetAppListWindow()).empty()); -} - IN_PROC_BROWSER_TEST_F(AppListClientImplBrowserTest, ShowAppInfo) { ash::SystemWebAppManager::GetForTest(profile()) ->InstallSystemAppsForTesting();
diff --git a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc index adb2956..99b0e235 100644 --- a/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc +++ b/chrome/browser/ash/app_mode/web_app/web_kiosk_app_service_launcher_unittest.cc
@@ -113,9 +113,11 @@ fake_web_app_provider_ = web_app::FakeWebAppProvider::Get(profile()); web_app::test::AwaitStartWebAppProviderAndSubsystems(profile()); + // TODO(http://b/283521737): Remove this usage and either fake out the + // scheduler, or use the whole FakeWebAppProvider system. externally_managed_app_manager().SetSubsystems( /*ui_manager=*/nullptr, /*finalizer=*/nullptr, - /*command_scheduler=*/nullptr); + /*command_scheduler=*/nullptr, /*web_contents_manager=*/nullptr); externally_managed_app_manager().SetHandleInstallRequestCallback( base::BindLambdaForTesting( [this](const web_app::ExternalInstallOptions& install_options)
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc index 8d9e174a..c765eec 100644 --- a/chrome/browser/ash/crosapi/crosapi_util.cc +++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -158,6 +158,7 @@ #include "services/device/public/mojom/hid.mojom.h" #include "services/media_session/public/mojom/audio_focus.mojom.h" #include "services/media_session/public/mojom/media_controller.mojom.h" +#include "ui/base/ui_base_features.h" #include "ui/gfx/switches.h" using MojoOptionalBool = crosapi::mojom::DeviceSettings::OptionalBool; @@ -613,6 +614,9 @@ params->enable_clipboard_history_refresh = chromeos::features::IsClipboardHistoryRefreshEnabled(); + + params->is_variable_refresh_rate_enabled = + ::features::IsVariableRefreshRateEnabled(); } template <typename BrowserParams>
diff --git a/chrome/browser/ash/input_method/input_method_engine.cc b/chrome/browser/ash/input_method/input_method_engine.cc index c56a0c6..9e09af9 100644 --- a/chrome/browser/ash/input_method/input_method_engine.cc +++ b/chrome/browser/ash/input_method/input_method_engine.cc
@@ -140,7 +140,7 @@ const bool new_value = profile_->GetPrefs()->GetBoolean(ash::prefs::kLongPressDiacriticsEnabled); if (!new_value) { - SystemNudgeController::RecordNudgeAction( + SystemNudgeController::MaybeRecordNudgeAction( NudgeCatalogName::kDisableDiacritics); } }
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc index 22f2773..1aeb189 100644 --- a/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc +++ b/chrome/browser/ash/login/app_mode/test/kiosk_update_browsertest.cc
@@ -473,7 +473,8 @@ std::string(kTestOfflineEnabledKioskApp) + "_v1.crx"); } -IN_PROC_BROWSER_TEST_F(KioskUpdateTest, LaunchOfflineEnabledAppNoNetwork) { +IN_PROC_BROWSER_TEST_F(KioskUpdateTest, + DISABLED_LaunchOfflineEnabledAppNoNetwork) { set_test_app_id(kTestOfflineEnabledKioskApp); SimulateNetworkOffline(); EXPECT_TRUE(LaunchApp(test_app_id()));
diff --git a/chrome/browser/ash/login/screens/update_screen_browsertest.cc b/chrome/browser/ash/login/screens/update_screen_browsertest.cc index b7e502a..78a79e2 100644 --- a/chrome/browser/ash/login/screens/update_screen_browsertest.cc +++ b/chrome/browser/ash/login/screens/update_screen_browsertest.cc
@@ -653,7 +653,8 @@ histogram_tester_.ExpectTotalCount(kTimeFinalize, 0); } -IN_PROC_BROWSER_TEST_P(UpdateScreenTest, TestTwoOfflineNetworks) { +// TODO(https://crbug.com/1449334): Flaky on Chrome OS. +IN_PROC_BROWSER_TEST_P(UpdateScreenTest, DISABLED_TestTwoOfflineNetworks) { // Change ethernet state to portal. network_portal_detector_.SimulateDefaultNetworkState( NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL);
diff --git a/chrome/browser/browser_process_platform_part_mac.mm b/chrome/browser/browser_process_platform_part_mac.mm index 1f4e227..1310bd6c 100644 --- a/chrome/browser/browser_process_platform_part_mac.mm +++ b/chrome/browser/browser_process_platform_part_mac.mm
@@ -15,11 +15,9 @@ #include "chrome/browser/chrome_browser_application_mac.h" #include "services/device/public/cpp/geolocation/system_geolocation_source_mac.h" -BrowserProcessPlatformPart::BrowserProcessPlatformPart() { -} +BrowserProcessPlatformPart::BrowserProcessPlatformPart() = default; -BrowserProcessPlatformPart::~BrowserProcessPlatformPart() { -} +BrowserProcessPlatformPart::~BrowserProcessPlatformPart() = default; void BrowserProcessPlatformPart::BeginStartTearDown() { if (app_shim_manager_) @@ -44,10 +42,9 @@ if (!try_to_quit_application) { // A keyboard menu invocation. - AppController* app_controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - if (![app_controller runConfirmQuitPanel]) + if (![AppController.sharedController runConfirmQuitPanel]) { return; + } } chrome_browser_application_mac::Terminate(); @@ -55,7 +52,7 @@ void BrowserProcessPlatformPart::PreMainMessageLoopRun() { // Create two AppShimManager::Delegates -- one for extensions-based apps - // (which will be deprecatedin 2020), and one for web apps (PWAs and + // (which will be deprecated in 2020), and one for web apps (PWAs and // bookmark apps). The WebAppShimManagerDelegate will defer to the // ExtensionAppShimManagerDelegate passed to it for extension-based apps. // When extension-based apps are deprecated, the
diff --git a/chrome/browser/chrome_browser_application_mac.mm b/chrome/browser/chrome_browser_application_mac.mm index 69231a86..a8af9b3 100644 --- a/chrome/browser/chrome_browser_application_mac.mm +++ b/chrome/browser/chrome_browser_application_mac.mm
@@ -226,14 +226,12 @@ // NSApplication event loop, so final post- MessageLoop::Run() work is done // before exiting. - (void)terminate:(id)sender { - AppController* appController = static_cast<AppController*>([NSApp delegate]); - [appController tryToTerminateApplication:self]; + [AppController.sharedController tryToTerminateApplication:self]; // Return, don't exit. The application is responsible for exiting on its own. } - (void)cancelTerminate:(id)sender { - AppController* appController = static_cast<AppController*>([NSApp delegate]); - [appController stopTryingToTerminateApplication:self]; + [AppController.sharedController stopTryingToTerminateApplication:self]; } - (NSEvent*)nextEventMatchingMask:(NSEventMask)mask @@ -354,7 +352,8 @@ } - (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute { - // This is an undocument attribute that's set when VoiceOver is turned on/off. + // This is an undocumented attribute that's set when VoiceOver is turned + // on/off. if ([attribute isEqualToString:@"AXEnhancedUserInterface"]) { content::BrowserAccessibilityState* accessibility_state = content::BrowserAccessibilityState::GetInstance();
diff --git a/chrome/browser/chrome_browser_main_mac.mm b/chrome/browser/chrome_browser_main_mac.mm index 789d147f..cf53f6b 100644 --- a/chrome/browser/chrome_browser_main_mac.mm +++ b/chrome/browser/chrome_browser_main_mac.mm
@@ -12,7 +12,6 @@ #include "base/functional/bind.h" #import "base/mac/foundation_util.h" #include "base/mac/mac_util.h" -#include "base/mac/scoped_nsobject.h" #include "base/metrics/histogram_functions.h" #include "base/path_service.h" #include "base/strings/sys_string_conversions.h" @@ -114,10 +113,8 @@ } #endif // !BUILDFLAG(CHROME_FOR_TESTING) - // Create the app delegate. This object is intentionally leaked as a global - // singleton. It is accessed through -[NSApp delegate]. - AppController* app_controller = [[AppController alloc] init]; - [NSApp setDelegate:app_controller]; + // Create the app delegate by requesting the shared AppController. + AppController* app_controller = AppController.sharedController; chrome::BuildMainMenu(NSApp, app_controller, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME), false); @@ -180,7 +177,5 @@ } void ChromeBrowserMainPartsMac::DidEndMainMessageLoop() { - AppController* appController = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - [appController didEndMainMessageLoop]; + [AppController.sharedController didEndMainMessageLoop]; }
diff --git a/chrome/browser/companion/core/BUILD.gn b/chrome/browser/companion/core/BUILD.gn index 0a14098..777fc49 100644 --- a/chrome/browser/companion/core/BUILD.gn +++ b/chrome/browser/companion/core/BUILD.gn
@@ -17,7 +17,7 @@ "promo_handler.h", "signin_delegate.h", ] - + public_deps = [ "//third_party/abseil-cpp:absl" ] deps = [ "mojom:mojo_bindings", "proto",
diff --git a/chrome/browser/companion/core/companion_metrics_logger.cc b/chrome/browser/companion/core/companion_metrics_logger.cc index d135848f..554e25a 100644 --- a/chrome/browser/companion/core/companion_metrics_logger.cc +++ b/chrome/browser/companion/core/companion_metrics_logger.cc
@@ -125,6 +125,10 @@ void CompanionMetricsLogger::RecordOpenTrigger( absl::optional<SidePanelOpenTrigger> open_trigger) { open_trigger_ = open_trigger; + if (open_trigger.has_value()) { + base::UmaHistogramEnumeration("Companion.SidePanel.OpenTrigger", + open_trigger.value()); + } } void CompanionMetricsLogger::RecordUiSurfaceShown(
diff --git a/chrome/browser/companion/core/features.cc b/chrome/browser/companion/core/features.cc index 5459415..5480c38 100644 --- a/chrome/browser/companion/core/features.cc +++ b/chrome/browser/companion/core/features.cc
@@ -39,10 +39,32 @@ const char kDisableCheckUserPermissionsForCompanion[] = "disable-checking-companion-user-permissions"; +const char kForceCompanionPinnedState[] = "force-companion-pinned-state"; + bool ShouldOverrideCheckingUserPermissionsForCompanion() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); return command_line->HasSwitch(kDisableCheckUserPermissionsForCompanion); } +absl::optional<bool> ShouldForceOverrideCompanionPinState() { + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (!command_line->HasSwitch(kForceCompanionPinnedState)) { + return absl::nullopt; + } + + std::string pinned_state = + command_line->GetSwitchValueASCII(kForceCompanionPinnedState); + if (pinned_state == "pinned") { + return true; + } + if (pinned_state == "unpinned") { + return false; + } + + NOTREACHED() << "Invalid Companion pin state command line switch value: " + << pinned_state; + return absl::nullopt; +} + } // namespace switches } // namespace companion
diff --git a/chrome/browser/companion/core/features.h b/chrome/browser/companion/core/features.h index 974e795..7d28b3b 100644 --- a/chrome/browser/companion/core/features.h +++ b/chrome/browser/companion/core/features.h
@@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" #include "build/build_config.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace companion { namespace features { @@ -23,11 +24,16 @@ namespace switches { extern const char kDisableCheckUserPermissionsForCompanion[]; +extern const char kForceCompanionPinnedState[]; // Returns true if checking of the user's permissions to share page information // with the Companion server should be ignored. Returns true only in tests. bool ShouldOverrideCheckingUserPermissionsForCompanion(); +// Returns whether the Companion pin state should force overridden, regardless +// of prefs or labs state. +absl::optional<bool> ShouldForceOverrideCompanionPinState(); + } // namespace switches } // namespace companion
diff --git a/chrome/browser/component_updater/pki_metadata_component_installer_browsertest.cc b/chrome/browser/component_updater/pki_metadata_component_installer_browsertest.cc index 9d21ecc..7817133 100644 --- a/chrome/browser/component_updater/pki_metadata_component_installer_browsertest.cc +++ b/chrome/browser/component_updater/pki_metadata_component_installer_browsertest.cc
@@ -392,6 +392,15 @@ ssl_test_util::AuthState::SHOWING_INTERSTITIAL); } +// TODO(https://crbug.com/1287211) additional Chrome Root Store browser tests to +// add: +// +// * Test that AIA fetching still works after updating CRS. +// * Test with the kChromeRootStoreUsed feature disabled: configuring a CRS +// update with the test root should not cause the page to load successfully. +// * Test that updates propagate into TrialComparisonCertVerifier too. Testing +// that loading the root in CRS would cause it to succeed with the trial +// verifier but not with primary. #endif } // namespace component_updater
diff --git a/chrome/browser/component_updater/registration.cc b/chrome/browser/component_updater/registration.cc index 9ba5383..3082190 100644 --- a/chrome/browser/component_updater/registration.cc +++ b/chrome/browser/component_updater/registration.cc
@@ -35,7 +35,6 @@ #include "chrome/common/buildflags.h" #include "chrome/common/chrome_paths.h" #include "components/component_updater/component_updater_service.h" -#include "components/component_updater/crl_set_remover.h" #include "components/component_updater/installer_policies/autofill_states_component_installer.h" #include "components/component_updater/installer_policies/masked_domain_list_component_installer.h" #include "components/component_updater/installer_policies/on_device_head_suggest_component_installer.h" @@ -143,10 +142,6 @@ base::FilePath path; if (base::PathService::Get(chrome::DIR_USER_DATA, &path)) { - // The CRLSet component previously resided in a different location: delete - // the old file. - component_updater::DeleteLegacyCRLSet(path); - component_updater::DeleteUrlParamFilter(path); // Clean up any remaining desktop sharing hub state.
diff --git a/chrome/browser/component_updater/updater_state_mac.mm b/chrome/browser/component_updater/updater_state_mac.mm index cbbde041..25debc2 100644 --- a/chrome/browser/component_updater/updater_state_mac.mm +++ b/chrome/browser/component_updater/updater_state_mac.mm
@@ -6,18 +6,14 @@ #import <Foundation/Foundation.h> -#include "base/apple/bridging.h" #include "base/enterprise_util.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/mac/foundation_util.h" +#include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "base/version.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace component_updater { namespace { @@ -26,18 +22,22 @@ FILE_PATH_LITERAL("Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/" "Contents/Info.plist"); -// Gets a value from the updater settings. +// Gets a value from the updater settings. Returns a retained object. +// T should be a toll-free Foundation framework type. See Apple's +// documentation for toll-free bridging. template <class T> -T* GetUpdaterSettingsValue(NSString* value_name) { - id plist_type = CFBridgingRelease( - CFPreferencesCopyAppValue(base::apple::NSToCFPtrCast(value_name), - CFSTR("com.google.Keystone.Agent"))); - - return base::mac::ObjCCastStrict<T>(plist_type); +base::scoped_nsobject<T> GetUpdaterSettingsValue(NSString* value_name) { + CFStringRef app_id = CFSTR("com.google.Keystone.Agent"); + base::ScopedCFTypeRef<CFPropertyListRef> plist( + CFPreferencesCopyAppValue(base::mac::NSToCFCast(value_name), app_id)); + return base::scoped_nsobject<T>( + base::mac::ObjCCastStrict<T>(static_cast<id>(plist.get())), + base::scoped_policy::RETAIN); } base::Time GetUpdaterSettingsTime(NSString* value_name) { - NSDate* date = GetUpdaterSettingsValue<NSDate>(value_name); + base::scoped_nsobject<NSDate> date = + GetUpdaterSettingsValue<NSDate>(value_name); base::Time result = base::Time::FromCFAbsoluteTime([date timeIntervalSinceReferenceDate]); @@ -61,8 +61,8 @@ return base::Version(); } CFStringRef version = base::mac::GetValueFromDictionary<CFStringRef>( - base::apple::NSToCFPtrCast(all_keys), kCFBundleVersionKey); - if (version == nullptr) { + base::mac::NSToCFCast(all_keys), kCFBundleVersionKey); + if (version == NULL) { return base::Version(); } return base::Version(base::SysCFStringRefToUTF8(version)); @@ -114,8 +114,9 @@ bool UpdaterState::IsAutoupdateCheckEnabled() { // Auto-update check period override (in seconds). // Applies only to older versions of Keystone. - NSNumber* timeInterval = GetUpdaterSettingsValue<NSNumber>(@"checkInterval"); - if (!timeInterval) { + base::scoped_nsobject<NSNumber> timeInterval = + GetUpdaterSettingsValue<NSNumber>(@"checkInterval"); + if (!timeInterval.get()) { return true; } int value = [timeInterval intValue];
diff --git a/chrome/browser/device_reauth/mac/authenticator_mac.mm b/chrome/browser/device_reauth/mac/authenticator_mac.mm index c42c74a8..e1815b8e 100644 --- a/chrome/browser/device_reauth/mac/authenticator_mac.mm +++ b/chrome/browser/device_reauth/mac/authenticator_mac.mm
@@ -7,18 +7,15 @@ #import <LocalAuthentication/LAContext.h> #include "base/functional/callback.h" +#include "base/mac/scoped_nsobject.h" #include "chrome/browser/password_manager/password_manager_util_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - AuthenticatorMac::AuthenticatorMac() = default; AuthenticatorMac::~AuthenticatorMac() = default; bool AuthenticatorMac::CheckIfBiometricsAvailable() { - LAContext* context = [[LAContext alloc] init]; + base::scoped_nsobject<LAContext> context([[LAContext alloc] init]); return [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]; @@ -27,4 +24,4 @@ bool AuthenticatorMac::AuthenticateUserWithNonBiometrics( const std::u16string& message) { return password_manager_util_mac::AuthenticateUser(message); -} +} \ No newline at end of file
diff --git a/chrome/browser/device_reauth/mac/device_authenticator_mac.mm b/chrome/browser/device_reauth/mac/device_authenticator_mac.mm index e9fc8920..f8ae9b4 100644 --- a/chrome/browser/device_reauth/mac/device_authenticator_mac.mm +++ b/chrome/browser/device_reauth/mac/device_authenticator_mac.mm
@@ -19,10 +19,6 @@ #include "device/fido/mac/touch_id_context.h" #include "ui/base/l10n/l10n_util.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - DeviceAuthenticatorMac::DeviceAuthenticatorMac( std::unique_ptr<AuthenticatorMacInterface> authenticator) : authenticator_(std::move(authenticator)) {}
diff --git a/chrome/browser/dips/dips_bounce_detector.cc b/chrome/browser/dips/dips_bounce_detector.cc index fbb7e72..91afd9b8 100644 --- a/chrome/browser/dips/dips_bounce_detector.cc +++ b/chrome/browser/dips/dips_bounce_detector.cc
@@ -507,8 +507,7 @@ DCHECK(access_details.render_frame_host); - // TODO(crbug.com/1434764): handle same-site iframes. - if (!access_details.render_frame_host->IsInPrimaryMainFrame() || + if (!IsInPrimaryPage(access_details.render_frame_host) || access_details.blocked_by_policy) { return; }
diff --git a/chrome/browser/dips/dips_bounce_detector_browsertest.cc b/chrome/browser/dips/dips_bounce_detector_browsertest.cc index f0b5e42..8e2540c 100644 --- a/chrome/browser/dips/dips_bounce_detector_browsertest.cc +++ b/chrome/browser/dips/dips_bounce_detector_browsertest.cc
@@ -297,6 +297,10 @@ host_resolver()->AddRule("e.test", "127.0.0.1"); host_resolver()->AddRule("f.test", "127.0.0.1"); host_resolver()->AddRule("g.test", "127.0.0.1"); + SetUpDIPSWebContentsObserver(); + } + + void SetUpDIPSWebContentsObserver() { web_contents_observer_ = DIPSWebContentsObserver::FromWebContents(GetActiveWebContents()); } @@ -445,67 +449,6 @@ nullptr; }; -class DIPSSiteDataAccessDetectorTest - : public DIPSBounceDetectorBrowserTest, - public testing::WithParamInterface<StorageType> { - public: - DIPSSiteDataAccessDetectorTest(const DIPSSiteDataAccessDetectorTest&) = - delete; - DIPSSiteDataAccessDetectorTest& operator=( - const DIPSSiteDataAccessDetectorTest&) = delete; - - DIPSSiteDataAccessDetectorTest() - : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} - - void SetUpOnMainThread() override { - host_resolver()->AddRule("*", "127.0.0.1"); - base::FilePath path; - base::PathService::Get(content::DIR_TEST_DATA, &path); - https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); - https_server_.ServeFilesFromDirectory(path); - https_server_.AddDefaultHandlers(kChromeTestDataDir); - ASSERT_TRUE(https_server_.Start()); - } - - auto* TestServer() { return &https_server_; } - - private: - net::test_server::EmbeddedTestServer https_server_; -}; - -IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest, - DetectSiteDataAccess_Storages) { - // Start logging `WebContentsObserver` callbacks. - WCOCallbackLogger::CreateForWebContents(GetActiveWebContents()); - auto* logger = WCOCallbackLogger::FromWebContents(GetActiveWebContents()); - - EXPECT_TRUE(content::NavigateToURLFromRenderer( - GetActiveWebContents()->GetPrimaryMainFrame(), - TestServer()->GetURL("a.test", "/title1.html"))); - - EXPECT_TRUE( - AccessStorage(GetActiveWebContents()->GetPrimaryMainFrame(), GetParam())); - - EXPECT_THAT( - logger->log(), - testing::ContainerEq(std::vector<std::string>({ - "DidStartNavigation(a.test/title1.html)", - "DidFinishNavigation(a.test/title1.html)", - "OnSiteDataAccessed(AccessDetails, Storage: Unknown: a.test/)", - }))); -} - -// WeLocks accesses aren't monitored by the `PageSpecificContentSettings` as -// there are not persistent. -INSTANTIATE_TEST_SUITE_P(All, - DIPSSiteDataAccessDetectorTest, - ::testing::Values(StorageType::DATABASE, - StorageType::LOCAL_STORAGE, - StorageType::SESSION_STORAGE, - StorageType::CACHE, - StorageType::FILE_SYSTEM, - StorageType::INDEXED_DB)); - IN_PROC_BROWSER_TEST_F(DIPSBounceDetectorBrowserTest, AttributeSameSiteIframesCookieClientAccessTo1P) { std::vector<std::string> redirects; @@ -1328,3 +1271,209 @@ // write cookies before bouncing the user. WaitForIssueAndCheckTrackingSites({"e.test", "f.test"}); } + +class DIPSSiteDataAccessDetectorTest + : public DIPSBounceDetectorBrowserTest, + public testing::WithParamInterface<StorageType> { + public: + DIPSSiteDataAccessDetectorTest(const DIPSSiteDataAccessDetectorTest&) = + delete; + DIPSSiteDataAccessDetectorTest& operator=( + const DIPSSiteDataAccessDetectorTest&) = delete; + + DIPSSiteDataAccessDetectorTest() + : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + base::FilePath path; + base::PathService::Get(content::DIR_TEST_DATA, &path); + https_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES); + https_server_.ServeFilesFromDirectory(path); + https_server_.AddDefaultHandlers(kChromeTestDataDir); + ASSERT_TRUE(https_server_.Start()); + SetUpDIPSWebContentsObserver(); + } + + auto* TestServer() { return &https_server_; } + + private: + net::test_server::EmbeddedTestServer https_server_; +}; + +IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest, + DetectSiteDataAccess_Storages) { + // Start logging `WebContentsObserver` callbacks. + WCOCallbackLogger::CreateForWebContents(GetActiveWebContents()); + auto* logger = WCOCallbackLogger::FromWebContents(GetActiveWebContents()); + + EXPECT_TRUE(content::NavigateToURLFromRenderer( + GetActiveWebContents()->GetPrimaryMainFrame(), + TestServer()->GetURL("a.test", "/title1.html"))); + + EXPECT_TRUE( + AccessStorage(GetActiveWebContents()->GetPrimaryMainFrame(), GetParam())); + + EXPECT_THAT( + logger->log(), + testing::ContainerEq(std::vector<std::string>({ + "DidStartNavigation(a.test/title1.html)", + "DidFinishNavigation(a.test/title1.html)", + "OnSiteDataAccessed(AccessDetails, Storage: Unknown: a.test/)", + }))); +} + +IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest, + AttributeSameSiteIframesSiteDataAccessTo1P) { + std::vector<std::string> redirects; + StartAppendingRedirectsTo(&redirects); + + const GURL primary_main_frame_url = + TestServer()->GetURL("a.test", "/iframe_blank.html"); + ASSERT_TRUE( + content::NavigateToURL(GetActiveWebContents(), primary_main_frame_url)); + + const GURL iframe_url = TestServer()->GetURL("a.test", "/title1.html"); + ASSERT_TRUE( + content::NavigateIframeToURL(GetActiveWebContents(), "test", iframe_url)); + + EXPECT_TRUE(AccessStorage(GetIFrame(), GetParam())); + + const GURL primary_main_frame_final_url = + TestServer()->GetURL("d.test", "/title1.html"); + // Performs a Client-redirect to `primary_main_frame_final_url`. + ASSERT_TRUE(content::NavigateToURLFromRendererWithoutUserGesture( + GetActiveWebContents(), primary_main_frame_final_url)); + + CloseTab(); + EXPECT_THAT(redirects, ElementsAre(("[1/1] blank -> a.test/iframe_blank.html " + "(Write) -> d.test/title1.html"))); +} + +IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest, + AttributeSameSiteNestedIframesSiteDataAccessTo1P) { + std::vector<std::string> redirects; + StartAppendingRedirectsTo(&redirects); + + const GURL primary_main_frame_url = + TestServer()->GetURL("a.test", "/iframe_blank.html"); + ASSERT_TRUE( + content::NavigateToURL(GetActiveWebContents(), primary_main_frame_url)); + + const GURL iframe_url = TestServer()->GetURL("a.test", "/iframe_blank.html"); + ASSERT_TRUE( + content::NavigateIframeToURL(GetActiveWebContents(), "test", iframe_url)); + + const GURL nested_iframe_url = TestServer()->GetURL("a.test", "/title1.html"); + NavigateNestedIFrameTo(GetIFrame(), "test", nested_iframe_url); + + EXPECT_TRUE(AccessStorage(GetNestedIFrame(), GetParam())); + + const GURL primary_main_frame_final_url = + TestServer()->GetURL("d.test", "/title1.html"); + // Performs a Client-redirect to `primary_main_frame_final_url`. + ASSERT_TRUE(content::NavigateToURLFromRendererWithoutUserGesture( + GetActiveWebContents(), primary_main_frame_final_url)); + + CloseTab(); + EXPECT_THAT(redirects, ElementsAre(("[1/1] blank -> a.test/iframe_blank.html " + "(Write) -> d.test/title1.html"))); +} + +IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest, + DiscardFencedFrameCookieClientAccess) { + // `StorageType::DATABASE` is disallowed in fenced frames. + if (GetParam() == StorageType::DATABASE) { + GTEST_SKIP(); + } + + std::vector<std::string> redirects; + StartAppendingRedirectsTo(&redirects); + + const GURL primary_main_frame_url = + TestServer()->GetURL("a.test", "/title1.html"); + ASSERT_TRUE( + content::NavigateToURL(GetActiveWebContents(), primary_main_frame_url)); + + const GURL fenced_frame_url = + TestServer()->GetURL("a.test", "/fenced_frames/title2.html"); + std::unique_ptr<content::RenderFrameHostWrapper> fenced_frame = + std::make_unique<content::RenderFrameHostWrapper>( + fenced_frame_test_helper()->CreateFencedFrame( + GetActiveWebContents()->GetPrimaryMainFrame(), fenced_frame_url)); + EXPECT_NE(fenced_frame, nullptr); + + EXPECT_TRUE(AccessStorage(fenced_frame->get(), GetParam())); + + const GURL primary_main_frame_final_url = + TestServer()->GetURL("d.test", "/title1.html"); + // Performs a Client-redirect to `primary_main_frame_final_url`. + ASSERT_TRUE(content::NavigateToURLFromRendererWithoutUserGesture( + GetActiveWebContents(), primary_main_frame_final_url)); + + CloseTab(); + EXPECT_THAT( + redirects, + ElementsAre( + ("[1/1] blank -> a.test/title1.html (None) -> d.test/title1.html"))); +} + +IN_PROC_BROWSER_TEST_P(DIPSSiteDataAccessDetectorTest, + DiscardPrerenderedPageCookieClientAccess) { + // Prerendering pages do not have access to `StorageType::FILE_SYSTEM` until + // activation (AKA becoming the primary page, whose test case is already + // covered). + if (GetParam() == StorageType::FILE_SYSTEM) { + GTEST_SKIP(); + } + + std::vector<std::string> redirects; + StartAppendingRedirectsTo(&redirects); + + const GURL primary_main_frame_url = + TestServer()->GetURL("a.test", "/title1.html"); + ASSERT_TRUE( + content::NavigateToURL(GetActiveWebContents(), primary_main_frame_url)); + + const GURL prerendering_url = TestServer()->GetURL("a.test", "/title2.html"); + const int host_id = prerender_test_helper()->AddPrerender(prerendering_url); + prerender_test_helper()->WaitForPrerenderLoadCompletion(prerendering_url); + content::test::PrerenderHostObserver observer(*GetActiveWebContents(), + host_id); + EXPECT_FALSE(observer.was_activated()); + content::RenderFrameHost* prerender_frame = + prerender_test_helper()->GetPrerenderedMainFrameHost(host_id); + EXPECT_NE(prerender_frame, nullptr); + + EXPECT_TRUE(AccessStorage(prerender_frame, GetParam())); + + prerender_test_helper()->CancelPrerenderedPage(host_id); + observer.WaitForDestroyed(); + + const GURL primary_main_frame_final_url = + TestServer()->GetURL("d.test", "/title1.html"); + // Performs a Client-redirect to `primary_main_frame_final_url`. + ASSERT_TRUE(content::NavigateToURLFromRendererWithoutUserGesture( + GetActiveWebContents(), primary_main_frame_final_url)); + + CloseTab(); + EXPECT_THAT( + redirects, + ElementsAre( + ("[1/1] blank -> a.test/title1.html (None) -> d.test/title1.html"))); +} + +// WeLocks accesses aren't monitored by the `PageSpecificContentSettings` as +// there are not persistent. +// TODO(crbug.com/1449328): Remove `StorageType::DATABASE` once deprecation is +// complete. +// TODO(crbug.com/1449328): Remove `StorageType::FILE_SYSTEM` once deprecation +// is complete. +INSTANTIATE_TEST_SUITE_P(All, + DIPSSiteDataAccessDetectorTest, + ::testing::Values(StorageType::DATABASE, + StorageType::LOCAL_STORAGE, + StorageType::SESSION_STORAGE, + StorageType::CACHE, + StorageType::FILE_SYSTEM, + StorageType::INDEXED_DB));
diff --git a/chrome/browser/download/download_status_updater_mac.mm b/chrome/browser/download/download_status_updater_mac.mm index e204fb43..e2d2091 100644 --- a/chrome/browser/download/download_status_updater_mac.mm +++ b/chrome/browser/download/download_status_updater_mac.mm
@@ -15,10 +15,6 @@ #include "components/download/public/common/download_item.h" #import "net/base/mac/url_conversions.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { const char kCrNSProgressUserDataKey[] = "CrNSProgressUserData"; @@ -27,16 +23,16 @@ public: CrNSProgressUserData(NSProgress* progress, const base::FilePath& target) : target_(target) { - progress_ = progress; + progress_.reset(progress, base::scoped_policy::RETAIN); } - ~CrNSProgressUserData() override { [progress_ unpublish]; } + ~CrNSProgressUserData() override { [progress_.get() unpublish]; } - NSProgress* progress() const { return progress_; } + NSProgress* progress() const { return progress_.get(); } base::FilePath target() const { return target_; } void setTarget(const base::FilePath& target) { target_ = target; } private: - NSProgress* __strong progress_; + base::scoped_nsobject<NSProgress> progress_; base::FilePath target_; }; @@ -153,12 +149,12 @@ base::mac::FilePathToNSString(download->GetTargetFilePath()); if (download->GetState() == download::DownloadItem::COMPLETE) { // Bounce the dock icon. - [NSDistributedNotificationCenter.defaultCenter + [[NSDistributedNotificationCenter defaultCenter] postNotificationName:@"com.apple.DownloadFileFinished" object:download_path]; } // Notify the Finder. - [NSWorkspace.sharedWorkspace noteFileSystemChanged:download_path]; + [[NSWorkspace sharedWorkspace] noteFileSystemChanged:download_path]; } }
diff --git a/chrome/browser/download/drag_download_item_mac.mm b/chrome/browser/download/drag_download_item_mac.mm index 2d60be06..4a9f2a9 100644 --- a/chrome/browser/download/drag_download_item_mac.mm +++ b/chrome/browser/download/drag_download_item_mac.mm
@@ -11,10 +11,6 @@ #include "ui/gfx/image/image.h" #include "ui/views/widget/widget.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - // Cocoa intends a smart dragging source, while `DragDownloadItem()` is a simple // "start dragging this" fire-and-forget. This is a generic source just good // enough to satisfy AppKit. @@ -59,7 +55,7 @@ NSURL* file_url = base::mac::FilePathToNSURL(download->GetTargetFilePath()); NSDraggingItem* file_item = - [[NSDraggingItem alloc] initWithPasteboardWriter:file_url]; + [[[NSDraggingItem alloc] initWithPasteboardWriter:file_url] autorelease]; if (icon) { NSImage* file_image = icon->ToNSImage(); NSSize image_size = file_image.size;
diff --git a/chrome/browser/enterprise/connectors/device_trust/navigation_throttle.h b/chrome/browser/enterprise/connectors/device_trust/navigation_throttle.h index cf61e58..cb2def8 100644 --- a/chrome/browser/enterprise/connectors/device_trust/navigation_throttle.h +++ b/chrome/browser/enterprise/connectors/device_trust/navigation_throttle.h
@@ -79,7 +79,7 @@ // to true. void OnConsentPrefUpdated(); - std::unique_ptr<ConsentRequester> consent_requester_ = nullptr; + std::unique_ptr<ConsentRequester> consent_requester_; // Only set to true when a challenge response (or timeout) resumed the // throttled navigation.
diff --git a/chrome/browser/enterprise/signals/device_info_fetcher_mac.mm b/chrome/browser/enterprise/signals/device_info_fetcher_mac.mm index a04c1f6b0..47c36bd 100644 --- a/chrome/browser/enterprise/signals/device_info_fetcher_mac.mm +++ b/chrome/browser/enterprise/signals/device_info_fetcher_mac.mm
@@ -18,10 +18,6 @@ #include "base/system/sys_info.h" #include "net/base/network_interfaces.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace enterprise_signals { namespace {
diff --git a/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chrome/browser/extensions/api/debugger/debugger_apitest.cc index ebd5e6e..e0062b9 100644 --- a/chrome/browser/extensions/api/debugger/debugger_apitest.cc +++ b/chrome/browser/extensions/api/debugger/debugger_apitest.cc
@@ -663,13 +663,7 @@ } }; -// TODO(crbug/1434257): Flaky on Lacros and Linux. -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX) -#define MAYBE_Debugger DISABLED_Debugger -#else -#define MAYBE_Debugger Debugger -#endif -IN_PROC_BROWSER_TEST_F(DebuggerExtensionApiTest, MAYBE_Debugger) { +IN_PROC_BROWSER_TEST_F(DebuggerExtensionApiTest, Debugger) { ASSERT_TRUE(RunExtensionTest("debugger")) << message_; } @@ -748,13 +742,7 @@ } }; -// TODO(crbug/1440919): Flaky on Lacros and Linux. -#if BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(IS_LINUX) -#define MAYBE_Debugger DISABLED_Debugger -#else -#define MAYBE_Debugger Debugger -#endif -IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest, MAYBE_Debugger) { +IN_PROC_BROWSER_TEST_F(SitePerProcessDebuggerExtensionApiTest, Debugger) { GURL url(embedded_test_server()->GetURL( "a.com", "/extensions/api_test/debugger/oopif.html")); GURL iframe_url(embedded_test_server()->GetURL(
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc index 8236d85..c54dd4d 100644 --- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc +++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -33,9 +33,11 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/passwords/settings/password_manager_porter_interface.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/browser/web_applications/test/web_app_test.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_id_constants.h" +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" #include "chrome/browser/webapps/chrome_webapps_client.h" #include "chrome/browser/webauthn/passkey_model_factory.h" #include "chrome/common/extensions/api/passwords_private.h" @@ -1390,8 +1392,11 @@ webapps::ChromeWebappsClient::GetInstance(); auto* provider = web_app::FakeWebAppProvider::Get(profile()); - provider->SetDefaultFakeSubsystems(); - provider->StartWithSubsystems(); + // This test harness is handling web contents loading, so use the real web + // contents manager. + provider->SetWebContentsManager( + std::make_unique<web_app::WebContentsManager>()); + web_app::test::AwaitStartWebAppProviderAndSubsystems(profile()); task_environment()->RunUntilIdle(); // Check that no web app installation is happening at the moment.
diff --git a/chrome/browser/file_select_helper_mac.mm b/chrome/browser/file_select_helper_mac.mm index 800875c..6192599f 100644 --- a/chrome/browser/file_select_helper_mac.mm +++ b/chrome/browser/file_select_helper_mac.mm
@@ -17,10 +17,6 @@ #include "third_party/zlib/google/zip.h" #include "ui/shell_dialogs/selected_file_info.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { base::StringPiece AsStringPiece(NSString* str) {
diff --git a/chrome/browser/first_run/first_run_internal_mac.mm b/chrome/browser/first_run/first_run_internal_mac.mm index fe8cf46..2479263 100644 --- a/chrome/browser/first_run/first_run_internal_mac.mm +++ b/chrome/browser/first_run/first_run_internal_mac.mm
@@ -6,14 +6,12 @@ #include "chrome/browser/mac/initial_prefs.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace first_run::internal { +namespace first_run { +namespace internal { base::FilePath InitialPrefsPath() { return initial_prefs::InitialPrefsPath(); } -} // namespace first_run::internal +} // namespace internal +} // namespace first_run
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 24595c5..f8bfeaf6 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1020,7 +1020,7 @@ "fjacky", "elklm" ], - "expiry_milestone": 115 + "expiry_milestone": 120 }, { "name": "chrome-cart-dom-based-heuristics", @@ -1115,7 +1115,7 @@ "fjacky", "elklm" ], - "expiry_milestone": 115 + "expiry_milestone": 120 }, { "name": "consistency-new-account-interface", @@ -1937,11 +1937,6 @@ "expiry_milestone": 120 }, { - "name": "enable-cast-remoting-query-blocklist", - "owners": [ "rwkeane@google.com", "openscreen-eng@google.com" ], - "expiry_milestone": 115 - }, - { "name": "enable-cast-streaming-av1", "owners": [ "jophba", "openscreen-eng" ], "expiry_milestone": 120 @@ -4255,11 +4250,6 @@ "expiry_milestone": 120 }, { - "name": "global-media-controls-modern-ui", - "owners": [ "steimel", "media-dev" ], - "expiry_milestone": 110 - }, - { "name": "google-one-offer-files-banner", "owners": ["yawano@google.com","assistive-eng@google.com"], "expiry_milestone": 116 @@ -5154,15 +5144,9 @@ "owners": ["qpubert@google.com", "djean@google.com"], "expiry_milestone": 115 }, - { - "name": "nearby-sharing-self-share-auto-accept", - "owners": [ "hansenmichael@google.com", "chromeos-cross-device-eng@google.com" ], - "expiry_milestone": 125 - }, - { - "name": "nearby-sharing-self-share-ui", - "owners": [ "hansenmichael@google.com", "chromeos-cross-device-eng@google.com" ], - "expiry_milestone": 125 + {"name": "nearby-sharing-self-share", + "owners": ["brandosocarras@google.com", "hansenmichael@google.com", "chromeos-cross-device-eng@google.com"], + "expiry_milestone": 125 }, { "name": "network-service-in-process",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 776d9ba..0f5305b 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1630,12 +1630,6 @@ "Show updated UI for Global Media Controls in CrOS."; #endif -const char kGlobalMediaControlsModernUIName[] = - "Global Media Controls Modern UI"; -const char kGlobalMediaControlsModernUIDescription[] = - "Use a redesigned version of the Global Media Controls UI. Requires " - "#global-media-controls to also be enabled."; - const char kGoogleOneOfferFilesBannerName[] = "Google One offer Files banner"; const char kGoogleOneOfferFilesBannerDescription[] = "Shows a Files banner about Google One offer."; @@ -1986,6 +1980,9 @@ const char kCscName[] = "CSC"; const char kCscDescription[] = ""; +const char kCscPinnedName[] = "CSC Pin State"; +const char kCscPinnedDescription[] = ""; + const char kCscVssName[] = "CSC-VSS"; const char kCscVssDescription[] = ""; @@ -6191,16 +6188,10 @@ const char kMultilingualTypingDescription[] = "Enables support for multilingual assistive typing on ChromeOS."; -const char kNearbySharingSelfShareAutoAcceptName[] = - "Nearby Sharing Self Share Auto-Accept"; -const char kNearbySharingSelfShareAutoAcceptDescription[] = - "Enables auto-accept functionality when sharing between a user's own " - "devices."; - -const char kNearbySharingSelfShareUIName[] = "Nearby Sharing Self Share UI"; -const char kNearbySharingSelfShareUIDescription[] = - "Enables UI features for Self Share to allow seamless sharing between a " - "user's own devices."; +const char kNearbySharingSelfShareName[] = "Nearby Sharing Self Share"; +const char kNearbySharingSelfShareDescription[] = + "Enables Self Share auto-accept and UI features to allow seamless sharing " + "between a user's own devices."; const char kOobeHidDetectionRevampName[] = "OOBE HID Detection Revamp"; const char kOobeHidDetectionRevampDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 13d5d61..0f932ec9f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -909,9 +909,6 @@ extern const char kGlobalMediaControlsCrOSUpdatedUIDescription[]; #endif -extern const char kGlobalMediaControlsModernUIName[]; -extern const char kGlobalMediaControlsModernUIDescription[]; - extern const char kGoogleOneOfferFilesBannerName[]; extern const char kGoogleOneOfferFilesBannerDescription[]; @@ -1107,6 +1104,9 @@ extern const char kCscName[]; extern const char kCscDescription[]; +extern const char kCscPinnedName[]; +extern const char kCscPinnedDescription[]; + extern const char kCscVssName[]; extern const char kCscVssDescription[]; @@ -3550,11 +3550,8 @@ extern const char kMultilingualTypingName[]; extern const char kMultilingualTypingDescription[]; -extern const char kNearbySharingSelfShareAutoAcceptName[]; -extern const char kNearbySharingSelfShareAutoAcceptDescription[]; - -extern const char kNearbySharingSelfShareUIName[]; -extern const char kNearbySharingSelfShareUIDescription[]; +extern const char kNearbySharingSelfShareName[]; +extern const char kNearbySharingSelfShareDescription[]; extern const char kOobeHidDetectionRevampName[]; extern const char kOobeHidDetectionRevampDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 3d0f078c..0d708d5a2 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -169,7 +169,6 @@ &kBackGestureRefactorAndroid, &kBackgroundThreadPool, &kBaselineGM3SurfaceColors, - &kBottomSheetGtsSupport, &kCastDeviceFilter, &kClearOmniboxFocusAfterNavigation, &kCloseTabSuggestions, @@ -475,13 +474,6 @@ "BaselineGM3SurfaceColors", base::FEATURE_DISABLED_BY_DEFAULT); -// Used as a killswitch rather than a rollout control as the feature this -// depends on runs on startup and this flag needs to be cached as it is used -// pre-native. -BASE_FEATURE(kBottomSheetGtsSupport, - "BottomSheetGtsSupport", - base::FEATURE_ENABLED_BY_DEFAULT); - // Used in downstream code. BASE_FEATURE(kCastDeviceFilter, "CastDeviceFilter",
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 934e2f2..c61bd96 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -30,7 +30,6 @@ BASE_DECLARE_FEATURE(kBackGestureRefactorAndroid); BASE_DECLARE_FEATURE(kBackgroundThreadPool); BASE_DECLARE_FEATURE(kBaselineGM3SurfaceColors); -BASE_DECLARE_FEATURE(kBottomSheetGtsSupport); BASE_DECLARE_FEATURE(kClearOmniboxFocusAfterNavigation); BASE_DECLARE_FEATURE(kCloseTabSuggestions); BASE_DECLARE_FEATURE(kCloseTabSaveTabList);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 23232d1..d9d3d2c17 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -148,7 +148,6 @@ "BackGestureRefactorActivityAndroid"; public static final String BASELINE_GM3_SURFACE_COLORS = "BaselineGM3SurfaceColors"; public static final String BOOKMARKS_REFRESH = "BookmarksRefresh"; - public static final String BOTTOM_SHEET_GTS_SUPPORT = "BottomSheetGtsSupport"; public static final String CACHE_DEPRECATED_SYSTEM_LOCATION_SETTING = "CacheDeprecatedSystemLocationSetting"; public static final String CAF_MRP_DEFERRED_DISCOVERY = "CafMRPDeferredDiscovery"; @@ -487,8 +486,6 @@ new CachedFlag(BACK_GESTURE_REFACTOR, false); public static final CachedFlag sBaselineGm3SurfaceColors = new CachedFlag(BASELINE_GM3_SURFACE_COLORS, false); - public static final CachedFlag sBottomSheetGtsSupport = - new CachedFlag(BOTTOM_SHEET_GTS_SUPPORT, true); public static final CachedFlag sCctAutoTranslate = new CachedFlag(CCT_AUTO_TRANSLATE, true); public static final CachedFlag sCctBottomBarSwipeUpGesture = new CachedFlag(CCT_BOTTOM_BAR_SWIPE_UP_GESTURE, true); @@ -604,7 +601,6 @@ sBackGestureRefactorActivityAndroid, sBackGestureRefactorAndroid, sBaselineGm3SurfaceColors, - sBottomSheetGtsSupport, sCctAutoTranslate, sCctBottomBarSwipeUpGesture, sCctBrandTransparency,
diff --git a/chrome/browser/fullscreen_mac.mm b/chrome/browser/fullscreen_mac.mm index d57d4c7f..cc0b862 100644 --- a/chrome/browser/fullscreen_mac.mm +++ b/chrome/browser/fullscreen_mac.mm
@@ -8,13 +8,9 @@ #include "base/command_line.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - bool IsFullScreenMode() { NSApplicationPresentationOptions options = - NSApp.currentSystemPresentationOptions; + [NSApp currentSystemPresentationOptions]; bool dock_hidden = (options & NSApplicationPresentationHideDock) || (options & NSApplicationPresentationAutoHideDock);
diff --git a/chrome/browser/global_keyboard_shortcuts_mac.mm b/chrome/browser/global_keyboard_shortcuts_mac.mm index 268856f..6c62ab97 100644 --- a/chrome/browser/global_keyboard_shortcuts_mac.mm +++ b/chrome/browser/global_keyboard_shortcuts_mac.mm
@@ -24,10 +24,6 @@ #include "ui/events/event_constants.h" #include "ui/events/keycodes/keyboard_code_conversion_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { // Returns a ui::Accelerator given a KeyboardShortcutData.
diff --git a/chrome/browser/headless/headless_mode_protocol_browsertest.cc b/chrome/browser/headless/headless_mode_protocol_browsertest.cc index 2592495..1cbcf14c 100644 --- a/chrome/browser/headless/headless_mode_protocol_browsertest.cc +++ b/chrome/browser/headless/headless_mode_protocol_browsertest.cc
@@ -210,12 +210,7 @@ "input/input-clipboard-ops.js") // https://crbug.com/1411976 -#if BUILDFLAG(IS_WIN) -#define MAYBE_ScreencastBasics DISABLED_ScreencastBasics -#else -#define MAYBE_ScreencastBasics ScreencastBasics -#endif -HEADLESS_MODE_PROTOCOL_TEST(MAYBE_ScreencastBasics, +HEADLESS_MODE_PROTOCOL_TEST(DISABLED_ScreencastBasics, "sanity/screencast-basics.js") HEADLESS_MODE_PROTOCOL_TEST(LargeBrowserWindowSize,
diff --git a/chrome/browser/icon_loader_mac.mm b/chrome/browser/icon_loader_mac.mm index f6acf136..ec9c7f75 100644 --- a/chrome/browser/icon_loader_mac.mm +++ b/chrome/browser/icon_loader_mac.mm
@@ -18,10 +18,6 @@ #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_util_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - // static IconLoader::IconGroup IconLoader::GroupForFilepath( const base::FilePath& file_path) {
diff --git a/chrome/browser/image_editor/event_capture_mac.mm b/chrome/browser/image_editor/event_capture_mac.mm index c5764d98..899a962 100644 --- a/chrome/browser/image_editor/event_capture_mac.mm +++ b/chrome/browser/image_editor/event_capture_mac.mm
@@ -8,6 +8,7 @@ #include <memory> +#include "base/apple/owned_objc.h" #include "base/check.h" #include "base/functional/callback.h" #include "base/memory/ptr_util.h" @@ -50,7 +51,8 @@ private: // remote_cocoa::CocoaMouseCaptureDelegate: bool PostCapturedEvent(NSEvent* event) override { - std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event); + std::unique_ptr<ui::Event> ui_event = + ui::EventFromNative(base::apple::OwnedNSEvent(event)); if (!ui_event) { return false; } @@ -121,8 +123,9 @@ return event; } - if (!target_window || [event window] == target_window) { - std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event); + if (!target_window || event.window == target_window) { + std::unique_ptr<ui::Event> ui_event = + ui::EventFromNative(base::apple::OwnedNSEvent(event)); if (!ui_event) { return event; }
diff --git a/chrome/browser/lifetime/application_lifetime_mac.mm b/chrome/browser/lifetime/application_lifetime_mac.mm index 32838ac..8548934 100644 --- a/chrome/browser/lifetime/application_lifetime_mac.mm +++ b/chrome/browser/lifetime/application_lifetime_mac.mm
@@ -13,10 +13,6 @@ #include "chrome/browser/lifetime/browser_shutdown.h" #include "ui/views/widget/widget.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace chrome { // At this point, the user is trying to quit (or the system is forcing the
diff --git a/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm b/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm index 00c6f3c6..ff89251f 100644 --- a/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm +++ b/chrome/browser/local_discovery/service_discovery_client_mac_factory.mm
@@ -6,10 +6,6 @@ #include "chrome/browser/local_discovery/service_discovery_client_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace local_discovery { // static
diff --git a/chrome/browser/mac/bluetooth_utility.mm b/chrome/browser/mac/bluetooth_utility.mm index ee56a06..5cfc2c7 100644 --- a/chrome/browser/mac/bluetooth_utility.mm +++ b/chrome/browser/mac/bluetooth_utility.mm
@@ -8,15 +8,10 @@ #import <IOBluetooth/IOBluetooth.h> #include <IOKit/IOKitLib.h> -#include "base/apple/bridging.h" #include "base/mac/foundation_util.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_ioobject.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace bluetooth_utility { BluetoothAvailability GetBluetoothAvailability() { @@ -38,13 +33,14 @@ while (device.reset(IOIteratorNext(scoped_iter.get())), device) { bluetooth_available = true; - base::ScopedCFTypeRef<CFMutableDictionaryRef> dict; - kr = IORegistryEntryCreateCFProperties(device, dict.InitializeInto(), - kCFAllocatorDefault, kNilOptions); + CFMutableDictionaryRef dict; + kr = IORegistryEntryCreateCFProperties( + device, &dict, kCFAllocatorDefault, kNilOptions); if (kr != KERN_SUCCESS) continue; + base::ScopedCFTypeRef<CFMutableDictionaryRef> scoped_dict(dict); - NSDictionary* objc_dict = base::apple::CFToNSPtrCast(dict.get()); + NSDictionary* objc_dict = base::mac::CFToNSCast(scoped_dict.get()); NSNumber* lmp_version = base::mac::ObjCCast<NSNumber>(objc_dict[@"LMPVersion"]); if (!lmp_version)
diff --git a/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm b/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm index 95e64392b..6bb5ccb 100644 --- a/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm +++ b/chrome/browser/mac/chrome_browser_main_extra_parts_mac.mm
@@ -6,10 +6,6 @@ #include "ui/display/screen.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - ChromeBrowserMainExtraPartsMac::ChromeBrowserMainExtraPartsMac() = default; ChromeBrowserMainExtraPartsMac::~ChromeBrowserMainExtraPartsMac() = default;
diff --git a/chrome/browser/mac/dock.mm b/chrome/browser/mac/dock.mm index 74e06d8..c35de6b 100644 --- a/chrome/browser/mac/dock.mm +++ b/chrome/browser/mac/dock.mm
@@ -11,7 +11,6 @@ #include <tuple> -#include "base/apple/bridging.h" #include "base/apple/bundle_locations.h" #include "base/logging.h" #include "base/mac/foundation_util.h" @@ -19,10 +18,6 @@ #include "base/mac/scoped_cftyperef.h" #include "build/branding_buildflags.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - extern "C" { // Undocumented private internal CFURL functions. The Dock uses these to @@ -55,14 +50,19 @@ // Foundation data types and returns an autoreleased NSDictionary. NSDictionary* DockFileDataDictionaryForURL(NSURL* url) { base::ScopedCFTypeRef<CFPropertyListRef> property_list( - _CFURLCopyPropertyListRepresentation(base::apple::NSToCFPtrCast(url))); + _CFURLCopyPropertyListRepresentation(base::mac::NSToCFCast(url))); CFDictionaryRef dictionary = base::mac::CFCast<CFDictionaryRef>(property_list); if (!dictionary) return nil; - return base::apple::CFToNSOwnershipCast( - (CFDictionaryRef)property_list.release()); + // It would be desirable to pipe the released object from the ScopedCFTypeRef + // directly into autorelease, as URLFromDockFileDataDictionary does below. + // However, this can't be done because CFPropertyListRef isn't bridgeable. + // Therefore, separate the release of the ownership of the ScopedCFTypeRef + // and the autorelease on the next line. + std::ignore = property_list.release(); + return [base::mac::CFToNSCast(dictionary) autorelease]; } // A wrapper around _CFURLCreateFromPropertyListRepresentation that operates @@ -70,11 +70,11 @@ NSURL* URLFromDockFileDataDictionary(NSDictionary* dictionary) { base::ScopedCFTypeRef<CFURLRef> url( _CFURLCreateFromPropertyListRepresentation( - kCFAllocatorDefault, base::apple::NSToCFPtrCast(dictionary))); + kCFAllocatorDefault, base::mac::NSToCFCast(dictionary))); if (!url) return nil; - return base::apple::CFToNSOwnershipCast(url.release()); + return [base::mac::CFToNSCast(url.release()) autorelease]; } // Returns an array parallel to |persistent_apps| containing only the
diff --git a/chrome/browser/mac/exception_processor.h b/chrome/browser/mac/exception_processor.h index fa7366a3..3abf195e 100644 --- a/chrome/browser/mac/exception_processor.h +++ b/chrome/browser/mac/exception_processor.h
@@ -29,7 +29,7 @@ // specifically, or |kUnknownNSException| if unknown. size_t BinForException(NSException* exception); -// Use UMA to track exception occurrence. +// Use UMA to track exception occurance. void RecordExceptionWithUma(NSException* exception); } // namespace chrome
diff --git a/chrome/browser/mac/exception_processor.mm b/chrome/browser/mac/exception_processor.mm index 0acdccaf..d25d272d 100644 --- a/chrome/browser/mac/exception_processor.mm +++ b/chrome/browser/mac/exception_processor.mm
@@ -19,10 +19,6 @@ #include "base/strings/sys_string_conversions.h" #include "components/crash/core/common/crash_key.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace chrome { // Maximum number of known named exceptions we'll support. There is
diff --git a/chrome/browser/mac/initial_prefs.mm b/chrome/browser/mac/initial_prefs.mm index 695f8bc2..e032fa2 100644 --- a/chrome/browser/mac/initial_prefs.mm +++ b/chrome/browser/mac/initial_prefs.mm
@@ -11,10 +11,6 @@ #include "chrome/common/chrome_paths_internal.h" #include "components/version_info/version_info.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chrome/browser/mac/install_from_dmg.mm b/chrome/browser/mac/install_from_dmg.mm index bdc7f73..f9fcfaed 100644 --- a/chrome/browser/mac/install_from_dmg.mm +++ b/chrome/browser/mac/install_from_dmg.mm
@@ -19,7 +19,6 @@ #include <algorithm> -#include "base/apple/bridging.h" #include "base/apple/bundle_locations.h" #include "base/auto_reset.h" #include "base/command_line.h" @@ -48,10 +47,6 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { // Given an io_service_t (expected to be of class IOMedia), walks the ancestor @@ -291,7 +286,7 @@ NSString* yes = l10n_util::GetNSStringWithFixup(IDS_INSTALL_FROM_DMG_YES); NSString* no = l10n_util::GetNSStringWithFixup(IDS_INSTALL_FROM_DMG_NO); - NSAlert* alert = [[NSAlert alloc] init]; + NSAlert* alert = [[[NSAlert alloc] init] autorelease]; alert.alertStyle = NSAlertStyleInformational; alert.messageText = title; @@ -323,7 +318,7 @@ IDS_INSTALL_FROM_DMG_AUTHENTICATION_PROMPT, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); return base::mac::AuthorizationCreateToRunAsRoot( - base::apple::NSToCFPtrCast(prompt)); + base::mac::NSToCFCast(prompt)); } // Invokes the installer program at `installer_path` to copy `source_path` to @@ -426,7 +421,7 @@ IDS_INSTALL_FROM_DMG_ERROR, l10n_util::GetStringUTF16(IDS_PRODUCT_NAME)); NSString* ok = l10n_util::GetNSStringWithFixup(IDS_OK); - NSAlert* alert = [[NSAlert alloc] init]; + NSAlert* alert = [[[NSAlert alloc] init] autorelease]; alert.alertStyle = NSAlertStyleWarning; alert.messageText = title;
diff --git a/chrome/browser/mac/nsprocessinfo_additions.mm b/chrome/browser/mac/nsprocessinfo_additions.mm index 06eb26ef..88b823ab 100644 --- a/chrome/browser/mac/nsprocessinfo_additions.mm +++ b/chrome/browser/mac/nsprocessinfo_additions.mm
@@ -8,10 +8,6 @@ @implementation NSProcessInfo(ChromeAdditions) -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - - (BOOL)cr_isMainBrowserOrTestProcess { NSString* processTypeString = [NSString stringWithFormat:@"--%s=", switches::kProcessType];
diff --git a/chrome/browser/mac/relauncher.mm b/chrome/browser/mac/relauncher.mm index 4a7a10a..b96deee 100644 --- a/chrome/browser/mac/relauncher.mm +++ b/chrome/browser/mac/relauncher.mm
@@ -25,6 +25,7 @@ #include "base/logging.h" #include "base/mac/launch_application.h" #include "base/mac/mac_logging.h" +#include "base/mac/scoped_nsobject.h" #include "base/path_service.h" #include "base/posix/eintr_wrapper.h" #include "base/process/launch.h" @@ -36,10 +37,6 @@ #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace mac_relauncher { namespace {
diff --git a/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm b/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm index d9c0ffb..4ec8d0b 100644 --- a/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm +++ b/chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm
@@ -22,10 +22,6 @@ #include "media/base/media_switches.h" #include "ui/base/cocoa/permissions_utils.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace system_media_permissions { namespace {
diff --git a/chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm b/chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm index c8ab96a8..ed2f1fd 100644 --- a/chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm +++ b/chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm
@@ -10,10 +10,6 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace system_media_permissions { namespace {
diff --git a/chrome/browser/media/webrtc/window_icon_util_mac.mm b/chrome/browser/media/webrtc/window_icon_util_mac.mm index b075efd..434b016 100644 --- a/chrome/browser/media/webrtc/window_icon_util_mac.mm +++ b/chrome/browser/media/webrtc/window_icon_util_mac.mm
@@ -11,10 +11,6 @@ #include "third_party/libyuv/include/libyuv/convert_argb.h" #include "third_party/skia/include/core/SkBitmap.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - gfx::ImageSkia GetWindowIcon(content::DesktopMediaID id) { DCHECK(id.type == content::DesktopMediaID::TYPE_WINDOW);
diff --git a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm index 0822e14..a154b2a 100644 --- a/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm +++ b/chrome/browser/media_galleries/mac/mtp_device_delegate_impl_mac.mm
@@ -10,6 +10,7 @@ #include <memory> #include "base/functional/bind.h" +#include "base/mac/scoped_nsobject.h" #include "base/memory/raw_ptr.h" #include "components/services/filesystem/public/mojom/types.mojom.h" #include "components/storage_monitor/image_capture_device.h" @@ -18,10 +19,6 @@ #include "content/public/browser/browser_thread.h" #include "storage/browser/file_system/async_file_util.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { int kReadDirectoryTimeLimitSeconds = 20; @@ -71,7 +68,7 @@ virtual void ResetDelegate(); private: - ImageCaptureDevice* __strong camera_device_; + base::scoped_nsobject<ImageCaptureDevice> camera_device_; // Weak pointer raw_ptr<MTPDeviceDelegateImplMac> delegate_; @@ -79,8 +76,9 @@ void MTPDeviceDelegateImplMac::DeviceListener::OpenCameraSession( const std::string& device_id) { - camera_device_ = - storage_monitor::ImageCaptureDeviceManager::deviceForUUID(device_id); + camera_device_.reset( + [storage_monitor::ImageCaptureDeviceManager::deviceForUUID(device_id) + retain]); [camera_device_ setListener:AsWeakPtr()]; [camera_device_ open]; } @@ -119,7 +117,7 @@ void MTPDeviceDelegateImplMac::DeviceListener::DeviceRemoved() { [camera_device_ close]; - camera_device_ = nil; + camera_device_.reset(); if (delegate_) delegate_->NoMoreItems(); } @@ -149,7 +147,8 @@ base::Unretained(camera_interface_.get()), device_id_)); } -MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() = default; +MTPDeviceDelegateImplMac::~MTPDeviceDelegateImplMac() { +} namespace {
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_mac.mm b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_mac.mm index b78408f0..26d7bdd 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_mac.mm +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics_mac.mm
@@ -8,10 +8,6 @@ #include "base/metrics/histogram_macros.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { // The possible values of the setting "Screens Have Separate Spaces".
diff --git a/chrome/browser/metrics/power/coalition_resource_usage_provider_mac.mm b/chrome/browser/metrics/power/coalition_resource_usage_provider_mac.mm index fd701c1b..7e94565 100644 --- a/chrome/browser/metrics/power/coalition_resource_usage_provider_mac.mm +++ b/chrome/browser/metrics/power/coalition_resource_usage_provider_mac.mm
@@ -9,10 +9,6 @@ #include "components/power_metrics/mach_time_mac.h" #include "components/power_metrics/resource_coalition_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { // Details about whether it's possible to get coalition resource usage data on
diff --git a/chrome/browser/metrics/power/power_metrics_provider_mac.mm b/chrome/browser/metrics/power/power_metrics_provider_mac.mm index 9258814..02a289c 100644 --- a/chrome/browser/metrics/power/power_metrics_provider_mac.mm +++ b/chrome/browser/metrics/power/power_metrics_provider_mac.mm
@@ -22,10 +22,6 @@ #include "base/timer/timer.h" #include "components/power_metrics/smc_mac.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { constexpr base::TimeDelta kStartupPowerMetricsCollectionDuration = base::Seconds(30);
diff --git a/chrome/browser/nearby_sharing/common/nearby_share_features.cc b/chrome/browser/nearby_sharing/common/nearby_share_features.cc index 9ac687d..7a3999a 100644 --- a/chrome/browser/nearby_sharing/common/nearby_share_features.cc +++ b/chrome/browser/nearby_sharing/common/nearby_share_features.cc
@@ -23,15 +23,10 @@ "NearbySharingOnePageOnboarding", base::FEATURE_ENABLED_BY_DEFAULT); -// Enables auto-accept functionality when sharing between a user's own devices. -BASE_FEATURE(kNearbySharingSelfShareAutoAccept, - "NearbySharingSelfShareAutoAccept", - base::FEATURE_DISABLED_BY_DEFAULT); - -// Enables UI features for Self Share, to allow seamless sharing between a -// user's own devices. -BASE_FEATURE(kNearbySharingSelfShareUI, - "NearbySharingSelfShareUI", +// Enables UI features for Self Share to allow seamless sharing between a user's +// own devices. +BASE_FEATURE(kNearbySharingSelfShare, + "kNearbySharingSelfShare", base::FEATURE_DISABLED_BY_DEFAULT); // Enables use of WebRTC in Nearby Share.
diff --git a/chrome/browser/nearby_sharing/common/nearby_share_features.h b/chrome/browser/nearby_sharing/common/nearby_share_features.h index eb4ffc51..e298c6fe 100644 --- a/chrome/browser/nearby_sharing/common/nearby_share_features.h +++ b/chrome/browser/nearby_sharing/common/nearby_share_features.h
@@ -12,8 +12,7 @@ BASE_DECLARE_FEATURE(kNearbySharing); BASE_DECLARE_FEATURE(kNearbySharingDeviceContacts); BASE_DECLARE_FEATURE(kNearbySharingOnePageOnboarding); -BASE_DECLARE_FEATURE(kNearbySharingSelfShareAutoAccept); -BASE_DECLARE_FEATURE(kNearbySharingSelfShareUI); +BASE_DECLARE_FEATURE(kNearbySharingSelfShare); BASE_DECLARE_FEATURE(kNearbySharingVisibilityReminder); BASE_DECLARE_FEATURE(kNearbySharingWebRtc); BASE_DECLARE_FEATURE(kNearbySharingWifiLan);
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager.cc b/chrome/browser/nearby_sharing/nearby_notification_manager.cc index 87a1e82..3f21d44 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager.cc
@@ -65,7 +65,7 @@ std::string CreateNotificationIdForShareTarget( const ShareTarget& share_target) { - if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShareUI)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { return std::string(kNearbyTransferResultNotificationIdPrefix) + share_target.id.ToString(); } else { @@ -828,8 +828,7 @@ ShowProgress(share_target, transfer_metadata); break; case TransferMetadata::Status::kAwaitingLocalConfirmation: - if (base::FeatureList::IsEnabled( - features::kNearbySharingSelfShareAutoAccept)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { // Only incoming transfers are handled via notifications. // Don't show notification for self shares since we will auto-accept. if (share_target.is_incoming && !share_target.for_self_share)
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc index 23b33118..f6e5332 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
@@ -152,21 +152,14 @@ class NearbyNotificationManagerTestBase : public testing::Test { public: - explicit NearbyNotificationManagerTestBase( - std::tuple<bool, bool> feature_list) { + explicit NearbyNotificationManagerTestBase(std::tuple<bool> feature_list) { std::vector<base::test::FeatureRef> enabled_features; std::vector<base::test::FeatureRef> disabled_features; is_self_share_enabled_ = std::get<0>(feature_list); - is_self_share_auto_accept_enabled_ = std::get<1>(feature_list); if (is_self_share_enabled_) { - enabled_features.push_back(features::kNearbySharingSelfShareUI); + enabled_features.push_back(features::kNearbySharingSelfShare); } else { - disabled_features.push_back(features::kNearbySharingSelfShareUI); - } - if (is_self_share_auto_accept_enabled_) { - enabled_features.push_back(features::kNearbySharingSelfShareAutoAccept); - } else { - disabled_features.push_back(features::kNearbySharingSelfShareAutoAccept); + disabled_features.push_back(features::kNearbySharingSelfShare); } scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); RegisterNearbySharingPrefs(pref_service_.registry()); @@ -285,14 +278,13 @@ data_decoder::test::InProcessDataDecoder in_process_data_decoder_; raw_ptr<MockSettingsOpener, ExperimentalAsh> settings_opener_; bool is_self_share_enabled_ = false; - bool is_self_share_auto_accept_enabled_ = false; }; // We parameterize these tests to run them with Self Share and Nearby Share // Visibility Reminder enabled and disabled. class NearbyNotificationManagerTest : public NearbyNotificationManagerTestBase, - public testing::WithParamInterface<std::tuple<bool, bool>> { + public testing::WithParamInterface<std::tuple<bool>> { public: NearbyNotificationManagerTest() : NearbyNotificationManagerTestBase(/*feature_list=*/GetParam()) {} @@ -407,7 +399,7 @@ public: NearbyNotificationManagerAttachmentsTest() : NearbyNotificationManagerTestBase( - /*feature_list=*/std::get<2>(GetParam())) {} + /*feature_list=*/std::get<1>(GetParam())) {} }; // Boolean parameter is |with_token| and the tuple parameter is featuree list @@ -420,7 +412,7 @@ public: NearbyNotificationManagerConnectionRequestTest() : NearbyNotificationManagerTestBase( - /*feature_list=*/std::get<1>(GetParam())) {} + /*feature_list=*/std::get<0>(GetParam())) {} }; std::u16string FormatNotificationTitle( @@ -1923,13 +1915,13 @@ manager()->OnTransferUpdate(share_target, transfer_metadata); std::vector<message_center::Notification> notifications = GetDisplayedNotifications(); - if (is_self_share_auto_accept_enabled_) { - ASSERT_EQ(0u, notifications.size()); + if (is_self_share_enabled_) { + ASSERT_EQ(0u, notifications.size()); } else { - ASSERT_EQ(1u, notifications.size()); + ASSERT_EQ(1u, notifications.size()); } } INSTANTIATE_TEST_SUITE_P(NearbyNotificationManagerTest, NearbyNotificationManagerTest, - testing::Combine(testing::Bool(), testing::Bool())); + testing::Combine(testing::Bool()));
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 4d9b3f9..5639f86 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -1955,7 +1955,7 @@ } // Do not advertise on lock screen unless Self Share is enabled. - if (!base::FeatureList::IsEnabled(features::kNearbySharingSelfShareUI)) { + if (!base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { if (is_screen_locked_) { StopAdvertising(); NS_LOG(VERBOSE) << __func__ @@ -3688,8 +3688,7 @@ return; } - if (base::FeatureList::IsEnabled( - features::kNearbySharingSelfShareAutoAccept)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { // Auto-accept self shares when not in high-visibility mode. if (share_target.for_self_share && !IsInHighVisibility()) { NS_LOG(INFO) << __func__ << ": Auto-accepting self share."; @@ -3826,8 +3825,7 @@ target.device_name = std::move(*device_name); target.is_incoming = is_incoming; target.device_id = GetDeviceId(endpoint_id, certificate); - if (base::FeatureList::IsEnabled( - features::kNearbySharingSelfShareAutoAccept)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { target.for_self_share = certificate && certificate->for_self_share(); }
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index 793ece71..fbf362f 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -351,8 +351,7 @@ // We will run tests with the following feature flags enabled and disabled in // all permutations. To add or a remove a feature you can just update this list. const std::vector<base::test::FeatureRef> kTestFeatures = { - features::kNearbySharingSelfShareAutoAccept, - features::kNearbySharingSelfShareUI}; + features::kNearbySharingSelfShare}; bool FileExists(const base::FilePath& file_path) { base::ScopedAllowBlockingForTesting allow_blocking; @@ -2324,7 +2323,7 @@ NearbySharingService::StatusCodes result = service_->RegisterReceiveSurface( &callback, NearbySharingService::ReceiveSurfaceState::kForeground); EXPECT_EQ(result, NearbySharingService::StatusCodes::kOk); - if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShareUI)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } else { EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); @@ -2342,7 +2341,7 @@ EXPECT_FALSE(fake_nearby_connections_manager_->is_shutdown()); session_controller_->SetScreenLocked(true); - if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShareUI)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { EXPECT_TRUE(fake_nearby_connections_manager_->IsAdvertising()); } else { EXPECT_FALSE(fake_nearby_connections_manager_->IsAdvertising()); @@ -5255,8 +5254,7 @@ ASSERT_TRUE(share_target.has_value()); EXPECT_EQ(kDeviceName, share_target->device_name); EXPECT_EQ(kDeviceType, share_target->type); - if (base::FeatureList::IsEnabled( - features::kNearbySharingSelfShareAutoAccept)) { + if (base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { EXPECT_EQ(certificate_proto.for_self_share(), share_target->for_self_share); } @@ -5286,8 +5284,7 @@ SetUpIncomingConnection(callback, /*for_self_share=*/true); // If Self Share is not enabled, we should just time out. - if (!base::FeatureList::IsEnabled( - features::kNearbySharingSelfShareAutoAccept)) { + if (!base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)) { base::RunLoop run_loop; EXPECT_CALL(callback, OnTransferUpdate(testing::_, testing::_)) .WillOnce(testing::Invoke(
diff --git a/chrome/browser/password_manager/password_manager_util_mac.mm b/chrome/browser/password_manager/password_manager_util_mac.mm index abe2af7..8e687ea1 100644 --- a/chrome/browser/password_manager/password_manager_util_mac.mm +++ b/chrome/browser/password_manager/password_manager_util_mac.mm
@@ -18,10 +18,6 @@ #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { NSString* UserAuthenticationRightName() { @@ -74,14 +70,14 @@ AuthorizationItem right_items[] = {{rightName.UTF8String, 0, nullptr, 0}}; AuthorizationRights rights = {std::size(right_items), right_items}; - base::ScopedCFTypeRef<CFStringRef> prompt = - base::SysUTF16ToCFStringRef(prompt_string); + NSString* prompt = base::SysUTF16ToNSString(prompt_string); // Pass kAuthorizationFlagDestroyRights to prevent the OS from saving the // authorization and not prompting the user when future requests are made. base::mac::ScopedAuthorizationRef authorization = base::mac::GetAuthorizationRightsWithPrompt( - &rights, prompt, kAuthorizationFlagDestroyRights); + &rights, base::mac::NSToCFCast(prompt), + kAuthorizationFlagDestroyRights); return static_cast<bool>(authorization); }
diff --git a/chrome/browser/platform_util_mac.mm b/chrome/browser/platform_util_mac.mm index 43040bd..f7530d9f 100644 --- a/chrome/browser/platform_util_mac.mm +++ b/chrome/browser/platform_util_mac.mm
@@ -22,10 +22,6 @@ #include "ui/views/widget/widget.h" #include "url/gurl.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace platform_util { // Returns true if revealing file paths in the Finder should be skipped
diff --git a/chrome/browser/policy/browser_dm_token_storage_mac.mm b/chrome/browser/policy/browser_dm_token_storage_mac.mm index ade8520..7cc153b 100644 --- a/chrome/browser/policy/browser_dm_token_storage_mac.mm +++ b/chrome/browser/policy/browser_dm_token_storage_mac.mm
@@ -29,10 +29,6 @@ #include "chrome/common/chrome_paths.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace policy { namespace {
diff --git a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc index 99d732e..8143bc8 100644 --- a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc +++ b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.cc
@@ -44,23 +44,35 @@ void EncryptedReportingClient::UploadReport( base::Value::Dict merging_payload, absl::optional<base::Value::Dict> context, - const std::string& dm_token, - const std::string& client_id, + policy::CloudPolicyClient* cloud_policy_client, ResponseCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); policy::DeviceManagementService* const device_management_service = delegate_->device_management_service(); if (!device_management_service) { + LOG(ERROR) << "Device management service required, but not found"; std::move(callback).Run(absl::nullopt); return; } + // This is the case for uploading managed user events from an + // unmanaged device. The server will authenticate by looking at the user dm + // tokens inside the records instead of a single request-level device dm + // token. + policy::DMAuth auth_data = policy::DMAuth::NoAuth(); + + if (cloud_policy_client) { + // The device cloud policy client only exists on managed devices and is the + // source of the DM token. So if the device is managed, we use the device dm + // token as authentication. + auth_data = policy::DMAuth::FromDMToken(cloud_policy_client->dm_token()); + } + auto config = std::make_unique<policy::EncryptedReportingJobConfiguration>( - g_browser_process->shared_url_loader_factory(), - policy::DMAuth::FromDMToken(dm_token), + g_browser_process->shared_url_loader_factory(), std::move(auth_data), device_management_service->configuration() ->GetEncryptedReportingServerUrl(), - std::move(merging_payload), dm_token, client_id, + std::move(merging_payload), cloud_policy_client, base::BindOnce(&EncryptedReportingClient::OnReportUploadCompleted, weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
diff --git a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h index 143ad24b..38659d6 100644 --- a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h +++ b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h
@@ -18,10 +18,14 @@ #include "components/policy/core/common/cloud/device_management_service.h" #include "third_party/abseil-cpp/absl/types/optional.h" +namespace policy { +class CloudPolicyClient; +} // namespace policy + namespace reporting { -// Implements the logic required to talk to the device management service for -// Encrypted Reporting Pipeline records upload. +// Implements the logic required to talk to the device management service +// for Encrypted Reporting Pipeline records upload. class EncryptedReportingClient { public: class Delegate { @@ -52,8 +56,7 @@ // completed. void UploadReport(base::Value::Dict merging_payload, absl::optional<base::Value::Dict> context, - const std::string& dm_token, - const std::string& client_id, + policy::CloudPolicyClient* cloud_policy_client, ResponseCallback callback); private: @@ -76,7 +79,6 @@ base::WeakPtrFactory<EncryptedReportingClient> weak_ptr_factory_{this}; }; - } // namespace reporting #endif // CHROME_BROWSER_POLICY_MESSAGING_LAYER_UPLOAD_ENCRYPTED_REPORTING_CLIENT_H_
diff --git a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc index 2311c6e..129f017 100644 --- a/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc +++ b/chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client_unittest.cc
@@ -9,6 +9,8 @@ #include <utility> #include <vector> +#include "base/containers/contains.h" +#include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/run_loop.h" @@ -22,6 +24,8 @@ #include "chrome/test/base/testing_browser_process.h" #include "chromeos/ash/components/system/statistics_provider.h" #include "components/policy/core/common/cloud/device_management_service.h" +#include "components/policy/core/common/cloud/encrypted_reporting_job_configuration.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" @@ -87,6 +91,13 @@ TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( url_loader_factory_.GetSafeWeakWrapper()); BuildPayload(); + + cloud_policy_client_.SetDMToken(kDmToken); + cloud_policy_client_.client_id_ = kClientId; + } + + void TearDown() override { + policy::EncryptedReportingJobConfiguration::ResetUploadsStateForTest(); } void BuildPayload() { @@ -129,6 +140,7 @@ std::unique_ptr<policy::DeviceManagementService> device_management_service_; network::TestURLLoaderFactory url_loader_factory_; + policy::MockCloudPolicyClient cloud_policy_client_; #if BUILDFLAG(IS_CHROMEOS_ASH) ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_; @@ -145,17 +157,27 @@ EncryptedReportingClient encrypted_reporting_client( std::make_unique<FakeDelegate>(device_management_service_.get())); encrypted_reporting_client.UploadReport(std::move(merging_payload_), - std::move(context_), kDmToken, - kClientId, cb); + std::move(context_), + &cloud_policy_client_, cb); base::RunLoop().RunUntilIdle(); ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + // Verify request header contains dm token + EXPECT_TRUE(base::Contains( + (*url_loader_factory_.pending_requests())[0].request.headers.ToString(), + kDmToken)); + const std::string& pending_request_url = (*url_loader_factory_.pending_requests())[0].request.url.spec(); EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); + // Verify request contains dm token + EXPECT_TRUE(base::Contains( + (*url_loader_factory_.pending_requests())[0].request.headers.ToString(), + kDmToken)); + url_loader_factory_.SimulateResponseForPendingRequest( pending_request_url, base::StringPrintf(R"({"%s" : "%s"})", kResponseKey, kResponseValue)); @@ -169,8 +191,8 @@ DecrementSequenceId(); BuildPayload(); encrypted_reporting_client.UploadReport(std::move(merging_payload_), - std::move(context_), kDmToken, - kClientId, cb); + std::move(context_), + &cloud_policy_client_, cb); // Sequence ID decreased, upload is rejected. EXPECT_FALSE(actual_reponse.has_value()); @@ -183,7 +205,7 @@ EncryptedReportingClient encrypted_reporting_client( std::make_unique<FakeDelegate>(nullptr)); encrypted_reporting_client.UploadReport( - std::move(merging_payload_), std::move(context_), kDmToken, kClientId, + std::move(merging_payload_), std::move(context_), &cloud_policy_client_, base::BindLambdaForTesting( [&responded, &actual_reponse](absl::optional<base::Value::Dict> response) { @@ -195,4 +217,25 @@ EXPECT_FALSE(actual_reponse.has_value()); } +// Verify that when the cloud policy client isn't provided, device info is not +// added to the request headers. +TEST_F(EncryptedReportingClientTest, UploadSucceedsWithoutDeviceInfo) { + // Set cloud policy client to be nullptr to indicate that device info is + // not available, i.e. the device dm token should NOT exists in + // the request headers. + EncryptedReportingClient encrypted_reporting_client( + std::make_unique<FakeDelegate>(device_management_service_.get())); + encrypted_reporting_client.UploadReport(std::move(merging_payload_), + std::move(context_), nullptr, + base::DoNothing()); + base::RunLoop().RunUntilIdle(); + + ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + + // Verify request does NOT contain dm token + EXPECT_FALSE(base::Contains( + (*url_loader_factory_.pending_requests())[0].request.headers.ToString(), + kDmToken)); +} + } // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/util/reporting_server_connector.cc b/chrome/browser/policy/messaging_layer/util/reporting_server_connector.cc index bb887dc..c8a143a 100644 --- a/chrome/browser/policy/messaging_layer/util/reporting_server_connector.cc +++ b/chrome/browser/policy/messaging_layer/util/reporting_server_connector.cc
@@ -23,6 +23,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/policy/chrome_browser_policy_connector.h" +#include "chrome/browser/policy/management_utils.h" #include "chrome/browser/policy/messaging_layer/upload/encrypted_reporting_client.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/reporting_util.h" @@ -56,6 +57,12 @@ "EnableEncryptedReportingClientForUpload", base::FEATURE_DISABLED_BY_DEFAULT); +// TODO(b/281905099): remove after rolling out reporting managed user events +// from unmanaged devices +BASE_FEATURE(kEnableReportingFromUnmanagedDevices, + "EnableReportingFromUnmanagedDevices", + base::FEATURE_DISABLED_BY_DEFAULT); + // Gets the size of payload as a JSON string. static int GetPayloadSize(const base::Value::Dict& payload) { std::string payload_json; @@ -196,14 +203,24 @@ core_ = nullptr; } +// static +// Returns true if device info should be including in the upload. Returns false +// otherwise. +bool DeviceInfoRequiredForUpload() { + return !base::FeatureList::IsEnabled(kEnableReportingFromUnmanagedDevices) || + policy::IsDeviceEnterpriseManaged(); +} + void ReportingServerConnector::UploadEncryptedReportInternal( base::Value::Dict merging_payload, absl::optional<base::Value::Dict> context, ResponseCallbackInternal callback) { if (base::FeatureList::IsEnabled(kEnableEncryptedReportingClientForUpload)) { - encrypted_reporting_client_->UploadReport( - std::move(merging_payload), std::move(context), client_->dm_token(), - client_->client_id(), std::move(callback)); + // TODO(b/283187811): remove cloud policy client as a parameter to + // `UploadReport` and read device info from `merging_payload` instead. + encrypted_reporting_client_->UploadReport(std::move(merging_payload), + std::move(context), client_, + std::move(callback)); return; } client_->UploadEncryptedReport(std::move(merging_payload), std::move(context), @@ -226,23 +243,27 @@ // Now we are on UI task runner. ReportingServerConnector* const connector = GetInstance(); - auto client_status = connector->EnsureUsableClient(); - if (!client_status.ok()) { - std::move(callback).Run(client_status); - return; - } - if (connector->client_->dm_token().empty()) { - std::move(callback).Run( - Status(error::UNAVAILABLE, "Device DM token not set")); - return; - } - // Client is usable. Prepare context for the upload. - // Compose the only context elements needed by reporting server. + // Add context elements needed by reporting server. base::Value::Dict context; context.SetByDottedPath("browser.userAgent", embedder_support::GetUserAgent()); - context.SetByDottedPath("device.dmToken", connector->client_->dm_token()); + + if (DeviceInfoRequiredForUpload()) { + // Initialize the cloud policy client + auto client_status = connector->EnsureUsableClient(); + if (!client_status.ok()) { + std::move(callback).Run(client_status); + return; + } + if (connector->client_->dm_token().empty()) { + std::move(callback).Run( + Status(error::UNAVAILABLE, "Device DM token not set")); + return; + } + // TODO(b/283187811): add device info to merging_payload + context.SetByDottedPath("device.dmToken", connector->client_->dm_token()); + } // Forward the `UploadEncryptedReport` to the cloud policy client. absl::optional<int> request_payload_size;
diff --git a/chrome/browser/policy/messaging_layer/util/reporting_server_connector.h b/chrome/browser/policy/messaging_layer/util/reporting_server_connector.h index 938007c..a0abf87 100644 --- a/chrome/browser/policy/messaging_layer/util/reporting_server_connector.h +++ b/chrome/browser/policy/messaging_layer/util/reporting_server_connector.h
@@ -24,6 +24,7 @@ class EncryptedReportingClient; BASE_DECLARE_FEATURE(kEnableEncryptedReportingClientForUpload); +BASE_DECLARE_FEATURE(kEnableReportingFromUnmanagedDevices); // Singleton wrapper of a client used for uploading events to the reporting // server. Enables safe access to the client with an ability to detect when it
diff --git a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc index caa22a1..cf4ee2c 100644 --- a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc +++ b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.cc
@@ -34,7 +34,7 @@ network::TestNetworkConnectionTracker::CreateGetter())) { auto mock_client = std::make_unique<::policy::MockCloudPolicyClient>(); mock_client->SetDMToken( - ::policy::DMToken::CreateValidToken("FAKE_DM_TOKEN").value()); + ::policy::DMToken::CreateValidToken(kFakeDmToken).value()); auto service = std::make_unique<::policy::MockCloudPolicyService>( mock_client.get(), store_.get()); GetInstance()->core_ = core_.get();
diff --git a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.h b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.h index a2041e1..c43b492 100644 --- a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.h +++ b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_test_util.h
@@ -15,6 +15,8 @@ namespace reporting { +constexpr char kFakeDmToken[] = "FAKE_DM_TOKEN"; + class EncryptedReportingClient; class ReportingServerConnector::TestEnvironment {
diff --git a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc index d82c891..5005619 100644 --- a/chrome/browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc +++ b/chrome/browser/policy/messaging_layer/util/reporting_server_connector_unittest.cc
@@ -18,6 +18,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/device_management_service.h" +#include "components/policy/core/common/cloud/encrypted_reporting_job_configuration.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/reporting/util/status.h" #include "components/reporting/util/statusor.h" @@ -31,10 +32,15 @@ #include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chromeos/ash/components/install_attributes/stub_install_attributes.h" #include "chromeos/ash/components/system/fake_statistics_provider.h" #include "chromeos/ash/components/system/statistics_provider.h" #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/startup/browser_init_params.h" +#endif + using testing::_; using testing::DoAll; using testing::Eq; @@ -97,8 +103,11 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) fake_statistics_provider_.SetMachineStatistic( ash::system::kSerialNumberKeyForTest, "fake-serial-number"); + install_attributes_.Get()->SetCloudManaged("fake-domain-name", + "fake-device-id"); #endif - // Prepare to respond to `ReportingServerConnector::UploadEncryptedReport`. + // Prepare to respond to + // `ReportingServerConnector::UploadEncryptedReport`. TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory( url_loader_factory_.GetSafeWeakWrapper()); auto config = @@ -110,6 +119,11 @@ test_env_.SetEncryptedReportingClient( std::make_unique<EncryptedReportingClient>(std::move(fake_delegate))); } + + void TearDown() override { + policy::EncryptedReportingJobConfiguration::ResetUploadsStateForTest(); + } + content::BrowserTaskEnvironment task_environment_; ReportingServerConnector::TestEnvironment test_env_; @@ -118,6 +132,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_; + ash::ScopedStubInstallAttributes install_attributes_ = + ash::ScopedStubInstallAttributes(); #endif }; @@ -168,17 +184,34 @@ EXPECT_OK(response_event.result()); } -TEST_F(ReportingServerConnectorTest, EncryptedReportingClientForUploadEnabled) { - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature( - kEnableEncryptedReportingClientForUpload); +// This test verifies that we can upload from an unmanaged device when the +// proper features are enabled. +// TODO(b/281905099): remove feature dependencies after roll out. +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) +TEST_F(ReportingServerConnectorTest, UploadFromUnmanagedDevice) { + // Set the device management state to unmanaged. +#if BUILDFLAG(IS_CHROMEOS_ASH) + install_attributes_.Get()->SetConsumerOwned(); +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + auto params = crosapi::mojom::BrowserInitParams::New(); + params->is_device_enterprised_managed = false; + chromeos::BrowserInitParams::SetInitParamsForTests(std::move(params)); +#endif - // EnableEncryptedReportingClientForUpload is enabled, + // Enable EnableEncryptedReportingClientForUpload and + // EnableReportingFromUnmanagedDevices features. Both are required to + // upload records from an unmanaged device. + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + /*enabled_features=*/{kEnableReportingFromUnmanagedDevices, + kEnableEncryptedReportingClientForUpload}, + /*disabled_features=*/{}); + // `EncryptedReportingClient` will be used for upload. EXPECT_CALL(*test_env_.client(), UploadEncryptedReport(_, _, _)).Times(0); - // Call `ReportingServerConnector::UploadEncryptedReport` from the thread - // pool. + // Call `ReportingServerConnector::UploadEncryptedReport` from the + // thread pool. test::TestEvent<StatusOr<base::Value::Dict>> response_event; base::ThreadPool::PostTask( FROM_HERE, @@ -192,6 +225,49 @@ const std::string& pending_request_url = (*url_loader_factory_.pending_requests())[0].request.url.spec(); + // Verify request header DOES NOT contain a dm token + EXPECT_FALSE(base::Contains( + (*url_loader_factory_.pending_requests())[0].request.headers.ToString(), + kFakeDmToken)); + + EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); + + url_loader_factory_.SimulateResponseForPendingRequest(pending_request_url, + R"({"key": + "value"})"); + EXPECT_OK(response_event.result()); +} +#endif // BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) + +TEST_F(ReportingServerConnectorTest, EncryptedReportingClientForUploadEnabled) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( + kEnableEncryptedReportingClientForUpload); + + // EnableEncryptedReportingClientForUpload is enabled, + // `EncryptedReportingClient` will be used for upload. + EXPECT_CALL(*test_env_.client(), UploadEncryptedReport(_, _, _)).Times(0); + + // Call `ReportingServerConnector::UploadEncryptedReport` from the + // thread pool. + test::TestEvent<StatusOr<base::Value::Dict>> response_event; + base::ThreadPool::PostTask( + FROM_HERE, + base::BindOnce(&ReportingServerConnector::UploadEncryptedReport, + /*merging_payload=*/base::Value::Dict(), + response_event.cb())); + + task_environment_.RunUntilIdle(); + ASSERT_THAT(*url_loader_factory_.pending_requests(), SizeIs(1)); + + const std::string& pending_request_url = + (*url_loader_factory_.pending_requests())[0].request.url.spec(); + + // Verify request header contains dm token + EXPECT_TRUE(base::Contains( + (*url_loader_factory_.pending_requests())[0].request.headers.ToString(), + kFakeDmToken)); + EXPECT_THAT(pending_request_url, StartsWith(kServerUrl)); url_loader_factory_.SimulateResponseForPendingRequest(pending_request_url,
diff --git a/chrome/browser/process_singleton_mac.mm b/chrome/browser/process_singleton_mac.mm index c92f894b..aba9d654 100644 --- a/chrome/browser/process_singleton_mac.mm +++ b/chrome/browser/process_singleton_mac.mm
@@ -9,10 +9,6 @@ #include "base/mac/scoped_aedesc.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { // Extracts the URL from |event| and forwards it to an already-running Chromium
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc index ce02161..9fb0fb5 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu_unittest.cc
@@ -81,14 +81,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" -#include "ash/constants/ash_switches.h" #include "chrome/browser/ash/crosapi/browser_util.h" -#include "chrome/browser/ash/profiles/profile_helper.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile_manager.h" -#include "components/account_id/account_id.h" -#include "components/user_manager/fake_user_manager.h" -#include "components/user_manager/scoped_user_manager.h" #endif using extensions::Extension; @@ -544,9 +537,6 @@ } PrefService* local_state() { return testing_local_state_->Get(); } - ScopedTestingLocalState* testing_local_state() { - return testing_local_state_.get(); - } Browser* GetBrowser() { if (!browser_) { @@ -1149,28 +1139,14 @@ // Ash, if Lacros is the only browser. TEST_F(RenderViewContextMenuPrefsTest, LensImageSearchDisabledIfAshBrowserIsDisabled) { + auto scoped_lacros_primary = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); base::test::ScopedFeatureList features; features.InitWithFeatures( {lens::features::kLensStandalone, lens::features::kEnableImageTranslate, - ash::features::kLacrosSupport, ash::features::kLacrosPrimary, - ash::features::kLacrosOnly, - ash::features::kLacrosProfileMigrationForceOff}, + ash::features::kLacrosOnly}, {}); - auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>(); - auto* primary_user = - fake_user_manager->AddUser(AccountId::FromUserEmail("test@test")); - fake_user_manager->UserLoggedIn(primary_user->GetAccountId(), - primary_user->username_hash(), - /*browser_restart=*/false, - /*is_child=*/false); - auto scoped_user_manager = std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); ASSERT_FALSE(crosapi::browser_util::IsAshWebBrowserEnabled()); - ash::ProfileHelper::Get(); - - TestingProfileManager testing_profile_manager( - TestingBrowserProcess::GetGlobal(), testing_local_state()); - ASSERT_TRUE(testing_profile_manager.SetUp()); SetUserSelectedDefaultSearchProvider("https://www.google.com", /*supports_image_search=*/true); @@ -1369,21 +1345,11 @@ // feature is enabled if Lacros is the only browser. TEST_F(RenderViewContextMenuPrefsTest, LensRegionSearchDisabledIfAshBrowserIsDisabled) { + auto scoped_lacros_primary = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); base::test::ScopedFeatureList features; features.InitWithFeatures( - {lens::features::kLensStandalone, ash::features::kLacrosSupport, - ash::features::kLacrosPrimary, ash::features::kLacrosOnly, - ash::features::kLacrosProfileMigrationForceOff}, - {}); - auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>(); - auto* primary_user = - fake_user_manager->AddUser(AccountId::FromUserEmail("test@test")); - fake_user_manager->UserLoggedIn(primary_user->GetAccountId(), - primary_user->username_hash(), - /*browser_restart=*/false, - /*is_child=*/false); - auto scoped_user_manager = std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); + {lens::features::kLensStandalone, ash::features::kLacrosOnly}, {}); ASSERT_FALSE(crosapi::browser_util::IsAshWebBrowserEnabled()); SetUserSelectedDefaultSearchProvider("https://www.google.com",
diff --git a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm index 4ce94104..bfd77ff3 100644 --- a/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm +++ b/chrome/browser/renderer_host/chrome_render_widget_host_view_mac_delegate.mm
@@ -7,6 +7,7 @@ #include <cmath> #include "base/auto_reset.h" +#include "base/mac/scoped_nsobject.h" #include "base/strings/sys_string_conversions.h" #include "chrome/browser/devtools/devtools_window.h" #include "chrome/browser/profiles/profile.h" @@ -30,10 +31,6 @@ #include "mojo/public/cpp/bindings/remote.h" #include "services/service_manager/public/cpp/interface_provider.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - @interface ChromeRenderWidgetHostViewMacDelegate () <HistorySwiperDelegate> @property(readonly) content::WebContents* webContents; @@ -48,7 +45,7 @@ int32_t _widgetRoutingId; // Responsible for 2-finger swipes history navigation. - HistorySwiper* __strong _historySwiper; + base::scoped_nsobject<HistorySwiper> _historySwiper; // A boolean set to true while resigning first responder status, to avoid // infinite recursion in the case of reentrance. @@ -61,13 +58,14 @@ if (self) { _widgetProcessId = renderWidgetHost->GetProcess()->GetID(); _widgetRoutingId = renderWidgetHost->GetRoutingID(); - _historySwiper = [[HistorySwiper alloc] initWithDelegate:self]; + _historySwiper.reset([[HistorySwiper alloc] initWithDelegate:self]); } return self; } - (void)dealloc { [_historySwiper setDelegate:nil]; + [super dealloc]; } - (content::WebContents*)webContents {
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 294da6be..ef0060f9 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -278,6 +278,7 @@ "$root_gen_dir/chrome/dev_ui_browser_resources.pak", "$root_gen_dir/chrome/internals_resources.pak", "$root_gen_dir/chrome/invalidations_resources.pak", + "$root_gen_dir/chrome/location_internals_resources.pak", "$root_gen_dir/chrome/media_resources.pak", "$root_gen_dir/chrome/net_internals_resources.pak", "$root_gen_dir/chrome/omnibox_resources.pak", @@ -303,6 +304,7 @@ "//chrome/browser/resources/browsing_topics:resources", "//chrome/browser/resources/internals:resources", "//chrome/browser/resources/invalidations:resources", + "//chrome/browser/resources/location_internals:resources", "//chrome/browser/resources/media:resources", "//chrome/browser/resources/net_internals:resources", "//chrome/browser/resources/omnibox:resources",
diff --git a/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn b/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn index dc8f7138..ba48f89 100644 --- a/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn +++ b/chrome/browser/resources/chromeos/internet_config_dialog/BUILD.gn
@@ -24,6 +24,7 @@ "chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js", "chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js", "chrome://resources/mojo/services/network/public/mojom/ip_address.mojom-webui.js", + "chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js", ] deps = [
diff --git a/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn b/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn index 82c918d..8efce67 100644 --- a/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn +++ b/chrome/browser/resources/chromeos/internet_detail_dialog/BUILD.gn
@@ -27,6 +27,7 @@ "chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js", "chrome://resources/mojo/services/network/public/mojom/ip_address.mojom-webui.js", "chrome://resources/ash/common/network/mojo_interface_provider.js", + "chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js", ] deps = [
diff --git a/chrome/browser/resources/location_internals/BUILD.gn b/chrome/browser/resources/location_internals/BUILD.gn new file mode 100644 index 0000000..4363668 --- /dev/null +++ b/chrome/browser/resources/location_internals/BUILD.gn
@@ -0,0 +1,19 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//ui/webui/resources/tools/build_webui.gni") + +build_webui("build") { + grd_prefix = "location_internals" + static_files = [ + "location_internals.css", + "location_internals.html", + ] + + non_web_component_files = [ "location_internals.ts" ] + + ts_deps = [ "//ui/webui/resources/js:build_ts" ] + + ts_composite = true +}
diff --git a/chrome/browser/resources/location_internals/DIR_METADATA b/chrome/browser/resources/location_internals/DIR_METADATA new file mode 100644 index 0000000..c400c68 --- /dev/null +++ b/chrome/browser/resources/location_internals/DIR_METADATA
@@ -0,0 +1,4 @@ +monorail: { + component: "Blink>Geolocation" +} +team_email: "device-dev@chromium.org"
diff --git a/chrome/browser/resources/location_internals/OWNERS b/chrome/browser/resources/location_internals/OWNERS new file mode 100644 index 0000000..f3b2efb --- /dev/null +++ b/chrome/browser/resources/location_internals/OWNERS
@@ -0,0 +1 @@ +file://content/browser/geolocation/OWNERS
diff --git a/chrome/browser/resources/location_internals/location_internals.css b/chrome/browser/resources/location_internals/location_internals.css new file mode 100644 index 0000000..fd1fefa --- /dev/null +++ b/chrome/browser/resources/location_internals/location_internals.css
@@ -0,0 +1,29 @@ +/* Copyright 2023 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +#container { + display: flex; + justify-content: space-around; + padding-inline-end: 20px; + padding-inline-start: 20px; +} + +table { + border-collapse: collapse; + font-family: arial, sans-serif; + margin-top: 20px; +} + +table caption { + font-size: 18px; + font-weight: bold; + text-align: start; +} + +td, +th { + border: 1px solid #ddd; + padding: 8px; + text-align: start; +}
diff --git a/chrome/browser/resources/location_internals/location_internals.html b/chrome/browser/resources/location_internals/location_internals.html new file mode 100644 index 0000000..1b2086fc --- /dev/null +++ b/chrome/browser/resources/location_internals/location_internals.html
@@ -0,0 +1,48 @@ +<!doctype html> +<html dir="$i18n{textdirection}" lang="$i18n{language}"> + +<head> + <meta charset="utf-8"> + <title>Location Internals</title> + <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> + <link rel="stylesheet" href="location_internals.css"> +</head> + +<body> + <h2 class="header">Location Internals</h2> + <header class="page-header"> + <button id="watch-btn">Start Watching Position</button> + </header> + <div id="container"> + + <table id="watch-position"> + <caption>WatchPosition</caption> + <thead> + <tr> + <th>Timestamp</th> + <th>Position</th> + <th>Accuracy</th> + <th>Altitude</th> + <th>AltitudeAccuracy</th> + <th>Heading</th> + <th>Speed</th> + </tr> + </thead> + <tbody> + <tr> + <td id="watch-position-timestamp"></td> + <td id="watch-position-position"></td> + <td id="watch-position-accuracy"></td> + <td id="watch-position-altitude"></td> + <td id="watch-position-altitude-accuracy"></td> + <td id="watch-position-heading"></td> + <td id="watch-position-speed"></td> + </tr> + </tbody> + </table> + + </div> + <script type="module" src="location_internals.js"></script> +</body> + +</html>
diff --git a/chrome/browser/resources/location_internals/location_internals.ts b/chrome/browser/resources/location_internals/location_internals.ts new file mode 100644 index 0000000..368aa4c --- /dev/null +++ b/chrome/browser/resources/location_internals/location_internals.ts
@@ -0,0 +1,79 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {getRequiredElement} from 'chrome://resources/js/util_ts.js'; + +let watchButton: HTMLElement; +let watchTable: HTMLElement; +let watchId: number = -1; + +document.addEventListener('DOMContentLoaded', () => { + watchButton = getRequiredElement<HTMLElement>('watch-btn'); + watchTable = getRequiredElement<HTMLElement>('watch-position'); + watchButton.addEventListener('click', () => { + if (watchId === -1) { + watchId = navigator.geolocation.watchPosition(logSuccess, logError, { + enableHighAccuracy: true, + timeout: 5000, + maximumAge: 0, + }); + watchButton.textContent = 'Stop Watching Position'; + } else { + navigator.geolocation.clearWatch(watchId); + watchId = -1; + watchButton.textContent = 'Start Watching Position'; + } + }); +}); + +function logSuccess(position: GeolocationPosition) { + assert(watchTable); + const timeCell = getRequiredElement<HTMLElement>('watch-position-timestamp'); + const positionCell = + getRequiredElement<HTMLElement>('watch-position-position'); + + timeCell.textContent = new Date(position.timestamp).toLocaleString(); + positionCell.textContent = + `${position.coords.latitude} ° , ${position.coords.longitude} ° `; + + if (position.coords.accuracy) { + const accuracyCell = + getRequiredElement<HTMLElement>('watch-position-accuracy'); + accuracyCell.textContent = position.coords.accuracy.toString(); + } + + if (position.coords.altitude) { + const altitudeCell = + getRequiredElement<HTMLElement>('watch-position-altitude'); + altitudeCell.textContent = position.coords.altitude.toString(); + } + + if (position.coords.altitudeAccuracy) { + const altitudeAccuracyCell = + getRequiredElement<HTMLElement>('watch-position-altitude-accuracy'); + altitudeAccuracyCell.textContent = + position.coords.altitudeAccuracy.toString(); + } + + if (position.coords.heading) { + const headingCell = + getRequiredElement<HTMLElement>('watch-position-heading'); + headingCell.textContent = position.coords.heading.toString(); + } + + if (position.coords.speed) { + const speedCell = getRequiredElement<HTMLElement>('watch-position-speed'); + speedCell.textContent = position.coords.speed.toString(); + } +} + +function logError(error: GeolocationPositionError) { + assert(watchTable); + const timeCell = getRequiredElement<HTMLElement>('watch-position-timestamp'); + const positionCell = + getRequiredElement<HTMLElement>('watch-position-position'); + timeCell.textContent = new Date().toLocaleString(); + positionCell.textContent = `${error.message}, code: ${error.code}`; +}
diff --git a/chrome/browser/resources/password_manager/BUILD.gn b/chrome/browser/resources/password_manager/BUILD.gn index 4f928a9c..502b328 100644 --- a/chrome/browser/resources/password_manager/BUILD.gn +++ b/chrome/browser/resources/password_manager/BUILD.gn
@@ -46,6 +46,7 @@ "dialogs/multi_store_delete_password_dialog.ts", "dialogs/move_passwords_dialog.ts", "dialogs/password_preview_item.ts", + "credential_note.ts", "password_details_card.ts", "password_details_section.ts", "password_list_item.ts",
diff --git a/chrome/browser/resources/password_manager/credential_note.html b/chrome/browser/resources/password_manager/credential_note.html new file mode 100644 index 0000000..14898ac6 --- /dev/null +++ b/chrome/browser/resources/password_manager/credential_note.html
@@ -0,0 +1,50 @@ +<style include="cr-input-style cr-shared-style"> + #noteField { + background: var(--cr-input-background-color); + border-radius: 10px; + display: flex; + flex-direction: column; + padding: 10px 12px; + } + + #noteValue { + border: 0; + color: var(--cr-primary-text-color); + flex: 1; + overflow: hidden; + padding: 0; + resize: none; + text-overflow: ellipsis; + white-space: pre-line; + } + + #noteValue[limit-note] { + max-height: 3lh; + } + + #showMore { + color: var(--cr-link-color); + } + + #noteValue, + #showMore { + font-family: inherit; + letter-spacing: 0.15px; + line-height: 20px; + } + + .cr-form-field-label { + margin-bottom: 8px; + } +</style> + +<div class="cr-form-field-label">$i18n{noteLabel}</div> +<div id="noteField" class="input-field"> + <div id="noteValue" role="textbox" limit-note$="[[!showNoteFully_]]"> + <span>[[getNoteValue_(note)]]</span> + </div> + <a id="showMore" href="/" on-click="onshowMoreClick_" + hidden="[[isNoteFullyVisible_(showNoteFully_, note)]]"> + $i18n{showMore} + </a> +</div>
diff --git a/chrome/browser/resources/password_manager/credential_note.ts b/chrome/browser/resources/password_manager/credential_note.ts new file mode 100644 index 0000000..83660091 --- /dev/null +++ b/chrome/browser/resources/password_manager/credential_note.ts
@@ -0,0 +1,69 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_shared_style.css.js'; +import 'chrome://resources/cr_elements/cr_input/cr_input_style.css.js'; + +import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {getTemplate} from './credential_note.html.js'; +import {PasswordManagerImpl} from './password_manager_proxy.js'; + +export interface CredentialNoteElement { + $: { + noteValue: HTMLElement, + showMore: HTMLAnchorElement, + }; +} + +const CredentialNoteElementBase = I18nMixin(PolymerElement); + +export class CredentialNoteElement extends CredentialNoteElementBase { + static get is() { + return 'credential-note'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + note: String, + }; + } + + note: string; + private showNoteFully_: boolean; + + override connectedCallback() { + super.connectedCallback(); + // Set default value here so listeners can be updated properly. + this.showNoteFully_ = false; + } + + private getNoteValue_(): string { + return !this.note ? this.i18n('emptyNote') : this.note!; + } + + private isNoteFullyVisible_(): boolean { + return this.showNoteFully_ || + this.$.noteValue.scrollHeight === this.$.noteValue.offsetHeight; + } + + private onshowMoreClick_(e: Event) { + e.preventDefault(); + this.showNoteFully_ = true; + PasswordManagerImpl.getInstance().extendAuthValidity(); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'credential-note': CredentialNoteElement; + } +} + +customElements.define(CredentialNoteElement.is, CredentialNoteElement);
diff --git a/chrome/browser/resources/password_manager/password_details_card.html b/chrome/browser/resources/password_manager/password_details_card.html index ee3b7ad..b04d3b2 100644 --- a/chrome/browser/resources/password_manager/password_details_card.html +++ b/chrome/browser/resources/password_manager/password_details_card.html
@@ -50,40 +50,6 @@ margin-inline-end: var(--cr-button-edge-spacing); } - #noteField { - background: var(--cr-input-background-color); - border-radius: 10px; - display: flex; - flex-direction: column; - padding: 10px 12px; - } - - #noteValue { - border: 0; - color: var(--cr-primary-text-color); - flex: 1; - overflow: hidden; - padding: 0; - resize: none; - text-overflow: ellipsis; - white-space: pre-line; - } - - #noteValue[limit-note] { - max-height: 3lh; - } - - #showMore { - color: var(--cr-link-color); - } - - #noteValue, - #showMore { - font-family: inherit; - letter-spacing: 0.15px; - line-height: 20px; - } - #shareButton { margin-inline-start: auto; } @@ -137,16 +103,8 @@ </div> <div class="column-container"> <div hidden="[[isFederated_(password)]]"> - <div class="cr-form-field-label">$i18n{noteLabel}</div> - <div id="noteField" class="input-field"> - <div id="noteValue" role="textbox" limit-note$="[[!showNoteFully_]]"> - <span>[[getNoteValue_(password.note)]]</span> - </div> - <a id="showMore" href="/" on-click="onshowMoreClick_" - hidden="[[isNoteFullyVisible_(showNoteFully_, password.note)]]"> - $i18n{showMore} - </a> - </div> + <credential-note note="[[password.note]]" id="noteValue"> + </credential-note> </div> </div> </div>
diff --git a/chrome/browser/resources/password_manager/password_details_card.ts b/chrome/browser/resources/password_manager/password_details_card.ts index 34870db..298dedf 100644 --- a/chrome/browser/resources/password_manager/password_details_card.ts +++ b/chrome/browser/resources/password_manager/password_details_card.ts
@@ -20,6 +20,7 @@ import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CredentialNoteElement} from './credential_note.js'; import {getTemplate} from './password_details_card.html.js'; import {PasswordManagerImpl, PasswordViewPageInteractions} from './password_manager_proxy.js'; import {ShowPasswordMixin} from './show_password_mixin.js'; @@ -41,8 +42,8 @@ deleteButton: CrButtonElement, domainLabel: HTMLElement, editButton: CrButtonElement, - noteValue: HTMLElement, passwordValue: CrInputElement, + noteValue: CredentialNoteElement, showMore: HTMLAnchorElement, showPasswordButton: CrIconButtonElement, toast: CrToastElement, @@ -67,8 +68,6 @@ password: Object, toastMessage_: String, - showNoteFully_: Boolean, - showEditPasswordDialog_: Boolean, showDeletePasswordDialog_: Boolean, @@ -83,21 +82,10 @@ password: chrome.passwordsPrivate.PasswordUiEntry; private toastMessage_: string; - private noteRows_: number; - private showNoteFully_: boolean; private showEditPasswordDialog_: boolean; private showDeletePasswordDialog_: boolean; private enableSendPasswords_: boolean; - override connectedCallback() { - super.connectedCallback(); - if (this.isFederated_()) { - return; - } - // Set default value here so listeners can be updated properly. - this.showNoteFully_ = false; - } - private isFederated_(): boolean { return !!this.password.federationText; } @@ -185,21 +173,6 @@ this.extendAuthValidity_(); } - private getNoteValue_(): string { - return !this.password.note ? this.i18n('emptyNote') : this.password.note!; - } - - private isNoteFullyVisible_(): boolean { - return this.showNoteFully_ || - this.$.noteValue.scrollHeight === this.$.noteValue.offsetHeight; - } - - private onshowMoreClick_(e: Event) { - e.preventDefault(); - this.showNoteFully_ = true; - this.extendAuthValidity_(); - } - private extendAuthValidity_() { PasswordManagerImpl.getInstance().extendAuthValidity(); }
diff --git a/chrome/browser/resources/password_manager/password_manager.ts b/chrome/browser/resources/password_manager/password_manager.ts index d0bf8ff..019d3a3 100644 --- a/chrome/browser/resources/password_manager/password_manager.ts +++ b/chrome/browser/resources/password_manager/password_manager.ts
@@ -12,6 +12,7 @@ export {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.js'; export {OpenWindowProxyImpl} from 'chrome://resources/js/open_window_proxy.js'; export {PluralStringProxy, PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; +export {CredentialNoteElement} from './credential_note.js'; export {AddPasswordDialogElement} from './dialogs/add_password_dialog.js'; export {AuthTimedOutDialogElement} from './dialogs/auth_timed_out_dialog.js'; export {EditPasswordDialogElement} from './dialogs/edit_password_dialog.js';
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn index 005556ee..d7b7eb6c 100644 --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn
@@ -115,10 +115,12 @@ "performance_page/performance_page.ts", "performance_page/tab_discard_exception_add_dialog.ts", "performance_page/tab_discard_exception_add_input.ts", + "performance_page/tab_discard_exception_current_sites_list.ts", "performance_page/tab_discard_exception_edit_dialog.ts", "performance_page/tab_discard_exception_edit_input.ts", "performance_page/tab_discard_exception_entry.ts", "performance_page/tab_discard_exception_list.ts", + "performance_page/tab_discard_exception_tabbed_add_dialog.ts", "people_page/people_page.ts", "people_page/signout_dialog.ts", "people_page/sync_account_control.ts",
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 7d070527..680f24b9 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -135,6 +135,7 @@ "kerberos_page/kerberos_add_account_dialog.ts", "kerberos_page/kerberos_page.ts", "keyboard_shortcut_banner/keyboard_shortcut_banner.ts", + "main_page_container/main_page_container.ts", "multidevice_page/multidevice_combined_setup_item.ts", "multidevice_page/multidevice_feature_item.ts", "multidevice_page/multidevice_feature_toggle.ts", @@ -284,7 +285,6 @@ "os_search_page/search_subpage.ts", "os_settings_main/os_settings_main.ts", "os_settings_menu/os_settings_menu.ts", - "os_settings_page/os_settings_page.ts", "os_settings_page/os_settings_animated_pages.ts", "os_settings_page/os_settings_section.ts", "os_settings_page/os_settings_subpage.ts", @@ -414,13 +414,13 @@ css_files = [ "device_page/input_device_settings_shared.css", "internet_page/internet_shared.css", + "main_page_container/main_page_container_styles.css", "os_apps_page/app_management_page/app_management_cros_shared_style.css", "os_apps_page/app_management_page/app_management_cros_shared_vars.css", "os_languages_page/shared_style.css", "os_languages_page/shared_vars.css", "os_printing_page/cups_printer_shared.css", "os_settings_icons.css", - "os_settings_page_styles.css", "settings_shared.css", "settings_vars.css", ]
diff --git a/chrome/browser/resources/settings/chromeos/common/load_time_booleans.ts b/chrome/browser/resources/settings/chromeos/common/load_time_booleans.ts index bb1af58..ac5d45db 100644 --- a/chrome/browser/resources/settings/chromeos/common/load_time_booleans.ts +++ b/chrome/browser/resources/settings/chromeos/common/load_time_booleans.ts
@@ -15,6 +15,10 @@ return loadTimeData.getBoolean('isGuest'); } +export function isRevampWayfindingEnabled(): boolean { + return loadTimeData.getBoolean('isRevampWayfindingEnabled'); +} + // Apps page export function androidAppsVisible(): boolean { return loadTimeData.getBoolean('androidAppsVisible');
diff --git a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts index 26ebd7ed..37070a3 100644 --- a/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts +++ b/chrome/browser/resources/settings/chromeos/crostini_page/crostini_port_forwarding.ts
@@ -14,11 +14,10 @@ import 'chrome://resources/cr_elements/cr_toast/cr_toast.js'; import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; -import './crostini_port_forwarding_add_port_dialog.js'; import '/shared/settings/controls/settings_toggle_button.js'; import '../os_settings_page/os_settings_section.js'; -import '../os_settings_page_styles.css.js'; import '../settings_shared.css.js'; +import './crostini_port_forwarding_add_port_dialog.js'; import {PrefsMixin} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js';
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.html b/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.html index 7d4ea2a..2a6bc8b2 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.html +++ b/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.html
@@ -4,7 +4,7 @@ --network-summary-item-border-top, var(--cr-separator-line)); } #hotspotPageTitle { - padding-inline-start: 22px; + padding-inline-start: 0; } </style> @@ -13,8 +13,10 @@ actionable$="[[shouldShowArrowButton_(hotspotInfo.allowStatus)]]" on-click="navigateToDetailPage_" class="flex layout horizontal center link-wrapper"> - <iron-icon id="hotspotIcon" icon="[[getIconClass_(isHotspotToggleOn_)]]"> - </iron-icon> + <network-icon + id="hotspotIcon" + hotspot-info="[[hotspotInfo]]"> + </network-icon> <div id="hotspotPageTitle" class="middle settings-box-text" aria-hidden="true">
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.ts b/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.ts index c7ab4d8..29ca722 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.ts +++ b/chrome/browser/resources/settings/chromeos/internet_page/hotspot_summary_item.ts
@@ -7,6 +7,7 @@ * a toggle button below the network summary item. */ +import 'chrome://resources/ash/common/network/network_icon.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.js'; import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js';
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.ts b/chrome/browser/resources/settings/chromeos/lazy_load.ts index 7c5d728..f5cd25e 100644 --- a/chrome/browser/resources/settings/chromeos/lazy_load.ts +++ b/chrome/browser/resources/settings/chromeos/lazy_load.ts
@@ -37,6 +37,7 @@ import './os_a11y_page/tts_voice_subpage.js'; import './os_about_page/detailed_build_info_subpage.js'; import './os_apps_page/app_management_page/app_detail_view.js'; +import './os_apps_page/app_management_page/main_view.js'; import './os_search_page/google_assistant_subpage.js'; import './os_search_page/search_subpage.js'; import './os_people_page/account_manager_subpage.js'; @@ -70,6 +71,7 @@ import './guest_os/guest_os_shared_usb_devices_add_dialog.js'; import './guest_os/guest_os_shared_paths.js'; import './keyboard_shortcut_banner/keyboard_shortcut_banner.js'; +import './os_apps_page/app_management_page/app_item.js'; import './os_apps_page/app_management_page/chrome_app_detail_view.js'; import './os_files_page/google_drive_subpage.js'; import './os_files_page/google_drive_confirmation_dialog.js'; @@ -142,7 +144,9 @@ export {PdfOcrUserSelection, SettingsTextToSpeechSubpageElement} from './os_a11y_page/text_to_speech_subpage.js'; export {SettingsTtsVoiceSubpageElement} from './os_a11y_page/tts_voice_subpage.js'; export {AppManagementAppDetailViewElement} from './os_apps_page/app_management_page/app_detail_view.js'; +export {AppManagementAppItemElement} from './os_apps_page/app_management_page/app_item.js'; export {AppManagementChromeAppDetailViewElement} from './os_apps_page/app_management_page/chrome_app_detail_view.js'; +export {AppManagementMainViewElement} from './os_apps_page/app_management_page/main_view.js'; export {SettingsGoogleDriveSubpageElement} from './os_files_page/google_drive_subpage.js'; export {SettingsOfficePageElement} from './os_files_page/office_page.js'; export {OsSettingsFilesPageElement} from './os_files_page/os_files_page.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html b/chrome/browser/resources/settings/chromeos/main_page_container/main_page_container.html similarity index 97% rename from chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html rename to chrome/browser/resources/settings/chromeos/main_page_container/main_page_container.html index be66361c..46b952fe 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.html +++ b/chrome/browser/resources/settings/chromeos/main_page_container/main_page_container.html
@@ -1,4 +1,4 @@ -<style include="os-settings-page-styles cr-hidden-style settings-shared"> +<style include="cr-hidden-style settings-shared main-page-container-styles"> :host([is-subpage-animating]) { /* Prevent an unwanted horizontal scrollbar when transitioning back from * a sub-page. */ @@ -222,7 +222,7 @@ </div> </template> -<template is="dom-if" if="[[!hasExpandedSection_]]"> +<template is="dom-if" if="[[shouldShowAdvancedToggle_]]"> <div id="toggleSpacer"></div> <h2 id="toggleContainer"> <cr-button id="advancedToggle" on-click="advancedToggleClicked_"
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts b/chrome/browser/resources/settings/chromeos/main_page_container/main_page_container.ts similarity index 88% rename from chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts rename to chrome/browser/resources/settings/chromeos/main_page_container/main_page_container.ts index 8a5f195..722ff68 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_page/os_settings_page.ts +++ b/chrome/browser/resources/settings/chromeos/main_page_container/main_page_container.ts
@@ -4,7 +4,8 @@ /** * @fileoverview - * 'os-settings-page' is the settings page containing the actual OS settings. + * 'main-page-container' is the container hosting all the + * main (top-level) pages, including advanced pages. */ /** @@ -30,11 +31,11 @@ import 'chrome://resources/cr_elements/icons.html.js'; import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; -import './settings_idle_load.js'; +import '../os_settings_page/settings_idle_load.js'; +import '../main_page_container/main_page_container_styles.css.js'; import '../os_about_page/eol_offer_section.js'; import '../os_settings_icons.html.js'; import '../os_settings_page/os_settings_section.js'; -import '../os_settings_page_styles.css.js'; import {WebUiListenerMixin} from 'chrome://resources/cr_elements/web_ui_listener_mixin.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; @@ -42,6 +43,7 @@ import {beforeNextRender, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {castExists} from '../assert_extras.js'; +import {isRevampWayfindingEnabled} from '../common/load_time_booleans.js'; import {MainPageMixin} from '../main_page_mixin.js'; import {AboutPageBrowserProxyImpl} from '../os_about_page/about_page_browser_proxy.js'; import {AndroidAppsBrowserProxyImpl, AndroidAppsInfo} from '../os_apps_page/android_apps_browser_proxy.js'; @@ -49,14 +51,14 @@ import {routes} from '../os_settings_routes.js'; import {Route, Router} from '../router.js'; -import {getTemplate} from './os_settings_page.html.js'; +import {getTemplate} from './main_page_container.html.js'; -const OsSettingsPageElementBase = +const MainPageContainerElementBase = MainPageMixin(WebUiListenerMixin(PolymerElement)); -export class OsSettingsPageElement extends OsSettingsPageElementBase { +export class MainPageContainerElement extends MainPageContainerElementBase { static get is() { - return 'os-settings-page'; + return 'main-page-container' as const; } static get template() { @@ -126,6 +128,19 @@ type: Boolean, value: false, }, + + isRevampWayfindingEnabled_: { + type: Boolean, + value: () => { + return isRevampWayfindingEnabled(); + }, + }, + + shouldShowAdvancedToggle_: { + type: Boolean, + computed: 'computeShouldShowAdvancedToggle_(' + + 'isRevampWayfindingEnabled_, hasExpandedSection_)', + }, }; } @@ -142,6 +157,8 @@ private advancedTogglingInProgress_: boolean; private showEolIncentive_: boolean; private shouldShowOfferText_: boolean; + private isRevampWayfindingEnabled_: boolean; + private shouldShowAdvancedToggle_: boolean; constructor() { super(); @@ -216,6 +233,10 @@ return !this.hasExpandedSection_ && this.showEolIncentive_; } + private computeShouldShowAdvancedToggle_(): boolean { + return !this.isRevampWayfindingEnabled_ && !this.hasExpandedSection_; + } + private androidAppsInfoUpdate_(info: AndroidAppsInfo) { this.androidAppsInfo = info; } @@ -332,8 +353,8 @@ declare global { interface HTMLElementTagNameMap { - 'os-settings-page': OsSettingsPageElement; + [MainPageContainerElement.is]: MainPageContainerElement; } } -customElements.define(OsSettingsPageElement.is, OsSettingsPageElement); +customElements.define(MainPageContainerElement.is, MainPageContainerElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_page_styles.css b/chrome/browser/resources/settings/chromeos/main_page_container/main_page_container_styles.css similarity index 100% rename from chrome/browser/resources/settings/chromeos/os_settings_page_styles.css rename to chrome/browser/resources/settings/chromeos/main_page_container/main_page_container_styles.css
diff --git a/chrome/browser/resources/settings/chromeos/main_page_mixin.ts b/chrome/browser/resources/settings/chromeos/main_page_mixin.ts index 912d6db..5e7a639 100644 --- a/chrome/browser/resources/settings/chromeos/main_page_mixin.ts +++ b/chrome/browser/resources/settings/chromeos/main_page_mixin.ts
@@ -47,6 +47,11 @@ return RouteState.SECTION; } +function isAdvancedRoute(route: Route): boolean { + const routes = Router.getInstance().routes; + return routes.ADVANCED && routes.ADVANCED.contains(route); +} + const ALL_STATES = new Set([ RouteState.DIALOG, RouteState.SECTION, @@ -105,12 +110,6 @@ assertNotReached(); } - private shouldExpandAdvanced_(route: Route): boolean { - const routes = Router.getInstance().routes; - return (this.tagName === 'OS-SETTINGS-PAGE') && routes.ADVANCED && - routes.ADVANCED.contains(route); - } - loadAdvancedPage(): Promise<Element> { return this.shadowRoot! .querySelector<SettingsIdleLoadElement>( @@ -134,7 +133,8 @@ const waitFn = beforeNextRender.bind(null, this); return new Promise(resolve => { - if (this.shouldExpandAdvanced_(route)) { + if (this.tagName === 'MAIN-PAGE-CONTAINER' && + isAdvancedRoute(route)) { this.dispatchCustomEvent_('hide-container'); waitFn(async () => { await this.loadAdvancedPage(); @@ -202,7 +202,7 @@ // Case where going from |this| page to an unrelated page. // For example: - // |this| is os-settings-page AND + // |this| is main-page-container AND // oldRoute is /searchEngines AND // newRoute is /help. if (containsOld && !containsNew) { @@ -211,7 +211,7 @@ // Case where return from an unrelated page to |this| page. // For example: - // |this| is os-settings-page AND + // |this| is main-page-container AND // oldRoute is /help AND // newRoute is /searchEngines if (!containsOld && containsNew) {
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html index f787e57e..525d528 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html +++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.html
@@ -1,4 +1,4 @@ -<style include="settings-shared os-settings-page-styles"> +<style include="settings-shared main-page-container-styles"> :host { --about-page-image-space: 10px; }
diff --git a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts index 69d9c34..cdbbc5b 100644 --- a/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts +++ b/chrome/browser/resources/settings/chromeos/os_about_page/os_about_page.ts
@@ -16,10 +16,10 @@ import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import 'chrome://resources/polymer/v3_0/iron-media-query/iron-media-query.js'; import '../icons.html.js'; +import '../main_page_container/main_page_container_styles.css.js'; import '../os_settings_page/os_settings_animated_pages.js'; import '../os_settings_page/os_settings_section.js'; import '../os_settings_page/os_settings_subpage.js'; -import '../os_settings_page_styles.css.js'; import '../settings_shared.css.js'; import '../os_settings_icons.html.js'; import '../os_reset_page/os_powerwash_dialog.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.ts b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.ts index a159c77..b7c93fe 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.ts +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/app_item.ts
@@ -17,7 +17,8 @@ const AppManagementAppItemElementBase = AppManagementStoreMixin(PolymerElement); -class AppManagementAppItemElement extends AppManagementAppItemElementBase { +export class AppManagementAppItemElement extends + AppManagementAppItemElementBase { static get is() { return 'app-management-app-item'; }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.ts b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.ts index 89ae7a7..48a6350 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.ts +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.ts
@@ -25,7 +25,8 @@ const AppManagementMainViewElementBase = AppManagementStoreMixin(RouteObserverMixin(PolymerElement)); -class AppManagementMainViewElement extends AppManagementMainViewElementBase { +export class AppManagementMainViewElement extends + AppManagementMainViewElementBase { static get is() { return 'app-management-main-view'; }
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.ts b/chrome/browser/resources/settings/chromeos/os_settings.ts index 44c442f..61efcc8 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings.ts
@@ -48,12 +48,10 @@ import './os_apps_page/android_apps_subpage.js'; import './os_apps_page/app_notifications_page/app_notifications_subpage.js'; import './os_apps_page/app_management_page/app_details_item.js'; -import './os_apps_page/app_management_page/app_item.js'; import './os_apps_page/app_management_page/app_management_page.js'; import './os_apps_page/app_management_page/arc_detail_view.js'; import './os_apps_page/app_management_page/borealis_page/borealis_detail_view.js'; import './os_apps_page/app_management_page/dom_switch.js'; -import './os_apps_page/app_management_page/main_view.js'; import './os_apps_page/app_management_page/pin_to_shelf_item.js'; import './os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js'; import './os_apps_page/app_management_page/pwa_detail_view.js'; @@ -131,6 +129,7 @@ export {NetworkSummaryElement} from './internet_page/network_summary.js'; export {NetworkSummaryItemElement} from './internet_page/network_summary_item.js'; export {SettingsKerberosPageElement} from './kerberos_page/kerberos_page.js'; +export {MainPageContainerElement} from './main_page_container/main_page_container.js'; export {recordClick, recordNavigation, recordPageBlur, recordPageFocus, recordSearch, recordSettingChange, setUserActionRecorderForTesting} from './metrics_recorder.js'; export * as appNotificationHandlerMojom from './mojom-webui/app_notification_handler.mojom-webui.js'; export * as crosAudioConfigMojom from './mojom-webui/cros_audio_config.mojom-webui.js'; @@ -183,7 +182,6 @@ export {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl, SearchEnginesInfo} from './os_search_page/search_engines_browser_proxy.js'; export {OsSettingsMainElement} from './os_settings_main/os_settings_main.js'; export {OsSettingsMenuElement} from './os_settings_menu/os_settings_menu.js'; -export {OsSettingsPageElement} from './os_settings_page/os_settings_page.js'; export {OsSettingsSectionElement} from './os_settings_page/os_settings_section.js'; export {OsSettingsRoutes, routes} from './os_settings_routes.js'; export {OsSettingsSearchBoxElement} from './os_settings_search_box/os_settings_search_box.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html index 5c7a2eef..1424718 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html +++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.html
@@ -37,7 +37,7 @@ <managed-footnote show-device-info></managed-footnote> </template> <template is="dom-if" if="[[showPages_.settings]]"> - <os-settings-page + <main-page-container class="cr-centered-card-container" prefs="{{prefs}}" page-availability="[[pageAvailability]]" @@ -45,7 +45,7 @@ on-subpage-expand="onShowingSubpage_" on-showing-main-page="onShowingMainPage_" advanced-toggle-expanded="{{advancedToggleExpanded}}"> - </os-settings-page> + </main-page-container> </template> <template is="dom-if" if="[[showPages_.about]]"> <os-settings-about-page role="main"
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts index c77cd7d..dcc5b97 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings_main/os_settings_main.ts
@@ -13,7 +13,7 @@ import 'chrome://resources/js/search_highlight_utils.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import '../os_about_page/os_about_page.js'; -import '../os_settings_page/os_settings_page.js'; +import '../main_page_container/main_page_container.js'; import '../settings_shared.css.js'; import '../settings_vars.css.js'; @@ -174,9 +174,9 @@ } /** - * A handler for the 'showing-section' event fired from os-settings-page, - * indicating that a section should be scrolled into view as a result of a - * navigation. + * A handler for the 'showing-section' event fired from + * main-page-container, indicating that a section should be + * scrolled into view as a result of a navigation. */ private onShowingSection_(e: CustomEvent<HTMLElement>) { const section = e.detail;
diff --git a/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts b/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts index 89effd40..9e90554c 100644 --- a/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts +++ b/chrome/browser/resources/settings/performance_page/performance_browser_proxy.ts
@@ -5,6 +5,7 @@ import {sendWithPromise} from 'chrome://resources/js/cr.js'; export interface PerformanceBrowserProxy { + getCurrentOpenSites(): Promise<string[]>; getDeviceHasBattery(): Promise<boolean>; openBatterySaverFeedbackDialog(): void; openHighEfficiencyFeedbackDialog(): void; @@ -12,6 +13,10 @@ } export class PerformanceBrowserProxyImpl implements PerformanceBrowserProxy { + getCurrentOpenSites() { + return sendWithPromise('getCurrentOpenSites'); + } + getDeviceHasBattery() { return sendWithPromise('getDeviceHasBattery'); }
diff --git a/chrome/browser/resources/settings/performance_page/tab_discard_exception_current_sites_list.html b/chrome/browser/resources/settings/performance_page/tab_discard_exception_current_sites_list.html new file mode 100644 index 0000000..c8e7a745 --- /dev/null +++ b/chrome/browser/resources/settings/performance_page/tab_discard_exception_current_sites_list.html
@@ -0,0 +1,33 @@ +<style include="settings-shared"> + cr-checkbox::part(label-container) { + min-width: 0; + } + + .label-slot { + align-items: center; + display: flex; + } + + .checkbox-label { + margin-inline-start: 10px; + } +</style> +<div id="container" scrollable> + <iron-list id="list" scroll-target="container" role="grid" + items="[[currentSites_]]" selected-items="{{selectedSites_}}" + selection-enabled multi-selection + aria-rowcount$="[[currentSites_.length]]" + hidden$="[[!currentSites_.length]]"> + <template> + <cr-checkbox class="list-item no-outline" role="row" + tab-index="[[tabIndex]]" + aria-rowindex$="[[getAriaRowindex_(index)]]" + on-change="onToggleSelection_" checked="{{selected}}"> + <div class="label-slot"> + <site-favicon url="[[item]]"></site-favicon> + <div class="checkbox-label text-elide">[[item]]</div> + </div> + </cr-checkbox> + </template> + </iron-list> +</div>
diff --git a/chrome/browser/resources/settings/performance_page/tab_discard_exception_current_sites_list.ts b/chrome/browser/resources/settings/performance_page/tab_discard_exception_current_sites_list.ts new file mode 100644 index 0000000..b634febe --- /dev/null +++ b/chrome/browser/resources/settings/performance_page/tab_discard_exception_current_sites_list.ts
@@ -0,0 +1,119 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; +import 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; +import '../settings_shared.css.js'; +import '../site_favicon.js'; + +import {PrefsMixin, PrefsMixinInterface} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; +import {CrScrollableMixin, CrScrollableMixinInterface} from 'chrome://resources/cr_elements/cr_scrollable_mixin.js'; +import {ListPropertyUpdateMixin, ListPropertyUpdateMixinInterface} from 'chrome://resources/cr_elements/list_property_update_mixin.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {IronListElement} from 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {PerformanceBrowserProxy, PerformanceBrowserProxyImpl} from './performance_browser_proxy.js'; +import {HighEfficiencyModeExceptionListAction, PerformanceMetricsProxy, PerformanceMetricsProxyImpl} from './performance_metrics_proxy.js'; +import {getTemplate} from './tab_discard_exception_current_sites_list.html.js'; +import {TAB_DISCARD_EXCEPTIONS_PREF} from './tab_discard_exception_validation_mixin.js'; + +export interface TabDiscardExceptionCurrentSitesListElement { + $: { + list: IronListElement, + }; +} + +type Constructor<T> = new (...args: any[]) => T; +const TabDiscardExceptionCurrentSitesListElementBase = + ListPropertyUpdateMixin(CrScrollableMixin(PrefsMixin(PolymerElement))) as + Constructor<ListPropertyUpdateMixinInterface&CrScrollableMixinInterface& + PrefsMixinInterface&PolymerElement>; + +export class TabDiscardExceptionCurrentSitesListElement extends + TabDiscardExceptionCurrentSitesListElementBase { + static get is() { + return 'tab-discard-exception-current-sites-list'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + currentSites_: {type: Array, value: []}, + + selectedSites_: {type: Array, value: []}, + + submitDisabled: { + type: Boolean, + computed: 'computeSubmitDisabled_(selectedSites_.length)', + notify: true, + }, + }; + } + + private browserProxy_: PerformanceBrowserProxy = + PerformanceBrowserProxyImpl.getInstance(); + private metricsProxy_: PerformanceMetricsProxy = + PerformanceMetricsProxyImpl.getInstance(); + + private currentSites_: string[]; + private selectedSites_: string[]; + private submitDisabled: boolean; + + override async connectedCallback() { + super.connectedCallback(); + + const currentRules = await this.browserProxy_.getCurrentOpenSites(); + const existingRules = + new Set(this.getPref(TAB_DISCARD_EXCEPTIONS_PREF).value); + this.updateList( + 'currentSites_', x => x, + currentRules.filter(rule => !existingRules.has(rule))); + if (this.currentSites_.length) { + this.updateScrollableContents(); + } + this.dispatchEvent(new CustomEvent('sites-populated', { + detail: {length: this.currentSites_.length}, + })); + } + + private computeSubmitDisabled_() { + return !this.selectedSites_.length; + } + + private onToggleSelection_(e: {model: {index: number}}) { + this.$.list.toggleSelectionForIndex(e.model.index); + } + + private getAriaRowindex_(index: number): number { + return index + 1; + } + + async submit() { + assert(!this.submitDisabled); + this.selectedSites_.forEach(rule => { + this.appendPrefListItem(TAB_DISCARD_EXCEPTIONS_PREF, rule); + }); + this.dispatchEvent(new CustomEvent('add-exception', { + bubbles: true, + composed: true, + })); + this.metricsProxy_.recordExceptionListAction( + HighEfficiencyModeExceptionListAction.ADD); + } +} + +declare global { + interface HTMLElementTagNameMap { + 'tab-discard-exception-current-sites-list': + TabDiscardExceptionCurrentSitesListElement; + } +} + +customElements.define( + TabDiscardExceptionCurrentSitesListElement.is, + TabDiscardExceptionCurrentSitesListElement);
diff --git a/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.html b/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.html index 6ea54b07..2162971 100644 --- a/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.html +++ b/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.html
@@ -76,6 +76,11 @@ on-close="onAddDialogClose_" on-add-exception="onAddException_"> </tab-discard-exception-add-dialog> </template> +<template is="dom-if" if="[[showTabbedAddDialog_]]" restamp> + <tab-discard-exception-tabbed-add-dialog prefs="{{prefs}}" + on-close="onTabbedAddDialogClose_" on-add-exception="onAddException_"> + </tab-discard-exception-tabbed-add-dialog> +</template> <template is="dom-if" if="[[showEditDialog_]]" restamp> <tab-discard-exception-edit-dialog prefs="{{prefs}}" on-close="onEditDialogClose_" rule-to-edit="[[selectedRule_]]">
diff --git a/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.ts b/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.ts index 1e1a926..7c6f9b2 100644 --- a/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.ts +++ b/chrome/browser/resources/settings/performance_page/tab_discard_exception_list.ts
@@ -13,6 +13,7 @@ import './tab_discard_exception_add_dialog.js'; import './tab_discard_exception_edit_dialog.js'; import './tab_discard_exception_entry.js'; +import './tab_discard_exception_tabbed_add_dialog.js'; import {PrefsMixin, PrefsMixinInterface} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; @@ -21,6 +22,7 @@ import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.js'; import {ListPropertyUpdateMixin, ListPropertyUpdateMixinInterface} from 'chrome://resources/cr_elements/list_property_update_mixin.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {IronCollapseElement} from 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js'; import {PaperTooltipElement} from 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; import {DomRepeat, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -82,11 +84,25 @@ value: '', }, + isDiscardExceptionsImprovementsEnabled_: { + readOnly: true, + type: Boolean, + value() { + return loadTimeData.getBoolean( + 'isDiscardExceptionsImprovementsEnabled'); + }, + }, + showAddDialog_: { type: Boolean, value: false, }, + showTabbedAddDialog_: { + type: Boolean, + value: false, + }, + showEditDialog_: { type: Boolean, value: false, @@ -106,7 +122,9 @@ private siteList_: TabDiscardExceptionEntry[]; private overflowSiteListExpanded: boolean; private selectedRule_: string; + private isDiscardExceptionsImprovementsEnabled_: boolean; private showAddDialog_: boolean; + private showTabbedAddDialog_: boolean; private showEditDialog_: boolean; private tooltipText_: string; @@ -131,7 +149,11 @@ private onAddClick_() { assert(!this.showEditDialog_); - this.showAddDialog_ = true; + if (this.isDiscardExceptionsImprovementsEnabled_) { + this.showTabbedAddDialog_ = true; + } else { + this.showAddDialog_ = true; + } } private onMenuClick_(e: CustomEvent<{target: HTMLElement, site: string}>) { @@ -143,6 +165,7 @@ private onEditClick_() { assert(this.selectedRule_); assert(!this.showAddDialog_); + assert(!this.showTabbedAddDialog_); this.showEditDialog_ = true; this.$.menu.get().close(); } @@ -158,6 +181,10 @@ this.showAddDialog_ = false; } + private onTabbedAddDialogClose_() { + this.showTabbedAddDialog_ = false; + } + private onEditDialogClose_() { this.showEditDialog_ = false; }
diff --git a/chrome/browser/resources/settings/performance_page/tab_discard_exception_tabbed_add_dialog.html b/chrome/browser/resources/settings/performance_page/tab_discard_exception_tabbed_add_dialog.html new file mode 100644 index 0000000..46cbc7d --- /dev/null +++ b/chrome/browser/resources/settings/performance_page/tab_discard_exception_tabbed_add_dialog.html
@@ -0,0 +1,64 @@ +<style> + cr-tabs { + --cr-tabs-font-size: 100%; + --cr-tabs-height: 40px; + } + + #dialog { + --border-top-color: var(--google-grey-300); + --cr-dialog-body-border-top: 1px solid var(--border-top-color); + } + + @media (prefers-color-scheme: dark) { + #dialog { + --border-top-color: var(--cr-separator-color); + } + } + + #dialog::part(body-container) { + height: 250px; + } + + #helpText { + padding-bottom: 20px; + } + + #inputPage { + padding-top: 20px; + } +</style> +<cr-dialog id="dialog" close-text="$i18n{close}"> + <div slot="title">$i18n{addSiteTitle}</div> + <div slot="header"> + <cr-tabs id="tabs" tab-names="[[tabNames_]]" selected="{{selectedTab_}}"> + </cr-tabs> + </div> + <div slot="body"> + <iron-pages selected="[[selectedTab_]]"> + <tab-discard-exception-current-sites-list id="list" prefs="{{prefs}}" + on-sites-populated="onSitesPopulated_" + submit-disabled="{{submitDisabledList_}}"> + </tab-discard-exception-current-sites-list> + <div id="inputPage"> + <div id="helpText"> + $i18nRaw{tabDiscardingExceptionsAddDialogHelp} + </div> + <tab-discard-exception-add-input id="input" prefs="{{prefs}}" + submit-disabled="{{submitDisabledManual_}}"> + </tab-discard-exception-add-input> + </div> + </iron-pages> + </div> + <div slot="button-container"> + <cr-button id="cancelButton" class="cancel-button" + on-click="onCancelClick_"> + $i18n{cancel} + </cr-button> + <cr-button id="actionButton" class="action-button" on-click="onSubmitClick_" + disabled$="[[isSubmitDisabled_( + submitDisabledList_, submitDisabledManual_, selectedTab_)]]" + aria-label$="$i18n{tabDiscardingExceptionsAddButtonAriaLabel}"> + $i18n{add} + </cr-button> + </div> +</cr-dialog>
diff --git a/chrome/browser/resources/settings/performance_page/tab_discard_exception_tabbed_add_dialog.ts b/chrome/browser/resources/settings/performance_page/tab_discard_exception_tabbed_add_dialog.ts new file mode 100644 index 0000000..4d8896d --- /dev/null +++ b/chrome/browser/resources/settings/performance_page/tab_discard_exception_tabbed_add_dialog.ts
@@ -0,0 +1,116 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/cr_elements/cr_button/cr_button.js'; +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import 'chrome://resources/cr_elements/cr_tabs/cr_tabs.js'; +import 'chrome://resources/polymer/v3_0/iron-pages/iron-pages.js'; +import './tab_discard_exception_add_input.js'; +import './tab_discard_exception_current_sites_list.js'; + +import {PrefsMixin, PrefsMixinInterface} from 'chrome://resources/cr_components/settings_prefs/prefs_mixin.js'; +import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import {CrTabsElement} from 'chrome://resources/cr_elements/cr_tabs/cr_tabs.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + +import {TabDiscardExceptionAddInputElement} from './tab_discard_exception_add_input.js'; +import {TabDiscardExceptionCurrentSitesListElement} from './tab_discard_exception_current_sites_list.js'; +import {getTemplate} from './tab_discard_exception_tabbed_add_dialog.html.js'; + +export enum TabDiscardExceptionAddDialogTabs { + LIST = 0, + MANUAL = 1, +} + +export interface TabDiscardExceptionTabbedAddDialogElement { + $: { + actionButton: CrButtonElement, + cancelButton: CrButtonElement, + dialog: CrDialogElement, + input: TabDiscardExceptionAddInputElement, + list: TabDiscardExceptionCurrentSitesListElement, + tabs: CrTabsElement, + }; +} + +type Constructor<T> = new (...args: any[]) => T; +const TabDiscardExceptionTabbedAddDialogElementBase = + PrefsMixin(PolymerElement) as + Constructor<PrefsMixinInterface&PolymerElement>; + +export class TabDiscardExceptionTabbedAddDialogElement extends + TabDiscardExceptionTabbedAddDialogElementBase { + static get is() { + return 'tab-discard-exception-tabbed-add-dialog'; + } + + static get template() { + return getTemplate(); + } + + static get properties() { + return { + selectedTab_: { + type: Number, + value: TabDiscardExceptionAddDialogTabs.MANUAL, + }, + + tabNames_: { + type: Array, + value: [ + loadTimeData.getString('tabDiscardingExceptionsAddDialogCurrentTabs'), + loadTimeData.getString('tabDiscardingExceptionsAddDialogManual'), + ], + }, + + submitDisabledList_: Boolean, + submitDisabledManual_: Boolean, + }; + } + + private selectedTab_: TabDiscardExceptionAddDialogTabs; + private tabNames_: string[]; + private submitDisabledList_: boolean; + private submitDisabledManual_: boolean; + + private onSitesPopulated_(e: CustomEvent<{length: number}>) { + if (e.detail.length > 0) { + this.selectedTab_ = TabDiscardExceptionAddDialogTabs.LIST; + } + this.$.dialog.showModal(); + } + + private onCancelClick_() { + this.$.dialog.cancel(); + } + + private onSubmitClick_() { + this.$.dialog.close(); + if (this.selectedTab_ === TabDiscardExceptionAddDialogTabs.MANUAL) { + this.$.input.submit(); + } else { + this.$.list.submit(); + } + } + + private isSubmitDisabled_() { + if (this.selectedTab_ === TabDiscardExceptionAddDialogTabs.MANUAL) { + return this.submitDisabledManual_; + } + return this.submitDisabledList_; + } +} + +declare global { + interface HTMLElementTagNameMap { + 'tab-discard-exception-tabbed-add-dialog': + TabDiscardExceptionTabbedAddDialogElement; + } +} + +customElements.define( + TabDiscardExceptionTabbedAddDialogElement.is, + TabDiscardExceptionTabbedAddDialogElement);
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts index 4e0efe6..ce29834 100644 --- a/chrome/browser/resources/settings/settings.ts +++ b/chrome/browser/resources/settings/settings.ts
@@ -73,6 +73,7 @@ export {TabDiscardExceptionEditDialogElement} from './performance_page/tab_discard_exception_edit_dialog.js'; export {TabDiscardExceptionEntryElement} from './performance_page/tab_discard_exception_entry.js'; export {TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE, TabDiscardExceptionListElement} from './performance_page/tab_discard_exception_list.js'; +export {TabDiscardExceptionAddDialogTabs, TabDiscardExceptionTabbedAddDialogElement} from './performance_page/tab_discard_exception_tabbed_add_dialog.js'; export {MAX_TAB_DISCARD_EXCEPTION_RULE_LENGTH, TAB_DISCARD_EXCEPTIONS_MANAGED_PREF, TAB_DISCARD_EXCEPTIONS_PREF} from './performance_page/tab_discard_exception_validation_mixin.js'; export {PrivacyGuideBrowserProxy, PrivacyGuideBrowserProxyImpl} from './privacy_page/privacy_guide/privacy_guide_browser_proxy.js'; export {SettingsPrivacyPageElement} from './privacy_page/privacy_page.js';
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html index a5de9b5..4748af0 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.html
@@ -91,6 +91,10 @@ margin-top: 40px; } + #folderEmptyState { + margin-bottom: 40px; + } + sp-empty-state[guest] { margin-top: 66px; } @@ -184,7 +188,8 @@ </div> <div class="sp-card" - hidden$="[[shouldHideCard_(labels_.*, searchQuery_, shownBookmarks_)]]"> + hidden$="[[shouldHideCard_(labels_.*, searchQuery_, shownBookmarks_, + guestMode_)]]"> <sp-heading hidden$="[[shouldHideHeader_( labels_.*, searchQuery_, shownBookmarks_)]]" @@ -220,6 +225,15 @@ on-click="onBulkEditClicked_"></cr-icon-button> </sp-heading> + <div class="sp-scroller" hidden="[[shownBookmarks_.length]]"> + <sp-empty-state id="folderEmptyState" + image-path="./images/bookmarks_empty.svg" + dark-image-path="./images/bookmarks_empty_dark.svg" + heading="$i18n{emptyTitleFolder}" + body="$i18n{emptyBodyFolder}"> + </sp-empty-state> + </div> + <div id="bookmarks" class="bookmarks sp-scroller" hidden="[[!shownBookmarks_.length]]" role="[[getBookmarksListRole_(editing_)]]" @@ -274,8 +288,8 @@ </div> </div> - <sp-empty-state - hidden="[[shownBookmarks_.length]]" + <sp-empty-state id="topLevelEmptyState" + hidden="[[!shouldShowTopLevelEmptyState_(shownBookmarks_, guestMode_)]]" guest$="[[guestMode_]]" image-path="[[getEmptyImagePath_(labels_.*, searchQuery_)]]" dark-image-path="[[getEmptyImagePathDark_(labels_.*, searchQuery_)]]"
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts index be48091..eb5862b 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
@@ -27,6 +27,7 @@ import '//resources/cr_elements/icons.html.js'; import '//resources/polymer/v3_0/iron-list/iron-list.js'; +import {SpEmptyStateElement} from '//bookmarks-side-panel.top-chrome/shared/sp_empty_state.js'; import {startColorChangeUpdater} from '//resources/cr_components/color_change_listener/colors_css_updater.js'; import {getInstance as getAnnouncerInstance} from '//resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; import {CrActionMenuElement} from '//resources/cr_elements/cr_action_menu/cr_action_menu.js'; @@ -86,6 +87,8 @@ sortMenu: CrActionMenuElement, editDialog: PowerBookmarksEditDialogElement, disabledFeatureDialog: CrDialogElement, + topLevelEmptyState: SpEmptyStateElement, + folderEmptyState: SpEmptyStateElement, }; } @@ -765,12 +768,19 @@ return false; } - private shouldShowEmptySearchState_() { + private shouldShowEmptySearchState_(): boolean { return this.hasActiveLabels_() || !!this.searchQuery_; } + private shouldShowTopLevelEmptyState_(): boolean { + return this.guestMode_ || + (this.shownBookmarks_.length === 0 && + (!!this.searchQuery_ || this.activeFolderPath_.length === 0)); + } + private shouldHideCard_(): boolean { - return this.shouldHideHeader_() && this.shownBookmarks_.length === 0; + return this.guestMode_ || + (this.shouldHideHeader_() && this.shownBookmarks_.length === 0); } private shouldHideHeader_(): boolean {
diff --git a/chrome/browser/shell_integration_mac.mm b/chrome/browser/shell_integration_mac.mm index 4932c27..7bb33b1e 100644 --- a/chrome/browser/shell_integration_mac.mm +++ b/chrome/browser/shell_integration_mac.mm
@@ -7,7 +7,6 @@ #include <AppKit/AppKit.h> #include <UniformTypeIdentifiers/UniformTypeIdentifiers.h> -#include "base/apple/bridging.h" #include "base/apple/bundle_locations.h" #include "base/mac/foundation_util.h" #include "base/mac/mac_util.h" @@ -18,10 +17,6 @@ #include "components/version_info/version_info.h" #import "net/base/mac/url_conversions.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace shell_integration { namespace { @@ -72,7 +67,7 @@ // We really do want the outer bundle here, not the main bundle since // setting a shortcut to Chrome as the default browser doesn't make sense. CFStringRef identifier = - base::apple::NSToCFPtrCast(base::apple::OuterBundle().bundleIdentifier); + base::mac::NSToCFCast(base::apple::OuterBundle().bundleIdentifier); if (!identifier) { return false; } @@ -145,9 +140,8 @@ } NSString* scheme_ns = base::SysUTF8ToNSString(scheme); - OSStatus return_code = - LSSetDefaultHandlerForURLScheme(base::apple::NSToCFPtrCast(scheme_ns), - base::apple::NSToCFPtrCast(identifier)); + OSStatus return_code = LSSetDefaultHandlerForURLScheme( + base::mac::NSToCFCast(scheme_ns), base::mac::NSToCFCast(identifier)); return return_code == noErr; } } @@ -180,8 +174,9 @@ app_urls = [NSWorkspace.sharedWorkspace URLsForApplicationsToOpenURL:ns_url]; } else { - app_urls = base::apple::CFToNSOwnershipCast(LSCopyApplicationURLsForURL( - base::apple::NSToCFPtrCast(ns_url), kLSRolesAll)); + CFArrayRef urls = + LSCopyApplicationURLsForURL(base::mac::NSToCFCast(ns_url), kLSRolesAll); + app_urls = [base::mac::CFToNSCast(urls) autorelease]; } if (app_urls.count == 0) { @@ -200,8 +195,8 @@ NSURL* ns_item_url = net::NSURLWithGURL(url); NSURL* ns_app_url = base::mac::FilePathToNSURL(app_path); Boolean result = FALSE; - LSCanURLAcceptURL(base::apple::NSToCFPtrCast(ns_item_url), - base::apple::NSToCFPtrCast(ns_app_url), kLSRolesAll, + LSCanURLAcceptURL(base::mac::NSToCFCast(ns_item_url), + base::mac::NSToCFCast(ns_app_url), kLSRolesAll, kLSAcceptDefault, &result); return result; }
diff --git a/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc b/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc index 79523af..81e2106e 100644 --- a/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_webauthn_credentials_sync_test.cc
@@ -273,6 +273,29 @@ .Wait()); } +// Tests that deleting a passkey is persisted across browser restarts. +IN_PROC_BROWSER_TEST_F(SingleClientWebAuthnCredentialsSyncTest, + PRE_DeletingPasskeysPersistsOverRestarts) { + ASSERT_TRUE(SetupSync()); + + sync_pb::WebauthnCredentialSpecifics passkey = NewPasskey(); + GetModel().AddNewPasskeyForTesting(passkey); + EXPECT_TRUE(ServerPasskeysMatchChecker( + UnorderedElementsAre(EntityHasSyncId(passkey.sync_id()))) + .Wait()); + EXPECT_THAT(GetModel().GetAllPasskeys(), + UnorderedElementsAre(PasskeyHasSyncId(passkey.sync_id()))); + GetModel().DeletePasskey(passkey.credential_id()); + EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); +} + +IN_PROC_BROWSER_TEST_F(SingleClientWebAuthnCredentialsSyncTest, + DeletingPasskeysPersistsOverRestarts) { + ASSERT_TRUE(SetupClients()); + ASSERT_TRUE(GetClient(0)->AwaitSyncSetupCompletion()); + EXPECT_TRUE(GetModel().GetAllPasskeys().empty()); +} + IN_PROC_BROWSER_TEST_F(SingleClientWebAuthnCredentialsSyncTest, LegacySyncIdCompatibility) { // Ordinarily, client_tag_hash is derived from the 16-byte `sync_id`.
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 07f558c7..45e3427 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -99,7 +99,6 @@ "//chrome/app:command_ids", "//chrome/app:generated_resources", "//chrome/app/vector_icons", - "//chrome/browser:browser_noarc", "//chrome/browser/autofill", "//chrome/browser/profiles:profile", "//chrome/browser/ui/tabs:tab_enums", @@ -122,7 +121,6 @@ "//ui/views", "//url", ] - allow_circular_includes_from = [ "//chrome/browser:browser_noarc" ] } } @@ -371,6 +369,8 @@ "webui/invalidations/invalidations_ui.h", "webui/local_state/local_state_ui.cc", "webui/local_state/local_state_ui.h", + "webui/location_internals/location_internals_ui.cc", + "webui/location_internals/location_internals_ui.h", "webui/log_web_ui_url.cc", "webui/log_web_ui_url.h", "webui/media/media_engagement_ui.cc", @@ -524,6 +524,7 @@ "//chrome/browser/resources/browsing_topics:resources", "//chrome/browser/resources/internals:resources", "//chrome/browser/resources/invalidations:resources", + "//chrome/browser/resources/location_internals:resources", "//chrome/browser/resources/media:resources", "//chrome/browser/resources/net_internals:resources", "//chrome/browser/resources/omnibox:resources", @@ -4125,13 +4126,11 @@ allow_circular_includes_from += [ ":ui_arc", "//chrome/browser/apps/app_shim", - "//chrome/browser:browser_noarc", ] deps += [ ":ui_arc", "//base:base_arc", - "//chrome/browser:browser_noarc", "//chrome/browser/apps/app_shim", "//chrome/browser/mac:keystone_glue", "//chrome/browser/updater:browser_updater_client",
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxMetrics.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxMetrics.java index dbf1eb63..81081f6 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxMetrics.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/OmniboxMetrics.java
@@ -11,9 +11,6 @@ import org.chromium.base.metrics.TimingMetric; import org.chromium.chrome.browser.omnibox.suggestions.mostvisited.SuggestTileType; import org.chromium.components.metrics.OmniboxEventProtos.OmniboxEventProto.PageClassification; -import org.chromium.components.omnibox.EntityInfoProto.ActionInfo.ActionType; -import org.chromium.components.omnibox.action.ActionInSuggestUmaType; -import org.chromium.components.omnibox.action.OmniboxPedalId; import org.chromium.components.omnibox.suggestions.OmniboxSuggestionUiType; import java.lang.annotation.Retention; @@ -66,9 +63,6 @@ int ACTIVITY_NOT_FOUND = 2; int COUNT = 3; } - // TODO(crbug/1418077) export this from upstream. - // See entity_info.proto, ActionType. - private static final int ACTION_TYPE_COUNT = 20; /** * Record how long the Suggestion List needed to layout its content and children. @@ -175,26 +169,6 @@ } /** - * Record the pedal shown when the user used the omnibox to go somewhere. - * - * @param pedalId the shown pedal's {@link OmniboxActionId}. - */ - public static void recordPedalShown(@OmniboxPedalId int pedalId) { - RecordHistogram.recordEnumeratedHistogram( - "Omnibox.PedalShown", pedalId, OmniboxPedalId.TOTAL_COUNT); - } - - /** - * Record a pedal is used. - * - @param omniboxActionType the clicked pedal's {@link OmniboxActionId}. - */ - public static void recordPedalUsed(@OmniboxPedalId int pedalId) { - RecordHistogram.recordEnumeratedHistogram( - "Omnibox.SuggestionUsed.Pedal", pedalId, OmniboxPedalId.TOTAL_COUNT); - } - - /** * Record page class specific histogram reflecting whether the user scrolled the suggestions * list. * @@ -269,48 +243,6 @@ } /** - * Record the Use of the Omnibox Action in Suggest. - * - * @param actionType the direct value of corresponding {@link - * EntityInfoProto.ActionInfo.ActionType} - * @param isUsed whether the suggestion was clicked - */ - public static void recordActionInSuggestUsed(int actionType) { - RecordHistogram.recordEnumeratedHistogram("Omnibox.ActionInSuggest.Used", - actionTypeToUmaType(actionType), ActionInSuggestUmaType.MAX_VALUE); - } - - /** - * Record the Presence of the Omnibox Action in Suggest. - * - * @param actionType the direct value of corresponding {@link - * EntityInfoProto.ActionInfo.ActionType} - * @param isUsed whether the suggestion was visible - */ - public static void recordActionInSuggestShown(int actionType) { - RecordHistogram.recordEnumeratedHistogram("Omnibox.ActionInSuggest.Shown", - actionTypeToUmaType(actionType), ActionInSuggestUmaType.MAX_VALUE); - } - - /** - * Translate ActionType to ActionInSuggestUmaType. - * - * @param type the type of Action in Suggest to translate. - */ - private static @ActionInSuggestUmaType int actionTypeToUmaType(int type) { - switch (type) { - case ActionType.CALL_VALUE: - return ActionInSuggestUmaType.CALL; - case ActionType.DIRECTIONS_VALUE: - return ActionInSuggestUmaType.DIRECTIONS; - case ActionType.REVIEWS_VALUE: - return ActionInSuggestUmaType.REVIEWS; - default: - return ActionInSuggestUmaType.UNKNOWN; - } - } - - /** * Translate the pageClass to a histogram suffix. * * @param histogram Histogram prefix.
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index 33eedc65..2b1bde4d 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.omnibox.suggestions; import android.content.Context; +import android.content.Intent; import android.content.res.Resources; import android.os.Handler; import android.os.SystemClock; @@ -181,6 +182,11 @@ new DropdownItemViewInfoListManager(mSuggestionModels, context); mClearFocusCallback = this::finishInteraction; OmniboxResourceProvider.invalidateDrawableCache(); + + var pm = context.getPackageManager(); + var dialIntent = new Intent(Intent.ACTION_DIAL); + OmniboxActionFactoryImpl.get().setDialerAvailable( + !pm.queryIntentActivities(dialIntent, 0).isEmpty()); } /**
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersAction.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersAction.java index 462e5eb..a59ae77 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersAction.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersAction.java
@@ -26,8 +26,8 @@ /** Associated user query, guaranteed to be a non-empty string. */ public final @NonNull String query; - public HistoryClustersAction(@NonNull String hint, @NonNull String query) { - super(OmniboxActionId.HISTORY_CLUSTERS, hint, JOURNEYS_ICON); + public HistoryClustersAction(long nativeInstance, @NonNull String hint, @NonNull String query) { + super(OmniboxActionId.HISTORY_CLUSTERS, nativeInstance, hint, JOURNEYS_ICON); assert !TextUtils.isEmpty(query); this.query = query; }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersActionUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersActionUnitTest.java index 9cf3f58..5182692 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersActionUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/HistoryClustersActionUnitTest.java
@@ -33,28 +33,28 @@ @Test public void creation_usesExpectedIcon() { - var action = new HistoryClustersAction("hint", "query"); + var action = new HistoryClustersAction(0, "hint", "query"); assertEquals(HistoryClustersAction.JOURNEYS_ICON, action.icon); } @Test public void creation_failsWithNullHint() { - assertThrows(AssertionError.class, () -> new HistoryClustersAction(null, "query")); + assertThrows(AssertionError.class, () -> new HistoryClustersAction(0, null, "query")); } @Test public void creation_failsWithEmptyHint() { - assertThrows(AssertionError.class, () -> new HistoryClustersAction("", "query")); + assertThrows(AssertionError.class, () -> new HistoryClustersAction(0, "", "query")); } @Test public void creation_failsWithNullQuery() { - assertThrows(AssertionError.class, () -> new HistoryClustersAction("hint", null)); + assertThrows(AssertionError.class, () -> new HistoryClustersAction(0, "hint", null)); } @Test public void creation_failsWithEmptyQuery() { - assertThrows(AssertionError.class, () -> new HistoryClustersAction("hint", "")); + assertThrows(AssertionError.class, () -> new HistoryClustersAction(0, "hint", "")); } @Test @@ -67,7 +67,7 @@ assertThrows(AssertionError.class, () -> HistoryClustersAction.from( - new OmniboxAction(OmniboxActionId.HISTORY_CLUSTERS, "", null) { + new OmniboxAction(OmniboxActionId.HISTORY_CLUSTERS, 0, "", null) { @Override public void execute(OmniboxActionDelegate d) {} })); @@ -76,13 +76,13 @@ @Test public void safeCasting_successWithFactoryBuiltAction() { HistoryClustersAction.from( - OmniboxActionFactoryImpl.get().buildHistoryClustersAction("hint", "query")); + OmniboxActionFactoryImpl.get().buildHistoryClustersAction(0, "hint", "query")); } @Test public void executeHistoryClusters() { String testJourneyName = "example journey name"; - var action = new HistoryClustersAction("hint", testJourneyName); + var action = new HistoryClustersAction(0, "hint", testJourneyName); action.execute(mDelegate); verify(mDelegate).openHistoryClustersPage(testJourneyName); verifyNoMoreInteractions(mDelegate);
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java index 7bd4b1e..8307fb0 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImpl.java
@@ -5,7 +5,9 @@ package org.chromium.chrome.browser.omnibox.suggestions.action; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import org.chromium.components.omnibox.EntityInfoProto; import org.chromium.components.omnibox.action.OmniboxAction; import org.chromium.components.omnibox.action.OmniboxActionFactory; import org.chromium.components.omnibox.action.OmniboxActionFactoryJni; @@ -16,10 +18,17 @@ */ public class OmniboxActionFactoryImpl implements OmniboxActionFactory { private static OmniboxActionFactoryImpl sFactory; + private boolean mDialerAvailable; /** Private constructor to suppress direct instantiation of this class. */ private OmniboxActionFactoryImpl() {} + /** Initialize the factory. Called before native code is ready. */ + public OmniboxActionFactoryImpl setDialerAvailable(boolean dialerAvailable) { + mDialerAvailable = dialerAvailable; + return this; + } + /** * Creates (if not already created) and returns the App-wide instance of the * OmniboxActionFactory. @@ -47,20 +56,23 @@ } @Override - public @NonNull OmniboxAction buildOmniboxPedal( - @NonNull String hint, @OmniboxPedalId int pedalId) { - return new OmniboxPedal(hint, pedalId); + public @Nullable OmniboxAction buildOmniboxPedal( + long nativeInstance, @NonNull String hint, @OmniboxPedalId int pedalId) { + return new OmniboxPedal(nativeInstance, hint, pedalId); } @Override - public @NonNull OmniboxAction buildActionInSuggest(@NonNull String hint, + public @Nullable OmniboxAction buildActionInSuggest(long nativeInstance, @NonNull String hint, /* EntityInfoProto.ActionInfo.ActionType */ int actionType, @NonNull String actionUri) { - return new OmniboxActionInSuggest(hint, actionType, actionUri); + if (actionType == EntityInfoProto.ActionInfo.ActionType.CALL_VALUE && !mDialerAvailable) { + return null; + } + return new OmniboxActionInSuggest(nativeInstance, hint, actionType, actionUri); } @Override - public @NonNull OmniboxAction buildHistoryClustersAction( - @NonNull String hint, @NonNull String query) { - return new HistoryClustersAction(hint, query); + public @Nullable OmniboxAction buildHistoryClustersAction( + long nativeInstance, @NonNull String hint, @NonNull String query) { + return new HistoryClustersAction(nativeInstance, hint, query); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java index 7f83310f..0a176f4 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionFactoryImplUnitTest.java
@@ -6,6 +6,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -22,6 +23,7 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; +import org.chromium.components.omnibox.EntityInfoProto; import org.chromium.components.omnibox.action.OmniboxActionFactoryJni; /** @@ -73,7 +75,7 @@ // The underlying code will throw if instance is not valid. // Checking for null in case that changes. assertNotNull(HistoryClustersAction.from( - OmniboxActionFactoryImpl.get().buildHistoryClustersAction("hint", "query"))); + OmniboxActionFactoryImpl.get().buildHistoryClustersAction(0, "hint", "query"))); } @Test @@ -81,7 +83,7 @@ // The underlying code will throw if instance is not valid. // Checking for null in case that changes. assertNotNull( - OmniboxPedal.from(OmniboxActionFactoryImpl.get().buildOmniboxPedal("hint", 1))); + OmniboxPedal.from(OmniboxActionFactoryImpl.get().buildOmniboxPedal(0, "hint", 1))); } @Test @@ -89,6 +91,18 @@ // The underlying code will throw if instance is not valid. // Checking for null in case that changes. assertNotNull(OmniboxActionInSuggest.from( - OmniboxActionFactoryImpl.get().buildActionInSuggest("hint", 1, "url"))); + OmniboxActionFactoryImpl.get().buildActionInSuggest(0, "hint", 1, "url"))); + } + + @Test + public void actionInSuggest_callActionNotCreatedWhenDialerUnavailable() { + assertNull(OmniboxActionFactoryImpl.get().setDialerAvailable(false).buildActionInSuggest( + 0, "hint", EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "url")); + } + + @Test + public void actionInSuggest_callActionCreatedWhenDialerAvailable() { + assertNotNull(OmniboxActionFactoryImpl.get().setDialerAvailable(true).buildActionInSuggest( + 0, "hint", EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "url")); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java index 0b96c4e..781ccb3 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggest.java
@@ -28,9 +28,10 @@ public final /* EntityInfoProto.ActionInfo.ActionType */ int actionType; private final @NonNull String mActionUri; - public OmniboxActionInSuggest(@NonNull String hint, + public OmniboxActionInSuggest(long nativeInstance, @NonNull String hint, /* EntityInfoProto.ActionInfo.ActionType */ int actionType, @NonNull String actionUri) { - super(OmniboxActionId.ACTION_IN_SUGGEST, hint, ICON_MAP.get(actionType, null)); + super(OmniboxActionId.ACTION_IN_SUGGEST, nativeInstance, hint, + ICON_MAP.get(actionType, null)); this.actionType = actionType; mActionUri = actionUri; } @@ -62,8 +63,6 @@ /** * Execute an Intent associated with OmniboxActionInSuggest. * - * TODO(crbug/1418077): pass the dependencies to constructor and define method in the interface. - * * @param loadPageInCurrentTab loads the page in the current tab (if available), else new tab * @param startActivity starts the activity described by supplied intent */
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java index c6b58aa..fca88f3e 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxActionInSuggestUnitTest.java
@@ -59,7 +59,7 @@ @Test public void creation_usesCustomIconForKnownActionTypes() { for (var kesemActionType : sKnownActionTypes) { - var action = new OmniboxActionInSuggest("hint", kesemActionType, ""); + var action = new OmniboxActionInSuggest(0, "hint", kesemActionType, ""); assertNotEquals(OmniboxAction.DEFAULT_ICON, action.icon); } } @@ -68,7 +68,7 @@ public void creation_usesFallbackIconForUnknownActionTypes() { for (var kesemActionType : EntityInfoProto.ActionInfo.ActionType.values()) { if (sKnownActionTypes.contains(kesemActionType.getNumber())) continue; - var action = new OmniboxActionInSuggest("hint", kesemActionType.getNumber(), ""); + var action = new OmniboxActionInSuggest(0, "hint", kesemActionType.getNumber(), ""); assertEquals(OmniboxAction.DEFAULT_ICON, action.icon); } } @@ -78,7 +78,7 @@ assertThrows(AssertionError.class, () -> new OmniboxActionInSuggest( - null, EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "")); + 0, null, EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "")); } @Test @@ -86,7 +86,7 @@ assertThrows(AssertionError.class, () -> new OmniboxActionInSuggest( - "", EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "")); + 0, "", EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "")); } @Test @@ -98,17 +98,17 @@ public void safeCasting_assertsWithWrongClassType() { assertThrows(AssertionError.class, () - -> OmniboxActionInSuggest.from( - new OmniboxAction(OmniboxActionId.ACTION_IN_SUGGEST, "hint", null) { - @Override - public void execute(OmniboxActionDelegate d) {} - })); + -> OmniboxActionInSuggest.from(new OmniboxAction( + OmniboxActionId.ACTION_IN_SUGGEST, 0, "hint", null) { + @Override + public void execute(OmniboxActionDelegate d) {} + })); } @Test public void safeCasting_successWithFactoryBuiltAction() { OmniboxActionInSuggest.from(OmniboxActionFactoryImpl.get().buildActionInSuggest( - "hint", EntityInfoProto.ActionInfo.ActionType.CALL_VALUE, "")); + 0, "hint", EntityInfoProto.ActionInfo.ActionType.REVIEWS_VALUE, "")); } /** @@ -117,7 +117,7 @@ private OmniboxAction buildActionInSuggest( EntityInfoProto.ActionInfo.ActionType type, Intent intent) { var uri = intent.toUri(Intent.URI_INTENT_SCHEME); - return new OmniboxActionInSuggest("wink", type.getNumber(), uri); + return new OmniboxActionInSuggest(0, "wink", type.getNumber(), uri); } @Test
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java index a28e7bd..9685bcc 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedal.java
@@ -7,7 +7,6 @@ import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import org.chromium.chrome.browser.omnibox.OmniboxMetrics; import org.chromium.components.browser_ui.settings.SettingsLauncher.SettingsFragment; import org.chromium.components.embedder_support.util.UrlConstants; import org.chromium.components.omnibox.R; @@ -26,8 +25,8 @@ /** The type of the underlying pedal. */ public final @OmniboxPedalId int pedalId; - public OmniboxPedal(@NonNull String hint, @OmniboxPedalId int pedalId) { - super(OmniboxActionId.PEDAL, hint, + public OmniboxPedal(long nativeInstance, @NonNull String hint, @OmniboxPedalId int pedalId) { + super(OmniboxActionId.PEDAL, nativeInstance, hint, pedalId == OmniboxPedalId.PLAY_CHROME_DINO_GAME ? DINO_GAME_ICON : null); this.pedalId = pedalId; } @@ -66,7 +65,6 @@ delegate.openIncognitoTab(); break; } - OmniboxMetrics.recordPedalUsed(pedalId); } /**
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java index 26adf4a..39c56787 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/action/OmniboxPedalUnitTest.java
@@ -18,7 +18,6 @@ import org.mockito.junit.MockitoRule; import org.robolectric.annotation.Config; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.components.browser_ui.settings.SettingsLauncher.SettingsFragment; import org.chromium.components.embedder_support.util.UrlConstants; @@ -43,27 +42,27 @@ @Test public void creation_usesExpectedCustomIconForDinoGame() { assertEquals(OmniboxPedal.DINO_GAME_ICON, - new OmniboxPedal("hint", OmniboxPedalId.PLAY_CHROME_DINO_GAME).icon); + new OmniboxPedal(0, "hint", OmniboxPedalId.PLAY_CHROME_DINO_GAME).icon); } @Test public void creation_usesDefaultIconForAllNonCustomizedCases() { for (int type = OmniboxPedalId.NONE; type < OmniboxPedalId.TOTAL_COUNT; type++) { if (sPedalsWithCustomIcons.contains(type)) continue; - assertEquals(OmniboxAction.DEFAULT_ICON, new OmniboxPedal("hint", type).icon); + assertEquals(OmniboxAction.DEFAULT_ICON, new OmniboxPedal(0, "hint", type).icon); } } @Test public void creation_failsWithNullHint() { assertThrows(AssertionError.class, - () -> new OmniboxPedal(null, OmniboxPedalId.CLEAR_BROWSING_DATA)); + () -> new OmniboxPedal(0, null, OmniboxPedalId.CLEAR_BROWSING_DATA)); } @Test public void creation_failsWithEmptyHint() { assertThrows(AssertionError.class, - () -> new OmniboxPedal("", OmniboxPedalId.CLEAR_BROWSING_DATA)); + () -> new OmniboxPedal(0, "", OmniboxPedalId.CLEAR_BROWSING_DATA)); } @Test @@ -74,7 +73,7 @@ @Test public void safeCasting_assertsWithWrongClassType() { assertThrows(AssertionError.class, - () -> OmniboxPedal.from(new OmniboxAction(OmniboxActionId.PEDAL, "", null) { + () -> OmniboxPedal.from(new OmniboxAction(OmniboxActionId.PEDAL, 0, "", null) { @Override public void execute(OmniboxActionDelegate d) {} })); @@ -83,100 +82,76 @@ @Test public void safeCasting_successWithFactoryBuiltAction() { OmniboxPedal.from( - OmniboxActionFactoryImpl.get().buildOmniboxPedal("hint", OmniboxPedalId.NONE)); - } - - /** - * Verify that a histogram recording the use of particular type of OmniboxPedal has been - * recorded. - * - * @param type The type of Pedal to check for. - */ - private void checkOmniboxPedalUsageRecorded(@OmniboxPedalId int type) { - assertEquals(1, - RecordHistogram.getHistogramValueCountForTesting( - "Omnibox.SuggestionUsed.Pedal", type)); - assertEquals(1, - RecordHistogram.getHistogramTotalCountForTesting("Omnibox.SuggestionUsed.Pedal")); + OmniboxActionFactoryImpl.get().buildOmniboxPedal(0, "hint", OmniboxPedalId.NONE)); } @Test public void executePedal_manageChromeSettings() { - new OmniboxPedal("hint", OmniboxPedalId.MANAGE_CHROME_SETTINGS).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.MANAGE_CHROME_SETTINGS).execute(mDelegate); verify(mDelegate, times(1)).openSettingsPage(SettingsFragment.MAIN); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.MANAGE_CHROME_SETTINGS); } @Test public void executePedal_clearBrowsingData() { - new OmniboxPedal("hint", OmniboxPedalId.CLEAR_BROWSING_DATA).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.CLEAR_BROWSING_DATA).execute(mDelegate); verify(mDelegate, times(1)).openSettingsPage(SettingsFragment.CLEAR_BROWSING_DATA); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.CLEAR_BROWSING_DATA); } @Test public void executePedal_managePasswords() { - new OmniboxPedal("hint", OmniboxPedalId.MANAGE_PASSWORDS).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.MANAGE_PASSWORDS).execute(mDelegate); verify(mDelegate, times(1)).openPasswordManager(); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.MANAGE_PASSWORDS); } @Test public void executePedal_updateCreditCard() { - new OmniboxPedal("hint", OmniboxPedalId.UPDATE_CREDIT_CARD).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.UPDATE_CREDIT_CARD).execute(mDelegate); verify(mDelegate, times(1)).openSettingsPage(SettingsFragment.PAYMENT_METHODS); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.UPDATE_CREDIT_CARD); } @Test public void executePedal_runChromeSafetyCheck() { - new OmniboxPedal("hint", OmniboxPedalId.RUN_CHROME_SAFETY_CHECK).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.RUN_CHROME_SAFETY_CHECK).execute(mDelegate); verify(mDelegate, times(1)).openSettingsPage(SettingsFragment.SAFETY_CHECK); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.RUN_CHROME_SAFETY_CHECK); } @Test public void executePedal_manageSiteSettings() { - new OmniboxPedal("hint", OmniboxPedalId.MANAGE_SITE_SETTINGS).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.MANAGE_SITE_SETTINGS).execute(mDelegate); verify(mDelegate, times(1)).openSettingsPage(SettingsFragment.SITE); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.MANAGE_SITE_SETTINGS); } @Test public void executePedal_manageChromeAccessibility() { - new OmniboxPedal("hint", OmniboxPedalId.MANAGE_CHROME_ACCESSIBILITY).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.MANAGE_CHROME_ACCESSIBILITY).execute(mDelegate); verify(mDelegate, times(1)).openSettingsPage(SettingsFragment.ACCESSIBILITY); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.MANAGE_CHROME_ACCESSIBILITY); } @Test public void executePedal_launchIncognito() { - new OmniboxPedal("hint", OmniboxPedalId.LAUNCH_INCOGNITO).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.LAUNCH_INCOGNITO).execute(mDelegate); verify(mDelegate, times(1)).openIncognitoTab(); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.LAUNCH_INCOGNITO); } @Test public void executePedal_viewChromeHistory() { - new OmniboxPedal("hint", OmniboxPedalId.VIEW_CHROME_HISTORY).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.VIEW_CHROME_HISTORY).execute(mDelegate); verify(mDelegate, times(1)).loadPageInCurrentTab(UrlConstants.HISTORY_URL); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.VIEW_CHROME_HISTORY); } @Test public void executePedal_playChromeDinoGame() { - new OmniboxPedal("hint", OmniboxPedalId.PLAY_CHROME_DINO_GAME).execute(mDelegate); + new OmniboxPedal(0, "hint", OmniboxPedalId.PLAY_CHROME_DINO_GAME).execute(mDelegate); verify(mDelegate, times(1)).loadPageInCurrentTab(UrlConstants.CHROME_DINO_URL); verifyNoMoreInteractions(mDelegate); - checkOmniboxPedalUsageRecorded(OmniboxPedalId.PLAY_CHROME_DINO_GAME); } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapter.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapter.java index bdbe385..0fadb3f 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapter.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapter.java
@@ -18,8 +18,6 @@ /** ModelListAdapter for Omnibox Suggestion Action Chips. */ public class ActionChipsAdapter extends SimpleRecyclerViewAdapter { @VisibleForTesting - // The 0th element is always the lead-in header. - public static final int FIRST_CHIP_INDEX = 1; private int mSelectedItem = RecyclerView.NO_POSITION; private LayoutManager mLayoutManager; @@ -56,7 +54,7 @@ @VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE) public void selectNextItem() { // Rotate: Nothing -> First chip -> ... -> Last chip -> Nothing. - var nextItem = FIRST_CHIP_INDEX; + var nextItem = 0; if (mSelectedItem != RecyclerView.NO_POSITION) nextItem = mSelectedItem + 1; if (nextItem >= getItemCount()) nextItem = RecyclerView.NO_POSITION; setSelectedItem(nextItem); @@ -69,7 +67,7 @@ public void selectPreviousItem() { // Rotate: Nothing -> Last chip -> ... -> First chip -> Nothing. var prevItem = RecyclerView.NO_POSITION; - if (mSelectedItem > FIRST_CHIP_INDEX) prevItem = mSelectedItem - 1; + if (mSelectedItem > 0) prevItem = mSelectedItem - 1; if (mSelectedItem == RecyclerView.NO_POSITION) prevItem = getItemCount() - 1; setSelectedItem(prevItem); } @@ -81,8 +79,7 @@ */ @VisibleForTesting public void setSelectedItem(int index) { - assert index == RecyclerView.NO_POSITION - || (index >= FIRST_CHIP_INDEX && index < getItemCount()); + assert index >= RecyclerView.NO_POSITION && index < getItemCount(); assert mLayoutManager != null; View previousSelectedView = getSelectedView();
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapterUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapterUnitTest.java index d697452b..1495a855 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapterUnitTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsAdapterUnitTest.java
@@ -36,10 +36,9 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class ActionChipsAdapterUnitTest { - private static final int HEADER_INDEX = 0; - private static final int CHIP_1_INDEX = 1; - private static final int CHIP_2_INDEX = 2; - private static final int CHIP_3_WITH_NO_VIEW_INDEX = 3; + private static final int CHIP_1_INDEX = 0; + private static final int CHIP_2_INDEX = 1; + private static final int CHIP_3_WITH_NO_VIEW_INDEX = 2; public @Rule MockitoRule mMockitoRule = MockitoJUnit.rule(); private @Mock View mHeader; private @Mock View mChip1; @@ -52,22 +51,17 @@ @Before public void setUp() { - // Header - mModel.add(new ListItem( - ActionChipsProperties.ViewType.HEADER, new PropertyModel(ChipProperties.ALL_KEYS))); - doReturn(mHeader).when(mLayoutManager).findViewByPosition(HEADER_INDEX); - - // Chip with View, 1 + // Chip with View, 0 mModel.add(new ListItem( ActionChipsProperties.ViewType.CHIP, new PropertyModel(ChipProperties.ALL_KEYS))); doReturn(mChip1).when(mLayoutManager).findViewByPosition(CHIP_1_INDEX); - // Chip with View, 2 + // Chip with View, 1 mModel.add(new ListItem( ActionChipsProperties.ViewType.CHIP, new PropertyModel(ChipProperties.ALL_KEYS))); doReturn(mChip2).when(mLayoutManager).findViewByPosition(CHIP_2_INDEX); - // Chip with no View, 3 + // Chip with no View, 2 mModel.add(new ListItem( ActionChipsProperties.ViewType.CHIP, new PropertyModel(ChipProperties.ALL_KEYS))); @@ -125,11 +119,6 @@ mAdapter.setSelectedItem(mAdapter.getItemCount()); } - @Test(expected = AssertionError.class) - public void setSelectedItem_rejectHeaderView() { - mAdapter.setSelectedItem(0); - } - // The following tests build on top of the setSelectedItem tests. // The method setSelectedItem stays at the heart of all of the functionality below // and is tested thoroughly by dedicated tests.
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsBinder.java index a05effd9..3217f712 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsBinder.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsBinder.java
@@ -9,7 +9,6 @@ import androidx.annotation.NonNull; -import org.chromium.chrome.browser.omnibox.OmniboxFeatures; import org.chromium.chrome.browser.omnibox.R; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; @@ -35,8 +34,6 @@ if (chipList != null) { adapter = new ActionChipsAdapter(chipList); - adapter.registerType(ActionChipsProperties.ViewType.HEADER, - ActionChipsBinder::createHeaderView, NOOP_BINDER); adapter.registerType(ActionChipsProperties.ViewType.CHIP, parent -> createChipView(parent, isIncognito), ChipViewBinder::bind); actionChipsVisibility = View.VISIBLE; @@ -46,30 +43,6 @@ } } - /** - * Create a view element that provides horizontal alignment. - */ - private static View createHeaderView(@NonNull ViewGroup parent) { - var res = parent.getResources(); - - boolean showModernizedSuggestionsList = - OmniboxFeatures.shouldShowModernizeVisualUpdate(parent.getContext()); - - int actionChipHeaderWidth = - res.getDimensionPixelSize(showModernizedSuggestionsList - ? R.dimen.omnibox_suggestion_icon_area_size_modern - : R.dimen.omnibox_suggestion_icon_area_size) - - - // We apply spacing to every element, 1/2 on the left and 1/2 on the right. - // Lead-in header receives both left and right spacing, but we also need to erase - // the space before the first chip. - res.getDimensionPixelSize(R.dimen.omnibox_action_chip_spacing) * 3 / 2; - - var view = new View(parent.getContext()); - view.setMinimumWidth(actionChipHeaderWidth); - return view; - } - public static ChipView createChipView(@NonNull ViewGroup parent, boolean isIncognito) { return new ChipView(parent.getContext(), isIncognito ? R.style.OmniboxIncognitoActionChipThemeOverlay
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java index e164ecd..f9f3d55 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProcessor.java
@@ -5,39 +5,30 @@ package org.chromium.chrome.browser.omnibox.suggestions.base; import android.content.Context; -import android.content.Intent; -import android.util.SparseBooleanArray; +import android.util.ArrayMap; import androidx.annotation.NonNull; -import androidx.collection.ArraySet; +import androidx.annotation.Nullable; -import org.chromium.chrome.browser.omnibox.OmniboxMetrics; import org.chromium.chrome.browser.omnibox.R; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionHost; -import org.chromium.chrome.browser.omnibox.suggestions.action.OmniboxActionInSuggest; -import org.chromium.chrome.browser.omnibox.suggestions.action.OmniboxPedal; import org.chromium.components.browser_ui.widget.chips.ChipProperties; import org.chromium.components.omnibox.AutocompleteMatch; -import org.chromium.components.omnibox.EntityInfoProto; import org.chromium.components.omnibox.action.OmniboxAction; -import org.chromium.components.omnibox.action.OmniboxActionId; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.PropertyModel; -import java.util.Set; - /** * A class that handles model creation for the Action Chips. */ public class ActionChipsProcessor { private final @NonNull Context mContext; private final @NonNull SuggestionHost mSuggestionHost; - private final @NonNull Set<Integer> mLastVisiblePedals = new ArraySet<>(); - private final @NonNull SparseBooleanArray mActionInSuggestShownOrUsed = - new SparseBooleanArray(); - private final boolean mDialerAvailable; - private int mJourneysActionShownPosition = -1; + private final @NonNull ArrayMap<OmniboxAction, Integer> mVisibleActions; + + /** The action that was executed, or null if no action was executed by the user. */ + private @Nullable OmniboxAction mExecutedAction; /** * @param context An Android context. @@ -46,21 +37,21 @@ public ActionChipsProcessor(@NonNull Context context, @NonNull SuggestionHost suggestionHost) { mContext = context; mSuggestionHost = suggestionHost; - - // TODO(crbug/1418077): Migrate this to OmniboxActionInSuggest along with execute logic. - var pm = mContext.getPackageManager(); - var dialIntent = new Intent(Intent.ACTION_DIAL); - mDialerAvailable = !pm.queryIntentActivities(dialIntent, 0).isEmpty(); + mVisibleActions = new ArrayMap<>(); } public void onUrlFocusChange(boolean hasFocus) { - if (!hasFocus) { - recordActionsShown(); + if (hasFocus) { + return; } + mVisibleActions.forEach((OmniboxAction action, Integer position) -> { + action.recordActionShown(position, action == mExecutedAction); + }); + mVisibleActions.clear(); } public void onSuggestionsReceived() { - mActionInSuggestShownOrUsed.clear(); + mVisibleActions.clear(); } /** @@ -79,14 +70,7 @@ var actionChipList = suggestion.getActions(); var modelList = new ModelList(); - // The header item increases lead-in padding before the first actual chip is shown. - // In default state, the chips will align with the suggestion text, but when scrolled - // the chips may show up under the decoration. - modelList.add(new ListItem(ActionChipsProperties.ViewType.HEADER, new PropertyModel())); - for (OmniboxAction chip : actionChipList) { - if (!actionSupported(chip)) continue; - final var chipModel = new PropertyModel.Builder(ChipProperties.ALL_KEYS) .with(ChipProperties.TEXT, chip.hint) @@ -100,95 +84,21 @@ .build(); modelList.add(new ListItem(ActionChipsProperties.ViewType.CHIP, chipModel)); - - // TODO(crbug/1418077): Move this to appropriate implementations. - switch (chip.actionId) { - case OmniboxActionId.PEDAL: - mLastVisiblePedals.add(OmniboxPedal.from(chip).pedalId); - break; - - case OmniboxActionId.HISTORY_CLUSTERS: - mJourneysActionShownPosition = position; - break; - - case OmniboxActionId.ACTION_IN_SUGGEST: - var actionType = OmniboxActionInSuggest.from(chip).actionType; - mActionInSuggestShownOrUsed.put(actionType, false); - break; - } + mVisibleActions.put(chip, position); } model.set(ActionChipsProperties.ACTION_CHIPS, modelList); } private boolean doesProcessSuggestion(AutocompleteMatch suggestion, int position) { - // TODO(crbug/1418077): Migrate this to OmniboxActionInSuggest along with execute logic. - for (int index = 0; index < suggestion.getActions().size(); ++index) { - if (actionSupported(suggestion.getActions().get(index))) return true; - } - - return false; - } - - /** - * Evaluates whether a given action is supported. - * TODO(crbug/1418077): Migrate this to OmniboxActionInSuggest along with execute logic. - */ - private boolean actionSupported(@NonNull OmniboxAction action) { - switch (action.actionId) { - case OmniboxActionId.PEDAL: - case OmniboxActionId.HISTORY_CLUSTERS: - return true; - - case OmniboxActionId.ACTION_IN_SUGGEST: - return OmniboxActionInSuggest.from(action).actionType - != EntityInfoProto.ActionInfo.ActionType.CALL_VALUE - || mDialerAvailable; - } - return false; + return !suggestion.getActions().isEmpty(); } /** * Invoke action associated with the ActionChip. - * - * TODO(crbug/1418077): Move this to appropriate implementations. */ private void executeAction(@NonNull OmniboxAction action, int position) { - switch (action.actionId) { - case OmniboxActionId.HISTORY_CLUSTERS: - OmniboxMetrics.recordResumeJourneyClick(position); - break; - - case OmniboxActionId.ACTION_IN_SUGGEST: - var actionType = OmniboxActionInSuggest.from(action).actionType; - mActionInSuggestShownOrUsed.put(actionType, true); - break; - } + mExecutedAction = action; mSuggestionHost.onOmniboxActionClicked(action); } - - /** - * Record the actions shown for all action types (Journeys + any pedals). - * - * TODO(crbug/1418077): Move this to appropriate implementations. - */ - private void recordActionsShown() { - for (Integer pedal : mLastVisiblePedals) { - OmniboxMetrics.recordPedalShown(pedal); - } - - for (var actionIndex = 0; actionIndex < mActionInSuggestShownOrUsed.size(); actionIndex++) { - int actionType = mActionInSuggestShownOrUsed.keyAt(actionIndex); - boolean wasUsed = mActionInSuggestShownOrUsed.valueAt(actionIndex); - OmniboxMetrics.recordActionInSuggestShown(actionType); - if (wasUsed) { - OmniboxMetrics.recordActionInSuggestUsed(actionType); - } - } - - OmniboxMetrics.recordResumeJourneyShown(mJourneysActionShownPosition); - - mJourneysActionShownPosition = -1; - mLastVisiblePedals.clear(); - } }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProperties.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProperties.java index 77966d8..5903f10 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProperties.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsProperties.java
@@ -22,13 +22,11 @@ * Views below can be used by any instance of the carousel, guaranteeing that each instance * will look like every other. */ - @IntDef({ViewType.HEADER, ViewType.CHIP}) + @IntDef({ViewType.CHIP}) @Retention(RetentionPolicy.SOURCE) public @interface ViewType { - /** Header element, used to provide leading space. */ - public int HEADER = 0; /** Carousel item is a PedalView instance. */ - public int CHIP = 1; + public int CHIP = 0; } /** Action Chip descriptors. */
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsView.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsView.java index fa7cec4..47aea049 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsView.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/ActionChipsView.java
@@ -15,6 +15,7 @@ import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView.ItemDecoration; +import org.chromium.chrome.browser.omnibox.OmniboxFeatures; import org.chromium.chrome.browser.omnibox.R; import org.chromium.chrome.browser.util.KeyNavigationUtil; import org.chromium.components.browser_ui.widget.chips.ChipView; @@ -40,6 +41,16 @@ setMinimumHeight(getResources().getDimensionPixelSize( R.dimen.omnibox_action_chips_container_height)); + boolean showModernizedSuggestionsList = + OmniboxFeatures.shouldShowModernizeVisualUpdate(context); + setPaddingRelative(getResources().getDimensionPixelSize(showModernizedSuggestionsList + ? R.dimen.omnibox_suggestion_icon_area_size_modern + : R.dimen.omnibox_suggestion_icon_area_size), + 0, 0, + getResources().getDimensionPixelSize(R.dimen.omnibox_suggestion_content_padding)); + // Permit Actions to scroll through the padding area (I know, right?). + setClipToPadding(false); + final @Px int actionChipSpacing = getResources().getDimensionPixelSize(R.dimen.omnibox_action_chip_spacing); addItemDecoration(new ItemDecoration() { @@ -50,9 +61,6 @@ outRect.left = actionChipSpacing / 2; } }); - - setPaddingRelative(0, 0, 0, - getResources().getDimensionPixelSize(R.dimen.omnibox_suggestion_content_padding)); } @Override
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java index 48dac0f1..acb1de9 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinder.java
@@ -37,7 +37,6 @@ import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action; import org.chromium.chrome.browser.ui.theme.BrandedColorScheme; import org.chromium.components.browser_ui.styles.ChromeColors; -import org.chromium.components.browser_ui.widget.RoundedCornerOutlineProvider; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder; @@ -103,7 +102,8 @@ updateColorScheme(model, view); } else if (DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED == propertyKey || DropdownCommonProperties.BG_TOP_CORNER_ROUNDED == propertyKey) { - roundSuggestionViewCorners(model, view); + view.setRoundingEdges(model.get(DropdownCommonProperties.BG_TOP_CORNER_ROUNDED), + model.get(DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED)); } else if (DropdownCommonProperties.TOP_MARGIN == propertyKey || DropdownCommonProperties.BOTTOM_MARGIN == propertyKey) { updateMargin(model, view); @@ -354,43 +354,6 @@ view.setLayoutParams(layoutParams); } - /** - * Round top/bottom suggestion view corners to mark suggestions that begin or end section -- or - * are standalone suggestions. - * - * The rounding mechanism utilizes OutlineProviders to guarantee that focus and selection won't - * leak outside of the rounded edges. - * - * @param model A property model, defining which corners (specifically: corners along which - * edge) should be rounded, - * @param view The view that should receive rounding. - */ - private static void roundSuggestionViewCorners(PropertyModel model, View view) { - var roundTopEdge = model.get(DropdownCommonProperties.BG_TOP_CORNER_ROUNDED); - var roundBottomEdge = model.get(DropdownCommonProperties.BG_BOTTOM_CORNER_ROUNDED); - - if (!roundTopEdge && !roundBottomEdge) { - // Note: Suggestion views are re-used. Make sure we don't carry over rounding from - // previous model. - view.setClipToOutline(false); - return; - } - - // TODO(crbug.com/1418077): This should be part of BaseSuggestionView. - // Move this once we reconcile Pedals with Base. - var outlineProvider = view.getOutlineProvider(); - if (!(outlineProvider instanceof RoundedCornerOutlineProvider)) { - outlineProvider = - new RoundedCornerOutlineProvider(view.getResources().getDimensionPixelSize( - R.dimen.omnibox_suggestion_bg_round_corner_radius)); - view.setOutlineProvider(outlineProvider); - } - RoundedCornerOutlineProvider roundedCornerOutlineProvider = - (RoundedCornerOutlineProvider) outlineProvider; - roundedCornerOutlineProvider.setRoundingEdges(true, roundTopEdge, true, roundBottomEdge); - view.setClipToOutline(true); - } - @VisibleForTesting static void initializeDimensions(Context context) { boolean showModernizeVisualUpdate =
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/HistoryClustersProcessorTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/HistoryClustersProcessorTest.java index d52ede2..7ac6722 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/HistoryClustersProcessorTest.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/HistoryClustersProcessorTest.java
@@ -134,7 +134,7 @@ return AutocompleteMatchBuilder.searchWithType(OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED) .setDisplayText(query) .setIsSearch(true) - .setActions(Arrays.asList(new HistoryClustersAction("hint", query))) + .setActions(Arrays.asList(new HistoryClustersAction(0, "hint", query))) .build(); }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionLayout.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionLayout.java index 93562d2..fdb16ab 100644 --- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionLayout.java +++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionLayout.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.omnibox.OmniboxFeatures; import org.chromium.chrome.browser.omnibox.R; +import org.chromium.components.browser_ui.widget.RoundedCornerOutlineProvider; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -35,6 +36,7 @@ public final @Px int mCompactContentHeightPx; private final @Px int mActionButtonWidthPx; private final @Px int mContentPaddingPx; + private final @NonNull RoundedCornerOutlineProvider mOutlineProvider; /** * SuggestionLayout's LayoutParams. @@ -155,6 +157,15 @@ mContentPaddingPx = getResources().getDimensionPixelSize(R.dimen.omnibox_suggestion_content_padding); + + mOutlineProvider = new RoundedCornerOutlineProvider(getResources().getDimensionPixelSize( + R.dimen.omnibox_suggestion_bg_round_corner_radius)); + setOutlineProvider(mOutlineProvider); + } + + public void setRoundingEdges(boolean roundTopEdge, boolean roundBottomEdge) { + mOutlineProvider.setRoundingEdges(true, roundTopEdge, true, roundBottomEdge); + setClipToOutline(roundTopEdge || roundBottomEdge); } @Override
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 547db2c..c2b9d910f 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_browsertest.cc
@@ -32,6 +32,7 @@ #include "ash/wm/desks/desks_controller.h" #include "ash/wm/desks/desks_test_util.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" +#include "base/auto_reset.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" @@ -637,10 +638,7 @@ class UnpinnedBrowserShortcutTest : public extensions::ExtensionBrowserTest { protected: - UnpinnedBrowserShortcutTest() { - scoped_feature_list_.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary}, {}); - } + UnpinnedBrowserShortcutTest() = default; UnpinnedBrowserShortcutTest(const UnpinnedBrowserShortcutTest&) = delete; UnpinnedBrowserShortcutTest& operator=(const UnpinnedBrowserShortcutTest&) = delete; @@ -662,7 +660,8 @@ raw_ptr<ChromeShelfController, ExperimentalAsh> controller_ = nullptr; private: - base::test::ScopedFeatureList scoped_feature_list_; + const base::AutoReset<absl::optional<bool>> set_lacros_primary_ = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); }; IN_PROC_BROWSER_TEST_F(UnpinnedBrowserShortcutTest, UnpinnedBrowserShortcut) {
diff --git a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc index f115664e7..2af1489 100644 --- a/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc +++ b/chrome/browser/ui/ash/shelf/chrome_shelf_controller_unittest.cc
@@ -37,6 +37,7 @@ #include "ash/public/cpp/window_properties.h" #include "ash/shelf/shelf_application_menu_model.h" #include "ash/webui/system_apps/public/system_web_app_type.h" +#include "base/auto_reset.h" #include "base/check.h" #include "base/check_op.h" #include "base/command_line.h" @@ -1393,10 +1394,7 @@ class ChromeShelfControllerLacrosPrimaryTest : public ChromeShelfControllerLacrosTest { public: - ChromeShelfControllerLacrosPrimaryTest() { - scoped_feature_list_.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary}, {}); - } + ChromeShelfControllerLacrosPrimaryTest() = default; ChromeShelfControllerLacrosPrimaryTest( const ChromeShelfControllerLacrosPrimaryTest&) = delete; ChromeShelfControllerLacrosPrimaryTest& operator=( @@ -1442,11 +1440,11 @@ apps::AppServiceProxy* proxy() { return proxy_; } private: + base::AutoReset<absl::optional<bool>> set_lacros_primary_ = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); raw_ptr<StandaloneBrowserExtensionAppShelfItemController, ExperimentalAsh> chrome_app_shelf_item_ = nullptr; raw_ptr<apps::AppServiceProxy, ExperimentalAsh> proxy_ = nullptr; - - base::test::ScopedFeatureList scoped_feature_list_; }; // A V1 windowed application.
diff --git a/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc b/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc index 5968ffb6..7831981 100644 --- a/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc +++ b/chrome/browser/ui/ash/user_education/welcome_tour/welcome_tour_interactive_uitest.cc
@@ -3,21 +3,47 @@ // found in the LICENSE file. #include "ash/constants/ash_features.h" +#include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/user_education/user_education_constants.h" -#include "ash/user_education/user_education_util.h" #include "ash/user_education/views/help_bubble_view_ash.h" #include "ash/user_education/welcome_tour/welcome_tour_controller.h" #include "base/test/scoped_feature_list.h" +#include "chrome/browser/ash/app_list/app_list_client_impl.h" +#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/test/interaction/interactive_browser_test.h" #include "components/strings/grit/components_strings.h" #include "content/public/test/browser_test.h" +#include "ui/aura/window.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/display/display.h" -#include "ui/display/screen.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/label.h" #include "ui/views/interaction/element_tracker_views.h" +#include "ui/views/view_class_properties.h" +#include "ui/views/widget/widget.h" + +namespace { + +// Aliases. +using ::testing::AllOf; +using ::testing::Eq; +using ::testing::Matches; +using ::testing::Property; + +// Matchers -------------------------------------------------------------------- + +MATCHER_P(ElementIdentifier, matcher, "") { + return Matches(matcher)(arg->GetProperty(views::kElementIdentifierKey)); +} + +MATCHER_P(RootWindow, matcher, "") { + return Matches(matcher)(arg->GetWidget()->GetNativeWindow()->GetRootWindow()); +} + +} // namespace // WelcomeTourInteractiveUiTest ------------------------------------------------ @@ -39,6 +65,14 @@ void SetUpOnMainThread() override { InteractiveBrowserTest::SetUpOnMainThread(); + // Install system apps. + // NOTE: This test requires the "Help" and "Settings" apps to be installed. + Profile* const profile = ProfileManager::GetActiveUserProfile(); + web_app::test::WaitUntilReady(web_app::WebAppProvider::GetForTest(profile)); + ash::SystemWebAppManager::GetForTest(profile) + ->InstallSystemAppsForTesting(); + AppListClientImpl::GetInstance()->UpdateProfile(); + // Ensure that the widget context for the test interaction sequence matches // the initial element context used to start the Welcome Tour. SetContextWidget( @@ -46,26 +80,23 @@ ash::WelcomeTourController::Get()->GetInitialElementContext())); } - // Returns a builder for an interaction step that runs `steps` in the context - // for a matching view in the primary root window for the specified - // `element_id`. If there are multiple matches, this method does *not* - // guarantee which context will be selected. - [[nodiscard]] auto InMatchingViewInPrimaryRootWindowContext( - ui::ElementIdentifier element_id, - MultiStep steps) { - return InContext( - views::ElementTrackerViews::GetContextForView( - ash::user_education_util::GetMatchingViewInRootWindow( - display::Screen::GetScreen()->GetPrimaryDisplay().id(), - element_id)), - std::move(steps)); - } - // Returns a builder for an interaction step that waits for a help bubble. [[nodiscard]] static auto WaitForHelpBubble() { return WaitForShow(ash::HelpBubbleViewAsh::kHelpBubbleElementIdForTesting); } + // Returns a builder for an interaction step that checks that the anchor of a + // help bubble (a) matches the specified `element_id`, and (b) is contained + // within the primary root window. + [[nodiscard]] static auto CheckHelpBubbleAnchor( + ui::ElementIdentifier element_id) { + return CheckViewProperty<ash::HelpBubbleViewAsh, views::View*>( + ash::HelpBubbleViewAsh::kHelpBubbleElementIdForTesting, + &ash::HelpBubbleViewAsh::GetAnchorView, + AllOf(ElementIdentifier(Eq(element_id)), + RootWindow(Eq(ash::Shell::GetPrimaryRootWindow())))); + } + // Returns a builder for an interaction step that checks that the body text of // a help bubble matches the specified `message_id`. [[nodiscard]] static auto CheckHelpBubbleBodyText(int message_id) { @@ -98,42 +129,55 @@ IN_PROC_BROWSER_TEST_F(WelcomeTourInteractiveUiTest, WelcomeTour) { RunTestSequence( // Step 1: Shelf. - InMatchingViewInPrimaryRootWindowContext( - ash::kShelfViewElementId, - Steps(WaitForHelpBubble(), - CheckHelpBubbleBodyText( - IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT), - CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), - PressHelpBubbleDefaultButton())), + InAnyContext(WaitForHelpBubble()), + InSameContext(Steps( + CheckHelpBubbleAnchor(ash::kShelfViewElementId), + CheckHelpBubbleBodyText(IDS_ASH_WELCOME_TOUR_SHELF_BUBBLE_BODY_TEXT), + CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), + PressHelpBubbleDefaultButton(), FlushEvents())), // Step 2: Status area. - InMatchingViewInPrimaryRootWindowContext( - ash::kUnifiedSystemTrayElementId, - Steps(WaitForHelpBubble(), + InAnyContext(WaitForHelpBubble()), + InSameContext( + Steps(CheckHelpBubbleAnchor(ash::kUnifiedSystemTrayElementId), CheckHelpBubbleBodyText( IDS_ASH_WELCOME_TOUR_STATUS_AREA_BUBBLE_BODY_TEXT), CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), - PressHelpBubbleDefaultButton())), + PressHelpBubbleDefaultButton(), FlushEvents())), // Step 3: Home button. - InMatchingViewInPrimaryRootWindowContext( - ash::kHomeButtonElementId, - Steps(WaitForHelpBubble(), + InAnyContext(WaitForHelpBubble()), + InSameContext( + Steps(CheckHelpBubbleAnchor(ash::kHomeButtonElementId), CheckHelpBubbleBodyText( IDS_ASH_WELCOME_TOUR_HOME_BUTTON_BUBBLE_BODY_TEXT), CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), - PressHelpBubbleDefaultButton())), + PressHelpBubbleDefaultButton(), FlushEvents())), // Step 4: Search box. - InAnyContext( - Steps(WaitForHelpBubble(), + InAnyContext(WaitForHelpBubble()), + InSameContext( + Steps(CheckHelpBubbleAnchor(ash::kSearchBoxViewElementId), CheckHelpBubbleBodyText( IDS_ASH_WELCOME_TOUR_SEARCH_BOX_BUBBLE_BODY_TEXT), CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), - PressHelpBubbleDefaultButton())) + PressHelpBubbleDefaultButton(), FlushEvents())), - // TODO(http://b:275616974): Implement after registering views. // Step 5: Settings app. + InAnyContext(WaitForHelpBubble()), + InSameContext( + Steps(CheckHelpBubbleAnchor(ash::kSettingsAppElementId), + CheckHelpBubbleBodyText( + IDS_ASH_WELCOME_TOUR_SETTINGS_APP_BUBBLE_BODY_TEXT), + CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_NEXT_BUTTON), + PressHelpBubbleDefaultButton(), FlushEvents())), + // Step 6: Explore app. - ); + InAnyContext(WaitForHelpBubble()), + InSameContext( + Steps(CheckHelpBubbleAnchor(ash::kExploreAppElementId), + CheckHelpBubbleBodyText( + IDS_ASH_WELCOME_TOUR_EXPLORE_APP_BUBBLE_BODY_TEXT), + CheckHelpBubbleDefaultButtonText(IDS_TUTORIAL_CLOSE_TUTORIAL), + PressHelpBubbleDefaultButton(), FlushEvents()))); }
diff --git a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc index ee979e3..6238b699 100644 --- a/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc +++ b/chrome/browser/ui/bookmarks/bookmark_context_menu_controller_unittest.cc
@@ -109,17 +109,6 @@ ASSERT_FALSE(model_->IsBookmarked(url)); } -// Tests open all on a folder with a couple of bookmarks. -TEST_F(BookmarkContextMenuControllerTest, OpenAll) { - const BookmarkNode* folder = model_->bookmark_bar_node()->children()[1].get(); - chrome::OpenAllNow(nullptr, {folder}, - WindowOpenDisposition::NEW_FOREGROUND_TAB, nullptr); - - // Should have navigated to F1's child, but not F11's child. - ASSERT_EQ(1u, wrapper_.urls().size()); - ASSERT_TRUE(folder->children()[0]->url() == wrapper_.urls()[0]); -} - // Tests the enabled state of the menus when supplied an empty vector. TEST_F(BookmarkContextMenuControllerTest, EmptyNodes) { BookmarkContextMenuController controller(
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc index e53f6238..3807df2 100644 --- a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc +++ b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.cc
@@ -319,22 +319,6 @@ : absl::nullopt)); } -void OpenAllNow(Browser* browser, - const std::vector<const BookmarkNode*>& nodes, - WindowOpenDisposition initial_disposition, - content::BrowserContext* browser_context) { - // Opens all |nodes| of type URL and any children of |nodes| that are of type - // URL. |navigator| is the PageNavigator used to open URLs. After the first - // url is opened |navigator| is set to the PageNavigator of the last active - // tab. This is done to handle a window disposition of new window, in which - // case we want subsequent tabs to open in that window. - OpenAllHelper(browser, - GetURLsToOpen(nodes, browser_context, - initial_disposition == - WindowOpenDisposition::OFF_THE_RECORD), - initial_disposition); -} - int OpenCount(gfx::NativeWindow parent, const std::vector<const bookmarks::BookmarkNode*>& nodes, content::BrowserContext* incognito_context) {
diff --git a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h index b172785..6934b5b 100644 --- a/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h +++ b/chrome/browser/ui/bookmarks/bookmark_utils_desktop.h
@@ -65,18 +65,6 @@ WindowOpenDisposition initial_disposition, bool add_to_group); -// Opens all the bookmarks in |nodes| that are of type url and all the child -// bookmarks that are of type url for folders in |nodes|. |initial_disposition| -// dictates how the first URL is opened, all subsequent URLs are opened as -// background tabs. -// -// This does not prompt the user. It will open an arbitrary number of -// bookmarks immediately. -void OpenAllNow(Browser* browser, - const std::vector<const bookmarks::BookmarkNode*>& nodes, - WindowOpenDisposition initial_disposition, - content::BrowserContext* browser_context); - // Returns the count of bookmarks that would be opened by OpenAll. If // |incognito_context| is set, the function will use it to check if the URLs // can be opened in incognito mode, which may affect the count.
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript.mm b/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript.mm index 62515ac..eb3ec56 100644 --- a/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript.mm +++ b/chrome/browser/ui/cocoa/applescript/bookmark_item_applescript.mm
@@ -67,9 +67,8 @@ return; } - AppController* appDelegate = - base::mac::ObjCCastStrict<AppController>(NSApp.delegate); - if (!chrome::mac::IsJavaScriptEnabledForProfile(appDelegate.lastProfile) && + if (!chrome::mac::IsJavaScriptEnabledForProfile( + AppController.sharedController.lastProfile) && gurl.SchemeIs(url::kJavaScriptScheme)) { AppleScript::SetError(AppleScript::Error::kJavaScriptUnsupported); return;
diff --git a/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm b/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm index efd998b..9825313 100644 --- a/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm +++ b/chrome/browser/ui/cocoa/applescript/bookmark_node_applescript.mm
@@ -129,10 +129,7 @@ } - (BookmarkModel*)bookmarkModel { - AppController* appDelegate = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - - Profile* lastProfile = appDelegate.lastProfile; + Profile* lastProfile = AppController.sharedController.lastProfile; if (!lastProfile) { AppleScript::SetError(AppleScript::Error::kGetProfile); return nullptr;
diff --git a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm index dd685828..41e7ecd 100644 --- a/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm +++ b/chrome/browser/ui/cocoa/applescript/browsercrapplication+applescript.mm
@@ -83,10 +83,7 @@ } - (BookmarkFolderAppleScript*)otherBookmarks { - AppController* appDelegate = - base::mac::ObjCCastStrict<AppController>(NSApp.delegate); - - Profile* lastProfile = appDelegate.lastProfile; + Profile* lastProfile = AppController.sharedController.lastProfile; if (!lastProfile) { AppleScript::SetError(AppleScript::Error::kGetProfile); return nil; @@ -107,10 +104,7 @@ } - (BookmarkFolderAppleScript*)bookmarksBar { - AppController* appDelegate = - base::mac::ObjCCastStrict<AppController>(NSApp.delegate); - - Profile* lastProfile = appDelegate.lastProfile; + Profile* lastProfile = AppController.sharedController.lastProfile; if (!lastProfile) { AppleScript::SetError(AppleScript::Error::kGetProfile); return nil;
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript.mm b/chrome/browser/ui/cocoa/applescript/window_applescript.mm index 8049ebd..c9f3136f 100644 --- a/chrome/browser/ui/cocoa/applescript/window_applescript.mm +++ b/chrome/browser/ui/cocoa/applescript/window_applescript.mm
@@ -59,11 +59,8 @@ // Check which mode to open a new window. NSScriptCommand* command = [NSScriptCommand currentCommand]; NSString* mode = command.evaluatedArguments[@"KeyDictionary"][@"mode"]; - AppController* appDelegate = - base::mac::ObjCCastStrict<AppController>(NSApp.delegate); - Profile* lastProfile = appDelegate.lastProfile; - + Profile* lastProfile = AppController.sharedController.lastProfile; if (!lastProfile) { AppleScript::SetError(AppleScript::Error::kGetProfile); return nil;
diff --git a/chrome/browser/ui/cocoa/applescript/window_applescript_browsertest.mm b/chrome/browser/ui/cocoa/applescript/window_applescript_browsertest.mm index 6a38d3b..584764e5 100644 --- a/chrome/browser/ui/cocoa/applescript/window_applescript_browsertest.mm +++ b/chrome/browser/ui/cocoa/applescript/window_applescript_browsertest.mm
@@ -43,9 +43,7 @@ // Create a window with a particular profile. IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, CreationWithProfile) { - AppController* appController = - base::mac::ObjCCastStrict<AppController>(NSApp.delegate); - Profile* lastProfile = appController.lastProfile; + Profile* lastProfile = AppController.sharedController.lastProfile; WindowAppleScript* window = [[WindowAppleScript alloc] initWithProfile:lastProfile]; EXPECT_TRUE(window); @@ -125,12 +123,10 @@ IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, InsertAndDeleteTabs) { WindowAppleScript* window = [[WindowAppleScript alloc] initWithBrowser:browser()]; - base::scoped_nsobject<TabAppleScript> aTab; NSUInteger count; for (NSUInteger i = 0; i < 5; ++i) { for (NSUInteger j = 0; j < 3; ++j) { - aTab.reset([[TabAppleScript alloc] init]); - [window insertInTabs:aTab]; + [window insertInTabs:[[TabAppleScript alloc] init]]; } count = 3 * i + 4; EXPECT_EQ(window.tabs.count, count); @@ -160,8 +156,7 @@ IN_PROC_BROWSER_TEST_F(WindowAppleScriptTest, ActiveTab) { WindowAppleScript* window = [[WindowAppleScript alloc] initWithBrowser:browser()]; - TabAppleScript* aTab = [[TabAppleScript alloc] init]; - [window insertInTabs:aTab]; + [window insertInTabs:[[TabAppleScript alloc] init]]; [window setActiveTabIndex:@2]; EXPECT_EQ(2, window.activeTabIndex.intValue); TabAppleScript* tab2 = window.tabs[1];
diff --git a/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm b/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm index fa1ea99..d6763bdb 100644 --- a/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm +++ b/chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac_interactive_uitest.mm
@@ -159,12 +159,10 @@ // Simulate a terminate triggered by a power off or log out. // Cocoa will send an NSWorkspaceWillPowerOffNotification followed by // -[NSApplication terminate:]. - AppController* app_controller = - base::mac::ObjCCast<AppController>([NSApp delegate]); NSNotification* notification = [NSNotification notificationWithName:NSWorkspaceWillPowerOffNotification object:nil]; - [app_controller willPowerOff:notification]; + [AppController.sharedController willPowerOff:notification]; [NSApp terminate:nil]; EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); }
diff --git a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm index 3ebbfbf..ac8e3731 100644 --- a/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm +++ b/chrome/browser/ui/cocoa/bookmarks/bookmark_menu_cocoa_controller.mm
@@ -171,9 +171,7 @@ } - (BOOL)validateMenuItem:(NSMenuItem*)menuItem { - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - return ![controller keyWindowIsModal]; + return ![AppController.sharedController keyWindowIsModal]; } // NSMenu delegate method: called just before menu is displayed.
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm index cf139b40..29404685 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -374,9 +374,8 @@ } // Set the icon of the group to the group color circle. - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - const auto& color_provider = [controller lastActiveColorProvider]; + const auto& color_provider = + [AppController.sharedController lastActiveColorProvider]; const ui::ColorId color_id = GetTabGroupContextMenuColorId(group->visual_data.color()); gfx::ImageSkia group_icon = gfx::CreateVectorIcon(
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm index 60ec181..5166e66 100644 --- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm +++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -118,17 +118,12 @@ protected: void SetUp() override { BrowserWithTestWindowTest::SetUp(); - appController_.reset([[AppController alloc] init]); - [appController_ setLastProfileForTesting:profile()]; - previousApplicationDelegate_ = [NSApp delegate]; - [NSApp setDelegate:appController_]; + [AppController.sharedController setLastProfileForTesting:profile()]; bridge_ = std::make_unique<MockBridge>(profile()); } void TearDown() override { - [NSApp setDelegate:previousApplicationDelegate_]; - appController_.reset(); bridge_.reset(); BrowserWithTestWindowTest::TearDown(); } @@ -193,10 +188,6 @@ protected: std::unique_ptr<MockBridge> bridge_; - - private: - base::scoped_nsobject<AppController> appController_; - id<NSApplicationDelegate> previousApplicationDelegate_; }; class HistoryMenuBridgeLifetimeTest : public testing::Test { @@ -619,9 +610,8 @@ HistoryServiceFactory::GetDefaultFactory()); std::unique_ptr<TestingProfile> profile = profile_builder.Build(); base::FilePath profile_dir = profile->GetPath(); - base::scoped_nsobject<AppController> appController( - [[AppController alloc] init]); - [NSApp setDelegate:appController]; + // Ensure the AppController is the NSApp delegate. + std::ignore = AppController.sharedController; auto bridge = std::make_unique<MockBridge>(profile.get()); std::unique_ptr<MockTRS> trs(new MockTRS(profile.get())); @@ -676,7 +666,6 @@ EXPECT_EQ(4u, menu_item_map(bridge.get()).size()); bridge.reset(); - [NSApp setDelegate:nil]; } TEST_F(HistoryMenuBridgeLifetimeTest, EmptyTabRestoreService) {
diff --git a/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm b/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm index 578af9d9f..e84755d 100644 --- a/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm +++ b/chrome/browser/ui/cocoa/history_menu_cocoa_controller.mm
@@ -77,9 +77,7 @@ } - (BOOL)validateMenuItem:(NSMenuItem*)menuItem { - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - return ![controller keyWindowIsModal]; + return ![AppController.sharedController keyWindowIsModal]; } // Open the URL of the given history item in the current tab.
diff --git a/chrome/browser/ui/layout_constants.cc b/chrome/browser/ui/layout_constants.cc index ba7d809..6977ac3 100644 --- a/chrome/browser/ui/layout_constants.cc +++ b/chrome/browser/ui/layout_constants.cc
@@ -19,14 +19,20 @@ switch (constant) { case APP_MENU_PROFILE_ROW_AVATAR_ICON_SIZE: return 24; - case BOOKMARK_BAR_HEIGHT: + case BOOKMARK_BAR_HEIGHT: { // The fixed margin ensures the bookmark buttons appear centered relative // to the white space above and below. - static constexpr int kBookmarkBarAttachedVerticalMargin = 4; + const int bookmark_bar_attached_vertical_margin = + features::IsChromeRefresh2023() ? 6 : 4; return GetLayoutConstant(BOOKMARK_BAR_BUTTON_HEIGHT) + - kBookmarkBarAttachedVerticalMargin; + bookmark_bar_attached_vertical_margin; + } case BOOKMARK_BAR_BUTTON_HEIGHT: return touch_ui ? 36 : 28; + case BOOKMARK_BAR_BUTTON_PADDING: + return features::IsChromeRefresh2023() + ? (touch_ui ? 0 : 8) + : GetLayoutConstant(TOOLBAR_ELEMENT_PADDING); case WEB_APP_MENU_BUTTON_SIZE: return 24; case WEB_APP_PAGE_ACTION_ICON_SIZE:
diff --git a/chrome/browser/ui/layout_constants.h b/chrome/browser/ui/layout_constants.h index 59cab88..01636de 100644 --- a/chrome/browser/ui/layout_constants.h +++ b/chrome/browser/ui/layout_constants.h
@@ -21,6 +21,9 @@ // The height of a button within the Bookmarks Bar. BOOKMARK_BAR_BUTTON_HEIGHT, + // The horizontal padding between buttons within the Bookmarks Bar. + BOOKMARK_BAR_BUTTON_PADDING, + // The size of icons used in Download bubbles. // TODO(crbug/1296323): We should be sourcing the size of the file icon from // the layout
diff --git a/chrome/browser/ui/side_panel/companion/companion_utils.cc b/chrome/browser/ui/side_panel/companion/companion_utils.cc index b8f541e..ea135fee 100644 --- a/chrome/browser/ui/side_panel/companion/companion_utils.cc +++ b/chrome/browser/ui/side_panel/companion/companion_utils.cc
@@ -71,6 +71,14 @@ } void UpdateCompanionDefaultPinnedToToolbarState(PrefService* pref_service) { + absl::optional<bool> should_force_pin = + switches::ShouldForceOverrideCompanionPinState(); + if (should_force_pin) { + pref_service->SetBoolean(prefs::kSidePanelCompanionEntryPinnedToToolbar, + *should_force_pin); + return; + } + bool companion_should_be_default_pinned = base::FeatureList::IsEnabled( ::features::kSidePanelCompanionDefaultPinned) ||
diff --git a/chrome/browser/ui/side_panel/companion/companion_utils_unittest.cc b/chrome/browser/ui/side_panel/companion/companion_utils_unittest.cc new file mode 100644 index 0000000..2531bd69 --- /dev/null +++ b/chrome/browser/ui/side_panel/companion/companion_utils_unittest.cc
@@ -0,0 +1,96 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/side_panel/companion/companion_utils.h" + +#include "base/command_line.h" +#include "base/feature_list.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/companion/core/constants.h" +#include "chrome/browser/companion/core/features.h" +#include "chrome/browser/ui/ui_features.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_registry_simple.h" +#include "components/prefs/testing_pref_service.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace companion { + +void RegisterPrefs(TestingPrefServiceSimple* pref_service) { + pref_service->registry()->RegisterBooleanPref( + prefs::kSidePanelCompanionEntryPinnedToToolbar, false); + pref_service->registry()->RegisterBooleanPref( + companion::kExpsOptInStatusGrantedPref, false); +} + +TEST(CompanionUtilsTest, PinnedStateCommandlineOverridePinned) { + TestingPrefServiceSimple pref_service; + RegisterPrefs(&pref_service); + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kForceCompanionPinnedState, "pinned"); + + UpdateCompanionDefaultPinnedToToolbarState(&pref_service); + EXPECT_EQ( + pref_service.GetBoolean(prefs::kSidePanelCompanionEntryPinnedToToolbar), + true); +} + +TEST(CompanionUtilsTest, PinnedStateCommandlineOverrideUnpinned) { + TestingPrefServiceSimple pref_service; + RegisterPrefs(&pref_service); + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kForceCompanionPinnedState, "unpinned"); + + UpdateCompanionDefaultPinnedToToolbarState(&pref_service); + EXPECT_EQ( + pref_service.GetBoolean(prefs::kSidePanelCompanionEntryPinnedToToolbar), + false); +} + +TEST(CompanionUtilsTest, UpdatePinnedStateDefaultUnpinnedLabsOverride) { + base::test::ScopedFeatureList scoped_feature_list; + TestingPrefServiceSimple pref_service; + RegisterPrefs(&pref_service); + + scoped_feature_list.InitAndDisableFeature( + ::features::kSidePanelCompanionDefaultPinned); + pref_service.SetBoolean(companion::kExpsOptInStatusGrantedPref, true); + + UpdateCompanionDefaultPinnedToToolbarState(&pref_service); + EXPECT_EQ( + pref_service.GetBoolean(prefs::kSidePanelCompanionEntryPinnedToToolbar), + true); +} + +TEST(CompanionUtilsTest, UpdatePinnedStateDefaultPinned) { + base::test::ScopedFeatureList scoped_feature_list; + TestingPrefServiceSimple pref_service; + RegisterPrefs(&pref_service); + + scoped_feature_list.InitAndEnableFeature( + ::features::kSidePanelCompanionDefaultPinned); + pref_service.SetBoolean(companion::kExpsOptInStatusGrantedPref, false); + + UpdateCompanionDefaultPinnedToToolbarState(&pref_service); + EXPECT_EQ( + pref_service.GetBoolean(prefs::kSidePanelCompanionEntryPinnedToToolbar), + true); +} + +TEST(CompanionUtilsTest, UpdatePinnedStateDefaultUnPinned) { + base::test::ScopedFeatureList scoped_feature_list; + TestingPrefServiceSimple pref_service; + RegisterPrefs(&pref_service); + + scoped_feature_list.InitAndDisableFeature( + ::features::kSidePanelCompanionDefaultPinned); + pref_service.SetBoolean(companion::kExpsOptInStatusGrantedPref, false); + + UpdateCompanionDefaultPinnedToToolbarState(&pref_service); + EXPECT_EQ( + pref_service.GetBoolean(prefs::kSidePanelCompanionEntryPinnedToToolbar), + false); +} + +} // namespace companion
diff --git a/chrome/browser/ui/startup/startup_browser_creator_unittest.cc b/chrome/browser/ui/startup/startup_browser_creator_unittest.cc index d5a9180..5e1e68a2 100644 --- a/chrome/browser/ui/startup/startup_browser_creator_unittest.cc +++ b/chrome/browser/ui/startup/startup_browser_creator_unittest.cc
@@ -11,11 +11,7 @@ #include "testing/gtest/include/gtest/gtest.h" #if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/constants/ash_features.h" -#include "base/test/scoped_feature_list.h" -#include "components/account_id/account_id.h" -#include "components/user_manager/fake_user_manager.h" -#include "components/user_manager/scoped_user_manager.h" +#include "chrome/browser/ash/crosapi/browser_util.h" #endif TEST(StartupBrowserCreatorTest, ShouldLoadProfileWithoutWindow) { @@ -23,9 +19,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) // Forcibly set ash-chrome as the primary browser. // This is the current default behavior. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitWithFeatures( - {}, {ash::features::kLacrosSupport, ash::features::kLacrosPrimary}); + auto set_lacros_primary = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(false); #endif EXPECT_FALSE(StartupBrowserCreator::ShouldLoadProfileWithoutWindow( base::CommandLine(base::CommandLine::NO_PROGRAM))); @@ -38,19 +33,8 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) { // Check what happens if lacros-chrome becomes the primary browser. - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary}, {}); - auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>(); - auto* primary_user = - fake_user_manager->AddUser(AccountId::FromUserEmail("test@test")); - fake_user_manager->UserLoggedIn(primary_user->GetAccountId(), - primary_user->username_hash(), - /*browser_restart=*/false, - /*is_child=*/false); - auto scoped_user_manager = - std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); + auto set_lacros_primary = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); EXPECT_TRUE(StartupBrowserCreator::ShouldLoadProfileWithoutWindow( base::CommandLine(base::CommandLine::NO_PROGRAM))); }
diff --git a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc index 7a472d2..de9243e 100644 --- a/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc +++ b/chrome/browser/ui/tabs/existing_tab_group_sub_menu_model.cc
@@ -136,7 +136,7 @@ ui::ImageModel image_model = ui::ImageModel::FromVectorIcon( kTabGroupIcon, color_provider.GetColor(color_id), kIconSize); - menu_item_infos.emplace_back(MenuItemInfo{displayed_title, image_model}); + menu_item_infos.emplace_back(displayed_title, image_model); menu_item_infos.back().may_have_mnemonics = false; } @@ -179,6 +179,12 @@ } void ExistingTabGroupSubMenuModel::ExecuteExistingCommand(size_t target_index) { + // The tab strip may have been modified while the context menu was open, + // including closing the tab originally at |context_index|. + if (!model()->ContainsIndex(GetContextIndex())) { + return; + } + DCHECK_LE(size_t(target_index), target_index_to_group_mapping_.size()); TabGroupModel* group_model = model()->group_model(); if (!group_model) @@ -189,11 +195,13 @@ tab_groups::TabGroupId group = target_index_to_group_mapping_.at(target_index); + // If the group exists in this model, move the tab into it. if (group_model->ContainsTabGroup(group)) { model()->ExecuteAddToExistingGroupCommand(GetContextIndex(), group); return; } + // Find the index of the browser with the group we are looking for. absl::optional<size_t> browser_index; std::vector<Browser*> browsers = tab_menu_model_delegate_->GetExistingWindowsForMoveMenu(); @@ -206,43 +214,38 @@ } } + // Do nothing if the browser does not exist. if (!browser_index.has_value()) return; std::vector<int> selected_indices; if (!model()->IsTabSelected(GetContextIndex())) { + // If the context index is not selected, set it as the selected index. selected_indices = {GetContextIndex()}; } else { + // Use the currently selected indices as the selected_indices we will move. const ui::ListSelectionModel::SelectedIndices selection_indices = model()->selection_model().selected_indices(); selected_indices = std::vector<int>(selection_indices.begin(), selection_indices.end()); } - TabStripModel* found_model = - browsers[browser_index.value()]->tab_strip_model(); - std::vector<int> selected_indices_in_found_model; - const ui::ListSelectionModel::SelectedIndices selection_indices = - found_model->selection_model().selected_indices(); - selected_indices_in_found_model = - std::vector<int>(selection_indices.begin(), selection_indices.end()); // At the time this was written, all tabs moved to a new window via - // MoveToExistingWindow() are placed at the end of the tabstrip, and any + // MoveToExistingWindow() are placed at the end of the tabstrip where any // previously selected tabs in the new window are unselected. model()->delegate()->MoveToExistingWindow(selected_indices, browser_index.value()); - // DCHECK that previously selected indices in the new model are now - // unselected. - for (int index : selected_indices_in_found_model) - DCHECK(!found_model->IsTabSelected(index)); + TabStripModel* found_model = + browsers[browser_index.value()]->tab_strip_model(); // Ensure that the selected_indices maintain selection in the new window. // Our indices to consider are guaranteed to be at the end of the tabstrip. for (size_t count = 0; count < selected_indices.size(); ++count) { - int tab = found_model->count() - 1 - count; - if (!found_model->IsTabSelected(tab)) - found_model->ToggleSelectionAt(tab); + const int tab_index = found_model->count() - 1 - count; + if (!found_model->IsTabSelected(tab_index)) { + found_model->ToggleSelectionAt(tab_index); + } } // Move all selected tabs into `group`. Note, we can choose any tab that is
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc index 143bc60..6e6984e 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc
@@ -44,7 +44,9 @@ Browser* SavedTabGroupUtils::GetBrowserWithTabGroupId( tab_groups::TabGroupId group_id) { for (Browser* browser : *BrowserList::GetInstance()) { - if (browser->tab_strip_model()->group_model()->ContainsTabGroup(group_id)) { + const TabStripModel* const tab_strip_model = browser->tab_strip_model(); + if (tab_strip_model && tab_strip_model->SupportsTabGroups() && + tab_strip_model->group_model()->ContainsTabGroup(group_id)) { return browser; } }
diff --git a/chrome/browser/ui/test/popup_multiscreen_interactive_uitest.cc b/chrome/browser/ui/test/popup_multiscreen_interactive_uitest.cc index 96c9d5f..cf1f431 100644 --- a/chrome/browser/ui/test/popup_multiscreen_interactive_uitest.cc +++ b/chrome/browser/ui/test/popup_multiscreen_interactive_uitest.cc
@@ -126,7 +126,7 @@ for (const display::Display& target_display : displays) { for (const char* url : {".", "about:blank"}) { const std::string open_script = content::JsReplace( - "open('$1', '', 'left=$2,top=$3,width=200,height=200')", url, + "open($1, '', 'left=$2,top=$3,width=200,height=200')", url, target_display.work_area().x(), target_display.work_area().y()); Browser* popup = OpenPopup(browser(), open_script); display::Display popup_display = GetDisplayNearestBrowser(popup);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc index 9940e6e5..1803e73d 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view.cc
@@ -920,7 +920,7 @@ int height = GetLayoutConstant(BOOKMARK_BAR_HEIGHT); const int bookmark_bar_button_padding = - GetLayoutConstant(TOOLBAR_ELEMENT_PADDING); + GetLayoutConstant(BOOKMARK_BAR_BUTTON_PADDING); if (managed_bookmarks_button_->GetVisible()) { gfx::Size size = managed_bookmarks_button_->GetPreferredSize(); @@ -995,12 +995,13 @@ : gfx::Size(); const int bookmark_bar_button_padding = - GetLayoutConstant(TOOLBAR_ELEMENT_PADDING); + GetLayoutConstant(BOOKMARK_BAR_BUTTON_PADDING); int max_x = kBookmarkBarHorizontalMargin + width - overflow_pref.width() - bookmarks_separator_pref.width(); - if (other_bookmarks_button_->GetVisible()) - max_x -= other_bookmarks_pref.width(); + if (other_bookmarks_button_->GetVisible()) { + max_x -= other_bookmarks_pref.width() + bookmark_bar_button_padding; + } // Start with the apps page shortcut button. if (apps_page_shortcut_->GetVisible()) {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc index cf2025ed..f6a71a98 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
@@ -130,28 +130,6 @@ ASSERT_FALSE(model_->IsBookmarked(url)); } -// Tests open all on a folder with a couple of bookmarks. -TEST_F(BookmarkContextMenuTest, OpenAll) { - const BookmarkNode* folder = model_->bookmark_bar_node()->children()[1].get(); - chrome::OpenAllNow(nullptr, {folder}, - WindowOpenDisposition::NEW_FOREGROUND_TAB, nullptr); - - // Should have navigated to F1's child but not F11's child. - ASSERT_EQ(2u, wrapper_.urls().size()); - ASSERT_TRUE(folder->children()[0]->url() == wrapper_.urls()[0]); -} - -// Tests open all on a folder with a couple of bookmarks in incognito window. -TEST_F(BookmarkContextMenuTest, OpenAllIncognito) { - const BookmarkNode* folder = model_->bookmark_bar_node()->children()[1].get(); - chrome::OpenAllNow(nullptr, {folder}, WindowOpenDisposition::OFF_THE_RECORD, - profile_.get()); - - // Should have navigated to only f1a but not f2a. - ASSERT_EQ(1u, wrapper_.urls().size()); - ASSERT_TRUE(folder->children()[0]->url() == wrapper_.urls()[0]); -} - // Tests counting tabs for 'open all' on a folder with a couple of bookmarks. TEST_F(BookmarkContextMenuTest, OpenCount) { const BookmarkNode* folder = model_->bookmark_bar_node()->children()[1].get();
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc index a79e41f..a7761c3 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar.cc
@@ -31,6 +31,7 @@ #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/dialog_model.h" +#include "ui/base/ui_base_features.h" #include "ui/base/window_open_disposition.h" #include "ui/compositor/layer_tree_owner.h" #include "ui/gfx/canvas.h" @@ -190,13 +191,14 @@ SetProperty(views::kElementIdentifierKey, kSavedTabGroupBarElementId); + const int element_padding = GetLayoutConstant(BOOKMARK_BAR_BUTTON_PADDING); + std::unique_ptr<views::LayoutManager> layout_manager = std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, - gfx::Insets::TLBR(kButtonPadding, - GetLayoutConstant(TOOLBAR_ELEMENT_PADDING) / 2, - kButtonPadding, 0), - GetLayoutConstant(TOOLBAR_ELEMENT_PADDING)); + gfx::Insets::TLBR(kButtonPadding, element_padding / 2, kButtonPadding, + 0), + element_padding); SetLayoutManager(std::move(layout_manager)); if (!saved_tab_group_model_) { @@ -443,7 +445,7 @@ } int SavedTabGroupBar::CalculatePreferredWidthRestrictedBy(int max_x) { - const int button_padding = GetLayoutConstant(TOOLBAR_ELEMENT_PADDING); + const int button_padding = GetLayoutConstant(BOOKMARK_BAR_BUTTON_PADDING); int current_x = 0; // Calculate the amount of space that the SavedTabGroupBar can utilize // restricted by `max_x`. @@ -728,7 +730,7 @@ const int x = indicator_index.value() > 0 ? children()[indicator_index.value() - 1]->bounds().right() + - GetLayoutConstant(TOOLBAR_ELEMENT_PADDING) / 2 + GetLayoutConstant(BOOKMARK_BAR_BUTTON_PADDING) / 2 : kDropIndicatorThicknessDips / 2; const gfx::Rect drop_indicator_bounds =
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm index c5bafdf..82d2903f 100644 --- a/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm +++ b/chrome/browser/ui/views/frame/immersive_mode_controller_mac.mm
@@ -4,7 +4,6 @@ #include <AppKit/AppKit.h> -#include "base/allocator/partition_allocator/pointers/raw_ptr.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller_mac.h" #include <vector> @@ -131,9 +130,8 @@ // Used as a convenience to access // NativeWidgetMacNSWindowHost::GetNSWindowMojo(). - // Dangling in ImmersiveModeControllerMacBrowserTest.ToggleFullscreen. - raw_ptr<remote_cocoa::mojom::NativeWidgetNSWindow, DanglingUntriaged> - ns_window_mojo_ = nullptr; // weak + raw_ptr<remote_cocoa::mojom::NativeWidgetNSWindow> ns_window_mojo_ = + nullptr; // weak // Used to hold the widget id for the tab hosting widget. This will be passed // to the remote_cocoa immersive mode controller where the tab strip will be
diff --git a/chrome/browser/ui/views/frame/top_container_background.cc b/chrome/browser/ui/views/frame/top_container_background.cc index b8e25fa..a78f63f 100644 --- a/chrome/browser/ui/views/frame/top_container_background.cc +++ b/chrome/browser/ui/views/frame/top_container_background.cc
@@ -22,33 +22,47 @@ /*translate_view_coordinates=*/false); } +bool TopContainerBackground::PaintThemeCustomImage( + gfx::Canvas* canvas, + const views::View* view, + const BrowserView* browser_view, + bool translate_view_coordinates) { + const ui::ThemeProvider* const theme_provider = view->GetThemeProvider(); + if (!theme_provider->HasCustomImage(IDR_THEME_TOOLBAR)) { + return false; + } + + // This is a recapitulation of the logic originally used to place the + // background image in the bookmarks bar. It is used to ensure backwards- + // compatibility with existing themes, even though it is not technically + // correct in all cases. + gfx::Point view_offset = view->GetMirroredPosition(); + // TODO(pbos): See if we can figure out how to translate correctly + // unconditionally from this bool. + if (translate_view_coordinates) { + views::View::ConvertPointToTarget(view, browser_view, &view_offset); + } + gfx::Point pos = + view_offset + browser_view->GetMirroredPosition().OffsetFromOrigin(); + pos.Offset(browser_view->frame()->GetThemeBackgroundXInset(), + -browser_view->tabstrip()->GetStrokeThickness() - + browser_view->frame()->GetTopInset()); + const gfx::Rect bounds = view->GetLocalBounds(); + + canvas->TileImageInt(*theme_provider->GetImageSkiaNamed(IDR_THEME_TOOLBAR), + pos.x(), pos.y(), bounds.x(), bounds.y(), bounds.width(), + bounds.height(), 1.0f, SkTileMode::kRepeat, + SkTileMode::kMirror); + return true; +} + void TopContainerBackground::PaintBackground(gfx::Canvas* canvas, const views::View* view, const BrowserView* browser_view, bool translate_view_coordinates) { - const ui::ThemeProvider* const theme_provider = view->GetThemeProvider(); - if (theme_provider->HasCustomImage(IDR_THEME_TOOLBAR)) { - // This is a recapitulation of the logic originally used to place the - // background image in the bookmarks bar. It is used to ensure backwards- - // compatibility with existing themes, even though it is not technically - // correct in all cases. - gfx::Point view_offset = view->GetMirroredPosition(); - // TODO(pbos): See if we can figure out how to translate correctly - // unconditionally from this bool. - if (translate_view_coordinates) - views::View::ConvertPointToTarget(view, browser_view, &view_offset); - gfx::Point pos = - view_offset + browser_view->GetMirroredPosition().OffsetFromOrigin(); - pos.Offset(browser_view->frame()->GetThemeBackgroundXInset(), - -browser_view->tabstrip()->GetStrokeThickness() - - browser_view->frame()->GetTopInset()); - const gfx::Rect bounds = view->GetLocalBounds(); - - canvas->TileImageInt(*theme_provider->GetImageSkiaNamed(IDR_THEME_TOOLBAR), - pos.x(), pos.y(), bounds.x(), bounds.y(), - bounds.width(), bounds.height(), 1.0f, - SkTileMode::kRepeat, SkTileMode::kMirror); - } else { + bool painted = PaintThemeCustomImage(canvas, view, browser_view, + translate_view_coordinates); + if (!painted) { canvas->DrawColor(view->GetColorProvider()->GetColor(kColorToolbar)); } }
diff --git a/chrome/browser/ui/views/frame/top_container_background.h b/chrome/browser/ui/views/frame/top_container_background.h index 336d8df..8bfbc00 100644 --- a/chrome/browser/ui/views/frame/top_container_background.h +++ b/chrome/browser/ui/views/frame/top_container_background.h
@@ -22,6 +22,13 @@ TopContainerBackground& operator=(const TopContainerBackground& other) = delete; + // Paints the theme's custom image if one exists. Returns whether or not any + // painting occurred. + static bool PaintThemeCustomImage(gfx::Canvas* canvas, + const views::View* view, + const BrowserView* browser_view, + bool translate_view_coordinates); + // Static version for painting this background, used by the SidePanel // background to paint this background as a part of its background. // TODO(pbos): See if we can get rid of `translate_view_coordinates` by
diff --git a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc index cddf9fc..d8e936f 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_suggestion_button_row_view.cc
@@ -65,7 +65,7 @@ if (base::FeatureList::IsEnabled(omnibox::kCr2023ActionChips) || features::GetChromeRefresh2023Level() == features::ChromeRefresh2023Level::kLevel2) { - SetImageLabelSpacing(4); + SetImageLabelSpacing(8); SetCustomPadding(ChromeLayoutProvider::Get()->GetInsetsMetric( INSETS_OMNIBOX_PILL_BUTTON)); SetCornerRadius(GetLayoutConstant(TOOLBAR_CORNER_RADIUS));
diff --git a/chrome/browser/ui/views/side_panel/search_companion/companion_page_browsertest.cc b/chrome/browser/ui/views/side_panel/search_companion/companion_page_browsertest.cc index 5404688..d0db232 100644 --- a/chrome/browser/ui/views/side_panel/search_companion/companion_page_browsertest.cc +++ b/chrome/browser/ui/views/side_panel/search_companion/companion_page_browsertest.cc
@@ -261,7 +261,7 @@ GetCompanionWebContents(browser()); EXPECT_TRUE(companion_web_contents); - // Wait for the navigations in both the frames to complete. + // Wait for the navigations in the inner iframe to complete. content::TestNavigationObserver nav_observer(companion_web_contents, 1); nav_observer.Wait(); } @@ -288,8 +288,7 @@ const GURL& url = request.GetURL(); std::string query_proto; - EXPECT_TRUE( - net::GetValueForKeyInQuery(url, "companion_query", &query_proto)); + net::GetValueForKeyInQuery(url, "companion_query", &query_proto); last_proto_from_url_load_ = DeserializeCompanionRequest(query_proto); if (request.method == net::test_server::HttpMethod::METHOD_POST) { @@ -361,10 +360,13 @@ companion_server_.GetURL("/companion_iframe.html").spec(); params["companion-image-upload-url"] = companion_server_.GetURL("/upload").spec(); + params["open-links-in-current-tab"] = ShouldOpenLinkInCurrentTab(); feature_list_.InitAndEnableFeatureWithParameters( companion::features::kSidePanelCompanion, params); } + virtual std::string ShouldOpenLinkInCurrentTab() { return "false"; } + void WaitForTabCount(int expected) { while (browser()->tab_strip_model()->count() != expected) { base::RunLoop().RunUntilIdle(); @@ -388,13 +390,30 @@ run_loop.Run(); } + void ExpectUkmCount(ukm::TestUkmRecorder* ukm_recorder, + size_t expected_count) { + EXPECT_EQ( + expected_count, + ukm_recorder + ->GetEntriesByName(ukm::builders::Companion_PageView::kEntryName) + .size()); + } + void ExpectUkmEntry(ukm::TestUkmRecorder* ukm_recorder, const char* metric_name, int expected_value) { - // There should be only one UKM entry of Companion_PageView type. + ExpectUkmCount(ukm_recorder, 1u); + ExpectUkmEntryAt(ukm_recorder, 0, metric_name, expected_value); + } + + void ExpectUkmEntryAt(ukm::TestUkmRecorder* ukm_recorder, + int index, + const char* metric_name, + int expected_value) { const char* entry_name = ukm::builders::Companion_PageView::kEntryName; - EXPECT_EQ(ukm_recorder->GetEntriesByName(entry_name).size(), 1ul); - auto* entry = ukm_recorder->GetEntriesByName(entry_name)[0]; + EXPECT_LE(index, static_cast<int>( + ukm_recorder->GetEntriesByName(entry_name).size())); + auto* entry = ukm_recorder->GetEntriesByName(entry_name)[index]; // Verify the metric. ukm_recorder->EntryHasMetric(entry, metric_name); @@ -464,6 +483,71 @@ EXPECT_EQ(proto->page_url(), CreateUrl(kHost, kRelativeUrl3)); } +class CompanionPageSameTabBrowserTest : public CompanionPageBrowserTest { + public: + std::string ShouldOpenLinkInCurrentTab() override { return "true"; } +}; + +IN_PROC_BROWSER_TEST_F(CompanionPageSameTabBrowserTest, + LinkClickOnCompanionPage) { + EnableSignInMsbbExps(/*signed_in=*/true, /*msbb=*/true, /*exps=*/true); + ukm::TestAutoSetUkmRecorder ukm_recorder; + // Load a page on the active tab and open companion side panel + ASSERT_TRUE( + ui_test_utils::NavigateToURL(browser(), CreateUrl(kHost, kRelativeUrl1))); + side_panel_coordinator()->Show(SidePanelEntry::Id::kSearchCompanion); + + WaitForCompanionToBeLoaded(); + EXPECT_EQ(1u, requests_received_on_server()); + EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(), + SidePanelEntry::Id::kSearchCompanion); + + // Click a link on the companion page. It should open in the same tab and + // refresh the companion. + std::string script = + "document.getElementById('some_link').click(); waitForMessage();"; + EvalJs(script); + + // Close side panel and verify UKM of the second companion entry. + side_panel_coordinator()->Close(); + ExpectUkmCount(&ukm_recorder, 2u); + ExpectUkmEntryAt( + &ukm_recorder, 1, ukm::builders::Companion_PageView::kOpenTriggerName, + static_cast<int>(SidePanelOpenTrigger::kOpenedInNewTabFromSidePanel)); +} + +IN_PROC_BROWSER_TEST_F(CompanionPageBrowserTest, LinkClickOnCompanionPage) { + EnableSignInMsbbExps(/*signed_in=*/true, /*msbb=*/true, /*exps=*/true); + ukm::TestAutoSetUkmRecorder ukm_recorder; + // Load a page on the active tab and open companion side panel + ASSERT_TRUE( + ui_test_utils::NavigateToURL(browser(), CreateUrl(kHost, kRelativeUrl1))); + side_panel_coordinator()->Show(SidePanelEntry::Id::kSearchCompanion, + SidePanelOpenTrigger::kComboboxSelected); + + WaitForCompanionToBeLoaded(); + EXPECT_EQ(1u, requests_received_on_server()); + EXPECT_EQ(side_panel_coordinator()->GetCurrentEntryId(), + SidePanelEntry::Id::kSearchCompanion); + + base::StatisticsRecorder::ForgetHistogramForTesting( + "Companion.SidePanel.OpenTrigger"); + + // Click a link. It should open in a new tab and open the companion side + // panel. Wait for that event. + EXPECT_TRUE(ExecJs("document.getElementById('some_link').click();")); + WaitForHistogram("Companion.SidePanel.OpenTrigger"); + EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); + + // Close side panel and verify UKM. There should be only one entry since the + // side panel in the previous tab wasn't closed. + side_panel_coordinator()->Close(); + ExpectUkmCount(&ukm_recorder, 1u); + ExpectUkmEntryAt( + &ukm_recorder, 0, ukm::builders::Companion_PageView::kOpenTriggerName, + static_cast<int>(SidePanelOpenTrigger::kOpenedInNewTabFromSidePanel)); +} + IN_PROC_BROWSER_TEST_F(CompanionPageBrowserTest, AutoRefreshOnMsbb) { EnableSignInMsbbExps(/*signed_in=*/true, /*msbb=*/false, /*exps=*/false); @@ -758,6 +842,8 @@ // Verify that a new tab opens up to load the exps URL. WaitForTabCount(2); + EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); + EXPECT_TRUE(web_contents()->GetVisibleURL().spec().starts_with( kExpectedExpsPromoUrl)); } @@ -788,6 +874,7 @@ // Verify that a new tab opens up to load the sign-in URL. WaitForTabCount(2); + EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); EXPECT_TRUE(web_contents()->GetVisibleURL().spec().starts_with( "https://accounts.google.com/signin/chrome/sync")); } @@ -852,6 +939,7 @@ // Verify that a new tab opens up to load the exps URL. WaitForTabCount(2); + EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); EXPECT_TRUE( web_contents()->GetVisibleURL().spec().starts_with(kPhReportingUrl)); }
diff --git a/chrome/browser/ui/views/side_panel/search_companion/companion_side_panel_controller.cc b/chrome/browser/ui/views/side_panel/search_companion/companion_side_panel_controller.cc index 4c857a01..9f1d061 100644 --- a/chrome/browser/ui/views/side_panel/search_companion/companion_side_panel_controller.cc +++ b/chrome/browser/ui/views/side_panel/search_companion/companion_side_panel_controller.cc
@@ -7,6 +7,8 @@ #include "chrome/browser/companion/core/features.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/side_panel/companion/companion_tab_helper.h" +#include "chrome/browser/ui/side_panel/side_panel_enums.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/side_panel/search_companion/search_companion_side_panel_coordinator.h" #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" @@ -138,10 +140,20 @@ } // Open the url in the desired tab. - content::WebContents* new_tab_web_contents = browser->OpenURL(params); + content::WebContents* tab_web_contents = browser->OpenURL(params); + + if (open_in_current_tab) { + // Add metrics to record the open trigger for the companion page as a link + // click from side panel. + auto* tab_helper = + companion::CompanionTabHelper::FromWebContents(tab_web_contents); + CHECK(!tab_helper->GetAndResetMostRecentSidePanelOpenTrigger().has_value()); + tab_helper->SetMostRecentSidePanelOpenTrigger( + SidePanelOpenTrigger::kOpenedInNewTabFromSidePanel); + } // If a new tab was opened, open companion side panel in it. - if (new_tab_web_contents && !open_in_current_tab) { + if (tab_web_contents && !open_in_current_tab) { SidePanelUI::GetSidePanelUIForBrowser(browser)->Show( SidePanelEntry::Id::kSearchCompanion, SidePanelOpenTrigger::kOpenedInNewTabFromSidePanel);
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index 4682fa0..a639a524 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -170,8 +170,40 @@ constexpr int kBrowserAppMenuRefreshExpandedMargin = 5; constexpr int kBrowserAppMenuRefreshCollapsedMargin = 2; +// Draws background akin to the tabstrip. +class TabstripLikeBackground : public views::Background { + public: + explicit TabstripLikeBackground(BrowserView* browser_view) + : browser_view_(browser_view) {} + + private: + // views::Background: + void Paint(gfx::Canvas* canvas, views::View* view) const override { + bool painted = TopContainerBackground::PaintThemeCustomImage( + canvas, view, browser_view_, /*translate_view_coordinates=*/false); + if (!painted) { + SkColor frame_color = + browser_view_->frame()->GetFrameView()->GetFrameColor( + BrowserFrameActiveState::kUseCurrent); + canvas->DrawColor(frame_color); + } + } + + const raw_ptr<BrowserView> browser_view_; +}; + } // namespace +class ToolbarView::ContainerView : public views::View { + public: + // Calling PreferredSizeChanged() will trigger the parent's + // ChildPreferredSizeChanged. + // Bubble up calls to ChildPreferredSizeChanged. + void ChildPreferredSizeChanged(View* child) override { + PreferredSizeChanged(); + } +}; + //////////////////////////////////////////////////////////////////////////////// // ToolbarView, public: @@ -183,14 +215,17 @@ display_mode_(GetDisplayMode(browser)) { SetID(VIEW_ID_TOOLBAR); + container_view_ = AddChildView(std::make_unique<ContainerView>()); + if (display_mode_ == DisplayMode::NORMAL) { - SetBackground(std::make_unique<TopContainerBackground>(browser_view)); + container_view_->SetBackground( + std::make_unique<TopContainerBackground>(browser_view)); for (const auto& view_and_command : GetViewCommandMap()) chrome::AddCommandObserver(browser_, view_and_command.second, this); } - views::SetCascadingColorProviderColor(this, views::kCascadingBackgroundColor, - kColorToolbar); + views::SetCascadingColorProviderColor( + container_view_, views::kCascadingBackgroundColor, kColorToolbar); } ToolbarView::~ToolbarView() { @@ -209,6 +244,21 @@ // See crbug.com/1183894#c2 aura::WindowOcclusionTracker::ScopedPause pause_occlusion; #endif + + // The background views must be behind container_view_. + if (features::IsChromeRefresh2023()) { + background_view_left_ = AddChildViewAt(std::make_unique<View>(), 0); + background_view_left_->SetBackground( + std::make_unique<TabstripLikeBackground>(browser_view_)); + background_view_right_ = AddChildViewAt(std::make_unique<View>(), 0); + background_view_right_->SetBackground( + std::make_unique<TabstripLikeBackground>(browser_view_)); + + active_state_subscription_ = + GetWidget()->RegisterPaintAsActiveChangedCallback(base::BindRepeating( + &ToolbarView::ActiveStateChanged, base::Unretained(this))); + } + auto location_bar = std::make_unique<LocationBarView>( browser_, browser_->profile(), browser_->command_controller(), this, display_mode_ != DisplayMode::NORMAL); @@ -222,20 +272,21 @@ } if (display_mode_ != DisplayMode::NORMAL) { - location_bar_ = AddChildView(std::move(location_bar)); + location_bar_ = container_view_->AddChildView(std::move(location_bar)); location_bar_->Init(); } if (display_mode_ == DisplayMode::CUSTOM_TAB) { - custom_tab_bar_ = - AddChildView(std::make_unique<CustomTabBarView>(browser_view_, this)); - SetLayoutManager(std::make_unique<views::FillLayout>()); + custom_tab_bar_ = container_view_->AddChildView( + std::make_unique<CustomTabBarView>(browser_view_, this)); + container_view_->SetLayoutManager(std::make_unique<views::FillLayout>()); initialized_ = true; return; } else if (display_mode_ == DisplayMode::LOCATION) { // Add the download button for popups. if (download_button) { - download_button_ = AddChildView(std::move(download_button)); + download_button_ = + container_view_->AddChildView(std::move(download_button)); download_button_->SetPreferredSize( gfx::Size(location_bar_->GetPreferredSize().height(), location_bar_->GetPreferredSize().height())); @@ -243,9 +294,9 @@ // Hide the icon by default; it will show up when there's a download. download_button_->Hide(); } - SetBackground( + container_view_->SetBackground( views::CreateThemedSolidBackground(kColorLocationBarBackground)); - SetLayoutManager(std::make_unique<views::FlexLayout>()) + container_view_->SetLayoutManager(std::make_unique<views::FlexLayout>()) ->SetOrientation(views::LayoutOrientation::kHorizontal) .SetCrossAxisAlignment(views::LayoutAlignment::kCenter) .SetDefault(views::kFlexBehaviorKey, @@ -327,18 +378,20 @@ } // Always add children in order from left to right, for accessibility. - back_ = AddChildView(std::move(back)); - forward_ = AddChildView(std::move(forward)); - reload_ = AddChildView(std::move(reload)); - home_ = AddChildView(std::move(home)); + back_ = container_view_->AddChildView(std::move(back)); + forward_ = container_view_->AddChildView(std::move(forward)); + reload_ = container_view_->AddChildView(std::move(reload)); + home_ = container_view_->AddChildView(std::move(home)); - location_bar_ = AddChildView(std::move(location_bar)); + location_bar_ = container_view_->AddChildView(std::move(location_bar)); if (extensions_container) - extensions_container_ = AddChildView(std::move(extensions_container)); + extensions_container_ = + container_view_->AddChildView(std::move(extensions_container)); if (toolbar_divider) { - toolbar_divider_ = AddChildView(std::move(toolbar_divider)); + toolbar_divider_ = + container_view_->AddChildView(std::move(toolbar_divider)); toolbar_divider_->SetPreferredSize( gfx::Size(kToolbarDividerWidth, kToolbarDividerHeight)); } @@ -348,8 +401,9 @@ UpdateChromeLabsNewBadgePrefs(browser_->profile(), chrome_labs_model_.get()); if (ShouldShowChromeLabsUI(chrome_labs_model_.get(), browser_->profile())) { - chrome_labs_button_ = AddChildView(std::make_unique<ChromeLabsButton>( - browser_view_, chrome_labs_model_.get())); + chrome_labs_button_ = + container_view_->AddChildView(std::make_unique<ChromeLabsButton>( + browser_view_, chrome_labs_model_.get())); show_chrome_labs_button_.Init( chrome_labs_prefs::kBrowserLabsEnabled, prefs, @@ -362,29 +416,33 @@ } } - battery_saver_button_ = - AddChildView(std::make_unique<BatterySaverButton>(browser_view_)); + battery_saver_button_ = container_view_->AddChildView( + std::make_unique<BatterySaverButton>(browser_view_)); if (cast) - cast_ = AddChildView(std::move(cast)); + cast_ = container_view_->AddChildView(std::move(cast)); if (media_button) - media_button_ = AddChildView(std::move(media_button)); + media_button_ = container_view_->AddChildView(std::move(media_button)); if (download_button) - download_button_ = AddChildView(std::move(download_button)); + download_button_ = + container_view_->AddChildView(std::move(download_button)); if (send_tab_to_self_button) - send_tab_to_self_button_ = AddChildView(std::move(send_tab_to_self_button)); + send_tab_to_self_button_ = + container_view_->AddChildView(std::move(send_tab_to_self_button)); if (side_panel_toolbar_container) { side_panel_container_ = - AddChildView(std::move(side_panel_toolbar_container)); + container_view_->AddChildView(std::move(side_panel_toolbar_container)); } else if (side_panel_button) { - side_panel_button_ = AddChildView(std::move(side_panel_button)); + side_panel_button_ = + container_view_->AddChildView(std::move(side_panel_button)); } - avatar_ = AddChildView(std::make_unique<AvatarToolbarButton>(browser_view_)); + avatar_ = container_view_->AddChildView( + std::make_unique<AvatarToolbarButton>(browser_view_)); bool show_avatar_toolbar_button = true; #if BUILDFLAG(IS_CHROMEOS_ASH) // ChromeOS only badges Incognito, Guest, and captive portal signin icons in @@ -406,7 +464,7 @@ app_menu_button->SetTooltipText( l10n_util::GetStringUTF16(IDS_APPMENU_TOOLTIP)); app_menu_button->SetID(VIEW_ID_APP_MENU); - app_menu_button_ = AddChildView(std::move(app_menu_button)); + app_menu_button_ = container_view_->AddChildView(std::move(app_menu_button)); LoadImages(); @@ -495,11 +553,13 @@ void ToolbarView::UpdateForWebUITabStrip() { #if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) if (browser_view_->webui_tab_strip() && app_menu_button_) { - const size_t insertion_index = GetIndexOf(app_menu_button_).value(); - AddChildViewAt(browser_view_->webui_tab_strip()->CreateNewTabButton(), - insertion_index); - AddChildViewAt(browser_view_->webui_tab_strip()->CreateTabCounter(), - insertion_index); + const size_t insertion_index = + container_view_->GetIndexOf(app_menu_button_).value(); + container_view_->AddChildViewAt( + browser_view_->webui_tab_strip()->CreateNewTabButton(), + insertion_index); + container_view_->AddChildViewAt( + browser_view_->webui_tab_strip()->CreateTabCounter(), insertion_index); LoadImages(); } #endif // BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) @@ -627,7 +687,7 @@ size = location_bar_->GetPreferredSize(); break; case DisplayMode::NORMAL: - size = View::CalculatePreferredSize(); + size = container_view_->GetPreferredSize(); // Because there are odd cases where something causes one of the views in // the toolbar to report an unreasonable height (see crbug.com/985909), we // cap the height at the size of known child views (location bar and back @@ -656,7 +716,7 @@ size = location_bar_->GetMinimumSize(); break; case DisplayMode::NORMAL: - size = View::GetMinimumSize(); + size = container_view_->GetMinimumSize(); // Because there are odd cases where something causes one of the views in // the toolbar to report an unreasonable height (see crbug.com/985909), we // cap the height at the size of known child views (location bar and back @@ -680,6 +740,18 @@ if (!initialized_) return; + // The container view should be the exact same size/position as ToolbarView. + container_view_->SetSize(size()); + + if (features::IsChromeRefresh2023()) { + // The background views should be behind the top-left and top-right corners + // of the container_view_. + const int corner_radius = GetLayoutConstant(TOOLBAR_CORNER_RADIUS); + background_view_left_->SetBounds(0, 0, corner_radius, corner_radius); + background_view_right_->SetBounds(width() - corner_radius, 0, corner_radius, + corner_radius); + } + if (display_mode_ == DisplayMode::CUSTOM_TAB) { custom_tab_bar_->SetBounds(0, 0, width(), custom_tab_bar_->GetPreferredSize().height()); @@ -690,11 +762,9 @@ if (display_mode_ == DisplayMode::NORMAL) { LayoutCommon(); -#if BUILDFLAG(IS_MAC) if (features::IsChromeRefresh2023()) { UpdateClipPath(); } -#endif } // Call super implementation to ensure layout manager and child layouts @@ -726,7 +796,12 @@ SkPathDirection::kCW, local_bounds.width(), corner_radius); path.lineTo(local_bounds.width(), local_bounds.height()); path.lineTo(0, local_bounds.height()); - SetClipPath(path); + container_view_->SetClipPath(path); +} + +void ToolbarView::ActiveStateChanged() { + background_view_left_->SchedulePaint(); + background_view_right_->SchedulePaint(); } bool ToolbarView::AcceleratorPressed(const ui::Accelerator& accelerator) { @@ -772,7 +847,8 @@ constexpr int kSidePanelFlexOrder = 3; constexpr int kExtensionsFlexOrder = 4; - layout_manager_ = SetLayoutManager(std::make_unique<views::FlexLayout>()); + layout_manager_ = + container_view_->SetLayoutManager(std::make_unique<views::FlexLayout>()); layout_manager_->SetOrientation(views::LayoutOrientation::kHorizontal) .SetCrossAxisAlignment(views::LayoutAlignment::kCenter)
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.h b/chrome/browser/ui/views/toolbar/toolbar_view.h index c38f2b0..be3bd96 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.h +++ b/chrome/browser/ui/views/toolbar/toolbar_view.h
@@ -199,6 +199,9 @@ void SetToolbarVisibility(bool visible); private: + // Forwards view overrides to this class. + class ContainerView; + // AccessiblePaneView: views::View* GetDefaultFocusableChild() override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; @@ -255,6 +258,9 @@ void UpdateClipPath(); + // Called when active state for the window changes. + void ActiveStateChanged(); + gfx::SlideAnimation size_animation_{this}; // Controls. Most of these can be null, e.g. in popup windows. Only @@ -304,6 +310,26 @@ // Whether this toolbar has been initialized. bool initialized_ = false; + + // container_view_ is transparent with the same dimensions as ToolbarView. + // All children are added to container_view_ and layout_manager_ applies to + // container_view_. The reason for this layer of indiretion is because + // container_view_ has a clip path set in UpdateClipPath() which adds rounded + // corners. This leaves some unpainted pixels, which are painted by + // background_view_left_ and background_view_right_. + // the future. + raw_ptr<ContainerView> container_view_ = nullptr; + + // There are two situations where background_view_left_ and + // background_view_right_ need be repainted: window active state change and + // theme change. active_state_subscription_ handles the former, and the latter + // causes the whole toolbar to be repainted so not special logic is necessary. + raw_ptr<View> background_view_left_ = nullptr; + raw_ptr<View> background_view_right_ = nullptr; + + // Listens to changes to active state to update background_view_right_ and + // background_view_left_, as their background depends on active state. + base::CallbackListSubscription active_state_subscription_; }; #endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_VIEW_H_
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index df126b8..5544913 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -873,7 +873,7 @@ provider->install_finalizer().UninstallWebApp( app_id, webapps::WebappUninstallSource::kAppsPage, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { - EXPECT_TRUE(webapps::UninstallSucceeded(code)); + EXPECT_EQ(code, webapps::UninstallResultCode::kSuccess); run_loop.Quit(); })); run_loop.Run();
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc index f8e4e10..e90449d 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -45,6 +45,7 @@ FedCmAccountSelectionView::~FedCmAccountSelectionView() { notify_delegate_of_dismiss_ = false; + should_show_bubble_widget_ = false; Close(); TabStripModelObserver::StopObservingAll(this); @@ -130,9 +131,10 @@ GetBubbleView()->ShowMultiAccountPicker(idp_display_data_list_); } - if (create_bubble) { + if (create_bubble || should_show_bubble_widget_) { input_protector_->VisibilityChanged(true); bubble_widget_->Show(); + should_show_bubble_widget_ = false; } // Else: // Do not force show the bubble. The bubble may be purposefully hidden if the @@ -239,6 +241,11 @@ input_protector_ = std::move(input_protector); } +void FedCmAccountSelectionView::SetIdpSigninPopupWindowForTesting( + std::unique_ptr<FedCmModalDialogView> idp_signin_popup_window) { + idp_signin_modal_dialog_ = std::move(idp_signin_popup_window); +} + views::Widget* FedCmAccountSelectionView::CreateBubbleWithAccessibleTitle( const std::u16string& top_frame_etld_plus_one, const absl::optional<std::u16string>& iframe_etld_plus_one, @@ -369,16 +376,21 @@ content::WebContents* FedCmAccountSelectionView::ShowModalDialog( const GURL& url) { - idp_signin_modal_dialog_ = - FedCmModalDialogView::ShowPopupWindow(delegate_->GetWebContents(), url); + if (!idp_signin_modal_dialog_) { + idp_signin_modal_dialog_ = + std::make_unique<FedCmModalDialogView>(delegate_->GetWebContents()); + } + input_protector_->VisibilityChanged(false); bubble_widget_->Hide(); - return idp_signin_modal_dialog_->GetWebContents(); + return idp_signin_modal_dialog_->ShowPopupWindow(url); } void FedCmAccountSelectionView::CloseModalDialog() { if (idp_signin_modal_dialog_) { idp_signin_modal_dialog_->ClosePopupWindow(); + idp_signin_modal_dialog_.reset(); + should_show_bubble_widget_ = true; } if (show_accounts_dialog_callback_) {
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h index 3880bd4..d724a7b 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
@@ -74,6 +74,11 @@ void SetInputEventActivationProtectorForTesting( std::unique_ptr<views::InputEventActivationProtector>); + void SetIdpSigninPopupWindowForTesting(std::unique_ptr<FedCmModalDialogView>); + + // AccountSelectionBubbleView::Observer: + content::WebContents* ShowModalDialog(const GURL& url) override; + void CloseModalDialog() override; protected: friend class FedCmAccountSelectionViewBrowserTest; @@ -126,9 +131,7 @@ const ui::Event& event) override; void OnBackButtonClicked() override; void OnCloseButtonClicked(const ui::Event& event) override; - content::WebContents* ShowModalDialog(const GURL& url) override; void OnSigninToIdP() override; - void CloseModalDialog() override; void ShowVerifyingSheet(const Account& account, const IdentityProviderDisplayData& idp_display_data); @@ -161,9 +164,21 @@ std::unique_ptr<FedCmModalDialogView> idp_signin_modal_dialog_; - // Callback to show accounts dialog upon closing IDP sign-in modal dialog. + // If dialog has been populated with accounts as a result of the IDP sign-in + // flow but the IDP sign-in pop-up window has not been closed yet, we use this + // callback to show the accounts dialog upon closing the IDP sign-in pop-up + // window. This can happen when IDP sign-in status header is sent after the + // sign-in flow is complete but the pop-up window is not closed yet e.g. user + // is asked to verify phone number, change password, etc. base::OnceClosure show_accounts_dialog_callback_; + // If dialog has NOT been populated with accounts yet as a result of the IDP + // sign-in flow and the IDP sign-in pop-up window has been closed, we use this + // boolean to let bubble widget know it should unhide itself when the dialog + // is ready. This can happen when the accounts fetch has yet to finish but the + // pop-up window has already been closed. + bool should_show_bubble_widget_{false}; + base::WeakPtrFactory<FedCmAccountSelectionView> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc index 9038d13f..6e2bd1d 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc
@@ -92,6 +92,23 @@ std::vector<std::string> account_ids_; }; +// Mock version of FedCmModalDialogView for injection during tests. +class MockFedCmModalDialogView : public FedCmModalDialogView { + public: + explicit MockFedCmModalDialogView(content::WebContents* web_contents) + : FedCmModalDialogView(web_contents) {} + ~MockFedCmModalDialogView() override = default; + + MockFedCmModalDialogView(const MockFedCmModalDialogView&) = delete; + MockFedCmModalDialogView& operator=(const MockFedCmModalDialogView&) = delete; + + MOCK_METHOD(content::WebContents*, + ShowPopupWindow, + (const GURL& url), + (override)); + MOCK_METHOD(void, ClosePopupWindow, (), (override)); +}; + // Test FedCmAccountSelectionView which uses TestBubbleView. class TestFedCmAccountSelectionView : public FedCmAccountSelectionView { public: @@ -211,6 +228,26 @@ mode, show_auto_reauthn_checkbox); } + std::unique_ptr<TestFedCmAccountSelectionView> CreateAndShowFailureDialog() { + auto controller = std::make_unique<TestFedCmAccountSelectionView>( + delegate_.get(), widget_.get(), bubble_view_.get()); + controller->ShowFailureDialog(kTopFrameEtldPlusOne, kIframeEtldPlusOne, + kIdpEtldPlusOne, + content::IdentityProviderMetadata()); + return controller; + } + + void CreateAndShowPopupWindow(TestFedCmAccountSelectionView& controller) { + auto idp_signin_popup_window = + std::make_unique<MockFedCmModalDialogView>(test_web_contents_.get()); + EXPECT_CALL(*idp_signin_popup_window, ShowPopupWindow).Times(1); + EXPECT_CALL(*idp_signin_popup_window, ClosePopupWindow).Times(1); + controller.SetIdpSigninPopupWindowForTesting( + std::move(idp_signin_popup_window)); + + controller.ShowModalDialog(GURL(u"https://example.com")); + } + ui::MouseEvent CreateMouseEvent() { return ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0); @@ -319,14 +356,11 @@ // sign-in dialog. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchDialogToSigninFlow) { - auto controller = std::make_unique<TestFedCmAccountSelectionView>( - delegate_.get(), widget_.get(), bubble_view_.get()); + std::unique_ptr<TestFedCmAccountSelectionView> controller = + CreateAndShowFailureDialog(); AccountSelectionBubbleView::Observer* observer = static_cast<AccountSelectionBubbleView::Observer*>(controller.get()); - controller->ShowFailureDialog(kTopFrameEtldPlusOne, kIframeEtldPlusOne, - kIdpEtldPlusOne, - content::IdentityProviderMetadata()); EXPECT_EQ(TestBubbleView::SheetType::kFailure, bubble_view_->sheet_type_); const char kAccountId[] = "account_id"; @@ -350,14 +384,11 @@ // into the IdP in a different tab. TEST_F(FedCmAccountSelectionViewDesktopTest, IdpSigninStatusMismatchDialogToSigninFlowHidden) { - auto controller = std::make_unique<TestFedCmAccountSelectionView>( - delegate_.get(), widget_.get(), bubble_view_.get()); + std::unique_ptr<TestFedCmAccountSelectionView> controller = + CreateAndShowFailureDialog(); AccountSelectionBubbleView::Observer* observer = static_cast<AccountSelectionBubbleView::Observer*>(controller.get()); - controller->ShowFailureDialog(kTopFrameEtldPlusOne, kIframeEtldPlusOne, - kIdpEtldPlusOne, - content::IdentityProviderMetadata()); EXPECT_EQ(TestBubbleView::SheetType::kFailure, bubble_view_->sheet_type_); const char kAccountId[] = "account_id"; @@ -506,3 +537,77 @@ "Blink.FedCm.ClosedSheetType.Desktop", static_cast<int>(FedCmAccountSelectionView::SheetType::AUTO_REAUTHN), 1); } + +// Test transitioning from IdP sign-in status mismatch failure dialog to regular +// sign-in dialog. This emulates a user signing into the IdP in a pop-up window +// and the pop-up window closes PRIOR to the failure dialog being updated to a +// regular sign-in dialog. +TEST_F(FedCmAccountSelectionViewDesktopTest, + IdpSigninStatusPopupClosedBeforeAccountsPopulated) { + // Trigger IdP sign-in status mismatch failure dialog. + std::unique_ptr<TestFedCmAccountSelectionView> controller = + CreateAndShowFailureDialog(); + EXPECT_EQ(TestBubbleView::SheetType::kFailure, bubble_view_->sheet_type_); + + // Emulate user clicking on "Continue" button in the failure dialog. + CreateAndShowPopupWindow(*controller); + + // When pop-up window is shown, failure dialog should be hidden. + EXPECT_FALSE(widget_->IsVisible()); + + // Emulate user completing the sign-in flow and IdP prompts closing the pop-up + // window. + controller->CloseModalDialog(); + + // Failure dialog should remain hidden because it has not been updated to an + // accounts dialog yet. + EXPECT_FALSE(widget_->IsVisible()); + + // Emulate IdP sending the IdP sign-in status header which updates the failure + // dialog to an accounts dialog. + const char kAccountId[] = "account_id"; + IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData({ + {kAccountId, LoginState::kSignUp}, + }); + Show(*controller, idp_data.accounts, SignInMode::kExplicit); + + // Accounts dialog should now be visible. + EXPECT_TRUE(widget_->IsVisible()); +} + +// Test transitioning from IdP sign-in status mismatch failure dialog to regular +// sign-in dialog. This emulates a user signing into the IdP in a pop-up window +// and the pop-up window closes AFTER the failure dialog has been updated to a +// regular sign-in dialog. +TEST_F(FedCmAccountSelectionViewDesktopTest, + IdpSigninStatusPopupClosedAfterAccountsPopulated) { + // Trigger IdP sign-in status mismatch failure dialog. + std::unique_ptr<TestFedCmAccountSelectionView> controller = + CreateAndShowFailureDialog(); + EXPECT_EQ(TestBubbleView::SheetType::kFailure, bubble_view_->sheet_type_); + + // Emulate user clicking on "Continue" button in the failure dialog. + CreateAndShowPopupWindow(*controller); + + // When pop-up window is shown, failure dialog should be hidden. + EXPECT_FALSE(widget_->IsVisible()); + + // Emulate IdP sending the IdP sign-in status header which updates the failure + // dialog to an accounts dialog. + const char kAccountId[] = "account_id"; + IdentityProviderDisplayData idp_data = CreateIdentityProviderDisplayData({ + {kAccountId, LoginState::kSignUp}, + }); + Show(*controller, idp_data.accounts, SignInMode::kExplicit); + + // Accounts dialog should remain hidden because the pop-up window has not been + // closed yet. + EXPECT_FALSE(widget_->IsVisible()); + + // Emulate user completing the sign-in flow and IdP prompts closing the pop-up + // window. + controller->CloseModalDialog(); + + // Accounts dialog should now be visible. + EXPECT_TRUE(widget_->IsVisible()); +}
diff --git a/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.cc b/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.cc index ca24e11..51fe6ab 100644 --- a/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.cc +++ b/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.cc
@@ -13,32 +13,12 @@ #include "ui/views/layout/box_layout.h" #include "ui/views/layout/table_layout.h" -FedCmModalDialogView::FedCmModalDialogView(content::WebContents* web_contents, - const GURL& url) +FedCmModalDialogView::FedCmModalDialogView(content::WebContents* web_contents) : source_window_(web_contents) {} FedCmModalDialogView::~FedCmModalDialogView() = default; -// static -std::unique_ptr<FedCmModalDialogView> FedCmModalDialogView::ShowPopupWindow( - content::WebContents* web_contents, - const GURL& url) { - std::unique_ptr<FedCmModalDialogView> dialog = - std::make_unique<FedCmModalDialogView>(web_contents, url); - dialog->Open(url); - return dialog; -} - -void FedCmModalDialogView::ClosePopupWindow() { - popup_window_->Close(); -} - -content::WebContents* FedCmModalDialogView::GetWebContents() { - DCHECK(popup_window_); - return popup_window_; -} - -void FedCmModalDialogView::Open(const GURL& url) { +content::WebContents* FedCmModalDialogView::ShowPopupWindow(const GURL& url) { content::OpenURLParams params( url, content::Referrer(), WindowOpenDisposition::NEW_POPUP, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, /*is_renderer_initiated=*/false); @@ -54,4 +34,14 @@ popup_window_->GetDelegate()->SetContentsBounds( popup_window_, gfx::Rect(x_coordinate, y_coordinate, kPopupWindowWidth, kPopupWindowHeight)); + + return popup_window_; +} + +void FedCmModalDialogView::ClosePopupWindow() { + if (!popup_window_) { + return; + } + + popup_window_->Close(); }
diff --git a/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.h b/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.h index cbadb36..4eec5355 100644 --- a/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.h +++ b/chrome/browser/ui/views/webid/fedcm_modal_dialog_view.h
@@ -14,24 +14,17 @@ // TODO(crbug.com/1430830): Rename modal dialog to pop-up window. class FedCmModalDialogView { public: - FedCmModalDialogView(content::WebContents* web_contents, const GURL& url); + explicit FedCmModalDialogView(content::WebContents* web_contents); FedCmModalDialogView(const FedCmModalDialogView&) = delete; FedCmModalDialogView& operator=(const FedCmModalDialogView&) = delete; - ~FedCmModalDialogView(); + virtual ~FedCmModalDialogView(); - // Shows a modal dialog of |url| prompted by FedCM on |web_contents|. The - // |url| is commonly but not limited to a URL which allows the user to sign in - // with an identity provider. - static std::unique_ptr<FedCmModalDialogView> ShowPopupWindow( - content::WebContents* web_contents, - const GURL& url); - void ClosePopupWindow(); - - content::WebContents* GetWebContents(); + // Shows a modal dialog of |url|. The |url| is commonly but not limited to a + // URL which allows the user to sign in with an identity provider. + virtual content::WebContents* ShowPopupWindow(const GURL& url); + virtual void ClosePopupWindow(); private: - void Open(const GURL& url); - raw_ptr<content::WebContents> source_window_{nullptr}; raw_ptr<content::WebContents> popup_window_{nullptr};
diff --git a/chrome/browser/ui/views/webid/fedcm_modal_dialog_view_unittest.cc b/chrome/browser/ui/views/webid/fedcm_modal_dialog_view_unittest.cc index 43e5c5a..faef836 100644 --- a/chrome/browser/ui/views/webid/fedcm_modal_dialog_view_unittest.cc +++ b/chrome/browser/ui/views/webid/fedcm_modal_dialog_view_unittest.cc
@@ -56,13 +56,11 @@ TestDelegate delegate(web_contents()); std::unique_ptr<FedCmModalDialogView> popup_window = - FedCmModalDialogView::ShowPopupWindow(web_contents(), - GURL(u"https://example.com")); + std::make_unique<FedCmModalDialogView>(web_contents()); + content::WebContents* web_contents = + popup_window->ShowPopupWindow(GURL(u"https://example.com")); base::RunLoop().RunUntilIdle(); EXPECT_EQ(1, delegate.opened()); - - content::WebContents* popup_window_web_contents = - popup_window->GetWebContents(); - ASSERT_TRUE(popup_window_web_contents); + ASSERT_TRUE(web_contents); }
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 804c8119..3e23262 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -48,6 +48,7 @@ #include "chrome/browser/ui/webui/intro/intro_ui.h" #include "chrome/browser/ui/webui/invalidations/invalidations_ui.h" #include "chrome/browser/ui/webui/local_state/local_state_ui.h" +#include "chrome/browser/ui/webui/location_internals/location_internals_ui.h" #include "chrome/browser/ui/webui/log_web_ui_url.h" #include "chrome/browser/ui/webui/media/media_engagement_ui.h" #include "chrome/browser/ui/webui/media/media_history_ui.h" @@ -480,6 +481,9 @@ } if (url.host_piece() == chrome::kChromeUILocalStateHost) return &NewWebUI<LocalStateUI>; + if (url.host_piece() == chrome::kChromeUILocationInternalsHost) { + return &NewWebUI<LocationInternalsUI>; + } if (url.host_piece() == chrome::kChromeUIMemoryInternalsHost) return &NewWebUI<MemoryInternalsUI>; if (url.host_piece() == chrome::kChromeUIMetricsInternalsHost) @@ -1137,6 +1141,7 @@ GURL(chrome::kChromeUIInternetConfigDialogURL), GURL(chrome::kChromeUIInternetDetailDialogURL), GURL(chrome::kOsUIInvalidationsURL), + GURL(chrome::kChromeUILocationInternalsURL), GURL(chrome::kChromeUILockScreenNetworkURL), GURL(chrome::kChromeUILockScreenStartReauthURL), GURL(chrome::kChromeUIManageMirrorSyncURL), @@ -1207,6 +1212,7 @@ GURL(chrome::kChromeUIGpuURL), GURL(chrome::kChromeUIHistogramsURL), GURL(chrome::kChromeUIInvalidationsUrl), + GURL(chrome::kChromeUILocationInternalsURL), GURL(chrome::kChromeUIManagementURL), GURL(chrome::kChromeUIPolicyURL), GURL(chrome::kChromeUIRestartURL),
diff --git a/chrome/browser/ui/webui/location_internals/DIR_METADATA b/chrome/browser/ui/webui/location_internals/DIR_METADATA new file mode 100644 index 0000000..c400c68 --- /dev/null +++ b/chrome/browser/ui/webui/location_internals/DIR_METADATA
@@ -0,0 +1,4 @@ +monorail: { + component: "Blink>Geolocation" +} +team_email: "device-dev@chromium.org"
diff --git a/chrome/browser/ui/webui/location_internals/OWNERS b/chrome/browser/ui/webui/location_internals/OWNERS new file mode 100644 index 0000000..7be889d --- /dev/null +++ b/chrome/browser/ui/webui/location_internals/OWNERS
@@ -0,0 +1,4 @@ +file://content/browser/geolocation/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/location_internals/location_internals_ui.cc b/chrome/browser/ui/webui/location_internals/location_internals_ui.cc new file mode 100644 index 0000000..96c867c --- /dev/null +++ b/chrome/browser/ui/webui/location_internals/location_internals_ui.cc
@@ -0,0 +1,30 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/location_internals/location_internals_ui.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/location_internals_resources.h" +#include "chrome/grit/location_internals_resources_map.h" +#include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" +#include "ui/resources/grit/webui_resources.h" + +LocationInternalsUI::LocationInternalsUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui) { + // Set up the chrome://location-internals source. + content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd( + Profile::FromWebUI(web_ui), chrome::kChromeUILocationInternalsHost); + + webui::SetupWebUIDataSource(source, + base::make_span(kLocationInternalsResources, + kLocationInternalsResourcesSize), + IDR_LOCATION_INTERNALS_LOCATION_INTERNALS_HTML); +} + +LocationInternalsUI::~LocationInternalsUI() = default; + +WEB_UI_CONTROLLER_TYPE_IMPL(LocationInternalsUI)
diff --git a/chrome/browser/ui/webui/location_internals/location_internals_ui.h b/chrome/browser/ui/webui/location_internals/location_internals_ui.h new file mode 100644 index 0000000..d8f0f75bb --- /dev/null +++ b/chrome/browser/ui/webui/location_internals/location_internals_ui.h
@@ -0,0 +1,25 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_LOCATION_INTERNALS_LOCATION_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_LOCATION_INTERNALS_LOCATION_INTERNALS_UI_H_ + +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "ui/webui/mojo_web_ui_controller.h" + +// The WebUI for chrome://location-internals +class LocationInternalsUI : public ui::MojoWebUIController { + public: + explicit LocationInternalsUI(content::WebUI* web_ui); + + LocationInternalsUI(const LocationInternalsUI&) = delete; + LocationInternalsUI& operator=(const LocationInternalsUI&) = delete; + + ~LocationInternalsUI() override; + + private: + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_LOCATION_INTERNALS_LOCATION_INTERNALS_UI_H_
diff --git a/chrome/browser/ui/webui/location_internals/location_internals_ui_browsertest.cc b/chrome/browser/ui/webui/location_internals/location_internals_ui_browsertest.cc new file mode 100644 index 0000000..a386529 --- /dev/null +++ b/chrome/browser/ui/webui/location_internals/location_internals_ui_browsertest.cc
@@ -0,0 +1,19 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/webui_url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "url/gurl.h" + +using LocationInternalsUIBrowserTest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(LocationInternalsUIBrowserTest, + OpenLocationInternalsWebUI) { + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), + GURL(content::GetWebUIURL(chrome::kChromeUILocationInternalsHost)))); +}
diff --git a/chrome/browser/ui/webui/management/management_ui.cc b/chrome/browser/ui/webui/management/management_ui.cc index 386d6c8..089a9f6 100644 --- a/chrome/browser/ui/webui/management/management_ui.cc +++ b/chrome/browser/ui/webui/management/management_ui.cc
@@ -96,6 +96,10 @@ {kManagementScreenCaptureEvent, IDS_MANAGEMENT_SCREEN_CAPTURE_EVENT}, {kManagementScreenCaptureData, IDS_MANAGEMENT_SCREEN_CAPTURE_DATA}, #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + {kManagementDeviceSignalsDisclosure, + IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE}, +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) {"browserReporting", IDS_MANAGEMENT_BROWSER_REPORTING}, {"browserReportingExplanation", IDS_MANAGEMENT_BROWSER_REPORTING_EXPLANATION},
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.cc b/chrome/browser/ui/webui/management/management_ui_handler.cc index fcfd314..7b8783a7 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler.cc +++ b/chrome/browser/ui/webui/management/management_ui_handler.cc
@@ -86,6 +86,11 @@ #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +#include "chrome/browser/enterprise/signals/user_permission_service_factory.h" +#include "components/device_signals/core/browser/user_permission_service.h" // nogncheck +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + #include "build/chromeos_buildflags.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/common/extensions/permissions/chrome_permission_message_provider.h" @@ -178,6 +183,11 @@ const char kManagementScreenCaptureData[] = "managementScreenCaptureData"; #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +const char kManagementDeviceSignalsDisclosure[] = + "managementDeviceSignalsDisclosure"; +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + #if BUILDFLAG(IS_CHROMEOS) const char kManagementLogUploadEnabled[] = "managementLogUploadEnabled"; const char kManagementReportActivityTimes[] = "managementReportActivityTimes"; @@ -728,6 +738,18 @@ GetReportingTypeValue(report_definition.reporting_type)); report_sources->Append(std::move(data)); } +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + // Insert the device signals consent disclosure at the end of browser + // reporting section. + auto* user_permission_service = GetUserPermissionService(); + if (user_permission_service && user_permission_service->CanCollectSignals() == + device_signals::UserPermission::kGranted) { + base::Value::Dict data; + data.Set("messageId", kManagementDeviceSignalsDisclosure); + data.Set("reportingType", GetReportingTypeValue(ReportingType::kDevice)); + report_sources->Append(std::move(data)); + } +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) } #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -1025,6 +1047,14 @@ ->policy_service(); } +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +device_signals::UserPermissionService* +ManagementUIHandler::GetUserPermissionService() { + return enterprise_signals::UserPermissionServiceFactory::GetForProfile( + Profile::FromWebUI(web_ui())); +} +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + void ManagementUIHandler::AsyncUpdateLogo() { #if BUILDFLAG(IS_CHROMEOS_ASH) policy::BrowserPolicyConnectorAsh* connector =
diff --git a/chrome/browser/ui/webui/management/management_ui_handler.h b/chrome/browser/ui/webui/management/management_ui_handler.h index 26d34eda..55fca1d 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler.h +++ b/chrome/browser/ui/webui/management/management_ui_handler.h
@@ -31,6 +31,10 @@ extern const char kManagementScreenCaptureData[]; #endif // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +extern const char kManagementDeviceSignalsDisclosure[]; +#endif // #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + #if BUILDFLAG(IS_CHROMEOS) extern const char kManagementLogUploadEnabled[]; extern const char kManagementReportActivityTimes[]; @@ -110,6 +114,12 @@ class SystemLogUploader; } // namespace policy +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +namespace device_signals { +class UserPermissionService; +} // namespace device_signals +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + class Profile; // The JavaScript message handler for the chrome://management page. @@ -163,6 +173,9 @@ base::Value::Dict GetThreatProtectionInfo(Profile* profile); base::Value::List GetManagedWebsitesInfo(Profile* profile) const; virtual policy::PolicyService* GetPolicyService(); +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + virtual device_signals::UserPermissionService* GetUserPermissionService(); +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) #if BUILDFLAG(IS_CHROMEOS_ASH) // Protected for testing.
diff --git a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc index 94b4817..3b05434a2 100644 --- a/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc +++ b/chrome/browser/ui/webui/management/management_ui_handler_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/browser/ui/webui/management/management_ui_handler.h" #include <map> #include <memory> #include <set> @@ -20,7 +21,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/policy/dm_token_utils.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h" -#include "chrome/browser/ui/webui/management/management_ui_handler.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/ash/components/settings/cros_settings_names.h" @@ -104,6 +104,10 @@ #include "services/network/test/test_network_connection_tracker.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) +#include "components/device_signals/core/browser/mock_user_permission_service.h" // nogncheck +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "chromeos/lacros/lacros_test_helper.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) @@ -236,6 +240,17 @@ policy::PolicyService* GetPolicyService() override { return policy_service_; } +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + device_signals::UserPermissionService* GetUserPermissionService() override { + return user_permission_service_; + } + + void SetUserPermissionService( + device_signals::UserPermissionService* user_permission_service) { + user_permission_service_ = user_permission_service; + } +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + #if BUILDFLAG(IS_CHROMEOS_ASH) MOCK_METHOD(policy::DeviceCloudPolicyManagerAsh*, GetDeviceCloudPolicyManager, @@ -251,6 +266,9 @@ raw_ptr<policy::PolicyService> policy_service_ = nullptr; bool update_required_eol_ = false; std::string device_domain = "devicedomain.com"; +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + raw_ptr<device_signals::UserPermissionService> user_permission_service_; +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) }; // We need to use a different base class for ChromeOS and non ChromeOS case. @@ -511,6 +529,9 @@ base::Value::Dict data = handler_.GetContextualManagedDataForTesting(profile_.get()); ExtractContextualSourceUpdate(data); +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + handler_.SetUserPermissionService(&mock_user_permission_service_); +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) } bool GetManaged() const { return extracted_.managed; } @@ -619,6 +640,9 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) chromeos::ScopedLacrosServiceTestHelper scoped_lacros_test_helper_; #endif // BUILDFLAG(IS_CHROMEOS_LACROS) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + device_signals::MockUserPermissionService mock_user_permission_service_; +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) TestManagementUIHandler handler_; }; @@ -1288,6 +1312,11 @@ } TEST_F(ManagementUIHandlerTests, CloudReportingPolicy) { +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + SetUpProfileAndHandler(); + EXPECT_CALL(mock_user_permission_service_, CanCollectSignals()) + .WillOnce(Return(device_signals::UserPermission::kGranted)); +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) policy::PolicyMap chrome_policies; const policy::PolicyNamespace chrome_policies_namespace = policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()); @@ -1295,11 +1324,13 @@ .WillRepeatedly(ReturnRef(chrome_policies)); SetPolicyValue(policy::key::kCloudReportingEnabled, true, chrome_policies); - const std::set<std::string> expected_messages = { + std::set<std::string> expected_messages = { kManagementExtensionReportMachineName, kManagementExtensionReportUsername, kManagementExtensionReportVersion, kManagementExtensionReportExtensionsPlugin}; - +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) + expected_messages.insert(kManagementDeviceSignalsDisclosure); +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ASSERT_PRED_FORMAT2(MessagesToBeEQ, handler_.GetExtensionReportingInfo(), expected_messages); }
diff --git a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc index ae9ee75..2ed16041 100644 --- a/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc +++ b/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc
@@ -119,7 +119,7 @@ html_source->AddBoolean( "isSelfShareEnabled", - base::FeatureList::IsEnabled(features::kNearbySharingSelfShareUI)); + base::FeatureList::IsEnabled(features::kNearbySharingSelfShare)); } NearbyShareDialogUI::~NearbyShareDialogUI() = default;
diff --git a/chrome/browser/ui/webui/settings/ash/main_section.cc b/chrome/browser/ui/webui/settings/ash/main_section.cc index 35887bca2..b72d26c 100644 --- a/chrome/browser/ui/webui/settings/ash/main_section.cc +++ b/chrome/browser/ui/webui/settings/ash/main_section.cc
@@ -176,8 +176,12 @@ // This handler is for chrome://os-settings. html_source->AddBoolean("isOSSettings", true); + + // Add app-wide feature flags html_source->AddBoolean("searchFeedbackEnabled", ash::features::IsOsSettingsSearchFeedbackEnabled()); + html_source->AddBoolean("isRevampWayfindingEnabled", + ash::features::IsOsSettingsRevampWayfindingEnabled()); html_source->AddBoolean("isGuest", IsGuestModeActive()); html_source->AddBoolean(
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 8dec0428..308ef5e3 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -675,6 +675,10 @@ IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_HEADER}, {"tabDiscardingExceptionsAdditionalSites", IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADDITIONAL_SITES}, + {"tabDiscardingExceptionsAddDialogCurrentTabs", + IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADD_DIALOG_CURRENT_TABS}, + {"tabDiscardingExceptionsAddDialogManual", + IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADD_DIALOG_MANUAL}, }; html_source->AddLocalizedStrings(kLocalizedStrings); @@ -722,6 +726,11 @@ base::NumberToString16( performance_manager::user_tuning::UserPerformanceTuningManager:: kLowBatteryThresholdPercent))); + html_source->AddString( + "tabDiscardingExceptionsAddDialogHelp", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_PERFORMANCE_TAB_DISCARDING_EXCEPTIONS_ADD_DIALOG_HELP, + base::ASCIIToUTF16(chrome::kHighEfficiencyModeTabDiscardingHelpUrl))); html_source->AddString("highEfficiencyLearnMoreUrl", chrome::kHighEfficiencyModeLearnMoreUrl);
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index 59303e6..fc7d714 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -503,6 +503,10 @@ "isHighEfficiencyMultistateModeEnabled", base::FeatureList::IsEnabled( performance_manager::features::kHighEfficiencyMultistateMode)); + html_source->AddBoolean( + "isDiscardExceptionsImprovementsEnabled", + base::FeatureList::IsEnabled( + performance_manager::features::kDiscardExceptionsImprovements)); html_source->AddBoolean( "enablePermissionStorageAccessApi",
diff --git a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc index b77239d..6293cad 100644 --- a/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc +++ b/chrome/browser/ui/webui/side_panel/bookmarks/bookmarks_side_panel_ui.cc
@@ -101,6 +101,8 @@ {"addCurrentTab", IDS_READ_LATER_ADD_CURRENT_TAB}, {"emptyTitle", IDS_BOOKMARKS_EMPTY_STATE_TITLE}, {"emptyBody", IDS_BOOKMARKS_EMPTY_STATE_BODY}, + {"emptyTitleFolder", IDS_BOOKMARKS_EMPTY_STATE_TITLE_FOLDER}, + {"emptyBodyFolder", IDS_BOOKMARKS_EMPTY_STATE_BODY_FOLDER}, {"emptyTitleGuest", IDS_BOOKMARKS_EMPTY_STATE_TITLE_GUEST}, {"emptyBodyGuest", IDS_BOOKMARKS_EMPTY_STATE_BODY_GUEST}, {"emptyTitleSearch", IDS_BOOKMARKS_EMPTY_STATE_TITLE_SEARCH},
diff --git a/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc b/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc index eb5aff89..49a01ff5 100644 --- a/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/companion/companion_page_handler.cc
@@ -8,6 +8,7 @@ #include "chrome/browser/companion/core/companion_metrics_logger.h" #include "chrome/browser/companion/core/companion_permission_utils.h" #include "chrome/browser/companion/core/companion_url_builder.h" +#include "chrome/browser/companion/core/features.h" #include "chrome/browser/companion/core/promo_handler.h" #include "chrome/browser/companion/text_finder/text_finder_manager.h" #include "chrome/browser/companion/text_finder/text_highlighter_manager.h" @@ -18,6 +19,7 @@ #include "chrome/browser/ui/side_panel/companion/companion_side_panel_controller_utils.h" #include "chrome/browser/ui/side_panel/companion/companion_tab_helper.h" #include "chrome/browser/ui/side_panel/companion/companion_utils.h" +#include "chrome/browser/ui/side_panel/side_panel_enums.h" #include "chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.h" #include "chrome/browser/ui/webui/side_panel/companion/signin_delegate_impl.h" #include "chrome/browser/unified_consent/unified_consent_service_factory.h" @@ -88,6 +90,12 @@ ukm::SourceId ukm_source_id = web_contents()->GetPrimaryMainFrame()->GetPageUkmSourceId(); metrics_logger_ = std::make_unique<CompanionMetricsLogger>(ukm_source_id); + auto* tab_helper = + companion::CompanionTabHelper::FromWebContents(web_contents()); + auto open_trigger = tab_helper->GetAndResetMostRecentSidePanelOpenTrigger(); + if (open_trigger.has_value()) { + metrics_logger_->RecordOpenTrigger(open_trigger); + } // Only notify the companion UI the page changed if we can share // information about the page by user consent.
diff --git a/chrome/browser/upgrade_detector/get_installed_version_mac.mm b/chrome/browser/upgrade_detector/get_installed_version_mac.mm index 1f01c077..3b97fdd 100644 --- a/chrome/browser/upgrade_detector/get_installed_version_mac.mm +++ b/chrome/browser/upgrade_detector/get_installed_version_mac.mm
@@ -14,10 +14,6 @@ #include "chrome/browser/updater/browser_updater_client_util.h" #include "chrome/common/chrome_features.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - namespace { InstalledAndCriticalVersion GetInstalledVersionSynchronous() {
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index 20063154..afc99ad 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -190,8 +190,6 @@ "remove_web_app_job.h", "scope_extension_info.cc", "scope_extension_info.h", - "uninstall_request.cc", - "uninstall_request.h", "user_display_mode.cc", "user_display_mode.h", "user_uninstalled_preinstalled_web_app_prefs.cc", @@ -274,6 +272,8 @@ "web_contents/web_app_icon_downloader.h", "web_contents/web_app_url_loader.cc", "web_contents/web_app_url_loader.h", + "web_contents/web_contents_manager.cc", + "web_contents/web_contents_manager.h", ] if (is_chromeos) {
diff --git a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc index cfa1853e..7e2a65e0 100644 --- a/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc +++ b/chrome/browser/web_applications/commands/fetch_manifest_and_install_command.cc
@@ -153,7 +153,11 @@ use_fallback_(use_fallback), data_retriever_(std::move(data_retriever)), install_error_log_entry_(/*background_installation=*/false, - install_surface_) {} + install_surface_) { + debug_log_.Set("visible_url", web_contents_->GetVisibleURL().spec()); + debug_log_.Set("last_committed_url", + web_contents_->GetLastCommittedURL().spec()); +} FetchManifestAndInstallCommand::~FetchManifestAndInstallCommand() = default;
diff --git a/chrome/browser/web_applications/commands/manifest_update_check_command.cc b/chrome/browser/web_applications/commands/manifest_update_check_command.cc index d13ee75..af8cd77 100644 --- a/chrome/browser/web_applications/commands/manifest_update_check_command.cc +++ b/chrome/browser/web_applications/commands/manifest_update_check_command.cc
@@ -27,7 +27,8 @@ base::Time check_time, base::WeakPtr<content::WebContents> web_contents, CompletedCallback callback, - std::unique_ptr<WebAppDataRetriever> data_retriever) + std::unique_ptr<WebAppDataRetriever> data_retriever, + std::unique_ptr<WebAppIconDownloader> icon_downloader) : WebAppCommandTemplate<AppLock>("ManifestUpdateCheckCommand"), url_(url), app_id_(app_id), @@ -35,7 +36,8 @@ completed_callback_(std::move(callback)), lock_description_(app_id), web_contents_(web_contents), - data_retriever_(std::move(data_retriever)) {} + data_retriever_(std::move(data_retriever)), + icon_downloader_(std::move(icon_downloader)) {} ManifestUpdateCheckCommand::~ManifestUpdateCheckCommand() = default; @@ -174,9 +176,8 @@ IconDownloaderOptions options = {.skip_page_favicons = true, .fail_all_if_any_fail = true}; - icon_downloader_.emplace(web_contents_.get(), std::move(icon_urls), - std::move(next_step_callback), options); - icon_downloader_->Start(); + icon_downloader_->Start(web_contents_.get(), icon_urls, + std::move(next_step_callback), options); } void ManifestUpdateCheckCommand::StashNewIconBitmaps(
diff --git a/chrome/browser/web_applications/commands/manifest_update_check_command.h b/chrome/browser/web_applications/commands/manifest_update_check_command.h index c6d8b55..46d521adb1 100644 --- a/chrome/browser/web_applications/commands/manifest_update_check_command.h +++ b/chrome/browser/web_applications/commands/manifest_update_check_command.h
@@ -59,7 +59,8 @@ base::Time check_time, base::WeakPtr<content::WebContents> web_contents, CompletedCallback callback, - std::unique_ptr<WebAppDataRetriever> data_retriever); + std::unique_ptr<WebAppDataRetriever> data_retriever, + std::unique_ptr<WebAppIconDownloader> icon_downloader); ~ManifestUpdateCheckCommand() override; @@ -145,7 +146,7 @@ std::unique_ptr<AppLock> lock_; base::WeakPtr<content::WebContents> web_contents_; std::unique_ptr<WebAppDataRetriever> data_retriever_; - absl::optional<WebAppIconDownloader> icon_downloader_; + std::unique_ptr<WebAppIconDownloader> icon_downloader_; // Temporary variables stored here while the update check progresses // asynchronously.
diff --git a/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc b/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc index 1158ba13..c77cf1e 100644 --- a/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc +++ b/chrome/browser/web_applications/commands/manifest_update_check_command_unittest.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_ui_manager.h" +#include "chrome/browser/web_applications/web_contents/web_app_icon_downloader.h" #include "components/services/app_service/public/cpp/url_handler_info.h" #include "components/webapps/browser/installable/installable_logging.h" #include "content/public/browser/web_contents.h" @@ -371,7 +372,8 @@ output_result.new_install_info = std::move(new_install_info); loop.Quit(); }), - std::move(data_retriever))); + std::move(data_retriever), + std::make_unique<WebAppIconDownloader>())); loop.Run(); return output_result; }
diff --git a/chrome/browser/web_applications/commands/web_app_uninstall_command.cc b/chrome/browser/web_applications/commands/web_app_uninstall_command.cc index 76dfe21..90bab879 100644 --- a/chrome/browser/web_applications/commands/web_app_uninstall_command.cc +++ b/chrome/browser/web_applications/commands/web_app_uninstall_command.cc
@@ -12,7 +12,6 @@ #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" #include "base/strings/to_string.h" -#include "base/types/pass_key.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/locks/all_apps_lock.h" #include "chrome/browser/web_applications/remove_web_app_job.h" @@ -48,90 +47,104 @@ uninstall_source == webapps::WebappUninstallSource::kTestCleanup; } -enum class InstallUrlActionNeeded { - kNone, - kRemoveInstallUrl, - kRemoveInstallSource, -}; - -InstallUrlActionNeeded GetInstallUrlActionNeeded( - const WebApp::ExternalConfigMap& config_map, - const UninstallRequest& request) { - auto it = config_map.find(*request.install_source()); - if (it == config_map.end()) { - return InstallUrlActionNeeded::kNone; - } - - const WebApp::ExternalManagementConfig& config = it->second; - const base::flat_set<GURL>& install_urls = config.install_urls; - if (install_urls.empty()) { - // TODO(crbug.com/1427340): Return a different UninstallResultCode - // for this case and log it in metrics. - return InstallUrlActionNeeded::kRemoveInstallSource; - } - if (install_urls.size() == 1 && - install_urls.contains(*request.install_url())) { - return InstallUrlActionNeeded::kRemoveInstallSource; - } - - return InstallUrlActionNeeded::kRemoveInstallUrl; -} - -enum class InstallSourceActionNeeded { - kNone, - kRemoveInstallSource, - kRemoveApp, -}; - -InstallSourceActionNeeded GetInstallSourceActionNeeded( - const WebAppSources& sources, - WebAppManagement::Type install_source) { - if (sources.none()) { - // TODO(crbug.com/1427340): Return a different UninstallResultCode - // for this case and log it in metrics. - return InstallSourceActionNeeded::kRemoveApp; - } - - if (!sources[install_source]) { - return InstallSourceActionNeeded::kNone; - } - - if (sources.count() > 1) { - return InstallSourceActionNeeded::kRemoveInstallSource; - } - - return InstallSourceActionNeeded::kRemoveApp; -} - } // namespace -WebAppUninstallCommand::WebAppUninstallCommand(UninstallRequest request, - UninstallWebAppCallback callback, - Profile& profile) +WebAppUninstallCommand::WebAppUninstallCommand( + const AppId& app_id, + absl::optional<WebAppManagement::Type> management_type_or_all, + webapps::WebappUninstallSource uninstall_source, + UninstallWebAppCallback callback, + Profile& profile) : WebAppCommandTemplate<AllAppsLock>("WebAppUninstallCommand"), lock_description_(std::make_unique<AllAppsLockDescription>()), - initial_request_app_id_(request.app_id()), + app_id_(app_id), callback_(std::move(callback)), profile_(profile) { - webapps::InstallableMetrics::TrackUninstallEvent(request.uninstall_source()); + // Initializing data for uninstallation tracking. + queued_uninstalls_.emplace_back(app_id_, management_type_or_all, + uninstall_source); - request_queue_.push_back(std::move(request)); + webapps::InstallableMetrics::TrackUninstallEvent(uninstall_source); } WebAppUninstallCommand::~WebAppUninstallCommand() = default; void WebAppUninstallCommand::StartWithLock(std::unique_ptr<AllAppsLock> lock) { lock_ = std::move(lock); - ProcessRequestQueueOrComplete(); + + while (!queued_uninstalls_.empty()) { + DCHECK(!all_uninstalled_queued_); + const UninstallInfo current_uninstall = + std::move(queued_uninstalls_.back()); + queued_uninstalls_.pop_back(); + AppendUninstallInfoToDebugLog(current_uninstall); + + const AppId& app_id = current_uninstall.app_id; + const WebApp* app = lock_->registrar().GetAppById(app_id); + if (!app) { + uninstall_results_[app_id] = + webapps::UninstallResultCode::kNoAppToUninstall; + AppendUninstallResultsToDebugLog(app_id); + continue; + } + + // This contains the external uninstall logic. + if (current_uninstall.management_type_or_all.has_value()) { + const WebAppManagement::Type source = + current_uninstall.management_type_or_all.value(); + // If there is more than a single source, then we can just remove the + // source from the web_app DB. Else we end up calling Uninstall() at the + // end. + if (!app->HasOnlySource(source)) { + // There is a chance that removed source type is NOT user uninstallable + // but the remaining source (after removal) types are user + // uninstallable. In this case, the following call will register os + // uninstallation. + apps_pending_uninstall_[app_id] = nullptr; + MaybeRegisterOsUninstall( + app, source, lock_->os_integration_manager(), + base::BindOnce(&WebAppUninstallCommand:: + RemoveManagementTypeAfterOsUninstallRegistration, + weak_factory_.GetWeakPtr(), app_id, source, + current_uninstall.uninstall_source)); + } else { + Uninstall(app_id, current_uninstall.uninstall_source); + } + } else { + // This contains the user uninstall and sync uninstall logic. + DCHECK( + CanUninstallAllManagementSources(current_uninstall.uninstall_source)); + // The following DCHECK streamlines the user uninstall and sync uninstall + // flow, because for sync uninstalls, the web_app source is removed before + // being synced, so the first condition fails by the time an Uninstall is + // invoked. + DCHECK(app->CanUserUninstallWebApp() || + current_uninstall.uninstall_source == + webapps::WebappUninstallSource::kSync); + if (app->IsPreinstalledApp()) { + // Update the default uninstalled web_app prefs if it is a preinstalled + // app but being removed by user. + const WebApp::ExternalConfigMap& config_map = + app->management_to_external_config_map(); + auto it = config_map.find(WebAppManagement::kDefault); + if (it != config_map.end()) { + UserUninstalledPreinstalledWebAppPrefs(profile_->GetPrefs()) + .Add(app_id, it->second.install_urls); + } else { + base::UmaHistogramBoolean( + "WebApp.Preinstalled.ExternalConfigMapAbsentDuringUninstall", + true); + } + } + Uninstall(app_id, current_uninstall.uninstall_source); + } + } + all_uninstalled_queued_ = true; + MaybeFinishUninstallAndDestruct(); } void WebAppUninstallCommand::OnShutdown() { - CHECK(callback_); - base::UmaHistogramBoolean("WebApp.Uninstall.Result", false); - SignalCompletionAndSelfDestruct( - CommandResult::kShutdown, - base::BindOnce(std::move(callback_), - webapps::UninstallResultCode::kError)); + Abort(webapps::UninstallResultCode::kError); return; } @@ -140,251 +153,122 @@ } base::Value WebAppUninstallCommand::ToDebugValue() const { - base::Value::Dict dict; - - base::Value::List requests; - for (const UninstallRequest& request : request_queue_) { - requests.Append(request.ToDebugValue()); - } - dict.Set("request_queue", std::move(requests)); - - dict.Set("initial_request_app_id", initial_request_app_id_); - - base::Value::List results; - for (const std::pair<AppId, webapps::UninstallResultCode>& pair : - uninstall_results_) { - base::Value::Dict result; - result.Set(pair.first, base::ToString(pair.second)); - } - dict.Set("uninstall_results", std::move(results)); - - dict.Set("active_remove_web_app_job", bool(active_remove_web_app_job_)); - - return base::Value(std::move(dict)); + base::Value::Dict uninstall_info; + uninstall_info.Set("command_data", debug_log_.Clone()); + return base::Value(std::move(uninstall_info)); } -//////////////////////////////////////////////////////////////////////////////// -// Process request queue. -//////////////////////////////////////////////////////////////////////////////// - -void WebAppUninstallCommand::ProcessRequestQueueOrComplete() { - if (request_queue_.empty()) { - CHECK(base::Contains(uninstall_results_, initial_request_app_id_)); - webapps::UninstallResultCode code = - uninstall_results_[initial_request_app_id_]; - base::UmaHistogramBoolean("WebApp.Uninstall.Result", - webapps::UninstallSucceeded(code)); - SignalCompletionAndSelfDestruct(CommandResult::kSuccess, - base::BindOnce(std::move(callback_), code)); - return; - } - - UninstallRequest request = std::move(request_queue_.front()); - request_queue_.pop_front(); - - auto request_complete_callback = - base::BindOnce(&WebAppUninstallCommand::RequestComplete, - weak_factory_.GetWeakPtr(), request.app_id()); - - if (request.install_url()) { - RemoveInstallUrl(request, std::move(request_complete_callback)); - } else if (request.install_source()) { - RemoveInstallSource(request, std::move(request_complete_callback)); - } else { - RemoveApp(request, std::move(request_complete_callback)); - } -} - -void WebAppUninstallCommand::RequestComplete( +WebAppUninstallCommand::UninstallInfo::UninstallInfo( AppId app_id, - webapps::UninstallResultCode code) { - CHECK(!base::Contains(uninstall_results_, app_id)); - uninstall_results_[app_id] = code; - ProcessRequestQueueOrComplete(); + absl::optional<WebAppManagement::Type> management_type_or_all, + webapps::WebappUninstallSource uninstall_source) + : app_id(app_id), + management_type_or_all(management_type_or_all), + uninstall_source(uninstall_source) {} + +WebAppUninstallCommand::UninstallInfo::~UninstallInfo() = default; + +WebAppUninstallCommand::UninstallInfo::UninstallInfo( + const UninstallInfo& uninstall_info) = default; + +WebAppUninstallCommand::UninstallInfo::UninstallInfo( + UninstallInfo&& uninstall_info) = default; + +void WebAppUninstallCommand::AppendUninstallInfoToDebugLog( + const UninstallInfo& uninstall_info) { + base::Value::Dict source_info; + if (uninstall_info.management_type_or_all.has_value()) { + source_info.Set( + "management_type", + base::ToString(uninstall_info.management_type_or_all.value())); + } + source_info.Set("uninstall_source", ConvertUninstallSourceToStringType( + uninstall_info.uninstall_source)); + debug_log_.Set(uninstall_info.app_id, base::Value(std::move(source_info))); } -//////////////////////////////////////////////////////////////////////////////// -// Remove install URL. -//////////////////////////////////////////////////////////////////////////////// +void WebAppUninstallCommand::AppendUninstallResultsToDebugLog( + const AppId& app_id) { + base::Value::Dict* app_dict = debug_log_.FindDict(app_id); + DCHECK(app_dict); + app_dict->Set("uninstall_result", webapps::ConvertUninstallResultCodeToString( + uninstall_results_[app_id])); +} -void WebAppUninstallCommand::RemoveInstallUrl( - const UninstallRequest& request, - RequestCompleteCallback callback) { - CHECK(request.install_source()); - CHECK(request.install_url()); - - const WebApp* app = lock_->registrar().GetAppById(request.app_id()); - if (!app) { - std::move(callback).Run(webapps::UninstallResultCode::kNoAppToUninstall); +void WebAppUninstallCommand::Abort(webapps::UninstallResultCode code) { + base::UmaHistogramBoolean("WebApp.Uninstall.Result", + (code == webapps::UninstallResultCode::kSuccess)); + if (!callback_) return; - } + SignalCompletionAndSelfDestruct(CommandResult::kFailure, + base::BindOnce(std::move(callback_), code)); +} - switch (GetInstallUrlActionNeeded(app->management_to_external_config_map(), - request)) { - case InstallUrlActionNeeded::kNone: - std::move(callback).Run(webapps::UninstallResultCode::kSuccess); - return; +void WebAppUninstallCommand::Uninstall( + const AppId& app_id, + webapps::WebappUninstallSource uninstall_source) { + QueueSubAppsForUninstallIfAny(app_id); + apps_pending_uninstall_[app_id] = RemoveWebAppJob::Start( + uninstall_source, app_id, *lock_, profile_.get(), + base::BindOnce(&WebAppUninstallCommand::OnSingleUninstallComplete, + weak_factory_.GetWeakPtr(), app_id, uninstall_source)); +} - case InstallUrlActionNeeded::kRemoveInstallUrl: { - { - ScopedRegistryUpdate update(&lock_->sync_bridge()); - CHECK(update->UpdateApp(request.app_id()) - ->RemoveInstallUrlForSource(*request.install_source(), - *request.install_url())); - } - - std::move(callback).Run(webapps::UninstallResultCode::kSuccess); - return; - } - - case InstallUrlActionNeeded::kRemoveInstallSource: - RemoveInstallSource( - UninstallRequest(base::PassKey<WebAppUninstallCommand>(), - /*is_sub_request=*/true, request.uninstall_source(), - request.app_id(), request.install_source()), - std::move(callback)); - return; +void WebAppUninstallCommand::QueueSubAppsForUninstallIfAny( + const AppId& app_id) { + std::vector<AppId> sub_app_ids = lock_->registrar().GetAllSubAppIds(app_id); + for (const AppId& sub_app_id : sub_app_ids) { + queued_uninstalls_.emplace_back( + sub_app_id, WebAppManagement::kSubApp, + webapps::WebappUninstallSource::kParentUninstall); } } -//////////////////////////////////////////////////////////////////////////////// -// Remove install source. -//////////////////////////////////////////////////////////////////////////////// - -void WebAppUninstallCommand::RemoveInstallSource( - const UninstallRequest& request, - RequestCompleteCallback callback) { - CHECK(request.install_source()); - CHECK(!request.install_url()); - - const WebApp* app = lock_->registrar().GetAppById(request.app_id()); - if (!app) { - std::move(callback).Run(webapps::UninstallResultCode::kNoAppToUninstall); - return; - } - - WebAppManagement::Type install_source = *request.install_source(); - switch (GetInstallSourceActionNeeded(app->GetSources(), install_source)) { - case InstallSourceActionNeeded::kNone: - // TODO(crbug.com/1427340): Return a different UninstallResultCode - // for when no action is taken instead of being overly specific to the "no - // app" case. - std::move(callback).Run(webapps::UninstallResultCode::kNoAppToUninstall); - return; - - case InstallSourceActionNeeded::kRemoveInstallSource: - MaybeRegisterOsUninstall( - app, install_source, lock_->os_integration_manager(), - base::BindOnce( - &WebAppUninstallCommand::RemoveInstallSourceFromDatabase, - weak_factory_.GetWeakPtr(), request.app_id(), - *request.install_source(), std::move(callback))); - - return; - - case InstallSourceActionNeeded::kRemoveApp: - RemoveApp(UninstallRequest(base::PassKey<WebAppUninstallCommand>(), - /*is_sub_request=*/true, - request.uninstall_source(), request.app_id()), - std::move(callback)); - return; - } -} - -void WebAppUninstallCommand::RemoveInstallSourceFromDatabase( - AppId app_id, - WebAppManagement::Type install_source, - RequestCompleteCallback callback, +void WebAppUninstallCommand::RemoveManagementTypeAfterOsUninstallRegistration( + const AppId& app_id, + const WebAppManagement::Type& management_type, + webapps::WebappUninstallSource uninstall_source, OsHooksErrors os_hooks_errors) { { ScopedRegistryUpdate update(&lock_->sync_bridge()); - WebApp* app = update->UpdateApp(app_id); - app->RemoveSource(install_source); - if (install_source == WebAppManagement::kSubApp) { - app->SetParentAppId(absl::nullopt); + WebApp* app_to_update = update->UpdateApp(app_id); + app_to_update->RemoveSource(management_type); + if (management_type == WebAppManagement::kSubApp) { + app_to_update->SetParentAppId(absl::nullopt); } - // TODO(crbug.com/1447308): Make sync uninstall not synchronously - // remove its sync install source even while a command has an app lock so - // that we can CHECK(app->HasAnySources()) here. } lock_->install_manager().NotifyWebAppSourceRemovedForTesting(app_id); - std::move(callback).Run(webapps::UninstallResultCode::kSuccess); + // Registering an OS uninstall is also an "uninstall", so the + // state is updated for the command. + OnSingleUninstallComplete(app_id, uninstall_source, + /*success=*/true); } -//////////////////////////////////////////////////////////////////////////////// -// Remove app. -//////////////////////////////////////////////////////////////////////////////// - -void WebAppUninstallCommand::RemoveApp(const UninstallRequest& request, - RequestCompleteCallback callback) { - CHECK(!request.install_source().has_value()); - CHECK(!request.install_url().has_value()); - - if (!request.is_sub_request()) { - CHECK(CanUninstallAllManagementSources(request.uninstall_source())); - } - - const WebApp* app = lock_->registrar().GetAppById(request.app_id()); - if (!app) { - std::move(callback).Run(webapps::UninstallResultCode::kNoAppToUninstall); - return; - } - - if (!request.is_sub_request()) { - // The following CHECK streamlines the user uninstall and sync uninstall - // flow, because for sync uninstalls, the web_app source is removed before - // being synced, so the first condition fails by the time an Uninstall is - // invoked. - // TODO(crbug.com/1447308): Checking kSync shouldn't be needed once - // this issue is resolved. - // TODO(crbug.com/1427340): Change this to be: - // if (uninstall_source is user initiated) { - // CHECK(user can uninstall); - // Add to user uninstalled prefs. - // } - CHECK(app->CanUserUninstallWebApp() || - request.uninstall_source() == webapps::WebappUninstallSource::kSync); - - if (app->IsPreinstalledApp()) { - // Update the default uninstalled web_app prefs if it is a preinstalled - // app but being removed by user. - const WebApp::ExternalConfigMap& config_map = - app->management_to_external_config_map(); - auto it = config_map.find(WebAppManagement::kDefault); - if (it != config_map.end()) { - UserUninstalledPreinstalledWebAppPrefs(profile_->GetPrefs()) - .Add(request.app_id(), it->second.install_urls); - } else { - base::UmaHistogramBoolean( - "WebApp.Preinstalled.ExternalConfigMapAbsentDuringUninstall", true); - } - } - } - - for (const AppId& sub_app_id : - lock_->registrar().GetAllSubAppIds(request.app_id())) { - request_queue_.emplace_back( - base::PassKey<WebAppUninstallCommand>(), - /*is_sub_request=*/true, - webapps::WebappUninstallSource::kParentUninstall, sub_app_id, - WebAppManagement::kSubApp); - } - - active_remove_web_app_job_ = RemoveWebAppJob::Start( - request.uninstall_source(), request.app_id(), *lock_, profile_.get(), - base::BindOnce(&WebAppUninstallCommand::OnUninstallJobComplete, - weak_factory_.GetWeakPtr(), std::move(callback))); -} - -void WebAppUninstallCommand::OnUninstallJobComplete( - RequestCompleteCallback callback, +void WebAppUninstallCommand::OnSingleUninstallComplete( + const AppId& app_id, + webapps::WebappUninstallSource source, bool success) { - CHECK(active_remove_web_app_job_); - active_remove_web_app_job_.reset(); - std::move(callback).Run(success ? webapps::UninstallResultCode::kSuccess - : webapps::UninstallResultCode::kError); + DCHECK(base::Contains(apps_pending_uninstall_, app_id)); + apps_pending_uninstall_.erase(app_id); + + if (source == webapps::WebappUninstallSource::kSync) { + base::UmaHistogramBoolean("Webapp.SyncInitiatedUninstallResult", success); + } + uninstall_results_[app_id] = success ? webapps::UninstallResultCode::kSuccess + : webapps::UninstallResultCode::kError; + AppendUninstallResultsToDebugLog(app_id); + MaybeFinishUninstallAndDestruct(); +} + +void WebAppUninstallCommand::MaybeFinishUninstallAndDestruct() { + if (apps_pending_uninstall_.empty() && all_uninstalled_queued_) { + // All uninstall jobs have finished. + SignalCompletionAndSelfDestruct( + CommandResult::kSuccess, + base::BindOnce(std::move(callback_), uninstall_results_[app_id_])); + } } } // namespace web_app
diff --git a/chrome/browser/web_applications/commands/web_app_uninstall_command.h b/chrome/browser/web_applications/commands/web_app_uninstall_command.h index f96bf52..c11d8f5 100644 --- a/chrome/browser/web_applications/commands/web_app_uninstall_command.h +++ b/chrome/browser/web_applications/commands/web_app_uninstall_command.h
@@ -12,9 +12,9 @@ #include "base/functional/callback_forward.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/values.h" #include "chrome/browser/web_applications/commands/web_app_command.h" #include "chrome/browser/web_applications/os_integration/os_integration_manager.h" -#include "chrome/browser/web_applications/uninstall_request.h" #include "chrome/browser/web_applications/web_app_id.h" #include "components/webapps/browser/installable/installable_metrics.h" #include "components/webapps/browser/uninstall_result_code.h" @@ -22,10 +22,6 @@ class Profile; -namespace base { -class Value; -} - namespace webapps { enum class UninstallResultCode; enum class WebappUninstallSource; @@ -69,9 +65,12 @@ using RemoveManagementTypeCallback = base::RepeatingCallback<void(const AppId& app_id)>; - WebAppUninstallCommand(UninstallRequest request, - UninstallWebAppCallback callback, - Profile& profile); + WebAppUninstallCommand( + const AppId& app_id, + absl::optional<WebAppManagement::Type> management_type_or_all, + webapps::WebappUninstallSource uninstall_source, + UninstallWebAppCallback callback, + Profile& profile); ~WebAppUninstallCommand() override; // WebAppCommandTemplate<AllAppsLock>: @@ -81,33 +80,49 @@ base::Value ToDebugValue() const override; private: - using RequestCompleteCallback = - base::OnceCallback<void(webapps::UninstallResultCode)>; + // Used to store information needed for uninstalling an app with app_id. + struct UninstallInfo { + UninstallInfo(AppId app_id, + absl::optional<WebAppManagement::Type> management_type_or_all, + webapps::WebappUninstallSource uninstall_source); + ~UninstallInfo(); + UninstallInfo(const UninstallInfo& uninstall_info); + UninstallInfo(UninstallInfo&& uninstall_info); + UninstallInfo& operator=(const UninstallInfo& uninstall_info) = delete; + UninstallInfo& operator=(UninstallInfo&& uninstall_info) = delete; - void ProcessRequestQueueOrComplete(); - void RequestComplete(AppId app_id, webapps::UninstallResultCode code); + AppId app_id; + absl::optional<WebAppManagement::Type> management_type_or_all; + webapps::WebappUninstallSource uninstall_source; + }; - void RemoveInstallUrl(const UninstallRequest& request, - RequestCompleteCallback callback); - - void RemoveInstallSource(const UninstallRequest& request, - RequestCompleteCallback callback); - void RemoveInstallSourceFromDatabase(AppId app_id, - WebAppManagement::Type install_source, - RequestCompleteCallback callback, - OsHooksErrors os_hooks_errors); - - void RemoveApp(const UninstallRequest& request, - RequestCompleteCallback callback); - void OnUninstallJobComplete(RequestCompleteCallback callback, bool success); + void AppendUninstallInfoToDebugLog(const UninstallInfo& uninstall_info); + void AppendUninstallResultsToDebugLog(const AppId& app_id); + void Abort(webapps::UninstallResultCode code); + void Uninstall(const AppId& app_id, + webapps::WebappUninstallSource uninstall_source); + void QueueSubAppsForUninstallIfAny(const AppId& app_id); + void RemoveManagementTypeAfterOsUninstallRegistration( + const AppId& app_id, + const WebAppManagement::Type& install_source, + webapps::WebappUninstallSource uninstall_source, + OsHooksErrors os_hooks_errors); + void OnSingleUninstallComplete(const AppId& app_id, + webapps::WebappUninstallSource source, + bool success); + void MaybeFinishUninstallAndDestruct(); std::unique_ptr<AllAppsLockDescription> lock_description_; std::unique_ptr<AllAppsLock> lock_; - base::circular_deque<UninstallRequest> request_queue_; - const AppId initial_request_app_id_; + const AppId app_id_; + base::circular_deque<UninstallInfo> queued_uninstalls_; base::flat_map<AppId, webapps::UninstallResultCode> uninstall_results_; - std::unique_ptr<RemoveWebAppJob> active_remove_web_app_job_; + base::flat_map<AppId, std::unique_ptr<RemoveWebAppJob>> + apps_pending_uninstall_; + base::Value::Dict debug_log_; + bool all_uninstalled_queued_ = false; + UninstallWebAppCallback callback_; // `this` is owned by `profile_`. @@ -118,4 +133,4 @@ } // namespace web_app -#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_WEB_APP_UNINSTALL_COMMAND_H_ +#endif // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_WEB_APP_INSTALL_COMMAND_H_
diff --git a/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc b/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc index c0986ff4..e59b4f8 100644 --- a/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc +++ b/chrome/browser/web_applications/commands/web_app_uninstall_command_unittest.cc
@@ -101,7 +101,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kSuccess, code); loop.Quit(); @@ -137,8 +137,8 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id, - WebAppManagement::kDefault), + app_id, WebAppManagement::kDefault, + webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kSuccess, code); loop.Quit(); @@ -174,7 +174,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kError, code); loop.Quit(); @@ -211,7 +211,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kError, code); loop.Quit(); @@ -242,7 +242,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kNoAppToUninstall, code); loop.Quit(); @@ -276,7 +276,7 @@ provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kError, code); }), @@ -316,7 +316,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kSuccess, code); loop.Quit(); @@ -354,7 +354,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kAppMenu, app_id), + app_id, absl::nullopt, webapps::WebappUninstallSource::kAppMenu, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kSuccess, code); loop.Quit(); @@ -417,8 +417,8 @@ base::RunLoop run_loop; auto command = std::make_unique<WebAppUninstallCommand>( - UninstallRequest(webapps::WebappUninstallSource::kExternalPolicy, app_id, - WebAppManagement::kPolicy), + app_id, WebAppManagement::kPolicy, + webapps::WebappUninstallSource::kExternalPolicy, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kSuccess, code); run_loop.Quit(); @@ -479,7 +479,7 @@ base::RunLoop loop; provider()->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(GetParam().source, app_id), + app_id, absl::nullopt, GetParam().source, base::BindLambdaForTesting([&](webapps::UninstallResultCode code) { EXPECT_EQ(webapps::UninstallResultCode::kSuccess, code); loop.Quit();
diff --git a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc index 1c97aee..df77281 100644 --- a/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc +++ b/chrome/browser/web_applications/extensions/externally_managed_app_install_task_unittest.cc
@@ -373,9 +373,8 @@ auto task = std::make_unique<ExternallyManagedAppInstallTask>( profile(), url_loader_.get(), ui_manager_, install_finalizer_, - command_scheduler_, std::move(options)); - task->SetDataRetrieverFactoryForTesting( - GetFactoryForRetriever(std::move(data_retriever))); + command_scheduler_, GetFactoryForRetriever(std::move(data_retriever)), + std::move(options)); return task; } @@ -895,7 +894,8 @@ ExternalInstallSource::kInternalDefault); ExternallyManagedAppInstallTask install_task( profile(), &url_loader(), ui_manager(), finalizer(), - command_scheduler(), install_options); + command_scheduler(), /*data_retriever_factory=*/base::NullCallback(), + install_options); url_loader().SetPrepareForLoadResultLoaded(); url_loader().SetNextLoadUrlResult(GURL(), result_pair.loader_result); @@ -917,7 +917,7 @@ ExternalInstallSource::kInternalDefault); ExternallyManagedAppInstallTask install_task( profile(), &url_loader(), ui_manager(), finalizer(), command_scheduler(), - install_options); + base::NullCallback(), install_options); url_loader().SetPrepareForLoadResultLoaded(); url_loader().SetNextLoadUrlResult( GURL(), WebAppUrlLoader::Result::kFailedWebContentsDestroyed); @@ -944,9 +944,9 @@ return info; }); - ExternallyManagedAppInstallTask task(profile(), /*url_loader=*/nullptr, - ui_manager(), finalizer(), - command_scheduler(), std::move(options)); + ExternallyManagedAppInstallTask task( + profile(), /*url_loader=*/nullptr, ui_manager(), finalizer(), + command_scheduler(), base::NullCallback(), std::move(options)); finalizer()->SetNextFinalizeInstallResult( kWebAppUrl, webapps::InstallResultCode::kSuccessNewInstall); @@ -992,9 +992,9 @@ return info; }); - ExternallyManagedAppInstallTask task(profile(), /*url_loader=*/nullptr, - ui_manager(), finalizer(), - command_scheduler(), std::move(options)); + ExternallyManagedAppInstallTask task( + profile(), /*url_loader=*/nullptr, ui_manager(), finalizer(), + command_scheduler(), base::NullCallback(), std::move(options)); finalizer()->SetNextFinalizeInstallResult( kWebAppUrl, webapps::InstallResultCode::kWriteDataFailed);
diff --git a/chrome/browser/web_applications/externally_managed_app_install_task.cc b/chrome/browser/web_applications/externally_managed_app_install_task.cc index 71f12f7..2887821 100644 --- a/chrome/browser/web_applications/externally_managed_app_install_task.cc +++ b/chrome/browser/web_applications/externally_managed_app_install_task.cc
@@ -49,6 +49,7 @@ WebAppUiManager* ui_manager, WebAppInstallFinalizer* install_finalizer, WebAppCommandScheduler* command_scheduler, + DataRetrieverFactory data_retriever_factory, ExternalInstallOptions install_options) : profile_(profile), url_loader_(url_loader), @@ -56,6 +57,7 @@ install_finalizer_(install_finalizer), command_scheduler_(command_scheduler), externally_installed_app_prefs_(profile_->GetPrefs()), + data_retriever_factory_(std::move(data_retriever_factory)), install_options_(std::move(install_options)) {} ExternallyManagedAppInstallTask::~ExternallyManagedAppInstallTask() = default; @@ -239,11 +241,6 @@ void ExternallyManagedAppInstallTask::ContinueWebAppInstall( content::WebContents* web_contents, ResultCallback result_callback) { - if (!data_retriever_factory_) { - data_retriever_factory_ = base::BindRepeating( - []() { return std::make_unique<WebAppDataRetriever>(); }); - } - command_scheduler_->InstallExternallyManagedApp( install_options_, base::BindOnce(
diff --git a/chrome/browser/web_applications/externally_managed_app_install_task.h b/chrome/browser/web_applications/externally_managed_app_install_task.h index 55e5ad1..54391840d 100644 --- a/chrome/browser/web_applications/externally_managed_app_install_task.h +++ b/chrome/browser/web_applications/externally_managed_app_install_task.h
@@ -44,6 +44,8 @@ public: using ResultCallback = base::OnceCallback<void( ExternallyManagedAppManager::InstallResult result)>; + using DataRetrieverFactory = + base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()>; // Constructs a task that will install a Web App for |profile|. // |install_options| will be used to decide some of the properties of the @@ -54,6 +56,7 @@ WebAppUiManager* ui_manager, WebAppInstallFinalizer* install_finalizer, WebAppCommandScheduler* command_scheduler, + DataRetrieverFactory data_retriever_factory, ExternalInstallOptions install_options); ExternallyManagedAppInstallTask(const ExternallyManagedAppInstallTask&) = @@ -71,8 +74,7 @@ const ExternalInstallOptions& install_options() { return install_options_; } - using DataRetrieverFactory = - base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()>; + // TODO(http://b/283521737): Remove this and use WebContentsManager. void SetDataRetrieverFactoryForTesting( DataRetrieverFactory data_retriever_factory); @@ -126,8 +128,8 @@ ExternallyInstalledWebAppPrefs externally_installed_app_prefs_; - const ExternalInstallOptions install_options_; DataRetrieverFactory data_retriever_factory_; + const ExternalInstallOptions install_options_; base::WeakPtrFactory<ExternallyManagedAppInstallTask> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.cc b/chrome/browser/web_applications/externally_managed_app_manager.cc index 1020fbfb..8a509f7 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager.cc
@@ -31,6 +31,7 @@ #include "chrome/browser/web_applications/web_app_registry_update.h" #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h" #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h" +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" #include "chrome/common/chrome_features.h" #include "components/webapps/browser/install_result_code.h" #include "content/public/browser/web_contents.h" @@ -95,7 +96,7 @@ }; ExternallyManagedAppManager::ExternallyManagedAppManager(Profile* profile) - : profile_(profile), url_loader_(std::make_unique<WebAppUrlLoader>()) {} + : profile_(profile) {} ExternallyManagedAppManager::~ExternallyManagedAppManager() { DCHECK(!registration_callback_); @@ -109,10 +110,27 @@ void ExternallyManagedAppManager::SetSubsystems( WebAppUiManager* ui_manager, WebAppInstallFinalizer* finalizer, - WebAppCommandScheduler* command_scheduler) { + WebAppCommandScheduler* command_scheduler, + WebContentsManager* web_contents_manager) { ui_manager_ = ui_manager; finalizer_ = finalizer; command_scheduler_ = command_scheduler; + if (!web_contents_manager) { + CHECK_IS_TEST(); + } else { + // TODO(http://b/283521737): Remove this and use WebContentsManager. + url_loader_ = web_contents_manager->CreateUrlLoader(); + // TODO(http://b/283521737): Remove this and use WebContentsManager. + data_retriever_factory_ = base::BindRepeating( + [](base::WeakPtr<WebContentsManager> web_contents_manager) + -> std::unique_ptr<WebAppDataRetriever> { + if (!web_contents_manager) { + return nullptr; + } + return web_contents_manager->CreateDataRetriever(); + }, + web_contents_manager->GetWeakPtr()); + } } void ExternallyManagedAppManager::InstallNow( @@ -219,7 +237,7 @@ void ExternallyManagedAppManager::SetDataRetrieverFactoryForTesting( base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()> factory) { CHECK_IS_TEST(); - data_retriever_factory_for_testing_ = std::move(factory); + data_retriever_factory_ = std::move(factory); } void ExternallyManagedAppManager::ReleaseWebContents() { @@ -237,12 +255,8 @@ std::unique_ptr<ExternallyManagedAppInstallTask> install_task = std::make_unique<ExternallyManagedAppInstallTask>( profile_, url_loader_.get(), ui_manager(), finalizer(), - command_scheduler(), std::move(install_options)); - if (data_retriever_factory_for_testing_) { - CHECK_IS_TEST(); - install_task->SetDataRetrieverFactoryForTesting( // IN-TEST - data_retriever_factory_for_testing_); - } + command_scheduler(), data_retriever_factory_, + std::move(install_options)); return install_task; }
diff --git a/chrome/browser/web_applications/externally_managed_app_manager.h b/chrome/browser/web_applications/externally_managed_app_manager.h index de3f154..b1d63d3 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager.h +++ b/chrome/browser/web_applications/externally_managed_app_manager.h
@@ -37,12 +37,13 @@ class AllAppsLock; class ExternallyManagedAppInstallTask; -class WebAppInstallFinalizer; -class WebAppCommandScheduler; -class WebAppUiManager; class ExternallyManagedAppRegistrationTaskBase; -class WebAppUrlLoader; +class WebAppCommandScheduler; class WebAppDataRetriever; +class WebAppInstallFinalizer; +class WebAppUiManager; +class WebAppUrlLoader; +class WebContentsManager; enum class RegistrationResultCode { kSuccess, kAlreadyRegistered, kTimeout }; @@ -107,7 +108,8 @@ void SetSubsystems(WebAppUiManager* ui_manager, WebAppInstallFinalizer* finalizer, - WebAppCommandScheduler* command_scheduler); + WebAppCommandScheduler* command_scheduler, + WebContentsManager* web_contents_manager); // Queues an installation operation with the highest priority. Essentially // installing the app immediately if there are no ongoing operations or @@ -172,7 +174,9 @@ void Shutdown(); + // TODO(http://b/283521737): Remove this and use WebContentsManager. void SetUrlLoaderForTesting(std::unique_ptr<WebAppUrlLoader> url_loader); + // TODO(http://b/283521737): Remove this and use WebContentsManager. void SetDataRetrieverFactoryForTesting( base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()> factory); @@ -267,7 +271,7 @@ std::unique_ptr<WebAppUrlLoader> url_loader_; // Allows tests to set the data retriever for install tasks. base::RepeatingCallback<std::unique_ptr<WebAppDataRetriever>()> - data_retriever_factory_for_testing_; + data_retriever_factory_; std::unique_ptr<content::WebContents> web_contents_;
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc index ae2edc9..3a43b11f 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager_impl_unittest.cc
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/functional/callback_helpers.h" #include "chrome/browser/web_applications/externally_managed_app_manager.h" #include <map> @@ -285,6 +286,7 @@ externally_managed_app_manager_impl->ui_manager(), externally_managed_app_manager_impl->finalizer(), externally_managed_app_manager_impl->command_scheduler(), + /*data_retriever_factory=*/base::NullCallback(), std::move(install_options)), externally_managed_app_manager_impl_( externally_managed_app_manager_impl),
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc index 788f2489..b8a316ad16 100644 --- a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc +++ b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
@@ -34,6 +34,7 @@ #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_helpers.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_registry_update.h" #include "chrome/browser/web_applications/web_app_sync_bridge.h" @@ -393,19 +394,6 @@ void SetUp() override { WebAppTest::SetUp(); - provider_ = web_app::FakeWebAppProvider::Get(profile()); - std::unique_ptr<ExternallyManagedAppManager> external_app_manager = - std::make_unique<ExternallyManagedAppManager>(profile()); - external_app_manager->SetUrlLoaderForTesting( - web_contents_manager_.CreateUrlLoader()); - - external_app_manager->SetDataRetrieverFactoryForTesting( - base::BindLambdaForTesting( - [fake_web_contents = web_contents_manager_.GetWeakPtr()]() { - CHECK(fake_web_contents); - return fake_web_contents->CreateDataRetriever(); - })); - provider_->SetExternallyManagedAppManager(std::move(external_app_manager)); // TODO(http://b/278922549): Disable the external management apps so we // don't compete with the policy app manager for our installs / // synchronization. @@ -434,17 +422,17 @@ return output; } - WebAppProvider& provider() { return *provider_; } + WebAppProvider& provider() { return *WebAppProvider::GetForTest(profile()); } WebAppRegistrar& app_registrar() { return provider().registrar_unsafe(); } - ExternallyManagedAppManager& external_mananager() { - return static_cast<ExternallyManagedAppManager&>( - provider().externally_managed_app_manager()); + ExternallyManagedAppManager& external_manager() { + return provider().externally_managed_app_manager(); } FakeWebContentsManager& web_contents_manager() { - return web_contents_manager_; + return static_cast<FakeWebContentsManager&>( + provider().web_contents_manager()); } AppId PopulateBasicInstallPageWithManifest(GURL install_url, @@ -456,7 +444,7 @@ install_page_state.redirection_url = absl::nullopt; install_page_state.page_install_info = std::make_unique<WebAppInstallInfo>( - GenerateManifestIdFromStartUrlOnly(start_url)); + GenerateManifestIdFromStartUrlOnly(install_url)); install_page_state.page_install_info->title = u"Basic app title"; install_page_state.manifest_url = manifest_url; @@ -468,7 +456,6 @@ install_page_state.opt_manifest->start_url = start_url; install_page_state.opt_manifest->id = GenerateManifestIdFromStartUrlOnly(start_url); - install_page_state.opt_manifest->display = blink::mojom::DisplayMode::kStandalone; install_page_state.opt_manifest->short_name = u"Basic app name"; @@ -477,8 +464,6 @@ } private: - raw_ptr<FakeWebAppProvider> provider_; - FakeWebContentsManager web_contents_manager_; base::test::ScopedFeatureList scoped_feature_list_; }; @@ -489,7 +474,7 @@ // non-functional / not available. SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl}, ExternalInstallSource::kExternalPolicy), ExternalInstallSource::kExternalPolicy, result.GetCallback()); @@ -518,7 +503,7 @@ kStartUrl); SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl}, ExternalInstallSource::kExternalPolicy), ExternalInstallSource::kExternalPolicy, result.GetCallback()); @@ -553,7 +538,7 @@ EXPECT_EQ(app_id, app_id2); SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl1, kInstallUrl2}, ExternalInstallSource::kExternalPolicy), ExternalInstallSource::kExternalPolicy, result.GetCallback()); @@ -589,113 +574,6 @@ /*additional_policy_ids=*/{})))); } -TEST_F(ExternallyAppManagerTest, RemovingInstallUrlsFromSource) { - const GURL kStartUrl = GURL("https://www.example.com/index.html"); - const GURL kInstallUrl1 = - GURL("https://www.example.com/nested/install_url.html"); - const GURL kInstallUrl2 = - GURL("https://www.example.com/nested/install_url2.html"); - const GURL kManifestUrl = GURL("https://www.example.com/manifest.json"); - - AppId app_id = PopulateBasicInstallPageWithManifest(kInstallUrl1, - kManifestUrl, kStartUrl); - AppId app_id2 = PopulateBasicInstallPageWithManifest(kInstallUrl2, - kManifestUrl, kStartUrl); - EXPECT_EQ(app_id, app_id2); - - // Synchronize with 2 install URLs. - { - SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( - CreateExternalInstallOptionsFromTemplate( - {kInstallUrl1, kInstallUrl2}, - ExternalInstallSource::kExternalPolicy), - ExternalInstallSource::kExternalPolicy, result.GetCallback()); - ASSERT_TRUE(result.Wait()); - - // Empty uninstall results. - EXPECT_THAT(result.Get<UninstallResults>(), IsEmpty()); - - // Installs should have both succeeded. - EXPECT_THAT( - result.Get<InstallResults>(), - UnorderedElementsAre( - std::make_pair( - kInstallUrl1, - ExternallyManagedAppManager::InstallResult( - webapps::InstallResultCode::kSuccessNewInstall, app_id)), - std::make_pair( - kInstallUrl2, - ExternallyManagedAppManager::InstallResult( - webapps::InstallResultCode::kSuccessNewInstall, app_id)))); - - EXPECT_EQ(app_registrar().GetAppIds().size(), 1ul); - const WebApp* app = app_registrar().GetAppById(app_id); - ASSERT_TRUE(app); - EXPECT_THAT(app->management_to_external_config_map(), - ElementsAre(std::make_pair( - WebAppManagement::kPolicy, - WebApp::ExternalManagementConfig( - /*is_placeholder=*/false, - /*install_urls=*/{kInstallUrl1, kInstallUrl2}, - /*additional_policy_ids=*/{})))); - } - - // Synchronize with 1 install URL. - { - SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( - CreateExternalInstallOptionsFromTemplate( - {kInstallUrl1}, ExternalInstallSource::kExternalPolicy), - ExternalInstallSource::kExternalPolicy, result.GetCallback()); - ASSERT_TRUE(result.Wait()); - - // Empty install results. - EXPECT_THAT(result.Get<InstallResults>(), - UnorderedElementsAre(std::make_pair( - kInstallUrl1, - ExternallyManagedAppManager::InstallResult( - webapps::InstallResultCode::kSuccessAlreadyInstalled, - app_id)))); - - // One install URL uninstalled. - EXPECT_THAT(result.Get<UninstallResults>(), - UnorderedElementsAre(std::make_pair(kInstallUrl2, true))); - - EXPECT_EQ(app_registrar().GetAppIds().size(), 1ul); - const WebApp* app = app_registrar().GetAppById(app_id); - ASSERT_TRUE(app); - EXPECT_THAT(app->management_to_external_config_map(), - ElementsAre(std::make_pair(WebAppManagement::kPolicy, - WebApp::ExternalManagementConfig( - /*is_placeholder=*/false, - /*install_urls=*/{kInstallUrl1}, - /*additional_policy_ids=*/{})))); - } - - // Synchronize with 0 install URLs. - { - SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( - CreateExternalInstallOptionsFromTemplate( - {}, ExternalInstallSource::kExternalPolicy), - ExternalInstallSource::kExternalPolicy, result.GetCallback()); - ASSERT_TRUE(result.Wait()); - - // Empty install results. - EXPECT_THAT(result.Get<InstallResults>(), IsEmpty()); - - // One install URL uninstalled. - EXPECT_THAT(result.Get<UninstallResults>(), - UnorderedElementsAre(std::make_pair(kInstallUrl1, true))); - - // App should be cleaned up. - EXPECT_EQ(app_registrar().GetAppIds().size(), 0ul); - const WebApp* app = app_registrar().GetAppById(app_id); - ASSERT_FALSE(app); - } -} - TEST_F(ExternallyAppManagerTest, InstallUrlChanges) { const GURL kStartUrl = GURL("https://www.example.com/index.html"); const GURL kInstallUrl = @@ -713,7 +591,7 @@ // First synchronize will install the app. { SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl}, ExternalInstallSource::kExternalPolicy), ExternalInstallSource::kExternalPolicy, result.GetCallback()); @@ -733,7 +611,7 @@ // the install urls correctly. { SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl2}, ExternalInstallSource::kExternalPolicy), ExternalInstallSource::kExternalPolicy, result.GetCallback()); @@ -777,8 +655,7 @@ web_contents_manager().GetOrCreatePageState(kInstallUrl); install_page_state.opt_manifest->short_name = u"Test user app"; - auto install_info = std::make_unique<WebAppInstallInfo>( - GenerateManifestIdFromStartUrlOnly(kStartUrl)); + auto install_info = std::make_unique<WebAppInstallInfo>(); install_info->start_url = kStartUrl; install_info->title = u"Test user app"; absl::optional<AppId> user_app_id = @@ -822,7 +699,7 @@ template_options.install_placeholder = true; SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl}, ExternalInstallSource::kExternalPolicy, template_options), @@ -868,7 +745,7 @@ page_state.redirection_url = kRedirectToUrl; SynchronizeFuture result; - provider().externally_managed_app_manager().SynchronizeInstalledApps( + external_manager().SynchronizeInstalledApps( CreateExternalInstallOptionsFromTemplate( {kInstallUrl}, ExternalInstallSource::kExternalPolicy, template_options),
diff --git a/chrome/browser/web_applications/test/fake_data_retriever.cc b/chrome/browser/web_applications/test/fake_data_retriever.cc index de5d1b0..f9b0c348 100644 --- a/chrome/browser/web_applications/test/fake_data_retriever.cc +++ b/chrome/browser/web_applications/test/fake_data_retriever.cc
@@ -47,7 +47,7 @@ } void FakeDataRetriever::GetIcons(content::WebContents* web_contents, - base::flat_set<GURL> icon_urls, + const base::flat_set<GURL>& icon_urls, bool skip_page_favicons, GetIconsCallback callback) { if (get_icons_delegate_) {
diff --git a/chrome/browser/web_applications/test/fake_data_retriever.h b/chrome/browser/web_applications/test/fake_data_retriever.h index ae0b81b..b05d501 100644 --- a/chrome/browser/web_applications/test/fake_data_retriever.h +++ b/chrome/browser/web_applications/test/fake_data_retriever.h
@@ -39,7 +39,7 @@ CheckInstallabilityCallback callback, absl::optional<webapps::InstallableParams> params) override; void GetIcons(content::WebContents* web_contents, - base::flat_set<GURL> icon_urls, + const base::flat_set<GURL>& icon_urls, bool skip_page_favicons, GetIconsCallback callback) override;
diff --git a/chrome/browser/web_applications/test/fake_web_app_provider.cc b/chrome/browser/web_applications/test/fake_web_app_provider.cc index e83fa2b..cb78dfb1 100644 --- a/chrome/browser/web_applications/test/fake_web_app_provider.cc +++ b/chrome/browser/web_applications/test/fake_web_app_provider.cc
@@ -11,8 +11,10 @@ #include "base/check.h" #include "base/command_line.h" #include "base/functional/bind.h" +#include "base/functional/callback_helpers.h" #include "base/memory/scoped_refptr.h" #include "base/one_shot_event.h" +#include "base/test/bind.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/externally_managed_app_manager.h" #include "chrome/browser/web_applications/manifest_update_manager.h" @@ -23,6 +25,7 @@ #include "chrome/browser/web_applications/test/fake_os_integration_manager.h" #include "chrome/browser/web_applications/test/fake_web_app_database_factory.h" #include "chrome/browser/web_applications/test/fake_web_app_ui_manager.h" +#include "chrome/browser/web_applications/test/fake_web_contents_manager.h" #include "chrome/browser/web_applications/test/test_file_utils.h" #include "chrome/browser/web_applications/web_app_command_manager.h" #include "chrome/browser/web_applications/web_app_command_scheduler.h" @@ -36,6 +39,9 @@ #include "chrome/browser/web_applications/web_app_translation_manager.h" #include "chrome/browser/web_applications/web_app_ui_manager.h" #include "chrome/browser/web_applications/web_app_utils.h" +#include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h" +#include "chrome/browser/web_applications/web_contents/web_app_url_loader.h" +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" #include "chrome/common/chrome_switches.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/core/keyed_service.h" @@ -185,6 +191,12 @@ origin_association_manager_ = std::move(origin_association_manager); } +void FakeWebAppProvider::SetWebContentsManager( + std::unique_ptr<WebContentsManager> web_contents_manager) { + CheckNotStartedAndDisconnect(); + web_contents_manager_ = std::move(web_contents_manager); +} + WebAppRegistrarMutable& FakeWebAppProvider::GetRegistrarMutable() const { DCHECK(registrar_); return *static_cast<WebAppRegistrarMutable*>(registrar_.get()); @@ -243,6 +255,8 @@ SetRegistrar(std::make_unique<WebAppRegistrarMutable>(profile_)); SetDatabaseFactory(std::make_unique<FakeWebAppDatabaseFactory>()); + SetWebContentsManager(std::make_unique<FakeWebContentsManager>()); + SetOsIntegrationManager(std::make_unique<FakeOsIntegrationManager>( profile_, /*app_shortcut_manager=*/nullptr, /*file_handler_manager=*/nullptr,
diff --git a/chrome/browser/web_applications/test/fake_web_app_provider.h b/chrome/browser/web_applications/test/fake_web_app_provider.h index fe1ad29..0e7a66b 100644 --- a/chrome/browser/web_applications/test/fake_web_app_provider.h +++ b/chrome/browser/web_applications/test/fake_web_app_provider.h
@@ -27,20 +27,54 @@ namespace web_app { class AbstractWebAppDatabaseFactory; -class WebAppRegistrar; -class OsIntegrationManager; -class WebAppInstallFinalizer; class ExternallyManagedAppManager; +class OsIntegrationManager; +class PreinstalledWebAppManager; +class WebAppCommandManager; +class WebAppIconManager; +class WebAppInstallFinalizer; class WebAppInstallManager; class WebAppPolicyManager; -class WebAppIconManager; -class WebAppTranslationManager; +class WebAppRegistrar; class WebAppRegistrarMutable; class WebAppSyncBridge; +class WebAppTranslationManager; class WebAppUiManager; -class WebAppCommandManager; -class PreinstalledWebAppManager; +class WebContentsManager; +// This is a tool that allows unit tests (enabled by default) and browser tests +// (disabled by default) to use a 'fake' version of the WebAppProvider system. +// This means that most of the dependencies are faked out. Specifically: +// * The database is in-memory. +// * Integration with Chrome Sync is off. +// * OS integration (saving shortcuts on disk, etc) doesn't execute, but does +// save its 'expected' state to the database. +// * All access to `WebContents` is redirected to the `FakeWebContentsManager` +// (accessible via `GetFakeWebContentsManager()`), which stores & returns +// results for any interaction here. +// +// Other features & notes: +// * FakeWebAppProvider is used by default in unit tests, as the +// `TestingProfile` hardcodes the usage of this fake version in the +// `KeyedServiceFactory` for the profile, +// * The system in NOT 'started' by default, which means commands and other +// operations will not run. This allows tests to do any customization they may +// want by calling `FakeWebAppProvider::Get()` and interacting with this +// object before the system is started. +// * Generally the system is then started by calling +// `web_app::test::AwaitStartWebAppProviderAndSubsystems(profile());`, which +// waits for the system to be `ready()`, but also for any external install +// managers to finish startup as well. +// * To use this in browser tests, you must use the FakeWebAppProviderCreator +// below. +// +// Future improvements: +// * TODO(http://b/257529391): Isolate the extensions system dependency to +// allow faking that as well. +// * TODO(http://b/279198384): Make better default for external manager behavior +// in unittests. Perhaps don't start them by default unless they specified. +// * TODO(http://b/279198562): Create a `FakeWebAppCommandScheduler`, allowing +// external systems to fully fake out usage of this system if they desire. class FakeWebAppProvider : public WebAppProvider { public: // Used by the TestingProfile in unit tests. @@ -101,6 +135,8 @@ void SetOriginAssociationManager( std::unique_ptr<WebAppOriginAssociationManager> origin_association_manager); + void SetWebContentsManager( + std::unique_ptr<WebContentsManager> web_contents_manager); // These getters can be called at any time: no // WebAppProvider::CheckIsConnected() check performed. See @@ -153,6 +189,7 @@ // If true, preinstalled apps will be processed & installed (or uninstalled) // after the system starts. bool synchronize_preinstalled_app_on_startup_ = false; + testing::NiceMock<syncer::MockModelTypeChangeProcessor> mock_processor_; };
diff --git a/chrome/browser/web_applications/test/fake_web_contents_manager.cc b/chrome/browser/web_applications/test/fake_web_contents_manager.cc index 46b7b6a..b9cd715d 100644 --- a/chrome/browser/web_applications/test/fake_web_contents_manager.cc +++ b/chrome/browser/web_applications/test/fake_web_contents_manager.cc
@@ -44,6 +44,8 @@ } } // namespace +// TODO(http://b/262606416): Replace FakeWebAppUrlLoader with this by redoing +// how the web contents dependency is wrapped. class FakeWebContentsManager::FakeUrlLoader : public WebAppUrlLoader { public: explicit FakeUrlLoader(base::WeakPtr<FakeWebContentsManager> manager) @@ -96,6 +98,91 @@ SEQUENCE_CHECKER(sequence_checker_); }; +class FakeWebContentsManager::FakeWebAppIconDownloader + : public WebAppIconDownloader { + public: + explicit FakeWebAppIconDownloader( + base::WeakPtr<FakeWebContentsManager> web_contents_manager) + : manager_(std::move(web_contents_manager)) {} + ~FakeWebAppIconDownloader() override = default; + + void Start(content::WebContents* web_contents, + const base::flat_set<GURL>& extra_icon_urls, + WebAppIconDownloaderCallback callback, + IconDownloaderOptions options) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(manager_); + IconsMap icons_map; + DownloadedIconsHttpResults per_icon_results; + for (const GURL& icon_url : extra_icon_urls) { + auto icons_it = manager_->icon_state_.find(icon_url); + if (icons_it == manager_->icon_state_.end()) { + per_icon_results[icon_url] = 404; + continue; + } + FakeWebContentsManager::FakeIconState& icon = icons_it->second; + // The real implementation includes these CHECK statements, so this does + // too. + CHECK_LE(100, icon.http_status_code); + CHECK_GT(600, icon.http_status_code); + if (icon.trigger_primary_page_changed_if_fetched) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), + IconsDownloadedResult::kPrimaryPageChanged, + IconsMap{}, DownloadedIconsHttpResults{})); + return; + } + icons_map[icon_url] = icon.bitmaps; + per_icon_results[icon_url] = icon.http_status_code; + if (icon.bitmaps.empty() && options.fail_all_if_any_fail) { + // TODO: Test this codepath when migrating the + // ManifestUpdateCheckCommand to use WebContentsManager. + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), + IconsDownloadedResult::kAbortedDueToFailure, + IconsMap{}, std::move(per_icon_results))); + return; + } + } + + // Add favicon if requested & available. + if (!options.skip_page_favicons) { + GURL url = manager_->loaded_urls_[web_contents]; + CHECK(url.is_valid() || url.is_empty()) + << "No url has been loaded on this web contents. " << url.spec(); + auto page_it = manager_->page_state_.find(url); + if (page_it != manager_->page_state_.end()) { + FakeWebContentsManager::FakePageState& page = page_it->second; + if (!page.favicon_url.is_empty()) { + icons_map[page.favicon_url] = page.favicon; + per_icon_results[page.favicon_url] = page.favicon.empty() ? 404 : 200; + if (page.favicon.empty() && options.fail_all_if_any_fail) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), + IconsDownloadedResult::kAbortedDueToFailure, + IconsMap{}, std::move(per_icon_results))); + return; + } + } + } + } + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), IconsDownloadedResult::kCompleted, + std::move(icons_map), std::move(per_icon_results))); + } + + private: + base::WeakPtr<FakeWebContentsManager> manager_; + + SEQUENCE_CHECKER(sequence_checker_); +}; + +// TODO(http://b/262606416): Replace FakeDataRetriever with this by redoing +// how the web contents dependency is wrapped. class FakeWebContentsManager::FakeWebAppDataRetriever : public WebAppDataRetriever { public: @@ -163,54 +250,20 @@ } void GetIcons(content::WebContents* web_contents, - base::flat_set<GURL> icon_urls, + const base::flat_set<GURL>& extra_favicon_urls, bool skip_page_favicons, GetIconsCallback callback) override { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); CHECK(manager_); - IconsMap icons_map; - DownloadedIconsHttpResults per_icon_results; - for (const GURL& icon_url : icon_urls) { - auto icons_it = manager_->icon_state_.find(icon_url); - if (icons_it == manager_->icon_state_.end()) { - per_icon_results[icon_url] = 404; - continue; - } - FakeWebContentsManager::FakeIconState& icon = icons_it->second; - // The real implementation includes these CHECK statements, so this does - // too. - CHECK_LE(100, icon.http_status_code); - CHECK_GT(600, icon.http_status_code); - if (icon.trigger_primary_page_changed_if_fetched) { - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), - IconsDownloadedResult::kPrimaryPageChanged, - IconsMap{}, DownloadedIconsHttpResults{})); - return; - } - icons_map[icon_url] = icon.bitmaps; - per_icon_results[icon_url] = icon.http_status_code; - } - - // Add favicon if requested & available. - if (!skip_page_favicons) { - GURL url = manager_->loaded_urls_[web_contents]; - CHECK(url.is_valid() || url.is_empty()) - << "No url has been loaded on this web contents. " << url.spec(); - auto page_it = manager_->page_state_.find(url); - if (page_it != manager_->page_state_.end()) { - FakeWebContentsManager::FakePageState& page = page_it->second; - if (!page.favicon_url.is_empty()) { - icons_map[page.favicon_url] = page.favicon; - per_icon_results[page.favicon_url] = page.favicon.empty() ? 404 : 200; - } - } - } - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), IconsDownloadedResult::kCompleted, - std::move(icons_map), std::move(per_icon_results))); + std::unique_ptr<FakeWebAppIconDownloader> fake_downloader = + std::make_unique<FakeWebAppIconDownloader>(manager_); + FakeWebAppIconDownloader* downloader_ptr = fake_downloader.get(); + base::OnceClosure owning_callback = + base::DoNothingWithBoundArgs(std::move(fake_downloader)); + downloader_ptr->Start(web_contents, extra_favicon_urls, + std::move(callback).Then(std::move(owning_callback)), + {.skip_page_favicons = skip_page_favicons, + .fail_all_if_any_fail = false}); } private: @@ -238,6 +291,11 @@ return std::make_unique<FakeWebAppDataRetriever>(weak_factory_.GetWeakPtr()); } +std::unique_ptr<WebAppIconDownloader> +FakeWebContentsManager::CreateIconDownloader() { + return std::make_unique<FakeWebAppIconDownloader>(weak_factory_.GetWeakPtr()); +} + void FakeWebContentsManager::SetIconState( const GURL& gurl, const FakeWebContentsManager::FakeIconState& icon_state) {
diff --git a/chrome/browser/web_applications/test/fake_web_contents_manager.h b/chrome/browser/web_applications/test/fake_web_contents_manager.h index 1a9f5d92..5627702 100644 --- a/chrome/browser/web_applications/test/fake_web_contents_manager.h +++ b/chrome/browser/web_applications/test/fake_web_contents_manager.h
@@ -13,6 +13,7 @@ #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h" #include "chrome/browser/web_applications/web_contents/web_app_icon_downloader.h" #include "chrome/browser/web_applications/web_contents/web_app_url_loader.h" +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" #include "components/webapps/browser/installable/installable_logging.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/variant.h" @@ -32,7 +33,7 @@ // reflect a fake network state. This class can be re-used when creating a // general dependency wrapper for the web contents system, see // http://b/262606416. -class FakeWebContentsManager { +class FakeWebContentsManager : public WebContentsManager { public: // State used to represent a page at a url, which is retrieved through // `LoadUrl`, `GetWebAppInstallInfo`, and @@ -79,10 +80,11 @@ }; FakeWebContentsManager(); - ~FakeWebContentsManager(); + ~FakeWebContentsManager() override; - std::unique_ptr<WebAppUrlLoader> CreateUrlLoader(); - std::unique_ptr<WebAppDataRetriever> CreateDataRetriever(); + std::unique_ptr<WebAppUrlLoader> CreateUrlLoader() override; + std::unique_ptr<WebAppDataRetriever> CreateDataRetriever() override; + std::unique_ptr<WebAppIconDownloader> CreateIconDownloader() override; // Set the behavior for calls to `GetIcons` from wrappers returned by this // fake class. @@ -101,6 +103,7 @@ private: class FakeUrlLoader; + class FakeWebAppIconDownloader; class FakeWebAppDataRetriever; std::map<GURL, FakeIconState> icon_state_;
diff --git a/chrome/browser/web_applications/test/mock_data_retriever.h b/chrome/browser/web_applications/test/mock_data_retriever.h index 7d22fb1..5c43ff7 100644 --- a/chrome/browser/web_applications/test/mock_data_retriever.h +++ b/chrome/browser/web_applications/test/mock_data_retriever.h
@@ -40,7 +40,7 @@ MOCK_METHOD(void, GetIcons, (content::WebContents * web_contents, - base::flat_set<GURL> icon_urls, + const base::flat_set<GURL>& icon_urls, bool skip_page_favicons, GetIconsCallback callback), (override));
diff --git a/chrome/browser/web_applications/uninstall_request.cc b/chrome/browser/web_applications/uninstall_request.cc deleted file mode 100644 index be6a82a..0000000 --- a/chrome/browser/web_applications/uninstall_request.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/web_applications/uninstall_request.h" - -#include "base/values.h" -#include "chrome/browser/web_applications/web_app_constants.h" -#include "chrome/browser/web_applications/web_app_id.h" -#include "components/webapps/browser/installable/installable_metrics.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "url/gurl.h" - -namespace web_app { - -UninstallRequest::UninstallRequest( - webapps::WebappUninstallSource uninstall_source, - AppId app_id, - absl::optional<WebAppManagement::Type> install_source, - absl::optional<GURL> install_url) - : uninstall_source_(uninstall_source), - app_id_(std::move(app_id)), - install_source_(std::move(install_source)), - install_url_(std::move(install_url)) { - CheckFields(); -} - -UninstallRequest::UninstallRequest( - base::PassKey<WebAppUninstallCommand>, - bool is_sub_request, - webapps::WebappUninstallSource uninstall_source, - AppId app_id, - absl::optional<WebAppManagement::Type> install_source, - absl::optional<GURL> install_url) - : uninstall_source_(uninstall_source), - app_id_(std::move(app_id)), - install_source_(std::move(install_source)), - install_url_(std::move(install_url)), - is_sub_request_(is_sub_request) { - CheckFields(); -} - -UninstallRequest::UninstallRequest(UninstallRequest&&) = default; - -UninstallRequest::~UninstallRequest() = default; - -UninstallRequest& UninstallRequest::operator=(UninstallRequest&&) = default; - -base::Value UninstallRequest::ToDebugValue() const { - base::Value::Dict dict; - dict.Set("uninstall_source", base::ToString(uninstall_source_)); - dict.Set("app_id", app_id_); - dict.Set("install_source", install_source_ - ? base::Value(base::ToString(*install_source_)) - : base::Value()); - dict.Set("install_url", - install_url_ ? base::Value(install_url_->spec()) : base::Value()); - dict.Set("is_sub_request", is_sub_request_); - return base::Value(std::move(dict)); -} - -void UninstallRequest::CheckFields() const { - CHECK(!app_id_.empty()); - if (install_url_) { - CHECK(install_source_); - } - if (install_source_ == WebAppManagement::Type::kSync) { - CHECK(!install_url_); - } -} - -} // namespace web_app
diff --git a/chrome/browser/web_applications/uninstall_request.h b/chrome/browser/web_applications/uninstall_request.h deleted file mode 100644 index f4e383b20..0000000 --- a/chrome/browser/web_applications/uninstall_request.h +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_WEB_APPLICATIONS_UNINSTALL_REQUEST_H_ -#define CHROME_BROWSER_WEB_APPLICATIONS_UNINSTALL_REQUEST_H_ - -#include "base/types/pass_key.h" -#include "chrome/browser/web_applications/web_app_constants.h" -#include "chrome/browser/web_applications/web_app_id.h" -#include "components/webapps/browser/installable/installable_metrics.h" -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "url/gurl.h" - -namespace base { -class Value; -} - -namespace web_app { - -class WebAppUninstallCommand; - -// This represents requests for different tiers of uninstallation: -// - app_id only: App removal. -// - app_id + install_source: Install source removal. -// - app_id + install_source + install_url: Install URL removal. -// Install sources are always removed if there are no remaining install URLs. -// Apps are always uninstalled if there are no remaining install sources. -class UninstallRequest { - public: - UninstallRequest( - webapps::WebappUninstallSource uninstall_source, - AppId app_id, - absl::optional<WebAppManagement::Type> install_source = absl::nullopt, - absl::optional<GURL> install_url = absl::nullopt); - UninstallRequest( - base::PassKey<WebAppUninstallCommand>, - bool is_sub_request, - webapps::WebappUninstallSource uninstall_source, - AppId app_id, - absl::optional<WebAppManagement::Type> install_source = absl::nullopt, - absl::optional<GURL> install_url = absl::nullopt); - UninstallRequest(const UninstallRequest&) = delete; - UninstallRequest(UninstallRequest&&); - ~UninstallRequest(); - - UninstallRequest& operator=(const UninstallRequest&) = delete; - UninstallRequest& operator=(UninstallRequest&&); - - webapps::WebappUninstallSource uninstall_source() const { - return uninstall_source_; - } - AppId app_id() const { return app_id_; } - absl::optional<WebAppManagement::Type> install_source() const { - return install_source_; - } - absl::optional<GURL> install_url() const { return install_url_; } - bool is_sub_request() const { return is_sub_request_; } - - base::Value ToDebugValue() const; - - private: - void CheckFields() const; - - webapps::WebappUninstallSource uninstall_source_; - AppId app_id_; - absl::optional<WebAppManagement::Type> install_source_; - absl::optional<GURL> install_url_; - bool is_sub_request_ = false; -}; - -} // namespace web_app - -#endif // CHROME_BROWSER_WEB_APPLICATIONS_UNINSTALL_REQUEST_H_
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc index 662109d..1409f2d 100644 --- a/chrome/browser/web_applications/web_app_command_scheduler.cc +++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -48,6 +48,7 @@ #include "chrome/browser/web_applications/web_app_sync_bridge.h" #include "chrome/browser/web_applications/web_app_ui_manager.h" #include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h" +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" #include "components/keep_alive_registry/keep_alive_registry.h" #include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/scoped_keep_alive.h" @@ -74,9 +75,7 @@ WebAppCommandScheduler::WebAppCommandScheduler(Profile& profile, WebAppProvider* provider) - : profile_(profile), - provider_(provider), - url_loader_(std::make_unique<WebAppUrlLoader>()) {} + : profile_(profile), provider_(provider) {} WebAppCommandScheduler::~WebAppCommandScheduler() = default; @@ -104,7 +103,7 @@ std::make_unique<FetchManifestAndInstallCommand>( install_surface, std::move(contents), bypass_service_worker_check, std::move(dialog_callback), std::move(callback), use_fallback, - std::make_unique<WebAppDataRetriever>()), + provider_->web_contents_manager().CreateDataRetriever()), location); } @@ -228,7 +227,7 @@ provider_->command_manager().ScheduleCommand( std::make_unique<InstallPlaceholderCommand>( &profile_.get(), install_options, std::move(callback), web_contents, - std::make_unique<WebAppDataRetriever>()), + provider_->web_contents_manager().CreateDataRetriever()), location); } @@ -267,7 +266,8 @@ provider_->command_manager().ScheduleCommand( std::make_unique<ManifestUpdateCheckCommand>( url, app_id, check_time, contents, std::move(callback), - std::make_unique<WebAppDataRetriever>()), + provider_->web_contents_manager().CreateDataRetriever(), + provider_->web_contents_manager().CreateIconDownloader()), location); } @@ -311,8 +311,9 @@ provider_->command_manager().ScheduleCommand( std::make_unique<web_app::FetchInstallabilityForChromeManagement>( - url, web_contents, std::make_unique<web_app::WebAppUrlLoader>(), - std::make_unique<web_app::WebAppDataRetriever>(), + url, web_contents, + provider_->web_contents_manager().CreateUrlLoader(), + provider_->web_contents_manager().CreateDataRetriever(), std::move(callback)), location); } @@ -358,12 +359,12 @@ base::BindOnce(std::move(callback), base::unexpected(error))); return; } - provider_->command_manager().ScheduleCommand( std::make_unique<InstallIsolatedWebAppCommand>( url_info, location, CreateIsolatedWebAppWebContents(*profile_), - std::make_unique<WebAppUrlLoader>(), std::move(keep_alive), - std::move(profile_keep_alive), std::move(callback), + provider_->web_contents_manager().CreateUrlLoader(), + std::move(keep_alive), std::move(profile_keep_alive), + std::move(callback), InstallIsolatedWebAppCommand::CreateDefaultResponseReaderFactory( *profile_->GetPrefs())), call_location); @@ -414,16 +415,22 @@ web_app.sync_fallback_data().name, web_app.sync_fallback_data().scope, web_app.sync_fallback_data().theme_color, web_app.user_display_mode(), web_app.sync_fallback_data().icon_infos); + // TODO(http://b/262606416): Remove this when fully transitioned to + // WebContentsManager. + if (!url_loader_) { + url_loader_ = provider_->web_contents_manager().CreateUrlLoader(); + } provider_->command_manager().ScheduleCommand( std::make_unique<InstallFromSyncCommand>( url_loader_.get(), &profile_.get(), - std::make_unique<WebAppDataRetriever>(), params, std::move(callback)), + provider_->web_contents_manager().CreateDataRetriever(), params, + std::move(callback)), location); } void WebAppCommandScheduler::Uninstall( const AppId& app_id, - absl::optional<WebAppManagement::Type> install_source, + absl::optional<WebAppManagement::Type> external_install_source, webapps::WebappUninstallSource uninstall_source, WebAppUninstallCommand::UninstallWebAppCallback callback, const base::Location& location) { @@ -435,7 +442,7 @@ } provider_->command_manager().ScheduleCommand( std::make_unique<WebAppUninstallCommand>( - UninstallRequest(uninstall_source, app_id, install_source), + app_id, external_install_source, uninstall_source, std::move(callback), profile_.get()), location); } @@ -588,6 +595,20 @@ std::move(callback), location); } +void WebAppCommandScheduler::InstallAppLocally(const AppId& app_id, + base::OnceClosure callback, + const base::Location& location) { + if (IsShuttingDown()) { + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, std::move(callback)); + return; + } + + provider_->command_manager().ScheduleCommand( + std::make_unique<InstallAppLocallyCommand>(app_id, std::move(callback)), + location); +} + void WebAppCommandScheduler::SynchronizeOsIntegration( const AppId& app_id, base::OnceClosure synchronize_callback, @@ -605,20 +626,6 @@ location); } -void WebAppCommandScheduler::InstallAppLocally(const AppId& app_id, - base::OnceClosure callback, - const base::Location& location) { - if (IsShuttingDown()) { - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, std::move(callback)); - return; - } - - provider_->command_manager().ScheduleCommand( - std::make_unique<InstallAppLocallyCommand>(app_id, std::move(callback)), - location); -} - void WebAppCommandScheduler::LaunchApp(apps::AppLaunchParams params, LaunchWebAppWindowSetting option, LaunchWebAppCallback callback,
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h index de6ba5d..d4ce955 100644 --- a/chrome/browser/web_applications/web_app_command_scheduler.h +++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -5,7 +5,10 @@ #ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_COMMAND_SCHEDULER_H_ #define CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_COMMAND_SCHEDULER_H_ +#include <memory> + #include "base/containers/flat_map.h" +#include "base/functional/callback_forward.h" #include "base/location.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ref.h" @@ -42,11 +45,13 @@ namespace web_app { class IsolatedWebAppUrlInfo; +class WebApp; class WebAppDataRetriever; class WebAppProvider; -struct IsolationData; -class WebApp; +class WebAppUrlLoader; +class WebContentsManager; enum class ApiApprovalState; +struct IsolationData; struct SynchronizeOsOptions; // The command scheduler is the main API to access the web app system. The @@ -68,6 +73,8 @@ WebAppCommandScheduler(Profile& profile, WebAppProvider* provider); virtual ~WebAppCommandScheduler(); + void Start(); + void Shutdown(); // User initiated install that uses current `WebContents` to fetch manifest @@ -202,7 +209,7 @@ // Schedules a command that uninstalls a web app. void Uninstall(const AppId& app_id, - absl::optional<WebAppManagement::Type> install_source, + absl::optional<WebAppManagement::Type> external_install_source, webapps::WebappUninstallSource uninstall_source, WebAppInstallFinalizer::UninstallWebAppCallback callback, const base::Location& location = FROM_HERE); @@ -319,9 +326,13 @@ const raw_ref<Profile> profile_; // Safe because we live on the WebAppProvider. - raw_ptr<WebAppProvider, DanglingUntriaged> provider_; + // raw_ptr is required due to the FakeWebAppCommandScheduler not having a + // WebAppProvider. + const raw_ptr<WebAppProvider> provider_; bool is_in_shutdown_ = false; + // TODO(http://b/262606416): Remove this when fully transitioned to + // WebContentsManager. std::unique_ptr<WebAppUrlLoader> url_loader_; base::WeakPtrFactory<WebAppCommandScheduler> weak_ptr_factory_{this};
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc index e17fc052..ce64d8c 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.cc +++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -101,25 +101,6 @@ } } -bool IsExternalInstallSource(WebAppManagement::Type install_source) { - switch (install_source) { - case WebAppManagement::Type::kSystem: - case WebAppManagement::Type::kKiosk: - case WebAppManagement::Type::kPolicy: - case WebAppManagement::Type::kSubApp: - case WebAppManagement::Type::kWebAppStore: - case WebAppManagement::Type::kDefault: - return true; - case WebAppManagement::Type::kSync: - // TODO(crbug.com/1427340): These are classified incorrectly, this check - // isn't really useful and should be removed. - case WebAppManagement::Type::kOneDriveIntegration: - case WebAppManagement::Type::kCommandLine: - case WebAppManagement::Type::kOem: - return false; - } -} - } // namespace WebAppInstallFinalizer::FinalizeOptions::FinalizeOptions( @@ -295,24 +276,27 @@ webapps::WebappUninstallSource uninstall_source, UninstallWebAppCallback callback) { DCHECK(started_); - DCHECK(IsExternalInstallSource(external_install_source)); - ScheduleUninstallCommand(app_id, external_install_source, - /*install_url=*/absl::nullopt, uninstall_source, + DCHECK(external_install_source == WebAppManagement::Type::kSystem || + external_install_source == WebAppManagement::Type::kKiosk || + external_install_source == WebAppManagement::Type::kPolicy || + external_install_source == WebAppManagement::Type::kSubApp || + external_install_source == WebAppManagement::Type::kWebAppStore || + external_install_source == WebAppManagement::Type::kDefault); + + ScheduleUninstallCommand(app_id, external_install_source, uninstall_source, std::move(callback)); } void WebAppInstallFinalizer::UninstallExternalWebAppByUrl( - const GURL& install_url, + const GURL& app_url, WebAppManagement::Type external_install_source, webapps::WebappUninstallSource uninstall_source, UninstallWebAppCallback callback) { - DCHECK(IsExternalInstallSource(external_install_source)); - absl::optional<AppId> app_id = - GetWebAppRegistrar().LookupExternalAppId(install_url); + GetWebAppRegistrar().LookupExternalAppId(app_url); if (!app_id.has_value()) { - LOG(WARNING) << "Couldn't uninstall web app with url " << install_url + LOG(WARNING) << "Couldn't uninstall web app with url " << app_url << "; No corresponding web app for url."; base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( FROM_HERE, @@ -321,8 +305,8 @@ return; } - ScheduleUninstallCommand(std::move(app_id).value(), external_install_source, - install_url, uninstall_source, std::move(callback)); + UninstallExternalWebApp(app_id.value(), external_install_source, + uninstall_source, std::move(callback)); } void WebAppInstallFinalizer::UninstallWebApp( @@ -333,7 +317,6 @@ // An external install source (or management type) is only required // for apps that have been externally installed. ScheduleUninstallCommand(app_id, /*external_install_source=*/absl::nullopt, - /*install_url=*/absl::nullopt, webapp_uninstall_source, std::move(callback)); } @@ -724,13 +707,11 @@ void WebAppInstallFinalizer::ScheduleUninstallCommand( const AppId& app_id, absl::optional<WebAppManagement::Type> external_install_source, - absl::optional<GURL> install_url, webapps::WebappUninstallSource uninstall_source, UninstallWebAppCallback callback) { auto uninstall_command = std::make_unique<WebAppUninstallCommand>( - UninstallRequest(uninstall_source, app_id, external_install_source, - install_url), - std::move(callback), *profile_); + app_id, external_install_source, uninstall_source, std::move(callback), + *profile_); command_manager_->ScheduleCommand(std::move(uninstall_command)); }
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.h b/chrome/browser/web_applications/web_app_install_finalizer.h index 1a6d858..b6b0265 100644 --- a/chrome/browser/web_applications/web_app_install_finalizer.h +++ b/chrome/browser/web_applications/web_app_install_finalizer.h
@@ -116,12 +116,8 @@ virtual void FinalizeUpdate(const WebAppInstallInfo& web_app_info, InstallFinalizedCallback callback); - // If `install_url` is set the `install_url` for `external_install_source` in - // `app_id` will be removed. If `install_url` is not set then the entire - // `external_install_source` in `app_id` will be removed. If no install - // sources are left in `app_id` the app is removed. - // TODO(https://crbug.com/1427340): Make callsites use the WebAppScheduler - // instead of this interface. + // Removes |webapp_uninstall_surface| from |app_id|. If no more interested + // sources left, deletes the app from disk and registrar. virtual void UninstallExternalWebApp( const AppId& app_id, WebAppManagement::Type external_install_source, @@ -130,18 +126,14 @@ // Removes the external app for |app_url| from disk and registrar. Fails if // there is no installed external app for |app_url|. - // TODO(https://crbug.com/1427340): Make callsites use the WebAppScheduler - // instead of this interface. virtual void UninstallExternalWebAppByUrl( - const GURL& install_url, + const GURL& app_url, WebAppManagement::Type external_install_source, webapps::WebappUninstallSource uninstall_surface, UninstallWebAppCallback callback); // Removes |webapp_uninstall_surface| from |app_id|, no matter how many // sources are left. - // TODO(https://crbug.com/1427340): Make callsites use the WebAppScheduler - // instead of this interface. virtual void UninstallWebApp(const AppId& app_id, webapps::WebappUninstallSource uninstall_surface, UninstallWebAppCallback callback); @@ -181,12 +173,9 @@ // Used to schedule a WebAppUninstallCommand. The |external_install_source| // field is only required for external app uninstalls to verify OS // unregistration, and is not used for sync/manual uninstalls. - // TODO(https://crbug.com/1427340): Make callsites use the WebAppScheduler - // instead of this interface. void ScheduleUninstallCommand( const AppId& app_id, absl::optional<WebAppManagement::Type> external_install_source, - absl::optional<GURL> install_url, webapps::WebappUninstallSource uninstall_source, UninstallWebAppCallback callback);
diff --git a/chrome/browser/web_applications/web_app_install_utils.h b/chrome/browser/web_applications/web_app_install_utils.h index 735bdfa..900a0bb 100644 --- a/chrome/browser/web_applications/web_app_install_utils.h +++ b/chrome/browser/web_applications/web_app_install_utils.h
@@ -115,8 +115,6 @@ void CreateWebAppInstallTabHelpers(content::WebContents* web_contents); // The function should be called before removing a source from the WebApp. -// If an install source that blocks user uninstallation is removed then OS hooks -// for user uninstallation should be deployed. void MaybeRegisterOsUninstall(const WebApp* web_app, WebAppManagement::Type source_uninstalling, OsIntegrationManager& os_integration_manager,
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc index 4e2ca89..2621f73 100644 --- a/chrome/browser/web_applications/web_app_provider.cc +++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -45,6 +45,7 @@ #include "chrome/browser/web_applications/web_app_translation_manager.h" #include "chrome/browser/web_applications/web_app_ui_manager.h" #include "chrome/browser/web_applications/web_app_utils.h" +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" #include "chrome/common/chrome_features.h" #include "content/public/browser/web_contents.h" @@ -142,6 +143,16 @@ StartImpl(); } +WebAppCommandScheduler& WebAppProvider::scheduler() { + return *command_scheduler_; +} + +WebAppCommandManager& WebAppProvider::command_manager() { + // Note: It is OK to access the command manager before connection or start. + // Internally it will queue commands to only happen after it has started. + return *command_manager_; +} + WebAppRegistrar& WebAppProvider::registrar_unsafe() { CheckIsConnected(); return *registrar_; @@ -222,14 +233,8 @@ return *origin_association_manager_; } -WebAppCommandManager& WebAppProvider::command_manager() { - // Note: It is OK to access the command manager before connection or start. - // Internally it will queue commands to only happen after it has started. - return *command_manager_; -} - -WebAppCommandScheduler& WebAppProvider::scheduler() { - return *command_scheduler_; +WebContentsManager& WebAppProvider::web_contents_manager() { + return *web_contents_manager_; } void WebAppProvider::Shutdown() { @@ -316,6 +321,8 @@ web_app_run_on_os_login_manager_ = std::make_unique<WebAppRunOnOsLoginManager>(command_scheduler_.get()); #endif + + web_contents_manager_ = std::make_unique<WebContentsManager>(); } void WebAppProvider::ConnectSubsystems() { @@ -333,7 +340,8 @@ registrar_.get(), ui_manager_.get(), command_scheduler_.get()); externally_managed_app_manager_->SetSubsystems( - ui_manager_.get(), install_finalizer_.get(), command_scheduler_.get()); + ui_manager_.get(), install_finalizer_.get(), command_scheduler_.get(), + web_contents_manager_.get()); preinstalled_web_app_manager_->SetSubsystems( registrar_.get(), ui_manager_.get(), externally_managed_app_manager_.get());
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h index 79590d22..a67d7ef 100644 --- a/chrome/browser/web_applications/web_app_provider.h +++ b/chrome/browser/web_applications/web_app_provider.h
@@ -34,20 +34,21 @@ namespace web_app { class AbstractWebAppDatabaseFactory; -class WebAppSyncBridge; -class WebAppIconManager; -class PreinstalledWebAppManager; -class WebAppInstallFinalizer; class ManifestUpdateManager; -class WebAppAudioFocusIdMap; -class WebAppInstallManager; -class WebAppPolicyManager; -class WebAppUiManager; class OsIntegrationManager; -class WebAppTranslationManager; +class PreinstalledWebAppManager; +class WebAppAudioFocusIdMap; class WebAppCommandManager; class WebAppCommandScheduler; +class WebAppIconManager; +class WebAppInstallFinalizer; +class WebAppInstallManager; class WebAppOriginAssociationManager; +class WebAppPolicyManager; +class WebAppSyncBridge; +class WebAppTranslationManager; +class WebAppUiManager; +class WebContentsManager; // WebAppProvider is the heart of Chrome web app code. // @@ -162,6 +163,8 @@ WebAppOriginAssociationManager& origin_association_manager(); + WebContentsManager& web_contents_manager(); + // KeyedService: void Shutdown() override; @@ -228,6 +231,7 @@ std::unique_ptr<WebAppCommandManager> command_manager_; std::unique_ptr<WebAppCommandScheduler> command_scheduler_; std::unique_ptr<WebAppOriginAssociationManager> origin_association_manager_; + std::unique_ptr<WebContentsManager> web_contents_manager_; base::OneShotEvent on_registry_ready_; base::OneShotEvent on_external_managers_synchronized_;
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc index baf563c..3d34fea 100644 --- a/chrome/browser/web_applications/web_app_sync_bridge.cc +++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -556,10 +556,6 @@ // Do copy on write: auto app_copy = std::make_unique<WebApp>(*existing_web_app); app_copy->RemoveSource(WebAppManagement::kSync); - // TODO(https://crbug.com/1447308): Mark the web app as pending sync source - // removal and schedule the removal so it conforms to the command locking - // system. Block web apps pending sync source removal from transmitting to - // the sync server. if (!app_copy->HasAnySources()) { // Uninstallation from the local database is a two-phase commit. Setting // this flag to true signals that uninstallation should occur, and then @@ -681,7 +677,7 @@ } else { for (const AppId& app_id : apps_to_delete) { command_scheduler_->Uninstall(app_id, - /*install_source=*/absl::nullopt, + /*external_install_source=*/absl::nullopt, webapps::WebappUninstallSource::kSync, base::BindOnce(callback, app_id)); }
diff --git a/chrome/browser/web_applications/web_contents/web_app_data_retriever.cc b/chrome/browser/web_applications/web_contents/web_app_data_retriever.cc index b37594c..783f5dcc 100644 --- a/chrome/browser/web_applications/web_contents/web_app_data_retriever.cc +++ b/chrome/browser/web_applications/web_contents/web_app_data_retriever.cc
@@ -126,7 +126,7 @@ } void WebAppDataRetriever::GetIcons(content::WebContents* web_contents, - base::flat_set<GURL> icon_urls, + const base::flat_set<GURL>& extra_icon_urls, bool skip_page_favicons, GetIconsCallback callback) { DCHECK(!web_contents->IsBeingDestroyed()); @@ -137,13 +137,12 @@ get_icons_callback_ = std::move(callback); IconDownloaderOptions options = {.skip_page_favicons = skip_page_favicons}; - icon_downloader_ = std::make_unique<WebAppIconDownloader>( - web_contents, std::move(icon_urls), + icon_downloader_ = std::make_unique<WebAppIconDownloader>(); + icon_downloader_->Start( + web_contents, extra_icon_urls, base::BindOnce(&WebAppDataRetriever::OnIconsDownloaded, weak_ptr_factory_.GetWeakPtr()), options); - - icon_downloader_->Start(); } void WebAppDataRetriever::WebContentsDestroyed() {
diff --git a/chrome/browser/web_applications/web_contents/web_app_data_retriever.h b/chrome/browser/web_applications/web_contents/web_app_data_retriever.h index 69ef802..a4ca321 100644 --- a/chrome/browser/web_applications/web_contents/web_app_data_retriever.h +++ b/chrome/browser/web_applications/web_contents/web_app_data_retriever.h
@@ -82,7 +82,7 @@ // Downloads icons from |icon_urls|. Runs |callback| with a map of // the retrieved icons. virtual void GetIcons(content::WebContents* web_contents, - base::flat_set<GURL> icon_urls, + const base::flat_set<GURL>& extra_favicon_urls, bool skip_page_favicons, GetIconsCallback callback);
diff --git a/chrome/browser/web_applications/web_contents/web_app_icon_downloader.cc b/chrome/browser/web_applications/web_contents/web_app_icon_downloader.cc index 2bdc8888..7849196 100644 --- a/chrome/browser/web_applications/web_contents/web_app_icon_downloader.cc +++ b/chrome/browser/web_applications/web_contents/web_app_icon_downloader.cc
@@ -4,53 +4,59 @@ #include "chrome/browser/web_applications/web_contents/web_app_icon_downloader.h" +#include "base/check_op.h" +#include "base/containers/flat_set.h" #include "base/functional/bind.h" #include "base/task/single_thread_task_runner.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/browser/web_applications/web_app_helpers.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" +#include "content/public/browser/web_contents_observer.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/geometry/size.h" namespace web_app { -WebAppIconDownloader::WebAppIconDownloader( - content::WebContents* web_contents, - base::flat_set<GURL> extra_favicon_urls, - WebAppIconDownloaderCallback callback, - IconDownloaderOptions options) - : content::WebContentsObserver(web_contents), - extra_favicon_urls_(std::move(extra_favicon_urls)), - options_(options), - callback_(std::move(callback)) { - DCHECK(web_contents); -} - +WebAppIconDownloader::WebAppIconDownloader() = default; WebAppIconDownloader::~WebAppIconDownloader() = default; -void WebAppIconDownloader::Start() { - CHECK(!web_contents()->IsBeingDestroyed()); - starting_ = true; +void WebAppIconDownloader::Start(content::WebContents* web_contents, + const base::flat_set<GURL>& extra_icon_urls, + WebAppIconDownloaderCallback callback, + IconDownloaderOptions options) { + // Cannot call start more than once. + CHECK_EQ(pending_requests(), 0ul); + CHECK(web_contents); + CHECK(!web_contents->IsBeingDestroyed()); + Observe(web_contents); + callback_ = std::move(callback); + options_ = options; + // Favicons are supported only in HTTP or HTTPS WebContents. - const GURL& url = web_contents()->GetLastCommittedURL(); + const GURL& url = web_contents->GetLastCommittedURL(); if (!url.is_empty() && !url.inner_url() && !url.SchemeIsHTTPOrHTTPS()) { options_.skip_page_favicons = true; } - FetchIcons(extra_favicon_urls_); + // The call to `GetFaviconURLsFromWebContents()` is to allow this method to + // be mocked by unit tests. + const auto& favicon_urls = GetFaviconURLsFromWebContents(); - if (!options_.skip_page_favicons) { - // The call to `GetFaviconURLsFromWebContents()` is to allow this method to - // be mocked by unit tests. - const auto& favicon_urls = GetFaviconURLsFromWebContents(); - if (!favicon_urls.empty()) { - FetchIcons(favicon_urls); + if (!options_.skip_page_favicons && !favicon_urls.empty()) { + std::vector<GURL> combined_icon_urls(extra_icon_urls.begin(), + extra_icon_urls.end()); + combined_icon_urls.reserve(combined_icon_urls.size() + favicon_urls.size()); + for (const auto& favicon_url : favicon_urls) { + if (favicon_url->icon_type != blink::mojom::FaviconIconType::kInvalid) { + combined_icon_urls.push_back(favicon_url->icon_url); + } } + FetchIcons(base::flat_set<GURL>(combined_icon_urls)); + } else { + FetchIcons(extra_icon_urls); } - starting_ = false; - MaybeCompleteCallback(); } int WebAppIconDownloader::DownloadImage(const GURL& url) { @@ -71,22 +77,13 @@ return web_contents()->GetFaviconURLs(); } -void WebAppIconDownloader::FetchIcons( - const std::vector<blink::mojom::FaviconURLPtr>& favicon_urls) { - if (!web_contents()) { - return; - } - - std::vector<GURL> urls; - for (const auto& favicon_url : favicon_urls) { - if (favicon_url->icon_type != blink::mojom::FaviconIconType::kInvalid) { - urls.push_back(favicon_url->icon_url); - } - } - FetchIcons(urls); -} - void WebAppIconDownloader::FetchIcons(const base::flat_set<GURL>& urls) { + CHECK_EQ(pending_requests(), 0ul); + CHECK(!populating_pending_requests_); + + // This is required because `DidDownloadFavicon` is triggered synchronously in + // some tests. + populating_pending_requests_ = true; // Download icons; put their download ids into |in_progress_requests_| and // their urls into |processed_urls_|. for (const GURL& url : urls) { @@ -95,6 +92,8 @@ in_progress_requests_.insert(DownloadImage(url)); } } + populating_pending_requests_ = false; + MaybeCompleteCallback(); } @@ -104,10 +103,8 @@ const GURL& image_url, const std::vector<SkBitmap>& bitmaps, const std::vector<gfx::Size>& original_bitmap_sizes) { - // Request may have been canceled by PrimaryPageChanged(). - if (in_progress_requests_.erase(id) == 0) { - return; - } + size_t num_deleted = in_progress_requests_.erase(id); + CHECK_EQ(num_deleted, 1ul); if (http_status_code != 0) { DCHECK_LE(100, http_status_code); @@ -128,18 +125,23 @@ } void WebAppIconDownloader::PrimaryPageChanged(content::Page& page) { - CancelDownloads(IconsDownloadedResult::kPrimaryPageChanged, - DownloadedIconsHttpResults{}); + if (callback_) { + CancelDownloads(IconsDownloadedResult::kPrimaryPageChanged, + DownloadedIconsHttpResults{}); + } } void WebAppIconDownloader::WebContentsDestroyed() { Observe(nullptr); - CancelDownloads(IconsDownloadedResult::kPrimaryPageChanged, - DownloadedIconsHttpResults{}); + if (callback_) { + CancelDownloads(IconsDownloadedResult::kPrimaryPageChanged, + DownloadedIconsHttpResults{}); + } } void WebAppIconDownloader::MaybeCompleteCallback() { - if (starting_ || !in_progress_requests_.empty() || callback_.is_null()) { + if (populating_pending_requests_ || !in_progress_requests_.empty() || + callback_.is_null()) { return; } base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( @@ -153,6 +155,7 @@ DownloadedIconsHttpResults icons_http_results) { DCHECK_NE(result, IconsDownloadedResult::kCompleted); + weak_ptr_factory_.InvalidateWeakPtrs(); in_progress_requests_.clear(); icons_map_.clear(); icons_http_results_.clear();
diff --git a/chrome/browser/web_applications/web_contents/web_app_icon_downloader.h b/chrome/browser/web_applications/web_contents/web_app_icon_downloader.h index b602a39..8c5dd50f 100644 --- a/chrome/browser/web_applications/web_contents/web_app_icon_downloader.h +++ b/chrome/browser/web_applications/web_contents/web_app_icon_downloader.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/functional/callback.h" -#include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/web_applications/web_app_install_utils.h" #include "content/public/browser/web_contents_observer.h" @@ -42,17 +41,17 @@ IconsMap icons_map, DownloadedIconsHttpResults icons_http_results)>; - // |extra_favicon_urls| allows callers to provide icon urls that aren't - // provided by the renderer (e.g touch icons on non-android environments). - WebAppIconDownloader(content::WebContents* web_contents, - base::flat_set<GURL> extra_favicon_urls, - WebAppIconDownloaderCallback callback, - IconDownloaderOptions options = IconDownloaderOptions()); + WebAppIconDownloader(); WebAppIconDownloader(const WebAppIconDownloader&) = delete; WebAppIconDownloader& operator=(const WebAppIconDownloader&) = delete; ~WebAppIconDownloader() override; - void Start(); + // |extra_icon_urls| allows callers to provide icon urls that aren't + // provided by the renderer (e.g touch icons on non-android environments). + virtual void Start(content::WebContents* web_contents, + const base::flat_set<GURL>& extra_icon_urls, + WebAppIconDownloaderCallback callback, + IconDownloaderOptions options = IconDownloaderOptions()); size_t pending_requests() const { return in_progress_requests_.size(); } @@ -66,7 +65,6 @@ // Fetches icons for the given urls. // |callback_| is run when all downloads complete. - void FetchIcons(const std::vector<blink::mojom::FaviconURLPtr>& favicon_urls); void FetchIcons(const base::flat_set<GURL>& urls); // Icon download callback. @@ -84,21 +82,15 @@ void CancelDownloads(IconsDownloadedResult result, DownloadedIconsHttpResults icons_http_results); - // URLs that aren't given by WebContentsObserver::DidUpdateFaviconURL() that - // should be used for this favicon. This is necessary in order to get touch - // icons on non-android environments. - base::flat_set<GURL> extra_favicon_urls_; - IconDownloaderOptions options_; - bool starting_ = false; - // The icons which were downloaded. Populated by FetchIcons(). IconsMap icons_map_; // The http status codes resulted from url downloading requests. DownloadedIconsHttpResults icons_http_results_; // Request ids of in-progress requests. + bool populating_pending_requests_ = false; std::set<int> in_progress_requests_; // Urls for which a download has already been initiated. Used to prevent
diff --git a/chrome/browser/web_applications/web_contents/web_app_icon_downloader_unittest.cc b/chrome/browser/web_applications/web_contents/web_app_icon_downloader_unittest.cc index 594adce..7b33acc1 100644 --- a/chrome/browser/web_applications/web_contents/web_app_icon_downloader_unittest.cc +++ b/chrome/browser/web_applications/web_contents/web_app_icon_downloader_unittest.cc
@@ -74,10 +74,10 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>(), - test_future.GetCallback()); + WebAppIconDownloader downloader; - downloader.Start(); + downloader.Start(web_contents(), std::vector<GURL>(), + test_future.GetCallback()); const std::vector<gfx::Size> sizes{gfx::Size(32, 32)}; web_contents_tester()->TestDidDownloadImage( /*url=*/favicon_url->icon_url, @@ -103,14 +103,14 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>(), - test_future.GetCallback()); + WebAppIconDownloader downloader; std::vector<blink::mojom::FaviconURLPtr> favicon_urls; favicon_urls.push_back(mojo::Clone(favicon_url)); web_contents_tester()->TestSetFaviconURL(mojo::Clone(favicon_urls)); - downloader.Start(); + downloader.Start(web_contents(), std::vector<GURL>(), + test_future.GetCallback()); std::vector<gfx::Size> sizes = {gfx::Size(0, 0)}; // data: URLs have a 0 HTTP status code. @@ -142,8 +142,7 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), extra_urls, - test_future.GetCallback()); + WebAppIconDownloader downloader; std::vector<blink::mojom::FaviconURLPtr> favicon_urls; favicon_urls.push_back(blink::mojom::FaviconURL::New( favicon_url_1, blink::mojom::FaviconIconType::kFavicon, @@ -159,7 +158,7 @@ web_contents_tester()->TestSetFaviconURL(mojo::Clone(favicon_urls)); - downloader.Start(); + downloader.Start(web_contents(), extra_urls, test_future.GetCallback()); std::vector<gfx::Size> sizes_1(1, gfx::Size(16, 16)); web_contents_tester()->TestDidDownloadImage( @@ -217,10 +216,9 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), extra_urls, - test_future.GetCallback(), - {.skip_page_favicons = true}); - downloader.Start(); + WebAppIconDownloader downloader; + downloader.Start(web_contents(), extra_urls, test_future.GetCallback(), + {.skip_page_favicons = true}); const std::vector<gfx::Size> sizes_1 = {gfx::Size{16, 16}}; web_contents_tester()->TestDidDownloadImage( @@ -255,8 +253,7 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>(), - test_future.GetCallback()); + WebAppIconDownloader downloader; std::vector<blink::mojom::FaviconURLPtr> favicon_urls; favicon_urls.push_back(blink::mojom::FaviconURL::New( @@ -264,7 +261,8 @@ blink::mojom::FaviconIconType::kFavicon, std::vector<gfx::Size>())); web_contents_tester()->TestSetFaviconURL(mojo::Clone(favicon_urls)); - downloader.Start(); + downloader.Start(web_contents(), std::vector<GURL>(), + test_future.GetCallback()); static_cast<content::WebContentsObserver&>(downloader).WebContentsDestroyed(); @@ -279,8 +277,7 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>(), - test_future.GetCallback()); + WebAppIconDownloader downloader; std::vector<blink::mojom::FaviconURLPtr> favicon_urls; favicon_urls.push_back(blink::mojom::FaviconURL::New( @@ -288,7 +285,8 @@ blink::mojom::FaviconIconType::kFavicon, std::vector<gfx::Size>())); web_contents_tester()->TestSetFaviconURL(mojo::Clone(favicon_urls)); - downloader.Start(); + downloader.Start(web_contents(), std::vector<GURL>(), + test_future.GetCallback()); content::NavigationSimulator::CreateRendererInitiated( GURL("https://foo.example"), main_rfh()) @@ -307,10 +305,9 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>{url}, - test_future.GetCallback(), - {.skip_page_favicons = true}); - downloader.Start(); + WebAppIconDownloader downloader; + downloader.Start(web_contents(), std::vector<GURL>{url}, + test_future.GetCallback(), {.skip_page_favicons = true}); std::vector<gfx::Size> sizes = {gfx::Size(32, 32)}; web_contents_tester()->TestDidDownloadImage( @@ -339,8 +336,7 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>(), - test_future.GetCallback()); + WebAppIconDownloader downloader; std::vector<blink::mojom::FaviconURLPtr> favicon_urls; favicon_urls.push_back(blink::mojom::FaviconURL::New( favicon_url, blink::mojom::FaviconIconType::kFavicon, @@ -348,7 +344,8 @@ web_contents_tester()->TestUpdateFaviconURL(mojo::Clone(favicon_urls)); - downloader.Start(); + downloader.Start(web_contents(), std::vector<GURL>(), + test_future.GetCallback()); content::NavigationSimulator::CreateRendererInitiated( GURL("https://foo.example/#test"), main_rfh()) @@ -389,15 +386,15 @@ base::test::TestFuture<IconsDownloadedResult, IconsMap, DownloadedIconsHttpResults> test_future; - WebAppIconDownloader downloader(web_contents(), std::vector<GURL>(), - test_future.GetCallback()); + WebAppIconDownloader downloader; std::vector<blink::mojom::FaviconURLPtr> favicon_urls; favicon_urls.push_back(blink::mojom::FaviconURL::New( favicon_url, blink::mojom::FaviconIconType::kFavicon, std::vector<gfx::Size>())); web_contents_tester()->TestUpdateFaviconURL(mojo::Clone(favicon_urls)); - downloader.Start(); + downloader.Start(web_contents(), std::vector<GURL>(), + test_future.GetCallback()); // Start a prerender and navigate the test page. const GURL& prerender_url = GURL("http://foo.example/bar");
diff --git a/chrome/browser/web_applications/web_contents/web_contents_manager.cc b/chrome/browser/web_applications/web_contents/web_contents_manager.cc new file mode 100644 index 0000000..0f373d49 --- /dev/null +++ b/chrome/browser/web_applications/web_contents/web_contents_manager.cc
@@ -0,0 +1,35 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/web_applications/web_contents/web_contents_manager.h" + +#include <memory> + +#include "chrome/browser/web_applications/web_contents/web_app_data_retriever.h" +#include "chrome/browser/web_applications/web_contents/web_app_icon_downloader.h" +#include "chrome/browser/web_applications/web_contents/web_app_url_loader.h" + +namespace web_app { + +WebContentsManager::WebContentsManager() = default; +WebContentsManager::~WebContentsManager() = default; + +std::unique_ptr<WebAppUrlLoader> WebContentsManager::CreateUrlLoader() { + return std::make_unique<WebAppUrlLoader>(); +} + +std::unique_ptr<WebAppDataRetriever> WebContentsManager::CreateDataRetriever() { + return std::make_unique<WebAppDataRetriever>(); +} + +std::unique_ptr<WebAppIconDownloader> +WebContentsManager::CreateIconDownloader() { + return std::make_unique<WebAppIconDownloader>(); +} + +base::WeakPtr<WebContentsManager> WebContentsManager::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/web_contents/web_contents_manager.h b/chrome/browser/web_applications/web_contents/web_contents_manager.h new file mode 100644 index 0000000..c3d1f201 --- /dev/null +++ b/chrome/browser/web_applications/web_contents/web_contents_manager.h
@@ -0,0 +1,45 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_WEB_APPLICATIONS_WEB_CONTENTS_WEB_CONTENTS_MANAGER_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_WEB_CONTENTS_WEB_CONTENTS_MANAGER_H_ + +#include <memory> +#include "base/memory/weak_ptr.h" + +namespace web_app { + +class WebAppDataRetriever; +class WebAppIconDownloader; +class WebAppUrlLoader; + +// This manager is intended to wrap all of the functionality that the +// `WebAppProvider` system needs from `WebContents`. This encompasses retrieving +// any information from a given `WebContents`. +// +// Since `WebContents` are generally not functional in unit tests, this class is +// faked by the the `FakeWebContentsManager` to allow easy unit testing. +// +// TODO(b/280517254): Have this class more fully encompass the WebContents +// dependency, instead of creating classes that operate on it. +class WebContentsManager { + public: + WebContentsManager(); + virtual ~WebContentsManager(); + + virtual std::unique_ptr<WebAppUrlLoader> CreateUrlLoader(); + + virtual std::unique_ptr<WebAppDataRetriever> CreateDataRetriever(); + + virtual std::unique_ptr<WebAppIconDownloader> CreateIconDownloader(); + + base::WeakPtr<WebContentsManager> GetWeakPtr(); + + private: + base::WeakPtrFactory<WebContentsManager> weak_ptr_factory_{this}; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_WEB_CONTENTS_WEB_CONTENTS_MANAGER_H_
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 7f49a94..6d3f6d8 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -985,6 +985,15 @@ } } +void AuthenticatorRequestDialogModel::StartICloudKeychain( + size_t mechanism_index) { + DCHECK(transport_availability_.has_icloud_keychain); + current_mechanism_ = mechanism_index; + + HideDialogAndDispatchToPlatformAuthenticator( + device::AuthenticatorType::kICloudKeychain); +} + void AuthenticatorRequestDialogModel::ContactPhone(const std::string& name, size_t mechanism_index) { current_mechanism_ = mechanism_index; @@ -1185,6 +1194,16 @@ } } + if (transport_availability_.has_icloud_keychain) { + const std::u16string name = u"iCloud Keychain (UNTRANSLATED)"; + mechanisms_.emplace_back( + Mechanism::ICloudKeychain(), name, name, kSmartphoneIcon, + base::BindRepeating( + &AuthenticatorRequestDialogModel::StartICloudKeychain, + base::Unretained(this), mechanisms_.size()), + /*priority=*/false); + } + // The Windows API option comes first so that it gets focus and people can // select it by simply hitting enter. if (win_native_api_enabled()) { @@ -1310,6 +1329,11 @@ transport_availability_.is_only_hybrid_or_internal; if (!use_conditional_mediation_) { // If there's a match on the platform authenticator, jump to that. + if (transport_availability_.has_icloud_keychain_credential == + device::FidoRequestHandlerBase::RecognizedCredential:: + kHasRecognizedCredential) { + priority_list.emplace_back(Mechanism::ICloudKeychain()); + } if (transport_availability_.has_platform_authenticator_credential == device::FidoRequestHandlerBase::RecognizedCredential:: kHasRecognizedCredential) {
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index 89210a8..b0f0361 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -185,9 +185,12 @@ using Transport = base::StrongAlias<class TransportTag, AuthenticatorTransport>; using WindowsAPI = base::StrongAlias<class WindowsAPITag, absl::monostate>; + using ICloudKeychain = + base::StrongAlias<class iCloudKeychainTag, std::monostate>; using Phone = base::StrongAlias<class PhoneTag, std::string>; using AddPhone = base::StrongAlias<class AddPhoneTag, absl::monostate>; - using Type = absl::variant<Transport, WindowsAPI, Phone, AddPhone>; + using Type = + absl::variant<Transport, WindowsAPI, Phone, AddPhone, ICloudKeychain>; Mechanism(Type type, std::u16string name, @@ -673,6 +676,8 @@ // |HideDialogAndDispatchToNativeWindowsApi|. void StartWinNativeApi(size_t mechanism_index); + void StartICloudKeychain(size_t mechanism_index); + // Contacts a paired phone. The phone is specified by name. void ContactPhone(const std::string& name, size_t mechanism_index); void ContactPhoneAfterOffTheRecordInterstitial(std::string name);
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index 5cb1bb4..7f90c21e 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -676,6 +676,17 @@ qr_generator_key, std::move(paired_phones)); } + +#if BUILDFLAG(IS_MAC) + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(GetRenderFrameHost()); + BrowserWindow* browser_window = + BrowserWindow::FindBrowserWindowWithWebContents(web_contents); + if (browser_window) { + discovery_factory->set_nswindow(reinterpret_cast<uintptr_t>( + browser_window->GetNativeWindow().GetNativeNSWindow())); + } +#endif } void ChromeAuthenticatorRequestDelegate::SelectAccount(
diff --git a/chrome/browser/webshare/mac/sharing_service_operation.mm b/chrome/browser/webshare/mac/sharing_service_operation.mm index b812df5..d359dcb4 100644 --- a/chrome/browser/webshare/mac/sharing_service_operation.mm +++ b/chrome/browser/webshare/mac/sharing_service_operation.mm
@@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "base/i18n/file_util_icu.h" +#include "base/mac/scoped_nsobject.h" #include "base/no_destructor.h" #include "base/rand_util.h" #include "base/strings/string_util.h" @@ -30,10 +31,6 @@ #include "storage/browser/blob/blob_storage_context.h" #include "url/gurl.h" -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - using content::BrowserContext; using content::StoragePartition;
diff --git a/chrome/build/lacros-arm.pgo.txt b/chrome/build/lacros-arm.pgo.txt index f4d498b4..60f3086 100644 --- a/chrome/build/lacros-arm.pgo.txt +++ b/chrome/build/lacros-arm.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-arm-generic-main-1685102568-5f5fb5ea84297163e419a43d2aba635a4024dde0.profdata +chrome-chromeos-arm-generic-main-1685145825-710dcd0523d4e718e30a0492abc556e2fa7534d0.profdata
diff --git a/chrome/build/lacros-arm64.pgo.txt b/chrome/build/lacros-arm64.pgo.txt index 955ed7b..e96aa35 100644 --- a/chrome/build/lacros-arm64.pgo.txt +++ b/chrome/build/lacros-arm64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-arm64-generic-main-1685102235-1600a260772d801b26f98a364700103fea5b7915.profdata +chrome-chromeos-arm64-generic-main-1685145825-232e52eec6f5378a9494abbef3a480fc010c3b68.profdata
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index dc26020c..b7ce38c 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1685103042-9a88f5ede08d819b9a467dc3597e7405a709230e.profdata +chrome-chromeos-amd64-generic-main-1685145619-1090fd4bd7ef34b48b3b8a85f48d3a081e2f6638.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index f87fcb6..6c32ed9 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1685102235-d1cf1896da6f7a6a4bdf6c99c04f52f64ad7a026.profdata +chrome-linux-main-1685123982-6cb8b8eb383b9663ba345f0f84916589cd5a1a91.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 928e48f..bdedfe3 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1685116180-408f62c3820a307035fc9d61345c0a18f97a5c61.profdata +chrome-mac-arm-main-1685166946-2053ddaf37525ad08658f617e7e342b4e71923dd.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index c2b57a03..f76f146 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1685080799-7ec53c6fb5c28472043cf9bd1081a4f74ef1ef2c.profdata +chrome-mac-main-1685145406-3c7846e61db69d56b81ff40a39c30b3dbb223e6b.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 3f37fa07..6df98a3 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1685102235-7b2ac353c2d49093fd3e462f0a96187ff20ea4ef.profdata +chrome-win32-main-1685156363-b5cbb347aa03a3f959b6ec54c293edf0cb3d074f.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index e51acb5..c35e62c 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1685102235-efdecedd5f216563357acafc4c5beb5e6f9caa3c.profdata +chrome-win64-main-1685156363-7196f8575a15ee74ff8d34420ba111144b95baf1.profdata
diff --git a/chrome/common/net/x509_certificate_model.cc b/chrome/common/net/x509_certificate_model.cc index 28ab925..53fdcb56 100644 --- a/chrome/common/net/x509_certificate_model.cc +++ b/chrome/common/net/x509_certificate_model.cc
@@ -16,9 +16,11 @@ #include "components/strings/grit/components_strings.h" #include "components/url_formatter/url_formatter.h" #include "crypto/sha2.h" +#include "net/cert/ct_objects_extractor.h" #include "net/cert/pki/cert_errors.h" #include "net/cert/pki/certificate_policies.h" #include "net/cert/pki/extended_key_usage.h" +#include "net/cert/pki/parse_certificate.h" #include "net/cert/pki/parse_name.h" #include "net/cert/pki/signature_algorithm.h" #include "net/cert/pki/verify_signed_data.h" @@ -216,6 +218,10 @@ constexpr uint8_t kMsNtdsReplication[] = {0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x19, 0x01}; +// 1.3.6.1.4.1.311.21.7 +constexpr uint8_t kMsCertTemplate[] = {0x2b, 0x06, 0x01, 0x04, 0x01, + 0x82, 0x37, 0x15, 0x07}; + // 1.3.6.1.4.1.311.2.1.21 constexpr uint8_t kEkuMsIndividualCodeSigning[] = { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x15}; @@ -471,6 +477,7 @@ IDS_CERT_X509_AUTH_INFO_ACCESS}, {net::der::Input(net::kCpsPointerId), IDS_CERT_PKIX_CPS_POINTER_QUALIFIER}, {net::der::Input(net::kUserNoticeId), IDS_CERT_PKIX_USER_NOTICE_QUALIFIER}, + {net::der::Input(net::ct::kEmbeddedSCTOid), IDS_CERT_X509_SCT_LIST}, // Extended Key Usages: {net::der::Input(net::kAnyEKU), IDS_CERT_EKU_ANY_EKU}, @@ -490,6 +497,9 @@ {net::der::Input(kMsCertsrvCaVersion), IDS_CERT_EXT_MS_CA_VERSION}, {net::der::Input(kMsNtPrincipalName), IDS_CERT_EXT_MS_NT_PRINCIPAL_NAME}, {net::der::Input(kMsNtdsReplication), IDS_CERT_EXT_MS_NTDS_REPLICATION}, + {net::der::Input(net::kMSApplicationPoliciesOid), + IDS_CERT_EXT_MS_APP_POLICIES}, + {net::der::Input(kMsCertTemplate), IDS_CERT_EXT_MS_CERT_TEMPLATE}, {net::der::Input(kEkuMsIndividualCodeSigning), IDS_CERT_EKU_MS_INDIVIDUAL_CODE_SIGNING}, {net::der::Input(kEkuMsCommercialCodeSigning),
diff --git a/chrome/common/net/x509_certificate_model_unittest.cc b/chrome/common/net/x509_certificate_model_unittest.cc index 13940021..776de95c 100644 --- a/chrome/common/net/x509_certificate_model_unittest.cc +++ b/chrome/common/net/x509_certificate_model_unittest.cc
@@ -160,6 +160,43 @@ extensions[3].value); } +TEST_P(X509CertificateModel, GetSCTField) { + auto cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), + "lets-encrypt-dst-x3-root.pem"); + ASSERT_TRUE(cert); + x509_certificate_model::X509CertificateModel model( + bssl::UpRef(cert->cert_buffer()), GetParam()); + ASSERT_TRUE(model.is_valid()); + + EXPECT_EQ("3", model.GetVersion()); + EXPECT_EQ("04:7B:F4:FD:2C:FB:01:92:D5:30:C1:0F:C9:19:83:2A:49:EF", + model.GetSerialNumberHexified()); + + auto extensions = model.GetExtensions("critical", "notcrit"); + auto extension_value = + FindExtension(extensions, "Signed Certificate Timestamp List"); + ASSERT_TRUE(extension_value); + EXPECT_EQ( + "notcrit\n" + "04 81 F1 00 EF 00 76 00 41 C8 CA B1 DF 22 46 4A\n" + "10 C6 A1 3A 09 42 87 5E 4E 31 8B 1B 03 EB EB 4B\n" + "C7 68 F0 90 62 96 06 F6 00 00 01 7E 17 63 85 3D\n" + "00 00 04 03 00 47 30 45 02 20 05 FB 47 45 BD 63\n" + "AD FD E7 AF 9E 7E D6 51 5A 1E AB 62 FE 2A 27 4B\n" + "A0 ED 8A 4A 8F B3 C8 36 8C BD 02 21 00 8B 07 10\n" + "4C BF 07 1C ED 54 DF 28 2C E3 B2 32 6B 43 48 E4\n" + "04 80 28 17 91 50 8D 28 FC 58 08 BF 7C 00 75 00\n" + "46 A5 55 EB 75 FA 91 20 30 B5 A2 89 69 F4 F3 7D\n" + "11 2C 41 74 BE FD 49 B8 85 AB F2 FC 70 FE 6D 47\n" + "00 00 01 7E 17 63 85 53 00 00 04 03 00 46 30 44\n" + "02 20 73 8C D6 ED CC 59 2D 3D 5E 1A 37 E9 42 A2\n" + "74 6D 95 1B 20 0E 19 91 40 0E AD A3 80 66 48 FB\n" + "17 32 02 20 02 3A 61 DA 61 EF CB 37 BB 97 5E AC\n" + "79 08 2B 5E 71 EA 9B 7B FC B4 F5 50 04 2E E0 40\n" + "42 44 2C 79", + extension_value); +} + TEST_P(X509CertificateModel, GetNDNCertFields) { auto cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), "ndn.ca.crt");
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc index 612b58df..a7a9941 100644 --- a/chrome/common/url_constants.cc +++ b/chrome/common/url_constants.cc
@@ -180,6 +180,9 @@ const char kHighEfficiencyModeLearnMoreUrl[] = "https://support.google.com/chrome/?p=chrome_memory_saver"; +const char kHighEfficiencyModeTabDiscardingHelpUrl[] = + "https://support.google.com/chrome/?p=performance_site_exclusion"; + const char kLearnMoreReportingURL[] = "https://support.google.com/chrome/?p=ui_usagestat";
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h index 00c496b3..bccad49 100644 --- a/chrome/common/url_constants.h +++ b/chrome/common/url_constants.h
@@ -193,6 +193,10 @@ // The URL for the "Learn more" link for the High Efficiency Mode. extern const char kHighEfficiencyModeLearnMoreUrl[]; +// The URL in the help text for the High Efficiency Mode tab discarding +// exceptions add dialog. +extern const char kHighEfficiencyModeTabDiscardingHelpUrl[]; + // The URL for the "Learn more" page for the usage/crash reporting option in the // first run dialog. extern const char kLearnMoreReportingURL[];
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 3226588..f38530ce 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -129,6 +129,7 @@ const char kChromeUIKillHost[] = "kill"; const char kChromeUILauncherInternalsHost[] = "launcher-internals"; const char kChromeUILocalStateHost[] = "local-state"; +const char kChromeUILocationInternalsHost[] = "location-internals"; const char kChromeUIManagementHost[] = "management"; const char kChromeUIManagementURL[] = "chrome://management"; const char kChromeUIMediaEngagementHost[] = "media-engagement"; @@ -293,6 +294,7 @@ #if BUILDFLAG(IS_CHROMEOS) const char kChromeUIGpuURL[] = "chrome://gpu"; const char kChromeUIHistogramsURL[] = "chrome://histograms"; +const char kChromeUILocationInternalsURL[] = "chrome://location-internals"; #endif #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index 9bbf2a5..58833120 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -125,6 +125,7 @@ extern const char kChromeUIKillHost[]; extern const char kChromeUILauncherInternalsHost[]; extern const char kChromeUILocalStateHost[]; +extern const char kChromeUILocationInternalsHost[]; extern const char kChromeUIManagementHost[]; extern const char kChromeUIManagementURL[]; extern const char kChromeUIMediaEngagementHost[]; @@ -268,6 +269,7 @@ #if BUILDFLAG(IS_CHROMEOS) extern const char kChromeUIGpuURL[]; extern const char kChromeUIHistogramsURL[]; +extern const char kChromeUILocationInternalsURL[]; extern const char kChromeUIKerberosInBrowserHost[]; extern const char kChromeUIKerberosInBrowserURL[]; extern const char kChromeUINotifGeneratorURL[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 5d77324..7d3a682a 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -555,7 +555,6 @@ deps += [ "//build:branding_buildflags", "//chrome/app_shim", - "//chrome/browser:browser_noarc", "//components/upload_list", ] configs += [ "//build/config/compiler:enable_arc" ] @@ -1340,7 +1339,6 @@ "//chrome/app:command_ids", "//chrome/app_shim", "//chrome/browser", - "//chrome/browser:browser_noarc", "//chrome/browser:browser_process", "//chrome/browser/apps/app_shim", "//chrome/browser/profiles:profile", @@ -2457,6 +2455,7 @@ "../browser/ui/webui/identity_internals_ui_browsertest.h", "../browser/ui/webui/inspect_ui_browsertest.cc", "../browser/ui/webui/interstitials/interstitial_ui_browsertest.cc", + "../browser/ui/webui/location_internals/location_internals_ui_browsertest.cc", "../browser/ui/webui/log_web_ui_url_browsertest.cc", "../browser/ui/webui/management/management_a11y_browsertest.cc", "../browser/ui/webui/management/management_a11y_browsertest.h", @@ -2846,7 +2845,6 @@ deps += [ ":browser_tests_arc", "//chrome/app_shim", - "//chrome/browser:browser_noarc", "//chrome/browser/apps/app_shim", "//chrome/browser/renderer_host:history_swiper", "//chrome/browser/ui:ui_arc", @@ -5583,7 +5581,6 @@ "//base/test:test_support", "//chrome/app:command_ids", "//chrome/app/theme:chrome_unscaled_resources_grit", - "//chrome/browser:browser_noarc", "//chrome/browser/autofill:test_support", "//chrome/browser/mac:keystone_glue", "//chrome/browser/ui:test_support", @@ -6688,7 +6685,6 @@ deps += [ ":unit_tests_arc", "//chrome/app_shim", - "//chrome/browser:browser_noarc", "//chrome/browser/apps/app_shim", "//chrome/browser/renderer_host:history_swiper", "//chrome/browser/ui:ui_arc", @@ -7260,6 +7256,7 @@ "../browser/ui/search/search_ipc_router_policy_unittest.cc", "../browser/ui/search/search_ipc_router_unittest.cc", "../browser/ui/serial/serial_chooser_controller_unittest.cc", + "../browser/ui/side_panel/companion/companion_utils_unittest.cc", "../browser/ui/singleton_tabs_unittest.cc", "../browser/ui/startup/launch_mode_recorder_unittest.cc", "../browser/ui/sync/sync_promo_ui_unittest.cc", @@ -9688,10 +9685,7 @@ } if (is_mac) { - deps += [ - "//chrome/browser:browser_noarc", - "//chrome/browser/apps/app_shim:app_shim", - ] + deps += [ "//chrome/browser/apps/app_shim:app_shim" ] sources += [ "base/interactive_test_utils_mac.mm" ] } @@ -10483,7 +10477,6 @@ deps += [ ":interactive_ui_tests_arc", - "//chrome/browser:browser_noarc", "//chrome/browser/apps/app_shim", "//chrome/browser/web_applications/extensions", "//components/spellcheck:buildflags",
diff --git a/chrome/test/chromedriver/chrome/chrome_android_impl.cc b/chrome/test/chromedriver/chrome/chrome_android_impl.cc index 44e311bd..6342c87 100644 --- a/chrome/test/chromedriver/chrome/chrome_android_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_android_impl.cc
@@ -20,14 +20,12 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy, std::unique_ptr<Device> device) : ChromeImpl(std::move(http_client), std::move(websocket_client), std::move(devtools_event_listeners), std::move(mobile_device), - std::move(socket_factory), page_load_strategy), device_(std::move(device)) {}
diff --git a/chrome/test/chromedriver/chrome/chrome_android_impl.h b/chrome/test/chromedriver/chrome/chrome_android_impl.h index 49525934..6af4da9 100644 --- a/chrome/test/chromedriver/chrome/chrome_android_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_android_impl.h
@@ -22,7 +22,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy, std::unique_ptr<Device> device); ~ChromeAndroidImpl() override;
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc index 6ae78b3..16d3ec05 100644 --- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.cc
@@ -78,7 +78,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy, base::Process process, const base::CommandLine& command, @@ -89,7 +88,6 @@ std::move(websocket_client), std::move(devtools_event_listeners), std::move(mobile_device), - std::move(socket_factory), page_load_strategy), process_(std::move(process)), command_(command),
diff --git a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h index 8fa96c1..2680651c 100644 --- a/chrome/test/chromedriver/chrome/chrome_desktop_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_desktop_impl.h
@@ -13,7 +13,6 @@ #include "base/process/process.h" #include "chrome/test/chromedriver/chrome/chrome_impl.h" #include "chrome/test/chromedriver/chrome/scoped_temp_dir_with_retry.h" -#include "chrome/test/chromedriver/net/sync_websocket_factory.h" namespace base { class TimeDelta; @@ -31,7 +30,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy, base::Process process, const base::CommandLine& command,
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc index 66b8704b..db6346a4 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_impl.cc
@@ -672,10 +672,8 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy) : mobile_device_(std::move(mobile_device)), - socket_factory_(std::move(socket_factory)), devtools_http_client_(std::move(http_client)), devtools_websocket_client_(std::move(websocket_client)), devtools_event_listeners_(std::move(devtools_event_listeners)),
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.h b/chrome/test/chromedriver/chrome/chrome_impl.h index af45b7d..c0dd7a4 100644 --- a/chrome/test/chromedriver/chrome/chrome_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_impl.h
@@ -13,7 +13,6 @@ #include "base/values.h" #include "chrome/test/chromedriver/chrome/chrome.h" #include "chrome/test/chromedriver/chrome/mobile_device.h" -#include "chrome/test/chromedriver/net/sync_websocket_factory.h" class DevToolsClient; class DevToolsClientImpl; @@ -65,7 +64,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy); virtual Status QuitImpl() = 0; @@ -93,7 +91,6 @@ bool quit_ = false; absl::optional<MobileDevice> mobile_device_; - SyncWebSocketFactory socket_factory_; std::unique_ptr<DevToolsHttpClient> devtools_http_client_; std::unique_ptr<DevToolsClient> devtools_websocket_client_;
diff --git a/chrome/test/chromedriver/chrome/chrome_remote_impl.cc b/chrome/test/chromedriver/chrome/chrome_remote_impl.cc index 97531a7..e7466c7 100644 --- a/chrome/test/chromedriver/chrome/chrome_remote_impl.cc +++ b/chrome/test/chromedriver/chrome/chrome_remote_impl.cc
@@ -17,13 +17,11 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy) : ChromeImpl(std::move(http_client), std::move(websocket_client), std::move(devtools_event_listeners), std::move(mobile_device), - std::move(socket_factory), page_load_strategy) {} ChromeRemoteImpl::~ChromeRemoteImpl() = default;
diff --git a/chrome/test/chromedriver/chrome/chrome_remote_impl.h b/chrome/test/chromedriver/chrome/chrome_remote_impl.h index aeea77d..6e635ce 100644 --- a/chrome/test/chromedriver/chrome/chrome_remote_impl.h +++ b/chrome/test/chromedriver/chrome/chrome_remote_impl.h
@@ -10,7 +10,6 @@ #include "chrome/test/chromedriver/chrome/chrome_impl.h" #include "chrome/test/chromedriver/chrome/mobile_device.h" -#include "chrome/test/chromedriver/net/sync_websocket_factory.h" class DevToolsClient; class DevToolsHttpClient; @@ -22,7 +21,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy); ~ChromeRemoteImpl() override;
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.h b/chrome/test/chromedriver/chrome/devtools_client_impl.h index 40338607..a82136a 100644 --- a/chrome/test/chromedriver/chrome/devtools_client_impl.h +++ b/chrome/test/chromedriver/chrome/devtools_client_impl.h
@@ -16,7 +16,6 @@ #include "base/memory/scoped_refptr.h" #include "base/values.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" -#include "chrome/test/chromedriver/net/sync_websocket_factory.h" #include "chrome/test/chromedriver/net/timeout.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "url/gurl.h"
diff --git a/chrome/test/chromedriver/chrome/download_directory_override_manager.cc b/chrome/test/chromedriver/chrome/download_directory_override_manager.cc index dfaece05..2b82a3cc 100644 --- a/chrome/test/chromedriver/chrome/download_directory_override_manager.cc +++ b/chrome/test/chromedriver/chrome/download_directory_override_manager.cc
@@ -5,7 +5,6 @@ #include "chrome/test/chromedriver/chrome/download_directory_override_manager.h" #include "base/values.h" -#include "chrome/test/chromedriver/chrome/browser_info.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/status.h"
diff --git a/chrome/test/chromedriver/chrome/frame_tracker.cc b/chrome/test/chromedriver/chrome/frame_tracker.cc index 080299b..e075c35d 100644 --- a/chrome/test/chromedriver/chrome/frame_tracker.cc +++ b/chrome/test/chromedriver/chrome/frame_tracker.cc
@@ -7,14 +7,11 @@ #include <utility> #include "base/json/json_writer.h" -#include "chrome/test/chromedriver/chrome/browser_info.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/chrome/web_view_impl.h" -FrameTracker::FrameTracker(DevToolsClient* client, - WebView* web_view, - const BrowserInfo* browser_info) +FrameTracker::FrameTracker(DevToolsClient* client, WebView* web_view) : web_view_(web_view) { client->AddListener(this); }
diff --git a/chrome/test/chromedriver/chrome/frame_tracker.h b/chrome/test/chromedriver/chrome/frame_tracker.h index b073b6a..65c1a8d 100644 --- a/chrome/test/chromedriver/chrome/frame_tracker.h +++ b/chrome/test/chromedriver/chrome/frame_tracker.h
@@ -14,16 +14,13 @@ #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" #include "chrome/test/chromedriver/chrome/web_view.h" -struct BrowserInfo; class DevToolsClient; class Status; // Tracks execution context creation. class FrameTracker : public DevToolsEventListener { public: - explicit FrameTracker(DevToolsClient* client, - WebView* web_view = nullptr, - const BrowserInfo* browser_info = nullptr); + explicit FrameTracker(DevToolsClient* client, WebView* web_view = nullptr); FrameTracker(const FrameTracker&) = delete; FrameTracker& operator=(const FrameTracker&) = delete;
diff --git a/chrome/test/chromedriver/chrome/javascript_dialog_manager.cc b/chrome/test/chromedriver/chrome/javascript_dialog_manager.cc index 3e075779..dd37bf2 100644 --- a/chrome/test/chromedriver/chrome/javascript_dialog_manager.cc +++ b/chrome/test/chromedriver/chrome/javascript_dialog_manager.cc
@@ -4,13 +4,10 @@ #include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h" -#include "chrome/test/chromedriver/chrome/browser_info.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/status.h" -JavaScriptDialogManager::JavaScriptDialogManager( - DevToolsClient* client, - const BrowserInfo* browser_info) +JavaScriptDialogManager::JavaScriptDialogManager(DevToolsClient* client) : client_(client) { client_->AddListener(this); }
diff --git a/chrome/test/chromedriver/chrome/javascript_dialog_manager.h b/chrome/test/chromedriver/chrome/javascript_dialog_manager.h index b3e04b67..416d1cd 100644 --- a/chrome/test/chromedriver/chrome/javascript_dialog_manager.h +++ b/chrome/test/chromedriver/chrome/javascript_dialog_manager.h
@@ -12,15 +12,13 @@ #include "base/values.h" #include "chrome/test/chromedriver/chrome/devtools_event_listener.h" -struct BrowserInfo; class DevToolsClient; class Status; // Tracks the opening and closing of JavaScript dialogs (e.g., alerts). class JavaScriptDialogManager : public DevToolsEventListener { public: - explicit JavaScriptDialogManager(DevToolsClient* client, - const BrowserInfo* browser_info); + explicit JavaScriptDialogManager(DevToolsClient* client); JavaScriptDialogManager(const JavaScriptDialogManager&) = delete; JavaScriptDialogManager& operator=(const JavaScriptDialogManager&) = delete;
diff --git a/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc b/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc index e73e6be..7483108e 100644 --- a/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc +++ b/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc
@@ -17,8 +17,7 @@ TEST(JavaScriptDialogManager, NoDialog) { StubDevToolsClient client; - BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); std::string message("HI"); ASSERT_EQ(kNoSuchAlert, manager.GetDialogMessage(&message).code()); ASSERT_FALSE(manager.IsDialogOpen()); @@ -28,8 +27,7 @@ TEST(JavaScriptDialogManager, HandleDialogPassesParams) { RecorderDevToolsClient client; - BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); base::Value::Dict params; params.Set("message", "hi"); params.Set("type", "prompt"); @@ -47,8 +45,7 @@ TEST(JavaScriptDialogManager, HandleDialogNullPrompt) { RecorderDevToolsClient client; - BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); base::Value::Dict params; params.Set("message", "hi"); params.Set("type", "prompt"); @@ -63,8 +60,7 @@ TEST(JavaScriptDialogManager, ReconnectClearsStateAndSendsEnable) { RecorderDevToolsClient client; - BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); base::Value::Dict params; params.Set("message", "hi"); params.Set("type", "alert"); @@ -127,8 +123,7 @@ TEST(JavaScriptDialogManager, OneDialog) { FakeDevToolsClient client; - BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); base::Value::Dict params; params.Set("message", "hi"); params.Set("type", "alert"); @@ -156,8 +151,7 @@ TEST(JavaScriptDialogManager, TwoDialogs) { FakeDevToolsClient client; - BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); base::Value::Dict params; params.Set("message", "1"); params.Set("type", "confirm"); @@ -196,7 +190,7 @@ TEST(JavaScriptDialogManager, OneDialogManualClose) { StubDevToolsClient client; BrowserInfo browser_info; - JavaScriptDialogManager manager(&client, &browser_info); + JavaScriptDialogManager manager(&client); base::Value::Dict params; params.Set("message", "hi"); params.Set("type", "alert");
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker.cc b/chrome/test/chromedriver/chrome/navigation_tracker.cc index bca4ad8..e166938 100644 --- a/chrome/test/chromedriver/chrome/navigation_tracker.cc +++ b/chrome/test/chromedriver/chrome/navigation_tracker.cc
@@ -8,7 +8,6 @@ #include "base/strings/string_util.h" #include "base/uuid.h" -#include "chrome/test/chromedriver/chrome/browser_info.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/javascript_dialog_manager.h" #include "chrome/test/chromedriver/chrome/status.h" @@ -79,7 +78,6 @@ NavigationTracker::NavigationTracker( DevToolsClient* client, WebView* web_view, - const BrowserInfo* browser_info, const JavaScriptDialogManager* dialog_manager, const bool is_eager) : client_(client), @@ -97,7 +95,6 @@ DevToolsClient* client, LoadingState known_state, WebView* web_view, - const BrowserInfo* browser_info, const JavaScriptDialogManager* dialog_manager, const bool is_eager) : client_(client), @@ -111,7 +108,7 @@ InitCurrentFrame(known_state); } -NavigationTracker::~NavigationTracker() {} +NavigationTracker::~NavigationTracker() = default; void NavigationTracker::SetFrame(const std::string& new_frame_id) { if (new_frame_id.empty())
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker.h b/chrome/test/chromedriver/chrome/navigation_tracker.h index 3dc797fe..c6444dd 100644 --- a/chrome/test/chromedriver/chrome/navigation_tracker.h +++ b/chrome/test/chromedriver/chrome/navigation_tracker.h
@@ -15,7 +15,6 @@ #include "chrome/test/chromedriver/chrome/page_load_strategy.h" #include "chrome/test/chromedriver/chrome/status.h" -struct BrowserInfo; class DevToolsClient; class JavaScriptDialogManager; class Status; @@ -27,14 +26,12 @@ public: NavigationTracker(DevToolsClient* client, WebView* web_view, - const BrowserInfo* browser_info, const JavaScriptDialogManager* dialog_manager, const bool is_eager = false); NavigationTracker(DevToolsClient* client, LoadingState known_state, WebView* web_view, - const BrowserInfo* browser_info, const JavaScriptDialogManager* dialog_manager, const bool is_eager = false);
diff --git a/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc b/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc index 3dd1804..bab1732 100644 --- a/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc +++ b/chrome/test/chromedriver/chrome/navigation_tracker_unittest.cc
@@ -124,9 +124,8 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; params.Set("frameId", client_ptr->GetId()); @@ -153,9 +152,8 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; params.Set("frameId", client_ptr->GetId()); @@ -183,9 +181,8 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; std::string top_frame_id = client_ptr->GetId(); @@ -237,9 +234,9 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); NavigationTracker tracker(client_ptr, NavigationTracker::kNotLoading, - &web_view, &browser_info, &dialog_manager); + &web_view, &dialog_manager); base::Value::Dict params_scheduled; params_scheduled.Set("delay", 0); @@ -254,15 +251,13 @@ TEST(NavigationTracker, CurrentFrameLoading) { base::Value::Dict dict; - BrowserInfo browser_info; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, false, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; std::string top_frame_id = client_ptr->GetId(); @@ -307,15 +302,13 @@ TEST(NavigationTracker, FrameAttachDetach) { base::Value::Dict dict; - BrowserInfo browser_info; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, false, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; std::string top_frame_id = client_ptr->GetId(); @@ -348,15 +341,13 @@ TEST(NavigationTracker, SetFrameNoFrame) { base::Value::Dict dict; - BrowserInfo browser_info; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, false, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; std::string top_frame_id = client_ptr->GetId(); @@ -425,9 +416,8 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); bool is_pending; ASSERT_EQ(kUnknownError, @@ -444,24 +434,21 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, true)); } TEST(NavigationTracker, UnknownStateForcesStart) { base::Value::Dict dict; - BrowserInfo browser_info; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, true, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); ASSERT_NO_FATAL_FAILURE(AssertPendingState(&tracker, true)); } @@ -476,9 +463,8 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); base::Value::Dict params; params.Set("frameId", client_ptr->GetId()); @@ -488,20 +474,15 @@ } TEST(NavigationTracker, OnSuccessfulNavigate) { - BrowserInfo browser_info; - std::string version_string = "{\"Browser\": \"Chrome/44.0.2403.125\"," - " \"WebKit-Version\": \"537.36 (@199461)\"}"; - ASSERT_TRUE(ParseBrowserInfo(version_string, &browser_info).IsOk()); - base::Value::Dict dict; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, true, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); NavigationTracker tracker(client_ptr, NavigationTracker::kNotLoading, - &web_view, &browser_info, &dialog_manager); + &web_view, &dialog_manager); base::Value::Dict params; base::Value::Dict result; @@ -515,21 +496,15 @@ } TEST(NavigationTracker, OnNetworkErroredNavigate) { - BrowserInfo browser_info; - std::string version_string = - "{\"Browser\": \"Chrome/44.0.2403.125\"," - " \"WebKit-Version\": \"537.36 (@199461)\"}"; - ASSERT_TRUE(ParseBrowserInfo(version_string, &browser_info).IsOk()); - base::Value::Dict dict; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, true, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); NavigationTracker tracker(client_ptr, NavigationTracker::kNotLoading, - &web_view, &browser_info, &dialog_manager); + &web_view, &dialog_manager); base::Value::Dict params; base::Value::Dict result; @@ -544,21 +519,15 @@ } TEST(NavigationTracker, OnNonNetworkErroredNavigate) { - BrowserInfo browser_info; - std::string version_string = - "{\"Browser\": \"Chrome/44.0.2403.125\"," - " \"WebKit-Version\": \"537.36 (@199461)\"}"; - ASSERT_TRUE(ParseBrowserInfo(version_string, &browser_info).IsOk()); - base::Value::Dict dict; std::unique_ptr<DevToolsClient> client_uptr = std::make_unique<DeterminingLoadStateDevToolsClient>( false, true, std::string(), &dict); DevToolsClient* client_ptr = client_uptr.get(); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); + JavaScriptDialogManager dialog_manager(client_ptr); EvaluateScriptWebView web_view(kOk); NavigationTracker tracker(client_ptr, NavigationTracker::kNotLoading, - &web_view, &browser_info, &dialog_manager); + &web_view, &dialog_manager); base::Value::Dict params; base::Value::Dict result; @@ -597,9 +566,8 @@ WebViewImpl web_view(client_ptr->GetId(), true, nullptr, &browser_info, std::move(client_uptr), absl::nullopt, PageLoadStrategy::kNormal); - JavaScriptDialogManager dialog_manager(client_ptr, &browser_info); - NavigationTracker tracker(client_ptr, &web_view, &browser_info, - &dialog_manager); + JavaScriptDialogManager dialog_manager(client_ptr); + NavigationTracker tracker(client_ptr, &web_view, &dialog_manager); bool is_pending; ASSERT_EQ(kOk, tracker.IsPendingNavigation(nullptr, &is_pending).code());
diff --git a/chrome/test/chromedriver/chrome/page_load_strategy.cc b/chrome/test/chromedriver/chrome/page_load_strategy.cc index fc217de..55d5837 100644 --- a/chrome/test/chromedriver/chrome/page_load_strategy.cc +++ b/chrome/test/chromedriver/chrome/page_load_strategy.cc
@@ -18,16 +18,13 @@ std::string strategy, DevToolsClient* client, WebView* web_view, - const BrowserInfo* browser_info, const JavaScriptDialogManager* dialog_manager) { if (strategy == kNone) { return new NonBlockingNavigationTracker(); } else if (strategy == kNormal) { - return new NavigationTracker(client, web_view, browser_info, dialog_manager, - false); + return new NavigationTracker(client, web_view, dialog_manager, false); } else if (strategy == kEager) { - return new NavigationTracker(client, web_view, browser_info, dialog_manager, - true); + return new NavigationTracker(client, web_view, dialog_manager, true); } else { NOTREACHED() << "invalid strategy '" << strategy << "'"; return nullptr;
diff --git a/chrome/test/chromedriver/chrome/page_load_strategy.h b/chrome/test/chromedriver/chrome/page_load_strategy.h index 40fd7e2..798639da 100644 --- a/chrome/test/chromedriver/chrome/page_load_strategy.h +++ b/chrome/test/chromedriver/chrome/page_load_strategy.h
@@ -8,7 +8,6 @@ #include "chrome/test/chromedriver/chrome/status.h" #include "chrome/test/chromedriver/chrome/web_view.h" -struct BrowserInfo; class DevToolsClient; class JavaScriptDialogManager; class Status; @@ -22,13 +21,12 @@ kNotLoading, }; - virtual ~PageLoadStrategy() {} + virtual ~PageLoadStrategy() = default; static PageLoadStrategy* Create( std::string strategy, DevToolsClient* client, WebView* web_view, - const BrowserInfo* browser_info, const JavaScriptDialogManager* dialog_manager); virtual Status IsPendingNavigation(const Timeout* timeout,
diff --git a/chrome/test/chromedriver/chrome/web_view_impl.cc b/chrome/test/chromedriver/chrome/web_view_impl.cc index c4fd02a..40da729 100644 --- a/chrome/test/chromedriver/chrome/web_view_impl.cc +++ b/chrome/test/chromedriver/chrome/web_view_impl.cc
@@ -325,8 +325,8 @@ is_detached_(false), parent_(parent), client_(std::move(client)), - frame_tracker_(new FrameTracker(client_.get(), this, browser_info)), - dialog_manager_(new JavaScriptDialogManager(client_.get(), browser_info)), + frame_tracker_(new FrameTracker(client_.get(), this)), + dialog_manager_(new JavaScriptDialogManager(client_.get())), mobile_emulation_override_manager_( new MobileEmulationOverrideManager(client_.get(), std::move(mobile_device), @@ -348,9 +348,9 @@ // all related calls to their parent. All WebViews must have either parent_ // or navigation_tracker_ if (!parent_) { - navigation_tracker_ = std::unique_ptr<PageLoadStrategy>( - PageLoadStrategy::Create(page_load_strategy, client_.get(), this, - browser_info, dialog_manager_.get())); + navigation_tracker_ = + std::unique_ptr<PageLoadStrategy>(PageLoadStrategy::Create( + page_load_strategy, client_.get(), this, dialog_manager_.get())); } client_->SetOwner(this); }
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc index 9929294..c64e6dc8b 100644 --- a/chrome/test/chromedriver/chrome_launcher.cc +++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -50,6 +50,7 @@ #include "chrome/test/chromedriver/chrome/web_view.h" #include "chrome/test/chromedriver/constants/version.h" #include "chrome/test/chromedriver/log_replay/chrome_replay_impl.h" +#include "chrome/test/chromedriver/log_replay/log_replay_socket.h" #include "chrome/test/chromedriver/log_replay/replay_http_client.h" #include "chrome/test/chromedriver/net/net_util.h" #include "chrome/test/chromedriver/net/sync_websocket.h" @@ -336,7 +337,7 @@ Status CreateBrowserwideDevToolsClientAndConnect( const DevToolsEndpoint& endpoint, const PerfLoggingPrefs& perf_logging_prefs, - const SyncWebSocketFactory& socket_factory, + std::unique_ptr<SyncWebSocket> socket, const std::vector<std::unique_ptr<DevToolsEventListener>>& devtools_event_listeners, const std::string& web_socket_url, @@ -345,7 +346,6 @@ if (url.length() == 0) { url = endpoint.GetBrowserDebuggerUrl(); } - std::unique_ptr<SyncWebSocket> socket = socket_factory.Run(); SyncWebSocket* socket_ptr = socket.get(); std::unique_ptr<DevToolsClientImpl> client(new DevToolsClientImpl( DevToolsClientImpl::kBrowserwideDevToolsClientId, "")); @@ -388,9 +388,11 @@ } std::unique_ptr<DevToolsClient> devtools_websocket_client; + std::unique_ptr<SyncWebSocket> socket = socket_factory.Run(); status = CreateBrowserwideDevToolsClientAndConnect( DevToolsEndpoint(capabilities.debugger_address), - capabilities.perf_logging_prefs, socket_factory, devtools_event_listeners, + capabilities.perf_logging_prefs, std::move(socket), + devtools_event_listeners, devtools_http_client->browser_info()->web_socket_url, &devtools_websocket_client); if (status.IsError()) { @@ -401,7 +403,7 @@ *chrome = std::make_unique<ChromeRemoteImpl>( std::move(devtools_http_client), std::move(devtools_websocket_client), std::move(devtools_event_listeners), capabilities.mobile_device, - socket_factory, capabilities.page_load_strategy); + capabilities.page_load_strategy); return Status(kOk); } @@ -522,8 +524,7 @@ devnull.reset(HANDLE_EINTR(open("/dev/null", O_WRONLY))); if (!devnull.is_valid()) return Status(kUnknownError, "couldn't open /dev/null"); - options.fds_to_remap.push_back( - std::make_pair(devnull.get(), STDERR_FILENO)); + options.fds_to_remap.emplace_back(devnull.get(), STDERR_FILENO); } #elif BUILDFLAG(IS_WIN) if (enable_chrome_logs) { @@ -647,9 +648,10 @@ } std::unique_ptr<DevToolsClient> devtools_websocket_client; + std::unique_ptr<SyncWebSocket> socket = socket_factory.Run(); status = CreateBrowserwideDevToolsClientAndConnect( DevToolsEndpoint(devtools_port), capabilities.perf_logging_prefs, - socket_factory, devtools_event_listeners, + std::move(socket), devtools_event_listeners, devtools_http_client->browser_info()->web_socket_url, &devtools_websocket_client); if (status.IsError()) { @@ -661,8 +663,8 @@ std::make_unique<ChromeDesktopImpl>( std::move(devtools_http_client), std::move(devtools_websocket_client), std::move(devtools_event_listeners), capabilities.mobile_device, - socket_factory, capabilities.page_load_strategy, std::move(process), - command, &user_data_dir_temp_dir, &extension_dir, + capabilities.page_load_strategy, std::move(process), command, + &user_data_dir_temp_dir, &extension_dir, capabilities.network_emulation_enabled); if (!capabilities.extension_load_timeout.is_zero()) { for (size_t i = 0; i < extension_bg_pages.size(); ++i) { @@ -735,9 +737,10 @@ } std::unique_ptr<DevToolsClient> devtools_websocket_client; + std::unique_ptr<SyncWebSocket> socket = socket_factory.Run(); status = CreateBrowserwideDevToolsClientAndConnect( DevToolsEndpoint(devtools_port), capabilities.perf_logging_prefs, - socket_factory, devtools_event_listeners, + std::move(socket), devtools_event_listeners, devtools_http_client->browser_info()->web_socket_url, &devtools_websocket_client); if (status.IsError()) { @@ -748,12 +751,11 @@ *chrome = std::make_unique<ChromeAndroidImpl>( std::move(devtools_http_client), std::move(devtools_websocket_client), std::move(devtools_event_listeners), capabilities.mobile_device, - socket_factory, capabilities.page_load_strategy, std::move(device)); + capabilities.page_load_strategy, std::move(device)); return Status(kOk); } Status LaunchReplayChrome(network::mojom::URLLoaderFactory* factory, - const SyncWebSocketFactory& socket_factory, const Capabilities& capabilities, std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, @@ -786,9 +788,15 @@ &retry, ChromeType::Replay); if (status.IsError()) return status; + const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); + base::CommandLine::StringType log_path_str = + cmd_line->GetSwitchValueNative("devtools-replay"); + base::FilePath log_path(log_path_str); + std::unique_ptr<SyncWebSocket> socket = + std::make_unique<LogReplaySocket>(log_path); std::unique_ptr<DevToolsClient> devtools_websocket_client; status = CreateBrowserwideDevToolsClientAndConnect( - DevToolsEndpoint(0), capabilities.perf_logging_prefs, socket_factory, + DevToolsEndpoint(0), capabilities.perf_logging_prefs, std::move(socket), devtools_event_listeners, devtools_http_client->browser_info()->web_socket_url, &devtools_websocket_client); @@ -802,9 +810,9 @@ std::make_unique<ChromeReplayImpl>( std::move(devtools_http_client), std::move(devtools_websocket_client), std::move(devtools_event_listeners), capabilities.mobile_device, - socket_factory, capabilities.page_load_strategy, - std::move(dummy_process), command, &user_data_dir_temp_dir, - &extension_dir, capabilities.network_emulation_enabled); + capabilities.page_load_strategy, std::move(dummy_process), command, + &user_data_dir_temp_dir, &extension_dir, + capabilities.network_emulation_enabled); if (!capabilities.extension_load_timeout.is_zero()) { for (size_t i = 0; i < extension_bg_pages.size(); ++i) { @@ -849,7 +857,7 @@ std::move(devtools_event_listeners), device_manager, chrome); } else if (cmd_line->HasSwitch("devtools-replay")) { - return LaunchReplayChrome(factory, socket_factory, capabilities, + return LaunchReplayChrome(factory, capabilities, std::move(devtools_event_listeners), chrome, w3c_compliant); } else {
diff --git a/chrome/test/chromedriver/chrome_launcher.h b/chrome/test/chromedriver/chrome_launcher.h index 2b7fb75..50bb418 100644 --- a/chrome/test/chromedriver/chrome_launcher.h +++ b/chrome/test/chromedriver/chrome_launcher.h
@@ -22,11 +22,9 @@ enum TerminationStatus; } // namespace base -namespace network { -namespace mojom { +namespace network::mojom { class URLLoaderFactory; -} -} // namespace network +} // namespace network::mojom class Chrome; class DeviceManager;
diff --git a/chrome/test/chromedriver/log_replay/chrome_replay_impl.cc b/chrome/test/chromedriver/log_replay/chrome_replay_impl.cc index 7fe680a..73544a4 100644 --- a/chrome/test/chromedriver/log_replay/chrome_replay_impl.cc +++ b/chrome/test/chromedriver/log_replay/chrome_replay_impl.cc
@@ -14,7 +14,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy, base::Process process, const base::CommandLine& command, @@ -25,7 +24,6 @@ std::move(websocket_client), std::move(devtools_event_listeners), std::move(mobile_device), - std::move(socket_factory), page_load_strategy, std::move(process), command,
diff --git a/chrome/test/chromedriver/log_replay/chrome_replay_impl.h b/chrome/test/chromedriver/log_replay/chrome_replay_impl.h index 71f6547..6e2e57f 100644 --- a/chrome/test/chromedriver/log_replay/chrome_replay_impl.h +++ b/chrome/test/chromedriver/log_replay/chrome_replay_impl.h
@@ -23,7 +23,6 @@ std::vector<std::unique_ptr<DevToolsEventListener>> devtools_event_listeners, absl::optional<MobileDevice> mobile_device, - SyncWebSocketFactory socket_factory, std::string page_load_strategy, base::Process process, const base::CommandLine& command,
diff --git a/chrome/test/chromedriver/log_replay/replay_http_client.h b/chrome/test/chromedriver/log_replay/replay_http_client.h index 358000a..7daa832a 100644 --- a/chrome/test/chromedriver/log_replay/replay_http_client.h +++ b/chrome/test/chromedriver/log_replay/replay_http_client.h
@@ -14,11 +14,9 @@ #include "chrome/test/chromedriver/log_replay/devtools_log_reader.h" #include "chrome/test/chromedriver/net/sync_websocket_factory.h" -namespace network { -namespace mojom { +namespace network::mojom { class URLLoaderFactory; -} -} // namespace network +} // namespace network::mojom // Subclass of DevToolsHttpClient that redirects communication // that would happen with Chrome to a DevToolsLogReader (i.e. a ChromeDriver
diff --git a/chrome/test/chromedriver/performance_logger.cc b/chrome/test/chromedriver/performance_logger.cc index 80b6799..43721697 100644 --- a/chrome/test/chromedriver/performance_logger.cc +++ b/chrome/test/chromedriver/performance_logger.cc
@@ -13,7 +13,6 @@ #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/values.h" -#include "chrome/test/chromedriver/chrome/browser_info.h" #include "chrome/test/chromedriver/chrome/chrome.h" #include "chrome/test/chromedriver/chrome/devtools_client.h" #include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
diff --git a/chrome/test/data/companion_iframe.html b/chrome/test/data/companion_iframe.html index f7ad827..20738dd 100644 --- a/chrome/test/data/companion_iframe.html +++ b/chrome/test/data/companion_iframe.html
@@ -1,4 +1,7 @@ <html> +<body> + <a id="some_link" href="google.html" target="_blank">Click Here</a> +</body> <script> // The proto received on last update postmessage. Reset on getLastReceivedCompanionProto(). @@ -17,6 +20,7 @@ function onBrowserMessage(event) { if (event.data['type'] == 31) { // `MethodType.kUpdateCompanionPage` window.lastReceivedCompanionProto = event.data['companionUpdateParams']; + promiseResolve(event.data['companionUpdateParams']); } else if (event.data['type'] == 32) { // `MethodType.kOnCqFindTextResultsAvailable` promiseResolve(event.data['cqTextFindResults']); }
diff --git a/chrome/test/data/extensions/api_test/debugger/background.js b/chrome/test/data/extensions/api_test/debugger/background.js index d7415f9..fd9cc04 100644 --- a/chrome/test/data/extensions/api_test/debugger/background.js +++ b/chrome/test/data/extensions/api_test/debugger/background.js
@@ -325,6 +325,7 @@ }); }, + /* TODO(crbug.com/1434257): This test is flaky. async function offlineErrorPage() { const url = 'http://127.0.0.1//extensions/api_test/debugger/inspected.html'; const tab = await openTab(url); @@ -405,6 +406,7 @@ chrome.debugger.onEvent.addListener(onEvent); chrome.debugger.attach(debuggee, protocolVersion, onAttach); }, + */ function autoAttachToOOPIF() { if (!config.customArg) {
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 2479a1fe..3ed65dc 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -247,6 +247,7 @@ "cr_components/cr_components_mojo_browsertest.js", "downloads/downloads_browsertest.js", "engagement/site_engagement_browsertest.js", + "location_internals/location_internals_browsertest.js", "media/media_engagement_browsertest.js", "media/media_history_webui_browsertest.js", "metrics_reporter/metrics_reporter_browsertest.js", @@ -452,6 +453,7 @@ "downloads:build_grdp", "history:build_grdp", "js:build_grdp", + "location_internals:build_grdp", "metrics_internals:build_grdp", "metrics_reporter:build_grdp", "mojo:build_grdp", @@ -480,6 +482,7 @@ "$target_gen_dir/downloads/resources.grdp", "$target_gen_dir/history/resources.grdp", "$target_gen_dir/js/resources.grdp", + "$target_gen_dir/location_internals/resources.grdp", "$target_gen_dir/metrics_internals/resources.grdp", "$target_gen_dir/metrics_reporter/resources.grdp", "$target_gen_dir/mocha_resources.grdp",
diff --git a/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_edit_dialog_test.ts b/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_edit_dialog_test.ts index 2f37cba..d3ffc70 100644 --- a/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_edit_dialog_test.ts +++ b/chrome/test/data/webui/chromeos/shortcut_customization/accelerator_edit_dialog_test.ts
@@ -14,7 +14,7 @@ import {fakeAcceleratorConfig, fakeLayoutInfo} from 'chrome://shortcut-customization/js/fake_data.js'; import {FakeShortcutProvider} from 'chrome://shortcut-customization/js/fake_shortcut_provider.js'; import {setShortcutProviderForTesting} from 'chrome://shortcut-customization/js/mojo_interface_provider.js'; -import {AcceleratorInfo, Modifier} from 'chrome://shortcut-customization/js/shortcut_types.js'; +import {AcceleratorInfo, AcceleratorState, Modifier} from 'chrome://shortcut-customization/js/shortcut_types.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; @@ -205,4 +205,40 @@ // Expect call count for `restoreDefault` to be 1. assertEquals(1, provider.getRestoreDefaultCallCount()); }); + + test('FilterDisabledAccelerators', async () => { + const acceleratorInfo1: AcceleratorInfo = createUserAcceleratorInfo( + Modifier.CONTROL | Modifier.SHIFT, + /*key=*/ 71, + /*keyDisplay=*/ 'g'); + + const acceleratorInfo2: AcceleratorInfo = createUserAcceleratorInfo( + Modifier.CONTROL, + /*key=*/ 67, + /*keyDisplay=*/ 'c'); + + // Default state is kEnabled. + const acceleratorInfo3: AcceleratorInfo = createUserAcceleratorInfo( + Modifier.CONTROL, + /*key=*/ 67, + /*keyDisplay=*/ 't'); + + acceleratorInfo1.state = AcceleratorState.kDisabledByUnavailableKeys; + acceleratorInfo2.state = AcceleratorState.kDisabledByUser; + + const accelerators = [acceleratorInfo1, acceleratorInfo2, acceleratorInfo3]; + const description = 'test shortcut'; + + viewElement!.acceleratorInfos = accelerators; + viewElement!.description = description; + await flush(); + const dialog = + viewElement!.shadowRoot!.querySelector('cr-dialog') as CrDialogElement; + assertTrue(dialog.open); + const acceleratorElements = + dialog.querySelectorAll('accelerator-edit-view'); + + // Expect acceleratorInfo1 and acceleratorInfo2 are filtered out. + assertEquals(1, acceleratorElements.length); + }); });
diff --git a/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js b/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js index 5fd44080..4bc6e0e 100644 --- a/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js +++ b/chrome/test/data/webui/cr_components/chromeos/network/network_icon_test.js
@@ -5,6 +5,7 @@ import 'chrome://os-settings/strings.m.js'; import 'chrome://resources/ash/common/network/network_icon.js'; +import {HotspotState} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; import {ActivationStateType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {DeviceStateType, NetworkType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; @@ -99,6 +100,41 @@ assertTrue(networkIcon.$$('#roaming').hidden); }); + test('Should not display badges for hotspot', async function() { + init(); + const hotspotInfo = {state: HotspotState.kEnabled}; + networkIcon.hotspotInfo = hotspotInfo; + + await flushAsync(); + + assertTrue(networkIcon.$$('#roaming').hidden); + assertTrue(networkIcon.$$('#secure').hidden); + assertTrue(networkIcon.$$('#technology').hidden); + }); + + [HotspotState.kEnabled, HotspotState.kDisabled, HotspotState.kEnabling, + HotspotState.kDisabling] + .forEach(hotspotState => { + test('Should display icon for hotspot', async function() { + init(); + const hotspotInfo = {state: hotspotState}; + networkIcon.hotspotInfo = hotspotInfo; + + await flushAsync(); + + if (hotspotState === HotspotState.kEnabled) { + assertTrue( + networkIcon.$$('#icon').classList.contains('hotspot-on')); + } else if (hotspotState === HotspotState.kEnabling) { + assertTrue(networkIcon.$$('#icon').classList.contains( + 'hotspot-connecting')); + } else { + assertTrue( + networkIcon.$$('#icon').classList.contains('hotspot-off')); + } + }); + }); + test('Should not display icon', async function() { init(); const networkState =
diff --git a/chrome/test/data/webui/location_internals/BUILD.gn b/chrome/test/data/webui/location_internals/BUILD.gn new file mode 100644 index 0000000..e0ced5f --- /dev/null +++ b/chrome/test/data/webui/location_internals/BUILD.gn
@@ -0,0 +1,24 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("../build_webui_tests.gni") + +build_webui_tests("build") { + resource_path_prefix = "location_internals" + + files = [ "location_internals_test.ts" ] + + ts_path_mappings = + [ "chrome://location-internals/*|" + + rebase_path( + "$root_gen_dir/chrome/browser/resources/location_internals/tsc/*", + target_gen_dir) ] + + ts_deps = [ + "//chrome/browser/resources/location_internals:build_ts", + "//ui/webui/resources/cr_elements:build_ts", + "//ui/webui/resources/js:build_ts", + "//ui/webui/resources/mojo:build_ts", + ] +}
diff --git a/chrome/test/data/webui/location_internals/location_internals_browsertest.js b/chrome/test/data/webui/location_internals/location_internals_browsertest.js new file mode 100644 index 0000000..efc17fe --- /dev/null +++ b/chrome/test/data/webui/location_internals/location_internals_browsertest.js
@@ -0,0 +1,48 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/** + * @fileoverview Tests for chrome://location-internals + */ + +GEN('#include "content/public/test/browser_test.h"'); + +/** + * @constructor + * @extends testing.Test + */ + +var LocationInternalsTest = class extends testing.Test { + /** @override */ + get browsePreload() { + return 'chrome://location-internals/'; + } + + /** @override */ + get isAsync() { + return true; + } + + /** @override */ + get extraLibraries() { + return [ + '//third_party/mocha/mocha.js', + '//chrome/test/data/webui/mocha_adapter.js', + ]; + } +}; + +TEST_F('LocationInternalsTest', 'All', async function() { + const module = await import('chrome://resources/js/static_types.js'); + const script = document.createElement('script'); + script.type = 'module'; + script.onload = () => { + // Run all registered tests. + mocha.run(); + }; + script.src = + module + .getTrustedScriptURL`chrome://webui-test/location_internals/location_internals_test.js`; + document.body.appendChild(script); +});
diff --git a/chrome/test/data/webui/location_internals/location_internals_test.ts b/chrome/test/data/webui/location_internals/location_internals_test.ts new file mode 100644 index 0000000..02eebef7 --- /dev/null +++ b/chrome/test/data/webui/location_internals/location_internals_test.ts
@@ -0,0 +1,14 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://webui-test/mojo_webui_test_support.js'; + +import {assert} from 'chrome://resources/js/assert_ts.js'; + +suite('LocationInternalsUITest', function() { + test('PageLoaded', async function() { + const watchTable = document.querySelector<HTMLElement>('#watch-position'); + assert(watchTable); + }); +});
diff --git a/chrome/test/data/webui/password_manager/BUILD.gn b/chrome/test/data/webui/password_manager/BUILD.gn index e525e407..84bc0e9 100644 --- a/chrome/test/data/webui/password_manager/BUILD.gn +++ b/chrome/test/data/webui/password_manager/BUILD.gn
@@ -15,6 +15,7 @@ "checkup_section_test.ts", "edit_password_dialog_test.ts", "move_passwords_dialog_test.ts", + "credential_note_test.ts", "password_details_card_test.ts", "password_details_section_test.ts", "password_manager_app_test.ts",
diff --git a/chrome/test/data/webui/password_manager/credential_note_test.ts b/chrome/test/data/webui/password_manager/credential_note_test.ts new file mode 100644 index 0000000..1e39458 --- /dev/null +++ b/chrome/test/data/webui/password_manager/credential_note_test.ts
@@ -0,0 +1,72 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://password-manager/password_manager.js'; + +import {CredentialNoteElement, Page, PasswordManagerImpl, Router} from 'chrome://password-manager/password_manager.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; + +import {TestPasswordManagerProxy} from './test_password_manager_proxy.js'; + +async function createNoteElement(note: string): Promise<CredentialNoteElement> { + const element = document.createElement('credential-note'); + // Fix the width so we can test hiding a long note. + element.style.display = 'block'; + element.style.width = '100px'; + element.note = note; + document.body.appendChild(element); + await flushTasks(); + return element; +} + +suite('CredentialNoteTest', function() { + let passwordManager: TestPasswordManagerProxy; + + setup(function() { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + passwordManager = new TestPasswordManagerProxy(); + PasswordManagerImpl.setInstance(passwordManager); + Router.getInstance().navigateTo(Page.PASSWORDS); + return flushTasks(); + }); + + test('empty note shows correct string', async function() { + const element = await createNoteElement(''); + + assertEquals( + loadTimeData.getString('emptyNote'), + element.$.noteValue.textContent!.trim()); + assertTrue(element.$.showMore.hidden); + }); + + test('short note is shown fully', async function() { + const note = 'Remember the milk'; + const element = await createNoteElement(note); + + assertEquals(note, element.$.noteValue.textContent!.trim()); + assertTrue(element.$.showMore.hidden); + }); + + test('long note is shown fully', async function() { + const note = + 'It is a long established fact that a reader will be distracted by ' + + 'the readable content of a page when looking at its layout. The ' + + 'point of using Lorem Ipsum is that it has a more-or-less normal ' + + 'distribution of letters, as opposed to using \'Content here, ' + + 'content here\', making it look like readable English.'; + + const element = await createNoteElement(note); + + assertEquals(note, element.$.noteValue.textContent!.trim()); + assertTrue(element.$.noteValue.hasAttribute('limit-note')); + assertFalse(element.$.showMore.hidden); + + // Open note fully + element.$.showMore.click(); + assertFalse(element.$.noteValue.hasAttribute('limit-note')); + await passwordManager.whenCalled('extendAuthValidity'); + }); +});
diff --git a/chrome/test/data/webui/password_manager/password_details_card_test.ts b/chrome/test/data/webui/password_manager/password_details_card_test.ts index 7904263..78a1e10 100644 --- a/chrome/test/data/webui/password_manager/password_details_card_test.ts +++ b/chrome/test/data/webui/password_manager/password_details_card_test.ts
@@ -44,8 +44,12 @@ }); test('Content displayed properly', async function() { - const password = createPasswordEntry( - {url: 'test.com', username: 'vik', password: 'password69'}); + const password = createPasswordEntry({ + url: 'test.com', + username: 'vik', + password: 'password69', + note: 'note', + }); const card = await createCardElement(password); @@ -53,9 +57,7 @@ assertEquals(password.password, card.$.passwordValue.value); assertEquals('password', card.$.passwordValue.type); assertTrue(isVisible(card.$.noteValue)); - assertEquals( - loadTimeData.getString('emptyNote'), - card.$.noteValue.textContent!.trim()); + assertEquals(password.note, card.$.noteValue.note); assertTrue(isVisible(card.$.copyUsernameButton)); assertTrue(isVisible(card.$.showPasswordButton)); assertTrue(isVisible(card.$.copyPasswordButton)); @@ -220,45 +222,6 @@ assertEquals(params.fromStores, password.storedIn); }); - test('short note is shown fully', async function() { - const password = createPasswordEntry({ - id: 1, - url: 'test.com', - username: 'vik', - note: 'This is just a short note. It is cold out there.', - }); - - const card = await createCardElement(password); - - assertEquals(password.note, card.$.noteValue.textContent!.trim()); - assertTrue(card.$.showMore.hidden); - }); - - test('long note is shown fully', async function() { - const password = createPasswordEntry({ - id: 1, - url: 'test.com', - username: 'vik', - note: - 'It is a long established fact that a reader will be distracted by ' + - 'the readable content of a page when looking at its layout. The ' + - 'point of using Lorem Ipsum is that it has a more-or-less normal ' + - 'distribution of letters, as opposed to using \'Content here, ' + - 'content here\', making it look like readable English.', - }); - - const card = await createCardElement(password); - - assertEquals(password.note, card.$.noteValue.textContent!.trim()); - assertTrue(card.$.noteValue.hasAttribute('limit-note')); - assertFalse(card.$.showMore.hidden); - - // Open note fully - card.$.showMore.click(); - assertFalse(card.$.noteValue.hasAttribute('limit-note')); - await passwordManager.whenCalled('extendAuthValidity'); - }); - [chrome.passwordsPrivate.PasswordStoreSet.DEVICE_AND_ACCOUNT, chrome.passwordsPrivate.PasswordStoreSet.DEVICE, chrome.passwordsPrivate.PasswordStoreSet.ACCOUNT]
diff --git a/chrome/test/data/webui/password_manager/password_manager_browsertest.js b/chrome/test/data/webui/password_manager/password_manager_browsertest.js index 0c8fae9..f406ef6 100644 --- a/chrome/test/data/webui/password_manager/password_manager_browsertest.js +++ b/chrome/test/data/webui/password_manager/password_manager_browsertest.js
@@ -29,6 +29,7 @@ ['App', 'password_manager_app_test.js'], ['Checkup', 'checkup_section_test.js'], ['CheckupDetails', 'checkup_details_section_test.js'], + ['CredentialNote', 'credential_note_test.js'], ['EditPassword', 'edit_password_dialog_test.js'], ['MovePasswordsDialog', 'move_passwords_dialog_test.js'], ['PasswordCard', 'password_details_card_test.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn index 5cf965b..4e60c2e 100644 --- a/chrome/test/data/webui/settings/chromeos/BUILD.gn +++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -52,6 +52,7 @@ "internet_subpage_tests.js", "internet_subpage_menu_test.js", "lock_screen_subpage_test.ts", + "main_page_container_test.js", "manage_users_subpage_tests.js", "nearby_share_receive_dialog_tests.js", "nearby_share_subpage_tests.js", @@ -69,7 +70,6 @@ "os_saved_devices_list_tests.js", "os_saved_devices_subpage_tests.js", "os_settings_main_test.js", - "os_settings_page_test.js", "os_settings_search_box_test.js", "os_sync_controls_subpage_test.js", "people_page_account_manager_subpage_test.js", @@ -111,7 +111,6 @@ "a11y/tts_subpage_a11y_test.js", "app_management/app_details_item_test.js", - "app_management/app_item_test.js", "app_management/app_management_page_tests.js", "app_management/app_test.js", "app_management/arc_detail_view_test.js", @@ -119,7 +118,6 @@ "app_management/dom_switch_test.js", "app_management/fake_page_handler.ts", "app_management/file_handling_item_test.js", - "app_management/main_view_test.js", "app_management/managed_apps_test.js", "app_management/pin_to_shelf_item_test.js", "app_management/plugin_vm_detail_view_test.js", @@ -204,7 +202,9 @@ "os_a11y_page/tts_voice_subpage_test.ts", "os_apps_page/app_management_page/app_detail_view_test.ts", + "os_apps_page/app_management_page/app_item_test.ts", "os_apps_page/app_management_page/chrome_app_detail_view_test.ts", + "os_apps_page/app_management_page/main_view_test.ts", "os_bluetooth_page/os_bluetooth_change_device_name_dialog_tests.js", "os_bluetooth_page/os_bluetooth_device_detail_subpage_tests.js",
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/app_item_test.js b/chrome/test/data/webui/settings/chromeos/app_management/app_item_test.js deleted file mode 100644 index 235f05e..0000000 --- a/chrome/test/data/webui/settings/chromeos/app_management/app_item_test.js +++ /dev/null
@@ -1,46 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -import {FakePageHandler} from './fake_page_handler.js'; -import {replaceBody} from './test_util.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; -import {Router} from 'chrome://os-settings/os_settings.js'; -import {AppType} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js'; - -suite('<app-management-app-item>', () => { - let appItem; - let arcApp; - - setup(async () => { - appItem = document.createElement('app-management-app-item'); - replaceBody(appItem); - await flushTasks(); - - // Create an ARC app. - const arcOptions = {type: AppType.kArc}; - - arcApp = FakePageHandler.createApp('app1_id', arcOptions); - appItem.app = arcApp; - - await flushTasks(); - }); - - test('Onclick redirects to correct route', async () => { - assertFalse(!!Router.getInstance().getQueryParameters().get('id')); - - appItem.click(); - await flushTasks(); - assertEquals( - arcApp.id, Router.getInstance().getQueryParameters().get('id')); - }); - - test('Icon renders', async () => { - const icon = appItem.shadowRoot.querySelector('#appIcon'); - - assertTrue(!!icon); - assertEquals(appItem.iconUrlFromId_(arcApp), icon.getAttribute('src')); - }); -});
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/main_view_test.js b/chrome/test/data/webui/settings/chromeos/app_management/main_view_test.js deleted file mode 100644 index 05dd0cdc..0000000 --- a/chrome/test/data/webui/settings/chromeos/app_management/main_view_test.js +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2018 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -'use strict'; - -import 'chrome://os-settings/os_settings.js'; -import {setupFakeHandler, replaceStore, replaceBody} from './test_util.js'; -import {Router} from 'chrome://os-settings/os_settings.js'; - -suite('<app-management-main-view>', function() { - let mainView; - let fakeHandler; - let store; - - /** - * @param {number} numApps - */ - async function addApps(numApps) { - for (let i = 0; i < numApps; i++) { - await fakeHandler.addApp(); - } - } - - function getAppItems() { - return mainView.shadowRoot.querySelector('#appList') - .querySelectorAll('app-management-app-item'); - } - - setup(function() { - fakeHandler = setupFakeHandler(); - store = replaceStore(); - - mainView = document.createElement('app-management-main-view'); - replaceBody(mainView); - }); - - test('simple app addition', async function() { - // Ensure there is no apps initially - assertEquals(0, getAppItems().length); - - const app = await fakeHandler.addApp(); - - const appItems = getAppItems(); - assertEquals(1, appItems.length); - assertFalse(!!Router.getInstance().getQueryParameters().get('id')); - store.setReducersEnabled(false); - - appItems[0].click(); - fakeHandler.flushPipesForTesting(); - assertTrue(!!Router.getInstance().getQueryParameters().get('id')); - }); -});
diff --git a/chrome/test/data/webui/settings/chromeos/internet_page/hotspot_summary_item_test.ts b/chrome/test/data/webui/settings/chromeos/internet_page/hotspot_summary_item_test.ts index 20be47c..93bde78 100644 --- a/chrome/test/data/webui/settings/chromeos/internet_page/hotspot_summary_item_test.ts +++ b/chrome/test/data/webui/settings/chromeos/internet_page/hotspot_summary_item_test.ts
@@ -9,7 +9,6 @@ import {CrosHotspotConfigInterface, CrosHotspotConfigObserverInterface, CrosHotspotConfigObserverRemote, HotspotAllowStatus, HotspotControlResult, HotspotState, WiFiSecurityMode} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js'; import {FakeHotspotConfig} from 'chrome://resources/ash/common/hotspot/fake_hotspot_config.js'; import {CrPolicyIndicatorElement} from 'chrome://resources/cr_elements/policy/cr_policy_indicator.js'; -import {IronIconElement} from 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; @@ -34,8 +33,8 @@ '#enableHotspotToggle'); } - function queryHotspotIcon(): IronIconElement|null { - return hotspotSummaryItem.shadowRoot!.querySelector<IronIconElement>( + function queryHotspotIcon(): HTMLElement|null { + return hotspotSummaryItem.shadowRoot!.querySelector<HTMLElement>( '#hotspotIcon'); } @@ -125,7 +124,9 @@ assertFalse(enableToggle.disabled, 'Toggle should be enabled'); assertTrue(!!subpageArrow, 'Subpage arrow should exist'); assertNull(policyIndicator, 'Policy indicator should not exist'); - assertEquals('os-settings:hotspot-disabled', hotspotIcon.icon); + const icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-off')); assertFalse(hotspotStateSublabel.hidden, 'State sublabel should show'); assertEquals( hotspotSummaryItem.i18n('hotspotSummaryStateOff'), @@ -153,7 +154,9 @@ assertFalse(enableToggle.disabled, 'Toggle should be enabled'); assertTrue(!!subpageArrow, 'Subpage arrow should exist'); assertNull(policyIndicator, 'Policy indicator should not exist'); - assertEquals('os-settings:hotspot-enabled', hotspotIcon.icon); + const icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-on')); assertFalse(hotspotStateSublabel.hidden, 'State sublabel should show'); assertEquals( hotspotSummaryItem.i18n('hotspotSummaryStateOn'), @@ -183,7 +186,9 @@ assertTrue(enableToggle.disabled, 'Toggle should be disabled'); assertNull(subpageArrow, 'Subpage arrow should not exist'); assertTrue(!!policyIndicator, 'Policy indicator should exist'); - assertEquals('os-settings:hotspot-disabled', hotspotIcon.icon); + let icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-off')); assertFalse(hotspotStateSublabel.hidden, 'State sublabel should show'); assertEquals( hotspotSummaryItem.i18n('hotspotSummaryStateOff'), @@ -199,14 +204,18 @@ assertEquals( hotspotSummaryItem.i18n('hotspotSummaryStateOn'), hotspotStateSublabel.textContent!.trim()); - assertEquals('os-settings:hotspot-enabled', hotspotIcon.icon); + icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-on')); hotspotConfig_.setFakeHotspotState(HotspotState.kDisabled); await flushAsync(); assertEquals( hotspotSummaryItem.i18n('hotspotSummaryStateOff'), hotspotStateSublabel.textContent!.trim()); - assertEquals('os-settings:hotspot-disabled', hotspotIcon.icon); + icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-off')); }); test('UI state when mobile data plan doesn\'t support hotspot', async () => { @@ -229,7 +238,9 @@ assertTrue(enableToggle.disabled, 'Toggle should be disabled'); assertNull(subpageArrow, 'Subpage arrow should not exist'); assertNull(policyIndicator, 'Policy indicator should not exist'); - assertEquals('os-settings:hotspot-disabled', hotspotIcon.icon); + const icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-off')); assertTrue(hotspotStateSublabel.hidden, 'State sublabel should hide'); assertFalse( hotspotDisabledSublabelLink.hidden, @@ -261,7 +272,9 @@ assertTrue(enableToggle.disabled, 'Toggle should be disabled'); assertNull(subpageArrow, 'Subpage arrow should not exist'); assertNull(policyIndicator, 'Policy indicator should not exist'); - assertEquals('os-settings:hotspot-disabled', hotspotIcon.icon); + const icon = hotspotIcon.shadowRoot!.querySelector<HTMLElement>('#icon'); + assertTrue(!!icon); + assertTrue(icon.classList.contains('hotspot-off')); assertTrue(hotspotStateSublabel.hidden, 'State sublabel should hide'); assertFalse( hotspotDisabledSublabelLink.hidden,
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js b/chrome/test/data/webui/settings/chromeos/main_page_container_test.js similarity index 66% rename from chrome/test/data/webui/settings/chromeos/os_settings_page_test.js rename to chrome/test/data/webui/settings/chromeos/main_page_container_test.js index fc02a13..7a3a05d 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/main_page_container_test.js
@@ -6,15 +6,16 @@ import {createPageAvailabilityForTesting, CrSettingsPrefs, Router, routes, setContactManagerForTesting, setNearbyShareSettingsForTesting} from 'chrome://os-settings/os_settings.js'; import {setBluetoothConfigForTesting} from 'chrome://resources/ash/common/bluetooth/cros_bluetooth_config.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {FakeBluetoothConfig} from 'chrome://webui-test/cr_components/chromeos/bluetooth/fake_bluetooth_config.js'; import {FakeContactManager} from 'chrome://webui-test/nearby_share/shared/fake_nearby_contact_manager.js'; import {FakeNearbyShareSettings} from 'chrome://webui-test/nearby_share/shared/fake_nearby_share_settings.js'; -suite('<os-settings-page>', function() { - /** @type {?OsSettingsPageElement} */ - let settingsPage = null; +suite('<main-page-container>', function() { + /** @type {?MainPageContainerElement} */ + let mainPageContainer = null; /** @type {?SettingsPrefsElement} */ let prefElement = null; @@ -32,8 +33,7 @@ fakeSettings = new FakeNearbyShareSettings(); setNearbyShareSettingsForTesting(fakeSettings); - // Using the real CrosBluetoothConfig will crash due to no - // SessionManager. + // Using the real CrosBluetoothConfig will crash due to no SessionManager. setBluetoothConfigForTesting(new FakeBluetoothConfig()); PolymerTest.clearBody(); @@ -42,9 +42,9 @@ await CrSettingsPrefs.initialized; }); - /** @return {OsSettingsPageElement} */ + /** @return {MainPageContainerElement} */ function init() { - const element = document.createElement('os-settings-page'); + const element = document.createElement('main-page-container'); element.prefs = prefElement.prefs; element.pageAvailability = createPageAvailabilityForTesting(); document.body.appendChild(element); @@ -52,19 +52,18 @@ return element; } - suite('Page availability', () => { suiteSetup(async () => { Router.getInstance().navigateTo(routes.BASIC); - settingsPage = init(); + mainPageContainer = init(); const idleRender = - settingsPage.shadowRoot.querySelector('settings-idle-load'); + mainPageContainer.shadowRoot.querySelector('settings-idle-load'); await idleRender.get(); }); suiteTeardown(() => { - settingsPage.remove(); + mainPageContainer.remove(); CrSettingsPrefs.resetForTesting(); Router.getInstance().resetRouteForTesting(); }); @@ -144,25 +143,68 @@ ].forEach(({pageName, elementName}) => { test(`${pageName} page is controlled by pageAvailability`, () => { // Make page available - settingsPage.pageAvailability = { - ...settingsPage.pageAvailability, + mainPageContainer.pageAvailability = { + ...mainPageContainer.pageAvailability, [pageName]: true, }; flush(); - let pageElement = settingsPage.shadowRoot.querySelector(elementName); + let pageElement = + mainPageContainer.shadowRoot.querySelector(elementName); assertTrue(!!pageElement, `<${elementName}> should exist.`); // Make page unavailable - settingsPage.pageAvailability = { - ...settingsPage.pageAvailability, + mainPageContainer.pageAvailability = { + ...mainPageContainer.pageAvailability, [pageName]: false, }; flush(); - pageElement = settingsPage.shadowRoot.querySelector(elementName); + pageElement = mainPageContainer.shadowRoot.querySelector(elementName); assertEquals(null, pageElement, `<${elementName}> should not exist.`); }); }); }); + + suite('Revamp: Wayfinding', () => { + suite('when enabled', () => { + suiteSetup(async () => { + loadTimeData.overrideValues({isRevampWayfindingEnabled: true}); + Router.getInstance().navigateTo(routes.BASIC); + mainPageContainer = init(); + }); + + suiteTeardown(() => { + mainPageContainer.remove(); + CrSettingsPrefs.resetForTesting(); + Router.getInstance().resetRouteForTesting(); + }); + + test('advanced toggle should not render', () => { + const advancedToggle = + mainPageContainer.shadowRoot.querySelector('#advancedToggle'); + assertNull(advancedToggle); + }); + }); + + suite('when disabled', () => { + suiteSetup(async () => { + loadTimeData.overrideValues({isRevampWayfindingEnabled: false}); + Router.getInstance().navigateTo(routes.BASIC); + mainPageContainer = init(); + }); + + suiteTeardown(() => { + mainPageContainer.remove(); + CrSettingsPrefs.resetForTesting(); + Router.getInstance().resetRouteForTesting(); + }); + + test('advanced toggle should render', () => { + const advancedToggle = + mainPageContainer.shadowRoot.querySelector('#advancedToggle'); + assertTrue(!!advancedToggle); + }); + }); + }); });
diff --git a/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/app_item_test.ts b/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/app_item_test.ts new file mode 100644 index 0000000..f655747 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/app_item_test.ts
@@ -0,0 +1,54 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://os-settings/lazy_load.js'; + +import {AppManagementAppItemElement} from 'chrome://os-settings/lazy_load.js'; +import {Router} from 'chrome://os-settings/os_settings.js'; +import {App, AppType} from 'chrome://resources/cr_components/app_management/app_management.mojom-webui.js'; +import {assertEquals, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; + +import {FakePageHandler} from '../../app_management/fake_page_handler.js'; +import {replaceBody} from '../../app_management/test_util.js'; + +suite('<app-management-app-item>', () => { + let appItem: AppManagementAppItemElement; + let arcApp: App; + + setup(async () => { + appItem = document.createElement('app-management-app-item'); + replaceBody(appItem); + await flushTasks(); + + // Create an ARC app. + const arcOptions = {type: AppType.kArc}; + + arcApp = FakePageHandler.createApp('app1_id', arcOptions); + appItem.app = arcApp; + + await flushTasks(); + }); + + teardown(() => { + appItem.remove(); + Router.getInstance().resetRouteForTesting(); + }); + + test('Onclick redirects to correct route', async () => { + assertNull(Router.getInstance().getQueryParameters().get('id')); + + appItem.click(); + await flushTasks(); + assertEquals( + arcApp.id, Router.getInstance().getQueryParameters().get('id')); + }); + + test('Icon renders', () => { + const icon = appItem.shadowRoot!.querySelector('#appIcon'); + + assertTrue(!!icon); + assertEquals(appItem['iconUrlFromId_'](arcApp), icon.getAttribute('src')); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts b/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts new file mode 100644 index 0000000..280283f --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/os_apps_page/app_management_page/main_view_test.ts
@@ -0,0 +1,55 @@ +// Copyright 2018 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://os-settings/lazy_load.js'; + +import {AppManagementMainViewElement} from 'chrome://os-settings/lazy_load.js'; +import {Router} from 'chrome://os-settings/os_settings.js'; +import {assertEquals, assertNull, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {TestStore} from 'chrome://webui-test/chromeos/test_store.js'; + +import {FakePageHandler} from '../../app_management/fake_page_handler.js'; +import {replaceBody, replaceStore, setupFakeHandler} from '../../app_management/test_util.js'; + +suite('<app-management-main-view>', () => { + let mainView: AppManagementMainViewElement; + let fakeHandler: FakePageHandler; + let store: TestStore; + + function getAppItems() { + const element = mainView.shadowRoot!.querySelector('#appList'); + assertTrue(!!element); + return element.querySelectorAll('app-management-app-item'); + } + + setup(() => { + fakeHandler = setupFakeHandler(); + store = replaceStore(); + + mainView = document.createElement('app-management-main-view'); + replaceBody(mainView); + }); + + teardown(() => { + mainView.remove(); + Router.getInstance().resetRouteForTesting(); + }); + + test('simple app addition', async () => { + // Ensure there is no apps initially + assertEquals(0, getAppItems().length); + + await fakeHandler.addApp(); + + const appItems = getAppItems(); + assertTrue(!!appItems); + assertEquals(1, appItems.length); + assertNull(Router.getInstance().getQueryParameters().get('id')); + store.setReducersEnabled(false); + + appItems[0]!.click(); + fakeHandler.flushPipesForTesting(); + assertTrue(!!Router.getInstance().getQueryParameters().get('id')); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js index 852851c8..18000d68 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -209,7 +209,6 @@ ['AppsPage', 'apps_page_test.js'], ['AppNotificationsSubpage', 'app_notifications_subpage_tests.js'], ['AppManagementAppDetailsItem', 'app_management/app_details_item_test.js'], - ['AppManagementAppItem', 'app_management/app_item_test.js'], ['AppManagementArcDetailView', 'app_management/arc_detail_view_test.js'], [ 'AppManagementBorealisDetailView', @@ -217,7 +216,6 @@ ], ['AppManagementDomSwitch', 'app_management/dom_switch_test.js'], ['AppManagementFileHandlingItem', 'app_management/file_handling_item_test.js'], - ['AppManagementMainView', 'app_management/main_view_test.js'], ['AppManagementManagedApp', 'app_management/managed_apps_test.js'], ['AppManagementPage', 'app_management/app_management_page_tests.js'], ['AppManagementPinToShelfItem', 'app_management/pin_to_shelf_item_test.js'], @@ -387,6 +385,7 @@ 'keyboard_shortcut_banner/keyboard_shortcut_banner_test.js' ], ['LockScreenSubpage', 'lock_screen_subpage_test.js'], + ['MainPageContainer', 'main_page_container_test.js'], ['ManageUsersSubpage', 'manage_users_subpage_tests.js'], // TODO(b/208932892): Re-enable once flakiness is fixed. // ['MultideviceFeatureItem', 'multidevice_feature_item_tests.js'], @@ -506,9 +505,17 @@ 'os_apps_page/app_management_page/app_detail_view_test.js' ], [ + 'OsAppsPageAppManagementPageAppItem', + 'os_apps_page/app_management_page/app_item_test.js' + ], + [ 'OsAppsPageAppManagementPageChromeAppDetailView', 'os_apps_page/app_management_page/chrome_app_detail_view_test.js', ], + [ + 'OsAppsPageAppManagementPageMainView', + 'os_apps_page/app_management_page/main_view_test.js' + ], ['OsBluetoothPage', 'os_bluetooth_page/os_bluetooth_page_tests.js'], [ 'OsBluetoothPageOsBluetoothChangeDeviceNameDialog', @@ -589,7 +596,6 @@ ['OsSearchPageSearchSubpage', 'os_search_page/search_subpage_test.js'], ['OsSettingsHatsUi', 'os_settings_ui/os_settings_hats_ui_test.js'], ['OsSettingsMenu', 'os_settings_menu/os_settings_menu_test.js'], - ['OsSettingsPage', 'os_settings_page_test.js'], ['OsSettingsUi', 'os_settings_ui/os_settings_ui_test.js'], ['OsSettingsUiAboutPage', 'os_settings_ui/os_settings_ui_about_page_test.js'], ['OsSettingsUiMenu', 'os_settings_ui/os_settings_ui_menu_test.js'],
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_main_test.js b/chrome/test/data/webui/settings/chromeos/os_settings_main_test.js index 0e37f9e..699a6d9 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_main_test.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_main_test.js
@@ -55,11 +55,12 @@ assertTrue(showManagedHeader()); - const page = settingsMain.shadowRoot.querySelector('os-settings-page'); + const mainPageContainer = + settingsMain.shadowRoot.querySelector('main-page-container'); const subpageExpandEvent = new CustomEvent('subpage-expand', {'bubbles': true, composed: true}); - page.dispatchEvent(subpageExpandEvent); + mainPageContainer.dispatchEvent(subpageExpandEvent); assertFalse(showManagedHeader()); }); @@ -75,9 +76,11 @@ /** @return {!HTMLElement} */ function getToggleContainer() { - const page = settingsMain.shadowRoot.querySelector('os-settings-page'); - assertTrue(!!page); - const toggleContainer = page.shadowRoot.querySelector('#toggleContainer'); + const mainPageContainer = + settingsMain.shadowRoot.querySelector('main-page-container'); + assertTrue(!!mainPageContainer); + const toggleContainer = + mainPageContainer.shadowRoot.querySelector('#toggleContainer'); assertTrue(!!toggleContainer); return toggleContainer; } @@ -103,13 +106,17 @@ */ async function assertPageDisplay(expectedBasic, expectedAdvanced) { flush(); - const page = settingsMain.shadowRoot.querySelector('os-settings-page'); + const mainPageContainer = + settingsMain.shadowRoot.querySelector('main-page-container'); assertEquals( expectedBasic, - getComputedStyle(page.shadowRoot.querySelector('#basicPage')).display); + getComputedStyle( + mainPageContainer.shadowRoot.querySelector('#basicPage')) + .display); - const advancedPage = - await page.shadowRoot.querySelector('#advancedPageTemplate').get(); + const advancedPage = await mainPageContainer.shadowRoot + .querySelector('#advancedPageTemplate') + .get(); assertEquals(expectedAdvanced, getComputedStyle(advancedPage).display); }
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_menu_test.js b/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_menu_test.js index 45271ae..6037844 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_menu_test.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_menu_test.js
@@ -99,10 +99,11 @@ const main = ui.shadowRoot.querySelector('os-settings-main'); assertTrue(!!main); - const mainPage = main.shadowRoot.querySelector('os-settings-page'); - assertTrue(!!mainPage); + const mainPageContainer = + main.shadowRoot.querySelector('main-page-container'); + assertTrue(!!mainPageContainer); const mainPageAdvancedToggle = - mainPage.shadowRoot.querySelector('#advancedToggle'); + mainPageContainer.shadowRoot.querySelector('#advancedToggle'); assertTrue(!!mainPageAdvancedToggle); const floatingMenu = ui.shadowRoot.querySelector('#left os-settings-menu'); assertTrue(!!floatingMenu);
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_page_availability_test.ts b/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_page_availability_test.ts index b0a9e03..14f18fc 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_page_availability_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_page_availability_test.ts
@@ -8,7 +8,7 @@ * Separated into a separate file to mitigate test timeouts. */ -import {CrSettingsPrefs, OsSettingsMainElement, OsSettingsPageElement, OsSettingsSectionElement, OsSettingsUiElement} from 'chrome://os-settings/os_settings.js'; +import {CrSettingsPrefs, MainPageContainerElement, OsSettingsMainElement, OsSettingsSectionElement, OsSettingsUiElement} from 'chrome://os-settings/os_settings.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -17,7 +17,7 @@ suite('<os-settings-ui> page availability', () => { let ui: OsSettingsUiElement; let settingsMain: OsSettingsMainElement; - let settingsPage: OsSettingsPageElement; + let mainPageContainer: MainPageContainerElement; async function createUi() { ui = document.createElement('os-settings-ui'); @@ -30,12 +30,12 @@ settingsMain = mainElement; const pageElement = - settingsMain.shadowRoot!.querySelector('os-settings-page'); + settingsMain.shadowRoot!.querySelector('main-page-container'); assert(pageElement); - settingsPage = pageElement; + mainPageContainer = pageElement; const idleRender = - settingsPage.shadowRoot!.querySelector('settings-idle-load'); + mainPageContainer.shadowRoot!.querySelector('settings-idle-load'); assert(idleRender); await idleRender.get(); flush(); @@ -118,9 +118,9 @@ ]; for (const name of availablePages) { test(`${name} page should be stamped and subpages hidden`, () => { - const section = - settingsPage.shadowRoot!.querySelector<OsSettingsSectionElement>( - `os-settings-section[section=${name}]`); + const section = mainPageContainer.shadowRoot! + .querySelector<OsSettingsSectionElement>( + `os-settings-section[section=${name}]`); assertTrue(!!section, `Expected to find ${name} page stamped`); verifySubpagesHidden(section); }); @@ -149,9 +149,9 @@ ]; for (const name of unavailablePages) { test(`${name} page should not be stamped`, () => { - const section = - settingsPage.shadowRoot!.querySelector<OsSettingsSectionElement>( - `os-settings-section[section=${name}]`); + const section = mainPageContainer.shadowRoot! + .querySelector<OsSettingsSectionElement>( + `os-settings-section[section=${name}]`); assertEquals(null, section, `Found unexpected page ${name}`); }); } @@ -171,9 +171,9 @@ ]; for (const name of availablePages) { test(`${name} page should be stamped and subpages hidden`, () => { - const section = - settingsPage.shadowRoot!.querySelector<OsSettingsSectionElement>( - `os-settings-section[section=${name}]`); + const section = mainPageContainer.shadowRoot! + .querySelector<OsSettingsSectionElement>( + `os-settings-section[section=${name}]`); assertTrue(!!section, `Expected to find ${name} page stamped`); verifySubpagesHidden(section); });
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_test.ts b/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_test.ts index 4a20dc8..cc63678 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_test.ts +++ b/chrome/test/data/webui/settings/chromeos/os_settings_ui/os_settings_ui_test.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {CrSettingsPrefs, OsSettingsMainElement, OsSettingsPageElement, OsSettingsUiElement} from 'chrome://os-settings/os_settings.js'; +import {CrSettingsPrefs, MainPageContainerElement, OsSettingsMainElement, OsSettingsUiElement} from 'chrome://os-settings/os_settings.js'; import {CrDrawerElement} from 'chrome://resources/cr_elements/cr_drawer/cr_drawer.js'; import {assert} from 'chrome://resources/js/assert_ts.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -14,7 +14,7 @@ suite('OSSettingsUi', function() { let ui: OsSettingsUiElement; let settingsMain: OsSettingsMainElement|null; - let settingsPage: OsSettingsPageElement|null; + let mainPageContainer: MainPageContainerElement|null; suiteSetup(async function() { document.body.innerHTML = ''; @@ -26,11 +26,12 @@ settingsMain = ui.shadowRoot!.querySelector('os-settings-main'); assert(settingsMain); - settingsPage = settingsMain.shadowRoot!.querySelector('os-settings-page'); - assert(settingsPage); + mainPageContainer = + settingsMain.shadowRoot!.querySelector('main-page-container'); + assert(mainPageContainer); const idleRender = - settingsPage.shadowRoot!.querySelector('settings-idle-load'); + mainPageContainer.shadowRoot!.querySelector('settings-idle-load'); assert(idleRender); await idleRender.get(); flush(); @@ -38,27 +39,29 @@ test('Update required end of life banner visibility', function() { flush(); - assert(settingsPage); + assert(mainPageContainer); assertEquals( null, - settingsPage.shadowRoot!.querySelector('#updateRequiredEolBanner')); + mainPageContainer.shadowRoot!.querySelector( + '#updateRequiredEolBanner')); - settingsPage!.set('showUpdateRequiredEolBanner_', true); + mainPageContainer!.set('showUpdateRequiredEolBanner_', true); flush(); - assertTrue( - !!settingsPage.shadowRoot!.querySelector('#updateRequiredEolBanner')); + assertTrue(!!mainPageContainer.shadowRoot!.querySelector( + '#updateRequiredEolBanner')); }); test('Update required end of life banner close button click', function() { - assert(settingsPage); - settingsPage.set('showUpdateRequiredEolBanner_', true); + assert(mainPageContainer); + mainPageContainer.set('showUpdateRequiredEolBanner_', true); flush(); - const banner = settingsPage.shadowRoot!.querySelector<HTMLElement>( + const banner = mainPageContainer.shadowRoot!.querySelector<HTMLElement>( '#updateRequiredEolBanner'); assertTrue(!!banner); - const closeButton = settingsPage.shadowRoot!.querySelector<HTMLElement>( - '#closeUpdateRequiredEol'); + const closeButton = + mainPageContainer.shadowRoot!.querySelector<HTMLElement>( + '#closeUpdateRequiredEol'); assert(closeButton); closeButton.click(); flush();
diff --git a/chrome/test/data/webui/settings/chromeos/test_api.ts b/chrome/test/data/webui/settings/chromeos/test_api.ts index 0f4cd44..f85eb45 100644 --- a/chrome/test/data/webui/settings/chromeos/test_api.ts +++ b/chrome/test/data/webui/settings/chromeos/test_api.ts
@@ -835,7 +835,7 @@ const privacyPage = querySelectorShadow(document.body, [ 'os-settings-ui', 'os-settings-main', - 'os-settings-page', + 'main-page-container', 'os-settings-privacy-page', ]); assertTrue(privacyPage instanceof HTMLElement); @@ -895,7 +895,7 @@ const googleDriveSubpage = querySelectorShadow(document.body, [ 'os-settings-ui', 'os-settings-main', - 'os-settings-page', + 'main-page-container', 'os-settings-files-page', 'settings-google-drive-subpage', ]);
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index 615491b6a..7d3bd046 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -557,6 +557,35 @@ runMochaSuite('TabDiscardExceptionList'); }); +var CrSettingsPerformancePageDiscardExceptionImprovementsTest = + class extends CrSettingsBrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://settings/test_loader.html?module=settings/performance_page_test.js'; + } + + /** @override */ + get featureListInternal() { + return { + enabled: [ + 'performance_manager::features::kDiscardExceptionsImprovements', + ], + }; + } +}; + +TEST_F( + 'CrSettingsPerformancePageDiscardExceptionImprovementsTest', 'Controls', + function() { + runMochaSuite('PerformancePage'); + }); + +TEST_F( + 'CrSettingsPerformancePageDiscardExceptionImprovementsTest', + 'ExceptionList', function() { + runMochaSuite('TabDiscardExceptionList'); + }); + var CrSettingsBatteryPageTest = class extends CrSettingsBrowserTest { /** @override */ get browsePreload() {
diff --git a/chrome/test/data/webui/settings/performance_page_test.ts b/chrome/test/data/webui/settings/performance_page_test.ts index ce95ad8..5e60d60 100644 --- a/chrome/test/data/webui/settings/performance_page_test.ts +++ b/chrome/test/data/webui/settings/performance_page_test.ts
@@ -2,11 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'chrome://settings/lazy_load.js'; import 'chrome://settings/settings.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {CrIconButtonElement, IronCollapseElement, SettingsRadioGroupElement} from 'chrome://settings/lazy_load.js'; -import {HIGH_EFFICIENCY_MODE_PREF, HighEfficiencyModeExceptionListAction, HighEfficiencyModeState, PerformanceBrowserProxyImpl, PerformanceMetricsProxyImpl, SettingsDropdownMenuElement, SettingsPerformancePageElement, TAB_DISCARD_EXCEPTIONS_MANAGED_PREF, TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE, TAB_DISCARD_EXCEPTIONS_PREF, TabDiscardExceptionAddDialogElement, TabDiscardExceptionEditDialogElement, TabDiscardExceptionEntryElement, TabDiscardExceptionListElement} from 'chrome://settings/settings.js'; +import {CrCheckboxElement, CrIconButtonElement, IronCollapseElement, SettingsRadioGroupElement} from 'chrome://settings/lazy_load.js'; +import {HIGH_EFFICIENCY_MODE_PREF, HighEfficiencyModeExceptionListAction, HighEfficiencyModeState, PerformanceBrowserProxyImpl, PerformanceMetricsProxyImpl, SettingsDropdownMenuElement, SettingsPerformancePageElement, TAB_DISCARD_EXCEPTIONS_MANAGED_PREF, TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE, TAB_DISCARD_EXCEPTIONS_PREF, TabDiscardExceptionAddDialogElement, TabDiscardExceptionEditDialogElement, TabDiscardExceptionEntryElement, TabDiscardExceptionListElement, TabDiscardExceptionTabbedAddDialogElement} from 'chrome://settings/settings.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; @@ -371,18 +373,60 @@ assertExceptionListEquals([]); }); - function getAddDialog(): TabDiscardExceptionAddDialogElement|null { - return tabDiscardExceptionsList.shadowRoot!.querySelector( + async function getAddDialog(): + Promise<TabDiscardExceptionAddDialogElement| + TabDiscardExceptionTabbedAddDialogElement> { + if (loadTimeData.getBoolean('isDiscardExceptionsImprovementsEnabled')) { + return await getTabbedAddDialog(); + } + const dialog = tabDiscardExceptionsList.shadowRoot!.querySelector( 'tab-discard-exception-add-dialog'); + assertTrue(!!dialog); + return dialog; } - function getEditDialog(): TabDiscardExceptionEditDialogElement|null { - return tabDiscardExceptionsList.shadowRoot!.querySelector( + async function getTabbedAddDialog(): + Promise<TabDiscardExceptionTabbedAddDialogElement> { + await performanceBrowserProxy.whenCalled('getCurrentOpenSites'); + const dialog = tabDiscardExceptionsList.shadowRoot!.querySelector( + 'tab-discard-exception-tabbed-add-dialog'); + assertTrue(!!dialog); + return dialog; + } + + function getEditDialog(): TabDiscardExceptionEditDialogElement { + const dialog = tabDiscardExceptionsList.shadowRoot!.querySelector( 'tab-discard-exception-edit-dialog'); + assertTrue(!!dialog); + return dialog; + } + + function assertAddDialogDoesNotExist() { + if (loadTimeData.getBoolean('isDiscardExceptionsImprovementsEnabled')) { + assertTabbedAddDialogDoesNotExist(); + } + const dialog = tabDiscardExceptionsList.shadowRoot!.querySelector( + 'tab-discard-exception-add-dialog'); + assertFalse(!!dialog); + } + + function assertTabbedAddDialogDoesNotExist() { + assertEquals( + 0, performanceBrowserProxy.getCallCount('getCurrentOpenSites')); + const dialog = tabDiscardExceptionsList.shadowRoot!.querySelector( + 'tab-discard-exception-tabbed-add-dialog'); + assertFalse(!!dialog); + } + + function assertEditDialogDoesNotExist() { + const dialog = tabDiscardExceptionsList.shadowRoot!.querySelector( + 'tab-discard-exception-edit-dialog'); + assertFalse(!!dialog); } async function inputDialog( dialog: TabDiscardExceptionAddDialogElement| + TabDiscardExceptionTabbedAddDialogElement| TabDiscardExceptionEditDialogElement, input: string) { const inputEvent = eventToPromise('input', dialog.$.input.$.input); @@ -390,55 +434,57 @@ dialog.$.input.$.input.dispatchEvent(new CustomEvent('input')); await inputEvent; dialog.$.actionButton.click(); - await performanceBrowserProxy.whenCalled('validateTabDiscardExceptionRule'); } test('testTabDiscardExceptionsListAdd', async function() { setupExceptionListEntries(['foo']); - let addDialog = getAddDialog(); - assertFalse(!!addDialog); + assertAddDialogDoesNotExist(); tabDiscardExceptionsList.$.addButton.click(); flush(); - addDialog = getAddDialog(); - assertTrue(!!addDialog); + const addDialog = await getAddDialog(); assertTrue(addDialog.$.dialog.open); assertEquals('', addDialog.$.input.$.input.value); + const addExceptionEvent = eventToPromise('add-exception', addDialog); await inputDialog(addDialog, 'bar'); + await addExceptionEvent; + assertEquals( + HighEfficiencyModeExceptionListAction.ADD, + await performanceMetricsProxy.whenCalled('recordExceptionListAction')); assertExceptionListEquals(['foo', 'bar']); }); test('testTabDiscardExceptionsListEdit', async function() { setupExceptionListEntries(['foo', 'bar']); const entry = getExceptionListEntry(1); - let editDialog = getEditDialog(); - assertFalse(!!editDialog); + assertEditDialogDoesNotExist(); clickMoreActionsButton(entry); clickEditMenuItem(); flush(); - editDialog = getEditDialog(); - assertTrue(!!editDialog); + const editDialog = getEditDialog(); assertTrue(editDialog.$.dialog.open); assertEquals(entry.entry.site, editDialog.$.input.$.input.value); await inputDialog(editDialog, 'baz'); + assertEquals( + HighEfficiencyModeExceptionListAction.EDIT, + await performanceMetricsProxy.whenCalled('recordExceptionListAction')); assertExceptionListEquals(['foo', 'baz']); }); - test('testTabDiscardExceptionsListAddAfterMenuClick', function() { + test('testTabDiscardExceptionsListAddAfterMenuClick', async function() { setupExceptionListEntries(['foo']); clickMoreActionsButton(getExceptionListEntry(0)); tabDiscardExceptionsList.$.addButton.click(); flush(); - const dialog = getAddDialog(); - assertTrue(!!dialog); - assertEquals('', dialog.$.input.$.input.value); + const addDialog = await getAddDialog(); + assertEquals('', addDialog.$.input.$.input.value); }); - test('testTabDiscardExceptionsListOverflow', async function() { + test('testTabDiscardExceptionsListAddExceptionOverflow', async function() { assertTrue(tabDiscardExceptionsList.$.expandButton.hidden); const entries = [ @@ -458,13 +504,39 @@ flush(); const newRule = `rule${TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE + 1}`; - const addDialog = getAddDialog(); - assertTrue(!!addDialog); + const addDialog = await getAddDialog(); await inputDialog(addDialog, newRule); assertTrue(tabDiscardExceptionsList.$.collapse.opened); assertExceptionListEquals([...entries, newRule]); }); + test('testTabDiscardExceptionsListAddExceptionsOverflow', async function() { + if (!loadTimeData.getBoolean('isDiscardExceptionsImprovementsEnabled')) { + return; + } + performanceBrowserProxy.setCurrentOpenSites([ + ...Array(3).keys(), + ].map(index => `rule${index}`)); + tabDiscardExceptionsList.$.addButton.click(); + flush(); + + const addDialog = await getTabbedAddDialog(); + flush(); + + addDialog.$.list.$.list + .querySelectorAll<CrCheckboxElement>('cr-checkbox:not([hidden])') + .forEach(checkboxElement => { + checkboxElement.click(); + }); + const addExceptionEvent = eventToPromise('add-exception', addDialog); + assertFalse(addDialog.$.actionButton.disabled); + addDialog.$.actionButton.click(); + await addExceptionEvent; + flush(); + + assertTrue(tabDiscardExceptionsList.$.collapse.opened); + }); + test('testTabDiscardExceptionsListOverflowEdit', async function() { const entries = [ ...Array(TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE + 1).keys(), @@ -476,7 +548,6 @@ clickEditMenuItem(); flush(); const editDialog = getEditDialog(); - assertTrue(!!editDialog); assertEquals(entry.entry.site, editDialog.$.input.$.input.value); await inputDialog(editDialog, 'foo'); assertExceptionListEquals([...entries.slice(0, -1), 'foo']); @@ -484,7 +555,6 @@ clickMoreActionsButton(entry); clickEditMenuItem(); flush(); - assertTrue(!!editDialog); await inputDialog(editDialog, getExceptionListEntry(0).entry.site); assertExceptionListEquals(entries.slice(0, -1)); });
diff --git a/chrome/test/data/webui/settings/tab_discard_exception_dialog_test.ts b/chrome/test/data/webui/settings/tab_discard_exception_dialog_test.ts index a506b42e..f63c8fa7 100644 --- a/chrome/test/data/webui/settings/tab_discard_exception_dialog_test.ts +++ b/chrome/test/data/webui/settings/tab_discard_exception_dialog_test.ts
@@ -2,18 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'chrome://settings/lazy_load.js'; import 'chrome://settings/settings.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {HighEfficiencyModeExceptionListAction, MAX_TAB_DISCARD_EXCEPTION_RULE_LENGTH, PerformanceBrowserProxyImpl, PerformanceMetricsProxyImpl, TAB_DISCARD_EXCEPTIONS_PREF, TabDiscardExceptionAddDialogElement, TabDiscardExceptionEditDialogElement} from 'chrome://settings/settings.js'; +import {CrCheckboxElement} from 'chrome://settings/lazy_load.js'; +import {HighEfficiencyModeExceptionListAction, MAX_TAB_DISCARD_EXCEPTION_RULE_LENGTH, PerformanceBrowserProxyImpl, PerformanceMetricsProxyImpl, TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE, TAB_DISCARD_EXCEPTIONS_PREF, TabDiscardExceptionAddDialogElement, TabDiscardExceptionAddDialogTabs, TabDiscardExceptionEditDialogElement, TabDiscardExceptionTabbedAddDialogElement} from 'chrome://settings/settings.js'; import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; +import {eventToPromise} from 'chrome://webui-test/test_util.js'; import {TestPerformanceBrowserProxy} from './test_performance_browser_proxy.js'; import {TestPerformanceMetricsProxy} from './test_performance_metrics_proxy.js'; suite('TabDiscardExceptionsDialog', function() { let dialog: TabDiscardExceptionAddDialogElement| + TabDiscardExceptionTabbedAddDialogElement| TabDiscardExceptionEditDialogElement; let performanceBrowserProxy: TestPerformanceBrowserProxy; let performanceMetricsProxy: TestPerformanceMetricsProxy; @@ -24,7 +27,11 @@ setup(function() { performanceBrowserProxy = new TestPerformanceBrowserProxy(); - performanceBrowserProxy.setValidationResult(true); + performanceBrowserProxy.setValidationResults({ + [EXISTING_RULE]: true, + [INVALID_RULE]: false, + [VALID_RULE]: true, + }); PerformanceBrowserProxyImpl.setInstance(performanceBrowserProxy); performanceMetricsProxy = new TestPerformanceMetricsProxy(); @@ -33,7 +40,9 @@ document.body.innerHTML = window.trustedTypes!.emptyHTML; }); - function setupDialog() { + function setupDialog(dialog: TabDiscardExceptionAddDialogElement| + TabDiscardExceptionTabbedAddDialogElement| + TabDiscardExceptionEditDialogElement) { dialog.set('prefs', { performance_tuning: { tab_discarding: { @@ -48,15 +57,28 @@ flush(); } - function setupAddDialog() { - dialog = document.createElement('tab-discard-exception-add-dialog'); - setupDialog(); + function setupAddDialog(): TabDiscardExceptionAddDialogElement { + const addDialog: TabDiscardExceptionAddDialogElement = + document.createElement('tab-discard-exception-add-dialog'); + setupDialog(addDialog); + return addDialog; } - function setupEditDialog() { - dialog = document.createElement('tab-discard-exception-edit-dialog'); - setupDialog(); - dialog.setRuleToEditForTesting(EXISTING_RULE); + async function setupTabbedAddDialog(): + Promise<TabDiscardExceptionTabbedAddDialogElement> { + const addDialog: TabDiscardExceptionTabbedAddDialogElement = + document.createElement('tab-discard-exception-tabbed-add-dialog'); + setupDialog(addDialog); + await performanceBrowserProxy.whenCalled('getCurrentOpenSites'); + return addDialog; + } + + function setupEditDialog(): TabDiscardExceptionEditDialogElement { + const editDialog: TabDiscardExceptionEditDialogElement = + document.createElement('tab-discard-exception-edit-dialog'); + setupDialog(editDialog); + editDialog.setRuleToEditForTesting(EXISTING_RULE); + return editDialog; } async function assertUserInputValidated(rule: string) { @@ -75,117 +97,126 @@ async function testValidation() { await assertUserInputValidated(' '); - assertFalse( - dialog.$.input.$.input.invalid, - 'error mesasge should be hidden on empty input'); - assertTrue( - dialog.$.actionButton.disabled, - 'submit button should be disabled on empty input'); + assertFalse(dialog.$.input.$.input.invalid); + assertTrue(dialog.$.actionButton.disabled); await assertUserInputValidated( 'a'.repeat(MAX_TAB_DISCARD_EXCEPTION_RULE_LENGTH + 1)); - assertTrue( - dialog.$.input.$.input.invalid, - 'error mesasge should be shown on long input'); - assertTrue( - dialog.$.actionButton.disabled, - 'submit button should be disabled on long input'); + assertTrue(dialog.$.input.$.input.invalid); + assertTrue(dialog.$.actionButton.disabled); await assertUserInputValidated(VALID_RULE); - assertFalse( - dialog.$.input.$.input.invalid, - 'error mesasge should be hidden on valid input'); - assertFalse( - dialog.$.actionButton.disabled, - 'submit button should be enabled on valid input'); + assertFalse(dialog.$.input.$.input.invalid); + assertFalse(dialog.$.actionButton.disabled); - performanceBrowserProxy.setValidationResult(false); await assertUserInputValidated(INVALID_RULE); - assertTrue( - dialog.$.input.$.input.invalid, - 'error mesasge should be shown on invalid input'); - assertTrue( - dialog.$.actionButton.disabled, - 'submit button should be disabled on invalid input'); + assertTrue(dialog.$.input.$.input.invalid); + assertTrue(dialog.$.actionButton.disabled); } test('testTabDiscardExceptionsAddDialogState', async function() { - setupAddDialog(); - assertTrue(dialog.$.dialog.open, 'dialog should be open initially'); - assertFalse( - dialog.$.input.$.input.invalid, - 'error mesasge should be hidden initially'); - assertTrue( - dialog.$.actionButton.disabled, - 'submit button should be disabled initially'); + dialog = setupAddDialog(); + assertTrue(dialog.$.dialog.open); + assertFalse(dialog.$.input.$.input.invalid); + assertTrue(dialog.$.actionButton.disabled); + + await testValidation(); + }); + + test('testTabDiscardExceptionsTabbedAddDialogState', async function() { + dialog = await setupTabbedAddDialog(); + assertTrue(dialog.$.dialog.open); + assertEquals( + TabDiscardExceptionAddDialogTabs.MANUAL, dialog.$.tabs.selected); + assertFalse(dialog.$.input.$.input.invalid); + assertTrue(dialog.$.actionButton.disabled); await testValidation(); }); test('testTabDiscardExceptionsListEditDialogState', async function() { - setupEditDialog(); - assertTrue(dialog.$.dialog.open, 'dialog should be open initially'); - assertFalse( - dialog.$.input.$.input.invalid, - 'error mesasge should be hidden initially'); - assertFalse( - dialog.$.actionButton.disabled, - 'submit button should be enabled initially'); + dialog = setupEditDialog(); + assertTrue(dialog.$.dialog.open); + assertFalse(dialog.$.input.$.input.invalid); + assertFalse(dialog.$.actionButton.disabled); await testValidation(); }); - async function assertCancel() { + function assertCancel() { dialog.$.cancelButton.click(); - await flushTasks(); - assertFalse( - dialog.$.dialog.open, 'dialog should be closed after cancelling'); + assertFalse(dialog.$.dialog.open); assertDeepEquals( dialog.getPref(TAB_DISCARD_EXCEPTIONS_PREF).value, [EXISTING_RULE]); } test('testTabDiscardExceptionsAddDialogCancel', async function() { - setupAddDialog(); + dialog = setupAddDialog(); await assertUserInputValidated(VALID_RULE); - await assertCancel(); + assertCancel(); + }); + + test('testTabDiscardExceptionsTabbedAddDialogCancel', async function() { + dialog = await setupTabbedAddDialog(); + await assertUserInputValidated(VALID_RULE); + assertCancel(); }); test('testTabDiscardExceptionsEditDialogCancel', async function() { - setupEditDialog(); + dialog = setupEditDialog(); await assertUserInputValidated(VALID_RULE); - await assertCancel(); + assertCancel(); }); - async function assertSubmit(expectedRules: string[]) { + function assertSubmit(expectedRules: string[]) { dialog.$.actionButton.click(); - await flushTasks(); - assertFalse( - dialog.$.dialog.open, 'dialog should be closed after submitting input'); + assertFalse(dialog.$.dialog.open); assertDeepEquals( dialog.getPref(TAB_DISCARD_EXCEPTIONS_PREF).value, expectedRules); } test('testTabDiscardExceptionsAddDialogSubmit', async function() { - setupAddDialog(); + dialog = setupAddDialog(); await assertUserInputValidated(VALID_RULE); - await assertSubmit([EXISTING_RULE, VALID_RULE]); + const addExceptionEvent = eventToPromise('add-exception', dialog); + assertSubmit([EXISTING_RULE, VALID_RULE]); + await addExceptionEvent; const action = await performanceMetricsProxy.whenCalled('recordExceptionListAction'); assertEquals(HighEfficiencyModeExceptionListAction.ADD, action); }); test('testTabDiscardExceptionsAddDialogSubmitExisting', async function() { - setupAddDialog(); + dialog = setupAddDialog(); await assertUserInputValidated(EXISTING_RULE); - await assertSubmit([EXISTING_RULE]); + assertSubmit([EXISTING_RULE]); }); - test('testTabDiscardExceptionsEditDialogSubmit', async function() { - setupEditDialog(); + test('testTabDiscardExceptionsTabbedAddDialogSubmit', async function() { + dialog = await setupTabbedAddDialog(); await assertUserInputValidated(VALID_RULE); - await assertSubmit([VALID_RULE]); + const addExceptionEvent = eventToPromise('add-exception', dialog); + assertSubmit([EXISTING_RULE, VALID_RULE]); + await addExceptionEvent; + const action = + await performanceMetricsProxy.whenCalled('recordExceptionListAction'); + assertEquals(HighEfficiencyModeExceptionListAction.ADD, action); + }); + + test( + 'testTabDiscardExceptionsTabbedAddDialogSubmitExisting', + async function() { + dialog = await setupTabbedAddDialog(); + await assertUserInputValidated(EXISTING_RULE); + assertSubmit([EXISTING_RULE]); + }); + + test('testTabDiscardExceptionsEditDialogSubmit', async function() { + dialog = setupEditDialog(); + await assertUserInputValidated(VALID_RULE); + assertSubmit([VALID_RULE]); const action = await performanceMetricsProxy.whenCalled('recordExceptionListAction'); assertEquals(HighEfficiencyModeExceptionListAction.EDIT, action); @@ -194,8 +225,85 @@ test('testTabDiscardExceptionsEditDialogSubmitExisting', async function() { dialog.setPrefValue( TAB_DISCARD_EXCEPTIONS_PREF, [EXISTING_RULE, VALID_RULE]); - setupEditDialog(); + dialog = setupEditDialog(); await assertUserInputValidated(VALID_RULE); - await assertSubmit([VALID_RULE]); + assertSubmit([VALID_RULE]); + }); + + async function assertRulesListEquals( + dialog: TabDiscardExceptionTabbedAddDialogElement, rules: string[]) { + const actual = dialog.$.list.$.list.items!; + assertDeepEquals(rules, actual); + } + + function getRulesListEntry( + dialog: TabDiscardExceptionTabbedAddDialogElement, + idx: number): CrCheckboxElement { + const entry = [...dialog.$.list.$.list.querySelectorAll<CrCheckboxElement>( + 'cr-checkbox:not([hidden])')][idx]; + assertTrue(!!entry); + return entry; + } + + test('testTabDiscardExceptionsTabbedAddDialogListEmpty', async function() { + performanceBrowserProxy.setCurrentOpenSites([EXISTING_RULE]); + dialog = await setupTabbedAddDialog(); + + assertEquals( + TabDiscardExceptionAddDialogTabs.MANUAL, dialog.$.tabs.selected); + }); + + test('testTabDiscardExceptionsTabbedAddDialogList', async function() { + const expectedRules = + [...Array(TAB_DISCARD_EXCEPTIONS_OVERFLOW_SIZE).keys()].map( + index => `rule${index}`); + performanceBrowserProxy.setCurrentOpenSites( + [EXISTING_RULE, ...expectedRules]); + dialog = await setupTabbedAddDialog(); + await eventToPromise('iron-resize', dialog); + flush(); + + assertEquals(TabDiscardExceptionAddDialogTabs.LIST, dialog.$.tabs.selected); + await assertRulesListEquals(dialog, expectedRules); + assertTrue(dialog.$.actionButton.disabled); + getRulesListEntry(dialog, 2).click(); + assertFalse(dialog.$.actionButton.disabled); + getRulesListEntry(dialog, 4).click(); + const addExceptionEvent = eventToPromise('add-exception', dialog); + assertSubmit([EXISTING_RULE, 'rule2', 'rule4']); + await addExceptionEvent; + }); + + function switchAddDialogTab( + dialog: TabDiscardExceptionTabbedAddDialogElement, + tabId: TabDiscardExceptionAddDialogTabs) { + const tabs = + dialog.$.tabs.shadowRoot!.querySelectorAll<HTMLElement>('.tab'); + const tab = tabs[tabId]; + assertTrue(!!tab); + tab.click(); + } + + test('testTabDiscardExceptionsTabbedAddDialogSwitchTabs', async function() { + performanceBrowserProxy.setCurrentOpenSites([VALID_RULE]); + dialog = await setupTabbedAddDialog(); + flush(); + + getRulesListEntry(dialog, 0).click(); + assertFalse(dialog.$.actionButton.disabled); + switchAddDialogTab(dialog, TabDiscardExceptionAddDialogTabs.MANUAL); + assertTrue(dialog.$.actionButton.disabled); + switchAddDialogTab(dialog, TabDiscardExceptionAddDialogTabs.LIST); + assertFalse(dialog.$.actionButton.disabled); + + getRulesListEntry(dialog, 0).click(); + switchAddDialogTab(dialog, TabDiscardExceptionAddDialogTabs.MANUAL); + await assertUserInputValidated(VALID_RULE); + assertFalse(dialog.$.actionButton.disabled); + switchAddDialogTab(dialog, TabDiscardExceptionAddDialogTabs.LIST); + assertTrue(dialog.$.actionButton.disabled); + switchAddDialogTab(dialog, TabDiscardExceptionAddDialogTabs.MANUAL); + await performanceBrowserProxy.whenCalled('validateTabDiscardExceptionRule'); + assertFalse(dialog.$.actionButton.disabled); }); });
diff --git a/chrome/test/data/webui/settings/test_performance_browser_proxy.ts b/chrome/test/data/webui/settings/test_performance_browser_proxy.ts index af531895..61a0b36e 100644 --- a/chrome/test/data/webui/settings/test_performance_browser_proxy.ts +++ b/chrome/test/data/webui/settings/test_performance_browser_proxy.ts
@@ -7,10 +7,12 @@ export class TestPerformanceBrowserProxy extends TestBrowserProxy implements PerformanceBrowserProxy { - private validationResult_: boolean = true; + private currentSites_: string[] = []; + private validationResults_: Record<string, boolean> = {}; constructor() { super([ + 'getCurrentOpenSites', 'getDeviceHasBattery', 'openBatterySaverFeedbackDialog', 'openHighEfficiencyFeedbackDialog', @@ -18,6 +20,15 @@ ]); } + setCurrentOpenSites(currentSites: string[]) { + this.currentSites_ = currentSites; + } + + getCurrentOpenSites() { + this.methodCalled('getCurrentOpenSites'); + return Promise.resolve(this.currentSites_); + } + getDeviceHasBattery() { this.methodCalled('getDeviceHasBattery'); return Promise.resolve(false); @@ -31,12 +42,12 @@ this.methodCalled('openHighEfficiencyFeedbackDialog'); } - setValidationResult(result: boolean) { - this.validationResult_ = result; + setValidationResults(results: Record<string, boolean>) { + this.validationResults_ = results; } validateTabDiscardExceptionRule(rule: string) { this.methodCalled('validateTabDiscardExceptionRule', rule); - return Promise.resolve(this.validationResult_); + return Promise.resolve(this.validationResults_[rule] ?? true); } } \ No newline at end of file
diff --git a/chrome/test/data/webui/side_panel/BUILD.gn b/chrome/test/data/webui/side_panel/BUILD.gn index 18517fa..5ba5728 100644 --- a/chrome/test/data/webui/side_panel/BUILD.gn +++ b/chrome/test/data/webui/side_panel/BUILD.gn
@@ -34,6 +34,10 @@ rebase_path( "$root_gen_dir/chrome/browser/resources/side_panel/bookmarks/tsc/*", target_gen_dir), + "chrome://bookmarks-side-panel.top-chrome/shared/*|" + + rebase_path( + "$root_gen_dir/chrome/browser/resources/side_panel/shared/tsc/*", + target_gen_dir), "chrome://read-later.top-chrome/*|" + rebase_path( "$root_gen_dir/chrome/browser/resources/side_panel/reading_list/tsc/*", target_gen_dir),
diff --git a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts index 150dfe4..11fb6e2 100644 --- a/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts +++ b/chrome/test/data/webui/side_panel/bookmarks/power_bookmarks_list_test.ts
@@ -10,12 +10,13 @@ import {ShoppingListApiProxyImpl} from 'chrome://bookmarks-side-panel.top-chrome/commerce/shopping_list_api_proxy.js'; import {PowerBookmarkRowElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmark_row.js'; import {PowerBookmarksListElement} from 'chrome://bookmarks-side-panel.top-chrome/power_bookmarks_list.js'; +import {SpEmptyStateElement} from 'chrome://bookmarks-side-panel.top-chrome/shared/sp_empty_state.js'; import {PageImageServiceBrowserProxy} from 'chrome://resources/cr_components/page_image_service/browser_proxy.js'; import {PageImageServiceHandlerRemote} from 'chrome://resources/cr_components/page_image_service/page_image_service.mojom-webui.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js'; import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {flushTasks} from 'chrome://webui-test/polymer_test_util.js'; import {TestMock} from 'chrome://webui-test/test_mock.js'; import {TestPluralStringProxy} from 'chrome://webui-test/test_plural_string_proxy.js'; @@ -75,7 +76,7 @@ }, ]; - function getBookmarkElements(root: HTMLElement): HTMLElement[] { + function getBookmarkElements(root: HTMLElement): PowerBookmarkRowElement[] { return Array.from(root.shadowRoot!.querySelectorAll('power-bookmark-row')); } @@ -104,6 +105,10 @@ viewType: ViewType.kCompact, emptyTitle: 'empty title base', emptyTitleSearch: 'empty title search', + emptyTitleFolder: 'folder is empty', + emptyBodyFolder: 'folder body', + emptyTitleGuest: 'guest title', + emptyBodyGuest: 'guest body', }); powerBookmarksList = document.createElement('power-bookmarks-list'); @@ -325,13 +330,28 @@ }); test('ShowsCorrectEmptyState', () => { - const emptyStateElement = - powerBookmarksList.shadowRoot!.querySelector('sp-empty-state'); - assertTrue(!!emptyStateElement); + function emptyStateIsHidden(emptyState: SpEmptyStateElement): boolean { + return emptyState.matches('[hidden], [hidden] *'); + } + const folderEmptyState = powerBookmarksList.$.folderEmptyState; + const topLevelEmptyState = powerBookmarksList.$.topLevelEmptyState; assertEquals( - loadTimeData.getString('emptyTitle'), emptyStateElement.heading); + loadTimeData.getString('emptyTitle'), topLevelEmptyState.heading); + assertEquals(loadTimeData.getString('emptyBody'), topLevelEmptyState.body); + // Has bookmarks so both empty states should be hidden. + assertTrue(emptyStateIsHidden(folderEmptyState)); + assertTrue(emptyStateIsHidden(topLevelEmptyState)); + + // Opening an empty folder should show the folder empty state. + getBookmarkElements(powerBookmarksList)[0]!.$.crUrlListItem.click(); + flush(); + assertFalse(emptyStateIsHidden(folderEmptyState)); + assertTrue(emptyStateIsHidden(topLevelEmptyState)); + + // A search with no results should show the top level empty state with + // text specific to search. const searchField = powerBookmarksList.shadowRoot!.querySelector('cr-toolbar-search-field'); assertTrue(!!searchField); @@ -339,6 +359,8 @@ searchField.onSearchTermSearch(); flush(); assertEquals( - loadTimeData.getString('emptyTitleSearch'), emptyStateElement.heading); + loadTimeData.getString('emptyTitleSearch'), topLevelEmptyState.heading); + assertTrue(emptyStateIsHidden(folderEmptyState)); + assertFalse(emptyStateIsHidden(topLevelEmptyState)); }); });
diff --git a/chrome/test/fuzzing/BUILD.gn b/chrome/test/fuzzing/BUILD.gn index dcf0768..8e1e7ec 100644 --- a/chrome/test/fuzzing/BUILD.gn +++ b/chrome/test/fuzzing/BUILD.gn
@@ -35,7 +35,9 @@ in_process_fuzzer("html_in_process_fuzzer") { sources = [ "html_in_process_fuzzer.cc" ] } - in_process_fuzzer("kombucha_in_process_fuzzer") { + in_process_proto_fuzzer("kombucha_in_process_fuzzer") { sources = [ "kombucha_in_process_fuzzer.cc" ] + + proto_source = "kombucha_in_process_fuzzer.proto" } }
diff --git a/chrome/test/fuzzing/in_process_fuzzer.gni b/chrome/test/fuzzing/in_process_fuzzer.gni index b1b0246..8c41c715 100644 --- a/chrome/test/fuzzing/in_process_fuzzer.gni +++ b/chrome/test/fuzzing/in_process_fuzzer.gni
@@ -3,6 +3,7 @@ # found in the LICENSE file. import("//testing/libfuzzer/fuzzer_test.gni") +import("//third_party/protobuf/proto_library.gni") # This template allows creation of a fuzzer which has access to all the # functionality of a browser_test, including a full GUI instance of Chromium. @@ -33,3 +34,117 @@ } } } + +# This template is a proto-based version of the in_process_fuzzer template. +# +# This rule copies the proto-relevant bits from the mojolpm_fuzzer_test +# template (//mojo/public/tools/fuzzers/mojolpm.gni) +# +# Parameters: +# sources +# List of source .cc files to compile. +# +# deps +# List of dependencies to compile this target. +# +# proto_source +# Single source .proto file defining the structure of a testcase. +# +# proto_deps +# List of additional dependencies for compiling proto_source. +# +# testcase_proto_kind (optional, required if seed_corpus_sources provided) +# Name of proto message type representing a testcase. +# +# seed_corpus_sources (optional) +# List of source .textproto files used to build a seed corpus. + +template("in_process_proto_fuzzer") { + if (fuzzing_engine_supports_custom_main) { + assert(defined(invoker.sources) && defined(invoker.proto_source), + "\"sources\" and \"proto_source\" must be defined for $target_name") + + assert( + !defined(invoker.seed_corpus_sources) || + defined(invoker.testcase_proto_kind), + "\"testcase_proto_kind\" must be defined for $target_name since \"seed_corpus_sources\" is defined.") + + proto_target_name = "${target_name}_proto" + + proto_library(proto_target_name) { + # Work relative to src (//) instead of (by default) the BUILD file. + proto_in_dir = "//" + + sources = [ invoker.proto_source ] + generate_python = false + + proto_deps = [] + + import_dirs = [ root_gen_dir ] + + link_deps = [] + + if (defined(invoker.proto_deps)) { + proto_deps += invoker.proto_deps + link_deps += invoker.proto_deps + } + + testonly = true + } + + if (defined(invoker.seed_corpus_sources)) { + protoc_convert_target_name = "${target_name}_protoc_convert" + seed_corpus_path = "${target_gen_dir}/${target_name}_seed_corpus" + + protoc_convert(protoc_convert_target_name) { + sources = invoker.seed_corpus_sources + + inputs = [ invoker.proto_source ] + + output_pattern = "${seed_corpus_path}/{{source_name_part}}.binarypb" + + args = [ + "--encode=${invoker.testcase_proto_kind}", + "-I", + rebase_path(root_gen_dir), + "-I", + rebase_path("//"), + rebase_path(inputs[0]), + ] + + deps = [] + + if (defined(invoker.proto_deps)) { + deps += invoker.proto_deps + } + + testonly = true + } + } + + fuzzer_test(target_name) { + sources = invoker.sources + deps = [ + ":${proto_target_name}", + "//chrome/test/fuzzing:in_process_fuzzer_runner", + "//third_party/libprotobuf-mutator", + ] + + if (defined(invoker.deps)) { + deps += invoker.deps + } + + if (defined(invoker.seed_corpus_sources)) { + seed_corpus = seed_corpus_path + seed_corpus_deps = [ ":${protoc_convert_target_name}" ] + } + exclude_main = true + } + } else { + # noop if the fuzzer harness always provides its own main + not_needed(invoker, "*") + + group(target_name) { + } + } +}
diff --git a/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc b/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc index 2d108c35..595cf58 100644 --- a/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc +++ b/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc
@@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "chrome/test/fuzzing/kombucha_in_process_fuzzer.pb.h" + #include "base/functional/bind.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/browser_element_identifiers.h" @@ -13,30 +15,36 @@ #include "net/test/embedded_test_server/embedded_test_server.h" // At the moment, this is an example use of the InProcessFuzzer framework -// that uses Kombucha. It's not yet intended to be an effective fuzzer, +// that uses Kombucha + protos. It's not yet intended to be an effective fuzzer, // but just to be the skeleton of how this framework can be used. +#define DEFINE_BINARY_PROTO_IN_PROCESS_FUZZER(arg) \ + DEFINE_PROTO_FUZZER_IN_PROCESS_IMPL(true, arg) + +#define DEFINE_PROTO_FUZZER_IN_PROCESS_IMPL(use_binary, arg) \ + static void TestOneProtoInput(arg); \ + using FuzzerProtoType = \ + protobuf_mutator::libfuzzer::macro_internal::GetFirstParam< \ + decltype(&TestOneProtoInput)>::type; \ + DEFINE_CUSTOM_PROTO_MUTATOR_IMPL(use_binary, FuzzerProtoType) \ + DEFINE_CUSTOM_PROTO_CROSSOVER_IMPL(use_binary, FuzzerProtoType) \ + DEFINE_POST_PROCESS_PROTO_MUTATION_IMPL(FuzzerProtoType) + class KombuchaInProcessFuzzer : virtual public InteractiveBrowserTestT<InProcessFuzzer> { public: - void SetUp() override { InteractiveBrowserTestT::SetUp(); } - - void TearDownOnMainThread() override { - InteractiveBrowserTestT::TearDownOnMainThread(); - } - + using KombuchaTestCase = chrome::test::fuzzing::kombucha_in_process_fuzzer:: + proto::KombuchaTestcase; void SetUpOnMainThread() override; int Fuzz(const uint8_t* data, size_t size) override; static std::unique_ptr<net::test_server::HttpResponse> HandleHTTPRequest( base::WeakPtr<KombuchaInProcessFuzzer> fuzzer_weak, const net::test_server::HttpRequest& request); - std::string current_fuzz_case_; + KombuchaTestCase current_fuzz_case_; base::WeakPtrFactory<KombuchaInProcessFuzzer> weak_ptr_factory_{this}; }; -REGISTER_IN_PROCESS_FUZZER(KombuchaInProcessFuzzer) - void KombuchaInProcessFuzzer::SetUpOnMainThread() { InteractiveBrowserTestT::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); @@ -53,33 +61,38 @@ const net::test_server::HttpRequest& request) { std::unique_ptr<net::test_server::BasicHttpResponse> response; response = std::make_unique<net::test_server::BasicHttpResponse>(); - response->set_content_type("text/html"); - std::string response_body = ""; - // We are running on the embedded test server's thread. We want to - // ask the fuzzer thread for the latest HTML payload, but there's a - // risk of UaF if it's being destroyed. We use a weak pointer, but - // we have to dereference that on the originating thread. + response->set_content_type("application/x-protobuf"); + KombuchaTestCase testcase; + // We are running on the embedded test server's thread. + // We want to ask the fuzzer thread for the latest payload, + // but there's a risk of UaF if it's being destroyed. + // We use a weak pointer, but we have to dereference that on the originating + // thread. base::RunLoop run_loop; base::RepeatingCallback<void()> get_payload_lambda = base::BindLambdaForTesting([&]() { KombuchaInProcessFuzzer* fuzzer = fuzzer_weak.get(); if (fuzzer) { - response_body = fuzzer->current_fuzz_case_; + testcase = fuzzer->current_fuzz_case_; } run_loop.Quit(); }); content::GetUIThreadTaskRunner()->PostTask(FROM_HERE, get_payload_lambda); run_loop.Run(); - response->set_content(response_body); + response->set_content(testcase.SerializeAsString()); response->set_code(net::HTTP_OK); return response; } int KombuchaInProcessFuzzer::Fuzz(const uint8_t* data, size_t size) { + KombuchaTestCase proto_testcase; + proto_testcase.ParseFromArray(data, size); + current_fuzz_case_ = proto_testcase; + + // The following does not make use of data and size in any way. + // This state is temporary; Fuzz should be updated to use the provided data. DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kPrimaryTabElementId); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kSecondaryTabElementId); - std::string html_string(reinterpret_cast<const char*>(data), size); - current_fuzz_case_ = html_string; GURL test_url = embedded_test_server()->GetURL("/test.html"); RunTestSequence( InstrumentTab(kPrimaryTabElementId, 0), @@ -89,3 +102,5 @@ NavigateWebContents(kSecondaryTabElementId, test_url)); return 0; } + +REGISTER_IN_PROCESS_FUZZER(KombuchaInProcessFuzzer)
diff --git a/chrome/test/fuzzing/kombucha_in_process_fuzzer.proto b/chrome/test/fuzzing/kombucha_in_process_fuzzer.proto new file mode 100644 index 0000000..daeca2c6 --- /dev/null +++ b/chrome/test/fuzzing/kombucha_in_process_fuzzer.proto
@@ -0,0 +1,21 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Message format for a generic in-process proto fuzzer for now. +// This currently is not useful but is intended to be a skeleton guide. + +syntax = "proto2"; + +package chrome.test.fuzzing.kombucha_in_process_fuzzer.proto; + +// KombuchaStep provides a level of indirection which allows Testcase to +// compactly express repeated sequences of actions. +message KombuchaStep { + repeated uint32 action_name = 1 [packed = true]; +} + +// KombuchaTestcase is the top-level message type interpreted by the fuzzer. +message KombuchaTestcase { + repeated KombuchaStep steps = 1; +}
diff --git a/chrome/test/variations/BUILD.gn b/chrome/test/variations/BUILD.gn index 99960d1..fee9205d 100644 --- a/chrome/test/variations/BUILD.gn +++ b/chrome/test/variations/BUILD.gn
@@ -1,3 +1,4 @@ +import("//build/config/android/config.gni") import("//build/config/python.gni") python_library("test_utils") { @@ -13,9 +14,24 @@ "//build/skia_gold_common/", "//chrome/test/variations/drivers/", "//chrome/test/variations/fixtures/", + "//chrome/test/variations/drivers/", ] data_deps = [ "//ui/base:goldctl" ] + + if (is_android && enable_chrome_android_internal) { + data += [ + "//build/android/", + "//tools/android/avd/proto/", + ] + + data_deps += [ + "//build/android:devil_chromium_py", + "//build/android:test_runner_py", + "//third_party/catapult/devil:devil", + "//clank/bin:installer_scripts" + ] + } } python_library("variations_desktop_smoke_tests") {
diff --git a/chrome/test/variations/drivers/android.py b/chrome/test/variations/drivers/android.py new file mode 100644 index 0000000..be00f48 --- /dev/null +++ b/chrome/test/variations/drivers/android.py
@@ -0,0 +1,143 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import logging +import posixpath +import re +import subprocess +import sys +import time + +from contextlib import contextmanager +from typing import List, Optional + +import attr + +from chrome.test.variations.drivers import DriverFactory +# This import also adds `devil` and `build/android` to `sys.path`. +from chrome.test.variations.test_utils import android +from selenium import webdriver +from selenium.webdriver.chrome import service + +from devil.android import device_temp_file +from devil.android import device_utils +from devil.android.sdk import intent + + +@attr.attrs() +class AndroidDriverFactory(DriverFactory): + channel: str = attr.attrib() + avd_config: Optional[str] = attr.attrib() + enabled_emulator_window: bool = attr.attrib() + chromedriver_path: str = attr.attrib() + ports: List[int] = attr.attrib() + + def __attrs_post_init__(self): + self._instance = android.launch_emulator( + avd_config=self.avd_config, + emulator_window=self.enabled_emulator_window, + ports=self.ports) + self._device_temp_dir = device_temp_file.NamedDeviceTemporaryDirectory( + self.device.adb) + self._install_package() + + def _install_package(self): + self._package_name = android.install_chrome(self.channel, self.device) + self.device.ClearApplicationState(self.package_name) + logging.info('Installed Chrome (%s)', self.package_name) + + @property + def device_temp_dir(self) -> device_temp_file.NamedDeviceTemporaryDirectory: + return self._device_temp_dir + + @property + def package_name(self) -> str: + return self._package_name + + @property + def activity_name(self) -> Optional[str]: + return None + + @property + def device(self) -> device_utils.DeviceUtils: + return self._instance.device + + def _push_seed(self, seed_file: str): + local_seed_file = posixpath.join( + self.device_temp_dir.name, os.path.basename(seed_file)) + self.device.adb.Push(seed_file, local_seed_file) + + uid = self.device.GetUidForPackage(self.package_name) + self.device.RunShellCommand( + ['chown', uid, local_seed_file], as_root=True) + return local_seed_file + + #override + @contextmanager + def create_driver( + self, + seed_file: Optional[str] = None, + options: Optional[webdriver.ChromeOptions] = None + ) -> webdriver.Remote: + options = options or webdriver.ChromeOptions() + options.enable_mobile( + android_package=self.package_name, + android_activity=self.activity_name, + ) + + if seed_file: + installed_seed_path = self._push_seed(seed_file) + logging.info('Installed seed at (%s)', installed_seed_path) + options.add_argument( + f'variations-test-seed-path={installed_seed_path}') + + driver = None + try: + yield (driver := webdriver.Chrome( + service=service.Service(self.chromedriver_path), + options=options)) + finally: + if driver: + driver.quit() + + #override + def close(self): + self._instance.Stop() + + +@attr.attrs() +class WebviewDriverFactory(AndroidDriverFactory): + + #override + @property + def package_name(self): + return 'org.chromium.webview_shell' + + #override + @property + def activity_name(self): + return '.WebViewBrowserActivity' + + #override + def _install_package(self): + # Clear the system webview shell. + self.device.ClearApplicationState(self.package_name) + + ver = android.install_webview(self.channel, self.device) + logging.info('Installed webview (%s)', ver) + + # Launch shell once to create local state files. + self.device.StartActivity( + intent.Intent( + action='android.intent.action.MAIN', + package=self.package_name, + activity='.WebViewBrowserActivity'), + blocking=True) + self.device.ForceStop(self.package_name) + + #override + def _push_seed(self, seed_file: str): + raise NotImplemented(f'not supported for webview.') +
diff --git a/chrome/test/variations/fixtures/driver.py b/chrome/test/variations/fixtures/driver.py index 09528d6..20ca9e7 100644 --- a/chrome/test/variations/fixtures/driver.py +++ b/chrome/test/variations/fixtures/driver.py
@@ -7,6 +7,7 @@ import pytest from chrome.test.variations import test_utils +from chrome.test.variations.drivers import DriverFactory def pytest_addoption(parser): @@ -28,6 +29,20 @@ help='The path to the existing chromedriver. ' 'This will ignore --channel and skip downloading.') + # Options for android emulators + parser.addoption( + '--avd-config', + type=os.path.realpath, + help=('Path to the avd config. Required for Android products. ' + '(See //tools/android/avd/proto for message definition ' + 'and existing *.textpb files.)')) + + parser.addoption( + '--emulator-window', + action='store_true', + default=False, + help='Enable graphical window display on the emulator.') + # pylint: disable=redefined-outer-name @pytest.fixture(scope="session") @@ -67,20 +82,46 @@ return str(os.path.join(downloaded_dir, 'chromedriver')) -@pytest.fixture +@pytest.fixture(scope='session') def driver_factory( pytestconfig, chromedriver_path: str, - tmp_path_factory: pytest.TempPathFactory - ) -> 'DriverFactory': + tmp_path_factory: pytest.TempPathFactory, + local_http_server: 'HTTPServer', + ) -> DriverFactory: """Returns a factory that creates a webdriver.""" + factory: Optional[DriverFactory] = None target_platform = pytestconfig.getoption('target_platform') if target_platform in ('linux', 'win', 'mac'): from chrome.test.variations.drivers import desktop - - return desktop.DesktopDriverFactory( + factory = desktop.DesktopDriverFactory( channel=pytestconfig.getoption('channel'), crash_dump_dir=str(tmp_path_factory.mktemp('crash')), chromedriver_path=chromedriver_path) - assert False, f'Not supported platform {target_platform}.' + elif target_platform in ('android', 'webview'): + assert test_utils.get_hosted_platform() == 'linux', ( + f'Only support to run android tests on Linux, but running on ' + f'{test_utils.get_hosted_platform()}' + ) + from chrome.test.variations.drivers import android + factories = { + 'android': android.AndroidDriverFactory, + 'webview': android.WebviewDriverFactory, + } + + factory = factories[target_platform]( + channel=pytestconfig.getoption('channel'), + avd_config=pytestconfig.getoption('avd_config'), + enabled_emulator_window=pytestconfig.getoption('emulator_window'), + chromedriver_path=chromedriver_path, + ports=[local_http_server.server_port] + ) + + if not factory: + assert False, f'Not supported platform {target_platform}.' + + try: + yield factory + finally: + factory.close()
diff --git a/chrome/test/variations/fixtures/http.py b/chrome/test/variations/fixtures/http.py index 3ced5fd4..854128f 100644 --- a/chrome/test/variations/fixtures/http.py +++ b/chrome/test/variations/fixtures/http.py
@@ -28,7 +28,7 @@ threading.Thread(target=http_server.serve_forever).start() return http_server -@pytest.fixture +@pytest.fixture(scope='session') def local_http_server(): """Starts and returns a http server.""" http_server = _start_http_server()
diff --git a/chrome/updater/device_management/dm_storage_linux.cc b/chrome/updater/device_management/dm_storage_linux.cc index 1aec74a36..0230c18 100644 --- a/chrome/updater/device_management/dm_storage_linux.cc +++ b/chrome/updater/device_management/dm_storage_linux.cc
@@ -52,10 +52,7 @@ // Overrides for TokenServiceInterface. std::string GetDeviceID() const override { return device_id_; } - bool IsEnrollmentMandatory() const override { - // TODO(crbug.com/1345407) : check if enrollment is mandatory. - return false; - } + bool IsEnrollmentMandatory() const override { return false; } bool StoreEnrollmentToken(const std::string& enrollment_token) override { if (!base::ImportantFileWriter::WriteFileAtomically(
diff --git a/chrome/updater/device_management/dm_storage_mac.mm b/chrome/updater/device_management/dm_storage_mac.mm index a8a0980..59a23f5 100644 --- a/chrome/updater/device_management/dm_storage_mac.mm +++ b/chrome/updater/device_management/dm_storage_mac.mm
@@ -94,10 +94,7 @@ // Overrides for TokenServiceInterface. std::string GetDeviceID() const override { return device_id_; } - bool IsEnrollmentMandatory() const override { - // TODO(crbug.com/1345407) : check if enrollment is mandatory. - return false; - } + bool IsEnrollmentMandatory() const override { return false; } bool StoreEnrollmentToken(const std::string& enrollment_token) override; std::string GetEnrollmentToken() const override { return enrollment_token_; } bool StoreDmToken(const std::string& dm_token) override;
diff --git a/chrome/updater/win/installer_api.cc b/chrome/updater/win/installer_api.cc index 2f58f32..aa58dc9 100644 --- a/chrome/updater/win/installer_api.cc +++ b/chrome/updater/win/installer_api.cc
@@ -393,7 +393,7 @@ if (!app_installer.MatchesExtension(L".exe") && !app_installer.MatchesExtension(L".msi")) { return AppInstallerResult( - update_client::InstallError::LAUNCH_PROCESS_FAILED); + update_client::InstallError::LAUNCH_PROCESS_FAILED, -1); } DeleteInstallerOutput(app_info.scope, app_info.app_id); @@ -415,10 +415,11 @@ : L"0"}, }; - auto process = base::LaunchProcess(cmdline, options); + base::Process process = base::LaunchProcess(cmdline, options); if (!process.IsValid()) { return AppInstallerResult( - update_client::InstallError::LAUNCH_PROCESS_FAILED); + update_client::InstallError::LAUNCH_PROCESS_FAILED, + HRESULTFromLastError()); } int exit_code = -1;
diff --git a/chromeos/ash/components/dbus/hermes/README.md b/chromeos/ash/components/dbus/hermes/README.md index d4d26f2..8610242 100644 --- a/chromeos/ash/components/dbus/hermes/README.md +++ b/chromeos/ash/components/dbus/hermes/README.md
@@ -35,4 +35,17 @@ TODO ### Hermes Profile Client -TODO +The [`HermesProfileClient`](https://source.chromium.org/chromium/chromium/src/+/main:chromeos/ash/components/dbus/hermes/hermes_profile_client.h;drc=e4714ce987b39d3207473e0cd5cc77fbbbf37fda) +class provides an interface for interacting with the to Hermes profile objects. +This client can be used to: +* Rename profile name +* Enable and disable a carrier profile +* Get properties for a profile entry +* Listen for profile property changes + +For detailed documentation on the Hermes EUICC DBus API, please refer to +[org.chromium.Hermes.Profile.xml](https://source.corp.google.com/h/chromium/chromiumos/codesearch/+/main:src/platform2/hermes/dbus_bindings/org.chromium.Hermes.Profile.xml;drc=938e77682349e4678ecc532c57fc1178a4c47978). + +The [`HermesProfileClient::TestInterface`](https://source.chromium.org/chromium/chromium/src/+/main:chromeos/ash/components/dbus/hermes/hermes_profile_client.h;l=27-40;drc=e4714ce987b39d3207473e0cd5cc77fbbbf37fda) +allows you to add fake profile entries for ChromeOS unit testing purposes. +This interface is implemented in the [`FakeHermesProfileClient`](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:chromeos/ash/components/dbus/hermes/fake_hermes_profile_client.h;l=19;drc=e4714ce987b39d3207473e0cd5cc77fbbbf37fda).
diff --git a/chromeos/ash/components/network/cellular_policy_handler.cc b/chromeos/ash/components/network/cellular_policy_handler.cc index b958a9d..4554ee05 100644 --- a/chromeos/ash/components/network/cellular_policy_handler.cc +++ b/chromeos/ash/components/network/cellular_policy_handler.cc
@@ -155,6 +155,56 @@ AttemptInstallESim(); } +void CellularPolicyHandler::ScheduleRetry( + std::unique_ptr<InstallPolicyESimRequest> request, + InstallRetryReason reason) { + if (reason != InstallRetryReason::kInternalError && + request->retry_backoff.failure_count() >= kInstallRetryLimit) { + NET_LOG(ERROR) << "Failed to install policy eSIM profile: " + << request->activation_code; + ProcessRequests(); + return; + } + + request->retry_backoff.InformOfRequest(/*succeeded=*/false); + + if (reason == InstallRetryReason::kOther) { + request->retry_backoff.SetCustomReleaseTime(base::TimeTicks::Now() + + kInstallRetryDelay); + } + + const base::TimeDelta retry_delay = + request->retry_backoff.GetTimeUntilRelease(); + + NET_LOG(ERROR) << "Failed to install policy eSIM profile. Retrying in " + << retry_delay << ": " << request->activation_code; + + base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&CellularPolicyHandler::PushRequestAndProcess, + weak_ptr_factory_.GetWeakPtr(), std::move(request)), + retry_delay); +} + +void CellularPolicyHandler::PushRequestAndProcess( + std::unique_ptr<InstallPolicyESimRequest> request) { + remaining_install_requests_.push_back(std::move(request)); + ProcessRequests(); +} + +void CellularPolicyHandler::PopRequest() { + remaining_install_requests_.pop_front(); + is_installing_ = false; + if (remaining_install_requests_.empty()) { + const NetworkProfile* profile = + network_profile_handler_->GetProfileForUserhash( + /*userhash=*/std::string()); + DCHECK(profile); + + managed_network_configuration_handler_->OnCellularPoliciesApplied(*profile); + } +} + void CellularPolicyHandler::AttemptInstallESim() { DCHECK(is_installing_); @@ -199,23 +249,6 @@ SetupESim(*euicc_path); } -void CellularPolicyHandler::OnRefreshProfileList( - const dbus::ObjectPath& euicc_path, - std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock) { - if (!inhibit_lock) { - NET_LOG(ERROR) << "Failed to refresh the profile list due to an inhibit " - << "error, path: " << euicc_path.value(); - SetupESim(euicc_path); - return; - } - - need_refresh_profile_list_ = false; - // Reset the inhibit_lock so that the device will be uninhibited - // automatically. - inhibit_lock.reset(); - SetupESim(euicc_path); -} - void CellularPolicyHandler::SetupESim(const dbus::ObjectPath& euicc_path) { base::Value::Dict new_shill_properties = GetNewShillProperties(); absl::optional<dbus::ObjectPath> profile_path = @@ -261,25 +294,21 @@ } } -base::Value::Dict CellularPolicyHandler::GetNewShillProperties() { - const NetworkProfile* profile = - network_profile_handler_->GetProfileForUserhash( - /*userhash=*/std::string()); - const std::string* guid = - remaining_install_requests_.front()->onc_config.FindString( - ::onc::network_config::kGUID); - DCHECK(guid); +void CellularPolicyHandler::OnRefreshProfileList( + const dbus::ObjectPath& euicc_path, + std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock) { + if (!inhibit_lock) { + NET_LOG(ERROR) << "Failed to refresh the profile list due to an inhibit " + << "error, path: " << euicc_path.value(); + SetupESim(euicc_path); + return; + } - return policy_util::CreateShillConfiguration( - *profile, *guid, /*global_policy=*/nullptr, - &(remaining_install_requests_.front()->onc_config), - /*user_settings=*/nullptr); -} - -const policy_util::SmdxActivationCode& -CellularPolicyHandler::GetCurrentActivationCode() const { - DCHECK(is_installing_); - return remaining_install_requests_.front()->activation_code; + need_refresh_profile_list_ = false; + // Reset the inhibit_lock so that the device will be uninhibited + // automatically. + inhibit_lock.reset(); + SetupESim(euicc_path); } void CellularPolicyHandler::OnConfigureESimService( @@ -355,54 +384,34 @@ ProcessRequests(); } -void CellularPolicyHandler::ScheduleRetry( - std::unique_ptr<InstallPolicyESimRequest> request, - InstallRetryReason reason) { - if (reason != InstallRetryReason::kInternalError && - request->retry_backoff.failure_count() >= kInstallRetryLimit) { - NET_LOG(ERROR) << "Failed to install policy eSIM profile: " - << request->activation_code; - ProcessRequests(); - return; - } +void CellularPolicyHandler::OnWaitTimeout() { + NET_LOG(ERROR) << "Timed out when waiting for the EUICC or profile list."; - request->retry_backoff.InformOfRequest(/*succeeded=*/false); - - if (reason == InstallRetryReason::kOther) { - request->retry_backoff.SetCustomReleaseTime(base::TimeTicks::Now() + - kInstallRetryDelay); - } - - const base::TimeDelta retry_delay = - request->retry_backoff.GetTimeUntilRelease(); - - NET_LOG(ERROR) << "Failed to install policy eSIM profile. Retrying in " - << retry_delay << ": " << request->activation_code; - - base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&CellularPolicyHandler::PushRequestAndProcess, - weak_ptr_factory_.GetWeakPtr(), std::move(request)), - retry_delay); -} - -void CellularPolicyHandler::PushRequestAndProcess( - std::unique_ptr<InstallPolicyESimRequest> request) { - remaining_install_requests_.push_back(std::move(request)); + auto current_request = std::move(remaining_install_requests_.front()); + PopRequest(); + ScheduleRetry(std::move(current_request), InstallRetryReason::kInternalError); ProcessRequests(); } -void CellularPolicyHandler::PopRequest() { - remaining_install_requests_.pop_front(); - is_installing_ = false; - if (remaining_install_requests_.empty()) { - const NetworkProfile* profile = - network_profile_handler_->GetProfileForUserhash( - /*userhash=*/std::string()); - DCHECK(profile); +base::Value::Dict CellularPolicyHandler::GetNewShillProperties() { + const NetworkProfile* profile = + network_profile_handler_->GetProfileForUserhash( + /*userhash=*/std::string()); + const std::string* guid = + remaining_install_requests_.front()->onc_config.FindString( + ::onc::network_config::kGUID); + DCHECK(guid); - managed_network_configuration_handler_->OnCellularPoliciesApplied(*profile); - } + return policy_util::CreateShillConfiguration( + *profile, *guid, /*global_policy=*/nullptr, + &(remaining_install_requests_.front()->onc_config), + /*user_settings=*/nullptr); +} + +const policy_util::SmdxActivationCode& +CellularPolicyHandler::GetCurrentActivationCode() const { + DCHECK(is_installing_); + return remaining_install_requests_.front()->activation_code; } absl::optional<dbus::ObjectPath> @@ -421,15 +430,6 @@ return absl::nullopt; } -void CellularPolicyHandler::OnWaitTimeout() { - NET_LOG(ERROR) << "Timed out when waiting for the EUICC or profile list."; - - auto current_request = std::move(remaining_install_requests_.front()); - PopRequest(); - ScheduleRetry(std::move(current_request), InstallRetryReason::kInternalError); - ProcessRequests(); -} - bool CellularPolicyHandler::HasNonCellularInternetConnectivity() { const NetworkState* default_network = network_state_handler_->DefaultNetwork();
diff --git a/chromeos/ash/components/network/cellular_policy_handler.h b/chromeos/ash/components/network/cellular_policy_handler.h index 25b80b3..b60f347 100644 --- a/chromeos/ash/components/network/cellular_policy_handler.h +++ b/chromeos/ash/components/network/cellular_policy_handler.h
@@ -137,11 +137,14 @@ void ResumeInstallIfNeeded(); void ProcessRequests(); + void ScheduleRetry(std::unique_ptr<InstallPolicyESimRequest> request, + InstallRetryReason reason); + void PushRequestAndProcess(std::unique_ptr<InstallPolicyESimRequest> request); + void PopRequest(); + void AttemptInstallESim(); void SetupESim(const dbus::ObjectPath& euicc_path); - base::Value::Dict GetNewShillProperties(); - const policy_util::SmdxActivationCode& GetCurrentActivationCode() const; - std::string GetCurrentPolicyGuid() const; + void OnRefreshProfileList( const dbus::ObjectPath& euicc_path, std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock); @@ -150,12 +153,11 @@ HermesResponseStatus hermes_status, absl::optional<dbus::ObjectPath> profile_path, absl::optional<std::string> service_path); - void ScheduleRetry(std::unique_ptr<InstallPolicyESimRequest> request, - InstallRetryReason reason); - void PushRequestAndProcess(std::unique_ptr<InstallPolicyESimRequest> request); - void PopRequest(); - absl::optional<dbus::ObjectPath> FindExistingMatchingESimProfile(); void OnWaitTimeout(); + + base::Value::Dict GetNewShillProperties(); + const policy_util::SmdxActivationCode& GetCurrentActivationCode() const; + absl::optional<dbus::ObjectPath> FindExistingMatchingESimProfile(); bool HasNonCellularInternetConnectivity(); raw_ptr<CellularESimProfileHandler, ExperimentalAsh>
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index d4dcf33..bbc85d2 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -960,8 +960,8 @@ // parameters here. If a new parameter is added and its value is only known // after the user has logged in, please update BrowserPostLoginParams as well. // -// Next version: 62 -// Next id: 62 +// Next version: 63 +// Next id: 63 [Stable, RenamedFrom="crosapi.mojom.LacrosInitParams"] struct BrowserInitParams { // This is ash-chrome's version of the Crosapi interface. This is used by @@ -1346,6 +1346,11 @@ // When this flag is on, the clipboard history refresh feature is enabled. [MinVersion=61] bool enable_clipboard_history_refresh@61; + + // When this flag is set to true, frames can be scheduled with variable + // refresh rate timing. + [MinVersion=62] + bool is_variable_refresh_rate_enabled@62; }; // BrowserPostLoginParams is the subset of parameters in BrowserInitParams
diff --git a/chromeos/startup/browser_params_proxy.cc b/chromeos/startup/browser_params_proxy.cc index d4cdd7d..7aacfeb3 100644 --- a/chromeos/startup/browser_params_proxy.cc +++ b/chromeos/startup/browser_params_proxy.cc
@@ -295,4 +295,8 @@ return BrowserInitParams::Get()->enable_clipboard_history_refresh; } +bool BrowserParamsProxy::IsVariableRefreshRateEnabled() const { + return BrowserInitParams::Get()->is_variable_refresh_rate_enabled; +} + } // namespace chromeos
diff --git a/chromeos/startup/browser_params_proxy.h b/chromeos/startup/browser_params_proxy.h index 34e48ba..e0196776d 100644 --- a/chromeos/startup/browser_params_proxy.h +++ b/chromeos/startup/browser_params_proxy.h
@@ -134,6 +134,8 @@ bool EnableClipboardHistoryRefresh() const; + bool IsVariableRefreshRateEnabled() const; + private: friend base::NoDestructor<BrowserParamsProxy>;
diff --git a/components/BUILD.gn b/components/BUILD.gn index ad4e3b1..434592b 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -391,6 +391,7 @@ "//components/query_tiles:unit_tests", "//components/reporting/resources:unit_tests", "//components/services/heap_profiling:unit_tests", + "//components/services/storage:tests", "//components/tracing:unit_tests", "//components/translate/content/browser:unit_tests", "//components/translate/content/renderer:unit_tests", @@ -470,7 +471,6 @@ "//components/security_interstitials/content:unit_tests", "//components/services/paint_preview_compositor:unit_tests", "//components/services/quarantine:unit_tests", - "//components/services/storage:tests", "//components/site_engagement/content:unit_tests", "//components/site_isolation:unit_tests", "//components/spellcheck/browser:unit_tests",
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index c6e3bfd8..61f0b15 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -16,6 +16,12 @@ "AutofillAcrossIframes", base::FEATURE_ENABLED_BY_DEFAULT); +// Controls whether to flatten and fill cross-iframe forms on iOS. +// TODO(crbug.com/1441921) Remove once launched. +BASE_FEATURE(kAutofillAcrossIframesIos, + "AutofillAcrossIframesIos", + base::FEATURE_DISABLED_BY_DEFAULT); + // When enabled, address data will be verified and autocorrected in the // save/update prompt before saving an address profile. Relevant only if the // AutofillAddressProfileSavePrompt feature is enabled.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 4bcfc73..d250808 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -15,6 +15,7 @@ // All features in alphabetical order. COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillAcrossIframes); +COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillAcrossIframesIos); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE( kAutofillAddressProfileSavePromptAddressVerificationSupport);
diff --git a/components/component_updater/BUILD.gn b/components/component_updater/BUILD.gn index cecf210..422cb8f 100644 --- a/components/component_updater/BUILD.gn +++ b/components/component_updater/BUILD.gn
@@ -45,15 +45,6 @@ ] } -static_library("crl_set_remover") { - sources = [ - "crl_set_remover.cc", - "crl_set_remover.h", - ] - - deps = [ "//base" ] -} - static_library("test_support") { testonly = true sources = [
diff --git a/components/component_updater/crl_set_remover.cc b/components/component_updater/crl_set_remover.cc deleted file mode 100644 index b7543f6..0000000 --- a/components/component_updater/crl_set_remover.cc +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/component_updater/crl_set_remover.h" - -#include "base/files/file_util.h" -#include "base/functional/bind.h" -#include "base/task/thread_pool.h" - -namespace component_updater { - -void DeleteLegacyCRLSet(const base::FilePath& user_data_dir) { - base::ThreadPool::PostTask( - FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, - base::GetDeleteFileCallback(user_data_dir.Append( - FILE_PATH_LITERAL("Certificate Revocation Lists")))); -} - -} // namespace component_updater
diff --git a/components/component_updater/crl_set_remover.h b/components/component_updater/crl_set_remover.h deleted file mode 100644 index 181daef..0000000 --- a/components/component_updater/crl_set_remover.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2017 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_COMPONENT_UPDATER_CRL_SET_REMOVER_H_ -#define COMPONENTS_COMPONENT_UPDATER_CRL_SET_REMOVER_H_ - -namespace base { -class FilePath; -} // namespace base - -namespace component_updater { - -// TODO(crbug.com/1449043): Remove in M66 or later. -void DeleteLegacyCRLSet(const base::FilePath& user_data_dir); - -} // namespace component_updater - -#endif // COMPONENTS_COMPONENT_UPDATER_CRL_SET_REMOVER_H_
diff --git a/components/desks_storage/BUILD.gn b/components/desks_storage/BUILD.gn index ebeebb1..92234cc 100644 --- a/components/desks_storage/BUILD.gn +++ b/components/desks_storage/BUILD.gn
@@ -54,12 +54,19 @@ sources = [ "core/desk_test_util.cc", "core/desk_test_util.h", + "core/fake_desk_sync_bridge.cc", + "core/fake_desk_sync_bridge.h", + "core/fake_desk_sync_service.cc", + "core/fake_desk_sync_service.h", ] + public_deps = [ ":desks_storage" ] + deps = [ "//ash/public/cpp", "//base", "//components/app_constants", + "//components/sync:test_support", ] }
diff --git a/components/desks_storage/core/desk_model.h b/components/desks_storage/core/desk_model.h index 1dda015..0b951564 100644 --- a/components/desks_storage/core/desk_model.h +++ b/components/desks_storage/core/desk_model.h
@@ -15,6 +15,7 @@ #include "base/time/time.h" #include "base/uuid.h" #include "base/values.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { class DeskTemplate;
diff --git a/components/desks_storage/core/desk_model_wrapper.cc b/components/desks_storage/core/desk_model_wrapper.cc index fe6b12f..9fb787f 100644 --- a/components/desks_storage/core/desk_model_wrapper.cc +++ b/components/desks_storage/core/desk_model_wrapper.cc
@@ -178,7 +178,6 @@ std::string DeskModelWrapper::GetCacheGuid() { return GetDeskTemplateModel()->GetCacheGuid(); } - desks_storage::DeskSyncBridge* DeskModelWrapper::GetDeskTemplateModel() const { DCHECK(desk_template_model_); return desk_template_model_;
diff --git a/components/desks_storage/core/fake_desk_sync_bridge.cc b/components/desks_storage/core/fake_desk_sync_bridge.cc new file mode 100644 index 0000000..54d93f66 --- /dev/null +++ b/components/desks_storage/core/fake_desk_sync_bridge.cc
@@ -0,0 +1,236 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/desks_storage/core/fake_desk_sync_bridge.h" + +#include "ash/public/cpp/desk_template.h" +#include "base/containers/contains.h" +#include "base/functional/bind.h" +#include "base/functional/callback_helpers.h" +#include "base/memory/ptr_util.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" +#include "base/uuid.h" +#include "build/chromeos_buildflags.h" +#include "components/app_constants/constants.h" +#include "components/desks_storage/core/desk_model_observer.h" +#include "components/desks_storage/core/desk_template_util.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/base/ui_base_types.h" + +#if !BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chromeos/crosapi/cpp/lacros_startup_state.h" // nogncheck +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) + +namespace desks_storage { + +FakeDeskSyncBridge::FakeDeskSyncBridge() : cache_guid_("test_guid") {} + +FakeDeskSyncBridge::~FakeDeskSyncBridge() = default; + +DeskModel::GetAllEntriesResult FakeDeskSyncBridge::GetAllEntries() { + if (!IsReady()) { + return GetAllEntriesResult(GetAllEntriesStatus::kFailure, + std::vector<const ash::DeskTemplate*>()); + } + + std::vector<const ash::DeskTemplate*> entries; + + for (const auto& it : policy_entries_) { + entries.push_back(it.get()); + } + + for (const auto& it : desk_template_entries_) { + DCHECK_EQ(it.first, it.second->uuid()); + entries.push_back(it.second.get()); + } + + return GetAllEntriesResult(GetAllEntriesStatus::kOk, std::move(entries)); +} + +DeskModel::GetEntryByUuidResult FakeDeskSyncBridge::GetEntryByUUID( + const base::Uuid& uuid) { + if (!IsReady()) { + return GetEntryByUuidResult(GetEntryByUuidStatus::kFailure, nullptr); + } + + if (!uuid.is_valid()) { + return GetEntryByUuidResult(GetEntryByUuidStatus::kInvalidUuid, nullptr); + } + + auto it = desk_template_entries_.find(uuid); + if (it == desk_template_entries_.end()) { + std::unique_ptr<ash::DeskTemplate> policy_entry = + GetAdminDeskTemplateByUUID(uuid); + + if (policy_entry) { + return GetEntryByUuidResult(GetEntryByUuidStatus::kOk, + std::move(policy_entry)); + } else { + return GetEntryByUuidResult(GetEntryByUuidStatus::kNotFound, nullptr); + } + } else { + return GetEntryByUuidResult(GetEntryByUuidStatus::kOk, + it->second.get()->Clone()); + } +} + +void FakeDeskSyncBridge::AddOrUpdateEntry( + std::unique_ptr<ash::DeskTemplate> new_entry, + AddOrUpdateEntryCallback callback) { + if (!IsReady()) { + // This sync bridge has not finished initializing. Do not save the new entry + // yet. + std::move(callback).Run(AddOrUpdateEntryStatus::kFailure, + std::move(new_entry)); + return; + } + + if (!new_entry) { + std::move(callback).Run(AddOrUpdateEntryStatus::kInvalidArgument, + std::move(new_entry)); + return; + } + + base::Uuid uuid = new_entry->uuid(); + if (!uuid.is_valid()) { + std::move(callback).Run(AddOrUpdateEntryStatus::kInvalidArgument, + std::move(new_entry)); + return; + } + std::vector<const ash::DeskTemplate*> added_or_updated; + // When a user creates a desk template locally, the desk template has `kUser` + // as its source. Only user desk templates should be saved to Sync. + DCHECK_EQ(ash::DeskTemplateSource::kUser, new_entry->source()); + auto entry = new_entry->Clone(); + + entry->set_template_name( + base::CollapseWhitespace(new_entry->template_name(), true)); + + if (entry->type() == ash::DeskTemplateType::kFloatingWorkspace) { + floating_workspace_templates_uuid_[cache_guid_] = uuid; + } + + desk_template_entries_[uuid] = std::move(entry); + added_or_updated.push_back(GetUserEntryByUUID(uuid)); + NotifyRemoteDeskTemplateAddedOrUpdated(added_or_updated); + std::move(callback).Run(AddOrUpdateEntryStatus::kOk, std::move(new_entry)); +} + +void FakeDeskSyncBridge::DeleteEntry(const base::Uuid& uuid, + DeleteEntryCallback callback) { + if (!IsReady()) { + // This sync bridge has not finished initializing. + // Cannot delete anything. + std::move(callback).Run(DeleteEntryStatus::kFailure); + return; + } + + if (GetUserEntryByUUID(uuid) == nullptr) { + // Consider the deletion successful if the entry does not exist. + std::move(callback).Run(DeleteEntryStatus::kOk); + return; + } + + desk_template_entries_.erase(uuid); + for (const auto& [cache_guid, fws_uuid] : + floating_workspace_templates_uuid_) { + if (fws_uuid == uuid) { + floating_workspace_templates_uuid_.erase(cache_guid); + } + } + std::move(callback).Run(DeleteEntryStatus::kOk); +} + +void FakeDeskSyncBridge::DeleteAllEntries(DeleteEntryCallback callback) { + desk_template_entries_.clear(); + floating_workspace_templates_uuid_.clear(); + std::move(callback).Run(DeleteEntryStatus::kOk); +} + +size_t FakeDeskSyncBridge::GetEntryCount() const { + return GetSaveAndRecallDeskEntryCount() + GetDeskTemplateEntryCount(); +} + +// Return 0 for now since chrome sync does not support save and recall desks. +size_t FakeDeskSyncBridge::GetSaveAndRecallDeskEntryCount() const { + return 0u; +} + +size_t FakeDeskSyncBridge::GetDeskTemplateEntryCount() const { + size_t template_count = std::count_if( + desk_template_entries_.begin(), desk_template_entries_.end(), + [](const std::pair<base::Uuid, std::unique_ptr<ash::DeskTemplate>>& + entry) { + return entry.second->type() == ash::DeskTemplateType::kTemplate; + }); + return template_count + policy_entries_.size(); +} + +// Chrome sync does not support save and recall desks yet. Return 0 for max +// count. +size_t FakeDeskSyncBridge::GetMaxSaveAndRecallDeskEntryCount() const { + return 0u; +} + +size_t FakeDeskSyncBridge::GetMaxDeskTemplateEntryCount() const { + return 6u + policy_entries_.size(); +} + +std::vector<base::Uuid> FakeDeskSyncBridge::GetAllEntryUuids() const { + std::vector<base::Uuid> keys; + + for (const auto& it : policy_entries_) { + keys.push_back(it.get()->uuid()); + } + + for (const auto& it : desk_template_entries_) { + DCHECK_EQ(it.first, it.second->uuid()); + keys.emplace_back(it.first); + } + return keys; +} + +bool FakeDeskSyncBridge::IsReady() const { + return true; +} + +bool FakeDeskSyncBridge::IsSyncing() const { + return false; +} + +ash::DeskTemplate* FakeDeskSyncBridge::FindOtherEntryWithName( + const std::u16string& name, + ash::DeskTemplateType type, + const base::Uuid& uuid) const { + return desk_template_util::FindOtherEntryWithName(name, uuid, + desk_template_entries_); +} + +const ash::DeskTemplate* FakeDeskSyncBridge::GetUserEntryByUUID( + const base::Uuid& uuid) const { + auto it = desk_template_entries_.find(uuid); + if (it == desk_template_entries_.end()) { + return nullptr; + } + return it->second.get(); +} + +void FakeDeskSyncBridge::NotifyRemoteDeskTemplateAddedOrUpdated( + const std::vector<const ash::DeskTemplate*>& new_entries) { + if (new_entries.empty()) { + return; + } + + for (DeskModelObserver& observer : observers_) { + observer.EntriesAddedOrUpdatedRemotely(new_entries); + } +} + +std::string FakeDeskSyncBridge::GetCacheGuid() { + return cache_guid_; +} + +} // namespace desks_storage
diff --git a/components/desks_storage/core/fake_desk_sync_bridge.h b/components/desks_storage/core/fake_desk_sync_bridge.h new file mode 100644 index 0000000..368ad91 --- /dev/null +++ b/components/desks_storage/core/fake_desk_sync_bridge.h
@@ -0,0 +1,78 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DESKS_STORAGE_CORE_FAKE_DESK_SYNC_BRIDGE_H_ +#define COMPONENTS_DESKS_STORAGE_CORE_FAKE_DESK_SYNC_BRIDGE_H_ + +#include "components/desks_storage/core/desk_model.h" + +namespace ash { +class DeskTemplate; +enum class DeskTemplateType; +} // namespace ash + +namespace desks_storage { + +// A fake desk sync bridge used for testing. +class FakeDeskSyncBridge : public DeskModel { + public: + FakeDeskSyncBridge(); + FakeDeskSyncBridge(const FakeDeskSyncBridge&) = delete; + FakeDeskSyncBridge& operator=(const FakeDeskSyncBridge&) = delete; + ~FakeDeskSyncBridge() override; + + DeskModel::GetAllEntriesResult GetAllEntries() override; + DeskModel::GetEntryByUuidResult GetEntryByUUID( + const base::Uuid& uuid) override; + + void AddOrUpdateEntry(std::unique_ptr<ash::DeskTemplate> new_entry, + AddOrUpdateEntryCallback callback) override; + void DeleteEntry(const base::Uuid& uuid, + DeleteEntryCallback callback) override; + void DeleteAllEntries(DeleteEntryCallback callback) override; + size_t GetEntryCount() const override; + size_t GetSaveAndRecallDeskEntryCount() const override; + size_t GetDeskTemplateEntryCount() const override; + size_t GetMaxSaveAndRecallDeskEntryCount() const override; + size_t GetMaxDeskTemplateEntryCount() const override; + std::vector<base::Uuid> GetAllEntryUuids() const override; + bool IsReady() const override; + // Whether this sync bridge is syncing local data to sync. This sync bridge + // still allows user to save desk templates locally when users disable syncing + // for Workspace Desk model type. + bool IsSyncing() const override; + + ash::DeskTemplate* FindOtherEntryWithName( + const std::u16string& name, + ash::DeskTemplateType type, + const base::Uuid& uuid) const override; + + void SetCacheGuid(std::string cache_guid) { cache_guid_ = cache_guid; } + std::string GetCacheGuid() override; + + private: + using DeskEntries = + base::flat_map<base::Uuid, std::unique_ptr<ash::DeskTemplate>>; + + // Notify all observers of any `new_entries` when they are added/updated via + // sync. + void NotifyRemoteDeskTemplateAddedOrUpdated( + const std::vector<const ash::DeskTemplate*>& new_entries); + + const ash::DeskTemplate* GetUserEntryByUUID(const base::Uuid& uuid) const; + + // `desk_template_entries_` is keyed by UUIDs. + DeskEntries desk_template_entries_; + + // `floating_workspace_templates_uuid_` is keyed by cache_guids. + base::flat_map<std::string, base::Uuid> floating_workspace_templates_uuid_; + + std::string cache_guid_; + + base::WeakPtrFactory<FakeDeskSyncBridge> weak_ptr_factory_{this}; +}; + +} // namespace desks_storage + +#endif // COMPONENTS_DESKS_STORAGE_CORE_FAKE_DESK_SYNC_BRIDGE_H_
diff --git a/components/desks_storage/core/fake_desk_sync_service.cc b/components/desks_storage/core/fake_desk_sync_service.cc new file mode 100644 index 0000000..b6d8ab6 --- /dev/null +++ b/components/desks_storage/core/fake_desk_sync_service.cc
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/desks_storage/core/fake_desk_sync_service.h" +#include "base/logging.h" +#include "fake_desk_sync_bridge.h" +#include "fake_desk_sync_service.h" + +namespace desks_storage { + +FakeDeskSyncService::FakeDeskSyncService(bool skip_engine_connection) + : fake_model_type_controller_delegate_(syncer::ModelType::WORKSPACE_DESK) { + fake_bridge_ = std::make_unique<FakeDeskSyncBridge>(); + fake_bridge_->SetCacheGuid("test_guid"); + if (skip_engine_connection) { + fake_model_type_controller_delegate_ + .EnableSkipEngineConnectionForActivationResponse(); + } +} +FakeDeskSyncService::~FakeDeskSyncService() = default; + +DeskModel* FakeDeskSyncService::GetDeskModel() { + return fake_bridge_.get(); +} + +FakeDeskSyncBridge* FakeDeskSyncService::GetDeskSyncBridge() { + return fake_bridge_.get(); +} + +base::WeakPtr<syncer::ModelTypeControllerDelegate> +FakeDeskSyncService::GetControllerDelegate() { + return fake_model_type_controller_delegate_.GetWeakPtr(); +} + +} // namespace desks_storage
diff --git a/components/desks_storage/core/fake_desk_sync_service.h b/components/desks_storage/core/fake_desk_sync_service.h new file mode 100644 index 0000000..0c1637f7 --- /dev/null +++ b/components/desks_storage/core/fake_desk_sync_service.h
@@ -0,0 +1,38 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_DESKS_STORAGE_CORE_FAKE_DESK_SYNC_SERVICE_H_ +#define COMPONENTS_DESKS_STORAGE_CORE_FAKE_DESK_SYNC_SERVICE_H_ + +#include "base/logging.h" +#include "components/desks_storage/core/desk_sync_service.h" +#include "components/desks_storage/core/fake_desk_sync_bridge.h" +#include "components/sync/test/fake_model_type_controller_delegate.h" + +namespace desks_storage { +class FakeDeskSyncBridge; + +// KeyedService responsible for desk templates sync. +class FakeDeskSyncService : public DeskSyncService { + public: + explicit FakeDeskSyncService(bool skip_engine_connection = false); + FakeDeskSyncService(const FakeDeskSyncService&) = delete; + FakeDeskSyncService& operator=(const FakeDeskSyncService&) = delete; + ~FakeDeskSyncService() override; + + DeskModel* GetDeskModel() override; + FakeDeskSyncBridge* GetDeskSyncBridge(); + void SetDeskSyncBridge(FakeDeskSyncBridge* fake_desk_sync_bridge); + + base::WeakPtr<syncer::ModelTypeControllerDelegate> GetControllerDelegate() + override; + + private: + std::unique_ptr<FakeDeskSyncBridge> fake_bridge_; + syncer::FakeModelTypeControllerDelegate fake_model_type_controller_delegate_; +}; + +} // namespace desks_storage + +#endif // COMPONENTS_DESKS_STORAGE_CORE_FAKE_DESK_SYNC_SERVICE_H_
diff --git a/components/flags_ui/resources/flags.css b/components/flags_ui/resources/flags.css index 9df8a1c6..09ef9ed 100644 --- a/components/flags_ui/resources/flags.css +++ b/components/flags_ui/resources/flags.css
@@ -70,12 +70,9 @@ body { color: var(--primary-color); - display: flex; - flex-direction: column; - font-family: Roboto; font-size: 0.8125em; /* Force the vertical scrollbar to always be displayed, to avoid UI jumps. */ - height: 100vh; + height: 100%; margin: 0; } @@ -108,8 +105,7 @@ } #flagsTemplate { - flex: 1; - padding: calc(60px + 1rem) var(--side-padding) 8px; + padding: 1rem var(--side-padding) 8px; } :focus-visible { @@ -150,9 +146,8 @@ background: var(--toolbar-color); box-shadow: 0 2px 2px 0 var(--shadow-color); box-sizing: border-box; - flex: none; left: 0; - position: fixed; + position: sticky; top: 0; width: 100%; z-index: 9; @@ -291,9 +286,6 @@ .experiment { color: var(--secondary-color); line-height: 1.45; - /* Adjustment for fixed header */ - margin: .3em 0 -70px; - padding-top: 70px; width: 100%; } @@ -472,9 +464,8 @@ .tab-content { display: none; line-height: 25px; - margin-top: -50px; /* Bottom padding should be greater than evaluated height of needs-restart */ - padding-bottom: 200px; + padding-bottom: 100px; position: relative; }
diff --git a/components/history_clusters/core/history_clusters_util.cc b/components/history_clusters/core/history_clusters_util.cc index f5820c01..42c2a6d 100644 --- a/components/history_clusters/core/history_clusters_util.cc +++ b/components/history_clusters/core/history_clusters_util.cc
@@ -9,6 +9,7 @@ #include "base/containers/contains.h" #include "base/containers/cxx20_erase.h" #include "base/i18n/case_conversion.h" +#include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" @@ -289,6 +290,7 @@ DCHECK_GT(min_visits, 0u); base::EraseIf(clusters, [&](auto& cluster) { int index = -1; + size_t num_visits_below_fold = 0; base::EraseIf(cluster.visits, [&](auto& visit) { index++; // Easy cases: cull all zero-score and explicitly Hidden visits. @@ -312,10 +314,26 @@ // At this point we know we have a low-scoring visit. If we haven't shown // enough visits above the fold yet, admit these low-score ones first. - return index >= static_cast<int>( - GetConfig().num_visits_to_always_show_above_the_fold); + if (index >= static_cast<int>( + GetConfig().num_visits_to_always_show_above_the_fold)) { + num_visits_below_fold++; + return true; + } + return false; }); - return cluster.visits.size() < min_visits; + bool should_hide_cluster = cluster.visits.size() < min_visits; + if (!should_hide_cluster) { + // Log the # of visits that would be "below the fold" as a percentage of + // all visits in the cluster. + base::UmaHistogramCounts100("History.Clusters.Backend.NumVisitsBelowFold", + num_visits_below_fold); + base::UmaHistogramPercentage( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", + static_cast<int>(100 * + (1.0 * num_visits_below_fold / + (num_visits_below_fold + cluster.visits.size())))); + } + return should_hide_cluster; }); }
diff --git a/components/history_clusters/core/history_clusters_util_unittest.cc b/components/history_clusters/core/history_clusters_util_unittest.cc index eeca8e0..1fb54da 100644 --- a/components/history_clusters/core/history_clusters_util_unittest.cc +++ b/components/history_clusters/core/history_clusters_util_unittest.cc
@@ -6,6 +6,7 @@ #include "base/ranges/algorithm.h" #include "base/strings/stringprintf.h" +#include "base/test/metrics/histogram_tester.h" #include "components/history/core/browser/history_types.h" #include "components/history_clusters/core/clustering_test_utils.h" #include "components/history_clusters/core/config.h" @@ -290,33 +291,79 @@ all_clusters[5].visits[1].interaction_state = history::ClusterVisit::InteractionState::kDone; - auto clusters = all_clusters; - // Test the zero-query state. - CullVisitsThatShouldBeHidden(clusters, /*is_zero_query_state=*/true); - ASSERT_EQ(clusters.size(), 4u); + { + // Test the zero-query state. + base::HistogramTester histogram_tester; - EXPECT_EQ(clusters[0].cluster_id, 0); - EXPECT_EQ(clusters[0].visits.size(), 5u); + auto clusters = all_clusters; + CullVisitsThatShouldBeHidden(clusters, /*is_zero_query_state=*/true); + ASSERT_EQ(clusters.size(), 4u); - EXPECT_EQ(clusters[1].cluster_id, 1); - EXPECT_EQ(clusters[1].visits.size(), 4u); + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.NumVisitsBelowFold", 4); + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", 4); - EXPECT_EQ(clusters[2].cluster_id, 2); - EXPECT_EQ(clusters[2].visits.size(), 2u); + // No visits are hidden as they are all high-scoring. + EXPECT_EQ(clusters[0].cluster_id, 0); + EXPECT_EQ(clusters[0].visits.size(), 5u); - EXPECT_EQ(clusters[3].cluster_id, 5); - EXPECT_EQ(clusters[3].visits.size(), 2u); + // 1 visit could have been shown but is below the fold due to score. + EXPECT_EQ(clusters[1].cluster_id, 1); + EXPECT_EQ(clusters[1].visits.size(), 4u); - // Test the queried state with a higher threshold of required visits. - clusters = all_clusters; - CullVisitsThatShouldBeHidden(clusters, /*is_zero_query_state=*/false); - // Cluster id = 3, with 1 visit after filtering should no longer be removed. - ASSERT_EQ(clusters.size(), 5u); - EXPECT_EQ(clusters[3].cluster_id, 3); - EXPECT_EQ(clusters[3].visits.size(), 1u); - // Cluster id = 5, with a Done visit, should have that Done visit visible. - EXPECT_EQ(clusters[4].cluster_id, 5); - EXPECT_EQ(clusters[4].visits.size(), 3u); + // No visits that should actually be shown are hidden. + EXPECT_EQ(clusters[2].cluster_id, 2); + EXPECT_EQ(clusters[2].visits.size(), 2u); + + // No visits that should actually be shown are hidden. + EXPECT_EQ(clusters[3].cluster_id, 5); + EXPECT_EQ(clusters[3].visits.size(), 2u); + + // Clusters index 0, 2, and 3. + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFold", 0, 3); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", 0, 3); + + // Cluster index 1. + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFold", 1, 1); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", 20, 1); + } + + { + base::HistogramTester histogram_tester; + // Test the queried state with a higher threshold of required visits. + auto clusters = all_clusters; + CullVisitsThatShouldBeHidden(clusters, /*is_zero_query_state=*/false); + + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.NumVisitsBelowFold", 5); + histogram_tester.ExpectTotalCount( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", 5); + + // Cluster id = 3, with 1 visit after filtering should no longer be removed. + ASSERT_EQ(clusters.size(), 5u); + EXPECT_EQ(clusters[3].cluster_id, 3); + EXPECT_EQ(clusters[3].visits.size(), 1u); + // Cluster id = 5, with a Done visit, should have that Done visit visible. + EXPECT_EQ(clusters[4].cluster_id, 5); + EXPECT_EQ(clusters[4].visits.size(), 3u); + + // Clusters 0, 2, 3, and 4. + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFold", 0, 4); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", 0, 4); + + // Cluster 1. + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFold", 1, 1); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.NumVisitsBelowFoldPercentage", 20, 1); + } } TEST(HistoryClustersUtilTest, CoalesceRelatedSearches) {
diff --git a/components/management_strings.grdp b/components/management_strings.grdp index f019a4a..07d7871 100644 --- a/components/management_strings.grdp +++ b/components/management_strings.grdp
@@ -319,4 +319,11 @@ URLs of pages you visit are sent to Google Cloud or third parties for analysis. For example, they might be scanned to detect unsafe websites or filter websites based on rules set by the administrator. </message> </if> + + <!-- Strings related to Chrome Enterprise Device Signals Sharing --> + <if expr="is_win or is_linux or is_macosx"> + <message name="IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE" desc="Disclosure message explaining that device signals can be shared."> + Information about your browser, OS, device, installed software, and files + </message> + </if> </grit-part>
diff --git a/components/management_strings_grdp/IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE.png.sha1 b/components/management_strings_grdp/IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE.png.sha1 new file mode 100644 index 0000000..5c05bfb --- /dev/null +++ b/components/management_strings_grdp/IDS_MANAGEMENT_DEVICE_SIGNALS_DISCLOSURE.png.sha1
@@ -0,0 +1 @@ +b6ca5d74b0974e288e867ca1cbf0928833972931 \ No newline at end of file
diff --git a/components/network_time/network_time_tracker.cc b/components/network_time/network_time_tracker.cc index 81dd9b0..5df54d09 100644 --- a/components/network_time/network_time_tracker.cc +++ b/components/network_time/network_time_tracker.cc
@@ -648,6 +648,10 @@ } double NetworkTimeTracker::ComputeClockDriftLatencyVariance() { + if (static_cast<uint8_t>(kClockDriftSamples.Get()) == 0) { + return std::numeric_limits<double>::infinity(); + } + base::TimeDelta mean = base::Seconds(0); for (size_t i = 0; i < clock_drift_samples_.size(); i++) { // Exclude middle sample since we do not use it @@ -666,6 +670,7 @@ diff_from_mean.InMilliseconds() * diff_from_mean.InMilliseconds(); } } + variance /= static_cast<uint8_t>(kClockDriftSamples.Get()); return variance; }
diff --git a/components/network_time/network_time_tracker_unittest.cc b/components/network_time/network_time_tracker_unittest.cc index cdc5a34..ed7f37e 100644 --- a/components/network_time/network_time_tracker_unittest.cc +++ b/components/network_time/network_time_tracker_unittest.cc
@@ -1007,8 +1007,10 @@ base::TimeDelta mean = (latency1 + latency3) / 2.0; double variance = - (latency1 - mean).InMilliseconds() * (latency1 - mean).InMilliseconds() + - (latency3 - mean).InMilliseconds() * (latency3 - mean).InMilliseconds(); + ((latency1 - mean).InMilliseconds() * (latency1 - mean).InMilliseconds() + + (latency3 - mean).InMilliseconds() * + (latency3 - mean).InMilliseconds()) / + 2; histograms.ExpectUniqueSample("PrivacyBudget.ClockDrift.FetchLatencyVariance", variance, 1); } @@ -1060,8 +1062,10 @@ base::TimeDelta mean = (latency1 + latency3) / 2.0; double variance = - (latency1 - mean).InMilliseconds() * (latency1 - mean).InMilliseconds() + - (latency3 - mean).InMilliseconds() * (latency3 - mean).InMilliseconds(); + ((latency1 - mean).InMilliseconds() * (latency1 - mean).InMilliseconds() + + (latency3 - mean).InMilliseconds() * + (latency3 - mean).InMilliseconds()) / + 2; histograms.ExpectTotalCount("PrivacyBudget.ClockDrift.FetchLatencyVariance", 1);
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index d58df19..6186dc9c4 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -632,6 +632,7 @@ "android/java/src/org/chromium/components/omnibox/AutocompleteSchemeClassifier.java", "android/java/src/org/chromium/components/omnibox/OmniboxUrlEmphasizer.java", "android/java/src/org/chromium/components/omnibox/SuggestionAnswer.java", + "android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java", "android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java", ] }
diff --git a/components/omnibox/browser/actions/history_clusters_action.cc b/components/omnibox/browser/actions/history_clusters_action.cc index 934da176..a616b52 100644 --- a/components/omnibox/browser/actions/history_clusters_action.cc +++ b/components/omnibox/browser/actions/history_clusters_action.cc
@@ -175,8 +175,8 @@ base::android::ScopedJavaLocalRef<jobject> HistoryClustersAction::GetOrCreateJavaObject(JNIEnv* env) const { if (!j_omnibox_action_) { - j_omnibox_action_.Reset( - BuildHistoryClustersAction(env, strings_.hint, query_)); + j_omnibox_action_.Reset(BuildHistoryClustersAction( + env, reinterpret_cast<intptr_t>(this), strings_.hint, query_)); } return base::android::ScopedJavaLocalRef<jobject>(j_omnibox_action_); }
diff --git a/components/omnibox/browser/actions/history_clusters_action.h b/components/omnibox/browser/actions/history_clusters_action.h index 2412166..9267c65 100644 --- a/components/omnibox/browser/actions/history_clusters_action.h +++ b/components/omnibox/browser/actions/history_clusters_action.h
@@ -69,10 +69,6 @@ // Used to open journeys in side panel with relevant clusters std::string query_; - -#if BUILDFLAG(IS_ANDROID) - mutable base::android::ScopedJavaGlobalRef<jobject> j_omnibox_action_; -#endif }; // If the feature is enabled, attaches any necessary History Clusters actions
diff --git a/components/omnibox/browser/actions/omnibox_action.cc b/components/omnibox/browser/actions/omnibox_action.cc index 0a518a5..5906e30 100644 --- a/components/omnibox/browser/actions/omnibox_action.cc +++ b/components/omnibox/browser/actions/omnibox_action.cc
@@ -14,6 +14,10 @@ #if defined(SUPPORT_PEDALS_VECTOR_ICONS) #include "components/omnibox/browser/vector_icons.h" // nogncheck #endif +#if BUILDFLAG(IS_ANDROID) +#include "base/android/jni_android.h" +#include "components/omnibox/browser/jni_headers/OmniboxAction_jni.h" +#endif OmniboxAction::LabelStrings::LabelStrings(int id_hint, int id_suggestion_contents, @@ -39,8 +43,7 @@ OmniboxAction::LabelStrings::~LabelStrings() = default; -namespace base { -namespace trace_event { +namespace base::trace_event { size_t EstimateMemoryUsage(const OmniboxAction::LabelStrings& self) { size_t total = 0; total += base::trace_event::EstimateMemoryUsage(self.hint); @@ -49,8 +52,7 @@ total += base::trace_event::EstimateMemoryUsage(self.accessibility_hint); return total; } -} // namespace trace_event -} // namespace base +} // namespace base::trace_event // ============================================================================= @@ -77,7 +79,15 @@ OmniboxAction::OmniboxAction(LabelStrings strings, GURL url) : strings_(strings), url_(url) {} -OmniboxAction::~OmniboxAction() = default; +OmniboxAction::~OmniboxAction() { +#if BUILDFLAG(IS_ANDROID) + if (j_omnibox_action_) { + Java_OmniboxAction_destroy(base::android::AttachCurrentThread(), + j_omnibox_action_); + j_omnibox_action_.Reset(); + } +#endif +} const OmniboxAction::LabelStrings& OmniboxAction::GetLabelStrings() const { return strings_;
diff --git a/components/omnibox/browser/actions/omnibox_action.h b/components/omnibox/browser/actions/omnibox_action.h index 89afc68..b926da14 100644 --- a/components/omnibox/browser/actions/omnibox_action.h +++ b/components/omnibox/browser/actions/omnibox_action.h
@@ -169,6 +169,10 @@ #if BUILDFLAG(IS_ANDROID) virtual base::android::ScopedJavaLocalRef<jobject> GetOrCreateJavaObject( JNIEnv* env) const; + + void RecordActionShown(JNIEnv* env, int position, bool executed) { + RecordActionShown(position, executed); + } #endif protected: @@ -182,6 +186,10 @@ // For navigation Actions, this holds the destination URL. Otherwise, empty. GURL url_; + +#if BUILDFLAG(IS_ANDROID) + mutable base::android::ScopedJavaGlobalRef<jobject> j_omnibox_action_; +#endif }; #endif // COMPONENTS_OMNIBOX_BROWSER_ACTIONS_OMNIBOX_ACTION_H_
diff --git a/components/omnibox/browser/actions/omnibox_action_factory_android.cc b/components/omnibox/browser/actions/omnibox_action_factory_android.cc index eda2a1c..499f33f 100644 --- a/components/omnibox/browser/actions/omnibox_action_factory_android.cc +++ b/components/omnibox/browser/actions/omnibox_action_factory_android.cc
@@ -40,34 +40,37 @@ base::android::ScopedJavaGlobalRef<jobject> BuildOmniboxPedal( JNIEnv* env, + intptr_t instance, const std::u16string& hint, OmniboxPedalId pedal_id) { return base::android::ScopedJavaGlobalRef( Java_OmniboxActionFactory_buildOmniboxPedal( - env, g_java_factory.Get(), + env, g_java_factory.Get(), instance, base::android::ConvertUTF16ToJavaString(env, hint), static_cast<int32_t>(pedal_id))); } base::android::ScopedJavaGlobalRef<jobject> BuildHistoryClustersAction( JNIEnv* env, + intptr_t instance, const std::u16string& hint, const std::string& query) { return base::android::ScopedJavaGlobalRef( Java_OmniboxActionFactory_buildHistoryClustersAction( - env, g_java_factory.Get(), + env, g_java_factory.Get(), instance, base::android::ConvertUTF16ToJavaString(env, hint), base::android::ConvertUTF8ToJavaString(env, query))); } base::android::ScopedJavaGlobalRef<jobject> BuildOmniboxActionInSuggest( JNIEnv* env, + intptr_t instance, const std::u16string& hint, int action_type, const std::string& action_uri) { return base::android::ScopedJavaGlobalRef( Java_OmniboxActionFactory_buildActionInSuggest( - env, g_java_factory.Get(), + env, g_java_factory.Get(), instance, base::android::ConvertUTF16ToJavaString(env, hint), action_type, base::android::ConvertUTF8ToJavaString(env, action_uri))); }
diff --git a/components/omnibox/browser/actions/omnibox_action_factory_android.h b/components/omnibox/browser/actions/omnibox_action_factory_android.h index 597ef4c..5ae79dd 100644 --- a/components/omnibox/browser/actions/omnibox_action_factory_android.h +++ b/components/omnibox/browser/actions/omnibox_action_factory_android.h
@@ -14,16 +14,19 @@ base::android::ScopedJavaGlobalRef<jobject> BuildOmniboxPedal( JNIEnv* env, + intptr_t instance, const std::u16string& hint, OmniboxPedalId pedal_id); base::android::ScopedJavaGlobalRef<jobject> BuildHistoryClustersAction( JNIEnv* env, + intptr_t instance, const std::u16string& hint, const std::string& query); base::android::ScopedJavaGlobalRef<jobject> BuildOmniboxActionInSuggest( JNIEnv* env, + intptr_t instance, const std::u16string& hint, int action_type, const std::string& action_uri);
diff --git a/components/omnibox/browser/actions/omnibox_action_in_suggest.cc b/components/omnibox/browser/actions/omnibox_action_in_suggest.cc index add69a9..6144726 100644 --- a/components/omnibox/browser/actions/omnibox_action_in_suggest.cc +++ b/components/omnibox/browser/actions/omnibox_action_in_suggest.cc
@@ -97,8 +97,8 @@ OmniboxActionInSuggest::GetOrCreateJavaObject(JNIEnv* env) const { if (!j_omnibox_action_) { j_omnibox_action_.Reset(BuildOmniboxActionInSuggest( - env, strings_.hint, action_info.action_type(), - action_info.action_uri())); + env, reinterpret_cast<intptr_t>(this), strings_.hint, + action_info.action_type(), action_info.action_uri())); } return base::android::ScopedJavaLocalRef<jobject>(j_omnibox_action_); }
diff --git a/components/omnibox/browser/actions/omnibox_action_in_suggest.h b/components/omnibox/browser/actions/omnibox_action_in_suggest.h index 143334b7..9f603ca 100644 --- a/components/omnibox/browser/actions/omnibox_action_in_suggest.h +++ b/components/omnibox/browser/actions/omnibox_action_in_suggest.h
@@ -40,10 +40,6 @@ private: ~OmniboxActionInSuggest() override; - -#if BUILDFLAG(IS_ANDROID) - mutable base::android::ScopedJavaGlobalRef<jobject> j_omnibox_action_; -#endif }; #endif // COMPONENTS_OMNIBOX_BROWSER_ACTIONS_OMNIBOX_ACTION_IN_SUGGEST_H_
diff --git a/components/omnibox/browser/actions/omnibox_pedal.cc b/components/omnibox/browser/actions/omnibox_pedal.cc index a4e1cac6..5b2f229 100644 --- a/components/omnibox/browser/actions/omnibox_pedal.cc +++ b/components/omnibox/browser/actions/omnibox_pedal.cc
@@ -321,7 +321,8 @@ base::android::ScopedJavaLocalRef<jobject> OmniboxPedal::GetOrCreateJavaObject( JNIEnv* env) const { if (!j_omnibox_action_) { - j_omnibox_action_.Reset(BuildOmniboxPedal(env, strings_.hint, PedalId())); + j_omnibox_action_.Reset(BuildOmniboxPedal( + env, reinterpret_cast<intptr_t>(this), strings_.hint, PedalId())); } return base::android::ScopedJavaLocalRef<jobject>(j_omnibox_action_); }
diff --git a/components/omnibox/browser/actions/omnibox_pedal.h b/components/omnibox/browser/actions/omnibox_pedal.h index 969c2b6b..dbee9e1 100644 --- a/components/omnibox/browser/actions/omnibox_pedal.h +++ b/components/omnibox/browser/actions/omnibox_pedal.h
@@ -256,10 +256,6 @@ SynonymGroup verbatim_synonym_group_; std::vector<SynonymGroup> synonym_groups_; - -#if BUILDFLAG(IS_ANDROID) - mutable base::android::ScopedJavaGlobalRef<jobject> j_omnibox_action_; -#endif }; // This is a simple pedal suitable only for use by tests.
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java index 9e4cf986..7c909f6 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxAction.java
@@ -11,6 +11,8 @@ import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.NativeMethods; import org.chromium.components.omnibox.R; /** @@ -42,13 +44,30 @@ public final @NonNull String hint; /** The icon to use to decorate the Action chip. */ public final @NonNull ChipIcon icon; + /** The corresponding native instance, or 0 if the native instance is not available. */ + private long mNativeInstance; - public OmniboxAction( - @OmniboxActionId int actionId, @NonNull String hint, @Nullable ChipIcon icon) { + public OmniboxAction(@OmniboxActionId int actionId, long nativeInstance, @NonNull String hint, + @Nullable ChipIcon icon) { assert !TextUtils.isEmpty(hint); this.actionId = actionId; this.hint = hint; this.icon = icon != null ? icon : DEFAULT_ICON; + mNativeInstance = nativeInstance; + } + + @CalledByNative + private void destroy() { + mNativeInstance = 0; + } + + /** + * Report information about pedal being shown. + */ + public void recordActionShown(int position, boolean executed) { + if (mNativeInstance != 0L) { + OmniboxActionJni.get().recordActionShown(mNativeInstance, position, executed); + } } /** @@ -57,4 +76,10 @@ * @param delegate delegate capable of routing and executing variety of action-specific tasks */ public abstract void execute(@NonNull OmniboxActionDelegate delegate); + + @NativeMethods + public interface Natives { + /** Emit histograms related to the action. */ + void recordActionShown(long nativeOmniboxAction, int position, boolean executed); + } }
diff --git a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java index 9aa7945..34856b63 100644 --- a/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java +++ b/components/omnibox/browser/android/java/src/org/chromium/components/omnibox/action/OmniboxActionFactory.java
@@ -22,7 +22,8 @@ */ @CalledByNative @NonNull - OmniboxAction buildOmniboxPedal(@NonNull String hint, @OmniboxPedalId int pedalId); + OmniboxAction buildOmniboxPedal( + long instance, @NonNull String hint, @OmniboxPedalId int pedalId); /** * Create a new OmniboxActionInSuggest. @@ -35,7 +36,7 @@ */ @CalledByNative @NonNull - OmniboxAction buildActionInSuggest(@NonNull String hint, + OmniboxAction buildActionInSuggest(long instance, @NonNull String hint, /* EntityInfoProto.ActionInfo.ActionType */ int actionType, @NonNull String actionUri); /** @@ -47,7 +48,8 @@ */ @CalledByNative @NonNull - OmniboxAction buildHistoryClustersAction(@NonNull String hint, @NonNull String query); + OmniboxAction buildHistoryClustersAction( + long instance, @NonNull String hint, @NonNull String query); @NativeMethods public interface Natives {
diff --git a/components/page_image_service/image_service.cc b/components/page_image_service/image_service.cc index db536d2..eccd08a6 100644 --- a/components/page_image_service/image_service.cc +++ b/components/page_image_service/image_service.cc
@@ -48,36 +48,24 @@ class ImageService::SuggestEntityImageURLFetcher { public: SuggestEntityImageURLFetcher( - AutocompleteProviderClient* autocomplete_provider_client, + const AutocompleteSchemeClassifier& autocomplete_scheme_classifier, + mojom::ClientId client_id, const std::u16string& search_query, const std::string& entity_id) - : autocomplete_provider_client_(autocomplete_provider_client), + : autocomplete_scheme_classifier_(autocomplete_scheme_classifier), + client_id_(client_id), search_query_(base::i18n::ToLower(search_query)), - entity_id_(entity_id) { - DCHECK(autocomplete_provider_client); - } + entity_id_(entity_id) {} SuggestEntityImageURLFetcher(const SuggestEntityImageURLFetcher&) = delete; // `callback` is called with the result. - void Start(base::OnceCallback<void(const GURL&)> callback) { - const TemplateURLService* template_url_service = - autocomplete_provider_client_->GetTemplateURLService(); - if (template_url_service == nullptr) { - return std::move(callback).Run(GURL()); - } - - // We are relying on the user's consent to Sync History, which in practice - // means only Google should get URL-keyed metadata requests via Suggest. - const TemplateURL* template_url = - template_url_service->GetDefaultSearchProvider(); - if (template_url == nullptr || - template_url->GetEngineType( - template_url_service->search_terms_data()) != - SEARCH_ENGINE_GOOGLE) { - return std::move(callback).Run(GURL()); - } - - DCHECK(!callback_); + void Start(const TemplateURL* template_url, + const SearchTermsData& search_terms_data, + RemoteSuggestionsService* remote_suggestions_service, + base::OnceCallback<void(const GURL&)> callback) { + CHECK(template_url); + CHECK(remote_suggestions_service); + CHECK(!callback_); callback_ = std::move(callback); TemplateURLRef::SearchTermsArgs search_terms_args; @@ -85,14 +73,10 @@ metrics::OmniboxEventProto::JOURNEYS; search_terms_args.search_terms = search_query_; - loader_ = - autocomplete_provider_client_ - ->GetRemoteSuggestionsService(/*create_if_necessary=*/true) - ->StartSuggestionsRequest( - template_url, search_terms_args, - template_url_service->search_terms_data(), - base::BindOnce(&SuggestEntityImageURLFetcher::OnURLLoadComplete, - weak_factory_.GetWeakPtr())); + loader_ = remote_suggestions_service->StartSuggestionsRequest( + template_url, search_terms_args, search_terms_data, + base::BindOnce(&SuggestEntityImageURLFetcher::OnURLLoadComplete, + weak_factory_.GetWeakPtr())); } private: @@ -101,30 +85,40 @@ std::unique_ptr<std::string> response_body) { DCHECK_EQ(loader_.get(), source); if (!response_received) { + UmaHistogramEnumerationForClient(kBackendSuggestResultHistogramName, + PageImageServiceResult::kResponseMissing, + client_id_); return std::move(callback_).Run(GURL()); } std::string response_json = SearchSuggestionParser::ExtractJsonData( source, std::move(response_body)); if (response_json.empty()) { + UmaHistogramEnumerationForClient( + kBackendSuggestResultHistogramName, + PageImageServiceResult::kResponseMalformed, client_id_); return std::move(callback_).Run(GURL()); } auto response_data = SearchSuggestionParser::DeserializeJsonData(response_json); if (!response_data) { + UmaHistogramEnumerationForClient( + kBackendSuggestResultHistogramName, + PageImageServiceResult::kResponseMalformed, client_id_); return std::move(callback_).Run(GURL()); } - AutocompleteInput input( - search_query_, metrics::OmniboxEventProto::JOURNEYS, - autocomplete_provider_client_->GetSchemeClassifier()); + AutocompleteInput input(search_query_, metrics::OmniboxEventProto::JOURNEYS, + autocomplete_scheme_classifier_); SearchSuggestionParser::Results results; if (!SearchSuggestionParser::ParseSuggestResults( - *response_data, input, - autocomplete_provider_client_->GetSchemeClassifier(), + *response_data, input, autocomplete_scheme_classifier_, /*default_result_relevance=*/100, /*is_keyword_result=*/false, &results)) { + UmaHistogramEnumerationForClient( + kBackendSuggestResultHistogramName, + PageImageServiceResult::kResponseMalformed, client_id_); return std::move(callback_).Run(GURL()); } @@ -134,17 +128,27 @@ GURL url(result.entity_info().image_url()); if (url.is_valid() && base::i18n::ToLower(result.match_contents()) == search_query_) { + UmaHistogramEnumerationForClient(kBackendSuggestResultHistogramName, + PageImageServiceResult::kSuccess, + client_id_); return std::move(callback_).Run(std::move(url)); } } // If we didn't find any matching images, still notify the caller. if (!callback_.is_null()) { + UmaHistogramEnumerationForClient(kBackendSuggestResultHistogramName, + PageImageServiceResult::kNoImage, + client_id_); std::move(callback_).Run(GURL()); } } - const raw_ptr<AutocompleteProviderClient> autocomplete_provider_client_; + // Embedder-specific logic on how to classify schemes. + const AutocompleteSchemeClassifier& autocomplete_scheme_classifier_; + + // The id of the UI requesting the image. + mojom::ClientId client_id_; // The search query and entity ID we are searching for. const std::u16string search_query_; @@ -253,7 +257,10 @@ UmaHistogramEnumerationForClient(kBackendHistogramName, PageImageServiceBackend::kSuggest, client_id); - return FetchSuggestImage(/*search_query=*/search_metadata->search_terms, + return FetchSuggestImage(search_metadata->template_url, + template_url_service->search_terms_data(), + client_id, + /*search_query=*/search_metadata->search_terms, /*entity_id=*/"", std::move(callback)); } } @@ -275,18 +282,26 @@ std::move(callback).Run(GURL()); } -void ImageService::FetchSuggestImage(const std::u16string& search_query, +void ImageService::FetchSuggestImage(const TemplateURL* template_url, + const SearchTermsData& search_terms_data, + mojom::ClientId client_id, + const std::u16string& search_query, const std::string& entity_id, ResultCallback callback) { auto fetcher = std::make_unique<SuggestEntityImageURLFetcher>( - autocomplete_provider_client_.get(), search_query, entity_id); + autocomplete_provider_client_->GetSchemeClassifier(), client_id, + search_query, entity_id); // Use a raw pointer temporary so we can give ownership of the unique_ptr to // the callback and have a well defined SuggestEntityImageURLFetcher lifetime. auto* fetcher_raw_ptr = fetcher.get(); - fetcher_raw_ptr->Start(base::BindOnce( - &ImageService::OnSuggestImageFetched, weak_factory_.GetWeakPtr(), - std::move(fetcher), std::move(callback))); + fetcher_raw_ptr->Start( + template_url, search_terms_data, + autocomplete_provider_client_->GetRemoteSuggestionsService( + /*create_if_necessary=*/true), + base::BindOnce(&ImageService::OnSuggestImageFetched, + weak_factory_.GetWeakPtr(), std::move(fetcher), + std::move(callback))); } void ImageService::OnSuggestImageFetched( @@ -401,7 +416,7 @@ if (iter == decisions.end()) { UmaHistogramEnumerationForClient( kBackendOptimizationGuideResultHistogramName, - PageImageServiceOptimizationGuideResult::kDecisionMissing, client_id); + PageImageServiceResult::kResponseMissing, client_id); return FulfillAllCallbacks(std::move(matching_callbacks), GURL()); } @@ -411,13 +426,13 @@ optimization_guide::OptimizationGuideDecision::kTrue) { UmaHistogramEnumerationForClient( kBackendOptimizationGuideResultHistogramName, - PageImageServiceOptimizationGuideResult::kNoImage, client_id); + PageImageServiceResult::kNoImage, client_id); return FulfillAllCallbacks(std::move(matching_callbacks), GURL()); } if (!decision.metadata.any_metadata().has_value()) { UmaHistogramEnumerationForClient( kBackendOptimizationGuideResultHistogramName, - PageImageServiceOptimizationGuideResult::kResponseMalformed, client_id); + PageImageServiceResult::kResponseMalformed, client_id); return FulfillAllCallbacks(std::move(matching_callbacks), GURL()); } @@ -427,7 +442,7 @@ if (!parsed_any) { UmaHistogramEnumerationForClient( kBackendOptimizationGuideResultHistogramName, - PageImageServiceOptimizationGuideResult::kResponseMalformed, client_id); + PageImageServiceResult::kResponseMalformed, client_id); return FulfillAllCallbacks(std::move(matching_callbacks), GURL()); } @@ -439,16 +454,16 @@ if (image_url.is_valid()) { UmaHistogramEnumerationForClient( kBackendOptimizationGuideResultHistogramName, - PageImageServiceOptimizationGuideResult::kSuccess, client_id); + PageImageServiceResult::kSuccess, client_id); return FulfillAllCallbacks(std::move(matching_callbacks), image_url); } } } // Fail if we can't find any. - UmaHistogramEnumerationForClient( - kBackendOptimizationGuideResultHistogramName, - PageImageServiceOptimizationGuideResult::kResponseMalformed, client_id); + UmaHistogramEnumerationForClient(kBackendOptimizationGuideResultHistogramName, + PageImageServiceResult::kResponseMalformed, + client_id); return FulfillAllCallbacks(std::move(matching_callbacks), GURL()); }
diff --git a/components/page_image_service/image_service.h b/components/page_image_service/image_service.h index e9f86fd..47312b0 100644 --- a/components/page_image_service/image_service.h +++ b/components/page_image_service/image_service.h
@@ -37,6 +37,8 @@ public: using ResultCallback = base::OnceCallback<void(const GURL& image_url)>; + // TODO(crbug.com/1449377): Replace AutocompleteProviderClient with individual + // services to make the Suggest backend testable. ImageService( std::unique_ptr<AutocompleteProviderClient> autocomplete_provider_client, optimization_guide::NewOptimizationGuideDecider* opt_guide, @@ -84,7 +86,10 @@ // Fetches an image from Suggest appropriate for `search_query` and // `entity_id`, returning the result asynchronously to `callback`. - void FetchSuggestImage(const std::u16string& search_query, + void FetchSuggestImage(const TemplateURL* template_url, + const SearchTermsData& search_terms_data, + mojom::ClientId client_id, + const std::u16string& search_query, const std::string& entity_id, ResultCallback callback);
diff --git a/components/page_image_service/image_service_unittest.cc b/components/page_image_service/image_service_unittest.cc index 9ed82cfe..f7f6919 100644 --- a/components/page_image_service/image_service_unittest.cc +++ b/components/page_image_service/image_service_unittest.cc
@@ -272,11 +272,11 @@ // Test histograms with literal names to validate client-sliced names. EXPECT_EQ(histogram_tester_.GetBucketCount( "PageImageService.Backend.OptimizationGuide.Result", - PageImageServiceOptimizationGuideResult::kSuccess), + PageImageServiceResult::kSuccess), 2); EXPECT_EQ(histogram_tester_.GetBucketCount( "PageImageService.Backend.OptimizationGuide.Result.Journeys", - PageImageServiceOptimizationGuideResult::kSuccess), + PageImageServiceResult::kSuccess), 2); }
diff --git a/components/page_image_service/metrics_util.h b/components/page_image_service/metrics_util.h index f77f94f..b4238d4a 100644 --- a/components/page_image_service/metrics_util.h +++ b/components/page_image_service/metrics_util.h
@@ -15,6 +15,8 @@ constexpr char kBackendHistogramName[] = "PageImageService.Backend"; constexpr char kBackendOptimizationGuideResultHistogramName[] = "PageImageService.Backend.OptimizationGuide.Result"; +constexpr char kBackendSuggestResultHistogramName[] = + "PageImageService.Backend.Suggest.Result"; constexpr char kConsentSuccessHistogramName[] = "PageImageService.ConsentSuccess"; @@ -27,9 +29,9 @@ }; // Used in UMA. Must not be renumbered, and must be kept in sync with enums.xml. -enum class PageImageServiceOptimizationGuideResult { +enum class PageImageServiceResult { kSuccess = 0, - kDecisionMissing = 1, + kResponseMissing = 1, kNoImage = 2, kResponseMalformed = 3, kMaxValue = kResponseMalformed,
diff --git a/components/page_info/core/about_this_site_service_unittest.cc b/components/page_info/core/about_this_site_service_unittest.cc index c1b477f..da803e1 100644 --- a/components/page_info/core/about_this_site_service_unittest.cc +++ b/components/page_info/core/about_this_site_service_unittest.cc
@@ -110,9 +110,9 @@ AboutThisSiteService* service() { return service_.get(); } private: - raw_ptr<MockAboutThisSiteServiceClient> client_; - std::unique_ptr<AboutThisSiteService> service_; std::unique_ptr<TemplateURLService> template_url_service_; + std::unique_ptr<AboutThisSiteService> service_; + raw_ptr<MockAboutThisSiteServiceClient> client_; }; // Tests that correct proto messages are accepted.
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc index 383df5a..6d28cd8b 100644 --- a/components/policy/core/common/cloud/cloud_policy_client.cc +++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -717,7 +717,7 @@ auto config = std::make_unique<EncryptedReportingJobConfiguration>( GetURLLoaderFactory(), DMAuth::FromDMToken(dm_token()), service()->configuration()->GetEncryptedReportingServerUrl(), - std::move(merging_payload), dm_token(), client_id(), + std::move(merging_payload), this, base::BindOnce(&CloudPolicyClient::OnEncryptedReportUploadCompleted, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); if (context.has_value()) {
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc index 9c647fa..764c4e6f6 100644 --- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc +++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.cc
@@ -141,18 +141,21 @@ DMAuth auth_data, const std::string& server_url, base::Value::Dict merging_payload, - const std::string& dm_token, - const std::string& client_id, + CloudPolicyClient* cloud_policy_client, UploadCompleteCallback complete_cb) : ReportingJobConfigurationBase(TYPE_UPLOAD_ENCRYPTED_REPORT, factory, std::move(auth_data), server_url, std::move(complete_cb)) { - // Init common payload fields. - // TODO(b/237809917): Init using `InitializePayloadWithoutDeviceInfo` when - // backend is ready to support unmanaged devices. - InitializePayloadWithDeviceInfo(dm_token, client_id); + if (cloud_policy_client) { + // Payload for managed device + InitializePayloadWithDeviceInfo(cloud_policy_client->dm_token(), + cloud_policy_client->client_id()); + } else { + // Payload for unmanaged device + InitializePayloadWithoutDeviceInfo(); + } // Merge it into the base class payload. payload_.Merge(std::move(merging_payload)); // Retrieve priorities and figure out maximum sequence id for each.
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h index 5f5e9add..c14bfaad 100644 --- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h +++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration.h
@@ -86,8 +86,7 @@ DMAuth auth_data, const std::string& server_url, base::Value::Dict merging_payload, - const std::string& dm_token, - const std::string& client_id, + CloudPolicyClient* cloud_policy_client, UploadCompleteCallback complete_cb); ~EncryptedReportingJobConfiguration() override;
diff --git a/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc b/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc index e30245ae..82401ef 100644 --- a/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc +++ b/components/policy/core/common/cloud/encrypted_reporting_job_configuration_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "components/policy/core/common/cloud/encrypted_reporting_job_configuration.h" +#include <cstddef> #include "base/base64.h" #include "base/functional/callback_helpers.h" @@ -16,12 +17,12 @@ #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/core/common/cloud/dm_auth.h" +#include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/reporting/proto/synced/record.pb.h" #include "components/reporting/proto/synced/record_constants.pb.h" #include "components/version_info/version_info.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" -#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -208,6 +209,9 @@ shared_url_loader_factory_ = base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( &url_loader_factory_); + // Setup the cloud policy client with a default dm token and client id. + client_.SetDMToken(kDmToken); + client_.client_id_ = kClientId; } TestUpload CreateTestUpload(const base::Value& record_value) { @@ -218,9 +222,9 @@ test_upload.completion_cb = std::make_unique<StrictMock<MockCompleteCb>>(); test_upload.configuration = std::make_unique<EncryptedReportingJobConfiguration>( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), kServerUrl, RequestPayloadBuilder().AddRecord(record_value).Build(), - kDmToken, kClientId, + &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(test_upload.completion_cb.get()))); return test_upload; @@ -285,6 +289,8 @@ base::test::SingleThreadTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + policy::MockCloudPolicyClient client_; + #if BUILDFLAG(IS_CHROMEOS_ASH) ash::system::ScopedFakeStatisticsProvider fake_statistics_provider_; class ScopedFakeSerialNumber { @@ -313,8 +319,8 @@ StrictMock<MockCompleteCb> completion_cb; EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - RequestPayloadBuilder().Build(), kDmToken, kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, RequestPayloadBuilder().Build(), &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); auto* payload = GetPayload(&configuration); const base::Value::Dict& payload_dict = payload->GetDict(); @@ -346,6 +352,54 @@ version_info::GetVersionNumber()); } +// Validates that the non-Record portions of the payload are generated +// correctly on unmanaged devices and do not contain any device info. +TEST_F(EncryptedReportingJobConfigurationTest, + ValidatePayloadWithoutDeviceInfo) { + StrictMock<MockCompleteCb> completion_cb; + EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); + + EncryptedReportingJobConfiguration configuration( + shared_url_loader_factory_, DMAuth::NoAuth(), kServerUrl, + RequestPayloadBuilder().Build(), /*cloud_policy_client=*/nullptr, + base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); + auto* payload = GetPayload(&configuration); + ASSERT_THAT(payload, NotNull()); + const base::Value::Dict& payload_dict = payload->GetDict(); + + // Expect that the payload does not contain any device info + EXPECT_THAT(payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::DeviceDictionaryBuilder:: + GetNamePath()), + IsNull()); + EXPECT_THAT(payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::DeviceDictionaryBuilder:: + GetClientIdPath()), + IsNull()); + EXPECT_THAT(payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::DeviceDictionaryBuilder:: + GetDMTokenPath()), + IsNull()); + EXPECT_THAT(payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::DeviceDictionaryBuilder:: + GetOSPlatformPath()), + IsNull()); + EXPECT_THAT(payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::DeviceDictionaryBuilder:: + GetOSVersionPath()), + IsNull()); + EXPECT_THAT(payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::BrowserDictionaryBuilder:: + GetMachineUserPath()), + IsNull()); + + // Should still contain chrome version since that's not device info + EXPECT_EQ(*payload_dict.FindStringByDottedPath( + ReportingJobConfigurationBase::BrowserDictionaryBuilder:: + GetChromeVersionPath()), + version_info::GetVersionNumber()); +} + // Ensures that records are added correctly and that the payload is Base64 // encoded. TEST_F(EncryptedReportingJobConfigurationTest, CorrectlyAddEncryptedRecord) { @@ -355,9 +409,9 @@ EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - RequestPayloadBuilder().AddRecord(record_value).Build(), kDmToken, - kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, RequestPayloadBuilder().AddRecord(record_value).Build(), + &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); base::Value::List* record_list = nullptr; @@ -388,8 +442,8 @@ StrictMock<MockCompleteCb> completion_cb; EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - builder.Build(), kDmToken, kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, builder.Build(), &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); base::Value::List* record_list = nullptr; @@ -413,8 +467,8 @@ StrictMock<MockCompleteCb> completion_cb; EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - builder.Build(), kDmToken, kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, builder.Build(), &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); base::Value::List* record_list = nullptr; @@ -439,8 +493,8 @@ StrictMock<MockCompleteCb> completion_cb; EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - builder.Build(), kDmToken, kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, builder.Build(), &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); base::Value::List* record_list = nullptr; @@ -461,8 +515,8 @@ StrictMock<MockCompleteCb> completion_cb; EXPECT_CALL(completion_cb, Call(_, _, _, _)).Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - RequestPayloadBuilder().Build(), kDmToken, kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, RequestPayloadBuilder().Build(), &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); const std::string kTestKey = "device.name"; @@ -533,8 +587,8 @@ testing::Eq(absl::nullopt))) .Times(1); EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - RequestPayloadBuilder().Build(), kDmToken, kClientId, + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, RequestPayloadBuilder().Build(), &client_, base::BindOnce(&MockCompleteCb::Call, base::Unretained(&completion_cb))); configuration.OnURLLoadComplete(&job, net::ERR_CONNECTION_RESET, 0 /* ignored */, ""); @@ -694,8 +748,8 @@ TEST_F(EncryptedReportingJobConfigurationTest, UmaName) { EncryptedReportingJobConfiguration configuration( - shared_url_loader_factory_, DMAuth::FromDMToken(kDmToken), kServerUrl, - RequestPayloadBuilder().Build(), kDmToken, kClientId, base::DoNothing()); + shared_url_loader_factory_, DMAuth::FromDMToken(client_.dm_token()), + kServerUrl, RequestPayloadBuilder().Build(), &client_, base::DoNothing()); EXPECT_EQ(configuration.GetUmaName(), "Browser.ERP.UploadEncryptedReport"); }
diff --git a/components/policy/core/common/cloud/reporting_job_configuration_base.cc b/components/policy/core/common/cloud/reporting_job_configuration_base.cc index e4343b3..f28cb718 100644 --- a/components/policy/core/common/cloud/reporting_job_configuration_base.cc +++ b/components/policy/core/common/cloud/reporting_job_configuration_base.cc
@@ -122,8 +122,9 @@ browser_dictionary.Set(kBrowserId, browser_id.AsUTF8Unsafe()); } - if (include_device_info) + if (include_device_info) { browser_dictionary.Set(kMachineUser, GetOSUsername()); + } browser_dictionary.Set(kChromeVersion, version_info::GetVersionNumber()); return browser_dictionary;
diff --git a/components/remote_cocoa/app_shim/BUILD.gn b/components/remote_cocoa/app_shim/BUILD.gn index 0625f07f..4aa9876 100644 --- a/components/remote_cocoa/app_shim/BUILD.gn +++ b/components/remote_cocoa/app_shim/BUILD.gn
@@ -64,6 +64,7 @@ defines = [ "REMOTE_COCOA_APP_SHIM_IMPLEMENTATION" ] deps = [ "//base", + "//base:base_arc", "//base:i18n", "//components/crash/core/common", "//components/remote_cocoa/common:mojo",
diff --git a/components/remote_cocoa/app_shim/bridged_content_view.mm b/components/remote_cocoa/app_shim/bridged_content_view.mm index a7dd841..cb25d4d 100644 --- a/components/remote_cocoa/app_shim/bridged_content_view.mm +++ b/components/remote_cocoa/app_shim/bridged_content_view.mm
@@ -6,6 +6,7 @@ #include <limits> +#include "base/apple/owned_objc.h" #include "base/check_op.h" #import "base/mac/foundation_util.h" #import "base/mac/mac_util.h" @@ -326,24 +327,26 @@ if (remote_cocoa::IsNSToolbarFullScreenWindow(target)) { // We are in immersive fullscreen. This event is generated from the overlay // window which sits atop the toolbar. Convert the event location to the - // content view coordiate, which should have the same bounds as the overlay + // content view coordinate, which should have the same bounds as the overlay // window. // This is to handle the case that `target` may contain the titlebar which // the overlay window does not contain. Without this, buttons in the toolbar // are not clickable when the titlebar is revealed. - event_location = MovePointToView([theEvent locationInWindow], source, self); + event_location = MovePointToView(theEvent.locationInWindow, source, self); } else { event_location = - MovePointToWindow([theEvent locationInWindow], source, target); + MovePointToWindow(theEvent.locationInWindow, source, target); } [self updateTooltipIfRequiredAt:event_location]; if (isScrollEvent) { - auto event = std::make_unique<ui::ScrollEvent>(theEvent); + auto event = + std::make_unique<ui::ScrollEvent>(base::apple::OwnedNSEvent(theEvent)); event->set_location(event_location); _bridge->host()->OnScrollEvent(std::move(event)); } else { - auto event = std::make_unique<ui::MouseEvent>(theEvent); + auto event = + std::make_unique<ui::MouseEvent>(base::apple::OwnedNSEvent(theEvent)); event->set_location(event_location); _bridge->host()->OnMouseEvent(std::move(event)); } @@ -431,7 +434,7 @@ if (!_hasUnhandledKeyDownEvent) return NO; - ui::KeyEvent event(_keyDownEvent); + ui::KeyEvent event((base::apple::OwnedNSEvent(_keyDownEvent))); [self handleKeyEvent:&event]; _hasUnhandledKeyDownEvent = NO; return event.handled(); @@ -459,7 +462,7 @@ // key events! if (NSApp.currentEvent.type == NSEventTypeKeyDown || NSApp.currentEvent.type == NSEventTypeKeyUp) { - event.SetNativeEvent(NSApp.currentEvent); + event.SetNativeEvent(base::apple::OwnedNSEvent(NSApp.currentEvent)); } if ([self dispatchKeyEventToMenuController:&event]) @@ -644,7 +647,8 @@ return; DCHECK([theEvent type] != NSEventTypeScrollWheel); - auto event = std::make_unique<ui::MouseEvent>(theEvent); + auto event = + std::make_unique<ui::MouseEvent>(base::apple::OwnedNSEvent(theEvent)); [self adjustUiEventLocation:event.get() fromNativeEvent:theEvent]; // Aura updates tooltips with the help of aura::Window::AddPreTargetHandler(). @@ -834,7 +838,7 @@ } - (void)keyUp:(NSEvent*)theEvent { - ui::KeyEvent event(theEvent); + ui::KeyEvent event((base::apple::OwnedNSEvent(theEvent))); [self handleKeyEvent:&event]; } @@ -846,7 +850,7 @@ // is also sent, so we should drop this one. See https://crbug.com/889618 return; } - ui::KeyEvent event(theEvent); + ui::KeyEvent event((base::apple::OwnedNSEvent(theEvent))); [self handleKeyEvent:&event]; } @@ -854,7 +858,8 @@ if (!_bridge) return; - auto event = std::make_unique<ui::ScrollEvent>(theEvent); + auto event = + std::make_unique<ui::ScrollEvent>(base::apple::OwnedNSEvent(theEvent)); [self adjustUiEventLocation:event.get() fromNativeEvent:theEvent]; // Aura updates tooltips with the help of aura::Window::AddPreTargetHandler(). @@ -880,13 +885,14 @@ swipeDetails.set_device_type(ui::GestureDeviceType::DEVICE_TOUCHPAD); swipeDetails.set_touch_points(3); - gfx::PointF location = ui::EventLocationFromNative(event); + base::apple::OwnedNSEvent owned_event(event); + gfx::PointF location = ui::EventLocationFromNative(owned_event); // Note this uses the default unique_touch_event_id of 0 (Swipe events do not // support -[NSEvent eventNumber]). This doesn't seem like a real omission // because the three-finger swipes are instant and can't be tracked anyway. auto gestureEvent = std::make_unique<ui::GestureEvent>( - location.x(), location.y(), ui::EventFlagsFromNative(event), - ui::EventTimeFromNative(event), swipeDetails); + location.x(), location.y(), ui::EventFlagsFromNative(owned_event), + ui::EventTimeFromNative(owned_event), swipeDetails); _bridge->host()->OnGestureEvent(std::move(gestureEvent)); } @@ -894,8 +900,8 @@ if (!_bridge) return; - const gfx::Point locationInContent = - gfx::ToFlooredPoint(ui::EventLocationFromNative(theEvent)); + const gfx::Point locationInContent = gfx::ToFlooredPoint( + ui::EventLocationFromNative(base::apple::OwnedNSEvent(theEvent))); bool foundWord = false; gfx::DecoratedText decoratedWord;
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm index 6a27c026..d1af0b2a 100644 --- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm +++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
@@ -861,7 +861,8 @@ return event; } - std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event); + std::unique_ptr<ui::Event> ui_event = + ui::EventFromNative(base::apple::OwnedNSEvent(event)); bool event_handled = false; weak_ptr->host_->DispatchMonitorEvent(std::move(ui_event), &event_handled);
diff --git a/components/services/storage/BUILD.gn b/components/services/storage/BUILD.gn index 4cc4724..9bb4f258 100644 --- a/components/services/storage/BUILD.gn +++ b/components/services/storage/BUILD.gn
@@ -235,6 +235,10 @@ "//third_party/sqlite", ] + if (is_ios) { + deps += [ "//components/test:service_worker_test_bundle_data" ] + } + data = [ "//components/services/storage/test_data/" ] }
diff --git a/components/supervised_user/core/browser/api_access_token_fetcher.cc b/components/supervised_user/core/browser/api_access_token_fetcher.cc index 6c84b75..f069e09 100644 --- a/components/supervised_user/core/browser/api_access_token_fetcher.cc +++ b/components/supervised_user/core/browser/api_access_token_fetcher.cc
@@ -5,16 +5,16 @@ #include "components/supervised_user/core/browser/api_access_token_fetcher.h" #include <memory> +#include <string> #include <utility> #include "base/functional/bind.h" -#include "base/no_destructor.h" #include "base/types/expected.h" #include "components/signin/public/identity_manager/access_token_fetcher.h" #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h" -#include "google_apis/gaia/gaia_constants.h" +#include "components/supervised_user/core/browser/fetcher_config.h" #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_access_token_manager.h" @@ -34,13 +34,17 @@ ApiAccessTokenFetcher::ApiAccessTokenFetcher( signin::IdentityManager& identity_manager, + const FetcherConfig& fetcher_config, Consumer consumer) : consumer_(std::move(consumer)) { + OAuth2AccessTokenManager::ScopeSet scope_set( + {std::string(fetcher_config.oauth2_scope)}); // base::Unretained(.) is safe, because no extra on-destroyed semantics are // needed and this instance must outlive the callback execution. primary_account_access_token_fetcher_ = std::make_unique<signin::PrimaryAccountAccessTokenFetcher>( - "family_info_fetcher", &identity_manager, Scopes(), + /*oauth_consumer_name=*/"supervised_user_fetcher", &identity_manager, + scope_set, base::BindOnce(&ApiAccessTokenFetcher::OnAccessTokenFetchComplete, base::Unretained(this)), signin::PrimaryAccountAccessTokenFetcher::Mode::kWaitUntilAvailable, @@ -53,10 +57,4 @@ signin::AccessTokenInfo access_token_info) { std::move(consumer_).Run(ToSingleReturnValue(error, access_token_info)); } - -const OAuth2AccessTokenManager::ScopeSet& ApiAccessTokenFetcher::Scopes() { - static auto nonce = base::NoDestructor<OAuth2AccessTokenManager::ScopeSet>{ - {GaiaConstants::kKidFamilyReadonlyOAuth2Scope}}; - return *nonce; -} } // namespace supervised_user
diff --git a/components/supervised_user/core/browser/api_access_token_fetcher.h b/components/supervised_user/core/browser/api_access_token_fetcher.h index 8985d2fa..bd12d50 100644 --- a/components/supervised_user/core/browser/api_access_token_fetcher.h +++ b/components/supervised_user/core/browser/api_access_token_fetcher.h
@@ -13,7 +13,7 @@ #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/primary_account_access_token_fetcher.h" -#include "google_apis/gaia/gaia_constants.h" +#include "components/supervised_user/core/browser/fetcher_config.h" #include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/oauth2_access_token_manager.h" @@ -31,6 +31,7 @@ // Non copyable. ApiAccessTokenFetcher() = delete; explicit ApiAccessTokenFetcher(signin::IdentityManager& identity_manager, + const FetcherConfig& fetcher_config, Consumer consumer); ApiAccessTokenFetcher(const ApiAccessTokenFetcher&) = delete; ApiAccessTokenFetcher& operator=(const ApiAccessTokenFetcher&) = delete; @@ -39,7 +40,6 @@ private: void OnAccessTokenFetchComplete(GoogleServiceAuthError error, signin::AccessTokenInfo access_token_info); - static const OAuth2AccessTokenManager::ScopeSet& Scopes(); Consumer consumer_; std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher> primary_account_access_token_fetcher_;
diff --git a/components/supervised_user/core/browser/api_access_token_fetcher_unittest.cc b/components/supervised_user/core/browser/api_access_token_fetcher_unittest.cc index 40926084..a3e8876 100644 --- a/components/supervised_user/core/browser/api_access_token_fetcher_unittest.cc +++ b/components/supervised_user/core/browser/api_access_token_fetcher_unittest.cc
@@ -14,6 +14,7 @@ #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/identity_test_environment.h" +#include "components/supervised_user/core/browser/fetcher_config.h" #include "google_apis/gaia/google_service_auth_error.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -32,9 +33,9 @@ using ::signin::AccessTokenInfo; using ::signin::ConsentLevel; using ::signin::IdentityTestEnvironment; -using ::testing::Test; -class ApiAccessTokenFetcherTest : public Test { +class ApiAccessTokenFetcherTest + : public ::testing::TestWithParam<FetcherConfig> { protected: // A pinhole class that allows to verify the fetch result. class Receiver { @@ -56,11 +57,12 @@ IdentityTestEnvironment identity_test_env_; }; -TEST_F(ApiAccessTokenFetcherTest, ReadToken) { +TEST_P(ApiAccessTokenFetcherTest, ReadToken) { AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( "bob@example.com", ConsentLevel::kSignin); Receiver receiver; ApiAccessTokenFetcher service(*identity_test_env_.identity_manager(), + /*fetcher_config=*/GetParam(), receiver.Receive()); identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( @@ -69,11 +71,12 @@ EXPECT_EQ(receiver.Get().value().token, "expected_access_token"); } -TEST_F(ApiAccessTokenFetcherTest, AuthError) { +TEST_P(ApiAccessTokenFetcherTest, AuthError) { AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( "bob@example.com", ConsentLevel::kSignin); Receiver receiver; ApiAccessTokenFetcher service(*identity_test_env_.identity_manager(), + /*fetcher_config=*/GetParam(), receiver.Receive()); identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithError( @@ -84,5 +87,10 @@ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS); } +INSTANTIATE_TEST_SUITE_P(ApiAccessTokenFetcherTest, + ApiAccessTokenFetcherTest, + ::testing::Values(kClassifyUrlConfig, + kListFamilyMembersConfig)); + } // namespace } // namespace supervised_user
diff --git a/components/supervised_user/core/browser/fetcher_config.cc b/components/supervised_user/core/browser/fetcher_config.cc index 31e5a3a..c95ac6d 100644 --- a/components/supervised_user/core/browser/fetcher_config.cc +++ b/components/supervised_user/core/browser/fetcher_config.cc
@@ -7,14 +7,53 @@ #include <string> #include "base/notreached.h" +#include "net/http/http_request_headers.h" #include "net/traffic_annotation/network_traffic_annotation.h" namespace supervised_user { namespace annotations { + +net::NetworkTrafficAnnotationTag ClassifyUrlTag() { + return net::DefineNetworkTrafficAnnotation("supervised_user_classify_url", + R"( +semantics { + sender: "Supervised Users" + description: + "Checks whether a given URL (or set of URLs) is considered safe by " + "a Google Family Link web restrictions API." + trigger: + "If the parent enabled this feature for the child account, this is " + "sent for every navigation." + data: + "An OAuth2 access token identifying and authenticating the " + "Google account, and the URL to be checked." + destination: GOOGLE_OWNED_SERVICE + internal { + contacts { + email: "chrome-kids-eng@google.com" + } + } + user_data { + type: NONE + } + last_reviewed: "2023-05-15" +} +policy { + cookies_allowed: NO + setting: + "This feature is only used in child accounts and cannot be " + "disabled by settings. Parent accounts can disable it in the " + "family dashboard." + policy_exception_justification: + "Enterprise admins don't have control over this feature " + "because it can't be enabled on enterprise environments." + })"); +} + net::NetworkTrafficAnnotationTag ListFamilyMembersTag() { return net::DefineNetworkTrafficAnnotation( - "kids_chrome_management_list_family_members", + "supervised_user_list_family_members", R"( semantics { sender: "Supervised Users" @@ -56,7 +95,9 @@ std::string FetcherConfig::GetHttpMethod() const { switch (method) { case Method::kGet: - return "GET"; + return net::HttpRequestHeaders::kGetMethod; + case Method::kPost: + return net::HttpRequestHeaders::kPostMethod; default: NOTREACHED_NORETURN(); }
diff --git a/components/supervised_user/core/browser/fetcher_config.h b/components/supervised_user/core/browser/fetcher_config.h index c7bb7aa..d6bb5fa4 100644 --- a/components/supervised_user/core/browser/fetcher_config.h +++ b/components/supervised_user/core/browser/fetcher_config.h
@@ -9,6 +9,7 @@ #include "base/memory/raw_ptr.h" #include "base/strings/string_piece.h" +#include "google_apis/gaia/gaia_constants.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "url/gurl.h" @@ -16,13 +17,13 @@ namespace annotations { // Traffic annotations can only live in cc/mm files. +net::NetworkTrafficAnnotationTag ClassifyUrlTag(); net::NetworkTrafficAnnotationTag ListFamilyMembersTag(); } // namespace annotations // Configuration bundle for the ProtoFetcher. struct FetcherConfig { - // TODO(b/276898959): add kPost option. - enum class Method { kGet }; + enum class Method { kUndefined, kGet, kPost }; // Primary endpoint of the fetcher. base::StringPiece service_endpoint{ @@ -33,19 +34,33 @@ // examples. base::StringPiece service_path; + // The OAuth 2.0 permission scope to request the authorization token. + base::StringPiece oauth2_scope; + // HTTP method used to communicate with the service. - Method method; + const Method method = Method::kUndefined; // Basename for histograms base::StringPiece histogram_basename; - net::NetworkTrafficAnnotationTag (*traffic_annotation)(); + net::NetworkTrafficAnnotationTag (*const traffic_annotation)() = nullptr; std::string GetHttpMethod() const; }; +constexpr FetcherConfig kClassifyUrlConfig = { + .service_path = "people/me:classifyUrl", + // TODO(b/284523446): Refer to GaiaConstants rather than literal. + .oauth2_scope = "https://www.googleapis.com/auth/kid.permission", + .method = FetcherConfig::Method::kPost, + .histogram_basename = "FamilyLinkUser.ClassifyUrlRequest", + .traffic_annotation = annotations::ClassifyUrlTag, +}; + constexpr FetcherConfig kListFamilyMembersConfig{ .service_path = "families/mine/members", + // TODO(b/284523446): Refer to GaiaConstants rather than literal. + .oauth2_scope = "https://www.googleapis.com/auth/kid.family.readonly", .method = FetcherConfig::Method::kGet, .histogram_basename = "Signin.ListFamilyMembersRequest", .traffic_annotation = annotations::ListFamilyMembersTag,
diff --git a/components/supervised_user/core/browser/proto/kidschromemanagement_messages.proto b/components/supervised_user/core/browser/proto/kidschromemanagement_messages.proto index eca427b..2eefda3 100644 --- a/components/supervised_user/core/browser/proto/kidschromemanagement_messages.proto +++ b/components/supervised_user/core/browser/proto/kidschromemanagement_messages.proto
@@ -37,15 +37,15 @@ } message ClassifyUrlRequest { - // Must be "me". Required. - optional string person_id = 1; + // Must be "me". + optional string person_id = 2; - // The URL to be classified. Required. - optional string url = 2; + // The URL to be classified. + optional string url = 3; - // Region_code is a 2-letter ISO 3166-1 code. Required. + // region_code is a 2-letter ISO 3166-1 code. // When set, uses specific logic to classify URLs for that region. - optional string region_code = 3; + optional string region_code = 4; } message ClassifyUrlResponse { @@ -59,8 +59,5 @@ RESTRICTED = 2; } - // URL classification. Required. - optional DisplayClassification display_classification = 1; - - // Next id: 2 + optional DisplayClassification display_classification = 2; }
diff --git a/components/supervised_user/core/browser/proto_fetcher.cc b/components/supervised_user/core/browser/proto_fetcher.cc index 90dff2a..fcfdc26 100644 --- a/components/supervised_user/core/browser/proto_fetcher.cc +++ b/components/supervised_user/core/browser/proto_fetcher.cc
@@ -31,6 +31,7 @@ #include "services/network/public/cpp/resource_request.h" #include "services/network/public/cpp/simple_url_loader.h" #include "services/network/public/mojom/url_response_head.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/protobuf/src/google/protobuf/message_lite.h" #include "url/gurl.h" @@ -99,14 +100,13 @@ .Resolve(base::StrCat({config.service_path, "?", kSystemParameters})); } -// TODO(b/276898959): Support payload for POST requests. std::unique_ptr<network::SimpleURLLoader> InitializeSimpleUrlLoader( const signin::AccessTokenInfo access_token_info, const FetcherConfig& fetcher_config, - const GURL& url) { + const absl::optional<std::string>& payload) { std::unique_ptr<ResourceRequest> resource_request = std::make_unique<ResourceRequest>(); - resource_request->url = url; + resource_request->url = CreateRequestUrl(fetcher_config); resource_request->method = fetcher_config.GetHttpMethod(); resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; resource_request->headers.SetHeader( @@ -115,6 +115,12 @@ std::unique_ptr<network::SimpleURLLoader> simple_url_loader = network::SimpleURLLoader::Create(std::move(resource_request), fetcher_config.traffic_annotation()); + + if (payload.has_value()) { + simple_url_loader->AttachStringForUpload(*payload, + "application/x-protobuf"); + } + simple_url_loader->SetRetryOptions( kNumFamilyInfoFetcherRetries, network::SimpleURLLoader::RETRY_ON_NETWORK_CHANGE); @@ -139,7 +145,7 @@ Callback callback) : payload_(request.SerializeAsString()), config_(fetcher_config) { access_token_fetcher_ = std::make_unique<ApiAccessTokenFetcher>( - identity_manager, + identity_manager, fetcher_config, BindOnce(&FetcherImpl::OnAccessTokenFetchComplete, Unretained(this), url_loader_factory, std::move(callback))); // Unretained(.) is safe because `this` @@ -205,9 +211,8 @@ return; } - // TODO(b/276898959): add optional payload for POST requests. simple_url_loader_ = InitializeSimpleUrlLoader( - access_token.value(), config_, CreateRequestUrl(config_)); + access_token.value(), config_, GetRequestPayload()); simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie( url_loader_factory.get(), @@ -241,11 +246,25 @@ std::move(response)); } + // Returns payload when it's eligible for the request type. + absl::optional<std::string> GetRequestPayload() const { + if (config_.method == FetcherConfig::Method::kGet) { + CHECK(payload_.empty()) << "Unexpected payload in GET request"; + return absl::nullopt; + } + return payload_; + } + std::unique_ptr<ApiAccessTokenFetcher> access_token_fetcher_; std::unique_ptr<network::SimpleURLLoader> simple_url_loader_; const std::string payload_; const FetcherConfig config_; }; + +using ClassifyUrlFetcher = + ProtoFetcher<kids_chrome_management::ClassifyUrlResponse>; +using ListFamilyMembersFetcher = + ProtoFetcher<kids_chrome_management::ListFamilyMembersResponse>; } // namespace // Main constructor, referenced by the rest. @@ -367,12 +386,22 @@ } // Fetcher factories. -std::unique_ptr<ProtoFetcher<kids_chrome_management::ListFamilyMembersResponse>> -FetchListFamilyMembers( +std::unique_ptr<ClassifyUrlFetcher> ClassifyURL( IdentityManager& identity_manager, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, - ProtoFetcher<kids_chrome_management::ListFamilyMembersResponse>::Callback - callback, + const kids_chrome_management::ClassifyUrlRequest& request, + ClassifyUrlFetcher::Callback callback, + const FetcherConfig& config) { + return std::make_unique< + FetcherImpl<kids_chrome_management::ClassifyUrlResponse>>( + identity_manager, url_loader_factory, request, config, + std::move(callback)); +} + +std::unique_ptr<ListFamilyMembersFetcher> FetchListFamilyMembers( + IdentityManager& identity_manager, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + ListFamilyMembersFetcher::Callback callback, const FetcherConfig& config) { return std::make_unique< FetcherImpl<kids_chrome_management::ListFamilyMembersResponse>>(
diff --git a/components/supervised_user/core/browser/proto_fetcher.h b/components/supervised_user/core/browser/proto_fetcher.h index dd4d66d..2381c7c 100644 --- a/components/supervised_user/core/browser/proto_fetcher.h +++ b/components/supervised_user/core/browser/proto_fetcher.h
@@ -142,6 +142,15 @@ callback, const FetcherConfig& config = kListFamilyMembersConfig); -} // namespace supervised_user +// Creates a disposable instance of an access token consumer that will classify +// the URL for supervised user. +std::unique_ptr<ProtoFetcher<kids_chrome_management::ClassifyUrlResponse>> +ClassifyURL(signin::IdentityManager& identity_manager, + scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, + const kids_chrome_management::ClassifyUrlRequest& request, + ProtoFetcher<kids_chrome_management::ClassifyUrlResponse>::Callback + callback, + const FetcherConfig& config = kClassifyUrlConfig); +} // namespace supervised_user #endif // COMPONENTS_SUPERVISED_USER_CORE_BROWSER_PROTO_FETCHER_H_
diff --git a/components/supervised_user/core/browser/proto_fetcher_unittest.cc b/components/supervised_user/core/browser/proto_fetcher_unittest.cc index 34382770..46dbffc4 100644 --- a/components/supervised_user/core/browser/proto_fetcher_unittest.cc +++ b/components/supervised_user/core/browser/proto_fetcher_unittest.cc
@@ -6,6 +6,7 @@ #include <memory> #include <string> +#include <tuple> #include "base/strings/string_piece.h" #include "base/test/task_environment.h" @@ -19,6 +20,7 @@ #include "net/base/net_errors.h" #include "net/http/http_request_headers.h" #include "net/http/http_status_code.h" +#include "services/network/public/cpp/data_element.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_utils.h" @@ -30,6 +32,8 @@ using ::base::BindOnce; using ::base::Time; +using ::kids_chrome_management::ClassifyUrlRequest; +using ::kids_chrome_management::ClassifyUrlResponse; using ::kids_chrome_management::FamilyRole; using ::kids_chrome_management::ListFamilyMembersRequest; using ::kids_chrome_management::ListFamilyMembersResponse; @@ -37,19 +41,8 @@ using ::network::TestURLLoaderFactory; using ::signin::ConsentLevel; using ::signin::IdentityTestEnvironment; -using ::testing::Test; -// Tests the kidsmanagement/v1 proto client. -class ProtoFetcherTest : public Test { - protected: - FetcherConfig test_fetcher_config_ = - FetcherTestConfigBuilder::FromConfig(kListFamilyMembersConfig) - .WithServiceEndpoint("http://example.com") - .Build(); - network::TestURLLoaderFactory test_url_loader_factory_; - base::test::TaskEnvironment task_environment_; - IdentityTestEnvironment identity_test_env_; -}; +constexpr base::StringPiece kTestEndpoint = "http://example.com"; template <typename Response> class Receiver { @@ -72,78 +65,186 @@ base::expected<std::unique_ptr<Response>, ProtoFetcherStatus> result_; }; -TEST_F(ProtoFetcherTest, AcceptsRequests) { - AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( - "bob@gmail.com", ConsentLevel::kSignin); - Receiver<ListFamilyMembersResponse> receiver; - ListFamilyMembersResponse response; +// Go around Gtest limitation for test parametrization - create aliases for type +// tuples +using ClassifyUrl = std::tuple<ClassifyUrlRequest, ClassifyUrlResponse>; +using ListFamilyMembers = + std::tuple<ListFamilyMembersRequest, ListFamilyMembersResponse>; - auto fetcher = FetchListFamilyMembers( - *identity_test_env_.identity_manager(), - test_url_loader_factory_.GetSafeWeakWrapper(), - BindOnce(&Receiver<ListFamilyMembersResponse>::Receive, - base::Unretained(&receiver)), - test_fetcher_config_); - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "access_token", Time::Max()); +// Tests the kidsmanagement/v1 proto client. +template <typename T> +class ProtoFetcherTest : public testing::Test { + protected: + // Go around Gtest limitation for test parametrization - extract Request and + // Response. + using Request = typename std::tuple_element<0, T>::type; + using Response = typename std::tuple_element<1, T>::type; - TestURLLoaderFactory::PendingRequest* pending_request = - test_url_loader_factory_.GetPendingRequest(0); - EXPECT_EQ(pending_request->request.url, - "http://example.com/families/mine/members?alt=proto"); - EXPECT_EQ(pending_request->request.method, "GET"); + FetcherConfig test_fetcher_config_ = + FetcherTestConfigBuilder::FromConfig(GetConfig()) + .WithServiceEndpoint(kTestEndpoint) + .Build(); + network::TestURLLoaderFactory test_url_loader_factory_; + base::test::TaskEnvironment task_environment_; + IdentityTestEnvironment identity_test_env_; - test_url_loader_factory_.SimulateResponseForPendingRequest( - pending_request->request.url.spec(), response.SerializeAsString()); + // Both methods are required because respective config and fetchers are not + // generic on purpose. The network connection is mocked and requests are only + // validate server side, so it doesn't make sense to send anything but default + // Proto. + FetcherConfig GetConfig() const; + std::unique_ptr<ProtoFetcher<Response>> GetFetcher( + Receiver<Response>& receiver, + const Request& request = Request()); +}; - ASSERT_TRUE(receiver.GetResult().has_value()); +template <> +FetcherConfig ProtoFetcherTest<ListFamilyMembers>::GetConfig() const { + return kListFamilyMembersConfig; +} +template <> +FetcherConfig ProtoFetcherTest<ClassifyUrl>::GetConfig() const { + return kClassifyUrlConfig; } -TEST_F(ProtoFetcherTest, NoAccessToken) { - AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( - "bob@gmail.com", ConsentLevel::kSignin); - Receiver<ListFamilyMembersResponse> receiver; - - auto fetcher = FetchListFamilyMembers( +template <> +std::unique_ptr<ProtoFetcher<ListFamilyMembersResponse>> +ProtoFetcherTest<ListFamilyMembers>::GetFetcher( + Receiver<ListFamilyMembersResponse>& receiver, + const Request& request) { + return FetchListFamilyMembers( *identity_test_env_.identity_manager(), test_url_loader_factory_.GetSafeWeakWrapper(), BindOnce(&Receiver<ListFamilyMembersResponse>::Receive, base::Unretained(&receiver)), - test_fetcher_config_); - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithError( - GoogleServiceAuthError( - GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); + test_fetcher_config_); // Unretained(.) must outlive the fetcher. +} - EXPECT_EQ(test_url_loader_factory_.NumPending(), 0); +template <> +std::unique_ptr<ProtoFetcher<ClassifyUrlResponse>> +ProtoFetcherTest<ClassifyUrl>::GetFetcher( + Receiver<ClassifyUrlResponse>& receiver, + const Request& request) { + return ClassifyURL( + *identity_test_env_.identity_manager(), + test_url_loader_factory_.GetSafeWeakWrapper(), request, + BindOnce(&Receiver<ClassifyUrlResponse>::Receive, + base::Unretained(&receiver)), + test_fetcher_config_); // Unretained(.) must outlive the fetcher. +} + +TYPED_TEST_SUITE_P(ProtoFetcherTest); + +TYPED_TEST_P(ProtoFetcherTest, ConfiguresEndpoint) { + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; + + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( + "bob@gmail.com", ConsentLevel::kSignin); + + auto fetcher = this->GetFetcher(receiver); + + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken("access_token", + Time::Max()); + + TestURLLoaderFactory::PendingRequest* pending_request = + this->test_url_loader_factory_.GetPendingRequest(0); + + GURL expected_url = + GURL("http://example.com/" + std::string(this->GetConfig().service_path) + + "?alt=proto"); + EXPECT_EQ(pending_request->request.url, expected_url); + EXPECT_EQ(pending_request->request.method, this->GetConfig().GetHttpMethod()); +} + +TYPED_TEST_P(ProtoFetcherTest, AddsPayload) { + if (this->GetConfig().method != FetcherConfig::Method::kPost) { + GTEST_SKIP() << "Payload not supported for " + << this->GetConfig().GetHttpMethod() << " requests."; + } + + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; + + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( + "bob@gmail.com", ConsentLevel::kSignin); + + auto fetcher = this->GetFetcher(receiver); + + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken("access_token", + Time::Max()); + + TestURLLoaderFactory::PendingRequest* pending_request = + this->test_url_loader_factory_.GetPendingRequest(0); + + std::string header; + EXPECT_TRUE(pending_request->request.headers.GetHeader( + net::HttpRequestHeaders::kContentType, &header)); + EXPECT_EQ(header, "application/x-protobuf"); +} + +TYPED_TEST_P(ProtoFetcherTest, AcceptsRequests) { + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; + Response response; + + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( + "bob@gmail.com", ConsentLevel::kSignin); + + auto fetcher = this->GetFetcher(receiver); + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken("access_token", + Time::Max()); + + TestURLLoaderFactory::PendingRequest* pending_request = + this->test_url_loader_factory_.GetPendingRequest(0); + + this->test_url_loader_factory_.SimulateResponseForPendingRequest( + pending_request->request.url.spec(), response.SerializeAsString()); + + EXPECT_TRUE(receiver.GetResult().has_value()); +} + +TYPED_TEST_P(ProtoFetcherTest, NoAccessToken) { + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; + + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( + "bob@gmail.com", ConsentLevel::kSignin); + + auto fetcher = this->GetFetcher(receiver); + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithError( + GoogleServiceAuthError( + GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); + + EXPECT_EQ(this->test_url_loader_factory_.NumPending(), 0); EXPECT_EQ(receiver.GetResult().error().state(), ProtoFetcherStatus::State::GOOGLE_SERVICE_AUTH_ERROR); EXPECT_EQ(receiver.GetResult().error().google_service_auth_error().state(), GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS); } -TEST_F(ProtoFetcherTest, HandlesMalformedResponse) { - AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( - "bob@gmail.com", ConsentLevel::kSignin); - Receiver<ListFamilyMembersResponse> receiver; +TYPED_TEST_P(ProtoFetcherTest, HandlesMalformedResponse) { + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; - auto fetcher = FetchListFamilyMembers( - *identity_test_env_.identity_manager(), - test_url_loader_factory_.GetSafeWeakWrapper(), - BindOnce(&Receiver<ListFamilyMembersResponse>::Receive, - base::Unretained(&receiver)), - test_fetcher_config_); - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "access_token", Time::Max()); + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( + "bob@gmail.com", ConsentLevel::kSignin); + + auto fetcher = this->GetFetcher(receiver); + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken("access_token", + Time::Max()); TestURLLoaderFactory::PendingRequest* pending_request = - test_url_loader_factory_.GetPendingRequest(0); + this->test_url_loader_factory_.GetPendingRequest(0); ASSERT_NE(nullptr, pending_request); - EXPECT_EQ(pending_request->request.url, - "http://example.com/families/mine/members?alt=proto"); - EXPECT_EQ(pending_request->request.method, "GET"); std::string malformed_value("garbage"); // Not a valid marshaled proto. - test_url_loader_factory_.SimulateResponseForPendingRequest( + this->test_url_loader_factory_.SimulateResponseForPendingRequest( pending_request->request.url.spec(), malformed_value); EXPECT_FALSE(receiver.GetResult().has_value()); EXPECT_EQ(receiver.GetResult().error().state(), @@ -152,24 +253,21 @@ // crbug/1444165: Do not use StringPrintf with StringPiece, c-strings are // expected. -TEST_F(ProtoFetcherTest, CreatesToken) { - AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( +TYPED_TEST_P(ProtoFetcherTest, CreatesToken) { + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; + + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( "bob@gmail.com", ConsentLevel::kSignin); - Receiver<ListFamilyMembersResponse> receiver; - auto fetcher = FetchListFamilyMembers( - *identity_test_env_.identity_manager(), - test_url_loader_factory_.GetSafeWeakWrapper(), - BindOnce(&Receiver<ListFamilyMembersResponse>::Receive, - base::Unretained(&receiver)), - test_fetcher_config_); - - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "token", Time::Max()); + auto fetcher = this->GetFetcher(receiver); + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken("token", + Time::Max()); // That's enough: request is pending, so token is accepted. TestURLLoaderFactory::PendingRequest* pending_request = - test_url_loader_factory_.GetPendingRequest(0); + this->test_url_loader_factory_.GetPendingRequest(0); ASSERT_NE(nullptr, pending_request); // Only check header format here. @@ -179,29 +277,23 @@ EXPECT_EQ(authorization_header, "Bearer token"); } -TEST_F(ProtoFetcherTest, HandlesServerError) { - AccountInfo account = identity_test_env_.MakePrimaryAccountAvailable( +TYPED_TEST_P(ProtoFetcherTest, HandlesServerError) { + using Response = typename std::tuple_element<1, TypeParam>::type; + Receiver<Response> receiver; + + AccountInfo account = this->identity_test_env_.MakePrimaryAccountAvailable( "bob@gmail.com", ConsentLevel::kSignin); - Receiver<ListFamilyMembersResponse> receiver; - auto fetcher = FetchListFamilyMembers( - *identity_test_env_.identity_manager(), - test_url_loader_factory_.GetSafeWeakWrapper(), - BindOnce(&Receiver<ListFamilyMembersResponse>::Receive, - base::Unretained(&receiver)), - test_fetcher_config_); - - identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( - "access_token", Time::Max()); + auto fetcher = this->GetFetcher(receiver); + this->identity_test_env_ + .WaitForAccessTokenRequestIfNecessaryAndRespondWithToken("access_token", + Time::Max()); TestURLLoaderFactory::PendingRequest* pending_request = - test_url_loader_factory_.GetPendingRequest(0); + this->test_url_loader_factory_.GetPendingRequest(0); ASSERT_NE(nullptr, pending_request); - EXPECT_EQ(pending_request->request.url, - "http://example.com/families/mine/members?alt=proto"); - EXPECT_EQ(pending_request->request.method, "GET"); - test_url_loader_factory_.SimulateResponseForPendingRequest( + this->test_url_loader_factory_.SimulateResponseForPendingRequest( pending_request->request.url.spec(), /*content=*/"", net::HTTP_BAD_REQUEST); EXPECT_FALSE(receiver.GetResult().has_value()); @@ -212,5 +304,17 @@ ProtoFetcherStatus::HttpStatusOrNetErrorType(net::HTTP_BAD_REQUEST)); } +REGISTER_TYPED_TEST_SUITE_P(ProtoFetcherTest, + ConfiguresEndpoint, + AddsPayload, + AcceptsRequests, + NoAccessToken, + HandlesMalformedResponse, + CreatesToken, + HandlesServerError); + +using Fetchers = ::testing::Types<ClassifyUrl, ListFamilyMembers>; +INSTANTIATE_TYPED_TEST_SUITE_P(AllFetchers, ProtoFetcherTest, Fetchers); + } // namespace } // namespace supervised_user
diff --git a/components/test/BUILD.gn b/components/test/BUILD.gn index cbb8136a..a4c0d82 100644 --- a/components/test/BUILD.gn +++ b/components/test/BUILD.gn
@@ -86,6 +86,10 @@ testonly = true filelist_name = "data/performance_manager/unit_tests_bundle_data.filelist" } + bundle_data_from_filelist("service_worker_test_bundle_data") { + testonly = true + filelist_name = "data/service_worker/unit_tests_bundle_data.filelist" + } bundle_data_from_filelist("url_rewrite_test_bundle_data") { testonly = true filelist_name = "data/url_rewrite/unit_tests_bundle_data.filelist"
diff --git a/components/test/PRESUBMIT.py b/components/test/PRESUBMIT.py index 9a35089..d2e5ec2 100644 --- a/components/test/PRESUBMIT.py +++ b/components/test/PRESUBMIT.py
@@ -38,6 +38,9 @@ input_api, output_api, 'data/history/unit_tests_bundle_data') results += presubmit_support.CheckBundleData( input_api, output_api, + 'data/service_worker/unit_tests_bundle_data') + results += presubmit_support.CheckBundleData( + input_api, output_api, 'data/url_rewrite/unit_tests_bundle_data') results += presubmit_support.CheckBundleData( input_api, output_api,
diff --git a/components/test/data/service_worker/OWNERS b/components/test/data/service_worker/OWNERS new file mode 100644 index 0000000..4e6079c --- /dev/null +++ b/components/test/data/service_worker/OWNERS
@@ -0,0 +1,2 @@ +# Anyone can update the test bundle data filelist. +per-file unit_tests_bundle_data.filelist=*
diff --git a/components/test/data/service_worker/unit_tests_bundle_data.filelist b/components/test/data/service_worker/unit_tests_bundle_data.filelist new file mode 100644 index 0000000..689c953c --- /dev/null +++ b/components/test/data/service_worker/unit_tests_bundle_data.filelist
@@ -0,0 +1,11 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# NOTE: this file is generated by build/ios/update_bundle_filelist.py +# If it requires updating, you should get a presubmit error with +# instructions on how to regenerate. Otherwise, do not edit. +//components/test/data/service_worker/created_by_origin_impl/Database/000003.log +//components/test/data/service_worker/created_by_origin_impl/Database/CURRENT +//components/test/data/service_worker/created_by_origin_impl/Database/LOCK +//components/test/data/service_worker/created_by_origin_impl/Database/LOG +//components/test/data/service_worker/created_by_origin_impl/Database/MANIFEST-000001
diff --git a/components/test/data/service_worker/unit_tests_bundle_data.globlist b/components/test/data/service_worker/unit_tests_bundle_data.globlist new file mode 100644 index 0000000..76ca24c --- /dev/null +++ b/components/test/data/service_worker/unit_tests_bundle_data.globlist
@@ -0,0 +1,11 @@ +# Copyright 2023 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# See build/ios/update_bundle_filelist.py for details on how .globlist +# files are used to update their .filelist counterparts. + +//components/test/data/service_worker/** +-//components/test/data/service_worker/*.filelist +-//components/test/data/service_worker/*.globlist +-//components/test/data/service_worker/OWNERS
diff --git a/components/viz/service/display_embedder/skia_output_device_dawn.cc b/components/viz/service/display_embedder/skia_output_device_dawn.cc index fd75e38..5c712db 100644 --- a/components/viz/service/display_embedder/skia_output_device_dawn.cc +++ b/components/viz/service/display_embedder/skia_output_device_dawn.cc
@@ -11,7 +11,6 @@ #include "base/time/time.h" #include "components/viz/common/gpu/dawn_context_provider.h" #include "gpu/command_buffer/service/shared_context_state.h" -#include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h" #include "third_party/skia/include/gpu/graphite/BackendTexture.h" #include "third_party/skia/include/gpu/graphite/Surface.h" #include "ui/gfx/presentation_feedback.h" @@ -26,18 +25,17 @@ // desktop and RGBA8Unorm for Android. Use GetPreferredSurfaceFormat when ready. #if BUILDFLAG(IS_ANDROID) constexpr SkColorType kSurfaceColorType = kRGBA_8888_SkColorType; -constexpr SharedImageFormat kSurfaceFormat = SinglePlaneFormat::kRGBA_8888; constexpr wgpu::TextureFormat kSwapChainFormat = wgpu::TextureFormat::RGBA8Unorm; #else constexpr SkColorType kSurfaceColorType = kBGRA_8888_SkColorType; -constexpr SharedImageFormat kSurfaceFormat = SinglePlaneFormat::kBGRA_8888; constexpr wgpu::TextureFormat kSwapChainFormat = wgpu::TextureFormat::BGRA8Unorm; #endif constexpr wgpu::TextureUsage kUsage = - wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding; + wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::TextureBinding | + wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst; } // namespace @@ -151,16 +149,8 @@ SkSurface* SkiaOutputDeviceDawn::BeginPaint( std::vector<GrBackendSemaphore>* end_semaphores) { - auto texture_info = gpu::GetGraphiteTextureInfo( - gpu::GrContextType::kGraphiteDawn, kSurfaceFormat, - /*plane_index=*/0, /*mipmapped=*/false, /*root_surface=*/true); - skgpu::graphite::DawnTextureInfo dawn_texture_info; - texture_info.getDawnTextureInfo(&dawn_texture_info); - - wgpu::TextureView texture_view = swap_chain_.GetCurrentTextureView(); - skgpu::graphite::BackendTexture backend_texture( - SkISize::Make(size_.width(), size_.height()), dawn_texture_info, - texture_view.Get()); + wgpu::Texture texture = swap_chain_.GetCurrentTexture(); + skgpu::graphite::BackendTexture backend_texture(texture.Get()); SkSurfaceProps surface_props{0, kUnknown_SkPixelGeometry}; sk_surface_ = SkSurfaces::WrapBackendTexture(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index 3ca9ed3f..2c920ad 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -473,10 +473,9 @@ // purpose of creating Graphite TextureInfo i.e. it will have CopySrc and // CopyDst usage. So don't treat it like a root surface which generally // won't have or support those usages. - const bool is_root_surface = !capabilities_.supports_surfaceless; skgpu::graphite::TextureInfo texture_info = gpu::GetGraphiteTextureInfo( dependency_->gr_context_type(), format_, /*plane_index=*/0, - /*mipmapped=*/false, is_root_surface); + /*mipmapped=*/false); CHECK(texture_info.isValid()); current_paint_.emplace(graphite_recorder_, image_info, texture_info); } else {
diff --git a/components/webapps/browser/uninstall_result_code.cc b/components/webapps/browser/uninstall_result_code.cc index 28069cc4..19dcc30e 100644 --- a/components/webapps/browser/uninstall_result_code.cc +++ b/components/webapps/browser/uninstall_result_code.cc
@@ -8,17 +8,6 @@ namespace webapps { -bool UninstallSucceeded(UninstallResultCode code) { - switch (code) { - case UninstallResultCode::kSuccess: - case UninstallResultCode::kNoAppToUninstall: - return true; - case UninstallResultCode::kCancelled: - case UninstallResultCode::kError: - return false; - } -} - std::string ConvertUninstallResultCodeToString(UninstallResultCode code) { switch (code) { case UninstallResultCode::kSuccess:
diff --git a/components/webapps/browser/uninstall_result_code.h b/components/webapps/browser/uninstall_result_code.h index d06ac47..635a555 100644 --- a/components/webapps/browser/uninstall_result_code.h +++ b/components/webapps/browser/uninstall_result_code.h
@@ -16,8 +16,6 @@ kError, }; -bool UninstallSucceeded(UninstallResultCode code); - std::string ConvertUninstallResultCodeToString(UninstallResultCode code); } // namespace webapps
diff --git a/components/webauthn/core/browser/passkey_sync_bridge.cc b/components/webauthn/core/browser/passkey_sync_bridge.cc index 9003c46..e2f407b 100644 --- a/components/webauthn/core/browser/passkey_sync_bridge.cc +++ b/components/webauthn/core/browser/passkey_sync_bridge.cc
@@ -290,6 +290,7 @@ for (const std::string& sync_id : sync_ids_to_delete) { data_.erase(sync_id); change_processor()->Delete(sync_id, write_batch->GetMetadataChangeList()); + write_batch->DeleteData(sync_id); } store_->CommitWriteBatch( std::move(write_batch), @@ -309,6 +310,7 @@ store_->CreateWriteBatch(); change_processor()->Put(sync_id, CreateEntityData(specifics), write_batch->GetMetadataChangeList()); + write_batch->WriteData(sync_id, specifics.SerializeAsString()); store_->CommitWriteBatch( std::move(write_batch), base::BindOnce(&PasskeySyncBridge::OnStoreCommitWriteBatch,
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm index ed4e4ad..fffe1327 100644 --- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -708,7 +708,7 @@ // and the following NSEventTypeMouseExited event should have the same pointer // type. For NSEventTypeMouseExited and NSEventTypeMouseEntered events, they // do not have a subtype. We decide their pointer types by checking if we - // recevied a NSEventTypeTabletProximity event. + // received a NSEventTypeTabletProximity event. NSEventType type = [theEvent type]; if (type == NSEventTypeMouseEntered || type == NSEventTypeMouseExited) { _pointerType = _isStylusEnteringProximity @@ -1102,7 +1102,7 @@ // Indicates if we should send the key event and corresponding editor commands // after processing the input method result. - BOOL delayEventUntilAfterImeCompostion = NO; + BOOL delayEventUntilAfterImeComposition = NO; // To emulate Windows, over-write |event.windowsKeyCode| to VK_PROCESSKEY // while an input method is composing or inserting a text. @@ -1123,7 +1123,7 @@ // We shouldn't do this if a new marked text was set by the input method, // otherwise the new marked text might be cancelled by webkit. if (_hasEditCommands && !_hasMarkedText) - delayEventUntilAfterImeCompostion = YES; + delayEventUntilAfterImeComposition = YES; } else { _hostHelper->ForwardKeyboardEventWithCommands(event, latency_info, std::move(_editCommands)); @@ -1178,10 +1178,10 @@ // edit commands here. This usually occurs when the input method wants to // finish current composition session but still wants the application to // handle the key event. See http://crbug.com/48161 for reference. - if (delayEventUntilAfterImeCompostion) { - // If |delayEventUntilAfterImeCompostion| is YES, then a fake key down event - // with windowsKeyCode == 0xE5 has already been sent to webkit. - // So before sending the real key down event, we need to send a fake key up + if (delayEventUntilAfterImeComposition) { + // If |delayEventUntilAfterImeComposition| is YES, then a fake key down + // event with windowsKeyCode == 0xE5 has already been sent to webkit. So + // before sending the real key down event, we need to send a fake key up // event to balance it. NativeWebKeyboardEvent fakeEvent = event; fakeEvent.SetType(blink::WebInputEvent::Type::kKeyUp); @@ -1205,7 +1205,7 @@ event.text[1] = 0; event.skip_in_browser = true; _hostHelper->ForwardKeyboardEvent(event, latency_info); - } else if ((!textInserted || delayEventUntilAfterImeCompostion) && + } else if ((!textInserted || delayEventUntilAfterImeComposition) && event.text[0] != '\0' && ((modifierFlags & kCtrlCmdKeyMask) || (_hasEditCommands && _editCommands.empty()))) { @@ -1555,7 +1555,7 @@ _host->OnFirstResponderChanged(true); - // Cancel any onging composition text which was left before we lost focus. + // Cancel any ongoing composition text which was left before we lost focus. // TODO(suzhe): We should do it in -resignFirstResponder: method, but // somehow that method won't be called when switching among different tabs. // See http://crbug.com/47209 @@ -1580,7 +1580,7 @@ _host->RequestShutdown(); } - // We should cancel any onging composition whenever RWH's Blur() method gets + // We should cancel any ongoing composition whenever RWH's Blur() method gets // called, because in this case, webkit will confirm the ongoing composition // internally. [self cancelComposition];
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 4a4fe81..412a434 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2855,8 +2855,9 @@ RunHtmlTest(FILE_PATH_LITERAL("portal-with-widget-inside.html")); } +// TODO(crbug.com/1367886): Flaky on multiple platforms IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, - AccessibilityPortalNameFromVisibleText) { + DISABLED_AccessibilityPortalNameFromVisibleText) { RunHtmlTest(FILE_PATH_LITERAL("portal-name-from-visible-text.html")); }
diff --git a/content/browser/isolated_origin_browsertest.cc b/content/browser/isolated_origin_browsertest.cc index 20dbc38..d101aa69 100644 --- a/content/browser/isolated_origin_browsertest.cc +++ b/content/browser/isolated_origin_browsertest.cc
@@ -651,6 +651,96 @@ browser_context, url::Origin::Create(non_isolated_sub_origin))); } +// A test to verify that an origin with a trailing dot in the domain name +// doesn't crash when it opts-out of origin isolation when +// kOriginAgentClusterDefaultEnabled is enabled. +IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, + TrailingDotDomainOptOutDoesNotCrash) { + GURL dotted_nonisolated_url( + https_server()->GetURL("a.com.", "/isolate_origin")); + + // Set header to opt this domain out of default OriginAgentCluster. + SetHeaderValue("?0"); + EXPECT_TRUE(NavigateToURL(shell(), dotted_nonisolated_url)); + url::Origin origin(url::Origin::Create(dotted_nonisolated_url)); + EXPECT_FALSE(ShouldOriginGetOptInProcessIsolation(origin)); +} + +// A test to confirm that "a.com." is treated as a separate host (and hence +// a separate origin) from "a.com". See example at +// https://url.spec.whatwg.org/#concept-domain. +IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, + TrailingDotDomainIsolatesSeparately1) { + GURL main_frame_url(https_server()->GetURL( + "foo.com", "/cross_site_iframe_factory.html?foo.com(foo.com,foo.com)")); + GURL isolated_url(https_server()->GetURL("a.com", "/isolate_origin")); + GURL dotted_isolated_url(https_server()->GetURL("a.com.", "/isolate_origin")); + SetHeaderValue("?1"); + + // Create page with sibling iframes. + EXPECT_TRUE(NavigateToURL(shell(), main_frame_url)); + FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root(); + EXPECT_EQ(2u, root->child_count()); + FrameTreeNode* child0_frame_node = root->child_at(0); + FrameTreeNode* child1_frame_node = root->child_at(1); + EXPECT_TRUE(NavigateToURLFromRenderer(child0_frame_node, isolated_url)); + EXPECT_TRUE( + NavigateToURLFromRenderer(child1_frame_node, dotted_isolated_url)); + + url::Origin child0_origin(url::Origin::Create(isolated_url)); + url::Origin child1_origin(url::Origin::Create(dotted_isolated_url)); + EXPECT_NE(isolated_url, dotted_isolated_url); + EXPECT_NE(child0_origin, child1_origin); + + EXPECT_TRUE(ShouldOriginGetOptInProcessIsolation(child0_origin)); + EXPECT_TRUE(ShouldOriginGetOptInProcessIsolation(child1_origin)); + + scoped_refptr<SiteInstanceImpl> child0_site_instance = + child0_frame_node->current_frame_host()->GetSiteInstance(); + scoped_refptr<SiteInstanceImpl> child1_site_instance = + child1_frame_node->current_frame_host()->GetSiteInstance(); + EXPECT_NE(child0_site_instance, child1_site_instance); + EXPECT_NE(child0_site_instance->GetProcess(), + child1_site_instance->GetProcess()); +} + +// A test similar to TrailingDotDomainIsolatesSeparately1, but this time the +// "a.com" domain does not opt-in via a header, and does not get an origin- +// keyed process. Thus, it ends up in a separate process from "a.com.". +IN_PROC_BROWSER_TEST_F(OriginIsolationOptInHeaderTest, + TrailingDotDomainIsolatesSeparately2) { + GURL main_frame_url(https_server()->GetURL( + "foo.com", "/cross_site_iframe_factory.html?foo.com(foo.com,foo.com)")); + GURL non_isolated_url(https_server()->GetURL("a.com", "/title1.html")); + GURL dotted_isolated_url(https_server()->GetURL("a.com.", "/isolate_origin")); + + // Create page with sibling iframes. + EXPECT_TRUE(NavigateToURL(shell(), main_frame_url)); + FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root(); + EXPECT_EQ(2u, root->child_count()); + FrameTreeNode* child0_frame_node = root->child_at(0); + FrameTreeNode* child1_frame_node = root->child_at(1); + SetHeaderValue("?1"); + EXPECT_TRUE( + NavigateToURLFromRenderer(child0_frame_node, dotted_isolated_url)); + SetHeaderValue(""); + EXPECT_TRUE(NavigateToURLFromRenderer(child1_frame_node, non_isolated_url)); + + url::Origin child0_origin(url::Origin::Create(dotted_isolated_url)); + url::Origin child1_origin(url::Origin::Create(non_isolated_url)); + + EXPECT_TRUE(ShouldOriginGetOptInProcessIsolation(child0_origin)); + EXPECT_FALSE(ShouldOriginGetOptInProcessIsolation(child1_origin)); + + scoped_refptr<SiteInstanceImpl> child0_site_instance = + child0_frame_node->current_frame_host()->GetSiteInstance(); + scoped_refptr<SiteInstanceImpl> child1_site_instance = + child1_frame_node->current_frame_host()->GetSiteInstance(); + EXPECT_NE(child0_site_instance, child1_site_instance); + EXPECT_NE(child0_site_instance->GetProcess(), + child1_site_instance->GetProcess()); +} + // A test to confirm that if an Origin-Agent-Cluster header is encountered (but // not committed) as part of a redirect, that it does not opt-in to // OriginAgentCluster isolation. The setup in this test is subtle, since in @@ -734,6 +824,34 @@ 1))); } +// A test to ensure that origins whose host has a trailing dot pass the +// validation checks for explicit opt-ins and opt-outs. This is an +// `OriginKeyedProcessByDefaultTest` test in order that the explicit opt-out +// will be tracked. Note: failure for either part of this test will involve +// crashing on a CHECK in +// ChildProcessSecurityPolicyImpl::AddOriginIsolationStateForBrowsingInstance(): +IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest, + HostWithTrailingDotAllowed) { + // Explicit opt-in with a trailing dot. + SetHeaderValue("?1"); + GURL opt_in_url(https_server()->GetURL("opt-in.foo.com.", "/isolate_origin")); + url::Origin opt_in_origin(url::Origin::Create(opt_in_url)); + + EXPECT_FALSE(ShouldOriginGetOptInProcessIsolation(opt_in_origin)); + EXPECT_TRUE(NavigateToURL(shell(), opt_in_url)); + EXPECT_TRUE(ShouldOriginGetOptInProcessIsolation(opt_in_origin)); + + // Explicit opt-out with a trailing dot. + SetHeaderValue("?0"); + GURL opt_out_url( + https_server()->GetURL("opt-out.foo.com.", "/isolate_origin")); + url::Origin opt_out_origin(url::Origin::Create(opt_out_url)); + + EXPECT_FALSE(ShouldOriginGetOptInProcessIsolation(opt_out_origin)); + EXPECT_TRUE(NavigateToURL(shell(), opt_out_url)); + EXPECT_FALSE(ShouldOriginGetOptInProcessIsolation(opt_out_origin)); +} + // A simple test that, when OAC-by-default is enabled with process-isolation, an // origin that receives default OAC is put in an origin-keyed process. IN_PROC_BROWSER_TEST_F(OriginKeyedProcessByDefaultTest,
diff --git a/content/browser/isolated_origin_util.cc b/content/browser/isolated_origin_util.cc index ebe8d8e..ec4773d 100644 --- a/content/browser/isolated_origin_util.cc +++ b/content/browser/isolated_origin_util.cc
@@ -109,7 +109,8 @@ // static bool IsolatedOriginUtil::IsValidIsolatedOrigin(const url::Origin& origin) { - return IsValidIsolatedOriginImpl(origin, true); + return IsValidIsolatedOriginImpl(origin, + /* is_legacy_isolated_origin_check=*/true); } // static @@ -117,7 +118,8 @@ const url::Origin& origin) { // Per https://html.spec.whatwg.org/C/#initialise-the-document-object, // non-secure contexts cannot be isolated via opt-in origin isolation. - return IsValidIsolatedOriginImpl(origin, false) && + return IsValidIsolatedOriginImpl( + origin, /* is_legacy_isolated_origin_check=*/false) && network::IsOriginPotentiallyTrustworthy(origin); } @@ -127,13 +129,14 @@ // Per https://html.spec.whatwg.org/C/#initialise-the-document-object, // non-secure contexts cannot be isolated via opt-in origin isolation, // but we allow non-secure contexts to opt-out for legacy sites. - return IsValidIsolatedOriginImpl(origin, false); + return IsValidIsolatedOriginImpl(origin, + /* is_legacy_isolated_origin_check=*/false); } // static bool IsolatedOriginUtil::IsValidIsolatedOriginImpl( const url::Origin& origin, - bool check_has_registry_domain) { + bool is_legacy_isolated_origin_check) { if (origin.opaque()) return false; @@ -154,7 +157,7 @@ // This is not relevant for opt-in origin isolation, which doesn't need to // match subdomains. (And it'd be bad to check this in that case, as it // prohibits http://localhost/; see https://crbug.com/1142894.) - if (check_has_registry_domain) { + if (is_legacy_isolated_origin_check) { const bool has_registry_domain = net::registry_controlled_domains::HostHasRegistryControlledDomain( origin.host(), @@ -164,11 +167,15 @@ return false; } - // For now, disallow hosts with a trailing dot. - // TODO(alexmos): Enabling this would require carefully thinking about + // Disallow hosts with a trailing dot for legacy isolated origins, but allow + // them for opt-in origin isolation since the spec says that they represent + // a distinct origin: https://url.spec.whatwg.org/#concept-domain. + // TODO(alexmos): Legacy isolated origins should probably support trailing + // dots as well, but enabling this would require carefully thinking about // whether hosts without a trailing dot should match it. - if (origin.host().back() == '.') + if (is_legacy_isolated_origin_check && origin.host().back() == '.') { return false; + } return true; }
diff --git a/content/browser/isolated_origin_util.h b/content/browser/isolated_origin_util.h index cc0c6d6c..20d69e00 100644 --- a/content/browser/isolated_origin_util.h +++ b/content/browser/isolated_origin_util.h
@@ -108,9 +108,12 @@ private: // Used to implement both IsValidIsolatedOrigin and - // IsValidOriginForOptInIsolation. + // IsValidOriginForOptInIsolation. The legacy isolated origin case performs + // some additional checks that don't apply to the opt-in case: it verifies the + // origin has a registry domain (for subdomain matching) and disallows + // trailing dots in the domain. static bool IsValidIsolatedOriginImpl(const url::Origin& origin, - bool check_has_registry_domain); + bool is_legacy_isolated_origin_check); }; } // namespace content
diff --git a/content/browser/media/media_devices_util.cc b/content/browser/media/media_devices_util.cc index 20776fa..8cb7cc5 100644 --- a/content/browser/media/media_devices_util.cc +++ b/content/browser/media/media_devices_util.cc
@@ -115,6 +115,8 @@ MediaDeviceSaltAndOrigin::MediaDeviceSaltAndOrigin( const MediaDeviceSaltAndOrigin& other) = default; +MediaDeviceSaltAndOrigin::~MediaDeviceSaltAndOrigin() = default; + void GetDefaultMediaDeviceID( MediaDeviceType device_type, int render_process_id, @@ -148,8 +150,9 @@ url::Origin origin; GURL url; net::SiteForCookies site_for_cookies; - url::Origin top_level_origin; + url::Origin main_frame_origin; std::string frame_salt; + absl::optional<ukm::SourceId> source_id; bool has_focus = true; bool is_background = false; @@ -157,10 +160,11 @@ origin = frame_host->GetLastCommittedOrigin(); url = frame_host->GetLastCommittedURL(); site_for_cookies = frame_host->ComputeSiteForCookies(); - top_level_origin = frame_host->frame_tree_node() - ->frame_tree() - .GetMainFrame() - ->GetLastCommittedOrigin(); + main_frame_origin = frame_host->frame_tree_node() + ->frame_tree() + .GetMainFrame() + ->GetLastCommittedOrigin(); + source_id = frame_host->GetPageUkmSourceId(); frame_salt = frame_host->GetMediaDeviceIDSaltBase(); has_focus = frame_host->GetView() && frame_host->GetView()->HasFocus(); @@ -177,7 +181,7 @@ are_persistent_ids_allowed = GetContentClient()->browser()->ArePersistentMediaDeviceIDsAllowed( process_host->GetBrowserContext(), url, site_for_cookies, - top_level_origin); + main_frame_origin); device_id_salt = process_host->GetBrowserContext()->GetMediaDeviceIDSalt(); group_id_salt = device_id_salt; } @@ -192,8 +196,11 @@ // thus appending a constant. group_id_salt += frame_salt + "groupid"; - return {std::move(device_id_salt), std::move(group_id_salt), - std::move(origin), has_focus, is_background}; + MediaDeviceSaltAndOrigin salt_and_origin( + std::move(device_id_salt), std::move(group_id_salt), std::move(origin), + has_focus, is_background); + salt_and_origin.ukm_source_id = source_id; + return salt_and_origin; } blink::WebMediaDeviceInfo TranslateMediaDeviceInfo(
diff --git a/content/browser/media/media_devices_util.h b/content/browser/media/media_devices_util.h index fa8f588..06196ca 100644 --- a/content/browser/media/media_devices_util.h +++ b/content/browser/media/media_devices_util.h
@@ -10,6 +10,8 @@ #include "base/functional/callback.h" #include "content/common/content_export.h" +#include "services/metrics/public/cpp/ukm_source_id.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/mediastream/media_devices.h" #include "url/origin.h" @@ -33,11 +35,14 @@ bool has_focus, bool is_background); MediaDeviceSaltAndOrigin(const MediaDeviceSaltAndOrigin& other); - ~MediaDeviceSaltAndOrigin() = default; + ~MediaDeviceSaltAndOrigin(); std::string device_id_salt; std::string group_id_salt; + // Last committed origin of the frame making a media device request. url::Origin origin; + // ukm::SourceId of the main frame making the media device request. + absl::optional<ukm::SourceId> ukm_source_id; bool has_focus; bool is_background; };
diff --git a/content/browser/preloading/prefetch/prefetch_container.cc b/content/browser/preloading/prefetch/prefetch_container.cc index e40d849..4d8bbe3 100644 --- a/content/browser/preloading/prefetch/prefetch_container.cc +++ b/content/browser/preloading/prefetch/prefetch_container.cc
@@ -519,8 +519,7 @@ } bool PrefetchContainer::HasIsolatedCookieCopyStarted() const { - switch ( - redirect_chain_[index_redirect_chain_to_serve_]->cookie_copy_status_) { + switch (GetCurrentSinglePrefetchToServe().cookie_copy_status_) { case SinglePrefetch::CookieCopyStatus::kNotStarted: return false; case SinglePrefetch::CookieCopyStatus::kInProgress: @@ -530,8 +529,7 @@ } bool PrefetchContainer::IsIsolatedCookieCopyInProgress() const { - switch ( - redirect_chain_[index_redirect_chain_to_serve_]->cookie_copy_status_) { + switch (GetCurrentSinglePrefetchToServe().cookie_copy_status_) { case SinglePrefetch::CookieCopyStatus::kNotStarted: case SinglePrefetch::CookieCopyStatus::kCompleted: return false; @@ -547,51 +545,50 @@ // changes from the copy. StopAllCookieListeners(); - redirect_chain_[index_redirect_chain_to_serve_]->cookie_copy_status_ = + GetCurrentSinglePrefetchToServe().cookie_copy_status_ = SinglePrefetch::CookieCopyStatus::kInProgress; - redirect_chain_[index_redirect_chain_to_serve_]->cookie_copy_start_time_ = + GetCurrentSinglePrefetchToServe().cookie_copy_start_time_ = base::TimeTicks::Now(); } void PrefetchContainer::OnIsolatedCookiesReadCompleteAndWriteStart() { DCHECK(IsIsolatedCookieCopyInProgress()); - redirect_chain_[index_redirect_chain_to_serve_] - ->cookie_read_end_and_write_start_time_ = base::TimeTicks::Now(); + GetCurrentSinglePrefetchToServe().cookie_read_end_and_write_start_time_ = + base::TimeTicks::Now(); } void PrefetchContainer::OnIsolatedCookieCopyComplete() { DCHECK(IsIsolatedCookieCopyInProgress()); - const auto& this_prefetch = redirect_chain_[index_redirect_chain_to_serve_]; + const auto& this_prefetch = GetCurrentSinglePrefetchToServe(); - this_prefetch->cookie_copy_status_ = + this_prefetch.cookie_copy_status_ = SinglePrefetch::CookieCopyStatus::kCompleted; - if (this_prefetch->cookie_copy_start_time_.has_value() && - this_prefetch->cookie_read_end_and_write_start_time_.has_value()) { + if (this_prefetch.cookie_copy_start_time_.has_value() && + this_prefetch.cookie_read_end_and_write_start_time_.has_value()) { RecordCookieCopyTimes( - this_prefetch->cookie_copy_start_time_.value(), - this_prefetch->cookie_read_end_and_write_start_time_.value(), + this_prefetch.cookie_copy_start_time_.value(), + this_prefetch.cookie_read_end_and_write_start_time_.value(), base::TimeTicks::Now()); } - if (this_prefetch->on_cookie_copy_complete_callback_) { - std::move(this_prefetch->on_cookie_copy_complete_callback_).Run(); + if (this_prefetch.on_cookie_copy_complete_callback_) { + std::move(this_prefetch.on_cookie_copy_complete_callback_).Run(); } } void PrefetchContainer::OnInterceptorCheckCookieCopy() { - if (!redirect_chain_[index_redirect_chain_to_serve_] - ->cookie_copy_start_time_) { + if (!GetCurrentSinglePrefetchToServe().cookie_copy_start_time_) { return; } UMA_HISTOGRAM_CUSTOM_TIMES( "PrefetchProxy.AfterClick.Mainframe.CookieCopyStartToInterceptorCheck", - base::TimeTicks::Now() - redirect_chain_[index_redirect_chain_to_serve_] - ->cookie_copy_start_time_.value(), + base::TimeTicks::Now() - + GetCurrentSinglePrefetchToServe().cookie_copy_start_time_.value(), base::TimeDelta(), base::Seconds(5), 50); } @@ -599,8 +596,8 @@ base::OnceClosure callback) { DCHECK(IsIsolatedCookieCopyInProgress()); - redirect_chain_[index_redirect_chain_to_serve_] - ->on_cookie_copy_complete_callback_ = std::move(callback); + GetCurrentSinglePrefetchToServe().on_cookie_copy_complete_callback_ = + std::move(callback); } void PrefetchContainer::TakeStreamingURLLoader( @@ -739,10 +736,8 @@ } bool PrefetchContainer::DoesCurrentURLToServeMatch(const GURL& url) const { - DCHECK(index_redirect_chain_to_serve_ >= 1 && - index_redirect_chain_to_serve_ < redirect_chain_.size()); - return IsMatchingURL(redirect_chain_[index_redirect_chain_to_serve_]->url_, - url); + DCHECK(index_redirect_chain_to_serve_ >= 1); + return IsMatchingURL(GetCurrentSinglePrefetchToServe().url_, url); } PrefetchContainer::SinglePrefetch& @@ -886,10 +881,9 @@ PrefetchContainer::SinglePrefetch::SinglePrefetch( const GURL& url, const net::SchemefulSite& referring_site) - : url_(url) { - net::SchemefulSite this_site(url_); - is_isolated_network_context_required_ = referring_site != this_site; -} + : url_(url), + is_isolated_network_context_required_(referring_site != + net::SchemefulSite(url_)) {} PrefetchContainer::SinglePrefetch::~SinglePrefetch() = default;
diff --git a/content/browser/preloading/prefetch/prefetch_container.h b/content/browser/preloading/prefetch/prefetch_container.h index e4a8170b..778554b6 100644 --- a/content/browser/preloading/prefetch/prefetch_container.h +++ b/content/browser/preloading/prefetch/prefetch_container.h
@@ -307,6 +307,11 @@ // Holds the state for the request for a single URL in the context of the // broader prefetch. A prefetch can request multiple URLs due to redirects. + // While prefetching, mutable references are used via + // `GetCurrentSinglePrefetchToPrefetch()` and non-mutable non-const members + // are updated. + // While serving, const references are used via + // `GetCurrentSinglePrefetchToServe()` and mutable members are updated. class SinglePrefetch { public: explicit SinglePrefetch(const GURL& url, @@ -321,7 +326,7 @@ // original prefetch URL. const GURL url_; - bool is_isolated_network_context_required_; + const bool is_isolated_network_context_required_; // Whether this |url_| is eligible to be prefetched absl::optional<bool> is_eligible_; @@ -338,16 +343,18 @@ }; // The current state of the cookie copy process for this prefetch. - CookieCopyStatus cookie_copy_status_ = CookieCopyStatus::kNotStarted; + mutable CookieCopyStatus cookie_copy_status_ = + CookieCopyStatus::kNotStarted; // The timestamps of when the overall cookie copy process starts, and midway // when the cookies are read from the isolated network context and are about // to be written to the default network context. - absl::optional<base::TimeTicks> cookie_copy_start_time_; - absl::optional<base::TimeTicks> cookie_read_end_and_write_start_time_; + mutable absl::optional<base::TimeTicks> cookie_copy_start_time_; + mutable absl::optional<base::TimeTicks> + cookie_read_end_and_write_start_time_; // A callback that runs once |cookie_copy_status_| is set to |kCompleted|. - base::OnceClosure on_cookie_copy_complete_callback_; + mutable base::OnceClosure on_cookie_copy_complete_callback_; }; // Returns the `SinglePrefetch` to be prefetched next. This is the last
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager.cc b/content/browser/preloading/prefetch/prefetch_document_manager.cc index 4ce3dcb3..fa9cb56e 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager.cc +++ b/content/browser/preloading/prefetch/prefetch_document_manager.cc
@@ -139,17 +139,6 @@ return; } - // If this prefetch has already been used with another navigation then stop. - if (prefetch_iter->second->HasPrefetchBeenConsideredToServe()) { - DVLOG(1) << "PrefetchDocumentManager::DidStartNavigation() for " - << *prefetch_iter->second - << ": skipped (already used for another navigation)"; - SetMetricsForPossibleNoVarySearchHintMatches( - all_prefetches_, navigation_handle->GetURL(), - *serving_page_metrics_container); - return; - } - prefetch_iter->second->SetServingPageMetrics( serving_page_metrics_container->GetWeakPtr()); prefetch_iter->second->UpdateServingPageMetrics();
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc index 38e1f3b..821406e3 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc
@@ -357,7 +357,14 @@ /*served=*/true); // Try to navigate again to the same URL. NavigateMainframeRendererTo(GetCrossOriginUrl("/candidate2.html?a=2&b=3")); - EXPECT_EQ(GetPrefetchesPreparedToServe().size(), 2u); + EXPECT_EQ(GetPrefetchesPreparedToServe().size(), 3u); + // PrepareToServe("/candidate2.html?a=2&b=3") is anyway called, but in + // non-test environment this will be merged or ignored later in + // PrefetchService. + EXPECT_EQ(GetPrefetchesPreparedToServe()[2].first, + GetCrossOriginUrl("/candidate2.html?a=2&b=3")); + EXPECT_EQ(GetPrefetchesPreparedToServe()[2].second->GetURL(), + GetCrossOriginUrl("/candidate2.html?a=2&b=3")); // Cover the case where we want to navigate to a URL with No-Vary-Search for // which the PrefetchContainer WeakPtr is not valid anymore. @@ -366,7 +373,7 @@ DCHECK(!GetPrefetchesPreparedToServe()[1].second); NavigateMainframeRendererTo( GetCrossOriginUrl("/candidate1.html?b=4&a=2&c=5")); - EXPECT_EQ(GetPrefetchesPreparedToServe().size(), 2u); + EXPECT_EQ(GetPrefetchesPreparedToServe().size(), 3u); } TEST_F(PrefetchDocumentManagerTest,
diff --git a/content/browser/preloading/prefetch/prefetch_service.cc b/content/browser/preloading/prefetch/prefetch_service.cc index 1a7ddddbd..b45c326 100644 --- a/content/browser/preloading/prefetch/prefetch_service.cc +++ b/content/browser/preloading/prefetch/prefetch_service.cc
@@ -1248,30 +1248,6 @@ bool is_servable = prefetch_container->IsPrefetchServable(PrefetchCacheableDuration()); - bool block_until_head = prefetch_container->ShouldBlockUntilHeadReceived(); - - if (prefetch_container->HaveDefaultContextCookiesChanged()) { - prefetch_container->SetPrefetchStatus( - PrefetchStatus::kPrefetchNotUsedCookiesChanged); - prefetch_container->UpdateServingPageMetrics(); - - DVLOG(1) << *prefetch_container - << ": didn't promote to ready (cookies changed)"; - return; - } - - // If the prefetch isn't ready to be served, then stop. - if (!is_servable && !block_until_head) { - DVLOG(1) << *prefetch_container - << ": didn't promote to ready (not servable)"; - return; - } - - // If the prefetch has a valid response, then it must be in - // |owned_prefetches_|. - DCHECK( - owned_prefetches_.find(prefetch_container->GetPrefetchContainerKey()) != - owned_prefetches_.end()); // `url` might be different from // `prefetch_container->GetPrefetchContainerKey().second` due to @@ -1289,8 +1265,7 @@ } // Move prefetch into |prefetches_ready_to_serve_|. - DVLOG(1) << *prefetch_container << ": promoted to ready" - << (block_until_head ? " and is blocked until head" : ""); + DVLOG(1) << *prefetch_container << ": promoted to ready"; prefetches_ready_to_serve_[ready_key] = prefetch_container; if (is_servable) { @@ -1383,7 +1358,7 @@ if (it != prefetches_ready_to_serve_.end()) { PrefetchContainer* prefetch = it->second.get(); prefetches_ready_to_serve_.erase(it); - if (prefetch) { + if (prefetch && !prefetch->HasPrefetchBeenConsideredToServe()) { return prefetch; } }
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc index 0e991111..e9120b7 100644 --- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -2010,6 +2010,10 @@ EXPECT_EQ(referring_page_metrics->prefetch_eligible_count, 1); EXPECT_EQ(referring_page_metrics->prefetch_successful_count, 1); + base::WeakPtr<PrefetchContainer> serveable_prefetch_container = + GetPrefetchToServe(GURL("https://example.com")); + EXPECT_FALSE(serveable_prefetch_container); + absl::optional<PrefetchServingPageMetrics> serving_page_metrics = GetMetricsForMostRecentNavigation(); ASSERT_TRUE(serving_page_metrics); @@ -2022,10 +2026,6 @@ EXPECT_EQ(serving_page_metrics->prefetch_header_latency.value(), base::Milliseconds(kHeaderLatency)); - base::WeakPtr<PrefetchContainer> serveable_prefetch_container = - GetPrefetchToServe(GURL("https://example.com")); - EXPECT_FALSE(serveable_prefetch_container); - // ReadyTime will be included in the UKM, because the prefetch was ready, and // then failed. ExpectCorrectUkmLogs(
diff --git a/content/browser/renderer_host/input/scroll_latency_browsertest.cc b/content/browser/renderer_host/input/scroll_latency_browsertest.cc index 8530ec3f..49010de 100644 --- a/content/browser/renderer_host/input/scroll_latency_browsertest.cc +++ b/content/browser/renderer_host/input/scroll_latency_browsertest.cc
@@ -372,8 +372,8 @@ }; // Crashes on Mac ASAN. https://crbug.com/1188553 -// TODO(crbug/1188553): Flaky on Linux Wayland CI/CQ builders. -#if BUILDFLAG(IS_MAC) || defined(OZONE_PLATFORM_WAYLAND) +// TODO(crbug.com/1188553): Flaky on Linux Wayland CI/CQ builders. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) #define MAYBE_ScrollbarThumbDragLatency DISABLED_ScrollbarThumbDragLatency #else #define MAYBE_ScrollbarThumbDragLatency ScrollbarThumbDragLatency
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/content/browser/renderer_host/input/web_input_event_builders_mac.mm index 14fdd49d..3dff118 100644 --- a/content/browser/renderer_host/input/web_input_event_builders_mac.mm +++ b/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -35,6 +35,7 @@ #include <stdint.h> +#include "base/apple/owned_objc.h" #include "base/mac/mac_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" @@ -250,19 +251,20 @@ } // namespace blink::WebKeyboardEvent WebKeyboardEventBuilder::Build(NSEvent* event) { - ui::ComputeEventLatencyOS(event); + ui::ComputeEventLatencyOS(base::apple::OwnedNSEvent(event)); ui::DomCode dom_code = ui::DomCodeFromNSEvent(event); int modifiers = ModifiersFromEvent(event) | ui::DomCodeToWebInputEventModifiers(dom_code); - if (([event type] != NSEventTypeFlagsChanged) && [event isARepeat]) + if ((event.type != NSEventTypeFlagsChanged) && event.ARepeat) { modifiers |= blink::WebInputEvent::kIsAutoRepeat; + } blink::WebKeyboardEvent result( ui::IsKeyUpEvent(event) ? blink::WebInputEvent::Type::kKeyUp : blink::WebInputEvent::Type::kRawKeyDown, - modifiers, ui::EventTimeStampFromSeconds([event timestamp])); + modifiers, ui::EventTimeStampFromSeconds(event.timestamp)); // Some keys have the same meaning but different locations on the keyboard: // the left and right shift keys; the numeric keypad keys and their @@ -331,7 +333,7 @@ NSView* view, blink::WebPointerProperties::PointerType pointerType, bool unacceleratedMovement) { - ui::ComputeEventLatencyOS(event); + ui::ComputeEventLatencyOS(base::apple::OwnedNSEvent(event)); blink::WebInputEvent::Type event_type = blink::WebInputEvent::Type::kUndefined; int click_count = 0; @@ -449,7 +451,7 @@ blink::WebMouseWheelEvent WebMouseWheelEventBuilder::Build( NSEvent* event, NSView* view) { - ui::ComputeEventLatencyOS(event); + ui::ComputeEventLatencyOS(base::apple::OwnedNSEvent(event)); blink::WebMouseWheelEvent result( blink::WebInputEvent::Type::kMouseWheel, ModifiersFromEvent(event), ui::EventTimeStampFromSeconds([event timestamp])); @@ -681,7 +683,7 @@ blink::WebTouchEvent result(event_type, ModifiersFromEvent(event), ui::EventTimeStampFromSeconds([event timestamp])); - ui::ComputeEventLatencyOS(event); + ui::ComputeEventLatencyOS(base::apple::OwnedNSEvent(event)); result.hovering = event_type == blink::WebInputEvent::Type::kTouchEnd; result.unique_touch_event_id = ui::GetNextTouchEventId(); result.touches_length = 1;
diff --git a/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm index 5c73950..c42c6569 100644 --- a/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm +++ b/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -8,6 +8,7 @@ #import <Cocoa/Cocoa.h> #include <stddef.h> +#include "base/apple/owned_objc.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "testing/gtest/include/gtest/gtest.h" @@ -675,7 +676,7 @@ blink::WebMouseWheelEvent web_event = content::WebMouseWheelEventBuilder::Build(mac_event, [window contentView]); - ui::MouseWheelEvent ui_event(mac_event); + ui::MouseWheelEvent ui_event((base::apple::OwnedNSEvent(mac_event))); EXPECT_EQ(delta_x * ui::kScrollbarPixelsPerCocoaTick, web_event.delta_x); EXPECT_EQ(web_event.delta_x, ui_event.x_offset());
diff --git a/content/browser/renderer_host/media/media_stream_manager.cc b/content/browser/renderer_host/media/media_stream_manager.cc index d20ad60..2d5255b 100644 --- a/content/browser/renderer_host/media/media_stream_manager.cc +++ b/content/browser/renderer_host/media/media_stream_manager.cc
@@ -75,6 +75,7 @@ #include "media/capture/video/video_capture_system_impl.h" #include "media/mojo/mojom/display_media_information.mojom.h" #include "third_party/abseil-cpp/absl/base/attributes.h" +#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/mediastream/media_devices.h" #include "third_party/blink/public/common/mediastream/media_stream_request.h" @@ -3351,6 +3352,12 @@ media_stream_metrics::RecordMediaStreamRequestResponseMetric( request->video_type(), request->request_type(), result); + if (request->salt_and_origin.ukm_source_id) { + media_stream_metrics::RecordMediaStreamRequestResponseUKM( + request->salt_and_origin.ukm_source_id.value(), request->video_type(), + request->request_type(), result); + } + if (request->request_type() == blink::MEDIA_DEVICE_ACCESS) { FinalizeMediaAccessRequest(request_it, stream_devices_set); return;
diff --git a/content/browser/renderer_host/media/media_stream_metrics.cc b/content/browser/renderer_host/media/media_stream_metrics.cc index 2cb9fa3e..ec08450 100644 --- a/content/browser/renderer_host/media/media_stream_metrics.cc +++ b/content/browser/renderer_host/media/media_stream_metrics.cc
@@ -6,6 +6,7 @@ #include "base/metrics/histogram_functions.h" #include "base/notreached.h" +#include "services/metrics/public/cpp/ukm_builders.h" #include "url/origin.h" namespace content::media_stream_metrics { @@ -35,8 +36,54 @@ kMaxValue = kDeviceInUse }; -void RecordMediaStreamRequestResult2(blink::mojom::MediaStreamType video_type, - MediaStreamRequestResult2 result2) { +MediaStreamRequestResult2 MapResultToResult2( + blink::mojom::MediaStreamRequestResult result) { + using blink::mojom::MediaStreamRequestResult; + switch (result) { + case MediaStreamRequestResult::OK: + return MediaStreamRequestResult2::kOk; + case MediaStreamRequestResult::PERMISSION_DENIED: + return MediaStreamRequestResult2::kPermissionDenied; + case MediaStreamRequestResult::PERMISSION_DISMISSED: + return MediaStreamRequestResult2::kPermissionDismissed; + case MediaStreamRequestResult::INVALID_STATE: + return MediaStreamRequestResult2::kInvalidState; + case MediaStreamRequestResult::NO_HARDWARE: + return MediaStreamRequestResult2::kNoHardware; + case MediaStreamRequestResult::INVALID_SECURITY_ORIGIN: + return MediaStreamRequestResult2::kInvalidSecurityOrigin; + case MediaStreamRequestResult::TAB_CAPTURE_FAILURE: + return MediaStreamRequestResult2::kTabCaptureFailure; + case MediaStreamRequestResult::SCREEN_CAPTURE_FAILURE: + return MediaStreamRequestResult2::kScreenCaptureFailure; + case MediaStreamRequestResult::CAPTURE_FAILURE: + return MediaStreamRequestResult2::kCaptureFailure; + case MediaStreamRequestResult::CONSTRAINT_NOT_SATISFIED: + return MediaStreamRequestResult2::kConstraintNotSatisfied; + case MediaStreamRequestResult::TRACK_START_FAILURE_AUDIO: + return MediaStreamRequestResult2::kTrackStartFailureAudio; + case MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO: + return MediaStreamRequestResult2::kTrackStartFailureVideo; + case MediaStreamRequestResult::NOT_SUPPORTED: + return MediaStreamRequestResult2::kNotSupported; + case MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN: + return MediaStreamRequestResult2::kFailedDueToShutdown; + case MediaStreamRequestResult::KILL_SWITCH_ON: + return MediaStreamRequestResult2::kKillSwitchOn; + case MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED: + return MediaStreamRequestResult2::kSystemPermissionDenied; + case MediaStreamRequestResult::DEVICE_IN_USE: + return MediaStreamRequestResult2::kDeviceInUse; + case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS: + break; + } + NOTREACHED_NORETURN(); +} + +void RecordMediaDeviceUpdateResponseMetric( + blink::mojom::MediaStreamType video_type, + blink::mojom::MediaStreamRequestResult result) { + MediaStreamRequestResult2 result2 = MapResultToResult2(result); switch (video_type) { case blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE: base::UmaHistogramEnumeration( @@ -52,85 +99,6 @@ } } -void RecordMediaDeviceUpdateResponseMetric( - blink::mojom::MediaStreamType video_type, - blink::mojom::MediaStreamRequestResult result) { - using blink::mojom::MediaStreamRequestResult; - switch (result) { - case MediaStreamRequestResult::OK: - RecordMediaStreamRequestResult2(video_type, - MediaStreamRequestResult2::kOk); - return; - case MediaStreamRequestResult::PERMISSION_DENIED: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kPermissionDenied); - return; - case MediaStreamRequestResult::PERMISSION_DISMISSED: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kPermissionDismissed); - return; - case MediaStreamRequestResult::INVALID_STATE: - RecordMediaStreamRequestResult2(video_type, - MediaStreamRequestResult2::kInvalidState); - return; - case MediaStreamRequestResult::NO_HARDWARE: - RecordMediaStreamRequestResult2(video_type, - MediaStreamRequestResult2::kNoHardware); - return; - case MediaStreamRequestResult::INVALID_SECURITY_ORIGIN: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kInvalidSecurityOrigin); - return; - case MediaStreamRequestResult::TAB_CAPTURE_FAILURE: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kTabCaptureFailure); - return; - case MediaStreamRequestResult::SCREEN_CAPTURE_FAILURE: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kScreenCaptureFailure); - return; - case MediaStreamRequestResult::CAPTURE_FAILURE: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kCaptureFailure); - return; - case MediaStreamRequestResult::CONSTRAINT_NOT_SATISFIED: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kConstraintNotSatisfied); - return; - case MediaStreamRequestResult::TRACK_START_FAILURE_AUDIO: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kTrackStartFailureAudio); - return; - case MediaStreamRequestResult::TRACK_START_FAILURE_VIDEO: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kTrackStartFailureVideo); - return; - case MediaStreamRequestResult::NOT_SUPPORTED: - RecordMediaStreamRequestResult2(video_type, - MediaStreamRequestResult2::kNotSupported); - return; - case MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kFailedDueToShutdown); - return; - case MediaStreamRequestResult::KILL_SWITCH_ON: - RecordMediaStreamRequestResult2(video_type, - MediaStreamRequestResult2::kKillSwitchOn); - return; - case MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED: - RecordMediaStreamRequestResult2( - video_type, MediaStreamRequestResult2::kSystemPermissionDenied); - return; - case MediaStreamRequestResult::DEVICE_IN_USE: - RecordMediaStreamRequestResult2(video_type, - MediaStreamRequestResult2::kDeviceInUse); - return; - case MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS: - break; - } - NOTREACHED(); -} - } // namespace void RecordMediaStreamRequestResponseMetric( @@ -150,11 +118,18 @@ } void RecordMediaStreamRequestResponseUKM( - const url::Origin& main_frame_origin, + ukm::SourceId ukm_source_id, blink::mojom::MediaStreamType video_type, blink::MediaStreamRequestType request_type, blink::mojom::MediaStreamRequestResult result) { - NOTIMPLEMENTED(); + MediaStreamRequestResult2 result2 = MapResultToResult2(result); + ukm::UkmRecorder* const recorder = ukm::UkmRecorder::Get(); + if (video_type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE && + request_type == blink::MEDIA_GENERATE_STREAM) { + ukm::builders::MediaStream_Device(ukm_source_id) + .SetVideoCaptureGenerateStreamResult(static_cast<int64_t>(result2)) + .Record(recorder); + } } } // namespace content::media_stream_metrics
diff --git a/content/browser/renderer_host/media/media_stream_metrics.h b/content/browser/renderer_host/media/media_stream_metrics.h index 79fec2a..dd881884 100644 --- a/content/browser/renderer_host/media/media_stream_metrics.h +++ b/content/browser/renderer_host/media/media_stream_metrics.h
@@ -5,12 +5,9 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_METRICS_H_ #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_METRICS_H_ +#include "services/metrics/public/cpp/ukm_source_id.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" -namespace url { -class Origin; -} - namespace content::media_stream_metrics { void RecordMediaStreamRequestResponseMetric( @@ -19,7 +16,7 @@ blink::mojom::MediaStreamRequestResult result); void RecordMediaStreamRequestResponseUKM( - const url::Origin& main_frame_origin, + ukm::SourceId ukm_source_id, blink::mojom::MediaStreamType video_type, blink::MediaStreamRequestType request_type, blink::mojom::MediaStreamRequestResult result);
diff --git a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc index 7341b53..7531642 100644 --- a/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc
@@ -16,6 +16,7 @@ #include "base/functional/bind.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" #include "base/test/task_environment.h" #include "build/build_config.h" #include "content/browser/renderer_host/media/video_capture_controller.h" @@ -29,6 +30,13 @@ #include "ui/gfx/mac/io_surface.h" #endif +#if BUILDFLAG(IS_WIN) +#include <dxgi1_2.h> +#include <mfapi.h> +#include "media/base/win/dxgi_device_manager.h" +#include "media/capture/video/win/video_capture_buffer_tracker_factory_win.h" +#endif + namespace content { namespace { @@ -40,20 +48,31 @@ } // namespace -static const media::VideoPixelFormat kCapturePixelFormats[] = { +static constexpr media::VideoPixelFormat kCapturePixelFormats[] = { media::PIXEL_FORMAT_I420, media::PIXEL_FORMAT_ARGB, media::PIXEL_FORMAT_Y16, }; -static const int kTestBufferPoolSize = 3; +static constexpr media::VideoCaptureBufferType kVideoCaptureBufferTypes[] = { + media::VideoCaptureBufferType::kSharedMemory, + media::VideoCaptureBufferType::kMailboxHolder, + media::VideoCaptureBufferType::kGpuMemoryBuffer}; + +static constexpr int kTestBufferPoolSize = 3; + +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) +static constexpr gfx::Size kDefaultTextureSize = gfx::Size(1080, 720); +static constexpr int kInvalidId = -1; +#endif // Note that this test does not exercise the class VideoCaptureBufferPool // in isolation. The "unit under test" is an instance of VideoCaptureBufferPool // with some context that is specific to renderer_host/media, and therefore // this test must live here and not in media/capture/video. class VideoCaptureBufferPoolTest - : public testing::TestWithParam<media::VideoPixelFormat> { + : public testing::TestWithParam< + std::tuple<media::VideoPixelFormat, media::VideoCaptureBufferType>> { public: VideoCaptureBufferPoolTest(const VideoCaptureBufferPoolTest&) = delete; VideoCaptureBufferPoolTest& operator=(const VideoCaptureBufferPoolTest&) = @@ -78,11 +97,22 @@ const std::unique_ptr<media::VideoCaptureBufferHandle> buffer_handle_; }; - VideoCaptureBufferPoolTest() - : expected_dropped_id_(0), - pool_(new media::VideoCaptureBufferPoolImpl( - media::VideoCaptureBufferType::kSharedMemory, - kTestBufferPoolSize)) {} + VideoCaptureBufferPoolTest() : expected_dropped_id_(0) { +#if BUILDFLAG(IS_WIN) + auto dxgi_device_manager = + media::DXGIDeviceManager::Create(CHROME_LUID{0, 0}); + DCHECK(dxgi_device_manager); + d3d11_device_ = dxgi_device_manager->GetDevice().Get(); + DCHECK(d3d11_device_); + pool_ = new media::VideoCaptureBufferPoolImpl( + GetBufferType(), kTestBufferPoolSize, + std::make_unique<media::VideoCaptureBufferTrackerFactoryWin>( + std::move(dxgi_device_manager))); +#else + pool_ = new media::VideoCaptureBufferPoolImpl( + media::VideoCaptureBufferType::kSharedMemory, kTestBufferPoolSize); +#endif + } void ExpectDroppedId(int expected_dropped_id) { expected_dropped_id_ = expected_dropped_id; @@ -110,17 +140,26 @@ pool_->GetHandleForInProcessAccess(buffer_id); return std::make_unique<Buffer>(pool_, std::move(buffer_handle), buffer_id); } + media::VideoPixelFormat GetPixelFormat() { return std::get<0>(GetParam()); } + media::VideoCaptureBufferType GetBufferType() { + return std::get<1>(GetParam()); + } +#if BUILDFLAG(IS_WIN) + raw_ptr<ID3D11Device> d3d11_device_ = nullptr; +#endif base::test::SingleThreadTaskEnvironment task_environment_; int expected_dropped_id_; scoped_refptr<media::VideoCaptureBufferPool> pool_; }; TEST_P(VideoCaptureBufferPoolTest, BufferPool) { + media::VideoPixelFormat pixel_format = GetPixelFormat(); + const gfx::Size size_lo = gfx::Size(10, 10); const gfx::Size size_hi = gfx::Size(21, 33); - const media::VideoCaptureFormat format_lo(size_lo, 0.0, GetParam()); - const media::VideoCaptureFormat format_hi(size_hi, 0.0, GetParam()); + const media::VideoCaptureFormat format_lo(size_lo, 0.0, pixel_format); + const media::VideoCaptureFormat format_hi(size_hi, 0.0, pixel_format); // Reallocation won't happen for the first part of the test. ExpectDroppedId(media::VideoCaptureBufferPool::kInvalidId); @@ -129,13 +168,13 @@ // reserved. ASSERT_EQ(0.0, pool_->GetBufferPoolUtilization()); - std::unique_ptr<Buffer> buffer1 = ReserveBuffer(size_lo, GetParam()); + std::unique_ptr<Buffer> buffer1 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer1.get()); ASSERT_EQ(1.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - std::unique_ptr<Buffer> buffer2 = ReserveBuffer(size_lo, GetParam()); + std::unique_ptr<Buffer> buffer2 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer2.get()); ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - std::unique_ptr<Buffer> buffer3 = ReserveBuffer(size_lo, GetParam()); + std::unique_ptr<Buffer> buffer3 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer3.get()); ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); @@ -156,19 +195,19 @@ memset(buffer3->data(), 0x77, buffer3->mapped_size()); // Fourth buffer should fail. Buffer pool utilization should be at 100%. - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // Release 1st buffer and retry; this should succeed. buffer1.reset(); ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - std::unique_ptr<Buffer> buffer4 = ReserveBuffer(size_lo, GetParam()); + std::unique_ptr<Buffer> buffer4 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer4.get()); ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_hi, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_hi, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // Validate the IDs @@ -183,36 +222,36 @@ // Deliver a buffer. pool_->HoldForConsumers(buffer_id3, 2); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); buffer3.reset(); // Old producer releases buffer. Should be a noop. - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_hi, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_hi, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); buffer2.reset(); // Active producer releases buffer. Should free a buffer. - buffer1 = ReserveBuffer(size_lo, GetParam()); + buffer1 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer1.get()); ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // First consumer finishes. pool_->RelinquishConsumerHold(buffer_id3, 1); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // Second consumer finishes. This should free that buffer. pool_->RelinquishConsumerHold(buffer_id3, 1); - buffer3 = ReserveBuffer(size_lo, GetParam()); + buffer3 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer3.get()); ASSERT_EQ(buffer_id3, buffer3->id()) << "Buffer ID should be reused."; ASSERT_EQ(memory_pointer3, buffer3->data()); ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // Now deliver & consume buffer1, but don't release the buffer. @@ -225,16 +264,16 @@ // be re-allocated to the producer, because |buffer1| still references it. But // when |buffer1| goes away, we should be able to re-reserve the buffer (and // the ID ought to be the same). - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); buffer1.reset(); // Should free the buffer. ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - buffer2 = ReserveBuffer(size_lo, GetParam()); + buffer2 = ReserveBuffer(size_lo, pixel_format); ASSERT_NE(nullptr, buffer2.get()); ASSERT_EQ(buffer_id1, buffer2->id()); buffer_id2 = buffer_id1; ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // Now try reallocation with different resolutions. We expect reallocation @@ -242,7 +281,7 @@ buffer2.reset(); ExpectDroppedId(buffer_id2); ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - buffer2 = ReserveBuffer(size_hi, GetParam()); + buffer2 = ReserveBuffer(size_hi, pixel_format); ASSERT_NE(nullptr, buffer2.get()); ASSERT_LE(ImageAllocationSize(format_hi), buffer2->mapped_size()); ASSERT_EQ(3, buffer2->id()); @@ -251,7 +290,7 @@ buffer2.reset(); // Frees it. ExpectDroppedId(media::VideoCaptureBufferPool::kInvalidId); ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - buffer2 = ReserveBuffer(size_lo, GetParam()); + buffer2 = ReserveBuffer(size_lo, pixel_format); void* const memory_pointer_lo = buffer2->data(); ASSERT_EQ(memory_pointer_hi, memory_pointer_lo) << "Decrease in resolution should not reallocate buffer"; @@ -259,7 +298,7 @@ ASSERT_EQ(3, buffer2->id()); ASSERT_LE(ImageAllocationSize(format_lo), buffer2->mapped_size()); ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization()); - ASSERT_FALSE(ReserveBuffer(size_lo, GetParam())) << "Pool should be empty"; + ASSERT_FALSE(ReserveBuffer(size_lo, pixel_format)) << "Pool should be empty"; ASSERT_EQ(1.0, pool_->GetBufferPoolUtilization()); // Tear down the pool_, writing into the buffers. The buffer should preserve @@ -280,6 +319,123 @@ buffer4.reset(); } +#if BUILDFLAG(IS_WIN) +namespace { + +gfx::GpuMemoryBufferHandle CreateHandle(ID3D11Device* d3d11_device) { + EXPECT_TRUE(d3d11_device != nullptr); + + D3D11_TEXTURE2D_DESC desc = {}; + desc.Width = kDefaultTextureSize.width(); + desc.Height = kDefaultTextureSize.height(); + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_NV12; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.SampleDesc.Count = 1; + desc.BindFlags = 0; + desc.MiscFlags = + D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE; + + ID3D11Texture2D* texture = nullptr; + HRESULT hr = d3d11_device->CreateTexture2D(&desc, nullptr, &texture); + EXPECT_HRESULT_SUCCEEDED(hr); + + Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource; + hr = texture->QueryInterface(IID_PPV_ARGS(&dxgi_resource)); + EXPECT_HRESULT_SUCCEEDED(hr); + + HANDLE texture_handle; + hr = dxgi_resource->CreateSharedHandle( + nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, nullptr, + &texture_handle); + EXPECT_HRESULT_SUCCEEDED(hr); + + gfx::GpuMemoryBufferHandle result; + result.type = gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE; + result.dxgi_handle.Set(texture_handle); + result.dxgi_token = gfx::DXGIHandleToken(); + return result; +} + +} // namespace + +TEST_P(VideoCaptureBufferPoolTest, BufferPoolExternalWin) { + auto handle0 = CreateHandle(d3d11_device_); + auto handle1 = CreateHandle(d3d11_device_); + auto handle2 = CreateHandle(d3d11_device_); + int buffer_id_to_drop; + int buffer_id0 = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + std::move(handle0), media::VideoPixelFormat::PIXEL_FORMAT_NV12, + kDefaultTextureSize, &buffer_id_to_drop, &buffer_id0), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); + EXPECT_NE(buffer_id0, kInvalidId); + EXPECT_EQ(buffer_id_to_drop, kInvalidId); + pool_->HoldForConsumers(buffer_id0, 1); + pool_->RelinquishProducerReservation(buffer_id0); + // We should get a new buffer for handle1. + int buffer_id1 = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + std::move(handle1), media::VideoPixelFormat::PIXEL_FORMAT_NV12, + kDefaultTextureSize, &buffer_id_to_drop, &buffer_id1), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); + EXPECT_NE(buffer_id1, kInvalidId); + EXPECT_EQ(buffer_id_to_drop, kInvalidId); + pool_->HoldForConsumers(buffer_id1, 1); + pool_->RelinquishProducerReservation(buffer_id1); + pool_->RelinquishConsumerHold(buffer_id1, 1); + // We should reuse handle1's buffer. + int buffer_id1_reuse = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + pool_->GetGpuMemoryBufferHandle(buffer_id1), + media::VideoPixelFormat::PIXEL_FORMAT_NV12, kDefaultTextureSize, + &buffer_id_to_drop, &buffer_id1_reuse), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); + EXPECT_EQ(buffer_id1, buffer_id1_reuse); + EXPECT_EQ(buffer_id_to_drop, kInvalidId); + pool_->HoldForConsumers(buffer_id1_reuse, 1); + pool_->RelinquishProducerReservation(buffer_id1_reuse); + // If we leave buffer_id1 held for a consumer, then we create a new buffer id + // for it. + int buffer_id1_new = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + pool_->GetGpuMemoryBufferHandle(buffer_id1), + media::VideoPixelFormat::PIXEL_FORMAT_NV12, kDefaultTextureSize, + &buffer_id_to_drop, &buffer_id1_new), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); + EXPECT_NE(buffer_id1, buffer_id1_new); + EXPECT_EQ(buffer_id_to_drop, kInvalidId); + pool_->HoldForConsumers(buffer_id1_new, 1); + pool_->RelinquishProducerReservation(buffer_id1_new); + pool_->RelinquishConsumerHold(buffer_id1_new, 1); + // We have now reached kTestBufferPoolSize buffers. So our next allocation + // will return the LRU buffer, which is buffer_id1_new. + pool_->RelinquishConsumerHold(buffer_id1_reuse, 1); + int buffer_id2 = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + std::move(handle2), media::VideoPixelFormat::PIXEL_FORMAT_NV12, + kDefaultTextureSize, &buffer_id_to_drop, &buffer_id2), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); + EXPECT_NE(buffer_id0, buffer_id2); + EXPECT_NE(buffer_id1, buffer_id2); + EXPECT_NE(buffer_id1_new, buffer_id2); + EXPECT_EQ(buffer_id_to_drop, buffer_id1_new); + EXPECT_NE(buffer_id2, kInvalidId); + // Finally, let's reuse handle0. + pool_->RelinquishConsumerHold(buffer_id0, 1); + int buffer_id0_reuse = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + pool_->GetGpuMemoryBufferHandle(buffer_id0), + media::VideoPixelFormat::PIXEL_FORMAT_NV12, kDefaultTextureSize, + &buffer_id_to_drop, &buffer_id0_reuse), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); + EXPECT_EQ(buffer_id0, buffer_id0_reuse); + EXPECT_EQ(buffer_id_to_drop, kInvalidId); +} + +#endif + #if BUILDFLAG(IS_MAC) namespace { @@ -288,7 +444,7 @@ result.type = gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER; result.id = gfx::GpuMemoryBufferHandle::kInvalidId; result.io_surface.reset( - gfx::CreateIOSurface(gfx::Size(100, 100), gfx::BufferFormat::BGRA_8888)); + gfx::CreateIOSurface(kDefaultTextureSize, gfx::BufferFormat::BGRA_8888)); return result; } @@ -299,66 +455,85 @@ auto handle1 = CreateIOSurfaceHandle(); auto handle2 = CreateIOSurfaceHandle(); - constexpr int kInvalidId = -1; int buffer_id_to_drop; - - int buffer_id0 = - pool_->ReserveIdForExternalBuffer(handle0, &buffer_id_to_drop); + int buffer_id0 = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + std::move(handle0), media::VideoPixelFormat::PIXEL_FORMAT_NV12, + kDefaultTextureSize, &buffer_id_to_drop, &buffer_id0), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); EXPECT_NE(buffer_id0, kInvalidId); EXPECT_EQ(buffer_id_to_drop, kInvalidId); - EXPECT_FALSE(IOSurfaceIsInUse(handle0.io_surface)); + EXPECT_FALSE( + IOSurfaceIsInUse(pool_->GetGpuMemoryBufferHandle(buffer_id0).io_surface)); pool_->HoldForConsumers(buffer_id0, 1); - EXPECT_TRUE(IOSurfaceIsInUse(handle0.io_surface)); + EXPECT_TRUE( + IOSurfaceIsInUse(pool_->GetGpuMemoryBufferHandle(buffer_id0).io_surface)); pool_->RelinquishProducerReservation(buffer_id0); - // We should get a new buffer for handle1. - int buffer_id1 = - pool_->ReserveIdForExternalBuffer(handle1, &buffer_id_to_drop); + int buffer_id1 = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + std::move(handle1), media::VideoPixelFormat::PIXEL_FORMAT_NV12, + kDefaultTextureSize, &buffer_id_to_drop, &buffer_id1), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); EXPECT_NE(buffer_id1, kInvalidId); EXPECT_EQ(buffer_id_to_drop, kInvalidId); pool_->HoldForConsumers(buffer_id1, 1); pool_->RelinquishProducerReservation(buffer_id1); pool_->RelinquishConsumerHold(buffer_id1, 1); - // We should reuse handle1's buffer. - int buffer_id1_reuse = - pool_->ReserveIdForExternalBuffer(handle1, &buffer_id_to_drop); + int buffer_id1_reuse = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + pool_->GetGpuMemoryBufferHandle(buffer_id1), + media::VideoPixelFormat::PIXEL_FORMAT_NV12, kDefaultTextureSize, + &buffer_id_to_drop, &buffer_id1_reuse), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); EXPECT_EQ(buffer_id1, buffer_id1_reuse); EXPECT_EQ(buffer_id_to_drop, kInvalidId); pool_->HoldForConsumers(buffer_id1_reuse, 1); pool_->RelinquishProducerReservation(buffer_id1_reuse); - // If we leave buffer_id1 held for a consumer, then we create a new buffer id // for it. - int buffer_id1_new = - pool_->ReserveIdForExternalBuffer(handle1, &buffer_id_to_drop); + int buffer_id1_new = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + pool_->GetGpuMemoryBufferHandle(buffer_id1), + media::VideoPixelFormat::PIXEL_FORMAT_NV12, kDefaultTextureSize, + &buffer_id_to_drop, &buffer_id1_new), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); EXPECT_NE(buffer_id1, buffer_id1_new); EXPECT_EQ(buffer_id_to_drop, kInvalidId); pool_->HoldForConsumers(buffer_id1_new, 1); pool_->RelinquishProducerReservation(buffer_id1_new); pool_->RelinquishConsumerHold(buffer_id1_new, 1); - // We have now reached kTestBufferPoolSize buffers. So our next allocation // will return the LRU buffer, which is buffer_id1_new. pool_->RelinquishConsumerHold(buffer_id1_reuse, 1); - int buffer_id2 = - pool_->ReserveIdForExternalBuffer(handle2, &buffer_id_to_drop); + int buffer_id2 = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + std::move(handle2), media::VideoPixelFormat::PIXEL_FORMAT_NV12, + kDefaultTextureSize, &buffer_id_to_drop, &buffer_id2), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); EXPECT_NE(buffer_id0, buffer_id2); EXPECT_NE(buffer_id1, buffer_id2); EXPECT_NE(buffer_id1_new, buffer_id2); + EXPECT_NE(buffer_id2, kInvalidId); EXPECT_EQ(buffer_id_to_drop, buffer_id1_new); - // Finally, let's reuse handle0. pool_->RelinquishConsumerHold(buffer_id0, 1); - int buffer_id0_reuse = - pool_->ReserveIdForExternalBuffer(handle0, &buffer_id_to_drop); + int buffer_id0_reuse = kInvalidId; + EXPECT_EQ(pool_->ReserveIdForExternalBuffer( + pool_->GetGpuMemoryBufferHandle(buffer_id0), + media::VideoPixelFormat::PIXEL_FORMAT_NV12, kDefaultTextureSize, + &buffer_id_to_drop, &buffer_id0_reuse), + media::VideoCaptureDevice::Client::ReserveResult::kSucceeded); EXPECT_EQ(buffer_id0, buffer_id0_reuse); EXPECT_EQ(buffer_id_to_drop, kInvalidId); } #endif -INSTANTIATE_TEST_SUITE_P(All, - VideoCaptureBufferPoolTest, - testing::ValuesIn(kCapturePixelFormats)); +INSTANTIATE_TEST_SUITE_P( + All, + VideoCaptureBufferPoolTest, + testing::Combine(testing::ValuesIn(kCapturePixelFormats), + testing::ValuesIn(kVideoCaptureBufferTypes))); } // namespace content
diff --git a/content/browser/webauth/authenticator_common_impl.cc b/content/browser/webauth/authenticator_common_impl.cc index 4578a752..21015d78 100644 --- a/content/browser/webauth/authenticator_common_impl.cc +++ b/content/browser/webauth/authenticator_common_impl.cc
@@ -364,8 +364,7 @@ if (make_credential_options.resident_key == device::ResidentKeyRequirement::kRequired && make_credential_options.user_verification == - device::UserVerificationRequirement::kPreferred && - base::FeatureList::IsEnabled(device::kWebAuthnCredProtectThree)) { + device::UserVerificationRequirement::kPreferred) { return device::CredProtectRequest::kUVRequired; } if (make_credential_options.resident_key !=
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index e4c3a49..4e2e722 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -116,6 +116,7 @@ #if BUILDFLAG(IS_MAC) #include "device/fido/mac/authenticator_config.h" #include "device/fido/mac/credential_store.h" +#include "device/fido/mac/scoped_icloud_keychain_test_environment.h" #include "device/fido/mac/scoped_touch_id_test_environment.h" #endif @@ -8980,6 +8981,128 @@ EXPECT_EQ(GetCredentials(kTestRelyingPartyId).size(), 2u); } +class ICloudKeychainAuthenticatorImplTest : public AuthenticatorImplTest { + protected: + class InspectTAIAuthenticatorRequestDelegate + : public AuthenticatorRequestClientDelegate { + public: + using Callback = base::RepeatingCallback<void( + const device::FidoRequestHandlerBase::TransportAvailabilityInfo&)>; + explicit InspectTAIAuthenticatorRequestDelegate(Callback callback) + : callback_(std::move(callback)) {} + + void OnTransportAvailabilityEnumerated( + device::FidoRequestHandlerBase::TransportAvailabilityInfo tai) + override { + callback_.Run(tai); + } + + private: + Callback callback_; + }; + + class InspectTAIContentBrowserClient : public ContentBrowserClient { + public: + explicit InspectTAIContentBrowserClient( + InspectTAIAuthenticatorRequestDelegate::Callback callback) + : callback_(std::move(callback)) {} + + std::unique_ptr<AuthenticatorRequestClientDelegate> + GetWebAuthenticationRequestDelegate( + RenderFrameHost* render_frame_host) override { + return std::make_unique<InspectTAIAuthenticatorRequestDelegate>( + callback_); + } + + private: + InspectTAIAuthenticatorRequestDelegate::Callback callback_; + }; + + void SetUp() override { + AuthenticatorImplTest::SetUp(); + old_client_ = SetBrowserClientForTesting(&test_client_); + // This test uses the real discoveries and sets the transports on an + // allowlist entry to limit it to kInternal. + AuthenticatorEnvironment::GetInstance()->Reset(); + } + + void TearDown() override { + SetBrowserClientForTesting(old_client_); + AuthenticatorImplTest::TearDown(); + } + + void OnTransportAvailabilityEnumerated( + const device::FidoRequestHandlerBase::TransportAvailabilityInfo& tai) { + if (tai_callback_) { + std::move(tai_callback_).Run(tai); + } + } + + static std::vector<device::DiscoverableCredentialMetadata> GetCredentials() { + device::DiscoverableCredentialMetadata metadata( + device::AuthenticatorType::kICloudKeychain, kTestRelyingPartyId, + {1, 2, 3, 4}, {{5, 6, 7, 8}, "name", "displayName"}); + return {std::move(metadata)}; + } + + InspectTAIContentBrowserClient test_client_{base::BindRepeating( + &ICloudKeychainAuthenticatorImplTest::OnTransportAvailabilityEnumerated, + base::Unretained(this))}; + raw_ptr<ContentBrowserClient> old_client_ = nullptr; + InspectTAIAuthenticatorRequestDelegate::Callback tai_callback_; +}; + +TEST_F(ICloudKeychainAuthenticatorImplTest, Discovery) { + if (__builtin_available(macOS 13.3, *)) { + for (const bool feature_enabled : {false, true}) { + SCOPED_TRACE(feature_enabled); + + absl::optional<base::test::ScopedFeatureList> scoped_feature_list; + if (feature_enabled) { + scoped_feature_list.emplace(device::kWebAuthnICloudKeychain); + } + + NavigateAndCommit(GURL(kTestOrigin1)); + device::fido::icloud_keychain::ScopedTestEnvironment test_environment( + GetCredentials()); + bool tai_seen = false; + tai_callback_ = base::BindLambdaForTesting( + [&tai_seen, feature_enabled]( + const device::FidoRequestHandlerBase::TransportAvailabilityInfo& + tai) { + tai_seen = true; + CHECK_EQ(tai.has_icloud_keychain, feature_enabled); + CHECK_EQ(tai.recognized_platform_authenticator_credentials.size(), + feature_enabled ? 1u : 0u); + CHECK_EQ(tai.has_icloud_keychain_credential, + feature_enabled + ? device::FidoRequestHandlerBase:: + RecognizedCredential::kHasRecognizedCredential + : device::FidoRequestHandlerBase:: + RecognizedCredential::kNoRecognizedCredential); + + if (feature_enabled) { + CHECK_EQ(tai.recognized_platform_authenticator_credentials[0] + .user.name.value(), + "name"); + } + }); + + auto options = GetTestPublicKeyCredentialRequestOptions(); + options->allow_credentials.clear(); + options->allow_credentials.push_back( + device::PublicKeyCredentialDescriptor( + device::CredentialType::kPublicKey, {1, 2, 3, 4}, + {device::FidoTransportProtocol::kInternal})); + const auto result = AuthenticatorGetAssertion(std::move(options)); + EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR); + EXPECT_TRUE(tai_seen); + } + } else { + GTEST_SKIP() << "Need macOS 13.3 for this test"; + } +} + #endif // BUILDFLAG(IS_MAC) // AuthenticatorCableV2Test tests features of the caBLEv2 transport and @@ -9496,8 +9619,6 @@ std::unique_ptr<device::cablev2::authenticator::Transaction> transaction_; bool did_complete_ = false; absl::optional<device::cablev2::authenticator::Platform::Error> error_; - base::test::ScopedFeatureList scoped_feature_list_{ - device::kWebAuthnPRFAsAuthenticator}; }; TEST_F(AuthenticatorCableV2AuthenticatorTest, GetAssertion) {
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index ceb29e0..d5cd506a 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -335,6 +335,10 @@ runtimeFeatureNameToChromiumFeatureMapping[] = { {"AllowContentInitiatedDataUrlNavigations", raw_ref(features::kAllowContentInitiatedDataUrlNavigations)}, + {"AllowURNsInIframes", raw_ref(blink::features::kAllowURNsInIframes)}, + {"AllowURNsInIframes", + raw_ref(features::kPrivacySandboxAdsAPIsOverride), + kSetOnlyIfOverridden}, {"AttributionReporting", raw_ref(features::kPrivacySandboxAdsAPIsOverride), kSetOnlyIfOverridden},
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn index c901125..23b3e99 100644 --- a/content/public/test/android/BUILD.gn +++ b/content/public/test/android/BUILD.gn
@@ -28,7 +28,6 @@ "//content/public/android:content_java", "//mojo/public/java:bindings_java", "//net/android:net_java", - "//net/android:net_java_test_support", "//services/service_manager/public/java:service_manager_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_test_monitor_java",
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java index 5e50ae8b..6c3d062e 100644 --- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java +++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java
@@ -10,7 +10,6 @@ import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.SkipCheck; -import org.chromium.net.test.EmbeddedTestServer; import org.chromium.ui.test.util.DeviceRestrictionSkipCheck; import org.chromium.ui.test.util.UiDisableIfSkipCheck; import org.chromium.ui.test.util.UiRestrictionSkipCheck; @@ -45,9 +44,4 @@ protected List<TestHook> getPreTestHooks() { return addToList(super.getPreTestHooks(), new ChildProcessAllocatorSettingsHook()); } - - @Override - protected List<ClassHook> getPreClassHooks() { - return addToList(super.getPreClassHooks(), EmbeddedTestServer.getPreClassHook()); - } }
diff --git a/content/renderer/pepper/pepper_webplugin_impl.cc b/content/renderer/pepper/pepper_webplugin_impl.cc index 15045c2..ac620c5 100644 --- a/content/renderer/pepper/pepper_webplugin_impl.cc +++ b/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -83,7 +83,7 @@ // Set subresource URL for crash reporting. static auto* const subresource_url = base::debug::AllocateCrashKeyString( "subresource_url", base::debug::CrashKeySize::Size256); - base::debug::SetCrashKeyString(subresource_url, init_data_->url.spec()); + base::debug::SetCrashKeyString(subresource_url, init_data_->url.possibly_invalid_spec()); } PepperWebPluginImpl::~PepperWebPluginImpl() {}
diff --git a/content/services/auction_worklet/bidder_worklet_unittest.cc b/content/services/auction_worklet/bidder_worklet_unittest.cc index 79aebef..491f4a9 100644 --- a/content/services/auction_worklet/bidder_worklet_unittest.cc +++ b/content/services/auction_worklet/bidder_worklet_unittest.cc
@@ -6909,7 +6909,7 @@ CreateGenerateBidScript( R"({ad: "ad", bid:1, render:"https://response.test/" })", /*extra_code=*/R"( - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); privateAggregation.contributeToHistogram({bucket: 123n, value: 45}); privateAggregation.contributeToHistogramOnEvent( "reserved.win", {bucket: 234n, value: 56}); @@ -7201,7 +7201,7 @@ RunReportWinWithFunctionBodyExpectingResult( R"( - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); privateAggregation.contributeToHistogram({bucket: 123n, value: 45}); privateAggregation.contributeToHistogramOnEvent( "reserved.win", {bucket: 234n, value: 56});
diff --git a/content/services/auction_worklet/context_recycler_unittest.cc b/content/services/auction_worklet/context_recycler_unittest.cc index 05f4edc7..44913446 100644 --- a/content/services/auction_worklet/context_recycler_unittest.cc +++ b/content/services/auction_worklet/context_recycler_unittest.cc
@@ -1272,7 +1272,7 @@ template <typename T> v8::Local<v8::Value> WrapDebugKey(T debug_key) { gin::Dictionary dict = gin::Dictionary::CreateEmpty(helper_->isolate()); - dict.Set("debug_key", debug_key); + dict.Set("debugKey", debug_key); return gin::ConvertToV8(helper_->isolate(), dict); } @@ -1671,8 +1671,8 @@ // Passing BigInts in directly is complicated so we construct them from // strings. - if (typeof arg.debug_key === "string") { - arg.debug_key = BigInt(arg.debug_key); + if (typeof arg.debugKey === "string") { + arg.debugKey = BigInt(arg.debugKey); } privateAggregation.enableDebugMode(arg); } @@ -1800,7 +1800,7 @@ EXPECT_THAT( error_msgs, ElementsAre("https://example.org/script.js:21 Uncaught TypeError: " - "debug_key must be a BigInt.")); + "debugKey must be a BigInt.")); EXPECT_TRUE(context_recycler.private_aggregation_bindings() ->TakePrivateAggregationRequests()
diff --git a/content/services/auction_worklet/seller_worklet_unittest.cc b/content/services/auction_worklet/seller_worklet_unittest.cc index a774039..8fba017 100644 --- a/content/services/auction_worklet/seller_worklet_unittest.cc +++ b/content/services/auction_worklet/seller_worklet_unittest.cc
@@ -4744,7 +4744,7 @@ RunScoreAdWithJavascriptExpectingResult( CreateScoreAdScript("5", R"( - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); privateAggregation.contributeToHistogram({bucket: 123n, value: 45}); privateAggregation.contributeToHistogramOnEvent( "reserved.win", {bucket: 234n, value: 56}); @@ -4973,7 +4973,7 @@ RunReportResultCreatedScriptExpectingResult( "5", R"( - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); privateAggregation.contributeToHistogram({bucket: 123n, value: 45}); )", /*expected_signals_for_winner=*/"5",
diff --git a/content/services/worklet_utils/private_aggregation_utils.cc b/content/services/worklet_utils/private_aggregation_utils.cc index 94af23b0..fa04017 100644 --- a/content/services/worklet_utils/private_aggregation_utils.cc +++ b/content/services/worklet_utils/private_aggregation_utils.cc
@@ -67,7 +67,7 @@ return absl::Uint128Low64(maybe_debug_key.value()); } - *error_out = "debug_key must be a BigInt"; + *error_out = "debugKey must be a BigInt"; return absl::nullopt; } @@ -228,7 +228,8 @@ } v8::Local<v8::Value> js_debug_key; - if (!dict.Get("debug_key", &js_debug_key)) { + + if (!dict.Get("debugKey", &js_debug_key)) { // Propagate any exception return; }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index f9d76b2..9c6b847 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -3084,6 +3084,7 @@ } if (is_mac) { deps += [ + "//device/fido:icloud_keychain_test_support", "//sandbox/mac:seatbelt", "//third_party/ocmock", "//ui/accelerated_widget_mac", @@ -3092,6 +3093,7 @@ frameworks = [ "Carbon.framework", "IOSurface.framework", + "AuthenticationServices.framework", ] } if (is_chromeos_ash) {
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 bc21d9f1..02ee52a 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
@@ -416,6 +416,8 @@ crbug.com/1316389 [ amd-0x67ef angle-metal passthrough ventura ] deqp/functional/gles3/transformfeedback/point_size.html [ Failure ] crbug.com/1316389 [ amd-0x67ef angle-metal passthrough ventura ] deqp/functional/gles3/transformfeedback/random_interleaved_points.html [ Failure ] crbug.com/1316389 [ amd-0x67ef angle-metal passthrough ventura ] deqp/functional/gles3/transformfeedback/random_separate_points.html [ Failure ] +crbug.com/1435021 [ mac amd-0x67ef angle-metal ] conformance/textures/misc/texture-active-bind.html [ RetryOnFailure ] +crbug.com/1435021 [ mac amd-0x67ef angle-metal ] conformance/textures/misc/texture-active-bind-2.html [ RetryOnFailure ] crbug.com/1435021 [ mac amd-0x67ef angle-metal ] conformance/canvas/draw-webgl-to-canvas-test.html [ RetryOnFailure ] ## Metal Intel ##
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 170de4e..67d5bd7 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
@@ -503,7 +503,8 @@ crbug.com/1422032 [ mac amd-0x67ef angle-opengl ] conformance/renderbuffers/stencil-renderbuffer-initialization.html [ Failure ] crbug.com/1435021 [ mac amd-0x67ef angle-metal ] conformance/textures/misc/texture-active-bind.html [ Failure ] -crbug.com/1442626 [ mac amd-0x67ef angle-metal ] conformance/canvas/draw-webgl-to-canvas-test.html [ RetryOnFailure ] +crbug.com/1435021 [ mac amd-0x67ef angle-metal ] conformance/textures/misc/texture-active-bind-2.html [ RetryOnFailure ] +crbug.com/1435021 [ mac amd-0x67ef angle-metal ] conformance/canvas/draw-webgl-to-canvas-test.html [ RetryOnFailure ] ## Mac Intel ##
diff --git a/device/BUILD.gn b/device/BUILD.gn index b1f5e18..59de793 100644 --- a/device/BUILD.gn +++ b/device/BUILD.gn
@@ -27,7 +27,6 @@ "fido/mac/authenticator_unittest.mm", "fido/mac/browsing_data_deletion_unittest.mm", "fido/mac/credential_store_unittest.mm", - "fido/mac/fake_icloud_keychain_sys.mm", "fido/mac/get_assertion_operation_unittest_mac.mm", "fido/mac/icloud_keychain_unittest.mm", "fido/mac/make_credential_operation_unittest_mac.mm", @@ -37,6 +36,7 @@ "//base/test:test_support", "//device/base:base", "//device/fido", + "//device/fido:icloud_keychain_test_support", "//device/fido:mocks", "//device/fido:test_support", "//services/data_decoder/public/cpp:test_support",
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index 1c826e8..0b093b0e 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -463,3 +463,23 @@ configs += [ "//build/config/compiler:enable_arc" ] } } + +# This is split from `test_support` because it requires the +# AuthenticationServices framework to be linked in, and that can't just be done +# as a dep/framework here. +if (is_mac) { + static_library("icloud_keychain_test_support") { + testonly = true + sources = [ + "mac/fake_icloud_keychain_sys.h", + "mac/fake_icloud_keychain_sys.mm", + "mac/scoped_icloud_keychain_test_environment.h", + "mac/scoped_icloud_keychain_test_environment.mm", + ] + deps = [ + "//base", + "//device/fido", + ] + configs += [ "//build/config/compiler:enable_arc" ] + } +}
diff --git a/device/fido/cable/v2_authenticator.cc b/device/fido/cable/v2_authenticator.cc index eadee7ba0..2f18351 100644 --- a/device/fido/cable/v2_authenticator.cc +++ b/device/fido/cable/v2_authenticator.cc
@@ -260,9 +260,7 @@ cbor::Value::ArrayValue extensions; extensions.emplace_back("devicePubKey"); - if (base::FeatureList::IsEnabled(kWebAuthnPRFAsAuthenticator)) { - extensions.emplace_back("prf"); - } + extensions.emplace_back("prf"); cbor::Value::MapValue response_map; response_map.emplace(1, std::move(versions));
diff --git a/device/fido/features.cc b/device/fido/features.cc index 4248593..d38c660 100644 --- a/device/fido/features.cc +++ b/device/fido/features.cc
@@ -36,16 +36,6 @@ "WebAuthenticationPasskeysUI", base::FEATURE_ENABLED_BY_DEFAULT); -// Added in M112. Remove in or after M115. -BASE_FEATURE(kWebAuthnCredProtectThree, - "WebAuthenticationCredProtectThree", - base::FEATURE_ENABLED_BY_DEFAULT); - -// Added in M112. Enabled in M113. Remove in or after M116. -BASE_FEATURE(kWebAuthnPRFAsAuthenticator, - "WebAuthenticationPRFAsAuthenticator", - base::FEATURE_ENABLED_BY_DEFAULT); - // Added in M113. Remove in or after M116. BASE_FEATURE(kWebAuthnMacPlatformAuthenticatorOptionalUv, "WebAuthenticationMacPlatformAuthenticatorOptionalUv",
diff --git a/device/fido/features.h b/device/fido/features.h index be189d97..7c638aa 100644 --- a/device/fido/features.h +++ b/device/fido/features.h
@@ -36,14 +36,6 @@ // Enable some experimental UI changes COMPONENT_EXPORT(DEVICE_FIDO) BASE_DECLARE_FEATURE(kWebAuthPasskeysUI); -// Set credProtect=3 when rk=required and uv=preferred. -COMPONENT_EXPORT(DEVICE_FIDO) -BASE_DECLARE_FEATURE(kWebAuthnCredProtectThree); - -// Advertise support for the `prf` extension as a hybrid authenticator. -COMPONENT_EXPORT(DEVICE_FIDO) -BASE_DECLARE_FEATURE(kWebAuthnPRFAsAuthenticator); - // Support optional UV for new credentials in the macOS platform authenticator. COMPONENT_EXPORT(DEVICE_FIDO) BASE_DECLARE_FEATURE(kWebAuthnMacPlatformAuthenticatorOptionalUv);
diff --git a/device/fido/fido_discovery_factory.cc b/device/fido/fido_discovery_factory.cc index 22b6d887..0ac3665 100644 --- a/device/fido/fido_discovery_factory.cc +++ b/device/fido/fido_discovery_factory.cc
@@ -15,6 +15,7 @@ #include "device/fido/cable/v2_discovery.h" #include "device/fido/features.h" #include "device/fido/fido_discovery_base.h" +#include "device/fido/mac/icloud_keychain.h" // HID is not supported on Android. #if !BUILDFLAG(IS_ANDROID) @@ -214,11 +215,16 @@ #if BUILDFLAG(IS_MAC) std::vector<std::unique_ptr<FidoDiscoveryBase>> FidoDiscoveryFactory::MaybeCreatePlatformDiscovery() const { + std::vector<std::unique_ptr<FidoDiscoveryBase>> ret; if (mac_touch_id_config_) { - return SingleDiscovery(std::make_unique<fido::mac::FidoTouchIdDiscovery>( + ret.emplace_back(std::make_unique<fido::mac::FidoTouchIdDiscovery>( *mac_touch_id_config_)); } - return {}; + if (base::FeatureList::IsEnabled(kWebAuthnICloudKeychain) && + fido::icloud_keychain::IsSupported()) { + ret.emplace_back(fido::icloud_keychain::NewDiscovery(nswindow_)); + } + return ret; } #endif
diff --git a/device/fido/fido_discovery_factory.h b/device/fido/fido_discovery_factory.h index 785d4151..1be0ebd2 100644 --- a/device/fido/fido_discovery_factory.h +++ b/device/fido/fido_discovery_factory.h
@@ -97,6 +97,10 @@ absl::optional<fido::mac::AuthenticatorConfig> mac_touch_id_config) { mac_touch_id_config_ = std::move(mac_touch_id_config); } + // Sets the window on top of which macOS will show any iCloud Keychain UI. + // This is passed as a `uintptr_t` to avoid handling `NSWindow` (an ObjC++ + // type) in C++. See crbug.com/1433041. + void set_nswindow(uintptr_t window) { nswindow_ = window; } #endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_WIN) @@ -140,6 +144,7 @@ #if BUILDFLAG(IS_MAC) absl::optional<fido::mac::AuthenticatorConfig> mac_touch_id_config_; + uintptr_t nswindow_ = 0; #endif // BUILDFLAG(IS_MAC) absl::optional<mojo::Remote<device::mojom::UsbDeviceManager>> usb_device_manager_;
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc index 218b7db8..5845360 100644 --- a/device/fido/fido_request_handler_base.cc +++ b/device/fido/fido_request_handler_base.cc
@@ -8,6 +8,7 @@ #include "base/containers/contains.h" #include "base/containers/cxx20_erase.h" +#include "base/feature_list.h" #include "base/functional/bind.h" #include "base/location.h" #include "base/logging.h" @@ -19,8 +20,10 @@ #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/fido/ble_adapter_manager.h" #include "device/fido/discoverable_credential_metadata.h" +#include "device/fido/features.h" #include "device/fido/fido_authenticator.h" #include "device/fido/fido_discovery_factory.h" +#include "device/fido/mac/icloud_keychain.h" #if BUILDFLAG(IS_WIN) #include "device/fido/win/authenticator.h" @@ -44,12 +47,12 @@ // callback is pending BLE status information. bool ble_information_pending = false; - // platform_credential_check_pending is true if the + // num_platform_credential_checks_pending is true if the // |OnTransportAvailabilityEnumerated| callback is pending // |OnHasRecognizedPlatformCredentialFilled| being called after the platform // authenticator has decided if it has credentials that are responsive to the // request. - bool platform_credential_check_pending = false; + unsigned num_platform_credential_checks_pending = 0; // win_is_uvpaa_check_pending is true if |OnTransportAvailabilityEnumerated| // callback is pending |OnIsUvpaa| being called. @@ -61,8 +64,8 @@ bool CanMakeCallback() const { return !callback_made && !ble_information_pending && - !platform_credential_check_pending && !win_is_uvpaa_check_pending && - num_discoveries_pending == 0; + num_platform_credential_checks_pending == 0 && + !win_is_uvpaa_check_pending && num_discoveries_pending == 0; } }; @@ -330,13 +333,16 @@ if (discovery->transport() == FidoTransportProtocol::kInternal && // |authenticators| can be empty in tests. !authenticators.empty()) { - DCHECK(!internal_authenticator_found_); internal_authenticator_found_ = true; - DCHECK_EQ(authenticators.size(), 1u); - transport_availability_callback_readiness_ - ->platform_credential_check_pending = true; - GetPlatformCredentialStatus(authenticators[0]); + for (FidoAuthenticator* platform_authenticator : authenticators) { + transport_availability_info_.has_icloud_keychain |= + platform_authenticator->GetType() == + AuthenticatorType::kICloudKeychain; + transport_availability_callback_readiness_ + ->num_platform_credential_checks_pending++; + GetPlatformCredentialStatus(platform_authenticator); + } } } @@ -400,24 +406,42 @@ void FidoRequestHandlerBase::GetPlatformCredentialStatus( FidoAuthenticator* platform_authenticator) { transport_availability_callback_readiness_ - ->platform_credential_check_pending = false; + ->num_platform_credential_checks_pending--; } void FidoRequestHandlerBase::OnHavePlatformCredentialStatus( + AuthenticatorType authenticator_type, std::vector<DiscoverableCredentialMetadata> creds, RecognizedCredential has_credentials) { - DCHECK_EQ(transport_availability_info_.has_platform_authenticator_credential, - RecognizedCredential::kNoRecognizedCredential); - transport_availability_info_.has_platform_authenticator_credential = - has_credentials; - transport_availability_info_.recognized_platform_authenticator_credentials = - std::move(creds); - if (has_credentials == RecognizedCredential::kNoRecognizedCredential) { - transport_availability_info_.available_transports.erase( - FidoTransportProtocol::kInternal); + if (authenticator_type == AuthenticatorType::kICloudKeychain) { + // iCloud Keychain is the second platform authenticator on the system and + // its status is reported via a different field. + DCHECK_EQ(transport_availability_info_.has_icloud_keychain_credential, + RecognizedCredential::kNoRecognizedCredential); + transport_availability_info_.has_icloud_keychain_credential = + has_credentials; + } else { + DCHECK_EQ( + transport_availability_info_.has_platform_authenticator_credential, + RecognizedCredential::kNoRecognizedCredential); + transport_availability_info_.has_platform_authenticator_credential = + has_credentials; + if (has_credentials == RecognizedCredential::kNoRecognizedCredential) { + transport_availability_info_.available_transports.erase( + FidoTransportProtocol::kInternal); + } } + + auto& out_creds = transport_availability_info_ + .recognized_platform_authenticator_credentials; + if (out_creds.empty()) { + out_creds = std::move(creds); + } else if (!creds.empty()) { + out_creds.insert(out_creds.end(), creds.begin(), creds.end()); + } + transport_availability_callback_readiness_ - ->platform_credential_check_pending = false; + ->num_platform_credential_checks_pending--; MaybeSignalTransportsEnumerated(); }
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index db183ba..1c133f3a 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h
@@ -74,6 +74,9 @@ // contain the hybrid or internal transports. bool is_only_hybrid_or_internal = false; + // True this process has iCloud Keychain support. Only meaningful on macOS. + bool has_icloud_keychain = false; + // The intersection of transports supported by the client and allowed by the // relying party. base::flat_set<FidoTransportProtocol> available_transports; @@ -83,6 +86,13 @@ RecognizedCredential has_platform_authenticator_credential = RecognizedCredential::kNoRecognizedCredential; + // This field mirrors the previous one but is specific to iCloud + // Keychain. They are separate because a macOS system can have both the + // Chromium platform authenticator and iCloud Keychain as platform + // authenticators. + RecognizedCredential has_icloud_keychain_credential = + RecognizedCredential::kNoRecognizedCredential; + // The set of recognized platform credential user entities that can fulfill // a GetAssertion request. Not all platform authenticators report this, so // the set might be empty even if @@ -341,6 +351,7 @@ // platform authenticator whether it has responsive discoverable credentials // and whether it has responsive credentials at all. void OnHavePlatformCredentialStatus( + AuthenticatorType authenticator_type, std::vector<DiscoverableCredentialMetadata> user_entities, RecognizedCredential has_credentials);
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc index 28d4bf2..71a6e3e 100644 --- a/device/fido/fido_request_handler_unittest.cc +++ b/device/fido/fido_request_handler_unittest.cc
@@ -227,7 +227,8 @@ void GetPlatformCredentialStatus( FidoAuthenticator* platform_authenticator) override { - OnHavePlatformCredentialStatus(/*user_entities=*/{}, + OnHavePlatformCredentialStatus(AuthenticatorType::kOther, + /*user_entities=*/{}, has_platform_credential_); }
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index 3e19b70..5c50ca59 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -563,7 +563,7 @@ request_, options_, base::BindOnce( &GetAssertionRequestHandler::OnHavePlatformCredentialStatus, - weak_factory_.GetWeakPtr())); + weak_factory_.GetWeakPtr(), platform_authenticator->GetType())); } bool GetAssertionRequestHandler::AuthenticatorSelectedForPINUVAuthToken(
diff --git a/device/fido/mac/scoped_icloud_keychain_test_environment.h b/device/fido/mac/scoped_icloud_keychain_test_environment.h new file mode 100644 index 0000000..a856a4b --- /dev/null +++ b/device/fido/mac/scoped_icloud_keychain_test_environment.h
@@ -0,0 +1,41 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef DEVICE_FIDO_MAC_SCOPED_ICLOUD_KEYCHAIN_TEST_ENVIRONMENT_H_ +#define DEVICE_FIDO_MAC_SCOPED_ICLOUD_KEYCHAIN_TEST_ENVIRONMENT_H_ + +#include <vector> + +#include "base/component_export.h" +#include "build/build_config.h" +#include "device/fido/discoverable_credential_metadata.h" + +#if !BUILDFLAG(IS_MAC) +#error "macOS-only file" +#endif + +#import <os/availability.h> + +namespace device::fido::icloud_keychain { + +// ScopedTestEnvironment can be instantiated to simulate the presence of iCloud +// Keychain for tests. This header is the interface between the Obj-C++ and C++ +// worlds as trying to use `fake_icloud_keychain_sys.h` directly will fail to +// compile in C++ tests. +class API_AVAILABLE(macos(13.3)) + COMPONENT_EXPORT(DEVICE_FIDO) ScopedTestEnvironment { + public: + explicit ScopedTestEnvironment( + std::vector<DiscoverableCredentialMetadata> creds); + ~ScopedTestEnvironment(); + + ScopedTestEnvironment(const ScopedTestEnvironment&) = delete; + ScopedTestEnvironment(ScopedTestEnvironment&&) = delete; + ScopedTestEnvironment& operator=(const ScopedTestEnvironment&) = delete; + ScopedTestEnvironment& operator=(ScopedTestEnvironment&&) = delete; +}; + +} // namespace device::fido::icloud_keychain + +#endif // DEVICE_FIDO_MAC_SCOPED_ICLOUD_KEYCHAIN_TEST_ENVIRONMENT_H_
diff --git a/device/fido/mac/scoped_icloud_keychain_test_environment.mm b/device/fido/mac/scoped_icloud_keychain_test_environment.mm new file mode 100644 index 0000000..6dfa2fe --- /dev/null +++ b/device/fido/mac/scoped_icloud_keychain_test_environment.mm
@@ -0,0 +1,29 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "device/fido/mac/scoped_icloud_keychain_test_environment.h" + +#include "device/fido/mac/fake_icloud_keychain_sys.h" +#include "device/fido/mac/icloud_keychain_sys.h" + +#if !defined(__OBJC__) || !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace device::fido::icloud_keychain { + +ScopedTestEnvironment::ScopedTestEnvironment( + std::vector<DiscoverableCredentialMetadata> creds) { + auto fake = base::MakeRefCounted<FakeSystemInterface>(); + fake->SetCredentials(std::move(creds)); + fake->set_auth_state(FakeSystemInterface::kAuthAuthorized); + SetSystemInterfaceForTesting(fake); + return; +} + +ScopedTestEnvironment::~ScopedTestEnvironment() { + SetSystemInterfaceForTesting(nullptr); +} + +} // namespace device::fido::icloud_keychain
diff --git a/device/vr/android/cardboard/BUILD.gn b/device/vr/android/cardboard/BUILD.gn index 1d1407c9..3e8d02e 100644 --- a/device/vr/android/cardboard/BUILD.gn +++ b/device/vr/android/cardboard/BUILD.gn
@@ -31,6 +31,7 @@ deps = [ "//base", + "//device/vr:vr_util", "//device/vr/android:vr_android", "//gpu/command_buffer/service:gles2", "//third_party/cardboard",
diff --git a/device/vr/android/cardboard/cardboard_device.cc b/device/vr/android/cardboard/cardboard_device.cc index 41cab59..332e461 100644 --- a/device/vr/android/cardboard/cardboard_device.cc +++ b/device/vr/android/cardboard/cardboard_device.cc
@@ -116,14 +116,11 @@ base::BindOnce(&CardboardDevice::OnCreateSessionResult, weak_ptr_factory_.GetWeakPtr())); - render_loop_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&CardboardRenderLoop::CreateSession, - render_loop_->GetWeakPtr(), - std::move(session_result_callback), - std::move(session_shutdown_callback), - xr_java_coordinator_.get(), cardboard_sdk_.get(), window, - frame_size, rotation, std::move(options_))); + PostTaskToRenderThread(base::BindOnce( + &CardboardRenderLoop::CreateSession, render_loop_->GetWeakPtr(), + std::move(session_result_callback), std::move(session_shutdown_callback), + xr_java_coordinator_.get(), cardboard_sdk_.get(), window, frame_size, + rotation, std::move(options_))); } void CardboardDevice::OnDrawingSurfaceTouch(bool is_primary, @@ -134,7 +131,15 @@ DVLOG(3) << __func__ << ": pointer_id=" << pointer_id << " is_primary=" << is_primary << " touching=" << touching; - // TODO(https://crbug.com/1429087): Process Touch Events. + // Cardboard doesn't care about anything but the primary pointer. + if (!is_primary) { + return; + } + + // Cardboard touch events don't make use of any of the pointer information, + // so we only need to notify that an touch has happened. + PostTaskToRenderThread(base::BindOnce(&CardboardRenderLoop::OnTriggerEvent, + render_loop_->GetWeakPtr(), touching)); } void CardboardDevice::OnDrawingSurfaceDestroyed() { @@ -180,4 +185,9 @@ OnExitPresent(); } +void CardboardDevice::PostTaskToRenderThread(base::OnceClosure task) { + DCHECK(main_thread_task_runner_->BelongsToCurrentThread()); + render_loop_->task_runner()->PostTask(FROM_HERE, std::move(task)); +} + } // namespace device
diff --git a/device/vr/android/cardboard/cardboard_device.h b/device/vr/android/cardboard/cardboard_device.h index 3dab6950f..25b695ab 100644 --- a/device/vr/android/cardboard/cardboard_device.h +++ b/device/vr/android/cardboard/cardboard_device.h
@@ -60,6 +60,8 @@ void OnCreateSessionResult(mojom::XRRuntimeSessionResultPtr result); private: + void PostTaskToRenderThread(base::OnceClosure task); + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; std::unique_ptr<CardboardSdk> cardboard_sdk_;
diff --git a/device/vr/android/cardboard/cardboard_image_transport.cc b/device/vr/android/cardboard/cardboard_image_transport.cc index 2297e1db..0d5843a9 100644 --- a/device/vr/android/cardboard/cardboard_image_transport.cc +++ b/device/vr/android/cardboard/cardboard_image_transport.cc
@@ -40,8 +40,11 @@ void CardboardImageTransport::DoRuntimeInitialization() { // TODO(https://crbug.com/1429088): Move this into helper classes rather than // directly using the cardboard types here. + CardboardOpenGlEsDistortionRendererConfig config = { + CardboardSupportedOpenGlEsTextureType::kGlTextureExternalOes, + }; renderer_ = internal::ScopedCardboardObject<CardboardDistortionRenderer*>( - CardboardOpenGlEs2DistortionRenderer_create()); + CardboardOpenGlEs2DistortionRenderer_create(&config)); surface_size_ = {0, 0}; @@ -135,6 +138,19 @@ fov[kFovLeft] * kRadToDeg, fov[kFovRight] * kRadToDeg); } +gfx::Transform CardboardImageTransport::GetMojoFromView( + CardboardEye eye, + gfx::Transform mojo_from_viewer) { + float view_from_viewer[16]; + CardboardLensDistortion_getEyeFromHeadMatrix(lens_distortion_.get(), eye, + view_from_viewer); + // This needs to be inverted because the Cardboard SDK appears to be giving + // back values that are the inverse of what WebXR expects. + gfx::Transform viewer_from_view = + gfx::Transform::ColMajorF(view_from_viewer).InverseOrIdentity(); + return mojo_from_viewer * viewer_from_view; +} + std::unique_ptr<CardboardImageTransport> CardboardImageTransportFactory::Create( std::unique_ptr<MailboxToSurfaceBridge> mailbox_bridge) { return std::make_unique<CardboardImageTransport>(std::move(mailbox_bridge));
diff --git a/device/vr/android/cardboard/cardboard_image_transport.h b/device/vr/android/cardboard/cardboard_image_transport.h index 6d4bcacd..ac1b2ea 100644 --- a/device/vr/android/cardboard/cardboard_image_transport.h +++ b/device/vr/android/cardboard/cardboard_image_transport.h
@@ -38,6 +38,8 @@ // pointer to the SDK here and in CardboardRenderLoop to get this, but we need // to consider that design. mojom::VRFieldOfViewPtr GetFOV(CardboardEye eye, const gfx::Size& frame_size); + gfx::Transform GetMojoFromView(CardboardEye eye, + gfx::Transform mojo_from_viewer); // Take the current WebXr Rendering Frame and render it to the supplied // framebuffer.
diff --git a/device/vr/android/cardboard/cardboard_render_loop.cc b/device/vr/android/cardboard/cardboard_render_loop.cc index 2f46bf1..bb39fa9 100644 --- a/device/vr/android/cardboard/cardboard_render_loop.cc +++ b/device/vr/android/cardboard/cardboard_render_loop.cc
@@ -4,6 +4,7 @@ #include "device/vr/android/cardboard/cardboard_render_loop.h" +#include <time.h> #include <memory> #include "base/task/bind_post_task.h" @@ -12,6 +13,7 @@ #include "device/vr/android/xr_java_coordinator.h" #include "device/vr/public/mojom/isolated_xr_service.mojom.h" #include "device/vr/public/mojom/vr_service.mojom-shared.h" +#include "device/vr/util/transform_utils.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "ui/gfx/geometry/transform.h" #include "ui/gl/gl_bindings.h" @@ -23,6 +25,25 @@ #include "ui/gl/init/gl_factory.h" namespace device { +namespace { +// TODO(https://crbug.com/1429096): It's not clear if the display rotation +// should factor into Cardboard's viewport orientation. Initial attempts to +// map them together frequently gave wrong results, whereas statically using +// kLandscapeLeft has the expected effect. +constexpr CardboardViewportOrientation kViewportOrientation = kLandscapeLeft; + +constexpr uint64_t kNanosInMs = 1000000; +constexpr uint64_t kNanosInSeconds = 1000 * kNanosInMs; + +// Static prediction value used in the hello_cardboard sample. +constexpr uint64_t kPredictionTimeWithoutVsyncNanos = 50 * kNanosInMs; + +int64_t GetBootTimeNano() { + struct timespec res; + clock_gettime(CLOCK_BOOTTIME, &res); + return (res.tv_sec * kNanosInSeconds) + res.tv_nsec; +} +} // namespace CardboardRenderLoop::CardboardRenderLoop( std::unique_ptr<CardboardImageTransportFactory> @@ -82,9 +103,6 @@ enabled_features_.insert(options->optional_features.begin(), options->optional_features.end()); - // TODO(https://crbug.com/1429096): `display_rotation` will need to be stored - // and translated to a cardboard type to get a head pose. - left_eye_ = mojom::XRView::New(); left_eye_->eye = mojom::XREye::kLeft; left_eye_->viewport = @@ -96,7 +114,6 @@ gfx::Rect(texture_size_.width() / 2, 0, texture_size_.width() / 2, texture_size_.height()); - // TODO(https://crbug.com/1429096): Finalize mojo_from_view. left_eye_->mojo_from_view = gfx::Transform(); left_eye_->field_of_view = cardboard_image_transport_->GetFOV(CardboardEye::kLeft, texture_size_); @@ -124,6 +141,15 @@ webxr_.get(), base::BindOnce(&CardboardRenderLoop::OnCardboardImageTransportReady, weak_ptr_factory_.GetWeakPtr())); + + head_tracker_ = internal::ScopedCardboardObject<CardboardHeadTracker*>( + CardboardHeadTracker_create()); + + // If the head tracker isn't explicitly resumed after creation it doesn't + // deliver any poses. Not clear if this is intended, as it's not mentioned in + // the documentation. + CardboardHeadTracker_resume(head_tracker_.get()); + CardboardHeadTracker_recenter(head_tracker_.get()); } bool CardboardRenderLoop::InitializeGl(gfx::AcceleratedWidget drawing_widget) { @@ -339,11 +365,37 @@ webxr_.get(), texture_size_, /*uv_transform=*/gfx::Transform()); } + // Get the head pose + int64_t timestamp_ns = GetBootTimeNano() + kPredictionTimeWithoutVsyncNanos; + float position[3]; + float orientation[4]; + CardboardHeadTracker_getPose(head_tracker_.get(), timestamp_ns, + kViewportOrientation, position, orientation); + + // Translate the head pose into the viewer pose pointer + // This needs to be inverted because the Cardboard SDK appears to be giving + // back values that are the inverse of what WebXR expects. + mojom::VRPosePtr pose = mojom::VRPose::New(); + pose->position = gfx::Point3F(-position[0], -position[1], -position[2]); + pose->orientation = gfx::Quaternion(-orientation[0], -orientation[1], + -orientation[2], orientation[3]); + pose->emulated_position = true; + + gfx::Transform mojo_from_viewer = vr_utils::VrPoseToTransform(pose.get()); + frame_data->mojo_from_viewer = std::move(pose); + + // Get the view transform for each eye + left_eye_->mojo_from_view = + cardboard_image_transport_->GetMojoFromView(kLeft, mojo_from_viewer); + right_eye_->mojo_from_view = + cardboard_image_transport_->GetMojoFromView(kRight, mojo_from_viewer); + frame_data->views.push_back(left_eye_.Clone()); frame_data->views.push_back(right_eye_.Clone()); - // TODO(https://crbug.com/1429096): Populate this. - frame_data->mojo_from_viewer = mojom::VRPose::New(); + std::vector<mojom::XRInputSourceStatePtr> input_state; + input_state.push_back(GetInputSourceState()); + frame_data->input_state = std::move(input_state); frame_data->time_delta = now - base::TimeTicks(); @@ -639,11 +691,49 @@ } } +void CardboardRenderLoop::OnTriggerEvent(bool pressed) { + DVLOG(2) << __func__ << ": pressed=" << pressed; + + if (pressed) { + trigger_pressed_ = true; + } else if (trigger_pressed_) { + trigger_pressed_ = false; + trigger_clicked_ = true; + } +} + +device::mojom::XRInputSourceStatePtr +CardboardRenderLoop::GetInputSourceState() { + device::mojom::XRInputSourceStatePtr state = + device::mojom::XRInputSourceState::New(); + // Only one gaze input source to worry about, so it can have a static id. + state->source_id = 1; + + // Report any trigger state changes made since the last call and reset the + // state here. + state->primary_input_pressed = trigger_pressed_; + state->primary_input_clicked = trigger_clicked_; + trigger_clicked_ = false; + + state->description = device::mojom::XRInputSourceDescription::New(); + + // It's a gaze-cursor-based device. + state->description->target_ray_mode = device::mojom::XRTargetRayMode::GAZING; + state->emulated_position = true; + + // No implicit handedness + state->description->handedness = device::mojom::XRHandedness::NONE; + + // Pointer and grip transforms are omitted since this is a gaze-based source. + + return state; +} + void CardboardRenderLoop::Pause() { DCHECK(task_runner()->BelongsToCurrentThread()); DVLOG(1) << __func__; - // TODO(https://crbug.com/1429102): Pause the device. + CardboardHeadTracker_pause(head_tracker_.get()); is_paused_ = true; } @@ -651,7 +741,7 @@ DCHECK(task_runner()->BelongsToCurrentThread()); DVLOG(1) << __func__; - // TODO(https://crbug.com/1429102): Resume the Device. + CardboardHeadTracker_resume(head_tracker_.get()); is_paused_ = false; }
diff --git a/device/vr/android/cardboard/cardboard_render_loop.h b/device/vr/android/cardboard/cardboard_render_loop.h index 77d80cb..4f128fd 100644 --- a/device/vr/android/cardboard/cardboard_render_loop.h +++ b/device/vr/android/cardboard/cardboard_render_loop.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/android/java_handler_thread.h" #include "base/memory/scoped_refptr.h" +#include "device/vr/android/cardboard/scoped_cardboard_objects.h" #include "device/vr/android/mailbox_to_surface_bridge.h" #include "device/vr/android/web_xr_presentation_state.h" #include "device/vr/public/mojom/isolated_xr_service.mojom.h" @@ -85,6 +86,9 @@ // mojom::XRSessionController void SetFrameDataRestricted(bool restricted) override; + void OnTriggerEvent(bool pressed); + device::mojom::XRInputSourceStatePtr GetInputSourceState(); + base::WeakPtr<CardboardRenderLoop> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); } @@ -134,6 +138,10 @@ gfx::RectF left_bounds_; gfx::RectF right_bounds_; + // Input Parameters + bool trigger_pressed_ = false; + bool trigger_clicked_ = false; + // Owned by our parent (cardboard_device) raw_ptr<CardboardSdk> cardboard_sdk_; @@ -154,6 +162,8 @@ bool restrict_frame_data_ = false; bool is_paused_ = false; + internal::ScopedCardboardObject<CardboardHeadTracker*> head_tracker_; + // This closure saves arguments for the next GetFrameData call, including a // mojo callback. Must remain owned by CardboardRenderLoop, don't pass it off // to the task runner directly. Storing the mojo getframedata callback in a
diff --git a/docs/mac_build_instructions.md b/docs/mac_build_instructions.md index baf9941..2291574 100644 --- a/docs/mac_build_instructions.md +++ b/docs/mac_build_instructions.md
@@ -348,6 +348,15 @@ $ git update-index --untracked-cache ``` +#### Configure git to use fsmonitor + +If `git --version` reports 2.37 or higher, use fsmonitor, which will +significantly speed git: + +```shell +$ git config core.fsmonitor true +``` + ### Xcode license agreement If you're getting the error
diff --git a/docs/ui/learn/bestpractices/colors.md b/docs/ui/learn/bestpractices/colors.md index 2866be3..02ec49b3 100644 --- a/docs/ui/learn/bestpractices/colors.md +++ b/docs/ui/learn/bestpractices/colors.md
@@ -172,7 +172,7 @@ void CollapsibleListView::OnThemeChanged() { views::View::OnThemeChanged(); const auto* color_provider = GetColorProvider(); - const SkColor icon_color = + const SkColor icon_color = color_provider->GetColor(ui::kColorIcon); const SkColor disabled_icon_color = color_provider->GetColor(ui::kColorIconDisabled); @@ -656,9 +656,7 @@ ... // Set the icon of the group to the group color circle. - AppController* controller = - base::mac::ObjCCastStrict<AppController>([NSApp delegate]); - const auto& theme = [controller lastActiveThemeProvider]; + const auto& theme = [AppController.sharedController lastActiveThemeProvider]; const int color_id = GetTabGroupContextMenuColorIdDeprecated(group->visual_data.color()); gfx::ImageSkia group_icon = gfx::CreateVectorIcon(
diff --git a/docs/updater/functional_spec.md b/docs/updater/functional_spec.md index 1dd470e..35a5489 100644 --- a/docs/updater/functional_spec.md +++ b/docs/updater/functional_spec.md
@@ -557,7 +557,7 @@ By default, if enrollment fails, for example if the enrollment token is invalid or revoked, the updater will start in an unmanaged state. Instead, if you want to prevent the updater from starting if enrollment fails, set -`EnrollmentMandatory` to `1`. +`EnrollmentMandatory` to `1` (Windows only). After the updater sets itself up, the `FetchPolicies` RPC is invoked on the updater server to register with device management and fetch policies.
diff --git a/docs/windows_build_instructions.md b/docs/windows_build_instructions.md index 87636c96..0f2d22f 100644 --- a/docs/windows_build_instructions.md +++ b/docs/windows_build_instructions.md
@@ -488,3 +488,34 @@ You will also need to run Visual Studio as administrator, or it will silently fail to attach to some of Chrome's child processes. +### Improving performance of `git status` + +#### Configure git to use an untracked cache + +If `git --version` reports 2.8 or higher, try running + +```shell +$ git update-index --test-untracked-cache +``` + +If the output ends with `OK`, then the following may also improve performance of +`git status`: + +```shell +$ git config core.untrackedCache true +``` + +If `git --version` reports 2.6 or higher, but below 2.8, you can instead run + +```shell +$ git update-index --untracked-cache +``` + +#### Configure git to use fsmonitor + +If `git --version` reports 2.37 or higher, use fsmonitor, which will +significantly speed git: + +```shell +$ git config core.fsmonitor true +```
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index c833f0e..8cb08dd 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -430,7 +430,6 @@ "guest_view/mime_handler_view/mime_handler_view_guest.h", "guest_view/mime_handler_view/mime_handler_view_guest_delegate.cc", "guest_view/mime_handler_view/mime_handler_view_guest_delegate.h", - # TODO(crbug.com/730220): Ideally web_view should be a separate target on # which the extension system depends. "guest_view/web_view/javascript_dialog_helper.cc", @@ -1020,10 +1019,8 @@ "//chromeos/ash/components/standalone_browser", "//chromeos/dbus/permission_broker", "//chromeos/dbus/power", - "//components/account_id", "//components/feedback", "//components/prefs:prefs", - "//components/user_manager:test_support", "//extensions/shell:app_shell_lib", ] }
diff --git a/extensions/browser/DEPS b/extensions/browser/DEPS index b93cd77..f8dc2c70 100644 --- a/extensions/browser/DEPS +++ b/extensions/browser/DEPS
@@ -57,9 +57,7 @@ ".*(test|test_util)\.(cc|h)$": [ "+ash/constants/ash_features.h", - "+components/account_id", "+components/javascript_dialogs", - "+components/user_manager", "+components/user_prefs", "+storage/browser/test",
diff --git a/extensions/browser/extension_registrar_unittest.cc b/extensions/browser/extension_registrar_unittest.cc index 3e358ce..edf4910 100644 --- a/extensions/browser/extension_registrar_unittest.cc +++ b/extensions/browser/extension_registrar_unittest.cc
@@ -28,11 +28,8 @@ #include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/common/pref_names.h" // nogncheck #include "chromeos/ash/components/standalone_browser/lacros_availability.h" -#include "components/account_id/account_id.h" // nogncheck #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" -#include "components/user_manager/fake_user_manager.h" -#include "components/user_manager/scoped_user_manager.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) namespace extensions { @@ -550,21 +547,10 @@ TEST_F(ExtensionRegistrarTest, DisableNotAshKeeplistedForceInstalledExtensionIfAshDisabled) { base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary, - ash::features::kLacrosOnly, - ash::features::kLacrosProfileMigrationForceOff}, - {}); - auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>(); - auto* primary_user = - fake_user_manager->AddUser(AccountId::FromUserEmail("test@test")); - fake_user_manager->UserLoggedIn(primary_user->GetAccountId(), - primary_user->username_hash(), - /*browser_restart=*/false, - /*is_child=*/false); - auto scoped_user_manager = std::make_unique<user_manager::ScopedUserManager>( - std::move(fake_user_manager)); + feature_list.InitAndEnableFeature(ash::features::kLacrosOnly); + auto set_lacros_primary = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); static_cast<TestingPrefServiceSimple*>(pref_service()) ->registry() ->RegisterIntegerPref( @@ -585,10 +571,8 @@ // disabled if ash is still enabled. TEST_F(ExtensionRegistrarTest, NotDisableNotAshKeeplistedForceInstalledExtensionIfAshEnabled) { - base::test::ScopedFeatureList feature_list; - feature_list.InitWithFeatures( - {ash::features::kLacrosSupport, ash::features::kLacrosPrimary}, - {ash::features::kLacrosOnly}); + auto set_lacros_primary = + crosapi::browser_util::SetLacrosPrimaryBrowserForTest(true); static_cast<TestingPrefServiceSimple*>(pref_service()) ->registry() ->RegisterIntegerPref(
diff --git a/fuchsia_web/webengine/browser/web_engine_config.cc b/fuchsia_web/webengine/browser/web_engine_config.cc index 0a72146a..e36fbe3 100644 --- a/fuchsia_web/webengine/browser/web_engine_config.cc +++ b/fuchsia_web/webengine/browser/web_engine_config.cc
@@ -160,5 +160,9 @@ } } + // TODO(crbug.com/1449048): Remove this switch once fixed. + command_line->AppendSwitchASCII(switches::kEnableHardwareOverlays, + "underlay"); + return true; }
diff --git a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc index c56e835..f3087fe2 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.cc
@@ -258,8 +258,7 @@ GrContextType gr_context_type, viz::SharedImageFormat format, int plane_index, - bool mipmapped, - bool root_surface) { + bool mipmapped) { if (gr_context_type == GrContextType::kGraphiteMetal) { #if BUILDFLAG(SKIA_USE_METAL) MTLPixelFormat mtl_pixel_format = @@ -293,11 +292,9 @@ dawn_texture_info.fSampleCount = 1; dawn_texture_info.fFormat = wgpu_format; dawn_texture_info.fUsage = wgpu::TextureUsage::RenderAttachment | - wgpu::TextureUsage::TextureBinding; - if (!root_surface) { - dawn_texture_info.fUsage |= - (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst); - } + wgpu::TextureUsage::TextureBinding | + wgpu::TextureUsage::CopySrc | + wgpu::TextureUsage::CopyDst; dawn_texture_info.fMipmapped = mipmapped ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo; return dawn_texture_info;
diff --git a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h index e210b03e..12c60d863 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h +++ b/gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h
@@ -117,8 +117,7 @@ GrContextType gr_context_type, viz::SharedImageFormat format, int plane_index = 0, - bool mipmapped = false, - bool root_surface = false); + bool mipmapped = false); } // namespace gpu
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc index 457ad16..ff28bbb 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc +++ b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.cc
@@ -184,6 +184,10 @@ return dxgi_handle_.Get(); } +const gfx::DXGIHandleToken& GpuMemoryBufferImplDXGI::GetToken() const { + return dxgi_token_; +} + GpuMemoryBufferImplDXGI::GpuMemoryBufferImplDXGI( gfx::GpuMemoryBufferId id, const gfx::Size& size,
diff --git a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h index 75c19c49..c1fd20c 100644 --- a/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h +++ b/gpu/ipc/common/gpu_memory_buffer_impl_dxgi.h
@@ -58,6 +58,7 @@ gfx::GpuMemoryBufferHandle CloneHandle() const override; HANDLE GetHandle() const; + const gfx::DXGIHandleToken& GetToken() const; private: GpuMemoryBufferImplDXGI(gfx::GpuMemoryBufferId id,
diff --git a/infra/config/generated/builders/ci/linux-exp-tsan-fyi-rel/properties.json b/infra/config/generated/builders/ci/linux-exp-tsan-fyi-rel/properties.json index fa867c90..ce7ad76 100644 --- a/infra/config/generated/builders/ci/linux-exp-tsan-fyi-rel/properties.json +++ b/infra/config/generated/builders/ci/linux-exp-tsan-fyi-rel/properties.json
@@ -17,7 +17,7 @@ "mb" ], "build_config": "Release", - "config": "chromium", + "config": "chromium_tsan2", "target_bits": 64 }, "legacy_gclient_config": {
diff --git a/infra/config/generated/builders/reclient/Linux Builder reclient staging untrusted/properties.json b/infra/config/generated/builders/reclient/Linux Builder reclient staging untrusted/properties.json index c9e95e0..69a6d39d 100644 --- a/infra/config/generated/builders/reclient/Linux Builder reclient staging untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Linux Builder reclient staging untrusted/properties.json
@@ -47,6 +47,9 @@ }, "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Linux Builder reclient staging/properties.json b/infra/config/generated/builders/reclient/Linux Builder reclient staging/properties.json index d3792af..9386d06f 100644 --- a/infra/config/generated/builders/reclient/Linux Builder reclient staging/properties.json +++ b/infra/config/generated/builders/reclient/Linux Builder reclient staging/properties.json
@@ -47,6 +47,9 @@ }, "instance": "rbe-chromium-trusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git "a/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051 untrusted/properties.json" "b/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051 untrusted/properties.json" index 46e9210..9852cde 100644 --- "a/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051 untrusted/properties.json" +++ "b/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051 untrusted/properties.json"
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git "a/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051/properties.json" "b/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051/properties.json" index 1296f43..9dee95d 100644 --- "a/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051/properties.json" +++ "b/infra/config/generated/builders/reclient/Linux Builder reclient test \050unified uploads\051/properties.json"
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json index 0f86422..4c99fe57 100644 --- a/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json
@@ -48,6 +48,9 @@ }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json index 3dc32155..9c332be 100644 --- a/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json
@@ -48,6 +48,9 @@ }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient staging untrusted/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient staging untrusted/properties.json index 5fd45c4..847bb11 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient staging untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient staging untrusted/properties.json
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json index 5a2f3a87..c46bb0ff 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient staging/properties.json
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-trusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json index 37de23c..56a3c1aa 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json
@@ -51,6 +51,9 @@ "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", "profiler_service": "reclient-mac", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json index 82db03ac..ff107c1 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json
@@ -51,6 +51,9 @@ "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", "profiler_service": "reclient-mac", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging untrusted/properties.json b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging untrusted/properties.json index a884dab..b40501e 100644 --- a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging untrusted/properties.json
@@ -55,6 +55,9 @@ }, "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging/properties.json b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging/properties.json index f381867..949c1834 100644 --- a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging/properties.json +++ b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient staging/properties.json
@@ -55,6 +55,9 @@ }, "instance": "rbe-chromium-trusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json index a11c559..fdf670b1 100644 --- a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json
@@ -56,6 +56,9 @@ }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json index 26a422e..101683d 100644 --- a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json
@@ -56,6 +56,9 @@ }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Win x64 Builder reclient staging untrusted/properties.json b/infra/config/generated/builders/reclient/Win x64 Builder reclient staging untrusted/properties.json index a1e0e8e..71aae1a 100644 --- a/infra/config/generated/builders/reclient/Win x64 Builder reclient staging untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Win x64 Builder reclient staging untrusted/properties.json
@@ -48,6 +48,9 @@ }, "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Win x64 Builder reclient staging/properties.json b/infra/config/generated/builders/reclient/Win x64 Builder reclient staging/properties.json index 6f6cd0b..26c4c87 100644 --- a/infra/config/generated/builders/reclient/Win x64 Builder reclient staging/properties.json +++ b/infra/config/generated/builders/reclient/Win x64 Builder reclient staging/properties.json
@@ -48,6 +48,9 @@ }, "instance": "rbe-chromium-trusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json index f6bf26b..3190057 100644 --- a/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json index 69716be..84a89c7 100644 --- a/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient staging untrusted/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient staging untrusted/properties.json index 462f8288..53999bc 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient staging untrusted/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient staging untrusted/properties.json
@@ -50,6 +50,9 @@ }, "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient staging/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient staging/properties.json index 0e9ac615..5527d27 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient staging/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient staging/properties.json
@@ -50,6 +50,9 @@ }, "instance": "rbe-chromium-trusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json index 84e989c2..ddbc971 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json
@@ -51,6 +51,9 @@ }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json index 19575d1..ca81cb8 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json
@@ -51,6 +51,9 @@ }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging untrusted/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging untrusted/properties.json index 9b3b5fc..4b2752bd 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging untrusted/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging untrusted/properties.json
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-untrusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging/properties.json index 35481f5..7281b79 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient staging/properties.json
@@ -49,6 +49,9 @@ }, "instance": "rbe-chromium-trusted", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json index bec1716..d03940f 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json
@@ -50,6 +50,9 @@ }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json index 28bbbcf..d39f8f3 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json
@@ -50,6 +50,9 @@ }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics", + "rewrapper_env": { + "RBE_exec_timeout": "15m" + }, "scandeps_server": true }, "$recipe_engine/resultdb/test_presentation": {
diff --git a/infra/config/generated/builders/try/linux-exp-tsan-fyi-rel/properties.json b/infra/config/generated/builders/try/linux-exp-tsan-fyi-rel/properties.json index b5341e0..1fc66f6 100644 --- a/infra/config/generated/builders/try/linux-exp-tsan-fyi-rel/properties.json +++ b/infra/config/generated/builders/try/linux-exp-tsan-fyi-rel/properties.json
@@ -17,7 +17,7 @@ "mb" ], "build_config": "Release", - "config": "chromium", + "config": "chromium_tsan2", "target_bits": 64 }, "legacy_gclient_config": {
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 274bb1cd..3cefce24 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -2845,7 +2845,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -3019,7 +3019,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -12007,7 +12007,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -12094,7 +12094,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -12181,7 +12181,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -14088,7 +14088,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -14185,7 +14185,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -14272,7 +14272,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -17523,7 +17523,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -36840,7 +36840,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe { @@ -38069,7 +38069,7 @@ dimensions: "cores:8" dimensions: "cpu:x86-64" dimensions: "free_space:standard" - dimensions: "os:Ubuntu-18.04" + dimensions: "os:Ubuntu-22.04" dimensions: "pool:luci.chromium.ci" dimensions: "ssd:0" exe {
diff --git a/infra/config/lib/linux-default.json b/infra/config/lib/linux-default.json index 9a73952..bdb1fce6 100644 --- a/infra/config/lib/linux-default.json +++ b/infra/config/lib/linux-default.json
@@ -1,11 +1,22 @@ { "ci": { + "Cast Linux": "Ubuntu-22.04", + "Cast Linux Debug": "Ubuntu-22.04", + "Linux Builder": "Ubuntu-22.04", + "Linux Builder (Wayland)": "Ubuntu-22.04", + "Linux Builder (dbg)": "Ubuntu-22.04", + "Linux Tests": "Ubuntu-22.04", + "Linux Tests (Wayland)": "Ubuntu-22.04", + "Linux Tests (dbg)(1)": "Ubuntu-22.04", + "Network Service Linux": "Ubuntu-22.04", "android-build-perf-developer": "Ubuntu-22.04", "build-perf-android": "Ubuntu-22.04", "build-perf-android-siso": "Ubuntu-22.04", "build-perf-linux": "Ubuntu-22.04", "build-perf-linux-siso": "Ubuntu-22.04", + "linux-bfcache-rel": "Ubuntu-22.04", "linux-build-perf-developer": "Ubuntu-22.04", + "linux-extended-tracing-rel": "Ubuntu-22.04", "linux-local-ssd-rel-dev": "Ubuntu-22.04", "linux-rel-jammy-dev": "Ubuntu-22.04", "linux-remote-ssd-rel-dev": "Ubuntu-22.04"
diff --git a/infra/config/subprojects/chromium/ci/chromium.linux.star b/infra/config/subprojects/chromium/ci/chromium.linux.star index f5b4f1c..735314b4 100644 --- a/infra/config/subprojects/chromium/ci/chromium.linux.star +++ b/infra/config/subprojects/chromium/ci/chromium.linux.star
@@ -135,7 +135,6 @@ ), build_gs_bucket = "chromium-linux-archive", ), - os = os.LINUX_BIONIC, tree_closing = False, console_view_entry = consoles.console_view_entry( category = "cast",
diff --git a/infra/config/subprojects/chromium/ci/chromium.memory.fyi.star b/infra/config/subprojects/chromium/ci/chromium.memory.fyi.star index 06d33e9c..aded7a72 100644 --- a/infra/config/subprojects/chromium/ci/chromium.memory.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.memory.fyi.star
@@ -35,7 +35,7 @@ config = "chromium", ), chromium_config = builder_config.chromium_config( - config = "chromium", + config = "chromium_tsan2", apply_configs = ["mb"], build_config = builder_config.build_config.RELEASE, target_bits = 64,
diff --git a/infra/config/subprojects/reclient/reclient.star b/infra/config/subprojects/reclient/reclient.star index 7e38c07f..c4c7d8dc 100644 --- a/infra/config/subprojects/reclient/reclient.star +++ b/infra/config/subprojects/reclient/reclient.star
@@ -68,6 +68,11 @@ # TODO(b/258210757) remove once long term breakpad plans are dertermined "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", }) + + reclient_rewrapper_env = kwargs.pop("reclient_rewrapper_env", {}) + reclient_rewrapper_env.update({ + "RBE_exec_timeout": "15m", + }) return [ ci.builder( name = name, @@ -80,6 +85,7 @@ ), reclient_bootstrap_env = reclient_bootstrap_env, reclient_scandeps_server = True, + reclient_rewrapper_env = reclient_rewrapper_env, **kwargs ), ci.builder( @@ -94,6 +100,7 @@ service_account = untrusted_service_account, reclient_bootstrap_env = reclient_bootstrap_env, reclient_scandeps_server = True, + reclient_rewrapper_env = reclient_rewrapper_env, **kwargs ), ] @@ -107,6 +114,10 @@ reclient_bootstrap_env.update({ "RBE_fast_log_collection": "true", }) + reclient_rewrapper_env = kwargs.pop("reclient_rewrapper_env", {}) + reclient_rewrapper_env.update({ + "RBE_exec_timeout": "15m", + }) return fyi_reclient_staging_builder( name = name, console_view_category = console_view_category, @@ -114,6 +125,7 @@ reclient_version = "test", untrusted_service_account = ci.DEFAULT_SERVICE_ACCOUNT, reclient_bootstrap_env = reclient_bootstrap_env, + reclient_rewrapper_env = reclient_rewrapper_env, **kwargs )
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index 9f5b4ac6..388cd233 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -434,7 +434,6 @@ "//components/browser_sync", "//components/browsing_data/core", "//components/component_updater", - "//components/component_updater:crl_set_remover", "//components/component_updater/installer_policies", "//components/crash/core/common", "//components/download/public/background_service:public",
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 4ac4fc8c..b350e0b0 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -16,7 +16,6 @@ #import "base/path_service.h" #import "base/strings/sys_string_conversions.h" #import "components/component_updater/component_updater_service.h" -#import "components/component_updater/crl_set_remover.h" #import "components/component_updater/installer_policies/autofill_states_component_installer.h" #import "components/component_updater/installer_policies/on_device_head_suggest_component_installer.h" #import "components/component_updater/installer_policies/optimization_hints_component_installer.h" @@ -226,9 +225,6 @@ base::FilePath path; const bool success = base::PathService::Get(ios::DIR_USER_DATA, &path); DCHECK(success); - // Clean up any legacy CRLSet on the local disk - CRLSet used to be shipped - // as a component on iOS but is not anymore. - component_updater::DeleteLegacyCRLSet(path); component_updater::DeleteUrlParamFilter(path); RegisterOnDeviceHeadSuggestComponent(
diff --git a/ios/chrome/browser/autofill/child_frame_registration_java_script_feature_unittest.mm b/ios/chrome/browser/autofill/child_frame_registration_java_script_feature_unittest.mm index 983887e..5819e77c 100644 --- a/ios/chrome/browser/autofill/child_frame_registration_java_script_feature_unittest.mm +++ b/ios/chrome/browser/autofill/child_frame_registration_java_script_feature_unittest.mm
@@ -36,7 +36,7 @@ ChildFrameRegistrationJavaScriptFeatureTest() : web_client_(std::make_unique<ChromeWebClient>()) { feature_list_.InitAndEnableFeature( - autofill::features::kAutofillAcrossIframes); + autofill::features::kAutofillAcrossIframesIos); PlatformTest::SetUp();
diff --git a/ios/chrome/browser/shared/ui/symbols/resources/camera_lens.symbolset/camera.lens.cr.svg b/ios/chrome/browser/shared/ui/symbols/resources/camera_lens.symbolset/camera.lens.cr.svg index 5b026d1..fa9073b1 100644 --- a/ios/chrome/browser/shared/ui/symbols/resources/camera_lens.symbolset/camera.lens.cr.svg +++ b/ios/chrome/browser/shared/ui/symbols/resources/camera_lens.symbolset/camera.lens.cr.svg
@@ -1,184 +1,257 @@ -<svg width="3300" height="2200" viewBox="0 0 3300 2200" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="camera.lens.cr"> -<g id="Notes"> -<path id="artboard" d="M3300 0H0V2200H3300V0Z" fill="white"/> -<path id="Vector" d="M263 292H3036" stroke="black" stroke-width="0.5"/> -<text id="Weight/Scale Variations" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="263" y="321.727">Weight/Scale Variations</tspan></text> -<text id="Ultralight" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="531.211" y="321.727">Ultralight</tspan></text> -<text id="Thin" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="842.922" y="321.727">Thin</tspan></text> -<text id="Light" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1137.63" y="321.727">Light</tspan></text> -<text id="Regular" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1426.34" y="321.727">Regular</tspan></text> -<text id="Medium" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1721.56" y="321.727">Medium</tspan></text> -<text id="Semibold" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2014.27" y="321.727">Semibold</tspan></text> -<text id="Bold" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2325.98" y="321.727">Bold</tspan></text> -<text id="Heavy" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2617.19" y="321.727">Heavy</tspan></text> -<text id="Black" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2916.4" y="321.727">Black</tspan></text> -<path id="Vector_2" d="M263 1903H3036" stroke="black" stroke-width="0.5"/> -<g id="Group"> -<path id="Vector_3" d="M272.248 1933.83C273.329 1933.83 274.344 1933.63 275.295 1933.22C276.245 1932.81 277.084 1932.24 277.81 1931.51C278.535 1930.78 279.105 1929.94 279.519 1928.99C279.932 1928.04 280.139 1927.03 280.139 1925.95C280.139 1924.88 279.932 1923.86 279.519 1922.91C279.105 1921.96 278.534 1921.12 277.805 1920.39C277.075 1919.67 276.236 1919.1 275.285 1918.69C274.335 1918.28 273.319 1918.07 272.238 1918.07C271.164 1918.07 270.152 1918.28 269.201 1918.69C268.251 1919.1 267.414 1919.67 266.691 1920.39C265.969 1921.12 265.401 1921.96 264.987 1922.91C264.574 1923.86 264.367 1924.88 264.367 1925.95C264.367 1927.03 264.574 1928.04 264.987 1928.99C265.401 1929.94 265.97 1930.78 266.696 1931.51C267.422 1932.24 268.26 1932.81 269.211 1933.22C270.161 1933.63 271.174 1933.83 272.248 1933.83ZM272.248 1932.35C271.363 1932.35 270.534 1932.18 269.763 1931.85C268.991 1931.53 268.314 1931.07 267.731 1930.48C267.149 1929.9 266.693 1929.22 266.364 1928.44C266.035 1927.67 265.871 1926.84 265.871 1925.95C265.871 1925.07 266.034 1924.24 266.359 1923.46C266.685 1922.69 267.139 1922.01 267.722 1921.42C268.304 1920.83 268.981 1920.38 269.753 1920.05C270.524 1919.72 271.353 1919.55 272.238 1919.55C273.13 1919.55 273.962 1919.72 274.733 1920.05C275.505 1920.38 276.184 1920.83 276.769 1921.42C277.355 1922.01 277.814 1922.69 278.146 1923.46C278.478 1924.24 278.644 1925.07 278.644 1925.95C278.644 1926.84 278.48 1927.67 278.151 1928.44C277.823 1929.22 277.367 1929.9 276.784 1930.48C276.202 1931.07 275.523 1931.53 274.748 1931.85C273.973 1932.18 273.14 1932.35 272.248 1932.35ZM268.654 1925.95C268.654 1926.17 268.723 1926.34 268.859 1926.47C268.996 1926.61 269.178 1926.67 269.406 1926.67H271.516V1928.79C271.516 1929.01 271.581 1929.19 271.711 1929.33C271.841 1929.47 272.017 1929.54 272.238 1929.54C272.453 1929.54 272.631 1929.47 272.771 1929.33C272.91 1929.19 272.98 1929.01 272.98 1928.79V1926.67H275.09C275.311 1926.67 275.49 1926.61 275.627 1926.47C275.764 1926.34 275.832 1926.17 275.832 1925.95C275.832 1925.73 275.764 1925.55 275.627 1925.41C275.49 1925.28 275.311 1925.21 275.09 1925.21H272.98V1923.1C272.98 1922.88 272.91 1922.7 272.771 1922.56C272.631 1922.42 272.453 1922.35 272.238 1922.35C272.017 1922.35 271.841 1922.42 271.711 1922.56C271.581 1922.7 271.516 1922.88 271.516 1923.1V1925.21H269.406C269.178 1925.21 268.996 1925.28 268.859 1925.41C268.723 1925.55 268.654 1925.73 268.654 1925.95Z" fill="black"/> -</g> -<g id="Group_2"> -<path id="Vector_4" d="M293.576 1935.91C294.937 1935.91 296.218 1935.65 297.419 1935.13C298.62 1934.61 299.68 1933.89 300.598 1932.97C301.516 1932.05 302.235 1930.99 302.756 1929.79C303.277 1928.59 303.537 1927.31 303.537 1925.95C303.537 1924.59 303.277 1923.31 302.756 1922.11C302.235 1920.91 301.516 1919.85 300.598 1918.93C299.68 1918.01 298.618 1917.29 297.414 1916.77C296.21 1916.25 294.927 1915.99 293.566 1915.99C292.206 1915.99 290.925 1916.25 289.724 1916.77C288.522 1917.29 287.465 1918.01 286.55 1918.93C285.635 1919.85 284.917 1920.91 284.396 1922.11C283.876 1923.31 283.615 1924.59 283.615 1925.95C283.615 1927.31 283.876 1928.59 284.396 1929.79C284.917 1930.99 285.637 1932.05 286.555 1932.97C287.473 1933.89 288.532 1934.61 289.733 1935.13C290.935 1935.65 292.215 1935.91 293.576 1935.91ZM293.576 1934.25C292.424 1934.25 291.346 1934.04 290.344 1933.61C289.341 1933.18 288.461 1932.58 287.702 1931.82C286.944 1931.06 286.351 1930.18 285.925 1929.18C285.498 1928.18 285.285 1927.1 285.285 1925.95C285.285 1924.8 285.498 1923.72 285.925 1922.72C286.351 1921.71 286.942 1920.83 287.697 1920.07C288.452 1919.31 289.331 1918.71 290.334 1918.29C291.337 1917.86 292.414 1917.65 293.566 1917.65C294.719 1917.65 295.796 1917.86 296.799 1918.29C297.801 1918.71 298.684 1919.31 299.445 1920.07C300.207 1920.83 300.803 1921.71 301.232 1922.72C301.662 1923.72 301.877 1924.8 301.877 1925.95C301.877 1927.1 301.664 1928.18 301.237 1929.18C300.811 1930.18 300.218 1931.06 299.46 1931.82C298.702 1932.58 297.819 1933.18 296.813 1933.61C295.808 1934.04 294.729 1934.25 293.576 1934.25ZM289.045 1925.95C289.045 1926.18 289.123 1926.38 289.279 1926.53C289.436 1926.68 289.637 1926.75 289.885 1926.75H292.756V1929.63C292.756 1929.88 292.831 1930.08 292.98 1930.23C293.13 1930.38 293.322 1930.46 293.557 1930.46C293.804 1930.46 294.004 1930.38 294.157 1930.23C294.31 1930.08 294.387 1929.88 294.387 1929.63V1926.75H297.268C297.515 1926.75 297.715 1926.68 297.868 1926.53C298.021 1926.38 298.098 1926.18 298.098 1925.95C298.098 1925.7 298.021 1925.5 297.868 1925.35C297.715 1925.2 297.515 1925.12 297.268 1925.12H294.387V1922.25C294.387 1921.99 294.31 1921.79 294.157 1921.64C294.004 1921.48 293.804 1921.41 293.557 1921.41C293.322 1921.41 293.13 1921.49 292.98 1921.64C292.831 1921.8 292.756 1922 292.756 1922.25V1925.12H289.885C289.631 1925.12 289.427 1925.2 289.274 1925.35C289.121 1925.5 289.045 1925.7 289.045 1925.95Z" fill="black"/> -</g> -<g id="Group_3"> -<path id="Vector_5" d="M320.617 1938.67C322.01 1938.67 323.34 1938.45 324.606 1938.02C325.872 1937.58 327.036 1936.98 328.097 1936.2C329.158 1935.41 330.081 1934.49 330.866 1933.43C331.65 1932.37 332.259 1931.21 332.692 1929.94C333.125 1928.67 333.341 1927.34 333.341 1925.95C333.341 1924.56 333.125 1923.23 332.692 1921.96C332.259 1920.7 331.65 1919.53 330.866 1918.47C330.081 1917.41 329.158 1916.49 328.097 1915.7C327.036 1914.92 325.871 1914.31 324.601 1913.88C323.332 1913.44 322 1913.23 320.607 1913.23C319.214 1913.23 317.884 1913.44 316.618 1913.88C315.351 1914.31 314.189 1914.92 313.131 1915.7C312.073 1916.49 311.152 1917.41 310.368 1918.47C309.583 1919.53 308.976 1920.7 308.546 1921.96C308.117 1923.23 307.902 1924.56 307.902 1925.95C307.902 1927.34 308.118 1928.67 308.551 1929.94C308.984 1931.21 309.591 1932.37 310.373 1933.43C311.154 1934.49 312.075 1935.41 313.136 1936.2C314.197 1936.98 315.361 1937.58 316.627 1938.02C317.894 1938.45 319.223 1938.67 320.617 1938.67ZM320.617 1936.85C319.412 1936.85 318.265 1936.67 317.174 1936.3C316.084 1935.93 315.086 1935.41 314.181 1934.75C313.276 1934.09 312.49 1933.3 311.823 1932.39C311.155 1931.48 310.639 1930.48 310.275 1929.39C309.91 1928.3 309.728 1927.16 309.728 1925.95C309.728 1924.74 309.91 1923.59 310.275 1922.5C310.639 1921.41 311.154 1920.41 311.818 1919.5C312.482 1918.59 313.266 1917.81 314.171 1917.14C315.076 1916.48 316.074 1915.96 317.165 1915.6C318.255 1915.24 319.402 1915.05 320.607 1915.05C321.818 1915.05 322.969 1915.24 324.059 1915.6C325.15 1915.96 326.149 1916.48 327.057 1917.14C327.965 1917.81 328.751 1918.59 329.415 1919.5C330.08 1920.41 330.596 1921.41 330.963 1922.5C331.331 1923.59 331.515 1924.74 331.515 1925.95C331.522 1927.16 331.343 1928.3 330.978 1929.39C330.613 1930.48 330.098 1931.48 329.43 1932.39C328.763 1933.3 327.975 1934.09 327.067 1934.75C326.159 1935.41 325.159 1935.93 324.069 1936.3C322.978 1936.67 321.828 1936.85 320.617 1936.85ZM314.845 1925.95C314.845 1926.21 314.931 1926.42 315.104 1926.58C315.277 1926.75 315.496 1926.83 315.763 1926.83H319.708V1930.79C319.708 1931.05 319.791 1931.27 319.957 1931.44C320.123 1931.62 320.337 1931.7 320.597 1931.7C320.864 1931.7 321.084 1931.62 321.256 1931.45C321.429 1931.28 321.515 1931.06 321.515 1930.79V1926.83H325.47C325.737 1926.83 325.955 1926.75 326.124 1926.58C326.294 1926.42 326.378 1926.21 326.378 1925.95C326.378 1925.68 326.294 1925.46 326.124 1925.29C325.955 1925.12 325.737 1925.03 325.47 1925.03H321.515V1921.09C321.515 1920.81 321.429 1920.59 321.256 1920.42C321.084 1920.25 320.864 1920.16 320.597 1920.16C320.337 1920.16 320.123 1920.25 319.957 1920.42C319.791 1920.59 319.708 1920.81 319.708 1921.09V1925.03H315.763C315.49 1925.03 315.268 1925.12 315.099 1925.29C314.93 1925.46 314.845 1925.68 314.845 1925.95Z" fill="black"/> -</g> -<text id="Design Variations" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="263" y="1952.73">Design Variations</tspan></text> -<text id="Symbols are supported in up to nine weights and three scales." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1970.73">Symbols are supported in up to nine weights and three scales.</tspan></text> -<text id="For optimal layout with text and other symbols, vertically align" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1988.73">For optimal layout with text and other symbols, vertically align</tspan></text> -<text id="symbols with the adjacent text." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="2006.73">symbols with the adjacent text.</tspan></text> -<path id="Vector_6" d="M776 1919V1933" stroke="#00AEEF" stroke-width="0.5"/> -<g id="Group_4"> -<path id="Vector_7" d="M779.311 1933.16C779.571 1933.16 779.773 1933.1 779.916 1932.99C780.059 1932.88 780.176 1932.69 780.268 1932.42L781.527 1928.97H787.289L788.549 1932.42C788.64 1932.69 788.757 1932.88 788.9 1932.99C789.044 1933.1 789.242 1933.16 789.496 1933.16C789.757 1933.16 789.963 1933.09 790.116 1932.94C790.269 1932.8 790.346 1932.6 790.346 1932.36C790.346 1932.21 790.31 1932.03 790.238 1931.83L785.658 1919.63C785.541 1919.33 785.382 1919.11 785.18 1918.96C784.978 1918.81 784.721 1918.73 784.408 1918.73C783.803 1918.73 783.393 1919.03 783.178 1919.62L778.598 1931.84C778.526 1932.04 778.49 1932.22 778.49 1932.37C778.49 1932.61 778.563 1932.81 778.71 1932.95C778.856 1933.09 779.057 1933.16 779.311 1933.16ZM782.006 1927.48L784.379 1920.91H784.428L786.801 1927.48H782.006Z" fill="black"/> -</g> -<path id="Vector_8" d="M793.197 1919V1933" stroke="#00AEEF" stroke-width="0.5"/> -<text id="Margins" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="776" y="1952.73">Margins</tspan></text> -<text id="Leading and trailing margins on the left and right side of each symbol" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="1970.73">Leading and trailing margins on the left and right side of each symbol</tspan></text> -<text id="can be adjusted by modifying the x-location of the margin guidelines." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="1988.73">can be adjusted by modifying the x-location of the margin guidelines.</tspan></text> -<text id="Modifications are automatically applied proportionally to all" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="2006.73">Modifications are automatically applied proportionally to all</tspan></text> -<text id="scales and weights." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="2024.73">scales and weights.</tspan></text> -<g id="Group_5"> -<path id="Vector_9" d="M1291.84 1934.86L1293.54 1936.57C1293.97 1937.01 1294.42 1937.21 1294.9 1937.18C1295.38 1937.15 1295.85 1936.87 1296.31 1936.36L1307.01 1924.57L1306.04 1923.59L1295.43 1935.27C1295.25 1935.48 1295.07 1935.59 1294.89 1935.62C1294.71 1935.64 1294.51 1935.54 1294.27 1935.3L1293.1 1934.14C1292.87 1933.91 1292.76 1933.7 1292.79 1933.52C1292.82 1933.34 1292.94 1933.16 1293.14 1932.98L1304.62 1922.18L1303.64 1921.21L1292.05 1932.1C1291.55 1932.56 1291.29 1933.02 1291.25 1933.5C1291.22 1933.97 1291.41 1934.43 1291.84 1934.86ZM1298.26 1916.67C1298.05 1916.87 1297.93 1917.1 1297.91 1917.36C1297.88 1917.62 1297.93 1917.85 1298.04 1918.05C1298.16 1918.23 1298.33 1918.37 1298.56 1918.46C1298.78 1918.55 1299.06 1918.55 1299.38 1918.48C1300.11 1918.31 1300.85 1918.24 1301.6 1918.27C1302.35 1918.3 1303.08 1918.54 1303.79 1919.01L1303.21 1920.47C1303.04 1920.89 1302.99 1921.25 1303.07 1921.56C1303.14 1921.87 1303.31 1922.16 1303.58 1922.43L1305.87 1924.75C1306.12 1924.99 1306.35 1925.14 1306.58 1925.18C1306.81 1925.21 1307.06 1925.21 1307.34 1925.16L1308.4 1924.96L1309.07 1925.63L1309.03 1926.19C1309.01 1926.44 1309.04 1926.67 1309.12 1926.88C1309.2 1927.08 1309.36 1927.31 1309.61 1927.55L1310.37 1928.29C1310.61 1928.53 1310.87 1928.66 1311.15 1928.67C1311.44 1928.68 1311.7 1928.56 1311.93 1928.33L1314.84 1925.41C1315.07 1925.18 1315.19 1924.92 1315.18 1924.64C1315.18 1924.37 1315.05 1924.11 1314.81 1923.87L1314.04 1923.11C1313.8 1922.86 1313.58 1922.7 1313.38 1922.61C1313.17 1922.52 1312.95 1922.49 1312.71 1922.51L1312.13 1922.56L1311.49 1921.92L1311.73 1920.8C1311.8 1920.52 1311.79 1920.26 1311.7 1920.01C1311.6 1919.77 1311.41 1919.5 1311.12 1919.21L1308.92 1917.02C1308.09 1916.19 1307.2 1915.57 1306.26 1915.16C1305.32 1914.75 1304.37 1914.53 1303.42 1914.52C1302.47 1914.5 1301.55 1914.67 1300.66 1915.04C1299.78 1915.4 1298.98 1915.95 1298.26 1916.67ZM1299.75 1917.04C1300.36 1916.6 1301.01 1916.28 1301.7 1916.09C1302.39 1915.9 1303.1 1915.84 1303.8 1915.91C1304.51 1915.98 1305.2 1916.17 1305.87 1916.48C1306.54 1916.8 1307.15 1917.23 1307.7 1917.79L1310.13 1920.21C1310.25 1920.32 1310.32 1920.44 1310.35 1920.55C1310.38 1920.66 1310.38 1920.8 1310.34 1920.97L1310.02 1922.45L1311.52 1923.94L1312.51 1923.88C1312.63 1923.87 1312.72 1923.88 1312.79 1923.9C1312.85 1923.92 1312.94 1923.98 1313.03 1924.08L1313.61 1924.66L1311.17 1927.1L1310.59 1926.52C1310.49 1926.43 1310.43 1926.34 1310.41 1926.28C1310.38 1926.21 1310.37 1926.12 1310.38 1925.99L1310.45 1925.01L1308.95 1923.53L1307.43 1923.78C1307.26 1923.81 1307.14 1923.82 1307.04 1923.79C1306.95 1923.77 1306.84 1923.7 1306.71 1923.58L1304.71 1921.58C1304.58 1921.46 1304.51 1921.35 1304.49 1921.25C1304.48 1921.14 1304.51 1920.99 1304.59 1920.81L1305.46 1918.72C1304.68 1917.99 1303.8 1917.49 1302.83 1917.21C1301.85 1916.93 1300.86 1916.94 1299.84 1917.24C1299.76 1917.26 1299.71 1917.24 1299.69 1917.19C1299.67 1917.14 1299.69 1917.09 1299.75 1917.04Z" fill="black"/> -</g> -<text id="Exporting" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="1289" y="1952.73">Exporting</tspan></text> -<text id="Symbols should be outlined when exporting to ensure the" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1289" y="1970.73">Symbols should be outlined when exporting to ensure the</tspan></text> -<text id="design is preserved when submitting to Xcode." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1289" y="1988.73">design is preserved when submitting to Xcode.</tspan></text> -<text id="template-version" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2946" y="1932.73">Template v.3.0</tspan></text> -<text id="Requires Xcode 13 or greater" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2857" y="1950.73">Requires Xcode 13 or greater</tspan></text> -<text id="descriptive-name" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2889" y="1968.73">Generated from camera</tspan></text> -<text id="Typeset at 100 points" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2903" y="1986.73">Typeset at 100 points</tspan></text> -<text id="Small" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="725.727">Small</tspan></text> -<text id="Medium_2" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1155.73">Medium</tspan></text> -<text id="Large" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1585.73">Large</tspan></text> -</g> -<g id="Guides"> -<g id="H-reference"> -<path id="Vector_10" d="M339.977 695.998H342.662L368.346 628.859H369.029V625.539H367.125L339.977 695.998ZM350.67 671.535H385.973L385.24 669.289H351.451L350.67 671.535ZM394.127 695.998H396.764L369.615 625.539H368.443V628.859L394.127 695.998Z" fill="#27AAE1"/> -</g> -<path id="Baseline-S" d="M263 696H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="Capline-S" d="M263 625.539H3036" stroke="#27AAE1" stroke-width="0.5"/> -<g id="H-reference_2"> -<path id="Vector_11" d="M339.977 1126H342.662L368.346 1058.86H369.029V1055.54H367.125L339.977 1126ZM350.67 1101.54H385.973L385.24 1099.29H351.451L350.67 1101.54ZM394.127 1126H396.764L369.615 1055.54H368.443V1058.86L394.127 1126Z" fill="#27AAE1"/> -</g> -<path id="Baseline-M" d="M263 1126H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="Capline-M" d="M263 1055.54H3036" stroke="#27AAE1" stroke-width="0.5"/> -<g id="H-reference_3"> -<path id="Vector_12" d="M339.977 1556H342.662L368.346 1488.86H369.029V1485.54H367.125L339.977 1556ZM350.67 1531.54H385.973L385.24 1529.29H351.451L350.67 1531.54ZM394.127 1556H396.764L369.615 1485.54H368.443V1488.86L394.127 1556Z" fill="#27AAE1"/> -</g> -<path id="Baseline-L" d="M263 1556H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="Capline-L" d="M263 1485.54H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="left-margin-Regular-M" d="M1377.43 1030.79V1150.12" stroke="#00AEEF" stroke-width="0.5"/> -<path id="right-margin-Regular-M" d="M1522.26 1030.79V1150.12" stroke="#00AEEF" stroke-width="0.5"/> -</g> -<g id="Symbols"> -<g id="Black-L"> -<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M2916.98 1452.3C2913.03 1452.3 2909.31 1454.09 2906.84 1457.17L2900.59 1464.97C2900.29 1465.34 2900.1 1465.74 2899.99 1466.15C2890.28 1466.38 2884.12 1467.17 2879.05 1469.75C2872.65 1473.01 2867.45 1478.21 2864.19 1484.61C2860.48 1491.88 2860.48 1501.4 2860.48 1520.44V1527.9C2860.48 1546.94 2860.48 1556.46 2864.19 1563.73C2867.45 1570.13 2872.65 1575.33 2879.05 1578.59C2886.32 1582.3 2895.84 1582.3 2914.88 1582.3H2951.91C2970.95 1582.3 2980.47 1582.3 2987.74 1578.59C2994.14 1575.33 2999.34 1570.13 3002.6 1563.73C3006.31 1556.46 3006.31 1546.94 3006.31 1527.9V1520.44C3006.31 1501.4 3006.31 1491.88 3002.6 1484.61C2999.34 1478.21 2994.14 1473.01 2987.74 1469.75C2982.73 1467.2 2976.66 1466.4 2967.15 1466.16L2959.95 1457.17C2957.49 1454.09 2953.75 1452.3 2949.81 1452.3H2916.98ZM2914.88 1486.04H2951.91C2961.76 1486.04 2967.94 1486.06 2972.61 1486.44C2977.04 1486.8 2978.31 1487.39 2978.66 1487.57C2981.3 1488.91 2983.44 1491.05 2984.78 1493.69C2984.96 1494.03 2985.55 1495.31 2985.91 1499.74C2986.29 1504.41 2986.31 1510.59 2986.31 1520.44V1527.9C2986.31 1537.75 2986.29 1543.93 2985.91 1548.6C2985.55 1553.03 2984.96 1554.31 2984.78 1554.65C2983.44 1557.29 2981.3 1559.43 2978.66 1560.77C2978.31 1560.95 2977.04 1561.54 2972.61 1561.9C2967.94 1562.28 2961.76 1562.3 2951.91 1562.3H2914.88C2905.03 1562.3 2898.85 1562.28 2894.18 1561.9C2889.75 1561.54 2888.48 1560.95 2888.13 1560.77C2885.49 1559.43 2883.35 1557.29 2882.01 1554.65C2881.83 1554.31 2881.24 1553.03 2880.88 1548.6C2880.5 1543.93 2880.48 1537.75 2880.48 1527.9V1520.44C2880.48 1510.59 2880.5 1504.41 2880.88 1499.74C2881.24 1495.31 2881.83 1494.03 2882.01 1493.69C2883.35 1491.05 2885.49 1488.91 2888.13 1487.57C2888.48 1487.39 2889.75 1486.8 2894.18 1486.44C2898.85 1486.06 2905.03 1486.04 2914.88 1486.04Z" fill="black"/> -<path id="Rectangle 11906" d="M2907.57 1524.17C2907.57 1509.91 2919.13 1498.35 2933.4 1498.35V1498.35C2947.66 1498.35 2959.22 1509.91 2959.22 1524.17V1524.17C2959.22 1538.43 2947.66 1549.99 2933.4 1549.99V1549.99C2919.13 1549.99 2907.57 1538.43 2907.57 1524.17V1524.17Z" fill="black"/> -</g> -<g id="Heavy-L"> -<path id="Union_2" fill-rule="evenodd" clip-rule="evenodd" d="M2620.27 1452.5C2616.33 1452.5 2612.6 1454.29 2610.13 1457.37L2603.88 1465.17C2603.59 1465.53 2603.4 1465.92 2603.29 1466.32C2593.18 1466.51 2586.92 1467.23 2581.8 1469.84C2575.59 1473 2570.54 1478.05 2567.37 1484.26C2563.78 1491.32 2563.78 1500.56 2563.78 1519.04V1529.7C2563.78 1548.18 2563.78 1557.42 2567.37 1564.48C2570.54 1570.69 2575.59 1575.74 2581.8 1578.9C2588.86 1582.5 2598.1 1582.5 2616.58 1582.5H2656.8C2675.28 1582.5 2684.52 1582.5 2691.58 1578.9C2697.79 1575.74 2702.84 1570.69 2706 1564.48C2709.6 1557.42 2709.6 1548.18 2709.6 1529.7V1519.04C2709.6 1500.56 2709.6 1491.32 2706 1484.26C2702.84 1478.05 2697.79 1473 2691.58 1469.84C2686.52 1467.26 2680.33 1466.53 2670.42 1466.32L2663.25 1457.37C2660.78 1454.29 2657.05 1452.5 2653.1 1452.5H2620.27ZM2616.58 1483.99H2656.8C2666.33 1483.99 2672.42 1484.01 2677.03 1484.38C2681.43 1484.74 2682.91 1485.34 2683.52 1485.65C2686.39 1487.12 2688.72 1489.45 2690.19 1492.32C2690.5 1492.93 2691.1 1494.41 2691.46 1498.81C2691.84 1503.43 2691.85 1509.51 2691.85 1519.04V1529.7C2691.85 1539.23 2691.84 1545.31 2691.46 1549.93C2691.1 1554.33 2690.5 1555.81 2690.19 1556.42C2688.72 1559.29 2686.39 1561.62 2683.52 1563.08C2682.91 1563.4 2681.43 1564 2677.03 1564.36C2672.42 1564.73 2666.33 1564.75 2656.8 1564.75H2616.58C2607.04 1564.75 2600.96 1564.73 2596.35 1564.36C2591.94 1564 2590.46 1563.4 2589.85 1563.08C2586.99 1561.62 2584.65 1559.29 2583.19 1556.42C2582.88 1555.81 2582.28 1554.33 2581.92 1549.93C2581.54 1545.31 2581.53 1539.23 2581.53 1529.7V1519.04C2581.53 1509.51 2581.54 1503.43 2581.92 1498.81C2582.28 1494.41 2582.88 1492.93 2583.19 1492.32C2584.65 1489.45 2586.99 1487.12 2589.85 1485.65C2590.46 1485.34 2591.94 1484.74 2596.35 1484.38C2600.96 1484.01 2607.04 1483.99 2616.58 1483.99Z" fill="black"/> -<path id="Rectangle 11906_2" d="M2610.87 1524.37C2610.87 1510.11 2622.43 1498.55 2636.69 1498.55V1498.55C2650.95 1498.55 2662.51 1510.11 2662.51 1524.37V1524.37C2662.51 1538.63 2650.95 1550.19 2636.69 1550.19V1550.19C2622.43 1550.19 2610.87 1538.63 2610.87 1524.37V1524.37Z" fill="black"/> -</g> -<g id="Bold-L"> -<path id="Union_3" fill-rule="evenodd" clip-rule="evenodd" d="M2323.55 1453.87C2319.61 1453.87 2315.88 1455.66 2313.42 1458.73L2307.17 1466.54C2306.88 1466.89 2306.69 1467.27 2306.58 1467.66C2296.07 1467.82 2289.7 1468.47 2284.54 1471.1C2278.51 1474.17 2273.62 1479.06 2270.55 1485.08C2267.06 1491.93 2267.06 1500.89 2267.06 1518.81V1532.66C2267.06 1550.59 2267.06 1559.55 2270.55 1566.39C2273.62 1572.41 2278.51 1577.31 2284.54 1580.38C2291.38 1583.86 2300.34 1583.86 2318.26 1583.86H2361.68C2379.61 1583.86 2388.57 1583.86 2395.41 1580.38C2401.43 1577.31 2406.33 1572.41 2409.4 1566.39C2412.88 1559.55 2412.88 1550.59 2412.88 1532.66V1518.81C2412.88 1500.89 2412.88 1491.93 2409.4 1485.08C2406.33 1479.06 2401.43 1474.17 2395.41 1471.1C2390.3 1468.49 2384.01 1467.83 2373.69 1467.67L2366.53 1458.74C2364.06 1455.66 2360.33 1453.87 2356.39 1453.87H2323.55ZM2318.26 1482.11H2361.68C2370.88 1482.11 2376.91 1482.12 2381.52 1482.5C2385.96 1482.86 2387.79 1483.49 2388.83 1484.02C2392.12 1485.69 2394.8 1488.37 2396.48 1491.66C2397.01 1492.7 2397.63 1494.53 2398 1498.97C2398.37 1503.58 2398.38 1509.61 2398.38 1518.81V1532.66C2398.38 1541.86 2398.37 1547.89 2398 1552.5C2397.63 1556.94 2397.01 1558.77 2396.48 1559.81C2394.8 1563.1 2392.12 1565.78 2388.83 1567.46C2387.79 1567.99 2385.96 1568.61 2381.52 1568.98C2376.91 1569.35 2370.88 1569.36 2361.68 1569.36H2318.26C2309.06 1569.36 2303.04 1569.35 2298.43 1568.98C2293.99 1568.61 2292.16 1567.99 2291.12 1567.46C2287.83 1565.78 2285.15 1563.1 2283.47 1559.81C2282.94 1558.77 2282.31 1556.94 2281.95 1552.5C2281.57 1547.89 2281.56 1541.86 2281.56 1532.66V1518.81C2281.56 1509.61 2281.57 1503.58 2281.95 1498.97C2282.31 1494.53 2282.94 1492.7 2283.47 1491.66C2285.15 1488.37 2287.83 1485.69 2291.12 1484.02C2292.16 1483.49 2293.99 1482.86 2298.43 1482.5C2303.04 1482.12 2309.06 1482.11 2318.26 1482.11Z" fill="black"/> -<path id="Rectangle 11906_3" d="M2314.15 1525.73C2314.15 1511.47 2325.71 1499.91 2339.97 1499.91V1499.91C2354.23 1499.91 2365.79 1511.47 2365.79 1525.73V1525.73C2365.79 1539.99 2354.23 1551.55 2339.97 1551.55V1551.55C2325.71 1551.55 2314.15 1539.99 2314.15 1525.73V1525.73Z" fill="black"/> -</g> -<g id="Semibold-L"> -<path id="Union_4" fill-rule="evenodd" clip-rule="evenodd" d="M2026.85 1453.87C2022.91 1453.87 2019.18 1455.66 2016.71 1458.74L2010.46 1466.54C2010.18 1466.89 2009.99 1467.26 2009.88 1467.65C1998.95 1467.77 1992.49 1468.34 1987.28 1470.99C1981.45 1473.96 1976.71 1478.71 1973.74 1484.54C1970.36 1491.17 1970.36 1499.85 1970.36 1517.21V1534.27C1970.36 1551.63 1970.36 1560.31 1973.74 1566.94C1976.71 1572.77 1981.45 1577.52 1987.28 1580.49C1993.91 1583.87 2002.6 1583.87 2019.96 1583.87H2066.58C2083.94 1583.87 2092.62 1583.87 2099.25 1580.49C2105.09 1577.52 2109.83 1572.77 2112.8 1566.94C2116.18 1560.31 2116.18 1551.63 2116.18 1534.27V1517.21C2116.18 1499.85 2116.18 1491.17 2112.8 1484.54C2109.83 1478.71 2105.09 1473.96 2099.25 1470.99C2094.1 1468.37 2087.71 1467.78 2076.96 1467.65L2069.83 1458.74C2067.36 1455.66 2063.63 1453.87 2059.68 1453.87H2026.85ZM2019.96 1479.86H2066.58C2075.46 1479.86 2081.39 1479.87 2085.94 1480.24C2090.35 1480.61 2092.39 1481.24 2093.69 1481.91C2097.22 1483.7 2100.09 1486.57 2101.88 1490.1C2102.55 1491.4 2103.19 1493.44 2103.55 1497.85C2103.92 1502.4 2103.93 1508.33 2103.93 1517.21V1534.27C2103.93 1543.15 2103.92 1549.08 2103.55 1553.63C2103.19 1558.04 2102.55 1560.08 2101.88 1561.38C2100.09 1564.91 2097.22 1567.78 2093.69 1569.57C2092.39 1570.24 2090.35 1570.88 2085.94 1571.24C2081.39 1571.61 2075.46 1571.62 2066.58 1571.62H2019.96C2011.07 1571.62 2005.15 1571.61 2000.59 1571.24C1996.18 1570.88 1994.15 1570.24 1992.85 1569.57C1989.32 1567.78 1986.45 1564.91 1984.65 1561.38C1983.99 1560.08 1983.35 1558.04 1982.99 1553.63C1982.62 1549.08 1982.61 1543.15 1982.61 1534.27V1517.21C1982.61 1508.33 1982.62 1502.4 1982.99 1497.85C1983.35 1493.44 1983.99 1491.4 1984.65 1490.1C1986.45 1486.57 1989.32 1483.7 1992.85 1481.91C1994.15 1481.24 1996.18 1480.61 2000.59 1480.24C2005.15 1479.87 2011.07 1479.86 2019.96 1479.86Z" fill="black"/> -<path id="Rectangle 11906_4" d="M2017.45 1525.74C2017.45 1511.48 2029.01 1499.92 2043.27 1499.92V1499.92C2057.53 1499.92 2069.09 1511.48 2069.09 1525.74V1525.74C2069.09 1540 2057.53 1551.56 2043.27 1551.56V1551.56C2029.01 1551.56 2017.45 1540 2017.45 1525.74V1525.74Z" fill="black"/> -</g> -<g id="Medium-L"> -<path id="Union_5" fill-rule="evenodd" clip-rule="evenodd" d="M1730.14 1453.84C1726.2 1453.84 1722.47 1455.63 1720 1458.71L1713.75 1466.52C1713.48 1466.86 1713.29 1467.23 1713.17 1467.61C1701.82 1467.7 1695.26 1468.19 1690.03 1470.86C1684.38 1473.73 1679.79 1478.32 1676.92 1483.97C1673.65 1490.38 1673.65 1498.78 1673.65 1515.59V1535.84C1673.65 1552.64 1673.65 1561.04 1676.92 1567.46C1679.79 1573.11 1684.38 1577.69 1690.03 1580.57C1696.45 1583.84 1704.85 1583.84 1721.65 1583.84H1771.47C1788.27 1583.84 1796.67 1583.84 1803.09 1580.57C1808.73 1577.69 1813.32 1573.11 1816.2 1567.46C1819.47 1561.04 1819.47 1552.64 1819.47 1535.84V1515.59C1819.47 1498.78 1819.47 1490.38 1816.2 1483.97C1813.32 1478.32 1808.73 1473.73 1803.09 1470.86C1797.9 1468.21 1791.42 1467.71 1780.24 1467.61L1773.12 1458.72C1770.65 1455.64 1766.92 1453.84 1762.97 1453.84H1730.14ZM1721.65 1478.34H1771.47C1780.05 1478.34 1785.83 1478.34 1790.3 1478.71C1794.64 1479.06 1796.77 1479.7 1798.21 1480.43C1801.83 1482.28 1804.78 1485.22 1806.62 1488.85C1807.35 1490.29 1807.99 1492.42 1808.35 1496.76C1808.71 1501.22 1808.72 1507.01 1808.72 1515.59V1535.84C1808.72 1544.42 1808.71 1550.21 1808.35 1554.67C1807.99 1559.01 1807.35 1561.14 1806.62 1562.58C1804.78 1566.2 1801.83 1569.15 1798.21 1570.99C1796.77 1571.73 1794.64 1572.36 1790.3 1572.72C1785.83 1573.08 1780.05 1573.09 1771.47 1573.09H1721.65C1713.07 1573.09 1707.28 1573.08 1702.82 1572.72C1698.48 1572.36 1696.35 1571.73 1694.91 1570.99C1691.29 1569.15 1688.34 1566.2 1686.5 1562.58C1685.76 1561.14 1685.13 1559.01 1684.77 1554.67C1684.41 1550.21 1684.4 1544.42 1684.4 1535.84V1515.59C1684.4 1507.01 1684.41 1501.22 1684.77 1496.76C1685.13 1492.42 1685.76 1490.29 1686.5 1488.85C1688.34 1485.22 1691.29 1482.28 1694.91 1480.43C1696.35 1479.7 1698.48 1479.06 1702.82 1478.71C1707.28 1478.34 1713.07 1478.34 1721.65 1478.34Z" fill="black"/> -<path id="Rectangle 11906_5" d="M1720.74 1525.71C1720.74 1511.45 1732.3 1499.89 1746.56 1499.89V1499.89C1760.82 1499.89 1772.38 1511.45 1772.38 1525.71V1525.71C1772.38 1539.97 1760.82 1551.53 1746.56 1551.53V1551.53C1732.3 1551.53 1720.74 1539.97 1720.74 1525.71V1525.71Z" fill="black"/> -</g> -<g id="Regular-L"> -<path id="Union_6" fill-rule="evenodd" clip-rule="evenodd" d="M1433.49 1453.82C1429.55 1453.82 1425.82 1455.61 1423.36 1458.68L1417.1 1466.49C1416.83 1466.83 1416.64 1467.19 1416.53 1467.56C1404.28 1467.6 1397.57 1467.92 1392.29 1470.61C1387.02 1473.29 1382.74 1477.58 1380.05 1482.85C1377 1488.84 1377 1496.68 1377 1512.36V1539.01C1377 1554.69 1377 1562.54 1380.05 1568.53C1382.74 1573.79 1387.02 1578.08 1392.29 1580.76C1398.28 1583.81 1406.12 1583.81 1421.8 1583.81H1478.02C1493.7 1583.81 1501.54 1583.81 1507.53 1580.76C1512.8 1578.08 1517.09 1573.79 1519.77 1568.53C1522.82 1562.54 1522.82 1554.69 1522.82 1539.01V1512.36C1522.82 1496.68 1522.82 1488.84 1519.77 1482.85C1517.09 1477.58 1512.8 1473.29 1507.53 1470.61C1502.3 1467.94 1495.65 1467.61 1483.58 1467.56L1476.47 1458.69C1474 1455.61 1470.27 1453.82 1466.32 1453.82H1433.49ZM1421.8 1476.06H1478.02C1486 1476.06 1491.48 1476.07 1495.72 1476.41C1499.86 1476.75 1502.08 1477.37 1503.67 1478.18C1507.34 1480.05 1510.33 1483.04 1512.2 1486.71C1513.01 1488.3 1513.63 1490.52 1513.97 1494.66C1514.32 1498.9 1514.32 1504.38 1514.32 1512.36V1539.01C1514.32 1546.99 1514.32 1552.47 1513.97 1556.71C1513.63 1560.85 1513.01 1563.07 1512.2 1564.67C1510.33 1568.34 1507.34 1571.32 1503.67 1573.19C1502.08 1574 1499.86 1574.62 1495.72 1574.96C1491.48 1575.31 1486 1575.31 1478.02 1575.31H1421.8C1413.82 1575.31 1408.35 1575.31 1404.1 1574.96C1399.96 1574.62 1397.74 1574 1396.15 1573.19C1392.48 1571.32 1389.5 1568.34 1387.63 1564.67C1386.81 1563.07 1386.19 1560.85 1385.85 1556.71C1385.51 1552.47 1385.5 1546.99 1385.5 1539.01V1512.36C1385.5 1504.38 1385.51 1498.9 1385.85 1494.66C1386.19 1490.52 1386.81 1488.3 1387.63 1486.71C1389.5 1483.04 1392.48 1480.05 1396.15 1478.18C1397.74 1477.37 1399.96 1476.75 1404.1 1476.41C1408.35 1476.07 1413.82 1476.06 1421.8 1476.06Z" fill="black"/> -<path id="Rectangle 11906_6" d="M1424.09 1525.68C1424.09 1511.42 1435.65 1499.86 1449.91 1499.86V1499.86C1464.17 1499.86 1475.73 1511.42 1475.73 1525.68V1525.68C1475.73 1539.94 1464.17 1551.5 1449.91 1551.5V1551.5C1435.65 1551.5 1424.09 1539.94 1424.09 1525.68V1525.68Z" fill="black"/> -</g> -<g id="Light-L"> -<path id="Union_7" fill-rule="evenodd" clip-rule="evenodd" d="M1136.71 1453.92C1132.77 1453.92 1129.04 1455.71 1126.58 1458.78L1120.32 1466.59C1120.06 1466.93 1119.87 1467.29 1119.75 1467.66C1106.56 1467.67 1099.71 1467.8 1094.42 1470.49C1089.53 1472.99 1085.55 1476.96 1083.06 1481.86C1080.22 1487.42 1080.22 1494.7 1080.22 1509.26V1542.31C1080.22 1556.88 1080.22 1564.16 1083.06 1569.72C1085.55 1574.61 1089.53 1578.59 1094.42 1581.08C1099.98 1583.91 1107.26 1583.91 1121.82 1583.91H1184.44C1199.01 1583.91 1206.29 1583.91 1211.85 1581.08C1216.74 1578.59 1220.72 1574.61 1223.21 1569.72C1226.04 1564.16 1226.04 1556.88 1226.04 1542.31V1509.26C1226.04 1494.7 1226.04 1487.42 1223.21 1481.86C1220.72 1476.96 1216.74 1472.99 1211.85 1470.49C1206.59 1467.82 1199.81 1467.67 1186.8 1467.66L1179.69 1458.79C1177.22 1455.71 1173.49 1453.92 1169.55 1453.92H1136.71ZM1121.82 1474.91H1184.44C1191.84 1474.91 1196.96 1474.92 1200.93 1475.24C1204.82 1475.56 1206.97 1476.14 1208.56 1476.95C1212.08 1478.75 1214.95 1481.62 1216.75 1485.15C1217.56 1486.74 1218.15 1488.89 1218.46 1492.77C1218.79 1496.75 1218.79 1501.86 1218.79 1509.26V1542.31C1218.79 1549.72 1218.79 1554.83 1218.46 1558.8C1218.15 1562.69 1217.56 1564.84 1216.75 1566.43C1214.95 1569.96 1212.08 1572.82 1208.56 1574.62C1206.97 1575.43 1204.82 1576.02 1200.93 1576.33C1196.96 1576.66 1191.84 1576.66 1184.44 1576.66H1121.82C1114.42 1576.66 1109.31 1576.66 1105.34 1576.33C1101.45 1576.02 1099.3 1575.43 1097.71 1574.62C1094.18 1572.82 1091.31 1569.96 1089.52 1566.43C1088.71 1564.84 1088.12 1562.69 1087.8 1558.8C1087.48 1554.83 1087.47 1549.72 1087.47 1542.31V1509.26C1087.47 1501.86 1087.48 1496.75 1087.8 1492.77C1088.12 1488.89 1088.71 1486.74 1089.52 1485.15C1091.31 1481.62 1094.18 1478.75 1097.71 1476.95C1099.3 1476.14 1101.45 1475.56 1105.34 1475.24C1109.31 1474.92 1114.42 1474.91 1121.82 1474.91Z" fill="black"/> -<path id="Rectangle 11906_7" d="M1127.31 1525.79C1127.31 1511.53 1138.87 1499.96 1153.13 1499.96V1499.96C1167.39 1499.96 1178.95 1511.53 1178.95 1525.79V1525.79C1178.95 1540.05 1167.39 1551.61 1153.13 1551.61V1551.61C1138.87 1551.61 1127.31 1540.05 1127.31 1525.79V1525.79Z" fill="black"/> -</g> -<g id="Thin-L"> -<path id="Union_8" fill-rule="evenodd" clip-rule="evenodd" d="M840.003 1454.01C836.062 1454.01 832.333 1455.8 829.868 1458.88L823.614 1466.68C823.225 1467.17 823.007 1467.71 822.935 1468.25C809.811 1468.26 802.986 1468.39 797.708 1471.08C792.816 1473.58 788.839 1477.55 786.346 1482.45C783.512 1488.01 783.512 1495.29 783.512 1509.85V1541.9C783.512 1556.46 783.512 1563.74 786.346 1569.3C788.839 1574.2 792.816 1578.17 797.708 1580.67C803.27 1583.5 810.551 1583.5 825.112 1583.5H887.733C902.295 1583.5 909.575 1583.5 915.137 1580.67C920.029 1578.17 924.007 1574.2 926.499 1569.3C929.333 1563.74 929.333 1556.46 929.333 1541.9V1509.85C929.333 1495.29 929.333 1488.01 926.499 1482.45C924.007 1477.55 920.029 1473.58 915.137 1471.08C909.937 1468.43 903.236 1468.26 890.487 1468.25L882.981 1458.88C880.514 1455.8 876.781 1454.01 872.836 1454.01H840.003ZM825.112 1472.25H887.733C895.08 1472.25 900.349 1472.25 904.484 1472.59C908.572 1472.92 911.198 1473.57 913.321 1474.65C917.461 1476.76 920.826 1480.12 922.935 1484.26C924.017 1486.39 924.658 1489.01 924.992 1493.1C925.33 1497.23 925.333 1502.5 925.333 1509.85V1541.9C925.333 1549.25 925.33 1554.52 924.992 1558.65C924.658 1562.74 924.017 1565.36 922.935 1567.49C920.826 1571.63 917.461 1574.99 913.321 1577.1C911.198 1578.18 908.572 1578.83 904.484 1579.16C900.349 1579.5 895.08 1579.5 887.733 1579.5H825.112C817.766 1579.5 812.496 1579.5 808.361 1579.16C804.273 1578.83 801.647 1578.18 799.524 1577.1C795.385 1574.99 792.019 1571.63 789.91 1567.49C788.828 1565.36 788.187 1562.74 787.853 1558.65C787.515 1554.52 787.512 1549.25 787.512 1541.9V1509.85C787.512 1502.5 787.515 1497.23 787.853 1493.1C788.187 1489.01 788.828 1486.39 789.91 1484.26C792.019 1480.12 795.385 1476.76 799.524 1474.65C801.647 1473.57 804.273 1472.92 808.361 1472.59C812.496 1472.25 817.766 1472.25 825.112 1472.25Z" fill="black"/> -<path id="Rectangle 11906_8" d="M830.602 1525.88C830.602 1511.62 842.162 1500.06 856.422 1500.06V1500.06C870.683 1500.06 882.243 1511.62 882.243 1525.88V1525.88C882.243 1540.14 870.683 1551.7 856.422 1551.7V1551.7C842.162 1551.7 830.602 1540.14 830.602 1525.88V1525.88Z" fill="black"/> -</g> -<g id="Ultralight-L"> -<path id="Union_9" fill-rule="evenodd" clip-rule="evenodd" d="M543.01 1454.09C539.064 1454.09 535.332 1455.88 532.865 1458.96L524.956 1468.83H523.312C510.431 1468.83 503.99 1468.83 499.07 1471.33C494.743 1473.54 491.224 1477.06 489.019 1481.39C486.512 1486.31 486.512 1492.75 486.512 1505.63V1546.28C486.512 1559.16 486.512 1565.6 489.019 1570.52C491.224 1574.85 494.743 1578.37 499.07 1580.57C503.99 1583.08 510.431 1583.08 523.312 1583.08H595.533C608.414 1583.08 614.855 1583.08 619.775 1580.57C624.103 1578.37 627.621 1574.85 629.826 1570.52C632.333 1565.6 632.333 1559.16 632.333 1546.28V1505.63C632.333 1492.75 632.333 1486.31 629.826 1481.39C627.621 1477.06 624.103 1473.54 619.775 1471.33C614.855 1468.83 608.414 1468.83 595.533 1468.83H593.89L585.981 1458.96C583.514 1455.88 579.782 1454.09 575.836 1454.09H543.01ZM523.312 1471.33H595.533C602.015 1471.33 606.726 1471.33 610.436 1471.63C614.117 1471.93 616.591 1472.52 618.64 1473.56C622.497 1475.53 625.633 1478.66 627.599 1482.52C628.643 1484.57 629.227 1487.04 629.528 1490.73C629.831 1494.44 629.833 1499.15 629.833 1505.63V1546.28C629.833 1552.76 629.831 1557.47 629.528 1561.18C629.227 1564.86 628.643 1567.34 627.599 1569.38C625.633 1573.24 622.497 1576.38 618.64 1578.34C616.591 1579.39 614.117 1579.97 610.436 1580.27C606.726 1580.58 602.015 1580.58 595.533 1580.58H523.312C516.83 1580.58 512.119 1580.58 508.409 1580.27C504.729 1579.97 502.254 1579.39 500.205 1578.34C496.348 1576.38 493.212 1573.24 491.247 1569.38C490.203 1567.34 489.618 1564.86 489.317 1561.18C489.014 1557.47 489.012 1552.76 489.012 1546.28V1505.63C489.012 1499.15 489.014 1494.44 489.317 1490.73C489.618 1487.04 490.203 1484.57 491.247 1482.52C493.212 1478.66 496.348 1475.53 500.205 1473.56C502.254 1472.52 504.729 1471.93 508.409 1471.63C512.119 1471.33 516.83 1471.33 523.312 1471.33Z" fill="black"/> -<path id="Rectangle 11906_9" d="M533.602 1525.95C533.602 1511.69 545.162 1500.13 559.422 1500.13V1500.13C573.683 1500.13 585.243 1511.69 585.243 1525.95V1525.95C585.243 1540.21 573.683 1551.77 559.422 1551.77V1551.77C545.162 1551.77 533.602 1540.21 533.602 1525.95V1525.95Z" fill="black"/> -</g> -<g id="Black-M"> -<path id="Union_10" fill-rule="evenodd" clip-rule="evenodd" d="M2920.33 1039.53C2917.91 1039.53 2915.61 1040.63 2914.09 1042.53L2908.27 1049.79C2905.23 1049.8 2903.38 1049.86 2901.77 1050.12C2890.22 1051.95 2881.16 1061.01 2879.33 1072.56C2879 1074.66 2879 1077.17 2879 1082.19V1104.13C2879 1109.14 2879 1111.65 2879.33 1113.75C2881.16 1125.3 2890.22 1134.36 2901.77 1136.19C2903.87 1136.53 2906.38 1136.53 2911.4 1136.53H2955.4C2960.41 1136.53 2962.92 1136.53 2965.02 1136.19C2976.57 1134.36 2985.63 1125.3 2987.46 1113.75C2987.8 1111.65 2987.8 1109.14 2987.8 1104.13V1082.19C2987.8 1077.17 2987.8 1074.66 2987.46 1072.56C2985.63 1061.01 2976.57 1051.95 2965.02 1050.12C2963.41 1049.86 2961.56 1049.8 2958.52 1049.79L2952.7 1042.53C2951.18 1040.63 2948.89 1039.53 2946.46 1039.53H2920.33ZM2911.4 1067.04H2955.4C2961.07 1067.04 2961.9 1067.09 2962.32 1067.16C2966.49 1067.82 2969.77 1071.09 2970.43 1075.26C2970.49 1075.68 2970.55 1076.51 2970.55 1082.19V1104.13C2970.55 1109.8 2970.49 1110.63 2970.43 1111.05C2969.77 1115.22 2966.49 1118.49 2962.32 1119.16C2961.9 1119.22 2961.07 1119.28 2955.4 1119.28H2911.4C2905.72 1119.28 2904.89 1119.22 2904.47 1119.16C2900.3 1118.49 2897.03 1115.22 2896.37 1111.05C2896.3 1110.63 2896.25 1109.8 2896.25 1104.13V1082.19C2896.25 1076.51 2896.3 1075.68 2896.37 1075.26C2897.03 1071.09 2900.3 1067.82 2904.47 1067.16C2904.89 1067.09 2905.72 1067.04 2911.4 1067.04Z" fill="black"/> -<path id="Rectangle 11906_10" d="M2914.13 1093.15C2914.13 1082.51 2922.76 1073.89 2933.4 1073.89V1073.89C2944.04 1073.89 2952.66 1082.51 2952.66 1093.15V1093.15C2952.66 1103.79 2944.04 1112.42 2933.4 1112.42V1112.42C2922.76 1112.42 2914.13 1103.79 2914.13 1093.15V1093.15Z" fill="black"/> -</g> -<g id="Heavy-M"> -<path id="Union_11" fill-rule="evenodd" clip-rule="evenodd" d="M2623.63 1040.53C2621.2 1040.53 2618.91 1041.63 2617.39 1043.53L2611.57 1050.79C2607.4 1050.79 2605.22 1050.8 2603.38 1051.09C2592.69 1052.79 2584.3 1061.18 2582.6 1071.87C2582.29 1073.82 2582.29 1076.14 2582.29 1080.79V1107.53C2582.29 1112.17 2582.29 1114.49 2582.6 1116.44C2584.3 1127.13 2592.69 1135.52 2603.38 1137.22C2605.33 1137.53 2607.65 1137.53 2612.29 1137.53H2661.09C2665.74 1137.53 2668.06 1137.53 2670 1137.22C2680.7 1135.52 2689.09 1127.13 2690.79 1116.44C2691.09 1114.49 2691.09 1112.17 2691.09 1107.53V1080.79C2691.09 1076.14 2691.09 1073.82 2690.79 1071.87C2689.09 1061.18 2680.7 1052.79 2670 1051.09C2668.16 1050.8 2665.98 1050.79 2661.81 1050.79L2656 1043.53C2654.48 1041.63 2652.18 1040.53 2649.76 1040.53H2623.63ZM2612.29 1065.79H2661.09C2666.31 1065.79 2667.17 1065.83 2667.66 1065.91C2671.94 1066.59 2675.29 1069.94 2675.97 1074.22C2676.05 1074.7 2676.09 1075.57 2676.09 1080.79V1107.53C2676.09 1112.74 2676.05 1113.61 2675.97 1114.09C2675.29 1118.37 2671.94 1121.72 2667.66 1122.4C2667.17 1122.48 2666.31 1122.53 2661.09 1122.53H2612.29C2607.08 1122.53 2606.21 1122.48 2605.73 1122.4C2601.45 1121.72 2598.09 1118.37 2597.42 1114.09C2597.34 1113.61 2597.29 1112.74 2597.29 1107.53V1080.79C2597.29 1075.57 2597.34 1074.7 2597.42 1074.22C2598.09 1069.94 2601.45 1066.59 2605.73 1065.91C2606.21 1065.83 2607.08 1065.79 2612.29 1065.79Z" fill="black"/> -<path id="Rectangle 11906_11" d="M2617.43 1094.15C2617.43 1083.51 2626.05 1074.89 2636.69 1074.89V1074.89C2647.33 1074.89 2655.96 1083.51 2655.96 1094.15V1094.15C2655.96 1104.79 2647.33 1113.42 2636.69 1113.42V1113.42C2626.05 1113.42 2617.43 1104.79 2617.43 1094.15V1094.15Z" fill="black"/> -</g> -<g id="Bold-M"> -<path id="Union_12" fill-rule="evenodd" clip-rule="evenodd" d="M2326.91 1040.53C2324.49 1040.53 2322.19 1041.63 2320.67 1043.53L2314.86 1050.78H2314.38C2309.92 1050.78 2307.69 1050.78 2305.82 1051.08C2295.55 1052.7 2287.5 1060.76 2285.87 1071.03C2285.58 1072.89 2285.58 1075.12 2285.58 1079.58V1108.72C2285.58 1113.18 2285.58 1115.41 2285.87 1117.28C2287.5 1127.55 2295.55 1135.6 2305.82 1137.23C2307.69 1137.52 2309.92 1137.52 2314.38 1137.52H2365.58C2370.04 1137.52 2372.27 1137.52 2374.13 1137.23C2384.4 1135.6 2392.45 1127.55 2394.08 1117.28C2394.38 1115.41 2394.38 1113.18 2394.38 1108.72V1079.58C2394.38 1075.12 2394.38 1072.89 2394.08 1071.03C2392.45 1060.76 2384.4 1052.7 2374.13 1051.08C2372.27 1050.78 2370.04 1050.78 2365.58 1050.78H2365.1L2359.28 1043.53C2357.76 1041.63 2355.47 1040.53 2353.04 1040.53H2326.91ZM2314.38 1063.28H2365.58C2370.51 1063.28 2371.53 1063.32 2372.18 1063.42C2377.1 1064.2 2380.96 1068.06 2381.73 1072.98C2381.84 1073.63 2381.88 1074.64 2381.88 1079.58V1108.72C2381.88 1113.66 2381.84 1114.67 2381.73 1115.32C2380.96 1120.24 2377.1 1124.1 2372.18 1124.88C2371.53 1124.98 2370.51 1125.02 2365.58 1125.02H2314.38C2309.44 1125.02 2308.43 1124.98 2307.78 1124.88C2302.86 1124.1 2299 1120.24 2298.22 1115.32C2298.11 1114.67 2298.08 1113.66 2298.08 1108.72V1079.58C2298.08 1074.64 2298.11 1073.63 2298.22 1072.98C2299 1068.06 2302.86 1064.2 2307.78 1063.42C2308.43 1063.32 2309.44 1063.28 2314.38 1063.28Z" fill="black"/> -<path id="Rectangle 11906_12" d="M2320.71 1094.15C2320.71 1083.51 2329.34 1074.88 2339.98 1074.88V1074.88C2350.62 1074.88 2359.24 1083.51 2359.24 1094.15V1094.15C2359.24 1104.79 2350.62 1113.41 2339.98 1113.41V1113.41C2329.34 1113.41 2320.71 1104.79 2320.71 1094.15V1094.15Z" fill="black"/> -</g> -<g id="Semibold-M"> -<path id="Union_13" fill-rule="evenodd" clip-rule="evenodd" d="M2030.2 1039.89C2027.78 1039.89 2025.48 1040.99 2023.96 1042.89L2018.15 1050.14H2016.47C2012.19 1050.14 2010.06 1050.14 2008.27 1050.43C1998.43 1051.99 1990.71 1059.71 1989.15 1069.55C1988.87 1071.33 1988.87 1073.47 1988.87 1077.74V1109.28C1988.87 1113.56 1988.87 1115.69 1989.15 1117.48C1990.71 1127.32 1998.43 1135.04 2008.27 1136.6C2010.06 1136.88 2012.19 1136.88 2016.47 1136.88H2070.07C2074.34 1136.88 2076.48 1136.88 2078.26 1136.6C2088.11 1135.04 2095.82 1127.32 2097.38 1117.48C2097.67 1115.69 2097.67 1113.56 2097.67 1109.28V1077.74C2097.67 1073.47 2097.67 1071.33 2097.38 1069.55C2095.82 1059.71 2088.11 1051.99 2078.26 1050.43C2076.48 1050.14 2074.34 1050.14 2070.07 1050.14H2068.39L2062.57 1042.89C2061.05 1040.99 2058.76 1039.89 2056.33 1039.89H2030.2ZM2016.47 1060.89H2070.07C2074.75 1060.89 2075.84 1060.93 2076.58 1061.05C2081.82 1061.88 2085.93 1065.99 2086.76 1071.23C2086.88 1071.97 2086.92 1073.06 2086.92 1077.74V1109.28C2086.92 1113.97 2086.88 1115.06 2086.76 1115.8C2085.93 1121.04 2081.82 1125.15 2076.58 1125.98C2075.84 1126.1 2074.75 1126.13 2070.07 1126.13H2016.47C2011.78 1126.13 2010.69 1126.1 2009.95 1125.98C2004.71 1125.15 2000.6 1121.04 1999.77 1115.8C1999.65 1115.06 1999.62 1113.97 1999.62 1109.28V1077.74C1999.62 1073.06 1999.65 1071.97 1999.77 1071.23C2000.6 1065.99 2004.71 1061.88 2009.95 1061.05C2010.69 1060.93 2011.78 1060.89 2016.47 1060.89Z" fill="black"/> -<path id="Rectangle 11906_13" d="M2024 1093.51C2024 1082.87 2032.63 1074.25 2043.27 1074.25V1074.25C2053.91 1074.25 2062.53 1082.87 2062.53 1093.51V1093.51C2062.53 1104.15 2053.91 1112.78 2043.27 1112.78V1112.78C2032.63 1112.78 2024 1104.15 2024 1093.51V1093.51Z" fill="black"/> -</g> -<g id="Medium-M"> -<path id="Union_14" fill-rule="evenodd" clip-rule="evenodd" d="M1733.49 1039.76C1731.06 1039.76 1728.77 1040.86 1727.25 1042.76L1721.43 1050.01H1717.35C1713.45 1050.01 1711.5 1050.01 1709.87 1050.27C1700.88 1051.69 1693.83 1058.74 1692.41 1067.73C1692.15 1069.36 1692.15 1071.31 1692.15 1075.21V1111.55C1692.15 1115.45 1692.15 1117.4 1692.41 1119.04C1693.83 1128.02 1700.88 1135.07 1709.87 1136.49C1711.5 1136.75 1713.45 1136.75 1717.35 1136.75H1775.75C1779.65 1136.75 1781.61 1136.75 1783.24 1136.49C1792.22 1135.07 1799.27 1128.02 1800.69 1119.04C1800.95 1117.4 1800.95 1115.45 1800.95 1111.55V1075.21C1800.95 1071.31 1800.95 1069.36 1800.69 1067.73C1799.27 1058.74 1792.22 1051.69 1783.24 1050.27C1781.61 1050.01 1779.65 1050.01 1775.75 1050.01H1771.67L1765.86 1042.76C1764.34 1040.86 1762.04 1039.76 1759.62 1039.76H1733.49ZM1717.35 1059.51H1775.75C1780.02 1059.51 1781.04 1059.54 1781.75 1059.65C1786.67 1060.43 1790.53 1064.29 1791.31 1069.21C1791.42 1069.92 1791.45 1070.95 1791.45 1075.21V1111.55C1791.45 1115.82 1791.42 1116.84 1791.31 1117.55C1790.53 1122.47 1786.67 1126.33 1781.75 1127.11C1781.04 1127.22 1780.02 1127.25 1775.75 1127.25H1717.35C1713.09 1127.25 1712.06 1127.22 1711.35 1127.11C1706.43 1126.33 1702.57 1122.47 1701.79 1117.55C1701.68 1116.84 1701.65 1115.82 1701.65 1111.55V1075.21C1701.65 1070.95 1701.68 1069.92 1701.79 1069.21C1702.57 1064.29 1706.43 1060.43 1711.35 1059.65C1712.06 1059.54 1713.09 1059.51 1717.35 1059.51Z" fill="black"/> -<path id="Rectangle 11906_14" d="M1727.29 1093.38C1727.29 1082.74 1735.91 1074.11 1746.55 1074.11V1074.11C1757.19 1074.11 1765.82 1082.74 1765.82 1093.38V1093.38C1765.82 1104.02 1757.19 1112.64 1746.55 1112.64V1112.64C1735.91 1112.64 1727.29 1104.02 1727.29 1093.38V1093.38Z" fill="black"/> -</g> -<g id="Regular-M"> -<path id="Union_15" fill-rule="evenodd" clip-rule="evenodd" d="M1436.78 1039.77C1434.35 1039.77 1432.06 1040.87 1430.54 1042.77L1424.72 1050.02H1418.24C1414.71 1050.02 1412.95 1050.02 1411.47 1050.26C1403.34 1051.55 1396.96 1057.92 1395.68 1066.05C1395.44 1067.53 1395.44 1069.29 1395.44 1072.82V1113.96C1395.44 1117.49 1395.44 1119.26 1395.68 1120.74C1396.96 1128.87 1403.34 1135.24 1411.47 1136.53C1412.95 1136.76 1414.71 1136.76 1418.24 1136.76H1481.44C1484.97 1136.76 1486.74 1136.76 1488.21 1136.53C1496.34 1135.24 1502.72 1128.87 1504.01 1120.74C1504.24 1119.26 1504.24 1117.49 1504.24 1113.96V1072.82C1504.24 1069.29 1504.24 1067.53 1504.01 1066.05C1502.72 1057.92 1496.34 1051.55 1488.21 1050.26C1486.74 1050.02 1484.97 1050.02 1481.44 1050.02H1474.96L1469.15 1042.77C1467.63 1040.87 1465.33 1039.77 1462.9 1039.77H1436.78ZM1418.24 1058.02H1481.44C1485.28 1058.02 1486.26 1058.05 1486.96 1058.16C1491.67 1058.9 1495.36 1062.6 1496.11 1067.3C1496.22 1068 1496.24 1068.99 1496.24 1072.82V1113.96C1496.24 1117.8 1496.22 1118.79 1496.11 1119.48C1495.36 1124.19 1491.67 1127.88 1486.96 1128.63C1486.26 1128.74 1485.28 1128.76 1481.44 1128.76H1418.24C1414.41 1128.76 1413.42 1128.74 1412.72 1128.63C1408.01 1127.88 1404.32 1124.19 1403.58 1119.48C1403.47 1118.79 1403.44 1117.8 1403.44 1113.96V1072.82C1403.44 1068.99 1403.47 1068 1403.58 1067.3C1404.32 1062.6 1408.01 1058.9 1412.72 1058.16C1413.42 1058.05 1414.41 1058.02 1418.24 1058.02Z" fill="black"/> -<path id="Rectangle 11906_15" d="M1430.58 1093.39C1430.58 1082.75 1439.2 1074.12 1449.84 1074.12V1074.12C1460.48 1074.12 1469.11 1082.75 1469.11 1093.39V1093.39C1469.11 1104.03 1460.48 1112.66 1449.84 1112.66V1112.66C1439.2 1112.66 1430.58 1104.03 1430.58 1093.39V1093.39Z" fill="black"/> -</g> -<g id="Light-M"> -<path id="Union_16" fill-rule="evenodd" clip-rule="evenodd" d="M1140.07 1040.96C1137.64 1040.96 1135.34 1042.06 1133.83 1043.95L1128.01 1051.21H1119.13C1115.97 1051.21 1114.39 1051.21 1113.07 1051.42C1105.8 1052.57 1100.09 1058.28 1098.94 1065.55C1098.73 1066.87 1098.73 1068.45 1098.73 1071.61V1117.55C1098.73 1120.71 1098.73 1122.29 1098.94 1123.61C1100.09 1130.88 1105.8 1136.59 1113.07 1137.74C1114.39 1137.95 1115.97 1137.95 1119.13 1137.95H1187.13C1190.29 1137.95 1191.87 1137.95 1193.19 1137.74C1200.47 1136.59 1206.17 1130.88 1207.32 1123.61C1207.53 1122.29 1207.53 1120.71 1207.53 1117.55V1071.61C1207.53 1068.45 1207.53 1066.87 1207.32 1065.55C1206.17 1058.28 1200.47 1052.57 1193.19 1051.42C1191.87 1051.21 1190.29 1051.21 1187.13 1051.21H1178.25L1172.44 1043.95C1170.92 1042.06 1168.62 1040.96 1166.19 1040.96H1140.07ZM1119.13 1057.21H1187.13C1190.52 1057.21 1191.51 1057.23 1192.25 1057.35C1196.96 1058.09 1200.65 1061.78 1201.4 1066.49C1201.51 1067.23 1201.53 1068.22 1201.53 1071.61V1117.55C1201.53 1120.94 1201.51 1121.93 1201.4 1122.67C1200.65 1127.38 1196.96 1131.07 1192.25 1131.82C1191.51 1131.93 1190.52 1131.95 1187.13 1131.95H1119.13C1115.74 1131.95 1114.75 1131.93 1114.01 1131.82C1109.3 1131.07 1105.61 1127.38 1104.87 1122.67C1104.75 1121.93 1104.73 1120.94 1104.73 1117.55V1071.61C1104.73 1068.22 1104.75 1067.23 1104.87 1066.49C1105.61 1061.78 1109.3 1058.09 1114.01 1057.35C1114.75 1057.23 1115.74 1057.21 1119.13 1057.21Z" fill="black"/> -<path id="Rectangle 11906_16" d="M1133.87 1094.58C1133.87 1083.94 1142.49 1075.31 1153.13 1075.31V1075.31C1163.77 1075.31 1172.4 1083.94 1172.4 1094.58V1094.58C1172.4 1105.22 1163.77 1113.84 1153.13 1113.84V1113.84C1142.49 1113.84 1133.87 1105.22 1133.87 1094.58V1094.58Z" fill="black"/> -</g> -<g id="Thin-M"> -<path id="Union_17" fill-rule="evenodd" clip-rule="evenodd" d="M843.36 1040.88C840.932 1040.88 838.635 1041.99 837.117 1043.88L830.899 1051.64H821.222C818.249 1051.64 816.763 1051.64 815.519 1051.84C808.673 1052.92 803.303 1058.29 802.219 1065.14C802.022 1066.38 802.022 1067.87 802.022 1070.84V1118.18C802.022 1121.15 802.022 1122.64 802.219 1123.88C803.303 1130.73 808.673 1136.1 815.519 1137.18C816.763 1137.38 818.249 1137.38 821.222 1137.38H891.622C894.595 1137.38 896.081 1137.38 897.325 1137.18C904.171 1136.1 909.541 1130.73 910.625 1123.88C910.822 1122.64 910.822 1121.15 910.822 1118.18V1070.84C910.822 1067.87 910.822 1066.38 910.625 1065.14C909.541 1058.29 904.171 1052.92 897.325 1051.84C896.081 1051.64 894.595 1051.64 891.622 1051.64H881.945L875.727 1043.88C874.209 1041.99 871.912 1040.88 869.484 1040.88H843.36ZM821.222 1055.64H891.622C894.748 1055.64 895.845 1055.65 896.699 1055.79C901.834 1056.6 905.861 1060.63 906.674 1065.76C906.81 1066.62 906.822 1067.71 906.822 1070.84V1118.18C906.822 1121.31 906.81 1122.4 906.674 1123.26C905.861 1128.39 901.834 1132.42 896.699 1133.23C895.845 1133.37 894.748 1133.38 891.622 1133.38H821.222C818.096 1133.38 816.999 1133.37 816.145 1133.23C811.01 1132.42 806.983 1128.39 806.17 1123.26C806.034 1122.4 806.022 1121.31 806.022 1118.18V1070.84C806.022 1067.71 806.034 1066.62 806.17 1065.76C806.983 1060.63 811.01 1056.6 816.145 1055.79C816.999 1055.65 818.096 1055.64 821.222 1055.64Z" fill="black"/> -<path id="Rectangle 11906_17" d="M837.157 1094.5C837.157 1083.86 845.782 1075.24 856.422 1075.24V1075.24C867.062 1075.24 875.687 1083.86 875.687 1094.5V1094.5C875.687 1105.14 867.062 1113.77 856.422 1113.77V1113.77C845.782 1113.77 837.157 1105.14 837.157 1094.5V1094.5Z" fill="black"/> -</g> -<g id="Ultralight-M"> -<path id="Union_18" fill-rule="evenodd" clip-rule="evenodd" d="M546.649 1040.88C544.221 1040.88 541.924 1041.99 540.406 1043.88L533.788 1052.14H523.312C520.525 1052.14 519.131 1052.14 517.965 1052.33C511.547 1053.34 506.513 1058.38 505.496 1064.79C505.312 1065.96 505.312 1067.35 505.312 1070.14V1118.88C505.312 1121.67 505.312 1123.06 505.496 1124.23C506.513 1130.65 511.547 1135.68 517.965 1136.7C519.131 1136.88 520.525 1136.88 523.312 1136.88H596.112C598.899 1136.88 600.292 1136.88 601.458 1136.7C607.876 1135.68 612.91 1130.65 613.927 1124.23C614.112 1123.06 614.112 1121.67 614.112 1118.88V1070.14C614.112 1067.35 614.112 1065.96 613.927 1064.79C612.91 1058.38 607.876 1053.34 601.458 1052.33C600.292 1052.14 598.899 1052.14 596.112 1052.14H585.635L579.017 1043.88C577.499 1041.99 575.202 1040.88 572.774 1040.88H546.649ZM523.312 1054.39H596.112C598.985 1054.39 600.159 1054.4 601.106 1054.55C606.562 1055.41 610.84 1059.69 611.705 1065.15C611.855 1066.09 611.862 1067.27 611.862 1070.14V1118.88C611.862 1121.75 611.855 1122.93 611.705 1123.88C610.84 1129.33 606.562 1133.61 601.106 1134.47C600.159 1134.62 598.985 1134.63 596.112 1134.63H523.312C520.439 1134.63 519.264 1134.62 518.317 1134.47C512.861 1133.61 508.583 1129.33 507.718 1123.88C507.569 1122.93 507.562 1121.75 507.562 1118.88V1070.14C507.562 1067.27 507.569 1066.09 507.718 1065.15C508.583 1059.69 512.861 1055.41 518.317 1054.55C519.264 1054.4 520.439 1054.39 523.312 1054.39Z" fill="black"/> -<path id="Rectangle 11906_18" d="M540.446 1094.5C540.446 1083.86 549.072 1075.24 559.711 1075.24V1075.24C570.351 1075.24 578.977 1083.86 578.977 1094.5V1094.5C578.977 1105.14 570.351 1113.77 559.711 1113.77V1113.77C549.072 1113.77 540.446 1105.14 540.446 1094.5V1094.5Z" fill="black"/> -</g> -<g id="Black-S"> -<path id="Union_19" fill-rule="evenodd" clip-rule="evenodd" d="M2923.67 619.23C2921.24 619.23 2918.94 620.333 2917.42 622.228L2913.23 627.461H2909.72C2898.68 627.461 2889.72 636.415 2889.72 647.461V677.097C2889.72 688.143 2898.68 697.097 2909.72 697.097H2957.07C2968.12 697.097 2977.07 688.143 2977.07 677.097V647.461C2977.07 636.415 2968.12 627.461 2957.07 627.461H2953.56L2949.37 622.228C2947.85 620.333 2945.55 619.23 2943.13 619.23H2923.67ZM2909.72 641.461H2957.07C2960.38 641.461 2963.07 644.147 2963.07 647.461V677.097C2963.07 680.411 2960.38 683.097 2957.07 683.097H2909.72C2906.41 683.097 2903.72 680.411 2903.72 677.097V647.461C2903.72 644.147 2906.41 641.461 2909.72 641.461Z" fill="black"/> -<path id="Rectangle 11906_19" d="M2917.93 662.279C2917.93 653.737 2924.85 646.812 2933.4 646.812V646.812C2941.94 646.812 2948.86 653.737 2948.86 662.279V662.279C2948.86 670.821 2941.94 677.745 2933.4 677.745V677.745C2924.85 677.745 2917.93 670.821 2917.93 662.279V662.279Z" fill="black"/> -</g> -<g id="Heavy-S"> -<path id="Union_20" fill-rule="evenodd" clip-rule="evenodd" d="M2626.96 619.668C2624.54 619.668 2622.24 620.771 2620.72 622.666L2616.53 627.898H2612.02C2601.53 627.898 2593.02 636.405 2593.02 646.898V678.535C2593.02 689.028 2601.53 697.535 2612.02 697.535H2661.37C2671.86 697.535 2680.37 689.028 2680.37 678.535V646.898C2680.37 636.405 2671.86 627.898 2661.37 627.898H2656.86L2652.67 622.666C2651.15 620.771 2648.85 619.668 2646.42 619.668H2626.96ZM2612.02 640.398H2661.37C2664.96 640.398 2667.87 643.309 2667.87 646.898V678.535C2667.87 682.124 2664.96 685.035 2661.37 685.035H2612.02C2608.43 685.035 2605.52 682.124 2605.52 678.535V646.898C2605.52 643.309 2608.43 640.398 2612.02 640.398Z" fill="black"/> -<path id="Rectangle 11906_20" d="M2621.23 662.716C2621.23 654.174 2628.15 647.25 2636.69 647.25V647.25C2645.24 647.25 2652.16 654.174 2652.16 662.716V662.716C2652.16 671.258 2645.24 678.183 2636.69 678.183V678.183C2628.15 678.183 2621.23 671.258 2621.23 662.716V662.716Z" fill="black"/> -</g> -<g id="Bold-S"> -<path id="Union_21" fill-rule="evenodd" clip-rule="evenodd" d="M2330.25 619.688C2327.82 619.688 2325.53 620.79 2324.01 622.685L2319.82 627.918H2314.31C2304.37 627.918 2296.31 635.977 2296.31 645.918V679.554C2296.31 689.495 2304.37 697.554 2314.31 697.554H2365.65C2375.6 697.554 2383.65 689.495 2383.65 679.554V645.918C2383.65 635.977 2375.6 627.918 2365.65 627.918H2360.15L2355.95 622.685C2354.44 620.79 2352.14 619.688 2349.71 619.688H2330.25ZM2314.31 638.418H2365.65C2369.8 638.418 2373.15 641.776 2373.15 645.918V679.554C2373.15 683.696 2369.8 687.054 2365.65 687.054H2314.31C2310.17 687.054 2306.81 683.696 2306.81 679.554V645.918C2306.81 641.776 2310.17 638.418 2314.31 638.418Z" fill="black"/> -<path id="Rectangle 11906_21" d="M2324.52 662.736C2324.52 654.194 2331.44 647.27 2339.98 647.27V647.27C2348.52 647.27 2355.45 654.194 2355.45 662.736V662.736C2355.45 671.278 2348.52 678.202 2339.98 678.202V678.202C2331.44 678.202 2324.52 671.278 2324.52 662.736V662.736Z" fill="black"/> -</g> -<g id="Semibold-S"> -<path id="Union_22" fill-rule="evenodd" clip-rule="evenodd" d="M2033.54 620.664C2031.11 620.664 2028.82 621.767 2027.3 623.662L2023.11 628.895H2016.6C2007.21 628.895 1999.6 636.506 1999.6 645.895V681.531C1999.6 690.919 2007.21 698.531 2016.6 698.531H2069.95C2079.33 698.531 2086.95 690.919 2086.95 681.531V645.895C2086.95 636.506 2079.33 628.895 2069.95 628.895H2063.44L2059.24 623.662C2057.73 621.767 2055.43 620.664 2053 620.664H2033.54ZM2016.6 638.145H2069.95C2074.23 638.145 2077.7 641.614 2077.7 645.895V681.531C2077.7 685.811 2074.23 689.281 2069.95 689.281H2016.6C2012.32 689.281 2008.85 685.811 2008.85 681.531V645.895C2008.85 641.614 2012.32 638.145 2016.6 638.145Z" fill="black"/> -<path id="Rectangle 11906_22" d="M2027.81 663.712C2027.81 655.171 2034.73 648.246 2043.27 648.246V648.246C2051.81 648.246 2058.74 655.171 2058.74 663.712V663.712C2058.74 672.254 2051.81 679.179 2043.27 679.179V679.179C2034.73 679.179 2027.81 672.254 2027.81 663.712V663.712Z" fill="black"/> -</g> -<g id="Medium-S"> -<path id="Union_23" fill-rule="evenodd" clip-rule="evenodd" d="M1736.83 620.617C1734.4 620.617 1732.1 621.72 1730.58 623.615L1726.39 628.848H1718.88C1710.05 628.848 1702.88 636.011 1702.88 644.848V682.484C1702.88 691.32 1710.05 698.484 1718.88 698.484H1774.23C1783.07 698.484 1790.23 691.32 1790.23 682.484V644.848C1790.23 636.011 1783.07 628.848 1774.23 628.848H1766.72L1762.53 623.615C1761.01 621.72 1758.71 620.617 1756.29 620.617H1736.83ZM1718.88 637.098H1774.23C1778.51 637.098 1781.98 640.567 1781.98 644.848V682.484C1781.98 686.764 1778.51 690.234 1774.23 690.234H1718.88C1714.6 690.234 1711.13 686.764 1711.13 682.484V644.848C1711.13 640.567 1714.6 637.098 1718.88 637.098Z" fill="black"/> -<path id="Rectangle 11906_23" d="M1731.09 663.666C1731.09 655.124 1738.01 648.199 1746.56 648.199V648.199C1755.1 648.199 1762.02 655.124 1762.02 663.666V663.666C1762.02 672.207 1755.1 679.132 1746.56 679.132V679.132C1738.01 679.132 1731.09 672.207 1731.09 663.666V663.666Z" fill="black"/> -</g> -<g id="Regular-S"> -<path id="Union_24" fill-rule="evenodd" clip-rule="evenodd" d="M1440.12 620.77C1437.69 620.77 1435.39 621.872 1433.87 623.767L1429.68 629H1421.17C1412.89 629 1406.17 635.716 1406.17 644V683.636C1406.17 691.92 1412.89 698.636 1421.17 698.636H1478.52C1486.8 698.636 1493.52 691.92 1493.52 683.636V644C1493.52 635.716 1486.8 629 1478.52 629H1470.01L1465.82 623.767C1464.3 621.872 1462 620.77 1459.58 620.77H1440.12ZM1421.17 636.15H1478.52C1482.86 636.15 1486.37 639.665 1486.37 644V683.636C1486.37 687.972 1482.86 691.486 1478.52 691.486H1421.17C1416.84 691.486 1413.32 687.972 1413.32 683.636V644C1413.32 639.665 1416.84 636.15 1421.17 636.15Z" fill="black"/> -<path id="Rectangle 11906_24" d="M1434.38 663.818C1434.38 655.276 1441.31 648.352 1449.85 648.352V648.352C1458.39 648.352 1465.31 655.276 1465.31 663.818V663.818C1465.31 672.36 1458.39 679.284 1449.85 679.284V679.284C1441.31 679.284 1434.38 672.36 1434.38 663.818V663.818Z" fill="black"/> -</g> -<g id="Light-S"> -<path id="Union_25" fill-rule="evenodd" clip-rule="evenodd" d="M1143.41 620.668C1140.98 620.668 1138.68 621.771 1137.17 623.666L1132.97 628.898H1123.46C1115.73 628.898 1109.46 635.166 1109.46 642.898V684.535C1109.46 692.267 1115.73 698.535 1123.46 698.535H1182.81C1190.54 698.535 1196.81 692.267 1196.81 684.535V642.898C1196.81 635.166 1190.54 628.898 1182.81 628.898H1173.3L1169.11 623.666C1167.59 621.771 1165.3 620.668 1162.87 620.668H1143.41ZM1123.46 634.398H1182.81C1187.51 634.398 1191.31 638.204 1191.31 642.898V684.535C1191.31 689.229 1187.51 693.035 1182.81 693.035H1123.46C1118.77 693.035 1114.96 689.229 1114.96 684.535V642.898C1114.96 638.204 1118.77 634.398 1123.46 634.398Z" fill="black"/> -<path id="Rectangle 11906_25" d="M1137.67 663.716C1137.67 655.174 1144.6 648.25 1153.14 648.25V648.25C1161.68 648.25 1168.6 655.174 1168.6 663.716V663.716C1168.6 672.258 1161.68 679.183 1153.14 679.183V679.183C1144.6 679.183 1137.67 672.258 1137.67 663.716V663.716Z" fill="black"/> -</g> -<g id="Thin-S"> -<path id="Union_26" fill-rule="evenodd" clip-rule="evenodd" d="M846.693 620.742C844.265 620.742 841.968 621.845 840.45 623.74L836.257 628.973H825.749C818.569 628.973 812.749 634.793 812.749 641.973V685.609C812.749 692.788 818.569 698.609 825.749 698.609H887.095C894.275 698.609 900.095 692.788 900.095 685.609V641.973C900.095 634.793 894.275 628.973 887.095 628.973H876.587L872.394 623.74C870.876 621.845 868.579 620.742 866.151 620.742H846.693ZM825.749 632.223H887.095C892.48 632.223 896.845 636.588 896.845 641.973V685.609C896.845 690.994 892.48 695.359 887.095 695.359H825.749C820.364 695.359 815.999 690.994 815.999 685.609V641.973C815.999 636.588 820.364 632.223 825.749 632.223Z" fill="black"/> -<path id="Rectangle 11906_26" d="M840.956 663.791C840.956 655.249 847.88 648.324 856.422 648.324V648.324C864.964 648.324 871.888 655.249 871.888 663.791V663.791C871.888 672.332 864.964 679.257 856.422 679.257V679.257C847.88 679.257 840.956 672.332 840.956 663.791V663.791Z" fill="black"/> -</g> -<g id="Ultralight-S"> -<path id="Union_27" fill-rule="evenodd" clip-rule="evenodd" d="M549.983 620.762C547.555 620.762 545.258 621.865 543.74 623.759L539.14 629.5H528.039C521.411 629.5 516.039 634.873 516.039 641.5V685.14C516.039 691.767 521.411 697.14 528.039 697.14H591.385C598.012 697.14 603.385 691.767 603.385 685.14V641.5C603.385 634.873 598.012 629.5 591.385 629.5H580.284L575.684 623.759C574.166 621.865 571.869 620.762 569.441 620.762H549.983ZM528.039 631.5H591.385C596.908 631.5 601.385 635.977 601.385 641.5V685.14C601.385 690.663 596.908 695.14 591.385 695.14H528.039C522.516 695.14 518.039 690.663 518.039 685.14V641.5C518.039 635.977 522.516 631.5 528.039 631.5Z" fill="black"/> -<path id="Rectangle 11906_27" d="M544.245 663.81C544.245 655.268 551.17 648.344 559.711 648.344V648.344C568.253 648.344 575.178 655.268 575.178 663.81V663.81C575.178 672.352 568.253 679.276 559.711 679.276V679.276C551.17 679.276 544.245 672.352 544.245 663.81V663.81Z" fill="black"/> -</g> -</g> -</g> +<?xml version="1.0" encoding="UTF-8"?> +<!--Generator: Apple Native CoreSVG 175.5--> +<!DOCTYPE svg +PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3300" height="2200"> + <!--glyph: "", point size: 100.0, font version: "18.0d12e2", template writer version: "101"--> + <style>.multicolor-0:custom {fill:#EA4335} +.multicolor-1:custom {fill:#34A853} +.multicolor-2:custom {fill:#4183F0} +.multicolor-3:custom {fill:#FBBC04} + +.hierarchical-0:primary {fill:#212121} +.hierarchical-1:secondary {fill:#4D4D4D} +.hierarchical-2:primary {fill:#212121} +.hierarchical-3:primary {fill:#212121} + +.SFSymbolsPreview34A853 {fill:#34A853;opacity:1.0} +.SFSymbolsPreview4183F0 {fill:#4183F0;opacity:1.0} +.SFSymbolsPreviewEA4335 {fill:#EA4335;opacity:1.0} +.SFSymbolsPreviewFBBC04 {fill:#FBBC04;opacity:1.0} +</style> + <g id="Notes"> + <rect height="2200" id="artboard" style="fill:white;opacity:1" width="3300" x="0" y="0"/> + <line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="292" y2="292"/> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 322)">Weight/Scale Variations</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 559.711 322)">Ultralight</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 856.422 322)">Thin</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1153.13 322)">Light</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1449.84 322)">Regular</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1746.56 322)">Medium</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2043.27 322)">Semibold</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2339.98 322)">Bold</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2636.69 322)">Heavy</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2933.4 322)">Black</text> + <line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1903" y2="1903"/> + <g transform="matrix(1 0 0 1 263 1933)"> + <path d="M9.24805 0.830078C13.5547 0.830078 17.1387-2.74414 17.1387-7.05078C17.1387-11.3574 13.5449-14.9316 9.23828-14.9316C4.94141-14.9316 1.36719-11.3574 1.36719-7.05078C1.36719-2.74414 4.95117 0.830078 9.24805 0.830078ZM9.24805-0.654297C5.70312-0.654297 2.87109-3.49609 2.87109-7.05078C2.87109-10.6055 5.69336-13.4473 9.23828-13.4473C12.793-13.4473 15.6445-10.6055 15.6445-7.05078C15.6445-3.49609 12.8027-0.654297 9.24805-0.654297ZM5.6543-7.05078C5.6543-6.62109 5.95703-6.32812 6.40625-6.32812L8.50586-6.32812L8.50586-4.20898C8.50586-3.76953 8.79883-3.4668 9.22852-3.4668C9.67773-3.4668 9.9707-3.76953 9.9707-4.20898L9.9707-6.32812L12.0898-6.32812C12.5293-6.32812 12.832-6.62109 12.832-7.05078C12.832-7.49023 12.5293-7.79297 12.0898-7.79297L9.9707-7.79297L9.9707-9.90234C9.9707-10.3516 9.67773-10.6543 9.22852-10.6543C8.79883-10.6543 8.50586-10.3516 8.50586-9.90234L8.50586-7.79297L6.40625-7.79297C5.95703-7.79297 5.6543-7.49023 5.6543-7.05078Z"/> + </g> + <g transform="matrix(1 0 0 1 281.867 1933)"> + <path d="M11.709 2.91016C17.1582 2.91016 21.6699-1.61133 21.6699-7.05078C21.6699-12.5 17.1484-17.0117 11.6992-17.0117C6.25977-17.0117 1.74805-12.5 1.74805-7.05078C1.74805-1.61133 6.26953 2.91016 11.709 2.91016ZM11.709 1.25C7.09961 1.25 3.41797-2.44141 3.41797-7.05078C3.41797-11.6602 7.08984-15.3516 11.6992-15.3516C16.3086-15.3516 20.0098-11.6602 20.0098-7.05078C20.0098-2.44141 16.3184 1.25 11.709 1.25ZM7.17773-7.05078C7.17773-6.57227 7.50977-6.25 8.00781-6.25L10.8789-6.25L10.8789-3.36914C10.8789-2.88086 11.2109-2.53906 11.6895-2.53906C12.1777-2.53906 12.5195-2.87109 12.5195-3.36914L12.5195-6.25L15.4004-6.25C15.8887-6.25 16.2305-6.57227 16.2305-7.05078C16.2305-7.53906 15.8887-7.88086 15.4004-7.88086L12.5195-7.88086L12.5195-10.752C12.5195-11.25 12.1777-11.5918 11.6895-11.5918C11.2109-11.5918 10.8789-11.25 10.8789-10.752L10.8789-7.88086L8.00781-7.88086C7.50977-7.88086 7.17773-7.53906 7.17773-7.05078Z"/> + </g> + <g transform="matrix(1 0 0 1 305.646 1933)"> + <path d="M14.9707 5.66406C21.9336 5.66406 27.6953-0.0976562 27.6953-7.05078C27.6953-14.0137 21.9238-19.7754 14.9609-19.7754C8.00781-19.7754 2.25586-14.0137 2.25586-7.05078C2.25586-0.0976562 8.01758 5.66406 14.9707 5.66406ZM14.9707 3.84766C8.93555 3.84766 4.08203-1.01562 4.08203-7.05078C4.08203-13.0957 8.92578-17.9492 14.9609-17.9492C21.0059-17.9492 25.8691-13.0957 25.8691-7.05078C25.8691-1.01562 21.0156 3.84766 14.9707 3.84766ZM9.19922-7.05078C9.19922-6.5332 9.57031-6.17188 10.1172-6.17188L14.0625-6.17188L14.0625-2.2168C14.0625-1.67969 14.4336-1.29883 14.9512-1.29883C15.4883-1.29883 15.8594-1.66992 15.8594-2.2168L15.8594-6.17188L19.8145-6.17188C20.3516-6.17188 20.7324-6.5332 20.7324-7.05078C20.7324-7.59766 20.3613-7.96875 19.8145-7.96875L15.8594-7.96875L15.8594-11.9141C15.8594-12.4609 15.4883-12.8418 14.9512-12.8418C14.4336-12.8418 14.0625-12.4609 14.0625-11.9141L14.0625-7.96875L10.1172-7.96875C9.57031-7.96875 9.19922-7.59766 9.19922-7.05078Z"/> + </g> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 1953)">Design Variations</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1971)">Symbols are supported in up to nine weights and three scales.</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1989)">For optimal layout with text and other symbols, vertically align</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 2007)">symbols with the adjacent text.</text> + <line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="776" x2="776" y1="1919" y2="1933"/> + <g transform="matrix(1 0 0 1 776 1933)"> + <path d="M3.31055 0.15625C3.82812 0.15625 4.08203-0.0390625 4.26758-0.585938L5.52734-4.0332L11.2891-4.0332L12.5488-0.585938C12.7344-0.0390625 12.9883 0.15625 13.4961 0.15625C14.0137 0.15625 14.3457-0.15625 14.3457-0.644531C14.3457-0.810547 14.3164-0.966797 14.2383-1.17188L9.6582-13.3691C9.43359-13.9648 9.0332-14.2676 8.4082-14.2676C7.80273-14.2676 7.39258-13.9746 7.17773-13.3789L2.59766-1.16211C2.51953-0.957031 2.49023-0.800781 2.49023-0.634766C2.49023-0.146484 2.80273 0.15625 3.31055 0.15625ZM6.00586-5.51758L8.37891-12.0898L8.42773-12.0898L10.8008-5.51758Z"/> + </g> + <line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="793.197" x2="793.197" y1="1919" y2="1933"/> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 776 1953)">Margins</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1971)">Leading and trailing margins on the left and right side of each symbol</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1989)">can be adjusted by modifying the x-location of the margin guidelines.</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2007)">Modifications are automatically applied proportionally to all</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2025)">scales and weights.</text> + <g transform="matrix(1 0 0 1 1289 1933)"> + <path d="M2.8418 1.86523L4.54102 3.57422C5.40039 4.44336 6.38672 4.38477 7.31445 3.35938L18.0078-8.42773L17.041-9.4043L6.42578 2.27539C6.07422 2.67578 5.74219 2.77344 5.27344 2.30469L4.10156 1.14258C3.63281 0.683594 3.74023 0.341797 4.14062-0.0195312L15.6152-10.8203L14.6387-11.7871L3.04688-0.898438C2.06055 0.0195312 1.98242 0.996094 2.8418 1.86523ZM9.25781-16.3281C8.83789-15.918 8.80859-15.3418 9.04297-14.9512C9.27734-14.5898 9.73633-14.3555 10.3809-14.5215C11.8457-14.8633 13.3691-14.9219 14.7949-13.9844L14.209-12.5293C13.8672-11.6992 14.043-11.1133 14.5801-10.5664L16.875-8.25195C17.3633-7.76367 17.7734-7.74414 18.3398-7.8418L19.4043-8.03711L20.0684-7.36328L20.0293-6.80664C19.9902-6.30859 20.1172-5.92773 20.6055-5.44922L21.3672-4.70703C21.8457-4.22852 22.4609-4.19922 22.9297-4.66797L25.8398-7.58789C26.3086-8.05664 26.2891-8.65234 25.8105-9.13086L25.0391-9.89258C24.5605-10.3711 24.1895-10.5273 23.7109-10.4883L23.1348-10.4395L22.4902-11.0742L22.7344-12.1973C22.8613-12.7637 22.7051-13.2031 22.1191-13.7891L19.9219-15.9766C16.582-19.2969 12.1484-19.2188 9.25781-16.3281ZM10.752-15.957C13.1836-17.7344 16.4746-17.4316 18.7012-15.2051L21.1328-12.793C21.3672-12.5586 21.4062-12.373 21.3379-12.0312L21.0156-10.5469L22.5195-9.0625L23.5059-9.12109C23.7598-9.13086 23.8379-9.11133 24.0332-8.91602L24.6094-8.33984L22.168-5.89844L21.5918-6.47461C21.3965-6.66992 21.3672-6.74805 21.377-7.01172L21.4453-7.98828L19.9512-9.47266L18.4277-9.21875C18.1055-9.15039 17.959-9.17969 17.7148-9.41406L15.7129-11.416C15.459-11.6504 15.4297-11.8164 15.5859-12.1875L16.4648-14.2773C14.9023-15.7324 12.8711-16.3574 10.8398-15.7617C10.6836-15.7227 10.625-15.8496 10.752-15.957Z"/> + </g> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 1289 1953)">Exporting</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1971)">Symbols should be outlined when exporting to ensure the</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1989)">design is preserved when submitting to Xcode.</text> + <text id="template-version" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1933)">Template v.3.0</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1951)">Requires Xcode 13 or greater</text> + <text id="descriptive-name" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1969)">Generated from lens.cr</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1987)">Typeset at 100 points</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 726)">Small</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1156)">Medium</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1586)">Large</text> + </g> + <g id="Guides"> + <g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 696)"> + <path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/> + </g> + <line id="Baseline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="696" y2="696"/> + <line id="Capline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="625.541" y2="625.541"/> + <g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1126)"> + <path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/> + </g> + <line id="Baseline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1126" y2="1126"/> + <line id="Capline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1055.54" y2="1055.54"/> + <g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1556)"> + <path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/> + </g> + <line id="Baseline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1556" y2="1556"/> + <line id="Capline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1485.54" y2="1485.54"/> + <line id="left-margin-Regular-M" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1377.43" x2="1377.43" y1="1030.79" y2="1150.12"/> + <line id="right-margin-Regular-M" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1522.26" x2="1522.26" y1="1030.79" y2="1150.12"/> + </g> + <g id="Symbols"> + <g id="Black-L" transform="matrix(1 0 0 1 2840.68 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M31.8791-16.84C26.3291-16.84 21.7791-12.32 22.0191-6.78C22.3591 1 23.2491 6.28 25.5091 10.73C28.7691 17.13 33.9691 22.33 40.3691 25.59C47.6391 29.29 57.1591 29.29 76.1991 29.29L84.3191 29.29C89.8391 29.29 94.3191 24.82 94.3191 19.29C94.3191 13.77 89.8391 9.29 84.3191 9.29L76.1991 9.29C66.3491 9.29 60.1691 9.28 55.4991 8.9C51.0691 8.53 49.7991 7.94 49.4491 7.77C46.8091 6.42 44.6691 4.28 43.3291 1.65C43.1491 1.3 42.5591 0.03 42.1991-4.41C42.1391-5.19 42.0791-6.02 42.0391-6.89C41.7591-12.39 37.3791-16.84 31.8791-16.84Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M156.359 6.50485L156.359 6.5049C156.359 15.2226 149.292 22.2897 140.574 22.2897L140.574 22.2897C131.856 22.2897 124.789 15.2226 124.789 6.5049L124.789 6.5048C124.789-2.2129 131.856-9.28 140.574-9.28L140.574-9.28C149.292-9.28 156.359-2.2129 156.359 6.5048Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M76.2391-105.7C72.2991-105.7 68.5691-103.91 66.0991-100.83L58.0191-90.75C50.1591-90.41 44.8391-89.53 40.3691-87.26C33.9691-84 28.7691-78.79 25.5091-72.4C23.2491-67.95 22.3591-62.67 22.0191-54.9C21.7791-49.36 26.3291-44.84 31.8791-44.84C37.3791-44.84 41.7591-49.29 42.0391-54.78C42.0791-55.66 42.1391-56.48 42.1991-57.26C42.5591-61.7 43.1491-62.97 43.3291-63.32C44.6691-65.95 46.8091-68.09 49.4491-69.44C49.7891-69.61 51.0691-70.2 55.4991-70.56C60.1691-70.95 66.3491-70.96 76.1991-70.96L109.219-70.96C119.069-70.96 125.259-70.95 129.929-70.56C134.359-70.2 135.629-69.61 135.979-69.44C138.609-68.09 140.759-65.95 142.099-63.32C142.269-62.97 142.859-61.7 143.229-57.26C143.289-56.48 143.339-55.66 143.389-54.78C143.669-49.29 148.049-44.84 153.549-44.84C159.099-44.84 163.649-49.36 163.409-54.9C163.059-62.67 162.179-67.95 159.919-72.4C156.659-78.79 151.459-84 145.059-87.26C140.569-89.54 135.209-90.42 127.289-90.75L119.209-100.83C116.749-103.91 113.019-105.7 109.069-105.7L76.2391-105.7ZM69.3391-30.84C69.3391-43.72 79.7891-54.16 92.6591-54.16C105.539-54.16 115.979-43.72 115.979-30.84C115.979-17.96 105.539-7.52 92.6591-7.52C79.7891-7.52 69.3391-17.96 69.3391-30.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M140.549-65.72C141.139-64.98 141.659-64.17 142.099-63.32C142.269-62.97 142.859-61.7 143.229-57.26C143.289-56.48 143.339-39.66 143.389-38.78C143.669-33.29 148.049-28.84 153.549-28.84C159.099-28.84 163.649-33.36 163.409-38.9C163.399-39.12 163.379-55.34 163.369-55.56C163.009-62.98 162.119-68.08 159.919-72.4C156.659-78.8 151.459-84 145.059-87.26C140.589-89.53 135.269-90.41 127.419-90.75L140.549-65.72Z"/> + </g> + <g id="Heavy-L" transform="matrix(1 0 0 1 2544.92 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M39.7758-7.42C39.8258-6.07 39.8958-4.84 39.9958-3.7C40.3558 0.71 40.9558 2.19 41.2658 2.8C42.7258 5.67 45.0558 8 47.9258 9.46C48.5358 9.77 50.0158 10.37 54.4258 10.73C59.0358 11.11 65.1158 11.12 74.6558 11.12L83.1958 11.12C88.0958 11.12 92.0758 15.1 92.0758 20C92.0758 24.9 88.0958 28.88 83.1958 28.88L74.6558 28.88C56.1658 28.88 46.9258 28.88 39.8658 25.28C33.6558 22.11 28.6158 17.07 25.4458 10.86C23.1358 6.32 22.3058 0.88 22.0158-7.33C21.8358-12.25 25.8658-16.25 30.7858-16.25C35.6658-16.25 39.5758-12.3 39.7758-7.42Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.536 6.08485L154.536 6.0849C154.536 14.8026 147.468 21.8697 138.751 21.8697L138.751 21.8697C130.033 21.8697 122.966 14.8026 122.966 6.0849L122.966 6.0848C122.966-2.6329 130.033-9.7 138.751-9.7L138.751-9.7C147.468-9.7 154.536-2.6329 154.536 6.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.3458-104.5C71.4058-104.5 67.6658-102.71 65.2058-99.63L56.8158-89.16C49.2858-88.83 44.1758-87.97 39.8658-85.78C33.6558-82.61 28.6158-77.57 25.4458-71.36C23.1358-66.82 22.3058-61.38 22.0158-53.17C21.8358-48.25 25.8658-44.25 30.7858-44.25C35.6658-44.25 39.5758-48.2 39.7758-53.08C39.8258-54.43 39.8958-55.66 39.9958-56.8C40.3558-61.21 40.9558-62.69 41.2658-63.3C42.7258-66.17 45.0558-68.5 47.9258-69.96C48.5358-70.27 50.0158-70.87 54.4258-71.23C59.0358-71.61 65.1158-71.62 74.6558-71.62L108.876-71.62C118.406-71.62 124.486-71.61 129.096-71.23C133.506-70.87 134.986-70.27 135.596-69.96C138.466-68.5 140.796-66.17 142.256-63.3C142.566-62.69 143.166-61.21 143.526-56.8C143.626-55.66 143.696-54.43 143.746-53.08C143.946-48.2 147.856-44.25 152.736-44.25C157.656-44.25 161.686-48.25 161.506-53.17C161.216-61.38 160.386-66.82 158.076-71.36C154.906-77.57 149.866-82.61 143.656-85.78C139.346-87.97 134.236-88.83 126.706-89.16L118.316-99.63C115.856-102.71 112.116-104.5 108.176-104.5L75.3458-104.5ZM68.4458-30.25C68.4458-43.13 78.8858-53.57 91.7658-53.57C104.636-53.57 115.086-43.13 115.086-30.25C115.086-17.37 104.636-6.93 91.7658-6.93C78.8858-6.93 68.4458-17.37 68.4458-30.25Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M140.036-66.54C140.906-65.56 141.656-64.48 142.256-63.3C142.566-62.69 143.166-61.21 143.526-56.8C143.626-55.66 143.696-38.43 143.746-37.08C143.946-32.2 147.856-28.25 152.736-28.25C157.656-28.25 161.686-32.25 161.506-37.17C161.506-37.26 161.496-53.34 161.496-53.43C161.196-61.49 160.366-66.87 158.076-71.36C154.906-77.56 149.866-82.61 143.656-85.78C139.346-87.97 134.236-88.83 126.706-89.16L125.716-90.4L140.036-66.54Z"/> + </g> + <g id="Bold-L" transform="matrix(1 0 0 1 2248.13 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M29.2114-15.25C25.2014-15.25 21.9314-11.99 22.0114-7.98C22.2214 1.55 22.9314 7.52 25.4214 12.4C28.4914 18.42 33.3814 23.32 39.4014 26.39C46.2514 29.88 55.2114 29.88 73.1314 29.88L84.6214 29.88C88.6214 29.88 91.8714 26.63 91.8714 22.62C91.8714 18.62 88.6214 15.38 84.6214 15.38L73.1314 15.38C63.9314 15.38 57.9014 15.36 53.3014 14.99C48.8614 14.62 47.0314 14 45.9914 13.47C42.6914 11.79 40.0214 9.11 38.3414 5.82C37.8114 4.78 37.1814 2.95 36.8214-1.49C36.6614-3.39 36.5714-5.52 36.5214-8.02C36.4314-12.02 33.2114-15.25 29.2114-15.25Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.681 7.08485L154.681 7.0849C154.681 15.8026 147.614 22.8697 138.896 22.8697L138.896 22.8697C130.179 22.8697 123.111 15.8026 123.111 7.0849L123.111 7.0848C123.111-1.6329 130.179-8.7 138.896-8.7L138.896-8.7C147.614-8.7 154.681-1.6329 154.681 7.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.4214-102.13C71.4814-102.13 67.7514-100.34 65.2914-97.27L59.0314-89.46C58.7314-89.08 58.5314-88.68 58.4314-88.26C49.6814-88.02 44.0514-87.26 39.4014-84.89C33.3814-81.82 28.4914-76.92 25.4214-70.9C22.9314-66.02 22.2214-60.05 22.0114-50.52C21.9314-46.51 25.2014-43.25 29.2114-43.25C33.2114-43.25 36.4314-46.48 36.5214-50.48C36.5714-52.98 36.6614-55.11 36.8214-57.01C37.1814-61.45 37.8114-63.28 38.3414-64.32C40.0214-67.61 42.6914-70.29 45.9914-71.97C47.0314-72.5 48.8614-73.12 53.3014-73.49C57.9014-73.86 63.9314-73.88 73.1314-73.88L110.551-73.88C119.751-73.88 125.781-73.86 130.391-73.49C134.831-73.12 136.661-72.5 137.701-71.97C140.991-70.29 143.671-67.61 145.341-64.32C145.871-63.28 146.501-61.45 146.861-57.01C147.021-55.11 147.111-52.98 147.171-50.48C147.261-46.48 150.481-43.25 154.471-43.25C158.491-43.25 161.761-46.51 161.671-50.52C161.471-60.05 160.751-66.02 158.261-70.9C155.201-76.92 150.301-81.82 144.281-84.89C139.701-87.22 134.161-87.99 125.621-88.25L118.401-97.26C115.931-100.34 112.201-102.13 108.261-102.13L75.4214-102.13ZM68.5214-29.25C68.5214-42.13 78.9614-52.57 91.8414-52.57C104.721-52.57 115.161-42.13 115.161-29.25C115.161-16.37 104.721-5.93 91.8414-5.93C78.9614-5.93 68.5214-16.37 68.5214-29.25Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M139.931-70.61C142.201-68.99 144.071-66.83 145.341-64.32C145.871-63.28 146.501-61.45 146.861-57.01C147.021-55.12 147.111-37.98 147.171-35.48C147.261-31.48 150.481-28.25 154.471-28.25C158.491-28.25 161.761-31.51 161.671-35.52C161.671-35.55 161.671-50.57 161.671-50.59C161.461-60.08 160.751-66.03 158.261-70.9C155.201-76.92 150.301-81.82 144.281-84.89C139.741-87.2 134.281-87.98 125.891-88.24L139.931-70.61Z"/> + </g> + <g id="Semibold-L" transform="matrix(1 0 0 1 1951.38 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M28.1104-15.26C24.7204-15.26 21.9704-12.51 22.0104-9.12C22.1504 1.49 22.7404 7.82 25.3504 12.94C28.3204 18.77 33.0604 23.52 38.9004 26.49C45.5304 29.87 54.2104 29.87 71.5704 29.87L85.4904 29.87C88.8704 29.87 91.6104 27.12 91.6104 23.74C91.6104 20.36 88.8704 17.62 85.4904 17.62L71.5704 17.62C62.6904 17.62 56.7604 17.61 52.2104 17.24C47.7904 16.88 45.7604 16.24 44.4604 15.57C40.9304 13.78 38.0604 10.91 36.2604 7.38C35.6004 6.08 34.9604 4.04 34.6004-0.37C34.4004-2.82 34.3104-5.66 34.2604-9.14C34.2204-12.52 31.4904-15.26 28.1104-15.26Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.75 7.08485L154.75 7.0849C154.75 15.8026 147.683 22.8697 138.965 22.8697L138.965 22.8697C130.248 22.8697 123.18 15.8026 123.18 7.0849L123.18 7.0848C123.18-1.6329 130.248-8.7 138.965-8.7L138.965-8.7C147.683-8.7 154.75-1.6329 154.75 7.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.4604-102.13C71.5204-102.13 67.7904-100.34 65.3204-97.27L59.0704-89.46C58.7804-89.1 58.5804-88.7 58.4704-88.3C49.3404-88.1 43.6004-87.4 38.9004-85C33.0604-82.03 28.3204-77.29 25.3504-71.46C22.7404-66.34 22.1504-60 22.0104-49.4C21.9704-46.01 24.7204-43.26 28.1104-43.26C31.4904-43.26 34.2204-45.99 34.2604-49.37C34.3104-52.86 34.4004-55.7 34.6004-58.15C34.9604-62.56 35.6004-64.59 36.2604-65.9C38.0604-69.42 40.9304-72.29 44.4604-74.09C45.7604-74.75 47.7904-75.39 52.2104-75.75C56.7604-76.12 62.6904-76.13 71.5704-76.13L112.19-76.13C121.07-76.13 127-76.12 131.55-75.75C135.96-75.39 138-74.75 139.3-74.09C142.83-72.29 145.7-69.42 147.5-65.9C148.16-64.59 148.8-62.56 149.16-58.15C149.36-55.7 149.45-52.86 149.5-49.37C149.54-45.99 152.27-43.26 155.65-43.26C159.04-43.26 161.79-46.01 161.75-49.4C161.61-60 161.02-66.34 158.41-71.46C155.44-77.29 150.7-82.03 144.86-85C140.22-87.37 134.56-88.08 125.62-88.29L118.44-97.26C115.97-100.34 112.24-102.13 108.29-102.13L75.4604-102.13ZM68.5604-29.26C68.5604-42.14 79.0004-52.58 91.8804-52.58C104.76-52.58 115.2-42.14 115.2-29.26C115.2-16.38 104.76-5.94 91.8804-5.94C79.0004-5.94 68.5604-16.38 68.5604-29.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M136.32-75.1C137.69-74.8 138.6-74.45 139.3-74.09C142.83-72.29 145.7-69.42 147.5-65.9C148.16-64.6 148.8-62.56 149.16-58.15C149.36-55.7 149.45-37.86 149.5-34.37C149.54-31 152.27-28.26 155.65-28.26C159.04-28.26 161.79-31.01 161.75-34.4C161.75-34.41 161.75-49.42 161.75-49.43C161.61-60.02 161.02-66.35 158.41-71.46C155.44-77.29 150.7-82.03 144.86-85.01C140.25-87.36 134.64-88.07 125.81-88.29L136.32-75.1Z"/> + </g> + <g id="Medium-L" transform="matrix(1 0 0 1 1654.65 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.3701-15.97C24.4001-15.97 21.9901-13.56 22.0101-10.59C22.1001 0.73 22.6001 7.26 25.2601 12.49C28.1401 18.13 32.7201 22.72 38.3701 25.6C44.7901 28.87 53.1901 28.87 69.9901 28.87L86.9601 28.87C89.9301 28.87 92.3301 26.46 92.3301 23.49C92.3301 20.52 89.9301 18.12 86.9601 18.12L69.9901 18.12C61.4101 18.12 55.6201 18.11 51.1601 17.74C46.8201 17.39 44.6901 16.75 43.2501 16.02C39.6301 14.17 36.6801 11.23 34.8401 7.61C34.1001 6.17 33.4701 4.03 33.1101-0.3C32.8801-3.1 32.8001-6.41 32.7601-10.6C32.7401-13.57 30.3401-15.97 27.3701-15.97Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.78 5.08485L154.78 5.0849C154.78 13.8026 147.713 20.8697 138.995 20.8697L138.995 20.8697C130.277 20.8697 123.21 13.8026 123.21 5.0849L123.21 5.0848C123.21-3.6329 130.277-10.7 138.995-10.7L138.995-10.7C147.713-10.7 154.78-3.6329 154.78 5.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.4801-104.16C71.5401-104.16 67.8101-102.37 65.3401-99.29L59.0901-91.48C58.5601-90.82 58.3501-90.06 58.3901-89.32C48.9201-89.16 43.1001-88.53 38.3701-86.11C32.7201-83.24 28.1301-78.65 25.2601-73C22.5501-67.69 22.0901-61.02 22.0101-49.35C21.9901-46.38 24.4001-43.97 27.3701-43.97C30.3401-43.97 32.7401-46.37 32.7601-49.34C32.7901-53.81 32.8701-57.29 33.1101-60.21C33.4701-64.55 34.1001-66.68 34.8401-68.12C36.6801-71.74 39.6301-74.69 43.2501-76.53C44.6901-77.27 46.8201-77.91 51.1601-78.26C55.6201-78.62 61.4101-78.63 69.9901-78.63L113.81-78.63C122.39-78.63 128.17-78.62 132.64-78.26C136.97-77.91 139.11-77.27 140.55-76.53C144.17-74.69 147.11-71.74 148.96-68.12C149.69-66.68 150.33-64.55 150.68-60.21C150.92-57.29 151.01-53.81 151.04-49.34C151.06-46.37 153.46-43.97 156.43-43.97C159.4-43.97 161.81-46.38 161.79-49.35C161.71-61.02 161.24-67.69 158.54-73C155.66-78.65 151.07-83.24 145.43-86.11C140.87-88.44 135.31-89.11 126.45-89.3L118.46-99.28C115.99-102.36 112.26-104.16 108.31-104.16L75.4801-104.16ZM68.5801-30.26C68.5801-43.14 79.0201-53.58 91.9001-53.58C104.78-53.58 115.22-43.14 115.22-30.26C115.22-17.38 104.78-6.94 91.9001-6.94C79.0201-6.94 68.5801-17.38 68.5801-30.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M135.7-77.91C138.08-77.55 139.5-77.07 140.55-76.53C144.17-74.69 147.11-71.74 148.96-68.12C149.69-66.68 150.33-64.55 150.68-60.21C150.92-57.29 151.01-38.8 151.04-34.34C151.06-31.37 153.46-28.97 156.43-28.97C159.4-28.97 161.81-31.38 161.79-34.35C161.79-34.36 161.79-49.38 161.79-49.4C161.71-61.04 161.24-67.7 158.54-73C155.66-78.64 151.07-83.23 145.43-86.11C140.9-88.42 135.38-89.1 126.63-89.3L135.7-77.91Z"/> + </g> + <g id="Regular-L" transform="matrix(1 0 0 1 1357.92 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.26-14.26C23.91-14.26 22.01-12.35 22.01-10.01C22.05 2.46 22.35 9.25 25.06 14.58C27.75 19.85 32.03 24.13 37.3 26.82C43.29 29.87 51.13 29.87 66.81 29.87L87.76 29.87C90.11 29.87 92.01 27.96 92.01 25.62C92.01 23.27 90.11 21.37 87.76 21.37L66.81 21.37C58.83 21.37 53.36 21.36 49.11 21.01C44.97 20.68 42.75 20.06 41.16 19.24C37.49 17.37 34.51 14.39 32.64 10.72C31.82 9.12 31.2 6.91 30.86 2.77C30.59-0.54 30.53-4.6 30.52-10.01C30.51-12.35 28.61-14.26 26.26-14.26Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.83 7.08485L154.83 7.0849C154.83 15.8026 147.763 22.8697 139.045 22.8697L139.045 22.8697C130.327 22.8697 123.26 15.8026 123.26 7.0849L123.26 7.0848C123.26-1.6329 130.327-8.7 139.045-8.7L139.045-8.7C147.763-8.7 154.83-1.6329 154.83 7.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.5-102.19C71.56-102.19 67.83-100.4 65.37-97.32L59.11-89.52C58.82-89.15 58.63-88.76 58.52-88.36C48.15-88.27 42.13-87.79 37.3-85.33C32.03-82.65 27.75-78.36 25.06-73.09C22.35-67.77 22.05-60.98 22.01-48.51C22.01-46.16 23.91-44.26 26.26-44.26C28.61-44.26 30.51-46.16 30.52-48.51C30.53-53.92 30.59-57.97 30.86-61.28C31.2-65.42 31.82-67.64 32.64-69.24C34.51-72.9 37.49-75.89 41.16-77.76C42.75-78.57 44.97-79.19 49.11-79.53C53.36-79.88 58.83-79.88 66.81-79.88L117.03-79.88C125.01-79.88 130.49-79.88 134.73-79.53C138.87-79.19 141.09-78.57 142.68-77.76C146.35-75.89 149.34-72.9 151.21-69.24C152.02-67.64 152.64-65.42 152.98-61.28C153.25-57.97 153.31-53.92 153.33-48.51C153.33-46.16 155.23-44.26 157.58-44.26C159.93-44.26 161.83-46.16 161.83-48.51C161.79-60.98 161.49-67.77 158.78-73.09C156.09-78.36 151.81-82.65 146.54-85.33C141.77-87.76 135.82-88.26 125.66-88.36L118.48-97.32C116.01-100.4 112.28-102.19 108.33-102.19L75.5-102.19ZM68.6-29.26C68.6-42.14 79.04-52.58 91.92-52.58C104.8-52.58 115.24-42.14 115.24-29.26C115.24-16.38 104.8-5.94 91.92-5.94C79.04-5.94 68.6-16.38 68.6-29.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M132.82-79.65C133.48-79.62 134.12-79.58 134.73-79.53C138.87-79.19 141.09-78.57 142.68-77.75C146.35-75.88 149.34-72.9 151.21-69.23C152.02-67.63 152.64-65.42 152.98-61.28C153.25-57.97 153.31-38.91 153.33-33.5C153.33-31.16 155.23-29.25 157.58-29.25C159.93-29.25 161.83-31.16 161.83-33.51C161.83-33.52 161.83-48.54 161.83-48.56C161.79-60.99 161.49-67.77 158.78-73.09C156.09-78.36 151.81-82.64 146.54-85.33C141.79-87.75 135.88-88.25 125.82-88.35L132.82-79.65Z"/> + </g> + <g id="Light-L" transform="matrix(1 0 0 1 1061.21 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M25.64-16.26C23.64-16.26 22.01-14.63 22.01-12.63L22.01-11.73C22.01 2.83 22.01 10.11 24.85 15.67C27.34 20.56 31.32 24.54 36.21 27.03C41.77 29.87 49.05 29.87 63.61 29.87L88.16 29.87C90.17 29.87 91.79 28.24 91.79 26.24C91.79 24.24 90.17 22.62 88.16 22.62L63.61 22.62C56.21 22.62 51.1 22.61 47.13 22.29C43.24 21.97 41.09 21.38 39.5 20.57C35.97 18.78 33.1 15.91 31.31 12.38C30.5 10.79 29.91 8.64 29.59 4.75C29.27 0.78 29.26-4.33 29.26-11.73L29.26-12.63C29.26-14.63 27.64-16.26 25.64-16.26Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M155.83 8.08485L155.83 8.0849C155.83 16.8026 148.763 23.8697 140.045 23.8697L140.045 23.8697C131.327 23.8697 124.26 16.8026 124.26 8.0849L124.26 8.0848C124.26-0.632904 131.327-7.7 140.045-7.7L140.045-7.7C148.763-7.7 155.83-0.632904 155.83 8.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.5-102.09C71.56-102.09 67.83-100.3 65.37-97.22L59.11-89.41C58.85-89.09 58.67-88.74 58.55-88.38C47.28-88.34 41.09-88.03 36.21-85.55C31.32-83.06 27.34-79.08 24.85-74.19C22.01-68.62 22.01-61.34 22.01-46.78L22.01-45.88C22.01-43.88 23.64-42.26 25.64-42.26C27.64-42.26 29.26-43.88 29.26-45.88L29.26-46.78C29.26-54.18 29.27-59.3 29.59-63.27C29.91-67.16 30.5-69.31 31.31-70.9C33.1-74.42 35.97-77.29 39.5-79.09C41.09-79.9 43.24-80.49 47.13-80.8C51.1-81.13 56.21-81.13 63.61-81.13L120.23-81.13C127.63-81.13 132.75-81.13 136.72-80.8C140.61-80.49 142.76-79.9 144.35-79.09C147.87-77.29 150.74-74.42 152.54-70.9C153.35-69.31 153.94-67.16 154.25-63.27C154.58-59.3 154.58-54.18 154.58-46.78L154.58-45.88C154.58-43.88 156.21-42.26 158.21-42.26C160.21-42.26 161.83-43.88 161.83-45.88L161.83-46.78C161.83-61.34 161.83-68.62 159-74.19C156.51-79.08 152.53-83.06 147.64-85.55C142.8-88.01 136.66-88.33 125.56-88.38L118.48-97.21C116.01-100.29 112.28-102.09 108.34-102.09L75.5-102.09ZM68.6-29.26C68.6-42.14 79.04-52.58 91.92-52.58C104.8-52.58 115.24-42.14 115.24-29.26C115.24-16.38 104.8-5.94 91.92-5.94C79.04-5.94 68.6-16.38 68.6-29.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M130.42-81.08C132.84-81.03 134.9-80.95 136.72-80.8C140.61-80.48 142.76-79.9 144.35-79.09C147.87-77.29 150.74-74.42 152.54-70.89C153.35-69.31 153.94-67.16 154.25-63.27C154.58-59.3 154.58-54.18 154.58-46.78L154.58-32.88C154.58-30.88 156.21-29.26 158.21-29.26C160.21-29.26 161.83-30.88 161.83-32.88L161.83-46.78C161.83-61.34 161.83-68.62 159-74.19C156.51-79.08 152.53-83.06 147.64-85.55C142.81-88 136.7-88.33 125.67-88.38L130.42-81.08Z"/> + </g> + <g id="Thin-L" transform="matrix(1 0 0 1 764.497 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.01-16.12C22.906-16.12 22.01-15.22 22.01-14.12L22.01-13.09C22.01 1.47 22.01 8.75 24.844 14.31C27.337 19.21 31.314 23.18 36.206 25.68C41.768 28.51 49.049 28.51 63.61 28.51L90.498 28.51C91.602 28.51 92.498 27.61 92.498 26.51C92.498 25.41 91.602 24.51 90.498 24.51L63.61 24.51C56.264 24.51 50.994 24.51 46.859 24.17C42.771 23.84 40.145 23.19 38.022 22.11C33.883 20 30.517 16.64 28.408 12.5C27.326 10.37 26.685 7.75 26.351 3.66C26.013-0.47 26.01-5.74 26.01-13.09L26.01-14.12C26.01-15.22 25.115-16.12 24.01-16.12Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M155.83 6.72485L155.83 6.7249C155.83 15.4426 148.763 22.5097 140.045 22.5097L140.045 22.5097C131.327 22.5097 124.26 15.4426 124.26 6.7249L124.26 6.7248C124.26-1.9929 131.327-9.06 140.045-9.06L140.045-9.06C148.763-9.06 155.83-1.9929 155.83 6.7248Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.507-103.98C71.561-103.98 67.829-102.19 65.362-99.11L57.042-88.73C46.72-88.67 40.861-88.28 36.206-85.91C31.314-83.42 27.337-79.44 24.844-74.55C22.01-68.98 22.01-61.7 22.01-47.14L22.01-46.12C22.01-45.01 22.906-44.12 24.01-44.12C25.115-44.12 26.01-45.01 26.01-46.12L26.01-47.14C26.01-54.49 26.013-59.76 26.351-63.89C26.685-67.98 27.326-70.61 28.408-72.73C30.517-76.87 33.883-80.24 38.022-82.34C40.145-83.43 42.771-84.07 46.859-84.4C50.994-84.74 56.264-84.74 63.61-84.74L120.23-84.74C127.577-84.74 132.846-84.74 136.981-84.4C141.069-84.07 143.695-83.43 145.818-82.34C149.958-80.24 153.323-76.87 155.432-72.73C156.514-70.61 157.155-67.98 157.489-63.89C157.827-59.76 157.83-54.49 157.83-47.14L157.83-46.12C157.83-45.01 158.726-44.12 159.83-44.12C160.935-44.12 161.83-45.01 161.83-46.12L161.83-47.14C161.83-61.7 161.83-68.98 158.996-74.55C156.504-79.44 152.526-83.42 147.634-85.91C142.979-88.28 137.121-88.67 126.798-88.73L118.478-99.11C116.011-102.19 112.279-103.98 108.333-103.98L75.507-103.98ZM68.6-30.12C68.6-43 79.041-53.44 91.92-53.44C104.799-53.44 115.24-43 115.24-30.12C115.24-17.24 104.799-6.8 91.92-6.8C79.041-6.8 68.6-17.24 68.6-30.12Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M129.632-84.7C132.461-84.66 134.869-84.57 136.981-84.4C141.07-84.07 143.695-83.42 145.818-82.34C149.958-80.23 153.323-76.87 155.432-72.73C156.514-70.61 157.155-67.98 157.489-63.89C157.827-59.76 157.83-54.49 157.83-47.14L157.83-31.12C157.83-30.01 158.726-29.12 159.83-29.12C160.935-29.12 161.83-30.01 161.83-31.12L161.83-47.14C161.83-61.7 161.83-68.98 158.996-74.54C156.504-79.44 152.526-83.41 147.634-85.91C143.011-88.26 137.201-88.66 127.009-88.73L129.632-84.7Z"/> + </g> + <g id="Ultralight-L" transform="matrix(1 0 0 1 467.786 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.26-15.25C22.57-15.25 22.01-14.69 22.01-14L22.01-7.92C22.01 4.96 22.01 11.4 24.517 16.32C26.722 20.65 30.241 24.16 34.568 26.37C39.488 28.88 45.929 28.88 58.81 28.88L91.248 28.88C91.938 28.88 92.498 28.32 92.498 27.63C92.498 26.94 91.938 26.38 91.248 26.38L58.81 26.38C52.328 26.38 47.617 26.37 43.907 26.07C40.227 25.77 37.752 25.19 35.703 24.14C31.846 22.18 28.71 19.04 26.745 15.18C25.701 13.13 25.116 10.66 24.815 6.98C24.512 3.27 24.51-1.44 24.51-7.92L24.51-14C24.51-14.69 23.951-15.25 23.26-15.25Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M156.83 8.08485L156.83 8.0849C156.83 16.8026 149.763 23.8697 141.045 23.8697L141.045 23.8697C132.327 23.8697 125.26 16.8026 125.26 8.0849L125.26 8.0848C125.26-0.632904 132.327-7.7 141.045-7.7L141.045-7.7C149.763-7.7 156.83-0.632904 156.83 8.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M65.362-98.04C67.829-101.12 71.561-102.91 75.507-102.91L108.333-102.91C112.279-102.91 116.011-101.12 118.478-98.04L127.008-87.4L127.008-87.4L127.034-87.37C138.593-87.37 144.614-87.24 149.272-84.87C153.6-82.66 157.118-79.14 159.323-74.82C161.83-69.9 161.83-63.46 161.83-50.58L161.83-44.5C161.83-43.81 161.271-43.25 160.58-43.25C159.89-43.25 159.33-43.81 159.33-44.5L159.33-50.58C159.33-57.06 159.328-61.77 159.025-65.48C158.724-69.16 158.14-71.63 157.096-73.68C155.13-77.54 151.994-80.68 148.137-82.64C146.088-83.68 143.614-84.27 139.933-84.57C136.223-84.87 131.512-84.88 125.03-84.88L58.81-84.88C52.328-84.88 47.617-84.87 43.907-84.57C40.227-84.27 37.752-83.68 35.703-82.64C31.846-80.68 28.71-77.54 26.745-73.68C25.701-71.63 25.116-69.16 24.815-65.48C24.512-61.77 24.51-57.06 24.51-50.57L24.51-44.5C24.51-43.81 23.951-43.25 23.26-43.25C22.57-43.25 22.01-43.81 22.01-44.5L22.01-50.57C22.01-63.46 22.01-69.9 24.517-74.82C26.722-79.14 30.241-82.66 34.568-84.87C39.221-87.24 45.233-87.37 56.765-87.37L56.765-87.45L56.877-87.45L65.362-98.04ZM91.92-52.57C79.041-52.57 68.6-42.13 68.6-29.25C68.6-16.37 79.041-5.93 91.92-5.93C104.799-5.93 115.24-16.37 115.24-29.25C115.24-42.13 104.799-52.57 91.92-52.57Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M128.665-84.87C133.331-84.86 136.955-84.81 139.933-84.57C143.613-84.27 146.088-83.68 148.137-82.64C151.994-80.68 155.13-77.54 157.095-73.68C158.139-71.63 158.724-69.16 159.025-65.48C159.328-61.77 159.33-57.06 159.33-50.58L159.33-30.5C159.33-29.81 159.889-29.25 160.58-29.25C161.27-29.25 161.83-29.81 161.83-30.5L161.83-50.58C161.83-63.46 161.83-69.9 159.323-74.82C157.118-79.14 153.599-82.66 149.272-84.87C144.619-87.24 138.606-87.37 127.072-87.38L128.665-84.87Z"/> + </g> + <g id="Black-M" transform="matrix(1 0 0 1 2860.99 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.92-23.78L36.35-23.78C37.95-23.78 39.26-22.48 39.26-20.87C39.26-15.19 39.31-14.36 39.38-13.94C40.04-9.77 43.31-6.5 47.48-5.84C47.9-5.77 48.73-5.72 54.41-5.72L64.39-5.72C69.15-5.72 73.01-1.86 73.01 2.9C73.01 7.67 69.15 11.53 64.39 11.53L54.41 11.53C49.39 11.53 46.88 11.53 44.78 11.2C33.23 9.37 24.17 0.31 22.34-11.25C22.01-13.35 22.01-15.85 22.01-20.87C22.01-22.48 23.31-23.78 24.92-23.78Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.47L118.81-4.47C118.81 2.15742 113.437 7.53 106.81 7.53L106.81 7.53C100.183 7.53 94.81 2.15742 94.81-4.47L94.81-4.47C94.81-11.0974 100.183-16.47 106.81-16.47L106.81-16.47C113.437-16.47 118.81-11.0974 118.81-4.47Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-89.47C60.43-89.47 57.9-88.09 56.42-85.81L50.87-77.2C48.07-77.19 46.32-77.12 44.78-76.88C33.23-75.05 24.17-65.99 22.34-54.43C22.01-52.34 22.01-49.83 22.01-44.81C22.01-42.83 23.62-41.22 25.6-41.22L35.67-41.22C37.65-41.22 39.26-42.83 39.26-44.81C39.26-50.49 39.31-51.32 39.38-51.74C40.04-55.91 43.31-59.18 47.48-59.84C47.9-59.91 48.73-59.96 54.41-59.96L90.41-59.96C96.08-59.96 96.91-59.91 97.33-59.84C101.51-59.18 104.78-55.91 105.44-51.74C105.5-51.32 105.56-50.49 105.56-44.81C105.56-42.83 107.17-41.22 109.15-41.22L119.22-41.22C121.2-41.22 122.81-42.83 122.81-44.81C122.81-49.83 122.81-52.34 122.48-54.43C120.65-65.99 111.59-75.05 100.03-76.88C98.5-77.12 96.74-77.19 93.95-77.2L88.4-85.81C86.92-88.09 84.39-89.47 81.68-89.47L63.14-89.47ZM55.14-32.84C55.14-42.38 62.87-50.11 72.41-50.11C81.94-50.11 89.67-42.38 89.67-32.84C89.67-23.31 81.94-15.58 72.41-15.58C62.87-15.58 55.14-23.31 55.14-32.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M103.65-56C104.56-54.77 105.19-53.32 105.44-51.74C105.5-51.32 105.56-40.49 105.56-34.81C105.56-32.83 107.16-31.22 109.15-31.22L119.22-31.22C121.2-31.22 122.81-32.83 122.81-34.81C122.81-39.83 122.81-52.34 122.48-54.43C120.65-65.99 111.58-75.05 100.03-76.88C98.5-77.12 96.74-77.19 93.95-77.2L93.76-77.5L103.65-56Z"/> + </g> + <g id="Heavy-M" transform="matrix(1 0 0 1 2564.27 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.32-22.78C24.39-22.78 22.01-20.4 22.01-17.47C22.01-12.82 22.01-10.5 22.32-8.56C24.02 2.14 32.41 10.53 43.1 12.22C45.05 12.53 47.37 12.53 52.01 12.53L65.22 12.53C69.36 12.53 72.72 9.17 72.72 5.03C72.72 0.89 69.36-2.47 65.22-2.47L52.01-2.47C46.8-2.47 45.93-2.52 45.45-2.59C41.17-3.27 37.81-6.63 37.14-10.91C37.06-11.39 37.01-12.25 37.01-17.47C37.01-20.4 34.64-22.78 31.7-22.78L27.32-22.78Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-3.47L118.81-3.47C118.81 3.15742 113.437 8.53 106.81 8.53L106.81 8.53C100.183 8.53 94.81 3.15742 94.81-3.47L94.81-3.47C94.81-10.0974 100.183-15.47 106.81-15.47L106.81-15.47C113.437-15.47 118.81-10.0974 118.81-3.47Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.15-88.47C60.43-88.47 57.9-87.09 56.43-84.81L50.88-76.21C46.98-76.21 44.88-76.18 43.1-75.9C32.41-74.21 24.02-65.82 22.32-55.12C22.01-53.18 22.01-50.86 22.01-46.21C22.01-42.9 24.69-40.22 28-40.22L31.02-40.22C34.33-40.22 37.01-42.9 37.01-46.21C37.01-51.43 37.06-52.29 37.14-52.78C37.81-57.05 41.17-60.41 45.45-61.09C45.93-61.16 46.8-61.21 52.01-61.21L92.81-61.21C98.03-61.21 98.89-61.16 99.38-61.09C103.66-60.41 107.01-57.05 107.69-52.78C107.77-52.29 107.81-51.43 107.81-46.21C107.81-42.9 110.49-40.22 113.8-40.22L116.82-40.22C120.13-40.22 122.81-42.9 122.81-46.21C122.81-50.86 122.81-53.18 122.51-55.12C120.81-65.82 112.42-74.21 101.72-75.9C99.95-76.18 97.85-76.21 93.95-76.21L88.4-84.81C86.93-87.09 84.4-88.47 81.68-88.47L63.15-88.47ZM55.15-31.84C55.15-41.38 62.88-49.11 72.41-49.11C81.95-49.11 89.68-41.38 89.68-31.84C89.68-22.31 81.95-14.58 72.41-14.58C62.88-14.58 55.15-22.31 55.15-31.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M103.51-59.43C105.7-57.91 107.25-55.53 107.69-52.78C107.77-52.29 107.81-41.43 107.81-36.21C107.81-32.9 110.49-30.22 113.8-30.22L116.82-30.22C120.13-30.22 122.81-32.9 122.81-36.21C122.81-40.86 122.81-53.18 122.51-55.12C120.81-65.82 112.42-74.21 101.72-75.9C99.95-76.18 97.86-76.21 93.98-76.21L103.51-59.43Z"/> + </g> + <g id="Bold-M" transform="matrix(1 0 0 1 2267.56 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M28.26-23.12C24.8-23.12 22.01-20.33 22.01-16.87L22.01-16.27C22.01-11.81 22.01-9.59 22.3-7.72C23.93 2.55 31.98 10.6 42.25 12.23C44.12 12.53 46.35 12.53 50.81 12.53L66.18 12.53C69.63 12.53 72.43 9.73 72.43 6.28C72.43 2.82 69.63 0.03 66.18 0.03L50.81 0.03C45.87 0.03 44.86-0.01 44.21-0.12C39.29-0.89 35.43-4.75 34.65-9.67C34.54-10.32 34.51-11.34 34.51-16.27L34.51-16.87C34.51-20.33 31.71-23.12 28.26-23.12Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-3.47L118.81-3.47C118.81 3.15742 113.437 8.53 106.81 8.53L106.81 8.53C100.183 8.53 94.81 3.15742 94.81-3.47L94.81-3.47C94.81-10.0974 100.183-15.47 106.81-15.47L106.81-15.47C113.437-15.47 118.81-10.0974 118.81-3.47Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-88.47C60.43-88.47 57.9-87.09 56.42-84.81L50.87-76.21L50.81-76.21C46.35-76.21 44.12-76.21 42.25-75.92C31.98-74.29 23.93-66.23 22.3-55.97C22.01-54.1 22.01-51.87 22.01-47.41L22.01-46.81C22.01-43.36 24.8-40.56 28.26-40.56C31.71-40.56 34.51-43.36 34.51-46.81L34.51-47.41C34.51-52.35 34.54-53.36 34.65-54.01C35.43-58.93 39.29-62.79 44.21-63.57C44.86-63.67 45.87-63.71 50.81-63.71L94.01-63.71C98.94-63.71 99.96-63.67 100.61-63.57C105.53-62.79 109.39-58.93 110.16-54.01C110.27-53.36 110.31-52.35 110.31-47.41L110.31-46.81C110.31-43.36 113.1-40.56 116.56-40.56C120.01-40.56 122.81-43.36 122.81-46.81L122.81-47.41C122.81-51.87 122.81-54.1 122.51-55.97C120.88-66.23 112.83-74.29 102.56-75.92C100.7-76.21 98.47-76.21 94.01-76.21L93.95-76.21L88.39-84.81C86.92-87.09 84.39-88.47 81.67-88.47L63.14-88.47ZM55.14-31.84C55.14-41.38 62.87-49.11 72.41-49.11C81.94-49.11 89.67-41.38 89.67-31.84C89.67-22.31 81.94-14.58 72.41-14.58C62.87-14.58 55.14-22.31 55.14-31.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M102.29-63.17C106.39-61.87 109.48-58.35 110.16-54.01C110.27-53.36 110.31-42.35 110.31-37.41L110.31-36.81C110.31-33.36 113.1-30.56 116.56-30.56C120.01-30.56 122.81-33.36 122.81-36.81L122.81-37.41C122.81-41.87 122.81-54.1 122.51-55.97C120.88-66.23 112.83-74.29 102.56-75.92C100.7-76.21 98.47-76.21 94.01-76.21L93.99-76.21L102.29-63.17Z"/> + </g> + <g id="Semibold-M" transform="matrix(1 0 0 1 1970.85 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.38-23.8C24.41-23.8 22.01-21.4 22.01-18.43L22.01-15.71C22.01-11.43 22.01-9.3 22.29-7.51C23.85 2.33 31.57 10.05 41.41 11.61C43.2 11.89 45.33 11.89 49.61 11.89L66.77 11.89C69.74 11.89 72.14 9.49 72.14 6.52C72.14 3.55 69.74 1.14 66.77 1.14L49.61 1.14C44.92 1.14 43.83 1.11 43.09 0.99C37.85 0.16 33.74-3.95 32.91-9.19C32.79-9.93 32.76-11.02 32.76-15.71L32.76-18.43C32.76-21.4 30.35-23.8 27.38-23.8Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.11L118.81-4.11C118.81 2.51742 113.437 7.89 106.81 7.89L106.81 7.89C100.183 7.89 94.81 2.51742 94.81-4.11L94.81-4.11C94.81-10.7374 100.183-16.11 106.81-16.11L106.81-16.11C113.437-16.11 118.81-10.7374 118.81-4.11Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-89.1C60.43-89.1 57.9-87.72 56.42-85.44L50.88-76.85L49.61-76.85C45.33-76.85 43.2-76.85 41.41-76.57C31.57-75.01 23.85-67.29 22.29-57.45C22.01-55.66 22.01-53.52 22.01-49.25L22.01-46.57C22.01-43.61 24.41-41.2 27.38-41.2C30.35-41.2 32.76-43.61 32.76-46.57L32.76-49.25C32.76-53.94 32.79-55.03 32.91-55.77C33.74-61.01 37.85-65.12 43.09-65.95C43.83-66.07 44.92-66.1 49.61-66.1L95.21-66.1C99.89-66.1 100.98-66.07 101.72-65.95C106.97-65.12 111.08-61.01 111.91-55.77C112.02-55.03 112.06-53.94 112.06-49.25L112.06-46.57C112.06-43.61 114.46-41.2 117.43-41.2C120.4-41.2 122.81-43.61 122.81-46.57L122.81-49.25C122.81-53.52 122.81-55.66 122.52-57.45C120.97-67.29 113.25-75.01 103.41-76.57C101.62-76.85 99.48-76.85 95.21-76.85L93.94-76.85L88.39-85.44C86.92-87.72 84.39-89.1 81.67-89.1L63.14-89.1ZM55.14-32.49C55.14-42.02 62.87-49.75 72.41-49.75C81.94-49.75 89.67-42.02 89.67-32.49C89.67-22.95 81.94-15.22 72.41-15.22C62.87-15.22 55.14-22.95 55.14-32.49Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M101.01-66.03C101.31-66.01 101.53-65.98 101.72-65.95C106.97-65.12 111.08-61.01 111.91-55.77C112.02-55.03 112.06-43.94 112.06-39.25L112.06-36.57C112.06-33.61 114.46-31.2 117.43-31.2C120.4-31.2 122.81-33.61 122.81-36.57L122.81-39.25C122.81-43.52 122.81-55.66 122.52-57.45C120.97-67.29 113.25-75.01 103.41-76.57C101.62-76.85 99.48-76.85 95.21-76.85L94-76.85L101.01-66.03Z"/> + </g> + <g id="Medium-M" transform="matrix(1 0 0 1 1674.14 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.76-23.8C24.14-23.8 22.01-21.67 22.01-19.05L22.01-13.43C22.01-9.53 22.01-7.58 22.27-5.95C23.69 3.04 30.74 10.08 39.73 11.51C41.36 11.77 43.31 11.77 47.21 11.77L68.11 11.77C70.73 11.77 72.86 9.64 72.86 7.02C72.86 4.39 70.73 2.27 68.11 2.27L47.21 2.27C42.95 2.27 41.92 2.24 41.21 2.12C36.29 1.34 32.43-2.52 31.65-7.44C31.54-8.14 31.51-9.17 31.51-13.43L31.51-19.05C31.51-21.67 29.39-23.8 26.76-23.8Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.23L118.81-4.23C118.81 2.39742 113.437 7.77 106.81 7.77L106.81 7.77C100.183 7.77 94.81 2.39742 94.81-4.23L94.81-4.23C94.81-10.8574 100.183-16.23 106.81-16.23L106.81-16.23C113.437-16.23 118.81-10.8574 118.81-4.23Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.15-89.23C60.43-89.23 57.9-87.86 56.43-85.57L50.88-76.98L47.21-76.98C43.31-76.98 41.36-76.98 39.73-76.72C30.74-75.29 23.69-68.25 22.27-59.26C22.01-57.63 22.01-55.68 22.01-51.78L22.01-45.94C22.01-43.32 24.14-41.19 26.76-41.19C29.39-41.19 31.51-43.32 31.51-45.94L31.51-51.78C31.51-56.04 31.54-57.07 31.65-57.78C32.43-62.7 36.29-66.56 41.21-67.33C41.92-67.45 42.95-67.48 47.21-67.48L97.61-67.48C101.88-67.48 102.9-67.45 103.61-67.33C108.53-66.56 112.39-62.7 113.17-57.78C113.28-57.07 113.31-56.04 113.31-51.78L113.31-45.94C113.31-43.32 115.44-41.19 118.06-41.19C120.69-41.19 122.81-43.32 122.81-45.94L122.81-51.78C122.81-55.68 122.81-57.63 122.55-59.26C121.13-68.25 114.08-75.29 105.1-76.72C103.47-76.98 101.51-76.98 97.61-76.98L93.95-76.98L88.4-85.57C86.93-87.86 84.4-89.23 81.68-89.23L63.15-89.23ZM55.15-32.61C55.15-42.15 62.88-49.88 72.41-49.88C81.95-49.88 89.68-42.15 89.68-32.61C89.68-23.07 81.95-15.35 72.41-15.35C62.88-15.35 55.15-23.07 55.15-32.61Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M100.02-67.47C102.32-67.46 103.06-67.42 103.61-67.33C108.53-66.56 112.39-62.7 113.17-57.78C113.28-57.07 113.31-56.04 113.31-51.78L113.31-35.94C113.31-33.32 115.44-31.19 118.06-31.19C120.69-31.19 122.81-33.32 122.81-35.94L122.81-51.78C122.81-55.68 122.81-57.63 122.55-59.26C121.13-68.25 114.08-75.29 105.1-76.72C103.47-76.98 101.51-76.98 97.61-76.98L93.97-76.98L100.02-67.47Z"/> + </g> + <g id="Regular-M" transform="matrix(1 0 0 1 1377.43 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.01-23.93C23.8-23.93 22.01-22.14 22.01-19.93L22.01-11.05C22.01-7.52 22.01-5.76 22.24-4.28C23.53 3.85 29.91 10.22 38.04 11.51C39.51 11.75 41.28 11.75 44.81 11.75L68.57 11.75C70.78 11.75 72.57 9.95 72.57 7.75C72.57 5.54 70.78 3.75 68.57 3.75L44.81 3.75C40.97 3.75 39.99 3.72 39.29 3.61C34.58 2.86 30.89-0.83 30.15-5.53C30.03-6.23 30.01-7.22 30.01-11.05L30.01-19.93C30.01-22.14 28.22-23.93 26.01-23.93Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.24L118.81-4.24C118.81 2.38742 113.437 7.76 106.81 7.76L106.81 7.76C100.183 7.76 94.81 2.38742 94.81-4.24L94.81-4.24C94.81-10.8674 100.183-16.24 106.81-16.24L106.81-16.24C113.437-16.24 118.81-10.8674 118.81-4.24Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-89.23C60.43-89.23 57.9-87.85 56.42-85.57L50.89-76.99L44.81-76.99C41.28-76.99 39.51-76.99 38.04-76.76C29.91-75.47 23.53-69.09 22.24-60.96C22.01-59.49 22.01-57.72 22.01-54.19L22.01-45.32C22.01-43.11 23.8-41.32 26.01-41.32C28.22-41.32 30.01-43.11 30.01-45.32L30.01-54.19C30.01-58.03 30.03-59.01 30.15-59.71C30.89-64.42 34.58-68.11 39.29-68.86C39.99-68.97 40.97-68.99 44.81-68.99L100.01-68.99C103.85-68.99 104.83-68.97 105.53-68.86C110.24-68.11 113.93-64.42 114.67-59.71C114.79-59.01 114.81-58.03 114.81-54.19L114.81-45.32C114.81-43.11 116.6-41.32 118.81-41.32C121.02-41.32 122.81-43.11 122.81-45.32L122.81-54.19C122.81-57.72 122.81-59.49 122.58-60.96C121.29-69.09 114.91-75.47 106.78-76.76C105.31-76.99 103.54-76.99 100.01-76.99L93.93-76.99L88.4-85.57C86.92-87.85 84.39-89.23 81.68-89.23L63.14-89.23ZM55.41-32.62C55.41-42.01 63.02-49.62 72.41-49.62C81.8-49.62 89.41-42.01 89.41-32.62C89.41-23.24 81.8-15.62 72.41-15.62C63.02-15.62 55.41-23.24 55.41-32.62Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M99.07-68.99L100.01-68.99C103.85-68.99 104.83-68.97 105.53-68.86C110.24-68.11 113.93-64.42 114.67-59.71C114.78-59.01 114.81-58.03 114.81-54.19L114.81-35.32C114.81-33.11 116.6-31.32 118.81-31.32C121.02-31.32 122.81-33.11 122.81-35.32L122.81-54.19C122.81-57.72 122.81-59.49 122.58-60.96C121.29-69.09 114.91-75.47 106.78-76.76C105.31-76.99 103.54-76.99 100.01-76.99L93.98-76.99L99.07-68.99Z"/> + </g> + <g id="Light-M" transform="matrix(1 0 0 1 1080.72 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M25.01-21.7C23.35-21.7 22.01-20.36 22.01-18.7L22.01-7.45C22.01-4.29 22.01-2.72 22.22-1.39C23.37 5.88 29.08 11.59 36.35 12.74C37.67 12.95 39.25 12.95 42.41 12.95L69.28 12.95C70.94 12.95 72.28 11.6 72.28 9.95C72.28 8.29 70.94 6.95 69.28 6.95L42.41 6.95C39.02 6.95 38.03 6.93 37.29 6.81C32.58 6.07 28.89 2.37 28.15-2.33C28.03-3.07 28.01-4.07 28.01-7.45L28.01-18.7C28.01-20.36 26.67-21.7 25.01-21.7Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-3.05L118.81-3.05C118.81 3.57742 113.437 8.95 106.81 8.95L106.81 8.95C100.183 8.95 94.81 3.57742 94.81-3.05L94.81-3.05C94.81-9.67742 100.183-15.05 106.81-15.05L106.81-15.05C113.437-15.05 118.81-9.67742 118.81-3.05Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M62.94-88.04C60.24-88.04 57.73-86.68 56.25-84.43L50.59-75.8L42.41-75.8C39.25-75.8 37.67-75.8 36.35-75.59C29.08-74.44 23.37-68.73 22.22-61.46C22.01-60.13 22.01-58.56 22.01-55.4L22.01-44.14C22.01-42.49 23.35-41.14 25.01-41.14C26.67-41.14 28.01-42.49 28.01-44.14L28.01-55.4C28.01-58.78 28.03-59.78 28.15-60.52C28.89-65.22 32.58-68.92 37.29-69.66C38.03-69.78 39.02-69.8 42.41-69.8L102.41-69.8C105.8-69.8 106.79-69.78 107.53-69.66C112.24-68.92 115.93-65.22 116.68-60.52C116.79-59.78 116.81-58.78 116.81-55.4L116.81-44.14C116.81-42.49 118.15-41.14 119.81-41.14C121.47-41.14 122.81-42.49 122.81-44.14L122.81-55.4C122.81-58.56 122.81-60.13 122.6-61.46C121.45-68.73 115.74-74.44 108.47-75.59C107.15-75.8 105.57-75.8 102.41-75.8L94.35-75.8C94.22-75.97 94.09-76.15 93.97-76.33L88.66-84.43C87.18-86.68 84.67-88.04 81.97-88.04L62.94-88.04ZM55.15-31.42C55.15-40.96 62.88-48.69 72.41-48.69C81.95-48.69 89.68-40.96 89.68-31.42C89.68-21.89 81.95-14.16 72.41-14.16C62.88-14.16 55.15-21.89 55.15-31.42Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M98.18-69.8L102.41-69.8C105.8-69.8 106.79-69.78 107.53-69.66C112.24-68.92 115.93-65.22 116.68-60.52C116.79-59.78 116.81-58.78 116.81-55.4L116.81-34.14C116.81-32.49 118.15-31.14 119.81-31.14C121.47-31.14 122.81-32.49 122.81-34.14L122.81-55.4C122.81-58.56 122.81-60.13 122.6-61.46C121.45-68.73 115.74-74.44 108.47-75.59C107.15-75.8 105.57-75.8 102.41-75.8L94.37-75.8L98.18-69.8Z"/> + </g> + <g id="Thin-M" transform="matrix(1 0 0 1 784.007 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.01-21.77C22.906-21.77 22.01-20.87 22.01-19.77L22.01-6.82C22.01-3.84 22.01-2.36 22.207-1.11C23.292 5.73 28.661 11.1 35.508 12.19C36.751 12.38 38.238 12.38 41.21 12.38L70.989 12.38C72.094 12.38 72.989 11.49 72.989 10.38C72.989 9.28 72.094 8.38 70.989 8.38L41.21 8.38C38.085 8.38 36.988 8.37 36.133 8.23C30.999 7.42 26.971 3.39 26.158-1.74C26.023-2.59 26.01-3.69 26.01-6.82L26.01-19.77C26.01-20.87 25.115-21.77 24.01-21.77Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M117.989-5L117.989-5C117.989 1.62742 112.616 7 105.989 7L105.989 7C99.3616 7 93.989 1.62742 93.989-5L93.989-5C93.989-11.6274 99.3616-17 105.989-17L105.989-17C112.616-17 117.989-11.6274 117.989-5Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M62.937-88.12C60.241-88.12 57.726-86.76 56.247-84.5L50.559-75.83L50.316-75.36L41.21-75.36C38.238-75.36 36.751-75.36 35.508-75.16C28.661-74.08 23.292-68.71 22.207-61.86C22.01-60.62 22.01-59.13 22.01-56.16L22.01-43.21C22.01-42.11 22.906-41.21 24.01-41.21C25.115-41.21 26.01-42.11 26.01-43.21L26.01-56.16C26.01-59.29 26.023-60.38 26.158-61.24C26.971-66.37 30.999-70.4 36.133-71.21C36.988-71.35 38.085-71.36 41.21-71.36L103.61-71.36C106.736-71.36 107.833-71.35 108.688-71.21C113.822-70.4 117.849-66.37 118.663-61.24C118.798-60.38 118.81-59.29 118.81-56.16L118.81-43.21C118.81-42.11 119.706-41.21 120.81-41.21C121.915-41.21 122.81-42.11 122.81-43.21L122.81-56.16C122.81-59.13 122.81-60.62 122.614-61.86C121.529-68.71 116.16-74.08 109.313-75.16C108.07-75.36 106.583-75.36 103.61-75.36L94.79-75.36C94.487-75.69 94.213-76.04 93.968-76.41L88.659-84.5C87.18-86.76 84.666-88.12 81.97-88.12L62.937-88.12ZM55.145-31.49C55.145-41.02 62.875-48.75 72.41-48.75C81.945-48.75 89.675-41.02 89.675-31.49C89.675-21.95 81.945-14.22 72.41-14.22C62.875-14.22 55.145-21.95 55.145-31.49Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M97.335-71.36L103.611-71.36C106.736-71.36 107.833-71.35 108.688-71.21C113.823-70.4 117.85-66.37 118.663-61.24C118.798-60.38 118.811-59.29 118.811-56.16L118.811-33.21C118.811-32.11 119.706-31.21 120.811-31.21C121.915-31.21 122.811-32.11 122.811-33.21L122.811-56.16C122.811-59.13 122.811-60.62 122.614-61.86C121.529-68.71 116.16-74.08 109.314-75.16C108.07-75.36 106.583-75.36 103.611-75.36L94.79-75.36L97.335-71.36Z"/> + </g> + <g id="Ultralight-M" transform="matrix(1 0 0 1 487.296 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.135-21.78C22.513-21.78 22.01-21.28 22.01-20.66L22.01-6.13C22.01-3.34 22.01-1.95 22.194-0.78C23.211 5.63 28.245 10.67 34.663 11.69C35.829 11.87 37.223 11.87 40.01 11.87L71.573 11.87C72.194 11.87 72.698 11.37 72.698 10.74C72.698 10.12 72.194 9.62 71.573 9.62L40.01 9.62C37.137 9.62 35.962 9.61 35.015 9.46C29.559 8.6 25.281 4.32 24.416-1.14C24.267-2.08 24.26-3.26 24.26-6.13L24.26-20.66C24.26-21.28 23.756-21.78 23.135-21.78Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M117.698-4.99L117.698-4.99C117.698 1.63742 112.325 7.01 105.698 7.01L105.698 7.01C99.0706 7.01 93.698 1.63742 93.698-4.99L93.698-4.99C93.698-11.6174 99.0706-16.99 105.698-16.99L105.698-16.99C112.325-16.99 117.698-11.6174 117.698-4.99Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M62.935-87.12C60.239-87.12 57.724-85.76 56.245-83.5L50.58-74.87L40.01-74.87C37.223-74.87 35.829-74.87 34.663-74.68C28.245-73.67 23.211-68.63 22.194-62.21C22.01-61.05 22.01-59.65 22.01-56.87L22.01-42.35C22.01-41.73 22.513-41.23 23.135-41.23C23.756-41.23 24.26-41.73 24.26-42.35L24.26-56.87C24.26-59.74 24.267-60.91 24.416-61.86C25.281-67.32 29.559-71.6 35.015-72.46C35.962-72.61 37.137-72.62 40.01-72.62L104.81-72.62C107.683-72.62 108.857-72.61 109.804-72.46C115.26-71.6 119.538-67.32 120.403-61.86C120.553-60.91 120.56-59.74 120.56-56.87L120.56-42.35C120.56-41.73 121.063-41.23 121.685-41.23C122.306-41.23 122.81-41.73 122.81-42.35L122.81-56.87C122.81-59.65 122.81-61.05 122.625-62.21C121.608-68.63 116.574-73.67 110.156-74.68C108.99-74.87 107.597-74.87 104.81-74.87L94.355-74.87C94.218-75.04 94.089-75.22 93.966-75.41L88.657-83.5C87.179-85.76 84.664-87.12 81.968-87.12L62.935-87.12ZM55.144-31.5C55.144-41.04 62.874-48.77 72.409-48.77C81.944-48.77 89.674-41.04 89.674-31.5C89.674-21.97 81.944-14.24 72.409-14.24C62.874-14.24 55.144-21.97 55.144-31.5Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M95.864-72.62L104.81-72.62C107.683-72.62 108.857-72.61 109.804-72.46C115.26-71.6 119.538-67.32 120.403-61.86C120.553-60.91 120.56-59.74 120.56-56.87L120.56-32.35C120.56-31.73 121.063-31.23 121.685-31.23C122.306-31.23 122.81-31.73 122.81-32.35L122.81-56.87C122.81-59.65 122.81-61.05 122.625-62.21C121.608-68.63 116.574-73.67 110.156-74.68C108.99-74.87 107.597-74.87 104.81-74.87L94.432-74.87L95.864-72.62Z"/> + </g> + <g id="Black-S" transform="matrix(1 0 0 1 2868.71 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M29.01-27.484C25.14-27.484 22.01-24.35 22.01-20.484L22.01-18.896C22.01-7.85 30.96 1.104 42.01 1.104L58.27 1.104C62.14 1.104 65.27-2.03 65.27-5.896C65.27-9.762 62.14-12.896 58.27-12.896L42.01-12.896C38.7-12.896 36.01-15.582 36.01-18.896L36.01-20.484C36.01-24.35 32.88-27.484 29.01-27.484Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-12.398L104.36-12.398C104.36-6.59901 99.659-1.898 93.86-1.898L93.86-1.898C88.061-1.898 83.36-6.59901 83.36-12.398L83.36-12.398C83.36-18.197 88.061-22.898 93.86-22.898L93.86-22.898C99.659-22.898 104.36-18.197 104.36-12.398Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.96-81.766C52.53-81.766 50.23-80.663 48.71-78.768L42.12-70.539L42.01-70.539C30.96-70.539 22.01-61.585 22.01-50.539L22.01-49.919C22.01-46.053 25.14-42.919 29.01-42.919C32.88-42.919 36.01-46.053 36.01-49.919L36.01-50.539C36.01-53.853 38.7-56.539 42.01-56.539L87.36-56.539C90.67-56.539 93.36-53.853 93.36-50.539L93.36-49.919C93.36-46.053 96.49-42.919 100.36-42.919C104.23-42.919 107.36-46.053 107.36-49.919L107.36-50.539C107.36-61.585 98.41-70.539 87.36-70.539L87.25-70.539L80.66-78.768C79.14-80.663 76.84-81.766 74.41-81.766L54.96-81.766ZM51.22-34.722C51.22-42.159 57.25-48.188 64.68-48.188C72.12-48.188 78.15-42.159 78.15-34.722C78.15-27.286 72.12-21.257 64.68-21.257C57.25-21.257 51.22-27.286 51.22-34.722Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M92.69-53.297C93.12-52.471 93.36-51.532 93.36-50.537L93.36-38.917C93.36-35.051 96.49-31.917 100.36-31.917C104.23-31.917 107.36-35.051 107.36-38.917L107.36-50.537C107.36-61.583 98.41-70.537 87.36-70.537L87.25-70.537L87.18-70.625L92.69-53.297Z"/> + </g> + <g id="Heavy-S" transform="matrix(1 0 0 1 2572 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M28.26-26.477C24.81-26.477 22.01-23.678 22.01-20.227L22.01-17.464C22.01-6.97 30.51 1.536 41.01 1.536L58.73 1.536C62.18 1.536 64.98-1.262 64.98-4.714C64.98-8.165 62.18-10.964 58.73-10.964L41.01-10.964C37.42-10.964 34.51-13.874 34.51-17.464L34.51-20.227C34.51-23.678 31.71-26.477 28.26-26.477Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-11.961L104.36-11.961C104.36-6.16201 99.659-1.461 93.86-1.461L93.86-1.461C88.061-1.461 83.36-6.16201 83.36-11.961L83.36-11.961C83.36-17.76 88.061-22.461 93.86-22.461L93.86-22.461C99.659-22.461 104.36-17.76 104.36-11.961Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.95-80.328C52.53-80.328 50.23-79.225 48.71-77.33L42.92-70.102L41.01-70.102C30.51-70.102 22.01-61.595 22.01-51.102L22.01-48.156C22.01-44.704 24.81-41.906 28.26-41.906C31.71-41.906 34.51-44.704 34.51-48.156L34.51-51.102C34.51-54.691 37.42-57.602 41.01-57.602L88.36-57.602C91.95-57.602 94.86-54.691 94.86-51.102L94.86-48.156C94.86-44.704 97.66-41.906 101.11-41.906C104.56-41.906 107.36-44.704 107.36-48.156L107.36-51.102C107.36-61.595 98.85-70.102 88.36-70.102L86.45-70.102L80.66-77.33C79.14-79.225 76.84-80.328 74.41-80.328L54.95-80.328ZM51.22-34.285C51.22-41.722 57.25-47.75 64.68-47.75C72.12-47.75 78.15-41.722 78.15-34.285C78.15-26.848 72.12-20.82 64.68-20.82C57.25-20.82 51.22-26.848 51.22-34.285Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M93.32-55.291C94.28-54.158 94.86-52.694 94.86-51.094L94.86-38.148C94.86-34.697 97.66-31.898 101.11-31.898C104.56-31.898 107.36-34.697 107.36-38.148L107.36-51.094C107.36-61.587 98.85-70.094 88.36-70.094L86.45-70.094L86.39-70.164L93.32-55.291Z"/> + </g> + <g id="Bold-S" transform="matrix(1 0 0 1 2275.29 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.26-26.477C24.36-26.477 22.01-24.126 22.01-21.227L22.01-16.432C22.01-6.491 30.07 1.568 40.01 1.568L59.45 1.568C62.35 1.568 64.7-0.783 64.7-3.682C64.7-6.582 62.35-8.932 59.45-8.932L40.01-8.932C35.87-8.932 32.51-12.29 32.51-16.432L32.51-21.227C32.51-24.126 30.16-26.477 27.26-26.477Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-11.93L104.36-11.93C104.36-6.13101 99.659-1.43 93.86-1.43L93.86-1.43C88.061-1.43 83.36-6.13101 83.36-11.93L83.36-11.93C83.36-17.729 88.061-22.43 93.86-22.43L93.86-22.43C99.659-22.43 104.36-17.729 104.36-11.93Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.96-80.305C52.53-80.305 50.23-79.202 48.71-77.307L42.91-70.07L40.01-70.07C30.07-70.07 22.01-62.011 22.01-52.07L22.01-47.156C22.01-44.257 24.36-41.906 27.26-41.906C30.16-41.906 32.51-44.257 32.51-47.156L32.51-52.07C32.51-56.212 35.87-59.57 40.01-59.57L89.36-59.57C93.5-59.57 96.86-56.212 96.86-52.07L96.86-47.156C96.86-44.257 99.21-41.906 102.11-41.906C105.01-41.906 107.36-44.257 107.36-47.156L107.36-52.07C107.36-62.011 99.3-70.07 89.36-70.07L86.45-70.07L80.66-77.307C79.14-79.202 76.84-80.305 74.41-80.305L54.96-80.305ZM51.22-34.254C51.22-41.69 57.25-47.719 64.68-47.719C72.12-47.719 78.15-41.69 78.15-34.254C78.15-26.817 72.12-20.789 64.68-20.789C57.25-20.789 51.22-26.817 51.22-34.254Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M95-57.013C96.16-55.693 96.86-53.964 96.86-52.07L96.86-38.156C96.86-35.257 99.21-32.906 102.11-32.906C105.01-32.906 107.36-35.257 107.36-38.156L107.36-52.07C107.36-62.011 99.3-70.07 89.36-70.07L86.5-70.07L95-57.013Z"/> + </g> + <g id="Semibold-S" transform="matrix(1 0 0 1 1978.58 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.63-24.562C24.08-24.562 22.01-22.492 22.01-19.938L22.01-13.46C22.01-4.071 29.62 3.54 39.01 3.54L60.77 3.54C63.32 3.54 65.39 1.47 65.39-1.085C65.39-3.639 63.32-5.71 60.77-5.71L39.01-5.71C34.73-5.71 31.26-9.179 31.26-13.46L31.26-19.938C31.26-22.492 29.19-24.562 26.63-24.562Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.961L104.36-9.961C104.36-4.16201 99.659 0.539 93.86 0.539L93.86 0.539C88.061 0.539 83.36-4.16201 83.36-9.961L83.36-9.961C83.36-15.76 88.061-20.461 93.86-20.461L93.86-20.461C99.659-20.461 104.36-15.76 104.36-9.961Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.95-78.336C52.52-78.336 50.23-77.233 48.71-75.338L42.91-68.102L39.01-68.102C29.62-68.102 22.01-60.49 22.01-51.102L22.01-44.621C22.01-42.067 24.08-39.996 26.63-39.996C29.19-39.996 31.26-42.067 31.26-44.621L31.26-51.102C31.26-55.382 34.73-58.852 39.01-58.852L90.36-58.852C94.64-58.852 98.11-55.382 98.11-51.102L98.11-44.621C98.11-42.067 100.18-39.996 102.73-39.996C105.29-39.996 107.36-42.067 107.36-44.621L107.36-51.102C107.36-60.49 99.74-68.102 90.36-68.102L86.45-68.102L80.65-75.338C79.13-77.233 76.84-78.336 74.41-78.336L54.95-78.336ZM51.22-32.285C51.22-39.722 57.25-45.75 64.68-45.75C72.12-45.75 78.15-39.722 78.15-32.285C78.15-24.848 72.12-18.82 64.68-18.82C57.25-18.82 51.22-24.848 51.22-32.285Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M94.72-57.507C96.76-56.112 98.11-53.763 98.11-51.102L98.11-36.621C98.11-34.067 100.18-31.996 102.73-31.996C105.28-31.996 107.36-34.067 107.36-36.621L107.36-51.102C107.36-60.49 99.74-68.102 90.36-68.102L86.49-68.102L94.72-57.507Z"/> + </g> + <g id="Medium-S" transform="matrix(1 0 0 1 1681.87 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.13-24.484C23.86-24.484 22.01-22.638 22.01-20.359L22.01-12.518C22.01-3.682 29.17 3.482 38.01 3.482L60.99 3.482C63.27 3.482 65.12 1.635 65.12-0.643C65.12-2.921 63.27-4.768 60.99-4.768L38.01-4.768C33.73-4.768 30.26-8.238 30.26-12.518L30.26-20.359C30.26-22.638 28.41-24.484 26.13-24.484Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-10.016L104.36-10.016C104.36-4.21701 99.659 0.484 93.86 0.484L93.86 0.484C88.061 0.484 83.36-4.21701 83.36-10.016L83.36-10.016C83.36-15.815 88.061-20.516 93.86-20.516L93.86-20.516C99.659-20.516 104.36-15.815 104.36-10.016Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M55.34-79.383C52.91-79.383 50.62-78.28 49.1-76.385L42.5-68.156L38.01-68.156C29.17-68.156 22.01-60.993 22.01-52.156L22.01-44.039C22.01-41.761 23.86-39.914 26.13-39.914C28.41-39.914 30.26-41.761 30.26-44.039L30.26-52.156C30.26-56.436 33.73-59.906 38.01-59.906L91.36-59.906C95.64-59.906 99.11-56.436 99.11-52.156L99.11-44.039C99.11-41.761 100.96-39.914 103.23-39.914C105.51-39.914 107.36-41.761 107.36-44.039L107.36-52.156C107.36-60.993 100.2-68.156 91.36-68.156L87.63-68.156L81.04-76.385C79.52-78.28 77.23-79.383 74.8-79.383L55.34-79.383ZM51.22-32.332C51.22-39.768 57.25-45.797 64.68-45.797C72.12-45.797 78.15-39.768 78.15-32.332C78.15-24.895 72.12-18.867 64.68-18.867C57.25-18.867 51.22-24.895 51.22-32.332Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M94.64-59.179C97.28-57.944 99.11-55.264 99.11-52.156L99.11-36.039C99.11-33.761 100.96-31.914 103.23-31.914C105.51-31.914 107.36-33.761 107.36-36.039L107.36-52.156C107.36-60.993 100.2-68.156 91.36-68.156L87.67-68.156L94.64-59.179Z"/> + </g> + <g id="Regular-S" transform="matrix(1 0 0 1 1385.15 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M29.16-20.878L29.16-11.354C29.16-7.019 32.68-3.504 37.01-3.504L61.26-3.504C63.24-3.504 64.84-1.904 64.84 0.071C64.84 2.045 63.24 3.646 61.26 3.646L37.01 3.646C28.73 3.646 22.01-3.07 22.01-11.354L22.01-20.878C22.01-22.853 23.61-24.453 25.59-24.453C27.56-24.453 29.16-22.853 29.16-20.878Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.852L104.36-9.852C104.36-4.05301 99.659 0.648 93.86 0.648L93.86 0.648C88.061 0.648 83.36-4.05301 83.36-9.852L83.36-9.852C83.36-15.651 88.061-20.352 93.86-20.352L93.86-20.352C99.659-20.352 104.36-15.651 104.36-9.852Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.71-76.229C50.23-78.124 52.53-79.227 54.96-79.227L74.42-79.227C76.84-79.227 79.14-78.124 80.66-76.229L87.26-67.992L92.36-67.992C100.65-67.992 107.36-61.276 107.36-52.992L107.36-43.458C107.36-41.483 105.76-39.883 103.79-39.883C101.81-39.883 100.21-41.483 100.21-43.458L100.21-52.992C100.21-57.328 96.7-60.842 92.36-60.842L37.01-60.842C32.68-60.842 29.16-57.328 29.16-52.992L29.16-43.458C29.16-41.483 27.56-39.883 25.59-39.883C23.61-39.883 22.01-41.483 22.01-43.458L22.01-52.992C22.01-61.276 28.73-67.992 37.01-67.992L42.12-67.992L48.71-76.229ZM64.69-45.641C57.25-45.641 51.22-39.612 51.22-32.176C51.22-24.739 57.25-18.711 64.69-18.711C72.12-18.711 78.15-24.739 78.15-32.176C78.15-39.612 72.12-45.641 64.69-45.641Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M92.8-60.829C96.93-60.601 100.21-57.179 100.21-52.991L100.21-35.457C100.21-33.483 101.81-31.882 103.79-31.882C105.76-31.882 107.36-33.483 107.36-35.457L107.36-52.991C107.36-61.276 100.65-67.991 92.36-67.991L87.26-67.991L86.66-68.742L92.8-60.829Z"/> + </g> + <g id="Light-S" transform="matrix(1 0 0 1 1088.44 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.76-24.562C23.24-24.562 22.01-23.331 22.01-21.812L22.01-10.464C22.01-2.732 28.28 3.536 36.01 3.536L61.8 3.536C63.32 3.536 64.55 2.305 64.55 0.786C64.55-0.732 63.32-1.964 61.8-1.964L36.01-1.964C31.32-1.964 27.51-5.769 27.51-10.464L27.51-21.812C27.51-23.331 26.28-24.562 24.76-24.562Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.961L104.36-9.961C104.36-4.16201 99.659 0.539 93.86 0.539L93.86 0.539C88.061 0.539 83.36-4.16201 83.36-9.961L83.36-9.961C83.36-15.76 88.061-20.461 93.86-20.461L93.86-20.461C99.659-20.461 104.36-15.76 104.36-9.961Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.72-75.33C50.23-77.225 52.53-78.328 54.96-78.328L74.42-78.328C76.85-78.328 79.14-77.225 80.66-75.33L86.45-68.102L93.36-68.102C101.09-68.102 107.36-61.834 107.36-54.102L107.36-42.742C107.36-41.223 106.13-39.992 104.61-39.992C103.09-39.992 101.86-41.223 101.86-42.742L101.86-54.102C101.86-58.796 98.06-62.602 93.36-62.602L36.01-62.602C31.32-62.602 27.51-58.796 27.51-54.102L27.51-42.742C27.51-41.223 26.28-39.992 24.76-39.992C23.24-39.992 22.01-41.223 22.01-42.742L22.01-54.102C22.01-61.834 28.28-68.102 36.01-68.102L42.92-68.102L48.72-75.33ZM64.69-45.75C57.25-45.75 51.22-39.722 51.22-32.285C51.22-24.848 57.25-18.82 64.69-18.82C72.12-18.82 78.15-24.848 78.15-32.285C78.15-39.722 72.12-45.75 64.69-45.75Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M90.78-62.602L93.36-62.602C98.06-62.602 101.86-58.796 101.86-54.102L101.86-34.742C101.86-33.223 103.09-31.992 104.61-31.992C106.13-31.992 107.36-33.223 107.36-34.742L107.36-54.102C107.36-61.834 101.09-68.102 93.36-68.102L86.51-68.102L90.78-62.602Z"/> + </g> + <g id="Thin-S" transform="matrix(1 0 0 1 791.732 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.635-24.484C22.738-24.484 22.01-23.757 22.01-22.859L22.01-9.385C22.01-2.206 27.83 3.615 35.01 3.615L63.624 3.615C64.522 3.615 65.249 2.887 65.249 1.99C65.249 1.092 64.522 0.365 63.624 0.365L35.01 0.365C29.625 0.365 25.26-4.001 25.26-9.385L25.26-22.859C25.26-23.757 24.533-24.484 23.635-24.484Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.883L104.36-9.883C104.36-4.08401 99.659 0.617 93.86 0.617L93.86 0.617C88.061 0.617 83.36-4.08401 83.36-9.883L83.36-9.883C83.36-15.682 88.061-20.383 93.86-20.383L93.86-20.383C99.659-20.383 104.36-15.682 104.36-9.883Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.713-75.26C50.231-77.155 52.528-78.258 54.956-78.258L74.414-78.258C76.842-78.258 79.139-77.155 80.657-75.26L86.455-68.023L94.36-68.023C101.54-68.023 107.36-62.203 107.36-55.023L107.36-41.539C107.36-40.642 106.633-39.914 105.735-39.914C104.838-39.914 104.11-40.642 104.11-41.539L104.11-55.023C104.11-60.408 99.745-64.773 94.36-64.773L35.01-64.773C29.625-64.773 25.26-60.408 25.26-55.023L25.26-41.539C25.26-40.642 24.533-39.914 23.635-39.914C22.738-39.914 22.01-40.642 22.01-41.539L22.01-55.023C22.01-62.203 27.83-68.023 35.01-68.023L42.914-68.023L48.713-75.26ZM64.685-45.672C57.249-45.672 51.22-39.643 51.22-32.207C51.22-24.77 57.249-18.742 64.685-18.742C72.122-18.742 78.15-24.77 78.15-32.207C78.15-39.643 72.122-45.672 64.685-45.672Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M89.016-64.773L94.36-64.773C99.745-64.773 104.11-60.408 104.11-55.023L104.11-33.539C104.11-32.642 104.838-31.914 105.735-31.914C106.633-31.914 107.36-32.642 107.36-33.539L107.36-55.023C107.36-62.203 101.54-68.023 94.36-68.023L86.492-68.023L89.016-64.773Z"/> + </g> + <g id="Ultralight-S" transform="matrix(1 0 0 1 495.021 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.01-24.117C22.458-24.117 22.01-23.669 22.01-23.117L22.01-7.852C22.01-1.224 27.383 4.148 34.01 4.148L63.967 4.148C64.519 4.148 64.967 3.701 64.967 3.148C64.967 2.596 64.519 2.148 63.967 2.148L34.01 2.148C28.487 2.148 24.01-2.329 24.01-7.852L24.01-23.117C24.01-23.669 23.562-24.117 23.01-24.117Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.352L104.36-9.352C104.36-3.55301 99.659 1.148 93.86 1.148L93.86 1.148C88.061 1.148 83.36-3.55301 83.36-9.352L83.36-9.352C83.36-15.151 88.061-19.852 93.86-19.852L93.86-19.852C99.659-19.852 104.36-15.151 104.36-9.352Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.713-74.237C50.231-76.132 52.528-77.234 54.956-77.234L74.414-77.234C76.842-77.234 79.139-76.132 80.657-74.237L85.26-68.492L95.36-68.492C101.987-68.492 107.36-63.12 107.36-56.492L107.36-41.227C107.36-40.674 106.912-40.227 106.36-40.227C105.808-40.227 105.36-40.674 105.36-41.227L105.36-56.492C105.36-62.015 100.883-66.492 95.36-66.492L34.01-66.492C28.487-66.492 24.01-62.015 24.01-56.492L24.01-41.227C24.01-40.674 23.562-40.227 23.01-40.227C22.458-40.227 22.01-40.674 22.01-41.227L22.01-56.492C22.01-63.12 27.383-68.492 34.01-68.492L44.11-68.492L48.713-74.237ZM64.685-45.641C57.248-45.641 51.22-39.612 51.22-32.176C51.22-24.739 57.248-18.711 64.685-18.711C72.122-18.711 78.15-24.739 78.15-32.176C78.15-39.612 72.122-45.641 64.685-45.641Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M86.931-66.492L95.36-66.492C100.883-66.492 105.36-62.015 105.36-56.492L105.36-33.227C105.36-32.674 105.808-32.227 106.36-32.227C106.912-32.227 107.36-32.674 107.36-33.227L107.36-56.492C107.36-63.12 101.987-68.492 95.36-68.492L85.378-68.492L86.931-66.492Z"/> + </g> + </g> </svg>
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn index 1a824d8..c69892e 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/cells/BUILD.gn
@@ -26,6 +26,7 @@ "content_suggestions_tile_view.mm", "magic_stack_module_container.h", "magic_stack_module_container.mm", + "magic_stack_module_container_delegate.h", "multi_row_container_view.h", "multi_row_container_view.mm", "query_suggestion_view.h",
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.h b/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.h index 52940017..d8dd36df 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.h +++ b/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.h
@@ -8,13 +8,16 @@ #import <UIKit/UIKit.h> enum class ContentSuggestionsModuleType; +@protocol MagicStackModuleContainerDelegate; // Container View for a module in the Magic Stack. @interface MagicStackModuleContainer : UIView // Initialize and configure with `contentView` for `type`. - (instancetype)initWithContentView:(UIView*)contentView - type:(ContentSuggestionsModuleType)type; + type:(ContentSuggestionsModuleType)type + delegate: + (id<MagicStackModuleContainerDelegate>)delegate; - (instancetype)initWithFrame:(CGRect)frame NS_UNAVAILABLE; - (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.mm b/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.mm index 87d0544..85929fb1 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.h" #import "base/notreached.h" +#import "ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_constants.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" #import "ios/chrome/common/ui/colors/semantic_color_names.h" @@ -48,6 +49,7 @@ @implementation MagicStackModuleContainer { NSLayoutConstraint* _contentViewWidthAnchor; + id<MagicStackModuleContainerDelegate> _delegate; } - (instancetype)initWithType:(ContentSuggestionsModuleType)type { @@ -58,11 +60,13 @@ } - (instancetype)initWithContentView:(UIView*)contentView - type:(ContentSuggestionsModuleType)type { + type:(ContentSuggestionsModuleType)type + delegate: + (id<MagicStackModuleContainerDelegate>)delegate { self = [super initWithFrame:CGRectZero]; if (self) { _type = type; - + _delegate = delegate; self.layer.cornerRadius = kCornerRadius; self.backgroundColor = [UIColor colorNamed:kBackgroundColor]; @@ -136,12 +140,19 @@ } - (CGSize)intrinsicContentSize { - // When the Most Visited Tiles module is not in the Magic Stack in a wider - // screen, the module is wider to match the wider Magic Stack ScrollView. - if (_type == ContentSuggestionsModuleType::kMostVisited && - !ShouldPutMostVisitedSitesInMagicStack() && + // When the Most Visited Tiles module is not in the Magic Stack or if a module + // is the only module in the Magic Stack in a wider screen, the module should + // be wider to match the wider Magic Stack ScrollView. + BOOL MVTModuleShouldUseWideWidth = + (_type == ContentSuggestionsModuleType::kMostVisited && + !ShouldPutMostVisitedSitesInMagicStack() && + self.traitCollection.horizontalSizeClass == + UIUserInterfaceSizeClassRegular); + BOOL moduleShouldUseWideWidth = self.traitCollection.horizontalSizeClass == - UIUserInterfaceSizeClassRegular) { + UIUserInterfaceSizeClassRegular && + [_delegate doesMagicStackShowOnlyOneModule:_type]; + if (MVTModuleShouldUseWideWidth || moduleShouldUseWideWidth) { return CGSizeMake(kMagicStackWideWidth, self.bounds.size.height); } return CGSizeMake(
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container_delegate.h b/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container_delegate.h new file mode 100644 index 0000000..8654696 --- /dev/null +++ b/ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container_delegate.h
@@ -0,0 +1,19 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_MAGIC_STACK_MODULE_CONTAINER_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_MAGIC_STACK_MODULE_CONTAINER_DELEGATE_H_ + +enum class ContentSuggestionsModuleType; + +// Protocol asking the receiver for more contextual information about modules. +@protocol MagicStackModuleContainerDelegate + +// YES if the module of `type` is the only module being shown in the Magic +// Stack. +- (BOOL)doesMagicStackShowOnlyOneModule:(ContentSuggestionsModuleType)type; + +@end + +#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CELLS_MAGIC_STACK_MODULE_CONTAINER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 5e4b54a..28fbf7ed 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -61,6 +61,7 @@ #import "ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.h" #import "ios/chrome/browser/ui/menu/browser_action_factory.h" #import "ios/chrome/browser/ui/menu/menu_histograms.h" +#import "ios/chrome/browser/ui/ntp/feed_delegate.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_constants.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_delegate.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" @@ -415,6 +416,10 @@ [_actionSheetCoordinator start]; } +- (void)setUpListViewHeightDidChange { + [self.feedDelegate contentSuggestionsWasUpdated]; +} + #pragma mark - SetUpList Helpers // Shows the Default Browser Promo.
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 43c71df..e203697 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -23,6 +23,7 @@ #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_shortcut_tile_view.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_tile_layout_util.h" #import "ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container.h" +#import "ios/chrome/browser/ui/content_suggestions/cells/magic_stack_module_container_delegate.h" #import "ios/chrome/browser/ui/content_suggestions/cells/multi_row_container_view.h" #import "ios/chrome/browser/ui/content_suggestions/cells/query_suggestion_view.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h" @@ -78,6 +79,7 @@ @interface ContentSuggestionsViewController () < UIGestureRecognizerDelegate, ContentSuggestionsSelectionActions, + MagicStackModuleContainerDelegate, SetUpListItemViewTapDelegate, URLDropDelegate, UIScrollViewDelegate, @@ -407,6 +409,7 @@ } - (void)setMagicStackOrder:(NSArray<NSNumber*>*)order { + CHECK([order count] > 0); _shouldShowMagicStack = YES; _magicStackModuleOrder = order; } @@ -483,7 +486,8 @@ [[MagicStackModuleContainer alloc] initWithContentView:multiRowContainer type:ContentSuggestionsModuleType:: - kCompactedSetUpList]; + kCompactedSetUpList + delegate:self]; [_magicStack insertArrangedSubview:setUpListCompactedModule atIndex:[self indexForMagicStackModule: @@ -492,7 +496,8 @@ } else { MagicStackModuleContainer* setUpListModule = [[MagicStackModuleContainer alloc] initWithContentView:view - type:type]; + type:type + delegate:self]; [_magicStack insertArrangedSubview:setUpListModule atIndex:[self indexForMagicStackModule:type]]; @@ -501,7 +506,8 @@ } } else { - SetUpListView* setUpListView = [[SetUpListView alloc] initWithItems:items]; + SetUpListView* setUpListView = + [[SetUpListView alloc] initWithItems:items rootView:self.view]; setUpListView.delegate = self.setUpListViewDelegate; self.setUpListView = setUpListView; [self.verticalStackView insertArrangedSubview:setUpListView atIndex:index]; @@ -582,7 +588,8 @@ [[SetUpListItemView alloc] initWithData:allSetData]; MagicStackModuleContainer* allSetModule = [[MagicStackModuleContainer alloc] initWithContentView:view - type:ContentSuggestionsModuleType::kSetUpListAllSet]; + type:ContentSuggestionsModuleType::kSetUpListAllSet + delegate:self]; // Determine which module to swap out. [self replaceModuleAtIndex: [self indexForMagicStackModule:[self currentlyShownModule]] @@ -698,8 +705,7 @@ [super traitCollectionDidChange:previousTraitCollection]; if (previousTraitCollection.horizontalSizeClass != self.traitCollection.horizontalSizeClass) { - if (self.traitCollection.horizontalSizeClass == - UIUserInterfaceSizeClassRegular) { + if ([self shouldShowWiderMagicStackLayer]) { _magicStackScrollView.clipsToBounds = YES; _magicStackScrollViewWidthAnchor.constant = kMagicStackWideWidth; } else { @@ -729,6 +735,20 @@ titleStringForModule:[self currentlyShownModule]]; } +#pragma mark - MagicStackModuleContainer + +- (BOOL)doesMagicStackShowOnlyOneModule:(ContentSuggestionsModuleType)type { + // Return NO if Most Visited Module is asking while it is not in the Magic + // Stack. + if (type == ContentSuggestionsModuleType::kMostVisited && + !ShouldPutMostVisitedSitesInMagicStack()) { + return NO; + } + ContentSuggestionsModuleType firstModuleType = (ContentSuggestionsModuleType)[ + [_magicStackModuleOrder objectAtIndex:0] intValue]; + return [_magicStackModuleOrder count] == 1 && firstModuleType == type; +} + #pragma mark - Private - (void)addUIElement:(UIView*)view withCustomBottomSpacing:(CGFloat)spacing { @@ -755,7 +775,8 @@ if (IsMagicStackEnabled()) { self.mostVisitedModuleContainer = [[MagicStackModuleContainer alloc] initWithContentView:self.mostVisitedStackView - type:ContentSuggestionsModuleType::kMostVisited]; + type:ContentSuggestionsModuleType::kMostVisited + delegate:self]; if (ShouldPutMostVisitedSitesInMagicStack()) { // Only add it to the Magic Stack here if it is after the inital // construction of the Magic Stack. @@ -831,9 +852,7 @@ - (void)createMagicStack { _magicStackScrollView = [[UIScrollView alloc] init]; [_magicStackScrollView setShowsHorizontalScrollIndicator:NO]; - _magicStackScrollView.clipsToBounds = - self.traitCollection.horizontalSizeClass == - UIUserInterfaceSizeClassRegular; + _magicStackScrollView.clipsToBounds = [self shouldShowWiderMagicStackLayer]; _magicStackScrollView.delegate = self; _magicStackScrollView.accessibilityIdentifier = kMagicStackScrollViewAccessibilityIdentifier; @@ -857,7 +876,8 @@ case ContentSuggestionsModuleType::kShortcuts: { self.shortcutsModuleContainer = [[MagicStackModuleContainer alloc] initWithContentView:self.shortcutsStackView - type:type]; + type:type + delegate:self]; [_magicStack addArrangedSubview:self.shortcutsModuleContainer]; break; } @@ -871,7 +891,8 @@ MagicStackModuleContainer* setUpListSyncModule = [[MagicStackModuleContainer alloc] initWithContentView:_setUpListSyncItemView - type:type]; + type:type + delegate:self]; [_magicStack addArrangedSubview:setUpListSyncModule]; break; } @@ -879,7 +900,8 @@ MagicStackModuleContainer* setUpListDefaultBrowserModule = [[MagicStackModuleContainer alloc] initWithContentView:_setUpListDefaultBrowserItemView - type:type]; + type:type + delegate:self]; [_magicStack addArrangedSubview:setUpListDefaultBrowserModule]; break; } @@ -887,7 +909,8 @@ MagicStackModuleContainer* setUpListAutofillModule = [[MagicStackModuleContainer alloc] initWithContentView:_setUpListAutofillItemView - type:type]; + type:type + delegate:self]; [_magicStack addArrangedSubview:setUpListAutofillModule]; break; } @@ -899,7 +922,8 @@ [[MagicStackModuleContainer alloc] initWithContentView:multiRowContainer type:ContentSuggestionsModuleType:: - kCompactedSetUpList]; + kCompactedSetUpList + delegate:self]; [_magicStack addArrangedSubview:setUpListCompactedModule]; break; } @@ -915,8 +939,7 @@ moduleWidthForHorizontalTraitCollection:self.traitCollection]; // Magic Stack has a wider width for wider screens so that clipToBounds can be // YES with a peeking module still visible. - if (self.traitCollection.horizontalSizeClass == - UIUserInterfaceSizeClassRegular) { + if ([self shouldShowWiderMagicStackLayer]) { width = kMagicStackWideWidth; } _magicStackScrollViewWidthAnchor = @@ -929,6 +952,12 @@ ]]; } +// YES if the Magic Stack should be using a wider layout. +- (BOOL)shouldShowWiderMagicStackLayer { + return self.traitCollection.horizontalSizeClass == + UIUserInterfaceSizeClassRegular; +} + // Returns the index position `moduleType` should be placed in the Magic Stack. // This should only be used when looking to add a module after the inital Magic // Stack construction.
diff --git a/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.h b/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.h index 821dae2e..f2ff423 100644 --- a/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.h +++ b/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.h
@@ -21,14 +21,19 @@ // Called when the user selects the Set Up List menu. - (void)showSetUpListMenuWithButton:(UIButton*)button; +// Called when the height of the SetUpListView did change. +- (void)setUpListViewHeightDidChange; + @end // A view that displays the Set Up List, a list of tasks a new user may want // to complete to set up the app. @interface SetUpListView : UIView -// Initializes the SetUpListView, with the given items. -- (instancetype)initWithItems:(NSArray<SetUpListItemViewData*>*)items; +// Initializes the SetUpListView, with the given `items`, and the given +// `rootView`. +- (instancetype)initWithItems:(NSArray<SetUpListItemViewData*>*)items + rootView:(UIView*)rootView; // The object that should handle delegate events. @property(nonatomic, weak) id<SetUpListViewDelegate> delegate;
diff --git a/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.mm b/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.mm index f34fd45c..41c90b8 100644 --- a/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.mm +++ b/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view.mm
@@ -70,6 +70,9 @@ // The array of item data given to the initializer. NSArray<SetUpListItemViewData*>* _itemsData; + // The view that needs layout if SetUpListView's height changes. + UIView* _rootView; + // The array of SetUpListItemViews. NSMutableArray<SetUpListItemView*>* _items; @@ -86,11 +89,13 @@ UIButton* _menuButton; } -- (instancetype)initWithItems:(NSArray<SetUpListItemViewData*>*)items { +- (instancetype)initWithItems:(NSArray<SetUpListItemViewData*>*)items + rootView:(UIView*)rootView { self = [super init]; if (self) { CHECK_GT(items.count, 0ul); _itemsData = items; + _rootView = rootView; } return self; } @@ -433,7 +438,12 @@ index++; } _itemsStack.accessibilityElements = _items; + // Layout the newly added (but still hidden) items, so that the animation is + // correct. + [self setNeedsLayout]; + [self layoutIfNeeded]; + __weak __typeof(self) weakSelf = self; __weak __typeof(_expandButton) weakExpandButton = _expandButton; [UIView animateWithDuration:kExpandAnimationDuration.InSecondsF() animations:^{ @@ -444,6 +454,7 @@ // Flip the expand button to point up; weakExpandButton.transform = CGAffineTransformScale( CGAffineTransformIdentity, 1, -1); + [weakSelf heightDidChange]; }]; } @@ -455,6 +466,7 @@ _expandButton.accessibilityLabel = l10n_util::GetNSString(IDS_IOS_SET_UP_LIST_EXPAND); + __weak __typeof(self) weakSelf = self; __weak __typeof(_expandButton) weakExpandButton = _expandButton; [UIView animateWithDuration:kExpandAnimationDuration.InSecondsF() animations:^{ @@ -465,6 +477,7 @@ // Flip the expand button to point down again; weakExpandButton.transform = CGAffineTransformScale(CGAffineTransformIdentity, 1, 1); + [weakSelf heightDidChange]; } completion:^(BOOL finished) { for (SetUpListItemView* item in items) { @@ -473,6 +486,14 @@ }]; } +// Tells the root view to re-layout and tells the delegate that the height +// changed. +- (void)heightDidChange { + [_rootView setNeedsLayout]; + [_rootView layoutIfNeeded]; + [self.delegate setUpListViewHeightDidChange]; +} + #pragma mark Private methods (All Set view) // Returns `YES` if all items are marked complete.
diff --git a/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view_unittest.mm b/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view_unittest.mm index e81d22a..290415a 100644 --- a/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view_unittest.mm +++ b/ios/chrome/browser/ui/content_suggestions/set_up_list/set_up_list_view_unittest.mm
@@ -112,7 +112,8 @@ // expand / collapse button functions as it should. Also verifies that // the items that are expected to be in the list are there at each step. TEST_F(SetUpListViewTest, ExpandCollapse) { - SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData]; + SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData + rootView:nil]; [_superview addSubview:view]; // It should initially display two items. @@ -142,7 +143,9 @@ // Tests that a touch on a SetUpListItemView results in a call to the view\ // delegate. TEST_F(SetUpListViewTest, TouchSetUpListItemView) { - SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData]; + SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData + rootView:nil]; + [_superview addSubview:view]; SetUpListItemView* item_view = @@ -167,7 +170,8 @@ // Tests that a tap on the menu button results in a call to the view delegate. TEST_F(SetUpListViewTest, MenuButton) { - SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData]; + SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData + rootView:nil]; [_superview addSubview:view]; id view_delegate = OCMProtocolMock(@protocol(SetUpListViewDelegate)); @@ -181,7 +185,8 @@ // Tests that a SetUpListItemView can be marked complete. TEST_F(SetUpListViewTest, SetUpListItemViewMarkComplete) { - SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData]; + SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData + rootView:nil]; [_superview addSubview:view]; SetUpListItemView* item_view = @@ -200,7 +205,9 @@ TEST_F(SetUpListViewTest, NoExpandButton) { NSArray<SetUpListItemViewData*>* first_two_items = [_itemsData subarrayWithRange:NSMakeRange(0, 2)]; - SetUpListView* view = [[SetUpListView alloc] initWithItems:first_two_items]; + SetUpListView* view = [[SetUpListView alloc] initWithItems:first_two_items + rootView:nil]; + [_superview addSubview:view]; SetUpListItemView* expand_button = @@ -210,7 +217,8 @@ // Tests that the "All Set" can be shown. TEST_F(SetUpListViewTest, AllSetView) { - SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData]; + SetUpListView* view = [[SetUpListView alloc] initWithItems:_itemsData + rootView:nil]; [_superview addSubview:view]; ExpectSubview(@"kSetUpListAllSetID", false);
diff --git a/ios/chrome/browser/ui/default_promo/default_browser_promo_coordinator.mm b/ios/chrome/browser/ui/default_promo/default_browser_promo_coordinator.mm index 52d7103..a7c5604 100644 --- a/ios/chrome/browser/ui/default_promo/default_browser_promo_coordinator.mm +++ b/ios/chrome/browser/ui/default_promo/default_browser_promo_coordinator.mm
@@ -132,7 +132,7 @@ - (void)confirmationAlertLearnMoreAction { base::RecordAction(base::UserMetricsAction( - "IOS.DefaultBrowserFullscreen.PromoMoreInfoTapped")); + "IOS.DefaultBrowserFullscreenPromo.MoreInfoTapped")); [self recordDefaultBrowserPromoShown]; NSString* message = GetDefaultBrowserLearnMoreText(); self.learnMoreViewController =
diff --git a/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn b/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn index d8c67be5..a47cb3a 100644 --- a/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/keyboard_assist/BUILD.gn
@@ -32,6 +32,7 @@ "//ios/chrome/browser/shared/public/commands", "//ios/chrome/browser/shared/public/features", "//ios/chrome/browser/shared/ui/elements", + "//ios/chrome/browser/shared/ui/symbols", "//ios/chrome/browser/shared/ui/util", "//ios/chrome/browser/ui/lens:lens_availability", "//ios/chrome/browser/ui/lens:lens_entrypoint",
diff --git a/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_views_utils.mm b/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_views_utils.mm index a74f3fe..ee9fe5b 100644 --- a/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_views_utils.mm +++ b/ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_views_utils.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_views_utils.h" #import "ios/chrome/browser/shared/ui/elements/extended_touch_target_button.h" +#import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/ui/omnibox/keyboard_assist/omnibox_assistive_keyboard_delegate.h" #import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" @@ -23,15 +24,17 @@ NSString* const kPasteSearchInputAccessoryViewID = @"kPasteSearchInputAccessoryViewID"; +// Parameters for the appearance of the buttons. +const CGFloat kSymbolButtonSize = 36.0; +const CGFloat kSymbolPointSize = 23.0; const CGFloat kPasteButtonSize = 36.0; +const CGFloat kButtonShadowOpacity = 0.35; +const CGFloat kButtonShadowRadius = 1.0; +const CGFloat kButtonShadowVerticalOffset = 1.0; namespace { void SetUpButtonWithIcon(UIButton* button, NSString* iconName) { - const CGFloat kButtonShadowOpacity = 0.35; - const CGFloat kButtonShadowRadius = 1.0; - const CGFloat kButtonShadowVerticalOffset = 1.0; - [button setTranslatesAutoresizingMaskIntoConstraints:NO]; UIImage* icon = [UIImage imageNamed:iconName]; [button setImage:icon forState:UIControlStateNormal]; @@ -41,6 +44,30 @@ button.layer.shadowRadius = kButtonShadowRadius; } +void SetUpButtonWithSymbol(UIButton* button, NSString* symbolName) { + [button setTranslatesAutoresizingMaskIntoConstraints:NO]; + UIImageSymbolConfiguration* configuration = [UIImageSymbolConfiguration + configurationWithPointSize:kSymbolPointSize + weight:UIImageSymbolWeightSemibold + scale:UIImageSymbolScaleMedium]; + + UIImage* icon = MakeSymbolMulticolor( + CustomSymbolWithConfiguration(symbolName, configuration)); + [button setImage:icon forState:UIControlStateNormal]; + button.backgroundColor = [UIColor whiteColor]; + button.layer.cornerRadius = kSymbolButtonSize / 2; + + button.layer.shadowColor = [UIColor blackColor].CGColor; + button.layer.shadowOffset = CGSizeMake(0, kButtonShadowVerticalOffset); + button.layer.shadowOpacity = kButtonShadowOpacity; + button.layer.shadowRadius = kButtonShadowRadius; + + [NSLayoutConstraint activateConstraints:@[ + [button.widthAnchor constraintEqualToConstant:kSymbolButtonSize], + [button.heightAnchor constraintEqualToConstant:kSymbolButtonSize] + ]]; +} + } // namespace NSArray<UIControl*>* OmniboxAssistiveKeyboardLeadingControls( @@ -66,7 +93,7 @@ [ExtendedTouchTargetButton buttonWithType:UIButtonTypeCustom]; if (useLens) { // Set up the camera button for Lens. - SetUpButtonWithIcon(cameraButton, @"keyboard_accessory_lens"); + SetUpButtonWithSymbol(cameraButton, kCameraLensSymbol); [cameraButton addTarget:delegate action:@selector(keyboardAccessoryLensTapped) forControlEvents:UIControlEventTouchUpInside];
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm index 9874ded..28a6dde 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
@@ -176,6 +176,11 @@ [self.delegate passwordDetailsCoordinatorDidRemove:self]; } +- (void)dismissPasswordDetailsTableViewController { + [self.delegate passwordDetailsCancelButtonWasTapped]; + [self.delegate passwordDetailsCoordinatorDidRemove:self]; +} + - (void)showPasscodeDialogForReason:(PasscodeDialogReason)reason { NSString* title = l10n_util::GetNSString(IDS_IOS_SETTINGS_SET_UP_SCREENLOCK_TITLE); @@ -354,7 +359,7 @@ self.viewController); // For password details opened outside of the settings context. if (_context == DetailsContext::kOutsideSettings) { - [self passwordDetailsTableViewControllerWasDismissed]; + [self dismissPasswordDetailsTableViewController]; } else { // For password details opened from the Password Manager in the settings. [self.baseNavigationController popViewControllerAnimated:YES];
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h index 1b0aacde..3f2ae9818 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h
@@ -14,6 +14,12 @@ - (void)passwordDetailsCoordinatorDidRemove: (PasswordDetailsCoordinator*)coordinator; +// Called when the user tapped on the cancel button. This is never called when +// the view is presented in the Settings context, because in these cases there +// is a Back button instead of Cancel. +@optional +- (void)passwordDetailsCancelButtonWasTapped; + @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_PASSWORD_PASSWORD_DETAILS_PASSWORD_DETAILS_COORDINATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h b/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h index a2caf8f2..d775906 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_handler.h
@@ -17,9 +17,18 @@ // Presenter which handles commands from `PasswordDetailsViewController`. @protocol PasswordDetailsHandler -// Called when the view controller was dismissed. +// Called when the view controller was dismissed by tapping on the Back button +// of the view controller. This is called by the -viewDidDisappear method of +// the Password Details View Controller. - (void)passwordDetailsTableViewControllerWasDismissed; +// Called to dismiss the view controller. Only call this method when the view +// controller is displayed outside the Settings context and the user taps on the +// cancel button. In the case of the Settings context, it is handled by the +// -passwordDetailsTableViewControllerWasDismissed method above that is called +// in -viewDidDisappear. +- (void)dismissPasswordDetailsTableViewController; + // Shows a dialog offering the user to set a passcode for `reason`. - (void)showPasscodeDialogForReason:(PasscodeDialogReason)reason;
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm index 1b10091..db484b0 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -1558,7 +1558,7 @@ - (void)dismissView { [self.view endEditing:YES]; - [self.handler passwordDetailsTableViewControllerWasDismissed]; + [self.handler dismissPasswordDetailsTableViewController]; } #pragma mark - UIResponder
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm index e7b8624..b0486a7 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller_unittest.mm
@@ -74,6 +74,9 @@ - (void)passwordDetailsTableViewControllerWasDismissed { } +- (void)dismissPasswordDetailsTableViewController { +} + - (void)showPasscodeDialogForReason:(PasscodeDialogReason)reason { }
diff --git a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm index 31070b2f..b9f70a0 100644 --- a/ios/chrome/browser/ui/settings/settings_navigation_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_navigation_controller.mm
@@ -762,13 +762,16 @@ - (void)passwordDetailsCoordinatorDidRemove: (PasswordDetailsCoordinator*)coordinator { - [self closeSettings]; DCHECK_EQ(self.passwordDetailsCoordinator, coordinator); [self.passwordDetailsCoordinator stop]; self.passwordDetailsCoordinator.delegate = nil; self.passwordDetailsCoordinator = nil; } +- (void)passwordDetailsCancelButtonWasTapped { + [self closeSettings]; +} + #pragma mark - ClearBrowsingDataCoordinatorDelegate - (void)clearBrowsingDataCoordinatorViewControllerWasRemoved:
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm index 7aad0ef..731f84b 100644 --- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm +++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_egtest.mm
@@ -11,6 +11,7 @@ #import "base/test/ios/wait_util.h" #import "base/time/time.h" #import "components/bookmarks/common/bookmark_pref_names.h" +#import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/signin/fake_system_identity.h" #import "ios/chrome/browser/tabs/inactive_tabs/features.h" #import "ios/chrome/browser/ui/authentication/signin_earl_grey.h" @@ -34,6 +35,7 @@ #import "ios/chrome/test/earl_grey/chrome_matchers.h" #import "ios/chrome/test/earl_grey/chrome_xcui_actions.h" #import "ios/chrome/test/earl_grey/web_http_server_chrome_test_case.h" +#import "ios/testing/earl_grey/app_launch_configuration.h" #import "ios/testing/earl_grey/app_launch_manager.h" #import "ios/testing/earl_grey/earl_grey_test.h" #import "ios/web/public/test/http_server/data_response_provider.h" @@ -2541,6 +2543,45 @@ conditionDescription); } +// Checks that tabs are sorted by their recency when the feature is enabled. +- (void)testRecencySort { + if ([ChromeEarlGrey isIPadIdiom]) { + EARL_GREY_TEST_SKIPPED(@"Skipped for iPad. The RecencyTab Grid Recency Sort" + @"feature is only supported on iPhone."); + } + + [self relaunchAppWithTabGridRecencySortEnabled]; + [self loadTestURLsInNewTabs]; + [ChromeEarlGreyUI openTabGrid]; + + [self verifyVisibleTabsCount:4]; + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle1, 0)] + assertWithMatcher:grey_sufficientlyVisible()]; + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle2, 1)] + assertWithMatcher:grey_sufficientlyVisible()]; + // Third tab has no title by design in this test class, so its URL is its + // fallback title. But since it depends on the port of the HTTP server + // underneath, it is not easily computable and checkable. So, don't check for + // it directly. + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle4, 3)] + assertWithMatcher:grey_sufficientlyVisible()]; + + // Open the second tab. + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle2, 1)] + performAction:grey_tap()]; + + // Check that the order changed in the tab grid: 1, 3, 4, 2. + [ChromeEarlGreyUI openTabGrid]; + + [self verifyVisibleTabsCount:4]; + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle1, 0)] + assertWithMatcher:grey_sufficientlyVisible()]; + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle4, 2)] + assertWithMatcher:grey_sufficientlyVisible()]; + [[EarlGrey selectElementWithMatcher:TabWithTitleAndIndex(kTitle2, 3)] + assertWithMatcher:grey_sufficientlyVisible()]; +} + #pragma mark - Helper Methods - (void)loadTestURLs { @@ -2713,4 +2754,12 @@ [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config]; } +// Relaunches the app with tab-grid-recency-sort enabled. +- (void)relaunchAppWithTabGridRecencySortEnabled { + AppLaunchConfiguration config; + config.relaunch_policy = ForceRelaunchByCleanShutdown; + config.features_enabled.push_back(kTabGridRecencySort); + [[AppLaunchManager sharedManager] ensureAppLaunchedWithConfiguration:config]; +} + @end
diff --git a/ios/chrome/browser/web/chrome_web_client.mm b/ios/chrome/browser/web/chrome_web_client.mm index eff31700..7fa87b3e 100644 --- a/ios/chrome/browser/web/chrome_web_client.mm +++ b/ios/chrome/browser/web/chrome_web_client.mm
@@ -304,7 +304,7 @@ autofill::SuggestionControllerJavaScriptFeature::GetInstance()); features.push_back(AutofillBottomSheetJavaScriptFeature::GetInstance()); if (base::FeatureList::IsEnabled( - autofill::features::kAutofillAcrossIframes)) { + autofill::features::kAutofillAcrossIframesIos)) { features.push_back( autofill::ChildFrameRegistrationJavaScriptFeature::GetInstance()); }
diff --git a/ios/chrome/widget_kit_extension/resources/widget_lens_icon.symbolset/lens.cr.svg b/ios/chrome/widget_kit_extension/resources/widget_lens_icon.symbolset/lens.cr.svg index 5b026d1..fa9073b1 100644 --- a/ios/chrome/widget_kit_extension/resources/widget_lens_icon.symbolset/lens.cr.svg +++ b/ios/chrome/widget_kit_extension/resources/widget_lens_icon.symbolset/lens.cr.svg
@@ -1,184 +1,257 @@ -<svg width="3300" height="2200" viewBox="0 0 3300 2200" fill="none" xmlns="http://www.w3.org/2000/svg"> -<g id="camera.lens.cr"> -<g id="Notes"> -<path id="artboard" d="M3300 0H0V2200H3300V0Z" fill="white"/> -<path id="Vector" d="M263 292H3036" stroke="black" stroke-width="0.5"/> -<text id="Weight/Scale Variations" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="263" y="321.727">Weight/Scale Variations</tspan></text> -<text id="Ultralight" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="531.211" y="321.727">Ultralight</tspan></text> -<text id="Thin" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="842.922" y="321.727">Thin</tspan></text> -<text id="Light" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1137.63" y="321.727">Light</tspan></text> -<text id="Regular" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1426.34" y="321.727">Regular</tspan></text> -<text id="Medium" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1721.56" y="321.727">Medium</tspan></text> -<text id="Semibold" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2014.27" y="321.727">Semibold</tspan></text> -<text id="Bold" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2325.98" y="321.727">Bold</tspan></text> -<text id="Heavy" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2617.19" y="321.727">Heavy</tspan></text> -<text id="Black" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2916.4" y="321.727">Black</tspan></text> -<path id="Vector_2" d="M263 1903H3036" stroke="black" stroke-width="0.5"/> -<g id="Group"> -<path id="Vector_3" d="M272.248 1933.83C273.329 1933.83 274.344 1933.63 275.295 1933.22C276.245 1932.81 277.084 1932.24 277.81 1931.51C278.535 1930.78 279.105 1929.94 279.519 1928.99C279.932 1928.04 280.139 1927.03 280.139 1925.95C280.139 1924.88 279.932 1923.86 279.519 1922.91C279.105 1921.96 278.534 1921.12 277.805 1920.39C277.075 1919.67 276.236 1919.1 275.285 1918.69C274.335 1918.28 273.319 1918.07 272.238 1918.07C271.164 1918.07 270.152 1918.28 269.201 1918.69C268.251 1919.1 267.414 1919.67 266.691 1920.39C265.969 1921.12 265.401 1921.96 264.987 1922.91C264.574 1923.86 264.367 1924.88 264.367 1925.95C264.367 1927.03 264.574 1928.04 264.987 1928.99C265.401 1929.94 265.97 1930.78 266.696 1931.51C267.422 1932.24 268.26 1932.81 269.211 1933.22C270.161 1933.63 271.174 1933.83 272.248 1933.83ZM272.248 1932.35C271.363 1932.35 270.534 1932.18 269.763 1931.85C268.991 1931.53 268.314 1931.07 267.731 1930.48C267.149 1929.9 266.693 1929.22 266.364 1928.44C266.035 1927.67 265.871 1926.84 265.871 1925.95C265.871 1925.07 266.034 1924.24 266.359 1923.46C266.685 1922.69 267.139 1922.01 267.722 1921.42C268.304 1920.83 268.981 1920.38 269.753 1920.05C270.524 1919.72 271.353 1919.55 272.238 1919.55C273.13 1919.55 273.962 1919.72 274.733 1920.05C275.505 1920.38 276.184 1920.83 276.769 1921.42C277.355 1922.01 277.814 1922.69 278.146 1923.46C278.478 1924.24 278.644 1925.07 278.644 1925.95C278.644 1926.84 278.48 1927.67 278.151 1928.44C277.823 1929.22 277.367 1929.9 276.784 1930.48C276.202 1931.07 275.523 1931.53 274.748 1931.85C273.973 1932.18 273.14 1932.35 272.248 1932.35ZM268.654 1925.95C268.654 1926.17 268.723 1926.34 268.859 1926.47C268.996 1926.61 269.178 1926.67 269.406 1926.67H271.516V1928.79C271.516 1929.01 271.581 1929.19 271.711 1929.33C271.841 1929.47 272.017 1929.54 272.238 1929.54C272.453 1929.54 272.631 1929.47 272.771 1929.33C272.91 1929.19 272.98 1929.01 272.98 1928.79V1926.67H275.09C275.311 1926.67 275.49 1926.61 275.627 1926.47C275.764 1926.34 275.832 1926.17 275.832 1925.95C275.832 1925.73 275.764 1925.55 275.627 1925.41C275.49 1925.28 275.311 1925.21 275.09 1925.21H272.98V1923.1C272.98 1922.88 272.91 1922.7 272.771 1922.56C272.631 1922.42 272.453 1922.35 272.238 1922.35C272.017 1922.35 271.841 1922.42 271.711 1922.56C271.581 1922.7 271.516 1922.88 271.516 1923.1V1925.21H269.406C269.178 1925.21 268.996 1925.28 268.859 1925.41C268.723 1925.55 268.654 1925.73 268.654 1925.95Z" fill="black"/> -</g> -<g id="Group_2"> -<path id="Vector_4" d="M293.576 1935.91C294.937 1935.91 296.218 1935.65 297.419 1935.13C298.62 1934.61 299.68 1933.89 300.598 1932.97C301.516 1932.05 302.235 1930.99 302.756 1929.79C303.277 1928.59 303.537 1927.31 303.537 1925.95C303.537 1924.59 303.277 1923.31 302.756 1922.11C302.235 1920.91 301.516 1919.85 300.598 1918.93C299.68 1918.01 298.618 1917.29 297.414 1916.77C296.21 1916.25 294.927 1915.99 293.566 1915.99C292.206 1915.99 290.925 1916.25 289.724 1916.77C288.522 1917.29 287.465 1918.01 286.55 1918.93C285.635 1919.85 284.917 1920.91 284.396 1922.11C283.876 1923.31 283.615 1924.59 283.615 1925.95C283.615 1927.31 283.876 1928.59 284.396 1929.79C284.917 1930.99 285.637 1932.05 286.555 1932.97C287.473 1933.89 288.532 1934.61 289.733 1935.13C290.935 1935.65 292.215 1935.91 293.576 1935.91ZM293.576 1934.25C292.424 1934.25 291.346 1934.04 290.344 1933.61C289.341 1933.18 288.461 1932.58 287.702 1931.82C286.944 1931.06 286.351 1930.18 285.925 1929.18C285.498 1928.18 285.285 1927.1 285.285 1925.95C285.285 1924.8 285.498 1923.72 285.925 1922.72C286.351 1921.71 286.942 1920.83 287.697 1920.07C288.452 1919.31 289.331 1918.71 290.334 1918.29C291.337 1917.86 292.414 1917.65 293.566 1917.65C294.719 1917.65 295.796 1917.86 296.799 1918.29C297.801 1918.71 298.684 1919.31 299.445 1920.07C300.207 1920.83 300.803 1921.71 301.232 1922.72C301.662 1923.72 301.877 1924.8 301.877 1925.95C301.877 1927.1 301.664 1928.18 301.237 1929.18C300.811 1930.18 300.218 1931.06 299.46 1931.82C298.702 1932.58 297.819 1933.18 296.813 1933.61C295.808 1934.04 294.729 1934.25 293.576 1934.25ZM289.045 1925.95C289.045 1926.18 289.123 1926.38 289.279 1926.53C289.436 1926.68 289.637 1926.75 289.885 1926.75H292.756V1929.63C292.756 1929.88 292.831 1930.08 292.98 1930.23C293.13 1930.38 293.322 1930.46 293.557 1930.46C293.804 1930.46 294.004 1930.38 294.157 1930.23C294.31 1930.08 294.387 1929.88 294.387 1929.63V1926.75H297.268C297.515 1926.75 297.715 1926.68 297.868 1926.53C298.021 1926.38 298.098 1926.18 298.098 1925.95C298.098 1925.7 298.021 1925.5 297.868 1925.35C297.715 1925.2 297.515 1925.12 297.268 1925.12H294.387V1922.25C294.387 1921.99 294.31 1921.79 294.157 1921.64C294.004 1921.48 293.804 1921.41 293.557 1921.41C293.322 1921.41 293.13 1921.49 292.98 1921.64C292.831 1921.8 292.756 1922 292.756 1922.25V1925.12H289.885C289.631 1925.12 289.427 1925.2 289.274 1925.35C289.121 1925.5 289.045 1925.7 289.045 1925.95Z" fill="black"/> -</g> -<g id="Group_3"> -<path id="Vector_5" d="M320.617 1938.67C322.01 1938.67 323.34 1938.45 324.606 1938.02C325.872 1937.58 327.036 1936.98 328.097 1936.2C329.158 1935.41 330.081 1934.49 330.866 1933.43C331.65 1932.37 332.259 1931.21 332.692 1929.94C333.125 1928.67 333.341 1927.34 333.341 1925.95C333.341 1924.56 333.125 1923.23 332.692 1921.96C332.259 1920.7 331.65 1919.53 330.866 1918.47C330.081 1917.41 329.158 1916.49 328.097 1915.7C327.036 1914.92 325.871 1914.31 324.601 1913.88C323.332 1913.44 322 1913.23 320.607 1913.23C319.214 1913.23 317.884 1913.44 316.618 1913.88C315.351 1914.31 314.189 1914.92 313.131 1915.7C312.073 1916.49 311.152 1917.41 310.368 1918.47C309.583 1919.53 308.976 1920.7 308.546 1921.96C308.117 1923.23 307.902 1924.56 307.902 1925.95C307.902 1927.34 308.118 1928.67 308.551 1929.94C308.984 1931.21 309.591 1932.37 310.373 1933.43C311.154 1934.49 312.075 1935.41 313.136 1936.2C314.197 1936.98 315.361 1937.58 316.627 1938.02C317.894 1938.45 319.223 1938.67 320.617 1938.67ZM320.617 1936.85C319.412 1936.85 318.265 1936.67 317.174 1936.3C316.084 1935.93 315.086 1935.41 314.181 1934.75C313.276 1934.09 312.49 1933.3 311.823 1932.39C311.155 1931.48 310.639 1930.48 310.275 1929.39C309.91 1928.3 309.728 1927.16 309.728 1925.95C309.728 1924.74 309.91 1923.59 310.275 1922.5C310.639 1921.41 311.154 1920.41 311.818 1919.5C312.482 1918.59 313.266 1917.81 314.171 1917.14C315.076 1916.48 316.074 1915.96 317.165 1915.6C318.255 1915.24 319.402 1915.05 320.607 1915.05C321.818 1915.05 322.969 1915.24 324.059 1915.6C325.15 1915.96 326.149 1916.48 327.057 1917.14C327.965 1917.81 328.751 1918.59 329.415 1919.5C330.08 1920.41 330.596 1921.41 330.963 1922.5C331.331 1923.59 331.515 1924.74 331.515 1925.95C331.522 1927.16 331.343 1928.3 330.978 1929.39C330.613 1930.48 330.098 1931.48 329.43 1932.39C328.763 1933.3 327.975 1934.09 327.067 1934.75C326.159 1935.41 325.159 1935.93 324.069 1936.3C322.978 1936.67 321.828 1936.85 320.617 1936.85ZM314.845 1925.95C314.845 1926.21 314.931 1926.42 315.104 1926.58C315.277 1926.75 315.496 1926.83 315.763 1926.83H319.708V1930.79C319.708 1931.05 319.791 1931.27 319.957 1931.44C320.123 1931.62 320.337 1931.7 320.597 1931.7C320.864 1931.7 321.084 1931.62 321.256 1931.45C321.429 1931.28 321.515 1931.06 321.515 1930.79V1926.83H325.47C325.737 1926.83 325.955 1926.75 326.124 1926.58C326.294 1926.42 326.378 1926.21 326.378 1925.95C326.378 1925.68 326.294 1925.46 326.124 1925.29C325.955 1925.12 325.737 1925.03 325.47 1925.03H321.515V1921.09C321.515 1920.81 321.429 1920.59 321.256 1920.42C321.084 1920.25 320.864 1920.16 320.597 1920.16C320.337 1920.16 320.123 1920.25 319.957 1920.42C319.791 1920.59 319.708 1920.81 319.708 1921.09V1925.03H315.763C315.49 1925.03 315.268 1925.12 315.099 1925.29C314.93 1925.46 314.845 1925.68 314.845 1925.95Z" fill="black"/> -</g> -<text id="Design Variations" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="263" y="1952.73">Design Variations</tspan></text> -<text id="Symbols are supported in up to nine weights and three scales." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1970.73">Symbols are supported in up to nine weights and three scales.</tspan></text> -<text id="For optimal layout with text and other symbols, vertically align" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1988.73">For optimal layout with text and other symbols, vertically align</tspan></text> -<text id="symbols with the adjacent text." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="2006.73">symbols with the adjacent text.</tspan></text> -<path id="Vector_6" d="M776 1919V1933" stroke="#00AEEF" stroke-width="0.5"/> -<g id="Group_4"> -<path id="Vector_7" d="M779.311 1933.16C779.571 1933.16 779.773 1933.1 779.916 1932.99C780.059 1932.88 780.176 1932.69 780.268 1932.42L781.527 1928.97H787.289L788.549 1932.42C788.64 1932.69 788.757 1932.88 788.9 1932.99C789.044 1933.1 789.242 1933.16 789.496 1933.16C789.757 1933.16 789.963 1933.09 790.116 1932.94C790.269 1932.8 790.346 1932.6 790.346 1932.36C790.346 1932.21 790.31 1932.03 790.238 1931.83L785.658 1919.63C785.541 1919.33 785.382 1919.11 785.18 1918.96C784.978 1918.81 784.721 1918.73 784.408 1918.73C783.803 1918.73 783.393 1919.03 783.178 1919.62L778.598 1931.84C778.526 1932.04 778.49 1932.22 778.49 1932.37C778.49 1932.61 778.563 1932.81 778.71 1932.95C778.856 1933.09 779.057 1933.16 779.311 1933.16ZM782.006 1927.48L784.379 1920.91H784.428L786.801 1927.48H782.006Z" fill="black"/> -</g> -<path id="Vector_8" d="M793.197 1919V1933" stroke="#00AEEF" stroke-width="0.5"/> -<text id="Margins" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="776" y="1952.73">Margins</tspan></text> -<text id="Leading and trailing margins on the left and right side of each symbol" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="1970.73">Leading and trailing margins on the left and right side of each symbol</tspan></text> -<text id="can be adjusted by modifying the x-location of the margin guidelines." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="1988.73">can be adjusted by modifying the x-location of the margin guidelines.</tspan></text> -<text id="Modifications are automatically applied proportionally to all" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="2006.73">Modifications are automatically applied proportionally to all</tspan></text> -<text id="scales and weights." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="776" y="2024.73">scales and weights.</tspan></text> -<g id="Group_5"> -<path id="Vector_9" d="M1291.84 1934.86L1293.54 1936.57C1293.97 1937.01 1294.42 1937.21 1294.9 1937.18C1295.38 1937.15 1295.85 1936.87 1296.31 1936.36L1307.01 1924.57L1306.04 1923.59L1295.43 1935.27C1295.25 1935.48 1295.07 1935.59 1294.89 1935.62C1294.71 1935.64 1294.51 1935.54 1294.27 1935.3L1293.1 1934.14C1292.87 1933.91 1292.76 1933.7 1292.79 1933.52C1292.82 1933.34 1292.94 1933.16 1293.14 1932.98L1304.62 1922.18L1303.64 1921.21L1292.05 1932.1C1291.55 1932.56 1291.29 1933.02 1291.25 1933.5C1291.22 1933.97 1291.41 1934.43 1291.84 1934.86ZM1298.26 1916.67C1298.05 1916.87 1297.93 1917.1 1297.91 1917.36C1297.88 1917.62 1297.93 1917.85 1298.04 1918.05C1298.16 1918.23 1298.33 1918.37 1298.56 1918.46C1298.78 1918.55 1299.06 1918.55 1299.38 1918.48C1300.11 1918.31 1300.85 1918.24 1301.6 1918.27C1302.35 1918.3 1303.08 1918.54 1303.79 1919.01L1303.21 1920.47C1303.04 1920.89 1302.99 1921.25 1303.07 1921.56C1303.14 1921.87 1303.31 1922.16 1303.58 1922.43L1305.87 1924.75C1306.12 1924.99 1306.35 1925.14 1306.58 1925.18C1306.81 1925.21 1307.06 1925.21 1307.34 1925.16L1308.4 1924.96L1309.07 1925.63L1309.03 1926.19C1309.01 1926.44 1309.04 1926.67 1309.12 1926.88C1309.2 1927.08 1309.36 1927.31 1309.61 1927.55L1310.37 1928.29C1310.61 1928.53 1310.87 1928.66 1311.15 1928.67C1311.44 1928.68 1311.7 1928.56 1311.93 1928.33L1314.84 1925.41C1315.07 1925.18 1315.19 1924.92 1315.18 1924.64C1315.18 1924.37 1315.05 1924.11 1314.81 1923.87L1314.04 1923.11C1313.8 1922.86 1313.58 1922.7 1313.38 1922.61C1313.17 1922.52 1312.95 1922.49 1312.71 1922.51L1312.13 1922.56L1311.49 1921.92L1311.73 1920.8C1311.8 1920.52 1311.79 1920.26 1311.7 1920.01C1311.6 1919.77 1311.41 1919.5 1311.12 1919.21L1308.92 1917.02C1308.09 1916.19 1307.2 1915.57 1306.26 1915.16C1305.32 1914.75 1304.37 1914.53 1303.42 1914.52C1302.47 1914.5 1301.55 1914.67 1300.66 1915.04C1299.78 1915.4 1298.98 1915.95 1298.26 1916.67ZM1299.75 1917.04C1300.36 1916.6 1301.01 1916.28 1301.7 1916.09C1302.39 1915.9 1303.1 1915.84 1303.8 1915.91C1304.51 1915.98 1305.2 1916.17 1305.87 1916.48C1306.54 1916.8 1307.15 1917.23 1307.7 1917.79L1310.13 1920.21C1310.25 1920.32 1310.32 1920.44 1310.35 1920.55C1310.38 1920.66 1310.38 1920.8 1310.34 1920.97L1310.02 1922.45L1311.52 1923.94L1312.51 1923.88C1312.63 1923.87 1312.72 1923.88 1312.79 1923.9C1312.85 1923.92 1312.94 1923.98 1313.03 1924.08L1313.61 1924.66L1311.17 1927.1L1310.59 1926.52C1310.49 1926.43 1310.43 1926.34 1310.41 1926.28C1310.38 1926.21 1310.37 1926.12 1310.38 1925.99L1310.45 1925.01L1308.95 1923.53L1307.43 1923.78C1307.26 1923.81 1307.14 1923.82 1307.04 1923.79C1306.95 1923.77 1306.84 1923.7 1306.71 1923.58L1304.71 1921.58C1304.58 1921.46 1304.51 1921.35 1304.49 1921.25C1304.48 1921.14 1304.51 1920.99 1304.59 1920.81L1305.46 1918.72C1304.68 1917.99 1303.8 1917.49 1302.83 1917.21C1301.85 1916.93 1300.86 1916.94 1299.84 1917.24C1299.76 1917.26 1299.71 1917.24 1299.69 1917.19C1299.67 1917.14 1299.69 1917.09 1299.75 1917.04Z" fill="black"/> -</g> -<text id="Exporting" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" font-weight="bold" letter-spacing="0em"><tspan x="1289" y="1952.73">Exporting</tspan></text> -<text id="Symbols should be outlined when exporting to ensure the" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1289" y="1970.73">Symbols should be outlined when exporting to ensure the</tspan></text> -<text id="design is preserved when submitting to Xcode." fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="1289" y="1988.73">design is preserved when submitting to Xcode.</tspan></text> -<text id="template-version" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2946" y="1932.73">Template v.3.0</tspan></text> -<text id="Requires Xcode 13 or greater" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2857" y="1950.73">Requires Xcode 13 or greater</tspan></text> -<text id="descriptive-name" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2889" y="1968.73">Generated from camera</tspan></text> -<text id="Typeset at 100 points" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="2903" y="1986.73">Typeset at 100 points</tspan></text> -<text id="Small" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="725.727">Small</tspan></text> -<text id="Medium_2" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1155.73">Medium</tspan></text> -<text id="Large" fill="black" xml:space="preserve" style="white-space: pre" font-family="Inter" font-size="13" letter-spacing="0em"><tspan x="263" y="1585.73">Large</tspan></text> -</g> -<g id="Guides"> -<g id="H-reference"> -<path id="Vector_10" d="M339.977 695.998H342.662L368.346 628.859H369.029V625.539H367.125L339.977 695.998ZM350.67 671.535H385.973L385.24 669.289H351.451L350.67 671.535ZM394.127 695.998H396.764L369.615 625.539H368.443V628.859L394.127 695.998Z" fill="#27AAE1"/> -</g> -<path id="Baseline-S" d="M263 696H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="Capline-S" d="M263 625.539H3036" stroke="#27AAE1" stroke-width="0.5"/> -<g id="H-reference_2"> -<path id="Vector_11" d="M339.977 1126H342.662L368.346 1058.86H369.029V1055.54H367.125L339.977 1126ZM350.67 1101.54H385.973L385.24 1099.29H351.451L350.67 1101.54ZM394.127 1126H396.764L369.615 1055.54H368.443V1058.86L394.127 1126Z" fill="#27AAE1"/> -</g> -<path id="Baseline-M" d="M263 1126H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="Capline-M" d="M263 1055.54H3036" stroke="#27AAE1" stroke-width="0.5"/> -<g id="H-reference_3"> -<path id="Vector_12" d="M339.977 1556H342.662L368.346 1488.86H369.029V1485.54H367.125L339.977 1556ZM350.67 1531.54H385.973L385.24 1529.29H351.451L350.67 1531.54ZM394.127 1556H396.764L369.615 1485.54H368.443V1488.86L394.127 1556Z" fill="#27AAE1"/> -</g> -<path id="Baseline-L" d="M263 1556H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="Capline-L" d="M263 1485.54H3036" stroke="#27AAE1" stroke-width="0.5"/> -<path id="left-margin-Regular-M" d="M1377.43 1030.79V1150.12" stroke="#00AEEF" stroke-width="0.5"/> -<path id="right-margin-Regular-M" d="M1522.26 1030.79V1150.12" stroke="#00AEEF" stroke-width="0.5"/> -</g> -<g id="Symbols"> -<g id="Black-L"> -<path id="Union" fill-rule="evenodd" clip-rule="evenodd" d="M2916.98 1452.3C2913.03 1452.3 2909.31 1454.09 2906.84 1457.17L2900.59 1464.97C2900.29 1465.34 2900.1 1465.74 2899.99 1466.15C2890.28 1466.38 2884.12 1467.17 2879.05 1469.75C2872.65 1473.01 2867.45 1478.21 2864.19 1484.61C2860.48 1491.88 2860.48 1501.4 2860.48 1520.44V1527.9C2860.48 1546.94 2860.48 1556.46 2864.19 1563.73C2867.45 1570.13 2872.65 1575.33 2879.05 1578.59C2886.32 1582.3 2895.84 1582.3 2914.88 1582.3H2951.91C2970.95 1582.3 2980.47 1582.3 2987.74 1578.59C2994.14 1575.33 2999.34 1570.13 3002.6 1563.73C3006.31 1556.46 3006.31 1546.94 3006.31 1527.9V1520.44C3006.31 1501.4 3006.31 1491.88 3002.6 1484.61C2999.34 1478.21 2994.14 1473.01 2987.74 1469.75C2982.73 1467.2 2976.66 1466.4 2967.15 1466.16L2959.95 1457.17C2957.49 1454.09 2953.75 1452.3 2949.81 1452.3H2916.98ZM2914.88 1486.04H2951.91C2961.76 1486.04 2967.94 1486.06 2972.61 1486.44C2977.04 1486.8 2978.31 1487.39 2978.66 1487.57C2981.3 1488.91 2983.44 1491.05 2984.78 1493.69C2984.96 1494.03 2985.55 1495.31 2985.91 1499.74C2986.29 1504.41 2986.31 1510.59 2986.31 1520.44V1527.9C2986.31 1537.75 2986.29 1543.93 2985.91 1548.6C2985.55 1553.03 2984.96 1554.31 2984.78 1554.65C2983.44 1557.29 2981.3 1559.43 2978.66 1560.77C2978.31 1560.95 2977.04 1561.54 2972.61 1561.9C2967.94 1562.28 2961.76 1562.3 2951.91 1562.3H2914.88C2905.03 1562.3 2898.85 1562.28 2894.18 1561.9C2889.75 1561.54 2888.48 1560.95 2888.13 1560.77C2885.49 1559.43 2883.35 1557.29 2882.01 1554.65C2881.83 1554.31 2881.24 1553.03 2880.88 1548.6C2880.5 1543.93 2880.48 1537.75 2880.48 1527.9V1520.44C2880.48 1510.59 2880.5 1504.41 2880.88 1499.74C2881.24 1495.31 2881.83 1494.03 2882.01 1493.69C2883.35 1491.05 2885.49 1488.91 2888.13 1487.57C2888.48 1487.39 2889.75 1486.8 2894.18 1486.44C2898.85 1486.06 2905.03 1486.04 2914.88 1486.04Z" fill="black"/> -<path id="Rectangle 11906" d="M2907.57 1524.17C2907.57 1509.91 2919.13 1498.35 2933.4 1498.35V1498.35C2947.66 1498.35 2959.22 1509.91 2959.22 1524.17V1524.17C2959.22 1538.43 2947.66 1549.99 2933.4 1549.99V1549.99C2919.13 1549.99 2907.57 1538.43 2907.57 1524.17V1524.17Z" fill="black"/> -</g> -<g id="Heavy-L"> -<path id="Union_2" fill-rule="evenodd" clip-rule="evenodd" d="M2620.27 1452.5C2616.33 1452.5 2612.6 1454.29 2610.13 1457.37L2603.88 1465.17C2603.59 1465.53 2603.4 1465.92 2603.29 1466.32C2593.18 1466.51 2586.92 1467.23 2581.8 1469.84C2575.59 1473 2570.54 1478.05 2567.37 1484.26C2563.78 1491.32 2563.78 1500.56 2563.78 1519.04V1529.7C2563.78 1548.18 2563.78 1557.42 2567.37 1564.48C2570.54 1570.69 2575.59 1575.74 2581.8 1578.9C2588.86 1582.5 2598.1 1582.5 2616.58 1582.5H2656.8C2675.28 1582.5 2684.52 1582.5 2691.58 1578.9C2697.79 1575.74 2702.84 1570.69 2706 1564.48C2709.6 1557.42 2709.6 1548.18 2709.6 1529.7V1519.04C2709.6 1500.56 2709.6 1491.32 2706 1484.26C2702.84 1478.05 2697.79 1473 2691.58 1469.84C2686.52 1467.26 2680.33 1466.53 2670.42 1466.32L2663.25 1457.37C2660.78 1454.29 2657.05 1452.5 2653.1 1452.5H2620.27ZM2616.58 1483.99H2656.8C2666.33 1483.99 2672.42 1484.01 2677.03 1484.38C2681.43 1484.74 2682.91 1485.34 2683.52 1485.65C2686.39 1487.12 2688.72 1489.45 2690.19 1492.32C2690.5 1492.93 2691.1 1494.41 2691.46 1498.81C2691.84 1503.43 2691.85 1509.51 2691.85 1519.04V1529.7C2691.85 1539.23 2691.84 1545.31 2691.46 1549.93C2691.1 1554.33 2690.5 1555.81 2690.19 1556.42C2688.72 1559.29 2686.39 1561.62 2683.52 1563.08C2682.91 1563.4 2681.43 1564 2677.03 1564.36C2672.42 1564.73 2666.33 1564.75 2656.8 1564.75H2616.58C2607.04 1564.75 2600.96 1564.73 2596.35 1564.36C2591.94 1564 2590.46 1563.4 2589.85 1563.08C2586.99 1561.62 2584.65 1559.29 2583.19 1556.42C2582.88 1555.81 2582.28 1554.33 2581.92 1549.93C2581.54 1545.31 2581.53 1539.23 2581.53 1529.7V1519.04C2581.53 1509.51 2581.54 1503.43 2581.92 1498.81C2582.28 1494.41 2582.88 1492.93 2583.19 1492.32C2584.65 1489.45 2586.99 1487.12 2589.85 1485.65C2590.46 1485.34 2591.94 1484.74 2596.35 1484.38C2600.96 1484.01 2607.04 1483.99 2616.58 1483.99Z" fill="black"/> -<path id="Rectangle 11906_2" d="M2610.87 1524.37C2610.87 1510.11 2622.43 1498.55 2636.69 1498.55V1498.55C2650.95 1498.55 2662.51 1510.11 2662.51 1524.37V1524.37C2662.51 1538.63 2650.95 1550.19 2636.69 1550.19V1550.19C2622.43 1550.19 2610.87 1538.63 2610.87 1524.37V1524.37Z" fill="black"/> -</g> -<g id="Bold-L"> -<path id="Union_3" fill-rule="evenodd" clip-rule="evenodd" d="M2323.55 1453.87C2319.61 1453.87 2315.88 1455.66 2313.42 1458.73L2307.17 1466.54C2306.88 1466.89 2306.69 1467.27 2306.58 1467.66C2296.07 1467.82 2289.7 1468.47 2284.54 1471.1C2278.51 1474.17 2273.62 1479.06 2270.55 1485.08C2267.06 1491.93 2267.06 1500.89 2267.06 1518.81V1532.66C2267.06 1550.59 2267.06 1559.55 2270.55 1566.39C2273.62 1572.41 2278.51 1577.31 2284.54 1580.38C2291.38 1583.86 2300.34 1583.86 2318.26 1583.86H2361.68C2379.61 1583.86 2388.57 1583.86 2395.41 1580.38C2401.43 1577.31 2406.33 1572.41 2409.4 1566.39C2412.88 1559.55 2412.88 1550.59 2412.88 1532.66V1518.81C2412.88 1500.89 2412.88 1491.93 2409.4 1485.08C2406.33 1479.06 2401.43 1474.17 2395.41 1471.1C2390.3 1468.49 2384.01 1467.83 2373.69 1467.67L2366.53 1458.74C2364.06 1455.66 2360.33 1453.87 2356.39 1453.87H2323.55ZM2318.26 1482.11H2361.68C2370.88 1482.11 2376.91 1482.12 2381.52 1482.5C2385.96 1482.86 2387.79 1483.49 2388.83 1484.02C2392.12 1485.69 2394.8 1488.37 2396.48 1491.66C2397.01 1492.7 2397.63 1494.53 2398 1498.97C2398.37 1503.58 2398.38 1509.61 2398.38 1518.81V1532.66C2398.38 1541.86 2398.37 1547.89 2398 1552.5C2397.63 1556.94 2397.01 1558.77 2396.48 1559.81C2394.8 1563.1 2392.12 1565.78 2388.83 1567.46C2387.79 1567.99 2385.96 1568.61 2381.52 1568.98C2376.91 1569.35 2370.88 1569.36 2361.68 1569.36H2318.26C2309.06 1569.36 2303.04 1569.35 2298.43 1568.98C2293.99 1568.61 2292.16 1567.99 2291.12 1567.46C2287.83 1565.78 2285.15 1563.1 2283.47 1559.81C2282.94 1558.77 2282.31 1556.94 2281.95 1552.5C2281.57 1547.89 2281.56 1541.86 2281.56 1532.66V1518.81C2281.56 1509.61 2281.57 1503.58 2281.95 1498.97C2282.31 1494.53 2282.94 1492.7 2283.47 1491.66C2285.15 1488.37 2287.83 1485.69 2291.12 1484.02C2292.16 1483.49 2293.99 1482.86 2298.43 1482.5C2303.04 1482.12 2309.06 1482.11 2318.26 1482.11Z" fill="black"/> -<path id="Rectangle 11906_3" d="M2314.15 1525.73C2314.15 1511.47 2325.71 1499.91 2339.97 1499.91V1499.91C2354.23 1499.91 2365.79 1511.47 2365.79 1525.73V1525.73C2365.79 1539.99 2354.23 1551.55 2339.97 1551.55V1551.55C2325.71 1551.55 2314.15 1539.99 2314.15 1525.73V1525.73Z" fill="black"/> -</g> -<g id="Semibold-L"> -<path id="Union_4" fill-rule="evenodd" clip-rule="evenodd" d="M2026.85 1453.87C2022.91 1453.87 2019.18 1455.66 2016.71 1458.74L2010.46 1466.54C2010.18 1466.89 2009.99 1467.26 2009.88 1467.65C1998.95 1467.77 1992.49 1468.34 1987.28 1470.99C1981.45 1473.96 1976.71 1478.71 1973.74 1484.54C1970.36 1491.17 1970.36 1499.85 1970.36 1517.21V1534.27C1970.36 1551.63 1970.36 1560.31 1973.74 1566.94C1976.71 1572.77 1981.45 1577.52 1987.28 1580.49C1993.91 1583.87 2002.6 1583.87 2019.96 1583.87H2066.58C2083.94 1583.87 2092.62 1583.87 2099.25 1580.49C2105.09 1577.52 2109.83 1572.77 2112.8 1566.94C2116.18 1560.31 2116.18 1551.63 2116.18 1534.27V1517.21C2116.18 1499.85 2116.18 1491.17 2112.8 1484.54C2109.83 1478.71 2105.09 1473.96 2099.25 1470.99C2094.1 1468.37 2087.71 1467.78 2076.96 1467.65L2069.83 1458.74C2067.36 1455.66 2063.63 1453.87 2059.68 1453.87H2026.85ZM2019.96 1479.86H2066.58C2075.46 1479.86 2081.39 1479.87 2085.94 1480.24C2090.35 1480.61 2092.39 1481.24 2093.69 1481.91C2097.22 1483.7 2100.09 1486.57 2101.88 1490.1C2102.55 1491.4 2103.19 1493.44 2103.55 1497.85C2103.92 1502.4 2103.93 1508.33 2103.93 1517.21V1534.27C2103.93 1543.15 2103.92 1549.08 2103.55 1553.63C2103.19 1558.04 2102.55 1560.08 2101.88 1561.38C2100.09 1564.91 2097.22 1567.78 2093.69 1569.57C2092.39 1570.24 2090.35 1570.88 2085.94 1571.24C2081.39 1571.61 2075.46 1571.62 2066.58 1571.62H2019.96C2011.07 1571.62 2005.15 1571.61 2000.59 1571.24C1996.18 1570.88 1994.15 1570.24 1992.85 1569.57C1989.32 1567.78 1986.45 1564.91 1984.65 1561.38C1983.99 1560.08 1983.35 1558.04 1982.99 1553.63C1982.62 1549.08 1982.61 1543.15 1982.61 1534.27V1517.21C1982.61 1508.33 1982.62 1502.4 1982.99 1497.85C1983.35 1493.44 1983.99 1491.4 1984.65 1490.1C1986.45 1486.57 1989.32 1483.7 1992.85 1481.91C1994.15 1481.24 1996.18 1480.61 2000.59 1480.24C2005.15 1479.87 2011.07 1479.86 2019.96 1479.86Z" fill="black"/> -<path id="Rectangle 11906_4" d="M2017.45 1525.74C2017.45 1511.48 2029.01 1499.92 2043.27 1499.92V1499.92C2057.53 1499.92 2069.09 1511.48 2069.09 1525.74V1525.74C2069.09 1540 2057.53 1551.56 2043.27 1551.56V1551.56C2029.01 1551.56 2017.45 1540 2017.45 1525.74V1525.74Z" fill="black"/> -</g> -<g id="Medium-L"> -<path id="Union_5" fill-rule="evenodd" clip-rule="evenodd" d="M1730.14 1453.84C1726.2 1453.84 1722.47 1455.63 1720 1458.71L1713.75 1466.52C1713.48 1466.86 1713.29 1467.23 1713.17 1467.61C1701.82 1467.7 1695.26 1468.19 1690.03 1470.86C1684.38 1473.73 1679.79 1478.32 1676.92 1483.97C1673.65 1490.38 1673.65 1498.78 1673.65 1515.59V1535.84C1673.65 1552.64 1673.65 1561.04 1676.92 1567.46C1679.79 1573.11 1684.38 1577.69 1690.03 1580.57C1696.45 1583.84 1704.85 1583.84 1721.65 1583.84H1771.47C1788.27 1583.84 1796.67 1583.84 1803.09 1580.57C1808.73 1577.69 1813.32 1573.11 1816.2 1567.46C1819.47 1561.04 1819.47 1552.64 1819.47 1535.84V1515.59C1819.47 1498.78 1819.47 1490.38 1816.2 1483.97C1813.32 1478.32 1808.73 1473.73 1803.09 1470.86C1797.9 1468.21 1791.42 1467.71 1780.24 1467.61L1773.12 1458.72C1770.65 1455.64 1766.92 1453.84 1762.97 1453.84H1730.14ZM1721.65 1478.34H1771.47C1780.05 1478.34 1785.83 1478.34 1790.3 1478.71C1794.64 1479.06 1796.77 1479.7 1798.21 1480.43C1801.83 1482.28 1804.78 1485.22 1806.62 1488.85C1807.35 1490.29 1807.99 1492.42 1808.35 1496.76C1808.71 1501.22 1808.72 1507.01 1808.72 1515.59V1535.84C1808.72 1544.42 1808.71 1550.21 1808.35 1554.67C1807.99 1559.01 1807.35 1561.14 1806.62 1562.58C1804.78 1566.2 1801.83 1569.15 1798.21 1570.99C1796.77 1571.73 1794.64 1572.36 1790.3 1572.72C1785.83 1573.08 1780.05 1573.09 1771.47 1573.09H1721.65C1713.07 1573.09 1707.28 1573.08 1702.82 1572.72C1698.48 1572.36 1696.35 1571.73 1694.91 1570.99C1691.29 1569.15 1688.34 1566.2 1686.5 1562.58C1685.76 1561.14 1685.13 1559.01 1684.77 1554.67C1684.41 1550.21 1684.4 1544.42 1684.4 1535.84V1515.59C1684.4 1507.01 1684.41 1501.22 1684.77 1496.76C1685.13 1492.42 1685.76 1490.29 1686.5 1488.85C1688.34 1485.22 1691.29 1482.28 1694.91 1480.43C1696.35 1479.7 1698.48 1479.06 1702.82 1478.71C1707.28 1478.34 1713.07 1478.34 1721.65 1478.34Z" fill="black"/> -<path id="Rectangle 11906_5" d="M1720.74 1525.71C1720.74 1511.45 1732.3 1499.89 1746.56 1499.89V1499.89C1760.82 1499.89 1772.38 1511.45 1772.38 1525.71V1525.71C1772.38 1539.97 1760.82 1551.53 1746.56 1551.53V1551.53C1732.3 1551.53 1720.74 1539.97 1720.74 1525.71V1525.71Z" fill="black"/> -</g> -<g id="Regular-L"> -<path id="Union_6" fill-rule="evenodd" clip-rule="evenodd" d="M1433.49 1453.82C1429.55 1453.82 1425.82 1455.61 1423.36 1458.68L1417.1 1466.49C1416.83 1466.83 1416.64 1467.19 1416.53 1467.56C1404.28 1467.6 1397.57 1467.92 1392.29 1470.61C1387.02 1473.29 1382.74 1477.58 1380.05 1482.85C1377 1488.84 1377 1496.68 1377 1512.36V1539.01C1377 1554.69 1377 1562.54 1380.05 1568.53C1382.74 1573.79 1387.02 1578.08 1392.29 1580.76C1398.28 1583.81 1406.12 1583.81 1421.8 1583.81H1478.02C1493.7 1583.81 1501.54 1583.81 1507.53 1580.76C1512.8 1578.08 1517.09 1573.79 1519.77 1568.53C1522.82 1562.54 1522.82 1554.69 1522.82 1539.01V1512.36C1522.82 1496.68 1522.82 1488.84 1519.77 1482.85C1517.09 1477.58 1512.8 1473.29 1507.53 1470.61C1502.3 1467.94 1495.65 1467.61 1483.58 1467.56L1476.47 1458.69C1474 1455.61 1470.27 1453.82 1466.32 1453.82H1433.49ZM1421.8 1476.06H1478.02C1486 1476.06 1491.48 1476.07 1495.72 1476.41C1499.86 1476.75 1502.08 1477.37 1503.67 1478.18C1507.34 1480.05 1510.33 1483.04 1512.2 1486.71C1513.01 1488.3 1513.63 1490.52 1513.97 1494.66C1514.32 1498.9 1514.32 1504.38 1514.32 1512.36V1539.01C1514.32 1546.99 1514.32 1552.47 1513.97 1556.71C1513.63 1560.85 1513.01 1563.07 1512.2 1564.67C1510.33 1568.34 1507.34 1571.32 1503.67 1573.19C1502.08 1574 1499.86 1574.62 1495.72 1574.96C1491.48 1575.31 1486 1575.31 1478.02 1575.31H1421.8C1413.82 1575.31 1408.35 1575.31 1404.1 1574.96C1399.96 1574.62 1397.74 1574 1396.15 1573.19C1392.48 1571.32 1389.5 1568.34 1387.63 1564.67C1386.81 1563.07 1386.19 1560.85 1385.85 1556.71C1385.51 1552.47 1385.5 1546.99 1385.5 1539.01V1512.36C1385.5 1504.38 1385.51 1498.9 1385.85 1494.66C1386.19 1490.52 1386.81 1488.3 1387.63 1486.71C1389.5 1483.04 1392.48 1480.05 1396.15 1478.18C1397.74 1477.37 1399.96 1476.75 1404.1 1476.41C1408.35 1476.07 1413.82 1476.06 1421.8 1476.06Z" fill="black"/> -<path id="Rectangle 11906_6" d="M1424.09 1525.68C1424.09 1511.42 1435.65 1499.86 1449.91 1499.86V1499.86C1464.17 1499.86 1475.73 1511.42 1475.73 1525.68V1525.68C1475.73 1539.94 1464.17 1551.5 1449.91 1551.5V1551.5C1435.65 1551.5 1424.09 1539.94 1424.09 1525.68V1525.68Z" fill="black"/> -</g> -<g id="Light-L"> -<path id="Union_7" fill-rule="evenodd" clip-rule="evenodd" d="M1136.71 1453.92C1132.77 1453.92 1129.04 1455.71 1126.58 1458.78L1120.32 1466.59C1120.06 1466.93 1119.87 1467.29 1119.75 1467.66C1106.56 1467.67 1099.71 1467.8 1094.42 1470.49C1089.53 1472.99 1085.55 1476.96 1083.06 1481.86C1080.22 1487.42 1080.22 1494.7 1080.22 1509.26V1542.31C1080.22 1556.88 1080.22 1564.16 1083.06 1569.72C1085.55 1574.61 1089.53 1578.59 1094.42 1581.08C1099.98 1583.91 1107.26 1583.91 1121.82 1583.91H1184.44C1199.01 1583.91 1206.29 1583.91 1211.85 1581.08C1216.74 1578.59 1220.72 1574.61 1223.21 1569.72C1226.04 1564.16 1226.04 1556.88 1226.04 1542.31V1509.26C1226.04 1494.7 1226.04 1487.42 1223.21 1481.86C1220.72 1476.96 1216.74 1472.99 1211.85 1470.49C1206.59 1467.82 1199.81 1467.67 1186.8 1467.66L1179.69 1458.79C1177.22 1455.71 1173.49 1453.92 1169.55 1453.92H1136.71ZM1121.82 1474.91H1184.44C1191.84 1474.91 1196.96 1474.92 1200.93 1475.24C1204.82 1475.56 1206.97 1476.14 1208.56 1476.95C1212.08 1478.75 1214.95 1481.62 1216.75 1485.15C1217.56 1486.74 1218.15 1488.89 1218.46 1492.77C1218.79 1496.75 1218.79 1501.86 1218.79 1509.26V1542.31C1218.79 1549.72 1218.79 1554.83 1218.46 1558.8C1218.15 1562.69 1217.56 1564.84 1216.75 1566.43C1214.95 1569.96 1212.08 1572.82 1208.56 1574.62C1206.97 1575.43 1204.82 1576.02 1200.93 1576.33C1196.96 1576.66 1191.84 1576.66 1184.44 1576.66H1121.82C1114.42 1576.66 1109.31 1576.66 1105.34 1576.33C1101.45 1576.02 1099.3 1575.43 1097.71 1574.62C1094.18 1572.82 1091.31 1569.96 1089.52 1566.43C1088.71 1564.84 1088.12 1562.69 1087.8 1558.8C1087.48 1554.83 1087.47 1549.72 1087.47 1542.31V1509.26C1087.47 1501.86 1087.48 1496.75 1087.8 1492.77C1088.12 1488.89 1088.71 1486.74 1089.52 1485.15C1091.31 1481.62 1094.18 1478.75 1097.71 1476.95C1099.3 1476.14 1101.45 1475.56 1105.34 1475.24C1109.31 1474.92 1114.42 1474.91 1121.82 1474.91Z" fill="black"/> -<path id="Rectangle 11906_7" d="M1127.31 1525.79C1127.31 1511.53 1138.87 1499.96 1153.13 1499.96V1499.96C1167.39 1499.96 1178.95 1511.53 1178.95 1525.79V1525.79C1178.95 1540.05 1167.39 1551.61 1153.13 1551.61V1551.61C1138.87 1551.61 1127.31 1540.05 1127.31 1525.79V1525.79Z" fill="black"/> -</g> -<g id="Thin-L"> -<path id="Union_8" fill-rule="evenodd" clip-rule="evenodd" d="M840.003 1454.01C836.062 1454.01 832.333 1455.8 829.868 1458.88L823.614 1466.68C823.225 1467.17 823.007 1467.71 822.935 1468.25C809.811 1468.26 802.986 1468.39 797.708 1471.08C792.816 1473.58 788.839 1477.55 786.346 1482.45C783.512 1488.01 783.512 1495.29 783.512 1509.85V1541.9C783.512 1556.46 783.512 1563.74 786.346 1569.3C788.839 1574.2 792.816 1578.17 797.708 1580.67C803.27 1583.5 810.551 1583.5 825.112 1583.5H887.733C902.295 1583.5 909.575 1583.5 915.137 1580.67C920.029 1578.17 924.007 1574.2 926.499 1569.3C929.333 1563.74 929.333 1556.46 929.333 1541.9V1509.85C929.333 1495.29 929.333 1488.01 926.499 1482.45C924.007 1477.55 920.029 1473.58 915.137 1471.08C909.937 1468.43 903.236 1468.26 890.487 1468.25L882.981 1458.88C880.514 1455.8 876.781 1454.01 872.836 1454.01H840.003ZM825.112 1472.25H887.733C895.08 1472.25 900.349 1472.25 904.484 1472.59C908.572 1472.92 911.198 1473.57 913.321 1474.65C917.461 1476.76 920.826 1480.12 922.935 1484.26C924.017 1486.39 924.658 1489.01 924.992 1493.1C925.33 1497.23 925.333 1502.5 925.333 1509.85V1541.9C925.333 1549.25 925.33 1554.52 924.992 1558.65C924.658 1562.74 924.017 1565.36 922.935 1567.49C920.826 1571.63 917.461 1574.99 913.321 1577.1C911.198 1578.18 908.572 1578.83 904.484 1579.16C900.349 1579.5 895.08 1579.5 887.733 1579.5H825.112C817.766 1579.5 812.496 1579.5 808.361 1579.16C804.273 1578.83 801.647 1578.18 799.524 1577.1C795.385 1574.99 792.019 1571.63 789.91 1567.49C788.828 1565.36 788.187 1562.74 787.853 1558.65C787.515 1554.52 787.512 1549.25 787.512 1541.9V1509.85C787.512 1502.5 787.515 1497.23 787.853 1493.1C788.187 1489.01 788.828 1486.39 789.91 1484.26C792.019 1480.12 795.385 1476.76 799.524 1474.65C801.647 1473.57 804.273 1472.92 808.361 1472.59C812.496 1472.25 817.766 1472.25 825.112 1472.25Z" fill="black"/> -<path id="Rectangle 11906_8" d="M830.602 1525.88C830.602 1511.62 842.162 1500.06 856.422 1500.06V1500.06C870.683 1500.06 882.243 1511.62 882.243 1525.88V1525.88C882.243 1540.14 870.683 1551.7 856.422 1551.7V1551.7C842.162 1551.7 830.602 1540.14 830.602 1525.88V1525.88Z" fill="black"/> -</g> -<g id="Ultralight-L"> -<path id="Union_9" fill-rule="evenodd" clip-rule="evenodd" d="M543.01 1454.09C539.064 1454.09 535.332 1455.88 532.865 1458.96L524.956 1468.83H523.312C510.431 1468.83 503.99 1468.83 499.07 1471.33C494.743 1473.54 491.224 1477.06 489.019 1481.39C486.512 1486.31 486.512 1492.75 486.512 1505.63V1546.28C486.512 1559.16 486.512 1565.6 489.019 1570.52C491.224 1574.85 494.743 1578.37 499.07 1580.57C503.99 1583.08 510.431 1583.08 523.312 1583.08H595.533C608.414 1583.08 614.855 1583.08 619.775 1580.57C624.103 1578.37 627.621 1574.85 629.826 1570.52C632.333 1565.6 632.333 1559.16 632.333 1546.28V1505.63C632.333 1492.75 632.333 1486.31 629.826 1481.39C627.621 1477.06 624.103 1473.54 619.775 1471.33C614.855 1468.83 608.414 1468.83 595.533 1468.83H593.89L585.981 1458.96C583.514 1455.88 579.782 1454.09 575.836 1454.09H543.01ZM523.312 1471.33H595.533C602.015 1471.33 606.726 1471.33 610.436 1471.63C614.117 1471.93 616.591 1472.52 618.64 1473.56C622.497 1475.53 625.633 1478.66 627.599 1482.52C628.643 1484.57 629.227 1487.04 629.528 1490.73C629.831 1494.44 629.833 1499.15 629.833 1505.63V1546.28C629.833 1552.76 629.831 1557.47 629.528 1561.18C629.227 1564.86 628.643 1567.34 627.599 1569.38C625.633 1573.24 622.497 1576.38 618.64 1578.34C616.591 1579.39 614.117 1579.97 610.436 1580.27C606.726 1580.58 602.015 1580.58 595.533 1580.58H523.312C516.83 1580.58 512.119 1580.58 508.409 1580.27C504.729 1579.97 502.254 1579.39 500.205 1578.34C496.348 1576.38 493.212 1573.24 491.247 1569.38C490.203 1567.34 489.618 1564.86 489.317 1561.18C489.014 1557.47 489.012 1552.76 489.012 1546.28V1505.63C489.012 1499.15 489.014 1494.44 489.317 1490.73C489.618 1487.04 490.203 1484.57 491.247 1482.52C493.212 1478.66 496.348 1475.53 500.205 1473.56C502.254 1472.52 504.729 1471.93 508.409 1471.63C512.119 1471.33 516.83 1471.33 523.312 1471.33Z" fill="black"/> -<path id="Rectangle 11906_9" d="M533.602 1525.95C533.602 1511.69 545.162 1500.13 559.422 1500.13V1500.13C573.683 1500.13 585.243 1511.69 585.243 1525.95V1525.95C585.243 1540.21 573.683 1551.77 559.422 1551.77V1551.77C545.162 1551.77 533.602 1540.21 533.602 1525.95V1525.95Z" fill="black"/> -</g> -<g id="Black-M"> -<path id="Union_10" fill-rule="evenodd" clip-rule="evenodd" d="M2920.33 1039.53C2917.91 1039.53 2915.61 1040.63 2914.09 1042.53L2908.27 1049.79C2905.23 1049.8 2903.38 1049.86 2901.77 1050.12C2890.22 1051.95 2881.16 1061.01 2879.33 1072.56C2879 1074.66 2879 1077.17 2879 1082.19V1104.13C2879 1109.14 2879 1111.65 2879.33 1113.75C2881.16 1125.3 2890.22 1134.36 2901.77 1136.19C2903.87 1136.53 2906.38 1136.53 2911.4 1136.53H2955.4C2960.41 1136.53 2962.92 1136.53 2965.02 1136.19C2976.57 1134.36 2985.63 1125.3 2987.46 1113.75C2987.8 1111.65 2987.8 1109.14 2987.8 1104.13V1082.19C2987.8 1077.17 2987.8 1074.66 2987.46 1072.56C2985.63 1061.01 2976.57 1051.95 2965.02 1050.12C2963.41 1049.86 2961.56 1049.8 2958.52 1049.79L2952.7 1042.53C2951.18 1040.63 2948.89 1039.53 2946.46 1039.53H2920.33ZM2911.4 1067.04H2955.4C2961.07 1067.04 2961.9 1067.09 2962.32 1067.16C2966.49 1067.82 2969.77 1071.09 2970.43 1075.26C2970.49 1075.68 2970.55 1076.51 2970.55 1082.19V1104.13C2970.55 1109.8 2970.49 1110.63 2970.43 1111.05C2969.77 1115.22 2966.49 1118.49 2962.32 1119.16C2961.9 1119.22 2961.07 1119.28 2955.4 1119.28H2911.4C2905.72 1119.28 2904.89 1119.22 2904.47 1119.16C2900.3 1118.49 2897.03 1115.22 2896.37 1111.05C2896.3 1110.63 2896.25 1109.8 2896.25 1104.13V1082.19C2896.25 1076.51 2896.3 1075.68 2896.37 1075.26C2897.03 1071.09 2900.3 1067.82 2904.47 1067.16C2904.89 1067.09 2905.72 1067.04 2911.4 1067.04Z" fill="black"/> -<path id="Rectangle 11906_10" d="M2914.13 1093.15C2914.13 1082.51 2922.76 1073.89 2933.4 1073.89V1073.89C2944.04 1073.89 2952.66 1082.51 2952.66 1093.15V1093.15C2952.66 1103.79 2944.04 1112.42 2933.4 1112.42V1112.42C2922.76 1112.42 2914.13 1103.79 2914.13 1093.15V1093.15Z" fill="black"/> -</g> -<g id="Heavy-M"> -<path id="Union_11" fill-rule="evenodd" clip-rule="evenodd" d="M2623.63 1040.53C2621.2 1040.53 2618.91 1041.63 2617.39 1043.53L2611.57 1050.79C2607.4 1050.79 2605.22 1050.8 2603.38 1051.09C2592.69 1052.79 2584.3 1061.18 2582.6 1071.87C2582.29 1073.82 2582.29 1076.14 2582.29 1080.79V1107.53C2582.29 1112.17 2582.29 1114.49 2582.6 1116.44C2584.3 1127.13 2592.69 1135.52 2603.38 1137.22C2605.33 1137.53 2607.65 1137.53 2612.29 1137.53H2661.09C2665.74 1137.53 2668.06 1137.53 2670 1137.22C2680.7 1135.52 2689.09 1127.13 2690.79 1116.44C2691.09 1114.49 2691.09 1112.17 2691.09 1107.53V1080.79C2691.09 1076.14 2691.09 1073.82 2690.79 1071.87C2689.09 1061.18 2680.7 1052.79 2670 1051.09C2668.16 1050.8 2665.98 1050.79 2661.81 1050.79L2656 1043.53C2654.48 1041.63 2652.18 1040.53 2649.76 1040.53H2623.63ZM2612.29 1065.79H2661.09C2666.31 1065.79 2667.17 1065.83 2667.66 1065.91C2671.94 1066.59 2675.29 1069.94 2675.97 1074.22C2676.05 1074.7 2676.09 1075.57 2676.09 1080.79V1107.53C2676.09 1112.74 2676.05 1113.61 2675.97 1114.09C2675.29 1118.37 2671.94 1121.72 2667.66 1122.4C2667.17 1122.48 2666.31 1122.53 2661.09 1122.53H2612.29C2607.08 1122.53 2606.21 1122.48 2605.73 1122.4C2601.45 1121.72 2598.09 1118.37 2597.42 1114.09C2597.34 1113.61 2597.29 1112.74 2597.29 1107.53V1080.79C2597.29 1075.57 2597.34 1074.7 2597.42 1074.22C2598.09 1069.94 2601.45 1066.59 2605.73 1065.91C2606.21 1065.83 2607.08 1065.79 2612.29 1065.79Z" fill="black"/> -<path id="Rectangle 11906_11" d="M2617.43 1094.15C2617.43 1083.51 2626.05 1074.89 2636.69 1074.89V1074.89C2647.33 1074.89 2655.96 1083.51 2655.96 1094.15V1094.15C2655.96 1104.79 2647.33 1113.42 2636.69 1113.42V1113.42C2626.05 1113.42 2617.43 1104.79 2617.43 1094.15V1094.15Z" fill="black"/> -</g> -<g id="Bold-M"> -<path id="Union_12" fill-rule="evenodd" clip-rule="evenodd" d="M2326.91 1040.53C2324.49 1040.53 2322.19 1041.63 2320.67 1043.53L2314.86 1050.78H2314.38C2309.92 1050.78 2307.69 1050.78 2305.82 1051.08C2295.55 1052.7 2287.5 1060.76 2285.87 1071.03C2285.58 1072.89 2285.58 1075.12 2285.58 1079.58V1108.72C2285.58 1113.18 2285.58 1115.41 2285.87 1117.28C2287.5 1127.55 2295.55 1135.6 2305.82 1137.23C2307.69 1137.52 2309.92 1137.52 2314.38 1137.52H2365.58C2370.04 1137.52 2372.27 1137.52 2374.13 1137.23C2384.4 1135.6 2392.45 1127.55 2394.08 1117.28C2394.38 1115.41 2394.38 1113.18 2394.38 1108.72V1079.58C2394.38 1075.12 2394.38 1072.89 2394.08 1071.03C2392.45 1060.76 2384.4 1052.7 2374.13 1051.08C2372.27 1050.78 2370.04 1050.78 2365.58 1050.78H2365.1L2359.28 1043.53C2357.76 1041.63 2355.47 1040.53 2353.04 1040.53H2326.91ZM2314.38 1063.28H2365.58C2370.51 1063.28 2371.53 1063.32 2372.18 1063.42C2377.1 1064.2 2380.96 1068.06 2381.73 1072.98C2381.84 1073.63 2381.88 1074.64 2381.88 1079.58V1108.72C2381.88 1113.66 2381.84 1114.67 2381.73 1115.32C2380.96 1120.24 2377.1 1124.1 2372.18 1124.88C2371.53 1124.98 2370.51 1125.02 2365.58 1125.02H2314.38C2309.44 1125.02 2308.43 1124.98 2307.78 1124.88C2302.86 1124.1 2299 1120.24 2298.22 1115.32C2298.11 1114.67 2298.08 1113.66 2298.08 1108.72V1079.58C2298.08 1074.64 2298.11 1073.63 2298.22 1072.98C2299 1068.06 2302.86 1064.2 2307.78 1063.42C2308.43 1063.32 2309.44 1063.28 2314.38 1063.28Z" fill="black"/> -<path id="Rectangle 11906_12" d="M2320.71 1094.15C2320.71 1083.51 2329.34 1074.88 2339.98 1074.88V1074.88C2350.62 1074.88 2359.24 1083.51 2359.24 1094.15V1094.15C2359.24 1104.79 2350.62 1113.41 2339.98 1113.41V1113.41C2329.34 1113.41 2320.71 1104.79 2320.71 1094.15V1094.15Z" fill="black"/> -</g> -<g id="Semibold-M"> -<path id="Union_13" fill-rule="evenodd" clip-rule="evenodd" d="M2030.2 1039.89C2027.78 1039.89 2025.48 1040.99 2023.96 1042.89L2018.15 1050.14H2016.47C2012.19 1050.14 2010.06 1050.14 2008.27 1050.43C1998.43 1051.99 1990.71 1059.71 1989.15 1069.55C1988.87 1071.33 1988.87 1073.47 1988.87 1077.74V1109.28C1988.87 1113.56 1988.87 1115.69 1989.15 1117.48C1990.71 1127.32 1998.43 1135.04 2008.27 1136.6C2010.06 1136.88 2012.19 1136.88 2016.47 1136.88H2070.07C2074.34 1136.88 2076.48 1136.88 2078.26 1136.6C2088.11 1135.04 2095.82 1127.32 2097.38 1117.48C2097.67 1115.69 2097.67 1113.56 2097.67 1109.28V1077.74C2097.67 1073.47 2097.67 1071.33 2097.38 1069.55C2095.82 1059.71 2088.11 1051.99 2078.26 1050.43C2076.48 1050.14 2074.34 1050.14 2070.07 1050.14H2068.39L2062.57 1042.89C2061.05 1040.99 2058.76 1039.89 2056.33 1039.89H2030.2ZM2016.47 1060.89H2070.07C2074.75 1060.89 2075.84 1060.93 2076.58 1061.05C2081.82 1061.88 2085.93 1065.99 2086.76 1071.23C2086.88 1071.97 2086.92 1073.06 2086.92 1077.74V1109.28C2086.92 1113.97 2086.88 1115.06 2086.76 1115.8C2085.93 1121.04 2081.82 1125.15 2076.58 1125.98C2075.84 1126.1 2074.75 1126.13 2070.07 1126.13H2016.47C2011.78 1126.13 2010.69 1126.1 2009.95 1125.98C2004.71 1125.15 2000.6 1121.04 1999.77 1115.8C1999.65 1115.06 1999.62 1113.97 1999.62 1109.28V1077.74C1999.62 1073.06 1999.65 1071.97 1999.77 1071.23C2000.6 1065.99 2004.71 1061.88 2009.95 1061.05C2010.69 1060.93 2011.78 1060.89 2016.47 1060.89Z" fill="black"/> -<path id="Rectangle 11906_13" d="M2024 1093.51C2024 1082.87 2032.63 1074.25 2043.27 1074.25V1074.25C2053.91 1074.25 2062.53 1082.87 2062.53 1093.51V1093.51C2062.53 1104.15 2053.91 1112.78 2043.27 1112.78V1112.78C2032.63 1112.78 2024 1104.15 2024 1093.51V1093.51Z" fill="black"/> -</g> -<g id="Medium-M"> -<path id="Union_14" fill-rule="evenodd" clip-rule="evenodd" d="M1733.49 1039.76C1731.06 1039.76 1728.77 1040.86 1727.25 1042.76L1721.43 1050.01H1717.35C1713.45 1050.01 1711.5 1050.01 1709.87 1050.27C1700.88 1051.69 1693.83 1058.74 1692.41 1067.73C1692.15 1069.36 1692.15 1071.31 1692.15 1075.21V1111.55C1692.15 1115.45 1692.15 1117.4 1692.41 1119.04C1693.83 1128.02 1700.88 1135.07 1709.87 1136.49C1711.5 1136.75 1713.45 1136.75 1717.35 1136.75H1775.75C1779.65 1136.75 1781.61 1136.75 1783.24 1136.49C1792.22 1135.07 1799.27 1128.02 1800.69 1119.04C1800.95 1117.4 1800.95 1115.45 1800.95 1111.55V1075.21C1800.95 1071.31 1800.95 1069.36 1800.69 1067.73C1799.27 1058.74 1792.22 1051.69 1783.24 1050.27C1781.61 1050.01 1779.65 1050.01 1775.75 1050.01H1771.67L1765.86 1042.76C1764.34 1040.86 1762.04 1039.76 1759.62 1039.76H1733.49ZM1717.35 1059.51H1775.75C1780.02 1059.51 1781.04 1059.54 1781.75 1059.65C1786.67 1060.43 1790.53 1064.29 1791.31 1069.21C1791.42 1069.92 1791.45 1070.95 1791.45 1075.21V1111.55C1791.45 1115.82 1791.42 1116.84 1791.31 1117.55C1790.53 1122.47 1786.67 1126.33 1781.75 1127.11C1781.04 1127.22 1780.02 1127.25 1775.75 1127.25H1717.35C1713.09 1127.25 1712.06 1127.22 1711.35 1127.11C1706.43 1126.33 1702.57 1122.47 1701.79 1117.55C1701.68 1116.84 1701.65 1115.82 1701.65 1111.55V1075.21C1701.65 1070.95 1701.68 1069.92 1701.79 1069.21C1702.57 1064.29 1706.43 1060.43 1711.35 1059.65C1712.06 1059.54 1713.09 1059.51 1717.35 1059.51Z" fill="black"/> -<path id="Rectangle 11906_14" d="M1727.29 1093.38C1727.29 1082.74 1735.91 1074.11 1746.55 1074.11V1074.11C1757.19 1074.11 1765.82 1082.74 1765.82 1093.38V1093.38C1765.82 1104.02 1757.19 1112.64 1746.55 1112.64V1112.64C1735.91 1112.64 1727.29 1104.02 1727.29 1093.38V1093.38Z" fill="black"/> -</g> -<g id="Regular-M"> -<path id="Union_15" fill-rule="evenodd" clip-rule="evenodd" d="M1436.78 1039.77C1434.35 1039.77 1432.06 1040.87 1430.54 1042.77L1424.72 1050.02H1418.24C1414.71 1050.02 1412.95 1050.02 1411.47 1050.26C1403.34 1051.55 1396.96 1057.92 1395.68 1066.05C1395.44 1067.53 1395.44 1069.29 1395.44 1072.82V1113.96C1395.44 1117.49 1395.44 1119.26 1395.68 1120.74C1396.96 1128.87 1403.34 1135.24 1411.47 1136.53C1412.95 1136.76 1414.71 1136.76 1418.24 1136.76H1481.44C1484.97 1136.76 1486.74 1136.76 1488.21 1136.53C1496.34 1135.24 1502.72 1128.87 1504.01 1120.74C1504.24 1119.26 1504.24 1117.49 1504.24 1113.96V1072.82C1504.24 1069.29 1504.24 1067.53 1504.01 1066.05C1502.72 1057.92 1496.34 1051.55 1488.21 1050.26C1486.74 1050.02 1484.97 1050.02 1481.44 1050.02H1474.96L1469.15 1042.77C1467.63 1040.87 1465.33 1039.77 1462.9 1039.77H1436.78ZM1418.24 1058.02H1481.44C1485.28 1058.02 1486.26 1058.05 1486.96 1058.16C1491.67 1058.9 1495.36 1062.6 1496.11 1067.3C1496.22 1068 1496.24 1068.99 1496.24 1072.82V1113.96C1496.24 1117.8 1496.22 1118.79 1496.11 1119.48C1495.36 1124.19 1491.67 1127.88 1486.96 1128.63C1486.26 1128.74 1485.28 1128.76 1481.44 1128.76H1418.24C1414.41 1128.76 1413.42 1128.74 1412.72 1128.63C1408.01 1127.88 1404.32 1124.19 1403.58 1119.48C1403.47 1118.79 1403.44 1117.8 1403.44 1113.96V1072.82C1403.44 1068.99 1403.47 1068 1403.58 1067.3C1404.32 1062.6 1408.01 1058.9 1412.72 1058.16C1413.42 1058.05 1414.41 1058.02 1418.24 1058.02Z" fill="black"/> -<path id="Rectangle 11906_15" d="M1430.58 1093.39C1430.58 1082.75 1439.2 1074.12 1449.84 1074.12V1074.12C1460.48 1074.12 1469.11 1082.75 1469.11 1093.39V1093.39C1469.11 1104.03 1460.48 1112.66 1449.84 1112.66V1112.66C1439.2 1112.66 1430.58 1104.03 1430.58 1093.39V1093.39Z" fill="black"/> -</g> -<g id="Light-M"> -<path id="Union_16" fill-rule="evenodd" clip-rule="evenodd" d="M1140.07 1040.96C1137.64 1040.96 1135.34 1042.06 1133.83 1043.95L1128.01 1051.21H1119.13C1115.97 1051.21 1114.39 1051.21 1113.07 1051.42C1105.8 1052.57 1100.09 1058.28 1098.94 1065.55C1098.73 1066.87 1098.73 1068.45 1098.73 1071.61V1117.55C1098.73 1120.71 1098.73 1122.29 1098.94 1123.61C1100.09 1130.88 1105.8 1136.59 1113.07 1137.74C1114.39 1137.95 1115.97 1137.95 1119.13 1137.95H1187.13C1190.29 1137.95 1191.87 1137.95 1193.19 1137.74C1200.47 1136.59 1206.17 1130.88 1207.32 1123.61C1207.53 1122.29 1207.53 1120.71 1207.53 1117.55V1071.61C1207.53 1068.45 1207.53 1066.87 1207.32 1065.55C1206.17 1058.28 1200.47 1052.57 1193.19 1051.42C1191.87 1051.21 1190.29 1051.21 1187.13 1051.21H1178.25L1172.44 1043.95C1170.92 1042.06 1168.62 1040.96 1166.19 1040.96H1140.07ZM1119.13 1057.21H1187.13C1190.52 1057.21 1191.51 1057.23 1192.25 1057.35C1196.96 1058.09 1200.65 1061.78 1201.4 1066.49C1201.51 1067.23 1201.53 1068.22 1201.53 1071.61V1117.55C1201.53 1120.94 1201.51 1121.93 1201.4 1122.67C1200.65 1127.38 1196.96 1131.07 1192.25 1131.82C1191.51 1131.93 1190.52 1131.95 1187.13 1131.95H1119.13C1115.74 1131.95 1114.75 1131.93 1114.01 1131.82C1109.3 1131.07 1105.61 1127.38 1104.87 1122.67C1104.75 1121.93 1104.73 1120.94 1104.73 1117.55V1071.61C1104.73 1068.22 1104.75 1067.23 1104.87 1066.49C1105.61 1061.78 1109.3 1058.09 1114.01 1057.35C1114.75 1057.23 1115.74 1057.21 1119.13 1057.21Z" fill="black"/> -<path id="Rectangle 11906_16" d="M1133.87 1094.58C1133.87 1083.94 1142.49 1075.31 1153.13 1075.31V1075.31C1163.77 1075.31 1172.4 1083.94 1172.4 1094.58V1094.58C1172.4 1105.22 1163.77 1113.84 1153.13 1113.84V1113.84C1142.49 1113.84 1133.87 1105.22 1133.87 1094.58V1094.58Z" fill="black"/> -</g> -<g id="Thin-M"> -<path id="Union_17" fill-rule="evenodd" clip-rule="evenodd" d="M843.36 1040.88C840.932 1040.88 838.635 1041.99 837.117 1043.88L830.899 1051.64H821.222C818.249 1051.64 816.763 1051.64 815.519 1051.84C808.673 1052.92 803.303 1058.29 802.219 1065.14C802.022 1066.38 802.022 1067.87 802.022 1070.84V1118.18C802.022 1121.15 802.022 1122.64 802.219 1123.88C803.303 1130.73 808.673 1136.1 815.519 1137.18C816.763 1137.38 818.249 1137.38 821.222 1137.38H891.622C894.595 1137.38 896.081 1137.38 897.325 1137.18C904.171 1136.1 909.541 1130.73 910.625 1123.88C910.822 1122.64 910.822 1121.15 910.822 1118.18V1070.84C910.822 1067.87 910.822 1066.38 910.625 1065.14C909.541 1058.29 904.171 1052.92 897.325 1051.84C896.081 1051.64 894.595 1051.64 891.622 1051.64H881.945L875.727 1043.88C874.209 1041.99 871.912 1040.88 869.484 1040.88H843.36ZM821.222 1055.64H891.622C894.748 1055.64 895.845 1055.65 896.699 1055.79C901.834 1056.6 905.861 1060.63 906.674 1065.76C906.81 1066.62 906.822 1067.71 906.822 1070.84V1118.18C906.822 1121.31 906.81 1122.4 906.674 1123.26C905.861 1128.39 901.834 1132.42 896.699 1133.23C895.845 1133.37 894.748 1133.38 891.622 1133.38H821.222C818.096 1133.38 816.999 1133.37 816.145 1133.23C811.01 1132.42 806.983 1128.39 806.17 1123.26C806.034 1122.4 806.022 1121.31 806.022 1118.18V1070.84C806.022 1067.71 806.034 1066.62 806.17 1065.76C806.983 1060.63 811.01 1056.6 816.145 1055.79C816.999 1055.65 818.096 1055.64 821.222 1055.64Z" fill="black"/> -<path id="Rectangle 11906_17" d="M837.157 1094.5C837.157 1083.86 845.782 1075.24 856.422 1075.24V1075.24C867.062 1075.24 875.687 1083.86 875.687 1094.5V1094.5C875.687 1105.14 867.062 1113.77 856.422 1113.77V1113.77C845.782 1113.77 837.157 1105.14 837.157 1094.5V1094.5Z" fill="black"/> -</g> -<g id="Ultralight-M"> -<path id="Union_18" fill-rule="evenodd" clip-rule="evenodd" d="M546.649 1040.88C544.221 1040.88 541.924 1041.99 540.406 1043.88L533.788 1052.14H523.312C520.525 1052.14 519.131 1052.14 517.965 1052.33C511.547 1053.34 506.513 1058.38 505.496 1064.79C505.312 1065.96 505.312 1067.35 505.312 1070.14V1118.88C505.312 1121.67 505.312 1123.06 505.496 1124.23C506.513 1130.65 511.547 1135.68 517.965 1136.7C519.131 1136.88 520.525 1136.88 523.312 1136.88H596.112C598.899 1136.88 600.292 1136.88 601.458 1136.7C607.876 1135.68 612.91 1130.65 613.927 1124.23C614.112 1123.06 614.112 1121.67 614.112 1118.88V1070.14C614.112 1067.35 614.112 1065.96 613.927 1064.79C612.91 1058.38 607.876 1053.34 601.458 1052.33C600.292 1052.14 598.899 1052.14 596.112 1052.14H585.635L579.017 1043.88C577.499 1041.99 575.202 1040.88 572.774 1040.88H546.649ZM523.312 1054.39H596.112C598.985 1054.39 600.159 1054.4 601.106 1054.55C606.562 1055.41 610.84 1059.69 611.705 1065.15C611.855 1066.09 611.862 1067.27 611.862 1070.14V1118.88C611.862 1121.75 611.855 1122.93 611.705 1123.88C610.84 1129.33 606.562 1133.61 601.106 1134.47C600.159 1134.62 598.985 1134.63 596.112 1134.63H523.312C520.439 1134.63 519.264 1134.62 518.317 1134.47C512.861 1133.61 508.583 1129.33 507.718 1123.88C507.569 1122.93 507.562 1121.75 507.562 1118.88V1070.14C507.562 1067.27 507.569 1066.09 507.718 1065.15C508.583 1059.69 512.861 1055.41 518.317 1054.55C519.264 1054.4 520.439 1054.39 523.312 1054.39Z" fill="black"/> -<path id="Rectangle 11906_18" d="M540.446 1094.5C540.446 1083.86 549.072 1075.24 559.711 1075.24V1075.24C570.351 1075.24 578.977 1083.86 578.977 1094.5V1094.5C578.977 1105.14 570.351 1113.77 559.711 1113.77V1113.77C549.072 1113.77 540.446 1105.14 540.446 1094.5V1094.5Z" fill="black"/> -</g> -<g id="Black-S"> -<path id="Union_19" fill-rule="evenodd" clip-rule="evenodd" d="M2923.67 619.23C2921.24 619.23 2918.94 620.333 2917.42 622.228L2913.23 627.461H2909.72C2898.68 627.461 2889.72 636.415 2889.72 647.461V677.097C2889.72 688.143 2898.68 697.097 2909.72 697.097H2957.07C2968.12 697.097 2977.07 688.143 2977.07 677.097V647.461C2977.07 636.415 2968.12 627.461 2957.07 627.461H2953.56L2949.37 622.228C2947.85 620.333 2945.55 619.23 2943.13 619.23H2923.67ZM2909.72 641.461H2957.07C2960.38 641.461 2963.07 644.147 2963.07 647.461V677.097C2963.07 680.411 2960.38 683.097 2957.07 683.097H2909.72C2906.41 683.097 2903.72 680.411 2903.72 677.097V647.461C2903.72 644.147 2906.41 641.461 2909.72 641.461Z" fill="black"/> -<path id="Rectangle 11906_19" d="M2917.93 662.279C2917.93 653.737 2924.85 646.812 2933.4 646.812V646.812C2941.94 646.812 2948.86 653.737 2948.86 662.279V662.279C2948.86 670.821 2941.94 677.745 2933.4 677.745V677.745C2924.85 677.745 2917.93 670.821 2917.93 662.279V662.279Z" fill="black"/> -</g> -<g id="Heavy-S"> -<path id="Union_20" fill-rule="evenodd" clip-rule="evenodd" d="M2626.96 619.668C2624.54 619.668 2622.24 620.771 2620.72 622.666L2616.53 627.898H2612.02C2601.53 627.898 2593.02 636.405 2593.02 646.898V678.535C2593.02 689.028 2601.53 697.535 2612.02 697.535H2661.37C2671.86 697.535 2680.37 689.028 2680.37 678.535V646.898C2680.37 636.405 2671.86 627.898 2661.37 627.898H2656.86L2652.67 622.666C2651.15 620.771 2648.85 619.668 2646.42 619.668H2626.96ZM2612.02 640.398H2661.37C2664.96 640.398 2667.87 643.309 2667.87 646.898V678.535C2667.87 682.124 2664.96 685.035 2661.37 685.035H2612.02C2608.43 685.035 2605.52 682.124 2605.52 678.535V646.898C2605.52 643.309 2608.43 640.398 2612.02 640.398Z" fill="black"/> -<path id="Rectangle 11906_20" d="M2621.23 662.716C2621.23 654.174 2628.15 647.25 2636.69 647.25V647.25C2645.24 647.25 2652.16 654.174 2652.16 662.716V662.716C2652.16 671.258 2645.24 678.183 2636.69 678.183V678.183C2628.15 678.183 2621.23 671.258 2621.23 662.716V662.716Z" fill="black"/> -</g> -<g id="Bold-S"> -<path id="Union_21" fill-rule="evenodd" clip-rule="evenodd" d="M2330.25 619.688C2327.82 619.688 2325.53 620.79 2324.01 622.685L2319.82 627.918H2314.31C2304.37 627.918 2296.31 635.977 2296.31 645.918V679.554C2296.31 689.495 2304.37 697.554 2314.31 697.554H2365.65C2375.6 697.554 2383.65 689.495 2383.65 679.554V645.918C2383.65 635.977 2375.6 627.918 2365.65 627.918H2360.15L2355.95 622.685C2354.44 620.79 2352.14 619.688 2349.71 619.688H2330.25ZM2314.31 638.418H2365.65C2369.8 638.418 2373.15 641.776 2373.15 645.918V679.554C2373.15 683.696 2369.8 687.054 2365.65 687.054H2314.31C2310.17 687.054 2306.81 683.696 2306.81 679.554V645.918C2306.81 641.776 2310.17 638.418 2314.31 638.418Z" fill="black"/> -<path id="Rectangle 11906_21" d="M2324.52 662.736C2324.52 654.194 2331.44 647.27 2339.98 647.27V647.27C2348.52 647.27 2355.45 654.194 2355.45 662.736V662.736C2355.45 671.278 2348.52 678.202 2339.98 678.202V678.202C2331.44 678.202 2324.52 671.278 2324.52 662.736V662.736Z" fill="black"/> -</g> -<g id="Semibold-S"> -<path id="Union_22" fill-rule="evenodd" clip-rule="evenodd" d="M2033.54 620.664C2031.11 620.664 2028.82 621.767 2027.3 623.662L2023.11 628.895H2016.6C2007.21 628.895 1999.6 636.506 1999.6 645.895V681.531C1999.6 690.919 2007.21 698.531 2016.6 698.531H2069.95C2079.33 698.531 2086.95 690.919 2086.95 681.531V645.895C2086.95 636.506 2079.33 628.895 2069.95 628.895H2063.44L2059.24 623.662C2057.73 621.767 2055.43 620.664 2053 620.664H2033.54ZM2016.6 638.145H2069.95C2074.23 638.145 2077.7 641.614 2077.7 645.895V681.531C2077.7 685.811 2074.23 689.281 2069.95 689.281H2016.6C2012.32 689.281 2008.85 685.811 2008.85 681.531V645.895C2008.85 641.614 2012.32 638.145 2016.6 638.145Z" fill="black"/> -<path id="Rectangle 11906_22" d="M2027.81 663.712C2027.81 655.171 2034.73 648.246 2043.27 648.246V648.246C2051.81 648.246 2058.74 655.171 2058.74 663.712V663.712C2058.74 672.254 2051.81 679.179 2043.27 679.179V679.179C2034.73 679.179 2027.81 672.254 2027.81 663.712V663.712Z" fill="black"/> -</g> -<g id="Medium-S"> -<path id="Union_23" fill-rule="evenodd" clip-rule="evenodd" d="M1736.83 620.617C1734.4 620.617 1732.1 621.72 1730.58 623.615L1726.39 628.848H1718.88C1710.05 628.848 1702.88 636.011 1702.88 644.848V682.484C1702.88 691.32 1710.05 698.484 1718.88 698.484H1774.23C1783.07 698.484 1790.23 691.32 1790.23 682.484V644.848C1790.23 636.011 1783.07 628.848 1774.23 628.848H1766.72L1762.53 623.615C1761.01 621.72 1758.71 620.617 1756.29 620.617H1736.83ZM1718.88 637.098H1774.23C1778.51 637.098 1781.98 640.567 1781.98 644.848V682.484C1781.98 686.764 1778.51 690.234 1774.23 690.234H1718.88C1714.6 690.234 1711.13 686.764 1711.13 682.484V644.848C1711.13 640.567 1714.6 637.098 1718.88 637.098Z" fill="black"/> -<path id="Rectangle 11906_23" d="M1731.09 663.666C1731.09 655.124 1738.01 648.199 1746.56 648.199V648.199C1755.1 648.199 1762.02 655.124 1762.02 663.666V663.666C1762.02 672.207 1755.1 679.132 1746.56 679.132V679.132C1738.01 679.132 1731.09 672.207 1731.09 663.666V663.666Z" fill="black"/> -</g> -<g id="Regular-S"> -<path id="Union_24" fill-rule="evenodd" clip-rule="evenodd" d="M1440.12 620.77C1437.69 620.77 1435.39 621.872 1433.87 623.767L1429.68 629H1421.17C1412.89 629 1406.17 635.716 1406.17 644V683.636C1406.17 691.92 1412.89 698.636 1421.17 698.636H1478.52C1486.8 698.636 1493.52 691.92 1493.52 683.636V644C1493.52 635.716 1486.8 629 1478.52 629H1470.01L1465.82 623.767C1464.3 621.872 1462 620.77 1459.58 620.77H1440.12ZM1421.17 636.15H1478.52C1482.86 636.15 1486.37 639.665 1486.37 644V683.636C1486.37 687.972 1482.86 691.486 1478.52 691.486H1421.17C1416.84 691.486 1413.32 687.972 1413.32 683.636V644C1413.32 639.665 1416.84 636.15 1421.17 636.15Z" fill="black"/> -<path id="Rectangle 11906_24" d="M1434.38 663.818C1434.38 655.276 1441.31 648.352 1449.85 648.352V648.352C1458.39 648.352 1465.31 655.276 1465.31 663.818V663.818C1465.31 672.36 1458.39 679.284 1449.85 679.284V679.284C1441.31 679.284 1434.38 672.36 1434.38 663.818V663.818Z" fill="black"/> -</g> -<g id="Light-S"> -<path id="Union_25" fill-rule="evenodd" clip-rule="evenodd" d="M1143.41 620.668C1140.98 620.668 1138.68 621.771 1137.17 623.666L1132.97 628.898H1123.46C1115.73 628.898 1109.46 635.166 1109.46 642.898V684.535C1109.46 692.267 1115.73 698.535 1123.46 698.535H1182.81C1190.54 698.535 1196.81 692.267 1196.81 684.535V642.898C1196.81 635.166 1190.54 628.898 1182.81 628.898H1173.3L1169.11 623.666C1167.59 621.771 1165.3 620.668 1162.87 620.668H1143.41ZM1123.46 634.398H1182.81C1187.51 634.398 1191.31 638.204 1191.31 642.898V684.535C1191.31 689.229 1187.51 693.035 1182.81 693.035H1123.46C1118.77 693.035 1114.96 689.229 1114.96 684.535V642.898C1114.96 638.204 1118.77 634.398 1123.46 634.398Z" fill="black"/> -<path id="Rectangle 11906_25" d="M1137.67 663.716C1137.67 655.174 1144.6 648.25 1153.14 648.25V648.25C1161.68 648.25 1168.6 655.174 1168.6 663.716V663.716C1168.6 672.258 1161.68 679.183 1153.14 679.183V679.183C1144.6 679.183 1137.67 672.258 1137.67 663.716V663.716Z" fill="black"/> -</g> -<g id="Thin-S"> -<path id="Union_26" fill-rule="evenodd" clip-rule="evenodd" d="M846.693 620.742C844.265 620.742 841.968 621.845 840.45 623.74L836.257 628.973H825.749C818.569 628.973 812.749 634.793 812.749 641.973V685.609C812.749 692.788 818.569 698.609 825.749 698.609H887.095C894.275 698.609 900.095 692.788 900.095 685.609V641.973C900.095 634.793 894.275 628.973 887.095 628.973H876.587L872.394 623.74C870.876 621.845 868.579 620.742 866.151 620.742H846.693ZM825.749 632.223H887.095C892.48 632.223 896.845 636.588 896.845 641.973V685.609C896.845 690.994 892.48 695.359 887.095 695.359H825.749C820.364 695.359 815.999 690.994 815.999 685.609V641.973C815.999 636.588 820.364 632.223 825.749 632.223Z" fill="black"/> -<path id="Rectangle 11906_26" d="M840.956 663.791C840.956 655.249 847.88 648.324 856.422 648.324V648.324C864.964 648.324 871.888 655.249 871.888 663.791V663.791C871.888 672.332 864.964 679.257 856.422 679.257V679.257C847.88 679.257 840.956 672.332 840.956 663.791V663.791Z" fill="black"/> -</g> -<g id="Ultralight-S"> -<path id="Union_27" fill-rule="evenodd" clip-rule="evenodd" d="M549.983 620.762C547.555 620.762 545.258 621.865 543.74 623.759L539.14 629.5H528.039C521.411 629.5 516.039 634.873 516.039 641.5V685.14C516.039 691.767 521.411 697.14 528.039 697.14H591.385C598.012 697.14 603.385 691.767 603.385 685.14V641.5C603.385 634.873 598.012 629.5 591.385 629.5H580.284L575.684 623.759C574.166 621.865 571.869 620.762 569.441 620.762H549.983ZM528.039 631.5H591.385C596.908 631.5 601.385 635.977 601.385 641.5V685.14C601.385 690.663 596.908 695.14 591.385 695.14H528.039C522.516 695.14 518.039 690.663 518.039 685.14V641.5C518.039 635.977 522.516 631.5 528.039 631.5Z" fill="black"/> -<path id="Rectangle 11906_27" d="M544.245 663.81C544.245 655.268 551.17 648.344 559.711 648.344V648.344C568.253 648.344 575.178 655.268 575.178 663.81V663.81C575.178 672.352 568.253 679.276 559.711 679.276V679.276C551.17 679.276 544.245 672.352 544.245 663.81V663.81Z" fill="black"/> -</g> -</g> -</g> +<?xml version="1.0" encoding="UTF-8"?> +<!--Generator: Apple Native CoreSVG 175.5--> +<!DOCTYPE svg +PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> +<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3300" height="2200"> + <!--glyph: "", point size: 100.0, font version: "18.0d12e2", template writer version: "101"--> + <style>.multicolor-0:custom {fill:#EA4335} +.multicolor-1:custom {fill:#34A853} +.multicolor-2:custom {fill:#4183F0} +.multicolor-3:custom {fill:#FBBC04} + +.hierarchical-0:primary {fill:#212121} +.hierarchical-1:secondary {fill:#4D4D4D} +.hierarchical-2:primary {fill:#212121} +.hierarchical-3:primary {fill:#212121} + +.SFSymbolsPreview34A853 {fill:#34A853;opacity:1.0} +.SFSymbolsPreview4183F0 {fill:#4183F0;opacity:1.0} +.SFSymbolsPreviewEA4335 {fill:#EA4335;opacity:1.0} +.SFSymbolsPreviewFBBC04 {fill:#FBBC04;opacity:1.0} +</style> + <g id="Notes"> + <rect height="2200" id="artboard" style="fill:white;opacity:1" width="3300" x="0" y="0"/> + <line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="292" y2="292"/> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 322)">Weight/Scale Variations</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 559.711 322)">Ultralight</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 856.422 322)">Thin</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1153.13 322)">Light</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1449.84 322)">Regular</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 1746.56 322)">Medium</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2043.27 322)">Semibold</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2339.98 322)">Bold</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2636.69 322)">Heavy</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:middle;" transform="matrix(1 0 0 1 2933.4 322)">Black</text> + <line style="fill:none;stroke:black;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1903" y2="1903"/> + <g transform="matrix(1 0 0 1 263 1933)"> + <path d="M9.24805 0.830078C13.5547 0.830078 17.1387-2.74414 17.1387-7.05078C17.1387-11.3574 13.5449-14.9316 9.23828-14.9316C4.94141-14.9316 1.36719-11.3574 1.36719-7.05078C1.36719-2.74414 4.95117 0.830078 9.24805 0.830078ZM9.24805-0.654297C5.70312-0.654297 2.87109-3.49609 2.87109-7.05078C2.87109-10.6055 5.69336-13.4473 9.23828-13.4473C12.793-13.4473 15.6445-10.6055 15.6445-7.05078C15.6445-3.49609 12.8027-0.654297 9.24805-0.654297ZM5.6543-7.05078C5.6543-6.62109 5.95703-6.32812 6.40625-6.32812L8.50586-6.32812L8.50586-4.20898C8.50586-3.76953 8.79883-3.4668 9.22852-3.4668C9.67773-3.4668 9.9707-3.76953 9.9707-4.20898L9.9707-6.32812L12.0898-6.32812C12.5293-6.32812 12.832-6.62109 12.832-7.05078C12.832-7.49023 12.5293-7.79297 12.0898-7.79297L9.9707-7.79297L9.9707-9.90234C9.9707-10.3516 9.67773-10.6543 9.22852-10.6543C8.79883-10.6543 8.50586-10.3516 8.50586-9.90234L8.50586-7.79297L6.40625-7.79297C5.95703-7.79297 5.6543-7.49023 5.6543-7.05078Z"/> + </g> + <g transform="matrix(1 0 0 1 281.867 1933)"> + <path d="M11.709 2.91016C17.1582 2.91016 21.6699-1.61133 21.6699-7.05078C21.6699-12.5 17.1484-17.0117 11.6992-17.0117C6.25977-17.0117 1.74805-12.5 1.74805-7.05078C1.74805-1.61133 6.26953 2.91016 11.709 2.91016ZM11.709 1.25C7.09961 1.25 3.41797-2.44141 3.41797-7.05078C3.41797-11.6602 7.08984-15.3516 11.6992-15.3516C16.3086-15.3516 20.0098-11.6602 20.0098-7.05078C20.0098-2.44141 16.3184 1.25 11.709 1.25ZM7.17773-7.05078C7.17773-6.57227 7.50977-6.25 8.00781-6.25L10.8789-6.25L10.8789-3.36914C10.8789-2.88086 11.2109-2.53906 11.6895-2.53906C12.1777-2.53906 12.5195-2.87109 12.5195-3.36914L12.5195-6.25L15.4004-6.25C15.8887-6.25 16.2305-6.57227 16.2305-7.05078C16.2305-7.53906 15.8887-7.88086 15.4004-7.88086L12.5195-7.88086L12.5195-10.752C12.5195-11.25 12.1777-11.5918 11.6895-11.5918C11.2109-11.5918 10.8789-11.25 10.8789-10.752L10.8789-7.88086L8.00781-7.88086C7.50977-7.88086 7.17773-7.53906 7.17773-7.05078Z"/> + </g> + <g transform="matrix(1 0 0 1 305.646 1933)"> + <path d="M14.9707 5.66406C21.9336 5.66406 27.6953-0.0976562 27.6953-7.05078C27.6953-14.0137 21.9238-19.7754 14.9609-19.7754C8.00781-19.7754 2.25586-14.0137 2.25586-7.05078C2.25586-0.0976562 8.01758 5.66406 14.9707 5.66406ZM14.9707 3.84766C8.93555 3.84766 4.08203-1.01562 4.08203-7.05078C4.08203-13.0957 8.92578-17.9492 14.9609-17.9492C21.0059-17.9492 25.8691-13.0957 25.8691-7.05078C25.8691-1.01562 21.0156 3.84766 14.9707 3.84766ZM9.19922-7.05078C9.19922-6.5332 9.57031-6.17188 10.1172-6.17188L14.0625-6.17188L14.0625-2.2168C14.0625-1.67969 14.4336-1.29883 14.9512-1.29883C15.4883-1.29883 15.8594-1.66992 15.8594-2.2168L15.8594-6.17188L19.8145-6.17188C20.3516-6.17188 20.7324-6.5332 20.7324-7.05078C20.7324-7.59766 20.3613-7.96875 19.8145-7.96875L15.8594-7.96875L15.8594-11.9141C15.8594-12.4609 15.4883-12.8418 14.9512-12.8418C14.4336-12.8418 14.0625-12.4609 14.0625-11.9141L14.0625-7.96875L10.1172-7.96875C9.57031-7.96875 9.19922-7.59766 9.19922-7.05078Z"/> + </g> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 263 1953)">Design Variations</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1971)">Symbols are supported in up to nine weights and three scales.</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1989)">For optimal layout with text and other symbols, vertically align</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 2007)">symbols with the adjacent text.</text> + <line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="776" x2="776" y1="1919" y2="1933"/> + <g transform="matrix(1 0 0 1 776 1933)"> + <path d="M3.31055 0.15625C3.82812 0.15625 4.08203-0.0390625 4.26758-0.585938L5.52734-4.0332L11.2891-4.0332L12.5488-0.585938C12.7344-0.0390625 12.9883 0.15625 13.4961 0.15625C14.0137 0.15625 14.3457-0.15625 14.3457-0.644531C14.3457-0.810547 14.3164-0.966797 14.2383-1.17188L9.6582-13.3691C9.43359-13.9648 9.0332-14.2676 8.4082-14.2676C7.80273-14.2676 7.39258-13.9746 7.17773-13.3789L2.59766-1.16211C2.51953-0.957031 2.49023-0.800781 2.49023-0.634766C2.49023-0.146484 2.80273 0.15625 3.31055 0.15625ZM6.00586-5.51758L8.37891-12.0898L8.42773-12.0898L10.8008-5.51758Z"/> + </g> + <line style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="793.197" x2="793.197" y1="1919" y2="1933"/> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 776 1953)">Margins</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1971)">Leading and trailing margins on the left and right side of each symbol</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 1989)">can be adjusted by modifying the x-location of the margin guidelines.</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2007)">Modifications are automatically applied proportionally to all</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 776 2025)">scales and weights.</text> + <g transform="matrix(1 0 0 1 1289 1933)"> + <path d="M2.8418 1.86523L4.54102 3.57422C5.40039 4.44336 6.38672 4.38477 7.31445 3.35938L18.0078-8.42773L17.041-9.4043L6.42578 2.27539C6.07422 2.67578 5.74219 2.77344 5.27344 2.30469L4.10156 1.14258C3.63281 0.683594 3.74023 0.341797 4.14062-0.0195312L15.6152-10.8203L14.6387-11.7871L3.04688-0.898438C2.06055 0.0195312 1.98242 0.996094 2.8418 1.86523ZM9.25781-16.3281C8.83789-15.918 8.80859-15.3418 9.04297-14.9512C9.27734-14.5898 9.73633-14.3555 10.3809-14.5215C11.8457-14.8633 13.3691-14.9219 14.7949-13.9844L14.209-12.5293C13.8672-11.6992 14.043-11.1133 14.5801-10.5664L16.875-8.25195C17.3633-7.76367 17.7734-7.74414 18.3398-7.8418L19.4043-8.03711L20.0684-7.36328L20.0293-6.80664C19.9902-6.30859 20.1172-5.92773 20.6055-5.44922L21.3672-4.70703C21.8457-4.22852 22.4609-4.19922 22.9297-4.66797L25.8398-7.58789C26.3086-8.05664 26.2891-8.65234 25.8105-9.13086L25.0391-9.89258C24.5605-10.3711 24.1895-10.5273 23.7109-10.4883L23.1348-10.4395L22.4902-11.0742L22.7344-12.1973C22.8613-12.7637 22.7051-13.2031 22.1191-13.7891L19.9219-15.9766C16.582-19.2969 12.1484-19.2188 9.25781-16.3281ZM10.752-15.957C13.1836-17.7344 16.4746-17.4316 18.7012-15.2051L21.1328-12.793C21.3672-12.5586 21.4062-12.373 21.3379-12.0312L21.0156-10.5469L22.5195-9.0625L23.5059-9.12109C23.7598-9.13086 23.8379-9.11133 24.0332-8.91602L24.6094-8.33984L22.168-5.89844L21.5918-6.47461C21.3965-6.66992 21.3672-6.74805 21.377-7.01172L21.4453-7.98828L19.9512-9.47266L18.4277-9.21875C18.1055-9.15039 17.959-9.17969 17.7148-9.41406L15.7129-11.416C15.459-11.6504 15.4297-11.8164 15.5859-12.1875L16.4648-14.2773C14.9023-15.7324 12.8711-16.3574 10.8398-15.7617C10.6836-15.7227 10.625-15.8496 10.752-15.957Z"/> + </g> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;font-weight:bold;" transform="matrix(1 0 0 1 1289 1953)">Exporting</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1971)">Symbols should be outlined when exporting to ensure the</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 1289 1989)">design is preserved when submitting to Xcode.</text> + <text id="template-version" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1933)">Template v.3.0</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1951)">Requires Xcode 13 or greater</text> + <text id="descriptive-name" style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1969)">Generated from lens.cr</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;text-anchor:end;" transform="matrix(1 0 0 1 3036 1987)">Typeset at 100 points</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 726)">Small</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1156)">Medium</text> + <text style="stroke:none;fill:black;font-family:sans-serif;font-size:13;" transform="matrix(1 0 0 1 263 1586)">Large</text> + </g> + <g id="Guides"> + <g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 696)"> + <path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/> + </g> + <line id="Baseline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="696" y2="696"/> + <line id="Capline-S" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="625.541" y2="625.541"/> + <g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1126)"> + <path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/> + </g> + <line id="Baseline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1126" y2="1126"/> + <line id="Capline-M" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1055.54" y2="1055.54"/> + <g id="H-reference" style="fill:#27AAE1;stroke:none;" transform="matrix(1 0 0 1 339 1556)"> + <path d="M0.993654 0L3.63775 0L29.3281-67.1323L30.0303-67.1323L30.0303-70.459L28.1226-70.459ZM11.6885-24.4799L46.9815-24.4799L46.2315-26.7285L12.4385-26.7285ZM55.1196 0L57.7637 0L30.6382-70.459L29.4326-70.459L29.4326-67.1323Z"/> + </g> + <line id="Baseline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1556" y2="1556"/> + <line id="Capline-L" style="fill:none;stroke:#27AAE1;opacity:1;stroke-width:0.5;" x1="263" x2="3036" y1="1485.54" y2="1485.54"/> + <line id="left-margin-Regular-M" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1377.43" x2="1377.43" y1="1030.79" y2="1150.12"/> + <line id="right-margin-Regular-M" style="fill:none;stroke:#00AEEF;stroke-width:0.5;opacity:1.0;" x1="1522.26" x2="1522.26" y1="1030.79" y2="1150.12"/> + </g> + <g id="Symbols"> + <g id="Black-L" transform="matrix(1 0 0 1 2840.68 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M31.8791-16.84C26.3291-16.84 21.7791-12.32 22.0191-6.78C22.3591 1 23.2491 6.28 25.5091 10.73C28.7691 17.13 33.9691 22.33 40.3691 25.59C47.6391 29.29 57.1591 29.29 76.1991 29.29L84.3191 29.29C89.8391 29.29 94.3191 24.82 94.3191 19.29C94.3191 13.77 89.8391 9.29 84.3191 9.29L76.1991 9.29C66.3491 9.29 60.1691 9.28 55.4991 8.9C51.0691 8.53 49.7991 7.94 49.4491 7.77C46.8091 6.42 44.6691 4.28 43.3291 1.65C43.1491 1.3 42.5591 0.03 42.1991-4.41C42.1391-5.19 42.0791-6.02 42.0391-6.89C41.7591-12.39 37.3791-16.84 31.8791-16.84Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M156.359 6.50485L156.359 6.5049C156.359 15.2226 149.292 22.2897 140.574 22.2897L140.574 22.2897C131.856 22.2897 124.789 15.2226 124.789 6.5049L124.789 6.5048C124.789-2.2129 131.856-9.28 140.574-9.28L140.574-9.28C149.292-9.28 156.359-2.2129 156.359 6.5048Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M76.2391-105.7C72.2991-105.7 68.5691-103.91 66.0991-100.83L58.0191-90.75C50.1591-90.41 44.8391-89.53 40.3691-87.26C33.9691-84 28.7691-78.79 25.5091-72.4C23.2491-67.95 22.3591-62.67 22.0191-54.9C21.7791-49.36 26.3291-44.84 31.8791-44.84C37.3791-44.84 41.7591-49.29 42.0391-54.78C42.0791-55.66 42.1391-56.48 42.1991-57.26C42.5591-61.7 43.1491-62.97 43.3291-63.32C44.6691-65.95 46.8091-68.09 49.4491-69.44C49.7891-69.61 51.0691-70.2 55.4991-70.56C60.1691-70.95 66.3491-70.96 76.1991-70.96L109.219-70.96C119.069-70.96 125.259-70.95 129.929-70.56C134.359-70.2 135.629-69.61 135.979-69.44C138.609-68.09 140.759-65.95 142.099-63.32C142.269-62.97 142.859-61.7 143.229-57.26C143.289-56.48 143.339-55.66 143.389-54.78C143.669-49.29 148.049-44.84 153.549-44.84C159.099-44.84 163.649-49.36 163.409-54.9C163.059-62.67 162.179-67.95 159.919-72.4C156.659-78.79 151.459-84 145.059-87.26C140.569-89.54 135.209-90.42 127.289-90.75L119.209-100.83C116.749-103.91 113.019-105.7 109.069-105.7L76.2391-105.7ZM69.3391-30.84C69.3391-43.72 79.7891-54.16 92.6591-54.16C105.539-54.16 115.979-43.72 115.979-30.84C115.979-17.96 105.539-7.52 92.6591-7.52C79.7891-7.52 69.3391-17.96 69.3391-30.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M140.549-65.72C141.139-64.98 141.659-64.17 142.099-63.32C142.269-62.97 142.859-61.7 143.229-57.26C143.289-56.48 143.339-39.66 143.389-38.78C143.669-33.29 148.049-28.84 153.549-28.84C159.099-28.84 163.649-33.36 163.409-38.9C163.399-39.12 163.379-55.34 163.369-55.56C163.009-62.98 162.119-68.08 159.919-72.4C156.659-78.8 151.459-84 145.059-87.26C140.589-89.53 135.269-90.41 127.419-90.75L140.549-65.72Z"/> + </g> + <g id="Heavy-L" transform="matrix(1 0 0 1 2544.92 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M39.7758-7.42C39.8258-6.07 39.8958-4.84 39.9958-3.7C40.3558 0.71 40.9558 2.19 41.2658 2.8C42.7258 5.67 45.0558 8 47.9258 9.46C48.5358 9.77 50.0158 10.37 54.4258 10.73C59.0358 11.11 65.1158 11.12 74.6558 11.12L83.1958 11.12C88.0958 11.12 92.0758 15.1 92.0758 20C92.0758 24.9 88.0958 28.88 83.1958 28.88L74.6558 28.88C56.1658 28.88 46.9258 28.88 39.8658 25.28C33.6558 22.11 28.6158 17.07 25.4458 10.86C23.1358 6.32 22.3058 0.88 22.0158-7.33C21.8358-12.25 25.8658-16.25 30.7858-16.25C35.6658-16.25 39.5758-12.3 39.7758-7.42Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.536 6.08485L154.536 6.0849C154.536 14.8026 147.468 21.8697 138.751 21.8697L138.751 21.8697C130.033 21.8697 122.966 14.8026 122.966 6.0849L122.966 6.0848C122.966-2.6329 130.033-9.7 138.751-9.7L138.751-9.7C147.468-9.7 154.536-2.6329 154.536 6.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.3458-104.5C71.4058-104.5 67.6658-102.71 65.2058-99.63L56.8158-89.16C49.2858-88.83 44.1758-87.97 39.8658-85.78C33.6558-82.61 28.6158-77.57 25.4458-71.36C23.1358-66.82 22.3058-61.38 22.0158-53.17C21.8358-48.25 25.8658-44.25 30.7858-44.25C35.6658-44.25 39.5758-48.2 39.7758-53.08C39.8258-54.43 39.8958-55.66 39.9958-56.8C40.3558-61.21 40.9558-62.69 41.2658-63.3C42.7258-66.17 45.0558-68.5 47.9258-69.96C48.5358-70.27 50.0158-70.87 54.4258-71.23C59.0358-71.61 65.1158-71.62 74.6558-71.62L108.876-71.62C118.406-71.62 124.486-71.61 129.096-71.23C133.506-70.87 134.986-70.27 135.596-69.96C138.466-68.5 140.796-66.17 142.256-63.3C142.566-62.69 143.166-61.21 143.526-56.8C143.626-55.66 143.696-54.43 143.746-53.08C143.946-48.2 147.856-44.25 152.736-44.25C157.656-44.25 161.686-48.25 161.506-53.17C161.216-61.38 160.386-66.82 158.076-71.36C154.906-77.57 149.866-82.61 143.656-85.78C139.346-87.97 134.236-88.83 126.706-89.16L118.316-99.63C115.856-102.71 112.116-104.5 108.176-104.5L75.3458-104.5ZM68.4458-30.25C68.4458-43.13 78.8858-53.57 91.7658-53.57C104.636-53.57 115.086-43.13 115.086-30.25C115.086-17.37 104.636-6.93 91.7658-6.93C78.8858-6.93 68.4458-17.37 68.4458-30.25Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M140.036-66.54C140.906-65.56 141.656-64.48 142.256-63.3C142.566-62.69 143.166-61.21 143.526-56.8C143.626-55.66 143.696-38.43 143.746-37.08C143.946-32.2 147.856-28.25 152.736-28.25C157.656-28.25 161.686-32.25 161.506-37.17C161.506-37.26 161.496-53.34 161.496-53.43C161.196-61.49 160.366-66.87 158.076-71.36C154.906-77.56 149.866-82.61 143.656-85.78C139.346-87.97 134.236-88.83 126.706-89.16L125.716-90.4L140.036-66.54Z"/> + </g> + <g id="Bold-L" transform="matrix(1 0 0 1 2248.13 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M29.2114-15.25C25.2014-15.25 21.9314-11.99 22.0114-7.98C22.2214 1.55 22.9314 7.52 25.4214 12.4C28.4914 18.42 33.3814 23.32 39.4014 26.39C46.2514 29.88 55.2114 29.88 73.1314 29.88L84.6214 29.88C88.6214 29.88 91.8714 26.63 91.8714 22.62C91.8714 18.62 88.6214 15.38 84.6214 15.38L73.1314 15.38C63.9314 15.38 57.9014 15.36 53.3014 14.99C48.8614 14.62 47.0314 14 45.9914 13.47C42.6914 11.79 40.0214 9.11 38.3414 5.82C37.8114 4.78 37.1814 2.95 36.8214-1.49C36.6614-3.39 36.5714-5.52 36.5214-8.02C36.4314-12.02 33.2114-15.25 29.2114-15.25Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.681 7.08485L154.681 7.0849C154.681 15.8026 147.614 22.8697 138.896 22.8697L138.896 22.8697C130.179 22.8697 123.111 15.8026 123.111 7.0849L123.111 7.0848C123.111-1.6329 130.179-8.7 138.896-8.7L138.896-8.7C147.614-8.7 154.681-1.6329 154.681 7.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.4214-102.13C71.4814-102.13 67.7514-100.34 65.2914-97.27L59.0314-89.46C58.7314-89.08 58.5314-88.68 58.4314-88.26C49.6814-88.02 44.0514-87.26 39.4014-84.89C33.3814-81.82 28.4914-76.92 25.4214-70.9C22.9314-66.02 22.2214-60.05 22.0114-50.52C21.9314-46.51 25.2014-43.25 29.2114-43.25C33.2114-43.25 36.4314-46.48 36.5214-50.48C36.5714-52.98 36.6614-55.11 36.8214-57.01C37.1814-61.45 37.8114-63.28 38.3414-64.32C40.0214-67.61 42.6914-70.29 45.9914-71.97C47.0314-72.5 48.8614-73.12 53.3014-73.49C57.9014-73.86 63.9314-73.88 73.1314-73.88L110.551-73.88C119.751-73.88 125.781-73.86 130.391-73.49C134.831-73.12 136.661-72.5 137.701-71.97C140.991-70.29 143.671-67.61 145.341-64.32C145.871-63.28 146.501-61.45 146.861-57.01C147.021-55.11 147.111-52.98 147.171-50.48C147.261-46.48 150.481-43.25 154.471-43.25C158.491-43.25 161.761-46.51 161.671-50.52C161.471-60.05 160.751-66.02 158.261-70.9C155.201-76.92 150.301-81.82 144.281-84.89C139.701-87.22 134.161-87.99 125.621-88.25L118.401-97.26C115.931-100.34 112.201-102.13 108.261-102.13L75.4214-102.13ZM68.5214-29.25C68.5214-42.13 78.9614-52.57 91.8414-52.57C104.721-52.57 115.161-42.13 115.161-29.25C115.161-16.37 104.721-5.93 91.8414-5.93C78.9614-5.93 68.5214-16.37 68.5214-29.25Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M139.931-70.61C142.201-68.99 144.071-66.83 145.341-64.32C145.871-63.28 146.501-61.45 146.861-57.01C147.021-55.12 147.111-37.98 147.171-35.48C147.261-31.48 150.481-28.25 154.471-28.25C158.491-28.25 161.761-31.51 161.671-35.52C161.671-35.55 161.671-50.57 161.671-50.59C161.461-60.08 160.751-66.03 158.261-70.9C155.201-76.92 150.301-81.82 144.281-84.89C139.741-87.2 134.281-87.98 125.891-88.24L139.931-70.61Z"/> + </g> + <g id="Semibold-L" transform="matrix(1 0 0 1 1951.38 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M28.1104-15.26C24.7204-15.26 21.9704-12.51 22.0104-9.12C22.1504 1.49 22.7404 7.82 25.3504 12.94C28.3204 18.77 33.0604 23.52 38.9004 26.49C45.5304 29.87 54.2104 29.87 71.5704 29.87L85.4904 29.87C88.8704 29.87 91.6104 27.12 91.6104 23.74C91.6104 20.36 88.8704 17.62 85.4904 17.62L71.5704 17.62C62.6904 17.62 56.7604 17.61 52.2104 17.24C47.7904 16.88 45.7604 16.24 44.4604 15.57C40.9304 13.78 38.0604 10.91 36.2604 7.38C35.6004 6.08 34.9604 4.04 34.6004-0.37C34.4004-2.82 34.3104-5.66 34.2604-9.14C34.2204-12.52 31.4904-15.26 28.1104-15.26Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.75 7.08485L154.75 7.0849C154.75 15.8026 147.683 22.8697 138.965 22.8697L138.965 22.8697C130.248 22.8697 123.18 15.8026 123.18 7.0849L123.18 7.0848C123.18-1.6329 130.248-8.7 138.965-8.7L138.965-8.7C147.683-8.7 154.75-1.6329 154.75 7.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.4604-102.13C71.5204-102.13 67.7904-100.34 65.3204-97.27L59.0704-89.46C58.7804-89.1 58.5804-88.7 58.4704-88.3C49.3404-88.1 43.6004-87.4 38.9004-85C33.0604-82.03 28.3204-77.29 25.3504-71.46C22.7404-66.34 22.1504-60 22.0104-49.4C21.9704-46.01 24.7204-43.26 28.1104-43.26C31.4904-43.26 34.2204-45.99 34.2604-49.37C34.3104-52.86 34.4004-55.7 34.6004-58.15C34.9604-62.56 35.6004-64.59 36.2604-65.9C38.0604-69.42 40.9304-72.29 44.4604-74.09C45.7604-74.75 47.7904-75.39 52.2104-75.75C56.7604-76.12 62.6904-76.13 71.5704-76.13L112.19-76.13C121.07-76.13 127-76.12 131.55-75.75C135.96-75.39 138-74.75 139.3-74.09C142.83-72.29 145.7-69.42 147.5-65.9C148.16-64.59 148.8-62.56 149.16-58.15C149.36-55.7 149.45-52.86 149.5-49.37C149.54-45.99 152.27-43.26 155.65-43.26C159.04-43.26 161.79-46.01 161.75-49.4C161.61-60 161.02-66.34 158.41-71.46C155.44-77.29 150.7-82.03 144.86-85C140.22-87.37 134.56-88.08 125.62-88.29L118.44-97.26C115.97-100.34 112.24-102.13 108.29-102.13L75.4604-102.13ZM68.5604-29.26C68.5604-42.14 79.0004-52.58 91.8804-52.58C104.76-52.58 115.2-42.14 115.2-29.26C115.2-16.38 104.76-5.94 91.8804-5.94C79.0004-5.94 68.5604-16.38 68.5604-29.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M136.32-75.1C137.69-74.8 138.6-74.45 139.3-74.09C142.83-72.29 145.7-69.42 147.5-65.9C148.16-64.6 148.8-62.56 149.16-58.15C149.36-55.7 149.45-37.86 149.5-34.37C149.54-31 152.27-28.26 155.65-28.26C159.04-28.26 161.79-31.01 161.75-34.4C161.75-34.41 161.75-49.42 161.75-49.43C161.61-60.02 161.02-66.35 158.41-71.46C155.44-77.29 150.7-82.03 144.86-85.01C140.25-87.36 134.64-88.07 125.81-88.29L136.32-75.1Z"/> + </g> + <g id="Medium-L" transform="matrix(1 0 0 1 1654.65 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.3701-15.97C24.4001-15.97 21.9901-13.56 22.0101-10.59C22.1001 0.73 22.6001 7.26 25.2601 12.49C28.1401 18.13 32.7201 22.72 38.3701 25.6C44.7901 28.87 53.1901 28.87 69.9901 28.87L86.9601 28.87C89.9301 28.87 92.3301 26.46 92.3301 23.49C92.3301 20.52 89.9301 18.12 86.9601 18.12L69.9901 18.12C61.4101 18.12 55.6201 18.11 51.1601 17.74C46.8201 17.39 44.6901 16.75 43.2501 16.02C39.6301 14.17 36.6801 11.23 34.8401 7.61C34.1001 6.17 33.4701 4.03 33.1101-0.3C32.8801-3.1 32.8001-6.41 32.7601-10.6C32.7401-13.57 30.3401-15.97 27.3701-15.97Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.78 5.08485L154.78 5.0849C154.78 13.8026 147.713 20.8697 138.995 20.8697L138.995 20.8697C130.277 20.8697 123.21 13.8026 123.21 5.0849L123.21 5.0848C123.21-3.6329 130.277-10.7 138.995-10.7L138.995-10.7C147.713-10.7 154.78-3.6329 154.78 5.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.4801-104.16C71.5401-104.16 67.8101-102.37 65.3401-99.29L59.0901-91.48C58.5601-90.82 58.3501-90.06 58.3901-89.32C48.9201-89.16 43.1001-88.53 38.3701-86.11C32.7201-83.24 28.1301-78.65 25.2601-73C22.5501-67.69 22.0901-61.02 22.0101-49.35C21.9901-46.38 24.4001-43.97 27.3701-43.97C30.3401-43.97 32.7401-46.37 32.7601-49.34C32.7901-53.81 32.8701-57.29 33.1101-60.21C33.4701-64.55 34.1001-66.68 34.8401-68.12C36.6801-71.74 39.6301-74.69 43.2501-76.53C44.6901-77.27 46.8201-77.91 51.1601-78.26C55.6201-78.62 61.4101-78.63 69.9901-78.63L113.81-78.63C122.39-78.63 128.17-78.62 132.64-78.26C136.97-77.91 139.11-77.27 140.55-76.53C144.17-74.69 147.11-71.74 148.96-68.12C149.69-66.68 150.33-64.55 150.68-60.21C150.92-57.29 151.01-53.81 151.04-49.34C151.06-46.37 153.46-43.97 156.43-43.97C159.4-43.97 161.81-46.38 161.79-49.35C161.71-61.02 161.24-67.69 158.54-73C155.66-78.65 151.07-83.24 145.43-86.11C140.87-88.44 135.31-89.11 126.45-89.3L118.46-99.28C115.99-102.36 112.26-104.16 108.31-104.16L75.4801-104.16ZM68.5801-30.26C68.5801-43.14 79.0201-53.58 91.9001-53.58C104.78-53.58 115.22-43.14 115.22-30.26C115.22-17.38 104.78-6.94 91.9001-6.94C79.0201-6.94 68.5801-17.38 68.5801-30.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M135.7-77.91C138.08-77.55 139.5-77.07 140.55-76.53C144.17-74.69 147.11-71.74 148.96-68.12C149.69-66.68 150.33-64.55 150.68-60.21C150.92-57.29 151.01-38.8 151.04-34.34C151.06-31.37 153.46-28.97 156.43-28.97C159.4-28.97 161.81-31.38 161.79-34.35C161.79-34.36 161.79-49.38 161.79-49.4C161.71-61.04 161.24-67.7 158.54-73C155.66-78.64 151.07-83.23 145.43-86.11C140.9-88.42 135.38-89.1 126.63-89.3L135.7-77.91Z"/> + </g> + <g id="Regular-L" transform="matrix(1 0 0 1 1357.92 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.26-14.26C23.91-14.26 22.01-12.35 22.01-10.01C22.05 2.46 22.35 9.25 25.06 14.58C27.75 19.85 32.03 24.13 37.3 26.82C43.29 29.87 51.13 29.87 66.81 29.87L87.76 29.87C90.11 29.87 92.01 27.96 92.01 25.62C92.01 23.27 90.11 21.37 87.76 21.37L66.81 21.37C58.83 21.37 53.36 21.36 49.11 21.01C44.97 20.68 42.75 20.06 41.16 19.24C37.49 17.37 34.51 14.39 32.64 10.72C31.82 9.12 31.2 6.91 30.86 2.77C30.59-0.54 30.53-4.6 30.52-10.01C30.51-12.35 28.61-14.26 26.26-14.26Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M154.83 7.08485L154.83 7.0849C154.83 15.8026 147.763 22.8697 139.045 22.8697L139.045 22.8697C130.327 22.8697 123.26 15.8026 123.26 7.0849L123.26 7.0848C123.26-1.6329 130.327-8.7 139.045-8.7L139.045-8.7C147.763-8.7 154.83-1.6329 154.83 7.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.5-102.19C71.56-102.19 67.83-100.4 65.37-97.32L59.11-89.52C58.82-89.15 58.63-88.76 58.52-88.36C48.15-88.27 42.13-87.79 37.3-85.33C32.03-82.65 27.75-78.36 25.06-73.09C22.35-67.77 22.05-60.98 22.01-48.51C22.01-46.16 23.91-44.26 26.26-44.26C28.61-44.26 30.51-46.16 30.52-48.51C30.53-53.92 30.59-57.97 30.86-61.28C31.2-65.42 31.82-67.64 32.64-69.24C34.51-72.9 37.49-75.89 41.16-77.76C42.75-78.57 44.97-79.19 49.11-79.53C53.36-79.88 58.83-79.88 66.81-79.88L117.03-79.88C125.01-79.88 130.49-79.88 134.73-79.53C138.87-79.19 141.09-78.57 142.68-77.76C146.35-75.89 149.34-72.9 151.21-69.24C152.02-67.64 152.64-65.42 152.98-61.28C153.25-57.97 153.31-53.92 153.33-48.51C153.33-46.16 155.23-44.26 157.58-44.26C159.93-44.26 161.83-46.16 161.83-48.51C161.79-60.98 161.49-67.77 158.78-73.09C156.09-78.36 151.81-82.65 146.54-85.33C141.77-87.76 135.82-88.26 125.66-88.36L118.48-97.32C116.01-100.4 112.28-102.19 108.33-102.19L75.5-102.19ZM68.6-29.26C68.6-42.14 79.04-52.58 91.92-52.58C104.8-52.58 115.24-42.14 115.24-29.26C115.24-16.38 104.8-5.94 91.92-5.94C79.04-5.94 68.6-16.38 68.6-29.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M132.82-79.65C133.48-79.62 134.12-79.58 134.73-79.53C138.87-79.19 141.09-78.57 142.68-77.75C146.35-75.88 149.34-72.9 151.21-69.23C152.02-67.63 152.64-65.42 152.98-61.28C153.25-57.97 153.31-38.91 153.33-33.5C153.33-31.16 155.23-29.25 157.58-29.25C159.93-29.25 161.83-31.16 161.83-33.51C161.83-33.52 161.83-48.54 161.83-48.56C161.79-60.99 161.49-67.77 158.78-73.09C156.09-78.36 151.81-82.64 146.54-85.33C141.79-87.75 135.88-88.25 125.82-88.35L132.82-79.65Z"/> + </g> + <g id="Light-L" transform="matrix(1 0 0 1 1061.21 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M25.64-16.26C23.64-16.26 22.01-14.63 22.01-12.63L22.01-11.73C22.01 2.83 22.01 10.11 24.85 15.67C27.34 20.56 31.32 24.54 36.21 27.03C41.77 29.87 49.05 29.87 63.61 29.87L88.16 29.87C90.17 29.87 91.79 28.24 91.79 26.24C91.79 24.24 90.17 22.62 88.16 22.62L63.61 22.62C56.21 22.62 51.1 22.61 47.13 22.29C43.24 21.97 41.09 21.38 39.5 20.57C35.97 18.78 33.1 15.91 31.31 12.38C30.5 10.79 29.91 8.64 29.59 4.75C29.27 0.78 29.26-4.33 29.26-11.73L29.26-12.63C29.26-14.63 27.64-16.26 25.64-16.26Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M155.83 8.08485L155.83 8.0849C155.83 16.8026 148.763 23.8697 140.045 23.8697L140.045 23.8697C131.327 23.8697 124.26 16.8026 124.26 8.0849L124.26 8.0848C124.26-0.632904 131.327-7.7 140.045-7.7L140.045-7.7C148.763-7.7 155.83-0.632904 155.83 8.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.5-102.09C71.56-102.09 67.83-100.3 65.37-97.22L59.11-89.41C58.85-89.09 58.67-88.74 58.55-88.38C47.28-88.34 41.09-88.03 36.21-85.55C31.32-83.06 27.34-79.08 24.85-74.19C22.01-68.62 22.01-61.34 22.01-46.78L22.01-45.88C22.01-43.88 23.64-42.26 25.64-42.26C27.64-42.26 29.26-43.88 29.26-45.88L29.26-46.78C29.26-54.18 29.27-59.3 29.59-63.27C29.91-67.16 30.5-69.31 31.31-70.9C33.1-74.42 35.97-77.29 39.5-79.09C41.09-79.9 43.24-80.49 47.13-80.8C51.1-81.13 56.21-81.13 63.61-81.13L120.23-81.13C127.63-81.13 132.75-81.13 136.72-80.8C140.61-80.49 142.76-79.9 144.35-79.09C147.87-77.29 150.74-74.42 152.54-70.9C153.35-69.31 153.94-67.16 154.25-63.27C154.58-59.3 154.58-54.18 154.58-46.78L154.58-45.88C154.58-43.88 156.21-42.26 158.21-42.26C160.21-42.26 161.83-43.88 161.83-45.88L161.83-46.78C161.83-61.34 161.83-68.62 159-74.19C156.51-79.08 152.53-83.06 147.64-85.55C142.8-88.01 136.66-88.33 125.56-88.38L118.48-97.21C116.01-100.29 112.28-102.09 108.34-102.09L75.5-102.09ZM68.6-29.26C68.6-42.14 79.04-52.58 91.92-52.58C104.8-52.58 115.24-42.14 115.24-29.26C115.24-16.38 104.8-5.94 91.92-5.94C79.04-5.94 68.6-16.38 68.6-29.26Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M130.42-81.08C132.84-81.03 134.9-80.95 136.72-80.8C140.61-80.48 142.76-79.9 144.35-79.09C147.87-77.29 150.74-74.42 152.54-70.89C153.35-69.31 153.94-67.16 154.25-63.27C154.58-59.3 154.58-54.18 154.58-46.78L154.58-32.88C154.58-30.88 156.21-29.26 158.21-29.26C160.21-29.26 161.83-30.88 161.83-32.88L161.83-46.78C161.83-61.34 161.83-68.62 159-74.19C156.51-79.08 152.53-83.06 147.64-85.55C142.81-88 136.7-88.33 125.67-88.38L130.42-81.08Z"/> + </g> + <g id="Thin-L" transform="matrix(1 0 0 1 764.497 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.01-16.12C22.906-16.12 22.01-15.22 22.01-14.12L22.01-13.09C22.01 1.47 22.01 8.75 24.844 14.31C27.337 19.21 31.314 23.18 36.206 25.68C41.768 28.51 49.049 28.51 63.61 28.51L90.498 28.51C91.602 28.51 92.498 27.61 92.498 26.51C92.498 25.41 91.602 24.51 90.498 24.51L63.61 24.51C56.264 24.51 50.994 24.51 46.859 24.17C42.771 23.84 40.145 23.19 38.022 22.11C33.883 20 30.517 16.64 28.408 12.5C27.326 10.37 26.685 7.75 26.351 3.66C26.013-0.47 26.01-5.74 26.01-13.09L26.01-14.12C26.01-15.22 25.115-16.12 24.01-16.12Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M155.83 6.72485L155.83 6.7249C155.83 15.4426 148.763 22.5097 140.045 22.5097L140.045 22.5097C131.327 22.5097 124.26 15.4426 124.26 6.7249L124.26 6.7248C124.26-1.9929 131.327-9.06 140.045-9.06L140.045-9.06C148.763-9.06 155.83-1.9929 155.83 6.7248Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M75.507-103.98C71.561-103.98 67.829-102.19 65.362-99.11L57.042-88.73C46.72-88.67 40.861-88.28 36.206-85.91C31.314-83.42 27.337-79.44 24.844-74.55C22.01-68.98 22.01-61.7 22.01-47.14L22.01-46.12C22.01-45.01 22.906-44.12 24.01-44.12C25.115-44.12 26.01-45.01 26.01-46.12L26.01-47.14C26.01-54.49 26.013-59.76 26.351-63.89C26.685-67.98 27.326-70.61 28.408-72.73C30.517-76.87 33.883-80.24 38.022-82.34C40.145-83.43 42.771-84.07 46.859-84.4C50.994-84.74 56.264-84.74 63.61-84.74L120.23-84.74C127.577-84.74 132.846-84.74 136.981-84.4C141.069-84.07 143.695-83.43 145.818-82.34C149.958-80.24 153.323-76.87 155.432-72.73C156.514-70.61 157.155-67.98 157.489-63.89C157.827-59.76 157.83-54.49 157.83-47.14L157.83-46.12C157.83-45.01 158.726-44.12 159.83-44.12C160.935-44.12 161.83-45.01 161.83-46.12L161.83-47.14C161.83-61.7 161.83-68.98 158.996-74.55C156.504-79.44 152.526-83.42 147.634-85.91C142.979-88.28 137.121-88.67 126.798-88.73L118.478-99.11C116.011-102.19 112.279-103.98 108.333-103.98L75.507-103.98ZM68.6-30.12C68.6-43 79.041-53.44 91.92-53.44C104.799-53.44 115.24-43 115.24-30.12C115.24-17.24 104.799-6.8 91.92-6.8C79.041-6.8 68.6-17.24 68.6-30.12Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M129.632-84.7C132.461-84.66 134.869-84.57 136.981-84.4C141.07-84.07 143.695-83.42 145.818-82.34C149.958-80.23 153.323-76.87 155.432-72.73C156.514-70.61 157.155-67.98 157.489-63.89C157.827-59.76 157.83-54.49 157.83-47.14L157.83-31.12C157.83-30.01 158.726-29.12 159.83-29.12C160.935-29.12 161.83-30.01 161.83-31.12L161.83-47.14C161.83-61.7 161.83-68.98 158.996-74.54C156.504-79.44 152.526-83.41 147.634-85.91C143.011-88.26 137.201-88.66 127.009-88.73L129.632-84.7Z"/> + </g> + <g id="Ultralight-L" transform="matrix(1 0 0 1 467.786 1556)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.26-15.25C22.57-15.25 22.01-14.69 22.01-14L22.01-7.92C22.01 4.96 22.01 11.4 24.517 16.32C26.722 20.65 30.241 24.16 34.568 26.37C39.488 28.88 45.929 28.88 58.81 28.88L91.248 28.88C91.938 28.88 92.498 28.32 92.498 27.63C92.498 26.94 91.938 26.38 91.248 26.38L58.81 26.38C52.328 26.38 47.617 26.37 43.907 26.07C40.227 25.77 37.752 25.19 35.703 24.14C31.846 22.18 28.71 19.04 26.745 15.18C25.701 13.13 25.116 10.66 24.815 6.98C24.512 3.27 24.51-1.44 24.51-7.92L24.51-14C24.51-14.69 23.951-15.25 23.26-15.25Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M156.83 8.08485L156.83 8.0849C156.83 16.8026 149.763 23.8697 141.045 23.8697L141.045 23.8697C132.327 23.8697 125.26 16.8026 125.26 8.0849L125.26 8.0848C125.26-0.632904 132.327-7.7 141.045-7.7L141.045-7.7C149.763-7.7 156.83-0.632904 156.83 8.0848Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M65.362-98.04C67.829-101.12 71.561-102.91 75.507-102.91L108.333-102.91C112.279-102.91 116.011-101.12 118.478-98.04L127.008-87.4L127.008-87.4L127.034-87.37C138.593-87.37 144.614-87.24 149.272-84.87C153.6-82.66 157.118-79.14 159.323-74.82C161.83-69.9 161.83-63.46 161.83-50.58L161.83-44.5C161.83-43.81 161.271-43.25 160.58-43.25C159.89-43.25 159.33-43.81 159.33-44.5L159.33-50.58C159.33-57.06 159.328-61.77 159.025-65.48C158.724-69.16 158.14-71.63 157.096-73.68C155.13-77.54 151.994-80.68 148.137-82.64C146.088-83.68 143.614-84.27 139.933-84.57C136.223-84.87 131.512-84.88 125.03-84.88L58.81-84.88C52.328-84.88 47.617-84.87 43.907-84.57C40.227-84.27 37.752-83.68 35.703-82.64C31.846-80.68 28.71-77.54 26.745-73.68C25.701-71.63 25.116-69.16 24.815-65.48C24.512-61.77 24.51-57.06 24.51-50.57L24.51-44.5C24.51-43.81 23.951-43.25 23.26-43.25C22.57-43.25 22.01-43.81 22.01-44.5L22.01-50.57C22.01-63.46 22.01-69.9 24.517-74.82C26.722-79.14 30.241-82.66 34.568-84.87C39.221-87.24 45.233-87.37 56.765-87.37L56.765-87.45L56.877-87.45L65.362-98.04ZM91.92-52.57C79.041-52.57 68.6-42.13 68.6-29.25C68.6-16.37 79.041-5.93 91.92-5.93C104.799-5.93 115.24-16.37 115.24-29.25C115.24-42.13 104.799-52.57 91.92-52.57Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M128.665-84.87C133.331-84.86 136.955-84.81 139.933-84.57C143.613-84.27 146.088-83.68 148.137-82.64C151.994-80.68 155.13-77.54 157.095-73.68C158.139-71.63 158.724-69.16 159.025-65.48C159.328-61.77 159.33-57.06 159.33-50.58L159.33-30.5C159.33-29.81 159.889-29.25 160.58-29.25C161.27-29.25 161.83-29.81 161.83-30.5L161.83-50.58C161.83-63.46 161.83-69.9 159.323-74.82C157.118-79.14 153.599-82.66 149.272-84.87C144.619-87.24 138.606-87.37 127.072-87.38L128.665-84.87Z"/> + </g> + <g id="Black-M" transform="matrix(1 0 0 1 2860.99 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.92-23.78L36.35-23.78C37.95-23.78 39.26-22.48 39.26-20.87C39.26-15.19 39.31-14.36 39.38-13.94C40.04-9.77 43.31-6.5 47.48-5.84C47.9-5.77 48.73-5.72 54.41-5.72L64.39-5.72C69.15-5.72 73.01-1.86 73.01 2.9C73.01 7.67 69.15 11.53 64.39 11.53L54.41 11.53C49.39 11.53 46.88 11.53 44.78 11.2C33.23 9.37 24.17 0.31 22.34-11.25C22.01-13.35 22.01-15.85 22.01-20.87C22.01-22.48 23.31-23.78 24.92-23.78Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.47L118.81-4.47C118.81 2.15742 113.437 7.53 106.81 7.53L106.81 7.53C100.183 7.53 94.81 2.15742 94.81-4.47L94.81-4.47C94.81-11.0974 100.183-16.47 106.81-16.47L106.81-16.47C113.437-16.47 118.81-11.0974 118.81-4.47Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-89.47C60.43-89.47 57.9-88.09 56.42-85.81L50.87-77.2C48.07-77.19 46.32-77.12 44.78-76.88C33.23-75.05 24.17-65.99 22.34-54.43C22.01-52.34 22.01-49.83 22.01-44.81C22.01-42.83 23.62-41.22 25.6-41.22L35.67-41.22C37.65-41.22 39.26-42.83 39.26-44.81C39.26-50.49 39.31-51.32 39.38-51.74C40.04-55.91 43.31-59.18 47.48-59.84C47.9-59.91 48.73-59.96 54.41-59.96L90.41-59.96C96.08-59.96 96.91-59.91 97.33-59.84C101.51-59.18 104.78-55.91 105.44-51.74C105.5-51.32 105.56-50.49 105.56-44.81C105.56-42.83 107.17-41.22 109.15-41.22L119.22-41.22C121.2-41.22 122.81-42.83 122.81-44.81C122.81-49.83 122.81-52.34 122.48-54.43C120.65-65.99 111.59-75.05 100.03-76.88C98.5-77.12 96.74-77.19 93.95-77.2L88.4-85.81C86.92-88.09 84.39-89.47 81.68-89.47L63.14-89.47ZM55.14-32.84C55.14-42.38 62.87-50.11 72.41-50.11C81.94-50.11 89.67-42.38 89.67-32.84C89.67-23.31 81.94-15.58 72.41-15.58C62.87-15.58 55.14-23.31 55.14-32.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M103.65-56C104.56-54.77 105.19-53.32 105.44-51.74C105.5-51.32 105.56-40.49 105.56-34.81C105.56-32.83 107.16-31.22 109.15-31.22L119.22-31.22C121.2-31.22 122.81-32.83 122.81-34.81C122.81-39.83 122.81-52.34 122.48-54.43C120.65-65.99 111.58-75.05 100.03-76.88C98.5-77.12 96.74-77.19 93.95-77.2L93.76-77.5L103.65-56Z"/> + </g> + <g id="Heavy-M" transform="matrix(1 0 0 1 2564.27 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.32-22.78C24.39-22.78 22.01-20.4 22.01-17.47C22.01-12.82 22.01-10.5 22.32-8.56C24.02 2.14 32.41 10.53 43.1 12.22C45.05 12.53 47.37 12.53 52.01 12.53L65.22 12.53C69.36 12.53 72.72 9.17 72.72 5.03C72.72 0.89 69.36-2.47 65.22-2.47L52.01-2.47C46.8-2.47 45.93-2.52 45.45-2.59C41.17-3.27 37.81-6.63 37.14-10.91C37.06-11.39 37.01-12.25 37.01-17.47C37.01-20.4 34.64-22.78 31.7-22.78L27.32-22.78Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-3.47L118.81-3.47C118.81 3.15742 113.437 8.53 106.81 8.53L106.81 8.53C100.183 8.53 94.81 3.15742 94.81-3.47L94.81-3.47C94.81-10.0974 100.183-15.47 106.81-15.47L106.81-15.47C113.437-15.47 118.81-10.0974 118.81-3.47Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.15-88.47C60.43-88.47 57.9-87.09 56.43-84.81L50.88-76.21C46.98-76.21 44.88-76.18 43.1-75.9C32.41-74.21 24.02-65.82 22.32-55.12C22.01-53.18 22.01-50.86 22.01-46.21C22.01-42.9 24.69-40.22 28-40.22L31.02-40.22C34.33-40.22 37.01-42.9 37.01-46.21C37.01-51.43 37.06-52.29 37.14-52.78C37.81-57.05 41.17-60.41 45.45-61.09C45.93-61.16 46.8-61.21 52.01-61.21L92.81-61.21C98.03-61.21 98.89-61.16 99.38-61.09C103.66-60.41 107.01-57.05 107.69-52.78C107.77-52.29 107.81-51.43 107.81-46.21C107.81-42.9 110.49-40.22 113.8-40.22L116.82-40.22C120.13-40.22 122.81-42.9 122.81-46.21C122.81-50.86 122.81-53.18 122.51-55.12C120.81-65.82 112.42-74.21 101.72-75.9C99.95-76.18 97.85-76.21 93.95-76.21L88.4-84.81C86.93-87.09 84.4-88.47 81.68-88.47L63.15-88.47ZM55.15-31.84C55.15-41.38 62.88-49.11 72.41-49.11C81.95-49.11 89.68-41.38 89.68-31.84C89.68-22.31 81.95-14.58 72.41-14.58C62.88-14.58 55.15-22.31 55.15-31.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M103.51-59.43C105.7-57.91 107.25-55.53 107.69-52.78C107.77-52.29 107.81-41.43 107.81-36.21C107.81-32.9 110.49-30.22 113.8-30.22L116.82-30.22C120.13-30.22 122.81-32.9 122.81-36.21C122.81-40.86 122.81-53.18 122.51-55.12C120.81-65.82 112.42-74.21 101.72-75.9C99.95-76.18 97.86-76.21 93.98-76.21L103.51-59.43Z"/> + </g> + <g id="Bold-M" transform="matrix(1 0 0 1 2267.56 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M28.26-23.12C24.8-23.12 22.01-20.33 22.01-16.87L22.01-16.27C22.01-11.81 22.01-9.59 22.3-7.72C23.93 2.55 31.98 10.6 42.25 12.23C44.12 12.53 46.35 12.53 50.81 12.53L66.18 12.53C69.63 12.53 72.43 9.73 72.43 6.28C72.43 2.82 69.63 0.03 66.18 0.03L50.81 0.03C45.87 0.03 44.86-0.01 44.21-0.12C39.29-0.89 35.43-4.75 34.65-9.67C34.54-10.32 34.51-11.34 34.51-16.27L34.51-16.87C34.51-20.33 31.71-23.12 28.26-23.12Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-3.47L118.81-3.47C118.81 3.15742 113.437 8.53 106.81 8.53L106.81 8.53C100.183 8.53 94.81 3.15742 94.81-3.47L94.81-3.47C94.81-10.0974 100.183-15.47 106.81-15.47L106.81-15.47C113.437-15.47 118.81-10.0974 118.81-3.47Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-88.47C60.43-88.47 57.9-87.09 56.42-84.81L50.87-76.21L50.81-76.21C46.35-76.21 44.12-76.21 42.25-75.92C31.98-74.29 23.93-66.23 22.3-55.97C22.01-54.1 22.01-51.87 22.01-47.41L22.01-46.81C22.01-43.36 24.8-40.56 28.26-40.56C31.71-40.56 34.51-43.36 34.51-46.81L34.51-47.41C34.51-52.35 34.54-53.36 34.65-54.01C35.43-58.93 39.29-62.79 44.21-63.57C44.86-63.67 45.87-63.71 50.81-63.71L94.01-63.71C98.94-63.71 99.96-63.67 100.61-63.57C105.53-62.79 109.39-58.93 110.16-54.01C110.27-53.36 110.31-52.35 110.31-47.41L110.31-46.81C110.31-43.36 113.1-40.56 116.56-40.56C120.01-40.56 122.81-43.36 122.81-46.81L122.81-47.41C122.81-51.87 122.81-54.1 122.51-55.97C120.88-66.23 112.83-74.29 102.56-75.92C100.7-76.21 98.47-76.21 94.01-76.21L93.95-76.21L88.39-84.81C86.92-87.09 84.39-88.47 81.67-88.47L63.14-88.47ZM55.14-31.84C55.14-41.38 62.87-49.11 72.41-49.11C81.94-49.11 89.67-41.38 89.67-31.84C89.67-22.31 81.94-14.58 72.41-14.58C62.87-14.58 55.14-22.31 55.14-31.84Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M102.29-63.17C106.39-61.87 109.48-58.35 110.16-54.01C110.27-53.36 110.31-42.35 110.31-37.41L110.31-36.81C110.31-33.36 113.1-30.56 116.56-30.56C120.01-30.56 122.81-33.36 122.81-36.81L122.81-37.41C122.81-41.87 122.81-54.1 122.51-55.97C120.88-66.23 112.83-74.29 102.56-75.92C100.7-76.21 98.47-76.21 94.01-76.21L93.99-76.21L102.29-63.17Z"/> + </g> + <g id="Semibold-M" transform="matrix(1 0 0 1 1970.85 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.38-23.8C24.41-23.8 22.01-21.4 22.01-18.43L22.01-15.71C22.01-11.43 22.01-9.3 22.29-7.51C23.85 2.33 31.57 10.05 41.41 11.61C43.2 11.89 45.33 11.89 49.61 11.89L66.77 11.89C69.74 11.89 72.14 9.49 72.14 6.52C72.14 3.55 69.74 1.14 66.77 1.14L49.61 1.14C44.92 1.14 43.83 1.11 43.09 0.99C37.85 0.16 33.74-3.95 32.91-9.19C32.79-9.93 32.76-11.02 32.76-15.71L32.76-18.43C32.76-21.4 30.35-23.8 27.38-23.8Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.11L118.81-4.11C118.81 2.51742 113.437 7.89 106.81 7.89L106.81 7.89C100.183 7.89 94.81 2.51742 94.81-4.11L94.81-4.11C94.81-10.7374 100.183-16.11 106.81-16.11L106.81-16.11C113.437-16.11 118.81-10.7374 118.81-4.11Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-89.1C60.43-89.1 57.9-87.72 56.42-85.44L50.88-76.85L49.61-76.85C45.33-76.85 43.2-76.85 41.41-76.57C31.57-75.01 23.85-67.29 22.29-57.45C22.01-55.66 22.01-53.52 22.01-49.25L22.01-46.57C22.01-43.61 24.41-41.2 27.38-41.2C30.35-41.2 32.76-43.61 32.76-46.57L32.76-49.25C32.76-53.94 32.79-55.03 32.91-55.77C33.74-61.01 37.85-65.12 43.09-65.95C43.83-66.07 44.92-66.1 49.61-66.1L95.21-66.1C99.89-66.1 100.98-66.07 101.72-65.95C106.97-65.12 111.08-61.01 111.91-55.77C112.02-55.03 112.06-53.94 112.06-49.25L112.06-46.57C112.06-43.61 114.46-41.2 117.43-41.2C120.4-41.2 122.81-43.61 122.81-46.57L122.81-49.25C122.81-53.52 122.81-55.66 122.52-57.45C120.97-67.29 113.25-75.01 103.41-76.57C101.62-76.85 99.48-76.85 95.21-76.85L93.94-76.85L88.39-85.44C86.92-87.72 84.39-89.1 81.67-89.1L63.14-89.1ZM55.14-32.49C55.14-42.02 62.87-49.75 72.41-49.75C81.94-49.75 89.67-42.02 89.67-32.49C89.67-22.95 81.94-15.22 72.41-15.22C62.87-15.22 55.14-22.95 55.14-32.49Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M101.01-66.03C101.31-66.01 101.53-65.98 101.72-65.95C106.97-65.12 111.08-61.01 111.91-55.77C112.02-55.03 112.06-43.94 112.06-39.25L112.06-36.57C112.06-33.61 114.46-31.2 117.43-31.2C120.4-31.2 122.81-33.61 122.81-36.57L122.81-39.25C122.81-43.52 122.81-55.66 122.52-57.45C120.97-67.29 113.25-75.01 103.41-76.57C101.62-76.85 99.48-76.85 95.21-76.85L94-76.85L101.01-66.03Z"/> + </g> + <g id="Medium-M" transform="matrix(1 0 0 1 1674.14 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.76-23.8C24.14-23.8 22.01-21.67 22.01-19.05L22.01-13.43C22.01-9.53 22.01-7.58 22.27-5.95C23.69 3.04 30.74 10.08 39.73 11.51C41.36 11.77 43.31 11.77 47.21 11.77L68.11 11.77C70.73 11.77 72.86 9.64 72.86 7.02C72.86 4.39 70.73 2.27 68.11 2.27L47.21 2.27C42.95 2.27 41.92 2.24 41.21 2.12C36.29 1.34 32.43-2.52 31.65-7.44C31.54-8.14 31.51-9.17 31.51-13.43L31.51-19.05C31.51-21.67 29.39-23.8 26.76-23.8Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.23L118.81-4.23C118.81 2.39742 113.437 7.77 106.81 7.77L106.81 7.77C100.183 7.77 94.81 2.39742 94.81-4.23L94.81-4.23C94.81-10.8574 100.183-16.23 106.81-16.23L106.81-16.23C113.437-16.23 118.81-10.8574 118.81-4.23Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.15-89.23C60.43-89.23 57.9-87.86 56.43-85.57L50.88-76.98L47.21-76.98C43.31-76.98 41.36-76.98 39.73-76.72C30.74-75.29 23.69-68.25 22.27-59.26C22.01-57.63 22.01-55.68 22.01-51.78L22.01-45.94C22.01-43.32 24.14-41.19 26.76-41.19C29.39-41.19 31.51-43.32 31.51-45.94L31.51-51.78C31.51-56.04 31.54-57.07 31.65-57.78C32.43-62.7 36.29-66.56 41.21-67.33C41.92-67.45 42.95-67.48 47.21-67.48L97.61-67.48C101.88-67.48 102.9-67.45 103.61-67.33C108.53-66.56 112.39-62.7 113.17-57.78C113.28-57.07 113.31-56.04 113.31-51.78L113.31-45.94C113.31-43.32 115.44-41.19 118.06-41.19C120.69-41.19 122.81-43.32 122.81-45.94L122.81-51.78C122.81-55.68 122.81-57.63 122.55-59.26C121.13-68.25 114.08-75.29 105.1-76.72C103.47-76.98 101.51-76.98 97.61-76.98L93.95-76.98L88.4-85.57C86.93-87.86 84.4-89.23 81.68-89.23L63.15-89.23ZM55.15-32.61C55.15-42.15 62.88-49.88 72.41-49.88C81.95-49.88 89.68-42.15 89.68-32.61C89.68-23.07 81.95-15.35 72.41-15.35C62.88-15.35 55.15-23.07 55.15-32.61Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M100.02-67.47C102.32-67.46 103.06-67.42 103.61-67.33C108.53-66.56 112.39-62.7 113.17-57.78C113.28-57.07 113.31-56.04 113.31-51.78L113.31-35.94C113.31-33.32 115.44-31.19 118.06-31.19C120.69-31.19 122.81-33.32 122.81-35.94L122.81-51.78C122.81-55.68 122.81-57.63 122.55-59.26C121.13-68.25 114.08-75.29 105.1-76.72C103.47-76.98 101.51-76.98 97.61-76.98L93.97-76.98L100.02-67.47Z"/> + </g> + <g id="Regular-M" transform="matrix(1 0 0 1 1377.43 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.01-23.93C23.8-23.93 22.01-22.14 22.01-19.93L22.01-11.05C22.01-7.52 22.01-5.76 22.24-4.28C23.53 3.85 29.91 10.22 38.04 11.51C39.51 11.75 41.28 11.75 44.81 11.75L68.57 11.75C70.78 11.75 72.57 9.95 72.57 7.75C72.57 5.54 70.78 3.75 68.57 3.75L44.81 3.75C40.97 3.75 39.99 3.72 39.29 3.61C34.58 2.86 30.89-0.83 30.15-5.53C30.03-6.23 30.01-7.22 30.01-11.05L30.01-19.93C30.01-22.14 28.22-23.93 26.01-23.93Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-4.24L118.81-4.24C118.81 2.38742 113.437 7.76 106.81 7.76L106.81 7.76C100.183 7.76 94.81 2.38742 94.81-4.24L94.81-4.24C94.81-10.8674 100.183-16.24 106.81-16.24L106.81-16.24C113.437-16.24 118.81-10.8674 118.81-4.24Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M63.14-89.23C60.43-89.23 57.9-87.85 56.42-85.57L50.89-76.99L44.81-76.99C41.28-76.99 39.51-76.99 38.04-76.76C29.91-75.47 23.53-69.09 22.24-60.96C22.01-59.49 22.01-57.72 22.01-54.19L22.01-45.32C22.01-43.11 23.8-41.32 26.01-41.32C28.22-41.32 30.01-43.11 30.01-45.32L30.01-54.19C30.01-58.03 30.03-59.01 30.15-59.71C30.89-64.42 34.58-68.11 39.29-68.86C39.99-68.97 40.97-68.99 44.81-68.99L100.01-68.99C103.85-68.99 104.83-68.97 105.53-68.86C110.24-68.11 113.93-64.42 114.67-59.71C114.79-59.01 114.81-58.03 114.81-54.19L114.81-45.32C114.81-43.11 116.6-41.32 118.81-41.32C121.02-41.32 122.81-43.11 122.81-45.32L122.81-54.19C122.81-57.72 122.81-59.49 122.58-60.96C121.29-69.09 114.91-75.47 106.78-76.76C105.31-76.99 103.54-76.99 100.01-76.99L93.93-76.99L88.4-85.57C86.92-87.85 84.39-89.23 81.68-89.23L63.14-89.23ZM55.41-32.62C55.41-42.01 63.02-49.62 72.41-49.62C81.8-49.62 89.41-42.01 89.41-32.62C89.41-23.24 81.8-15.62 72.41-15.62C63.02-15.62 55.41-23.24 55.41-32.62Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M99.07-68.99L100.01-68.99C103.85-68.99 104.83-68.97 105.53-68.86C110.24-68.11 113.93-64.42 114.67-59.71C114.78-59.01 114.81-58.03 114.81-54.19L114.81-35.32C114.81-33.11 116.6-31.32 118.81-31.32C121.02-31.32 122.81-33.11 122.81-35.32L122.81-54.19C122.81-57.72 122.81-59.49 122.58-60.96C121.29-69.09 114.91-75.47 106.78-76.76C105.31-76.99 103.54-76.99 100.01-76.99L93.98-76.99L99.07-68.99Z"/> + </g> + <g id="Light-M" transform="matrix(1 0 0 1 1080.72 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M25.01-21.7C23.35-21.7 22.01-20.36 22.01-18.7L22.01-7.45C22.01-4.29 22.01-2.72 22.22-1.39C23.37 5.88 29.08 11.59 36.35 12.74C37.67 12.95 39.25 12.95 42.41 12.95L69.28 12.95C70.94 12.95 72.28 11.6 72.28 9.95C72.28 8.29 70.94 6.95 69.28 6.95L42.41 6.95C39.02 6.95 38.03 6.93 37.29 6.81C32.58 6.07 28.89 2.37 28.15-2.33C28.03-3.07 28.01-4.07 28.01-7.45L28.01-18.7C28.01-20.36 26.67-21.7 25.01-21.7Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M118.81-3.05L118.81-3.05C118.81 3.57742 113.437 8.95 106.81 8.95L106.81 8.95C100.183 8.95 94.81 3.57742 94.81-3.05L94.81-3.05C94.81-9.67742 100.183-15.05 106.81-15.05L106.81-15.05C113.437-15.05 118.81-9.67742 118.81-3.05Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M62.94-88.04C60.24-88.04 57.73-86.68 56.25-84.43L50.59-75.8L42.41-75.8C39.25-75.8 37.67-75.8 36.35-75.59C29.08-74.44 23.37-68.73 22.22-61.46C22.01-60.13 22.01-58.56 22.01-55.4L22.01-44.14C22.01-42.49 23.35-41.14 25.01-41.14C26.67-41.14 28.01-42.49 28.01-44.14L28.01-55.4C28.01-58.78 28.03-59.78 28.15-60.52C28.89-65.22 32.58-68.92 37.29-69.66C38.03-69.78 39.02-69.8 42.41-69.8L102.41-69.8C105.8-69.8 106.79-69.78 107.53-69.66C112.24-68.92 115.93-65.22 116.68-60.52C116.79-59.78 116.81-58.78 116.81-55.4L116.81-44.14C116.81-42.49 118.15-41.14 119.81-41.14C121.47-41.14 122.81-42.49 122.81-44.14L122.81-55.4C122.81-58.56 122.81-60.13 122.6-61.46C121.45-68.73 115.74-74.44 108.47-75.59C107.15-75.8 105.57-75.8 102.41-75.8L94.35-75.8C94.22-75.97 94.09-76.15 93.97-76.33L88.66-84.43C87.18-86.68 84.67-88.04 81.97-88.04L62.94-88.04ZM55.15-31.42C55.15-40.96 62.88-48.69 72.41-48.69C81.95-48.69 89.68-40.96 89.68-31.42C89.68-21.89 81.95-14.16 72.41-14.16C62.88-14.16 55.15-21.89 55.15-31.42Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M98.18-69.8L102.41-69.8C105.8-69.8 106.79-69.78 107.53-69.66C112.24-68.92 115.93-65.22 116.68-60.52C116.79-59.78 116.81-58.78 116.81-55.4L116.81-34.14C116.81-32.49 118.15-31.14 119.81-31.14C121.47-31.14 122.81-32.49 122.81-34.14L122.81-55.4C122.81-58.56 122.81-60.13 122.6-61.46C121.45-68.73 115.74-74.44 108.47-75.59C107.15-75.8 105.57-75.8 102.41-75.8L94.37-75.8L98.18-69.8Z"/> + </g> + <g id="Thin-M" transform="matrix(1 0 0 1 784.007 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.01-21.77C22.906-21.77 22.01-20.87 22.01-19.77L22.01-6.82C22.01-3.84 22.01-2.36 22.207-1.11C23.292 5.73 28.661 11.1 35.508 12.19C36.751 12.38 38.238 12.38 41.21 12.38L70.989 12.38C72.094 12.38 72.989 11.49 72.989 10.38C72.989 9.28 72.094 8.38 70.989 8.38L41.21 8.38C38.085 8.38 36.988 8.37 36.133 8.23C30.999 7.42 26.971 3.39 26.158-1.74C26.023-2.59 26.01-3.69 26.01-6.82L26.01-19.77C26.01-20.87 25.115-21.77 24.01-21.77Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M117.989-5L117.989-5C117.989 1.62742 112.616 7 105.989 7L105.989 7C99.3616 7 93.989 1.62742 93.989-5L93.989-5C93.989-11.6274 99.3616-17 105.989-17L105.989-17C112.616-17 117.989-11.6274 117.989-5Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M62.937-88.12C60.241-88.12 57.726-86.76 56.247-84.5L50.559-75.83L50.316-75.36L41.21-75.36C38.238-75.36 36.751-75.36 35.508-75.16C28.661-74.08 23.292-68.71 22.207-61.86C22.01-60.62 22.01-59.13 22.01-56.16L22.01-43.21C22.01-42.11 22.906-41.21 24.01-41.21C25.115-41.21 26.01-42.11 26.01-43.21L26.01-56.16C26.01-59.29 26.023-60.38 26.158-61.24C26.971-66.37 30.999-70.4 36.133-71.21C36.988-71.35 38.085-71.36 41.21-71.36L103.61-71.36C106.736-71.36 107.833-71.35 108.688-71.21C113.822-70.4 117.849-66.37 118.663-61.24C118.798-60.38 118.81-59.29 118.81-56.16L118.81-43.21C118.81-42.11 119.706-41.21 120.81-41.21C121.915-41.21 122.81-42.11 122.81-43.21L122.81-56.16C122.81-59.13 122.81-60.62 122.614-61.86C121.529-68.71 116.16-74.08 109.313-75.16C108.07-75.36 106.583-75.36 103.61-75.36L94.79-75.36C94.487-75.69 94.213-76.04 93.968-76.41L88.659-84.5C87.18-86.76 84.666-88.12 81.97-88.12L62.937-88.12ZM55.145-31.49C55.145-41.02 62.875-48.75 72.41-48.75C81.945-48.75 89.675-41.02 89.675-31.49C89.675-21.95 81.945-14.22 72.41-14.22C62.875-14.22 55.145-21.95 55.145-31.49Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M97.335-71.36L103.611-71.36C106.736-71.36 107.833-71.35 108.688-71.21C113.823-70.4 117.85-66.37 118.663-61.24C118.798-60.38 118.811-59.29 118.811-56.16L118.811-33.21C118.811-32.11 119.706-31.21 120.811-31.21C121.915-31.21 122.811-32.11 122.811-33.21L122.811-56.16C122.811-59.13 122.811-60.62 122.614-61.86C121.529-68.71 116.16-74.08 109.314-75.16C108.07-75.36 106.583-75.36 103.611-75.36L94.79-75.36L97.335-71.36Z"/> + </g> + <g id="Ultralight-M" transform="matrix(1 0 0 1 487.296 1126)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.135-21.78C22.513-21.78 22.01-21.28 22.01-20.66L22.01-6.13C22.01-3.34 22.01-1.95 22.194-0.78C23.211 5.63 28.245 10.67 34.663 11.69C35.829 11.87 37.223 11.87 40.01 11.87L71.573 11.87C72.194 11.87 72.698 11.37 72.698 10.74C72.698 10.12 72.194 9.62 71.573 9.62L40.01 9.62C37.137 9.62 35.962 9.61 35.015 9.46C29.559 8.6 25.281 4.32 24.416-1.14C24.267-2.08 24.26-3.26 24.26-6.13L24.26-20.66C24.26-21.28 23.756-21.78 23.135-21.78Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M117.698-4.99L117.698-4.99C117.698 1.63742 112.325 7.01 105.698 7.01L105.698 7.01C99.0706 7.01 93.698 1.63742 93.698-4.99L93.698-4.99C93.698-11.6174 99.0706-16.99 105.698-16.99L105.698-16.99C112.325-16.99 117.698-11.6174 117.698-4.99Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M62.935-87.12C60.239-87.12 57.724-85.76 56.245-83.5L50.58-74.87L40.01-74.87C37.223-74.87 35.829-74.87 34.663-74.68C28.245-73.67 23.211-68.63 22.194-62.21C22.01-61.05 22.01-59.65 22.01-56.87L22.01-42.35C22.01-41.73 22.513-41.23 23.135-41.23C23.756-41.23 24.26-41.73 24.26-42.35L24.26-56.87C24.26-59.74 24.267-60.91 24.416-61.86C25.281-67.32 29.559-71.6 35.015-72.46C35.962-72.61 37.137-72.62 40.01-72.62L104.81-72.62C107.683-72.62 108.857-72.61 109.804-72.46C115.26-71.6 119.538-67.32 120.403-61.86C120.553-60.91 120.56-59.74 120.56-56.87L120.56-42.35C120.56-41.73 121.063-41.23 121.685-41.23C122.306-41.23 122.81-41.73 122.81-42.35L122.81-56.87C122.81-59.65 122.81-61.05 122.625-62.21C121.608-68.63 116.574-73.67 110.156-74.68C108.99-74.87 107.597-74.87 104.81-74.87L94.355-74.87C94.218-75.04 94.089-75.22 93.966-75.41L88.657-83.5C87.179-85.76 84.664-87.12 81.968-87.12L62.935-87.12ZM55.144-31.5C55.144-41.04 62.874-48.77 72.409-48.77C81.944-48.77 89.674-41.04 89.674-31.5C89.674-21.97 81.944-14.24 72.409-14.24C62.874-14.24 55.144-21.97 55.144-31.5Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M95.864-72.62L104.81-72.62C107.683-72.62 108.857-72.61 109.804-72.46C115.26-71.6 119.538-67.32 120.403-61.86C120.553-60.91 120.56-59.74 120.56-56.87L120.56-32.35C120.56-31.73 121.063-31.23 121.685-31.23C122.306-31.23 122.81-31.73 122.81-32.35L122.81-56.87C122.81-59.65 122.81-61.05 122.625-62.21C121.608-68.63 116.574-73.67 110.156-74.68C108.99-74.87 107.597-74.87 104.81-74.87L94.432-74.87L95.864-72.62Z"/> + </g> + <g id="Black-S" transform="matrix(1 0 0 1 2868.71 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M29.01-27.484C25.14-27.484 22.01-24.35 22.01-20.484L22.01-18.896C22.01-7.85 30.96 1.104 42.01 1.104L58.27 1.104C62.14 1.104 65.27-2.03 65.27-5.896C65.27-9.762 62.14-12.896 58.27-12.896L42.01-12.896C38.7-12.896 36.01-15.582 36.01-18.896L36.01-20.484C36.01-24.35 32.88-27.484 29.01-27.484Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-12.398L104.36-12.398C104.36-6.59901 99.659-1.898 93.86-1.898L93.86-1.898C88.061-1.898 83.36-6.59901 83.36-12.398L83.36-12.398C83.36-18.197 88.061-22.898 93.86-22.898L93.86-22.898C99.659-22.898 104.36-18.197 104.36-12.398Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.96-81.766C52.53-81.766 50.23-80.663 48.71-78.768L42.12-70.539L42.01-70.539C30.96-70.539 22.01-61.585 22.01-50.539L22.01-49.919C22.01-46.053 25.14-42.919 29.01-42.919C32.88-42.919 36.01-46.053 36.01-49.919L36.01-50.539C36.01-53.853 38.7-56.539 42.01-56.539L87.36-56.539C90.67-56.539 93.36-53.853 93.36-50.539L93.36-49.919C93.36-46.053 96.49-42.919 100.36-42.919C104.23-42.919 107.36-46.053 107.36-49.919L107.36-50.539C107.36-61.585 98.41-70.539 87.36-70.539L87.25-70.539L80.66-78.768C79.14-80.663 76.84-81.766 74.41-81.766L54.96-81.766ZM51.22-34.722C51.22-42.159 57.25-48.188 64.68-48.188C72.12-48.188 78.15-42.159 78.15-34.722C78.15-27.286 72.12-21.257 64.68-21.257C57.25-21.257 51.22-27.286 51.22-34.722Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M92.69-53.297C93.12-52.471 93.36-51.532 93.36-50.537L93.36-38.917C93.36-35.051 96.49-31.917 100.36-31.917C104.23-31.917 107.36-35.051 107.36-38.917L107.36-50.537C107.36-61.583 98.41-70.537 87.36-70.537L87.25-70.537L87.18-70.625L92.69-53.297Z"/> + </g> + <g id="Heavy-S" transform="matrix(1 0 0 1 2572 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M28.26-26.477C24.81-26.477 22.01-23.678 22.01-20.227L22.01-17.464C22.01-6.97 30.51 1.536 41.01 1.536L58.73 1.536C62.18 1.536 64.98-1.262 64.98-4.714C64.98-8.165 62.18-10.964 58.73-10.964L41.01-10.964C37.42-10.964 34.51-13.874 34.51-17.464L34.51-20.227C34.51-23.678 31.71-26.477 28.26-26.477Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-11.961L104.36-11.961C104.36-6.16201 99.659-1.461 93.86-1.461L93.86-1.461C88.061-1.461 83.36-6.16201 83.36-11.961L83.36-11.961C83.36-17.76 88.061-22.461 93.86-22.461L93.86-22.461C99.659-22.461 104.36-17.76 104.36-11.961Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.95-80.328C52.53-80.328 50.23-79.225 48.71-77.33L42.92-70.102L41.01-70.102C30.51-70.102 22.01-61.595 22.01-51.102L22.01-48.156C22.01-44.704 24.81-41.906 28.26-41.906C31.71-41.906 34.51-44.704 34.51-48.156L34.51-51.102C34.51-54.691 37.42-57.602 41.01-57.602L88.36-57.602C91.95-57.602 94.86-54.691 94.86-51.102L94.86-48.156C94.86-44.704 97.66-41.906 101.11-41.906C104.56-41.906 107.36-44.704 107.36-48.156L107.36-51.102C107.36-61.595 98.85-70.102 88.36-70.102L86.45-70.102L80.66-77.33C79.14-79.225 76.84-80.328 74.41-80.328L54.95-80.328ZM51.22-34.285C51.22-41.722 57.25-47.75 64.68-47.75C72.12-47.75 78.15-41.722 78.15-34.285C78.15-26.848 72.12-20.82 64.68-20.82C57.25-20.82 51.22-26.848 51.22-34.285Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M93.32-55.291C94.28-54.158 94.86-52.694 94.86-51.094L94.86-38.148C94.86-34.697 97.66-31.898 101.11-31.898C104.56-31.898 107.36-34.697 107.36-38.148L107.36-51.094C107.36-61.587 98.85-70.094 88.36-70.094L86.45-70.094L86.39-70.164L93.32-55.291Z"/> + </g> + <g id="Bold-S" transform="matrix(1 0 0 1 2275.29 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M27.26-26.477C24.36-26.477 22.01-24.126 22.01-21.227L22.01-16.432C22.01-6.491 30.07 1.568 40.01 1.568L59.45 1.568C62.35 1.568 64.7-0.783 64.7-3.682C64.7-6.582 62.35-8.932 59.45-8.932L40.01-8.932C35.87-8.932 32.51-12.29 32.51-16.432L32.51-21.227C32.51-24.126 30.16-26.477 27.26-26.477Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-11.93L104.36-11.93C104.36-6.13101 99.659-1.43 93.86-1.43L93.86-1.43C88.061-1.43 83.36-6.13101 83.36-11.93L83.36-11.93C83.36-17.729 88.061-22.43 93.86-22.43L93.86-22.43C99.659-22.43 104.36-17.729 104.36-11.93Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.96-80.305C52.53-80.305 50.23-79.202 48.71-77.307L42.91-70.07L40.01-70.07C30.07-70.07 22.01-62.011 22.01-52.07L22.01-47.156C22.01-44.257 24.36-41.906 27.26-41.906C30.16-41.906 32.51-44.257 32.51-47.156L32.51-52.07C32.51-56.212 35.87-59.57 40.01-59.57L89.36-59.57C93.5-59.57 96.86-56.212 96.86-52.07L96.86-47.156C96.86-44.257 99.21-41.906 102.11-41.906C105.01-41.906 107.36-44.257 107.36-47.156L107.36-52.07C107.36-62.011 99.3-70.07 89.36-70.07L86.45-70.07L80.66-77.307C79.14-79.202 76.84-80.305 74.41-80.305L54.96-80.305ZM51.22-34.254C51.22-41.69 57.25-47.719 64.68-47.719C72.12-47.719 78.15-41.69 78.15-34.254C78.15-26.817 72.12-20.789 64.68-20.789C57.25-20.789 51.22-26.817 51.22-34.254Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M95-57.013C96.16-55.693 96.86-53.964 96.86-52.07L96.86-38.156C96.86-35.257 99.21-32.906 102.11-32.906C105.01-32.906 107.36-35.257 107.36-38.156L107.36-52.07C107.36-62.011 99.3-70.07 89.36-70.07L86.5-70.07L95-57.013Z"/> + </g> + <g id="Semibold-S" transform="matrix(1 0 0 1 1978.58 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.63-24.562C24.08-24.562 22.01-22.492 22.01-19.938L22.01-13.46C22.01-4.071 29.62 3.54 39.01 3.54L60.77 3.54C63.32 3.54 65.39 1.47 65.39-1.085C65.39-3.639 63.32-5.71 60.77-5.71L39.01-5.71C34.73-5.71 31.26-9.179 31.26-13.46L31.26-19.938C31.26-22.492 29.19-24.562 26.63-24.562Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.961L104.36-9.961C104.36-4.16201 99.659 0.539 93.86 0.539L93.86 0.539C88.061 0.539 83.36-4.16201 83.36-9.961L83.36-9.961C83.36-15.76 88.061-20.461 93.86-20.461L93.86-20.461C99.659-20.461 104.36-15.76 104.36-9.961Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M54.95-78.336C52.52-78.336 50.23-77.233 48.71-75.338L42.91-68.102L39.01-68.102C29.62-68.102 22.01-60.49 22.01-51.102L22.01-44.621C22.01-42.067 24.08-39.996 26.63-39.996C29.19-39.996 31.26-42.067 31.26-44.621L31.26-51.102C31.26-55.382 34.73-58.852 39.01-58.852L90.36-58.852C94.64-58.852 98.11-55.382 98.11-51.102L98.11-44.621C98.11-42.067 100.18-39.996 102.73-39.996C105.29-39.996 107.36-42.067 107.36-44.621L107.36-51.102C107.36-60.49 99.74-68.102 90.36-68.102L86.45-68.102L80.65-75.338C79.13-77.233 76.84-78.336 74.41-78.336L54.95-78.336ZM51.22-32.285C51.22-39.722 57.25-45.75 64.68-45.75C72.12-45.75 78.15-39.722 78.15-32.285C78.15-24.848 72.12-18.82 64.68-18.82C57.25-18.82 51.22-24.848 51.22-32.285Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M94.72-57.507C96.76-56.112 98.11-53.763 98.11-51.102L98.11-36.621C98.11-34.067 100.18-31.996 102.73-31.996C105.28-31.996 107.36-34.067 107.36-36.621L107.36-51.102C107.36-60.49 99.74-68.102 90.36-68.102L86.49-68.102L94.72-57.507Z"/> + </g> + <g id="Medium-S" transform="matrix(1 0 0 1 1681.87 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M26.13-24.484C23.86-24.484 22.01-22.638 22.01-20.359L22.01-12.518C22.01-3.682 29.17 3.482 38.01 3.482L60.99 3.482C63.27 3.482 65.12 1.635 65.12-0.643C65.12-2.921 63.27-4.768 60.99-4.768L38.01-4.768C33.73-4.768 30.26-8.238 30.26-12.518L30.26-20.359C30.26-22.638 28.41-24.484 26.13-24.484Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-10.016L104.36-10.016C104.36-4.21701 99.659 0.484 93.86 0.484L93.86 0.484C88.061 0.484 83.36-4.21701 83.36-10.016L83.36-10.016C83.36-15.815 88.061-20.516 93.86-20.516L93.86-20.516C99.659-20.516 104.36-15.815 104.36-10.016Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M55.34-79.383C52.91-79.383 50.62-78.28 49.1-76.385L42.5-68.156L38.01-68.156C29.17-68.156 22.01-60.993 22.01-52.156L22.01-44.039C22.01-41.761 23.86-39.914 26.13-39.914C28.41-39.914 30.26-41.761 30.26-44.039L30.26-52.156C30.26-56.436 33.73-59.906 38.01-59.906L91.36-59.906C95.64-59.906 99.11-56.436 99.11-52.156L99.11-44.039C99.11-41.761 100.96-39.914 103.23-39.914C105.51-39.914 107.36-41.761 107.36-44.039L107.36-52.156C107.36-60.993 100.2-68.156 91.36-68.156L87.63-68.156L81.04-76.385C79.52-78.28 77.23-79.383 74.8-79.383L55.34-79.383ZM51.22-32.332C51.22-39.768 57.25-45.797 64.68-45.797C72.12-45.797 78.15-39.768 78.15-32.332C78.15-24.895 72.12-18.867 64.68-18.867C57.25-18.867 51.22-24.895 51.22-32.332Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M94.64-59.179C97.28-57.944 99.11-55.264 99.11-52.156L99.11-36.039C99.11-33.761 100.96-31.914 103.23-31.914C105.51-31.914 107.36-33.761 107.36-36.039L107.36-52.156C107.36-60.993 100.2-68.156 91.36-68.156L87.67-68.156L94.64-59.179Z"/> + </g> + <g id="Regular-S" transform="matrix(1 0 0 1 1385.15 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M29.16-20.878L29.16-11.354C29.16-7.019 32.68-3.504 37.01-3.504L61.26-3.504C63.24-3.504 64.84-1.904 64.84 0.071C64.84 2.045 63.24 3.646 61.26 3.646L37.01 3.646C28.73 3.646 22.01-3.07 22.01-11.354L22.01-20.878C22.01-22.853 23.61-24.453 25.59-24.453C27.56-24.453 29.16-22.853 29.16-20.878Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.852L104.36-9.852C104.36-4.05301 99.659 0.648 93.86 0.648L93.86 0.648C88.061 0.648 83.36-4.05301 83.36-9.852L83.36-9.852C83.36-15.651 88.061-20.352 93.86-20.352L93.86-20.352C99.659-20.352 104.36-15.651 104.36-9.852Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.71-76.229C50.23-78.124 52.53-79.227 54.96-79.227L74.42-79.227C76.84-79.227 79.14-78.124 80.66-76.229L87.26-67.992L92.36-67.992C100.65-67.992 107.36-61.276 107.36-52.992L107.36-43.458C107.36-41.483 105.76-39.883 103.79-39.883C101.81-39.883 100.21-41.483 100.21-43.458L100.21-52.992C100.21-57.328 96.7-60.842 92.36-60.842L37.01-60.842C32.68-60.842 29.16-57.328 29.16-52.992L29.16-43.458C29.16-41.483 27.56-39.883 25.59-39.883C23.61-39.883 22.01-41.483 22.01-43.458L22.01-52.992C22.01-61.276 28.73-67.992 37.01-67.992L42.12-67.992L48.71-76.229ZM64.69-45.641C57.25-45.641 51.22-39.612 51.22-32.176C51.22-24.739 57.25-18.711 64.69-18.711C72.12-18.711 78.15-24.739 78.15-32.176C78.15-39.612 72.12-45.641 64.69-45.641Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M92.8-60.829C96.93-60.601 100.21-57.179 100.21-52.991L100.21-35.457C100.21-33.483 101.81-31.882 103.79-31.882C105.76-31.882 107.36-33.483 107.36-35.457L107.36-52.991C107.36-61.276 100.65-67.991 92.36-67.991L87.26-67.991L86.66-68.742L92.8-60.829Z"/> + </g> + <g id="Light-S" transform="matrix(1 0 0 1 1088.44 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M24.76-24.562C23.24-24.562 22.01-23.331 22.01-21.812L22.01-10.464C22.01-2.732 28.28 3.536 36.01 3.536L61.8 3.536C63.32 3.536 64.55 2.305 64.55 0.786C64.55-0.732 63.32-1.964 61.8-1.964L36.01-1.964C31.32-1.964 27.51-5.769 27.51-10.464L27.51-21.812C27.51-23.331 26.28-24.562 24.76-24.562Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.961L104.36-9.961C104.36-4.16201 99.659 0.539 93.86 0.539L93.86 0.539C88.061 0.539 83.36-4.16201 83.36-9.961L83.36-9.961C83.36-15.76 88.061-20.461 93.86-20.461L93.86-20.461C99.659-20.461 104.36-15.76 104.36-9.961Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.72-75.33C50.23-77.225 52.53-78.328 54.96-78.328L74.42-78.328C76.85-78.328 79.14-77.225 80.66-75.33L86.45-68.102L93.36-68.102C101.09-68.102 107.36-61.834 107.36-54.102L107.36-42.742C107.36-41.223 106.13-39.992 104.61-39.992C103.09-39.992 101.86-41.223 101.86-42.742L101.86-54.102C101.86-58.796 98.06-62.602 93.36-62.602L36.01-62.602C31.32-62.602 27.51-58.796 27.51-54.102L27.51-42.742C27.51-41.223 26.28-39.992 24.76-39.992C23.24-39.992 22.01-41.223 22.01-42.742L22.01-54.102C22.01-61.834 28.28-68.102 36.01-68.102L42.92-68.102L48.72-75.33ZM64.69-45.75C57.25-45.75 51.22-39.722 51.22-32.285C51.22-24.848 57.25-18.82 64.69-18.82C72.12-18.82 78.15-24.848 78.15-32.285C78.15-39.722 72.12-45.75 64.69-45.75Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M90.78-62.602L93.36-62.602C98.06-62.602 101.86-58.796 101.86-54.102L101.86-34.742C101.86-33.223 103.09-31.992 104.61-31.992C106.13-31.992 107.36-33.223 107.36-34.742L107.36-54.102C107.36-61.834 101.09-68.102 93.36-68.102L86.51-68.102L90.78-62.602Z"/> + </g> + <g id="Thin-S" transform="matrix(1 0 0 1 791.732 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.635-24.484C22.738-24.484 22.01-23.757 22.01-22.859L22.01-9.385C22.01-2.206 27.83 3.615 35.01 3.615L63.624 3.615C64.522 3.615 65.249 2.887 65.249 1.99C65.249 1.092 64.522 0.365 63.624 0.365L35.01 0.365C29.625 0.365 25.26-4.001 25.26-9.385L25.26-22.859C25.26-23.757 24.533-24.484 23.635-24.484Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.883L104.36-9.883C104.36-4.08401 99.659 0.617 93.86 0.617L93.86 0.617C88.061 0.617 83.36-4.08401 83.36-9.883L83.36-9.883C83.36-15.682 88.061-20.383 93.86-20.383L93.86-20.383C99.659-20.383 104.36-15.682 104.36-9.883Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.713-75.26C50.231-77.155 52.528-78.258 54.956-78.258L74.414-78.258C76.842-78.258 79.139-77.155 80.657-75.26L86.455-68.023L94.36-68.023C101.54-68.023 107.36-62.203 107.36-55.023L107.36-41.539C107.36-40.642 106.633-39.914 105.735-39.914C104.838-39.914 104.11-40.642 104.11-41.539L104.11-55.023C104.11-60.408 99.745-64.773 94.36-64.773L35.01-64.773C29.625-64.773 25.26-60.408 25.26-55.023L25.26-41.539C25.26-40.642 24.533-39.914 23.635-39.914C22.738-39.914 22.01-40.642 22.01-41.539L22.01-55.023C22.01-62.203 27.83-68.023 35.01-68.023L42.914-68.023L48.713-75.26ZM64.685-45.672C57.249-45.672 51.22-39.643 51.22-32.207C51.22-24.77 57.249-18.742 64.685-18.742C72.122-18.742 78.15-24.77 78.15-32.207C78.15-39.643 72.122-45.672 64.685-45.672Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M89.016-64.773L94.36-64.773C99.745-64.773 104.11-60.408 104.11-55.023L104.11-33.539C104.11-32.642 104.838-31.914 105.735-31.914C106.633-31.914 107.36-32.642 107.36-33.539L107.36-55.023C107.36-62.203 101.54-68.023 94.36-68.023L86.492-68.023L89.016-64.773Z"/> + </g> + <g id="Ultralight-S" transform="matrix(1 0 0 1 495.021 696)"> + <path class="multicolor-0:custom hierarchical-0:primary SFSymbolsPreviewEA4335" d="M23.01-24.117C22.458-24.117 22.01-23.669 22.01-23.117L22.01-7.852C22.01-1.224 27.383 4.148 34.01 4.148L63.967 4.148C64.519 4.148 64.967 3.701 64.967 3.148C64.967 2.596 64.519 2.148 63.967 2.148L34.01 2.148C28.487 2.148 24.01-2.329 24.01-7.852L24.01-23.117C24.01-23.669 23.562-24.117 23.01-24.117Z"/> + <path class="multicolor-1:custom hierarchical-1:secondary SFSymbolsPreview34A853" d="M104.36-9.352L104.36-9.352C104.36-3.55301 99.659 1.148 93.86 1.148L93.86 1.148C88.061 1.148 83.36-3.55301 83.36-9.352L83.36-9.352C83.36-15.151 88.061-19.852 93.86-19.852L93.86-19.852C99.659-19.852 104.36-15.151 104.36-9.352Z"/> + <path class="multicolor-2:custom hierarchical-2:primary SFSymbolsPreview4183F0" d="M48.713-74.237C50.231-76.132 52.528-77.234 54.956-77.234L74.414-77.234C76.842-77.234 79.139-76.132 80.657-74.237L85.26-68.492L95.36-68.492C101.987-68.492 107.36-63.12 107.36-56.492L107.36-41.227C107.36-40.674 106.912-40.227 106.36-40.227C105.808-40.227 105.36-40.674 105.36-41.227L105.36-56.492C105.36-62.015 100.883-66.492 95.36-66.492L34.01-66.492C28.487-66.492 24.01-62.015 24.01-56.492L24.01-41.227C24.01-40.674 23.562-40.227 23.01-40.227C22.458-40.227 22.01-40.674 22.01-41.227L22.01-56.492C22.01-63.12 27.383-68.492 34.01-68.492L44.11-68.492L48.713-74.237ZM64.685-45.641C57.248-45.641 51.22-39.612 51.22-32.176C51.22-24.739 57.248-18.711 64.685-18.711C72.122-18.711 78.15-24.739 78.15-32.176C78.15-39.612 72.122-45.641 64.685-45.641Z"/> + <path class="multicolor-3:custom hierarchical-3:primary SFSymbolsPreviewFBBC04" d="M86.931-66.492L95.36-66.492C100.883-66.492 105.36-62.015 105.36-56.492L105.36-33.227C105.36-32.674 105.808-32.227 106.36-32.227C106.912-32.227 107.36-32.674 107.36-33.227L107.36-56.492C107.36-63.12 101.987-68.492 95.36-68.492L85.378-68.492L86.931-66.492Z"/> + </g> + </g> </svg>
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 6059719..a37cac1 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -1156,6 +1156,11 @@ "MediaFoundationD3D11VideoCapture", base::FEATURE_DISABLED_BY_DEFAULT); +// Enable zero-copy based on MediaFoundation video capture with D3D11. +BASE_FEATURE(kMediaFoundationD3D11VideoCaptureZeroCopy, + "MediaFoundationD3D11VideoCaptureZeroCopy", + base::FEATURE_DISABLED_BY_DEFAULT); + // Enables VP8 decode acceleration for Windows. const base::Feature MEDIA_EXPORT kMediaFoundationVP8Decoding{ "MediaFoundationVP8Decoding", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 4995ab1..e3005778 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -368,6 +368,7 @@ // For feature check of kMediaFoundationD3D11VideoCapture at runtime, // please use IsMediaFoundationD3D11VideoCaptureEnabled() instead. MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaFoundationD3D11VideoCapture); +MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaFoundationD3D11VideoCaptureZeroCopy); MEDIA_EXPORT BASE_DECLARE_FEATURE(kMediaFoundationClearPlayback); MEDIA_EXPORT BASE_DECLARE_FEATURE(kAllowMediaFoundationFrameServerMode);
diff --git a/media/capture/video/chromeos/mock_video_capture_client.cc b/media/capture/video/chromeos/mock_video_capture_client.cc index fd38373..484ed50 100644 --- a/media/capture/video/chromeos/mock_video_capture_client.cc +++ b/media/capture/video/chromeos/mock_video_capture_client.cc
@@ -72,7 +72,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) { + const gfx::Rect& visible_rect) { if (frame_cb_) std::move(frame_cb_).Run(); }
diff --git a/media/capture/video/chromeos/mock_video_capture_client.h b/media/capture/video/chromeos/mock_video_capture_client.h index 7d15e09..4ed142a 100644 --- a/media/capture/video/chromeos/mock_video_capture_client.h +++ b/media/capture/video/chromeos/mock_video_capture_client.h
@@ -60,7 +60,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) override; + const gfx::Rect& visible_rect) override; // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>. ReserveResult ReserveOutputBuffer(const gfx::Size& dimensions, VideoPixelFormat format,
diff --git a/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc b/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc index 4a8101e3..1b4f5bd9 100644 --- a/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc +++ b/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc
@@ -164,7 +164,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) override { + const gfx::Rect& visible_rect) override { NOTREACHED_NORETURN(); } void OnIncomingCapturedBuffer(Buffer buffer,
diff --git a/media/capture/video/mock_video_capture_device_client.h b/media/capture/video/mock_video_capture_device_client.h index a4e7142..ac7f70b6 100644 --- a/media/capture/video/mock_video_capture_device_client.h +++ b/media/capture/video/mock_video_capture_device_client.h
@@ -43,7 +43,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_size)); + const gfx::Rect& visible_rect)); MOCK_METHOD4(ReserveOutputBuffer, ReserveResult(const gfx::Size&, VideoPixelFormat, int, Buffer*)); MOCK_METHOD3(OnError,
diff --git a/media/capture/video/video_capture_buffer_pool.h b/media/capture/video/video_capture_buffer_pool.h index 1300668..6662d544 100644 --- a/media/capture/video/video_capture_buffer_pool.h +++ b/media/capture/video/video_capture_buffer_pool.h
@@ -87,13 +87,20 @@ virtual void RelinquishProducerReservation(int buffer_id) = 0; // Reserve a buffer id to use for a buffer specified by |handle| (which was - // allocated by some external source). This call cannot fail (no allocation is - // done). It may return a new id, or may reuse an existing id, if the buffer - // represented by |handle| is already being tracked. The behavior of - // |buffer_id_to_drop| is the same as ReserveForProducer. - virtual int ReserveIdForExternalBuffer( - const gfx::GpuMemoryBufferHandle& handle, - int* buffer_id_to_drop) = 0; + // allocated by some external source). + + // For windows, |handle| is used to create buffer, but not on mac. |format| is + // the source texture format, it should be NV12 now. |dimensions| is used + // for create buffer on Windows. If the pool is already at maximum capacity, + // return the reused ID based on LRU strategy. Otherwise, return a new tracker + // ID via |buffer_id|. The behavior of |buffer_id_to_drop| is the same as + // ReserveForProducer. + virtual VideoCaptureDevice::Client::ReserveResult ReserveIdForExternalBuffer( + gfx::GpuMemoryBufferHandle handle, + VideoPixelFormat format, + const gfx::Size& dimensions, + int* buffer_id_to_drop, + int* buffer_id) = 0; // Returns a snapshot of the current number of buffers in-use divided by the // maximum |count_|.
diff --git a/media/capture/video/video_capture_buffer_pool_impl.cc b/media/capture/video/video_capture_buffer_pool_impl.cc index 3fc260b..aabde7b 100644 --- a/media/capture/video/video_capture_buffer_pool_impl.cc +++ b/media/capture/video/video_capture_buffer_pool_impl.cc
@@ -118,9 +118,15 @@ tracker->SetHeldByProducer(false); } -int VideoCaptureBufferPoolImpl::ReserveIdForExternalBuffer( - const gfx::GpuMemoryBufferHandle& handle, - int* buffer_id_to_drop) { +VideoCaptureDevice::Client::ReserveResult +VideoCaptureBufferPoolImpl::ReserveIdForExternalBuffer( + gfx::GpuMemoryBufferHandle handle, + VideoPixelFormat format, + const gfx::Size& dimensions, + int* buffer_id_to_drop, + int* buffer_id) { + DCHECK(buffer_id); + DCHECK(buffer_id_to_drop); base::AutoLock lock(lock_); // Look for a tracker that matches this buffer and is not in use. While @@ -129,12 +135,14 @@ auto lru_tracker_it = trackers_.end(); for (auto it = trackers_.begin(); it != trackers_.end(); ++it) { VideoCaptureBufferTracker* const tracker = it->second.get(); - if (tracker->IsHeldByProducerOrConsumer()) + if (tracker->IsHeldByProducerOrConsumer()) { continue; + } if (tracker->IsSameGpuMemoryBuffer(handle)) { tracker->SetHeldByProducer(true); - return it->first; + *buffer_id = it->first; + return VideoCaptureDevice::Client::ReserveResult::kSucceeded; } if (lru_tracker_it == trackers_.end() || @@ -154,10 +162,20 @@ // Create the new tracker. const int new_buffer_id = next_buffer_id_++; auto tracker = - buffer_tracker_factory_->CreateTrackerForExternalGpuMemoryBuffer(handle); + buffer_tracker_factory_->CreateTrackerForExternalGpuMemoryBuffer( + std::move(handle)); +#if BUILDFLAG(IS_WIN) + // Windows needs to create buffer from external handle, but not on mac. + if (!tracker || !tracker->Init(dimensions, format, nullptr)) { + DLOG(ERROR) << "Error initializing VideoCaptureBufferTracker"; + *buffer_id = kInvalidId; + return VideoCaptureDevice::Client::ReserveResult::kAllocationFailed; + } +#endif tracker->SetHeldByProducer(true); trackers_[new_buffer_id] = std::move(tracker); - return new_buffer_id; + *buffer_id = new_buffer_id; + return VideoCaptureDevice::Client::ReserveResult::kSucceeded; } void VideoCaptureBufferPoolImpl::HoldForConsumers(int buffer_id,
diff --git a/media/capture/video/video_capture_buffer_pool_impl.h b/media/capture/video/video_capture_buffer_pool_impl.h index 215c9df6..b5f183a5f 100644 --- a/media/capture/video/video_capture_buffer_pool_impl.h +++ b/media/capture/video/video_capture_buffer_pool_impl.h
@@ -59,8 +59,12 @@ int* buffer_id, int* buffer_id_to_drop) override; void RelinquishProducerReservation(int buffer_id) override; - int ReserveIdForExternalBuffer(const gfx::GpuMemoryBufferHandle& handle, - int* buffer_id_to_drop) override; + VideoCaptureDevice::Client::ReserveResult ReserveIdForExternalBuffer( + gfx::GpuMemoryBufferHandle handle, + VideoPixelFormat format, + const gfx::Size& dimensions, + int* buffer_id_to_drop, + int* buffer_id) override; double GetBufferPoolUtilization() const override; void HoldForConsumers(int buffer_id, int num_clients) override; void RelinquishConsumerHold(int buffer_id, int num_clients) override;
diff --git a/media/capture/video/video_capture_buffer_pool_util.cc b/media/capture/video/video_capture_buffer_pool_util.cc index 0af0a15..e9c0d86d 100644 --- a/media/capture/video/video_capture_buffer_pool_util.cc +++ b/media/capture/video/video_capture_buffer_pool_util.cc
@@ -46,8 +46,13 @@ // On Windows, for GMB backed zero-copy more buffers are needed because it's // routinely observed that it runs out of default buffer count when just // displaying 60 FPS media in a video element + + // It's confirmed that MFCaptureEngine may terminate the capture with + // MF_E_SAMPLEALLOCATOR_EMPTY error if more than 10 buffers are held by the + // client. Usually there are 3-5 frames in flight, unless there's some + // micro-freeze in the renderer or the gpu service. if (switches::IsVideoCaptureUseGpuMemoryBufferEnabled()) { - max_buffer_count = 30; + max_buffer_count = 10; } #endif
diff --git a/media/capture/video/video_capture_buffer_tracker_factory.h b/media/capture/video/video_capture_buffer_tracker_factory.h index c9cb9fd1..4fc16f868 100644 --- a/media/capture/video/video_capture_buffer_tracker_factory.h +++ b/media/capture/video/video_capture_buffer_tracker_factory.h
@@ -25,7 +25,7 @@ VideoCaptureBufferType buffer_type) = 0; virtual std::unique_ptr<VideoCaptureBufferTracker> CreateTrackerForExternalGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle) = 0; + gfx::GpuMemoryBufferHandle handle) = 0; }; } // namespace media
diff --git a/media/capture/video/video_capture_buffer_tracker_factory_impl.cc b/media/capture/video/video_capture_buffer_tracker_factory_impl.cc index 1756e1d..e00e850 100644 --- a/media/capture/video/video_capture_buffer_tracker_factory_impl.cc +++ b/media/capture/video/video_capture_buffer_tracker_factory_impl.cc
@@ -39,7 +39,7 @@ std::unique_ptr<VideoCaptureBufferTracker> VideoCaptureBufferTrackerFactoryImpl::CreateTrackerForExternalGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle) { + gfx::GpuMemoryBufferHandle handle) { #if BUILDFLAG(IS_MAC) return std::make_unique<GpuMemoryBufferTrackerMac>(handle.io_surface); #else
diff --git a/media/capture/video/video_capture_buffer_tracker_factory_impl.h b/media/capture/video/video_capture_buffer_tracker_factory_impl.h index 1dd7ca7..4666552 100644 --- a/media/capture/video/video_capture_buffer_tracker_factory_impl.h +++ b/media/capture/video/video_capture_buffer_tracker_factory_impl.h
@@ -19,7 +19,7 @@ VideoCaptureBufferType buffer_type) override; std::unique_ptr<VideoCaptureBufferTracker> CreateTrackerForExternalGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle) override; + gfx::GpuMemoryBufferHandle handle) override; }; } // namespace media
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h index e321ba18..6bf0b7d 100644 --- a/media/capture/video/video_capture_device.h +++ b/media/capture/video/video_capture_device.h
@@ -220,7 +220,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) = 0; + const gfx::Rect& visible_rect) = 0; // Reserve an output buffer into which contents can be captured directly. // The returned |buffer| will always be allocated with a memory size
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc index 37d9616..df0aa91 100644 --- a/media/capture/video/video_capture_device_client.cc +++ b/media/capture/video/video_capture_device_client.cc
@@ -487,9 +487,16 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) { - auto ready_frame = CreateReadyFrameFromExternalBuffer( - std::move(buffer), reference_time, timestamp, visible_rect); + const gfx::Rect& visible_rect) { + ReadyFrameInBuffer ready_frame; + if (CreateReadyFrameFromExternalBuffer( + std::move(buffer), reference_time, timestamp, visible_rect, + &ready_frame) != ReserveResult::kSucceeded) { + DVLOG(2) << __func__ + << " CreateReadyFrameFromExternalBuffer failed: reservation " + "trakcer failed."; + return; + } std::vector<ReadyFrameInBuffer> scaled_ready_frames; scaled_ready_frames.reserve(scaled_buffers.size()); for (auto& scaled_buffer : scaled_buffers) { @@ -498,25 +505,40 @@ // be removed in another CL. gfx::Rect scaled_buffer_visible_rect = gfx::Rect{scaled_buffer.format.frame_size}; - scaled_ready_frames.push_back(CreateReadyFrameFromExternalBuffer( - std::move(scaled_buffer), reference_time, timestamp, - scaled_buffer_visible_rect)); + ReadyFrameInBuffer scaled_ready_frame; + if (CreateReadyFrameFromExternalBuffer( + std::move(scaled_buffer), reference_time, timestamp, + scaled_buffer_visible_rect, + &scaled_ready_frame) != ReserveResult::kSucceeded) { + DVLOG(2) << __func__ + << " CreateReadyFrameFromExternalBuffer failed: scaled frame " + "reservation trakcer failed."; + return; + } + scaled_ready_frames.push_back(std::move(scaled_ready_frame)); } receiver_->OnFrameReadyInBuffer(std::move(ready_frame), std::move(scaled_ready_frames)); } -ReadyFrameInBuffer VideoCaptureDeviceClient::CreateReadyFrameFromExternalBuffer( +VideoCaptureDevice::Client::ReserveResult +VideoCaptureDeviceClient::CreateReadyFrameFromExternalBuffer( CapturedExternalVideoBuffer buffer, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) { + const gfx::Rect& visible_rect, + ReadyFrameInBuffer* ready_buffer) { // Reserve an ID for this buffer that will not conflict with any of the IDs // used by |buffer_pool_|. int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; - int buffer_id = buffer_pool_->ReserveIdForExternalBuffer(buffer.handle, - &buffer_id_to_drop); - + // Use std::move to transfer the handle ownership here since the buffer will + // be created and confirm each ScopedHandle can only have one owner at a + // time. + int buffer_id = VideoCaptureBufferPool::kInvalidId; + VideoCaptureDevice::Client::ReserveResult reservation_result_code = + buffer_pool_->ReserveIdForExternalBuffer( + std::move(buffer.handle), buffer.format.pixel_format, + visible_rect.size(), &buffer_id_to_drop, &buffer_id); // If a buffer to retire was specified, retire one. if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) { auto entry_iter = @@ -527,11 +549,18 @@ } } + if (reservation_result_code != ReserveResult::kSucceeded) { + return reservation_result_code; + } + // Register the buffer with the receiver if it is new. if (!base::Contains(buffer_ids_known_by_receiver_, buffer_id)) { + // On windows, 'GetGpuMemoryBufferHandle' will duplicate a new handle which + // refers to the same object as the original handle. + // https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-duplicatehandle media::mojom::VideoBufferHandlePtr buffer_handle = media::mojom::VideoBufferHandle::NewGpuMemoryBufferHandle( - std::move(buffer.handle)); + buffer_pool_->GetGpuMemoryBufferHandle(buffer_id)); receiver_->OnNewBuffer(buffer_id, std::move(buffer_handle)); buffer_ids_known_by_receiver_.push_back(buffer_id); } @@ -550,11 +579,12 @@ buffer_pool_->HoldForConsumers(buffer_id, 1); buffer_pool_->RelinquishProducerReservation(buffer_id); - return ReadyFrameInBuffer( + *ready_buffer = ReadyFrameInBuffer( buffer_id, 0 /* frame_feedback_id */, std::make_unique<ScopedBufferPoolReservation<ConsumerReleaseTraits>>( buffer_pool_, buffer_id), std::move(info)); + return VideoCaptureDevice::Client::ReserveResult::kSucceeded; } VideoCaptureDevice::Client::ReserveResult
diff --git a/media/capture/video/video_capture_device_client.h b/media/capture/video/video_capture_device_client.h index f7f32f0..fa9e9216 100644 --- a/media/capture/video/video_capture_device_client.h +++ b/media/capture/video/video_capture_device_client.h
@@ -87,7 +87,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) override; + const gfx::Rect& visible_rect) override; ReserveResult ReserveOutputBuffer(const gfx::Size& dimensions, VideoPixelFormat format, int frame_feedback_id, @@ -113,11 +113,12 @@ double GetBufferPoolUtilization() const override; private: - ReadyFrameInBuffer CreateReadyFrameFromExternalBuffer( + VideoCaptureDevice::Client::ReserveResult CreateReadyFrameFromExternalBuffer( CapturedExternalVideoBuffer buffer, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect); + const gfx::Rect& visible_rect, + ReadyFrameInBuffer* ready_buffer); // A branch of OnIncomingCapturedData for Y16 frame_format.pixel_format. void OnIncomingCapturedY16Data(const uint8_t* data,
diff --git a/media/capture/video/video_frame_receiver.cc b/media/capture/video/video_frame_receiver.cc index f34d7046..42507db 100644 --- a/media/capture/video/video_frame_receiver.cc +++ b/media/capture/video/video_frame_receiver.cc
@@ -8,6 +8,8 @@ namespace media { +ReadyFrameInBuffer::ReadyFrameInBuffer() = default; + ReadyFrameInBuffer::ReadyFrameInBuffer( int buffer_id, int frame_feedback_id,
diff --git a/media/capture/video/video_frame_receiver.h b/media/capture/video/video_frame_receiver.h index 5cf234e..c59e7d1 100644 --- a/media/capture/video/video_frame_receiver.h +++ b/media/capture/video/video_frame_receiver.h
@@ -15,6 +15,7 @@ namespace media { struct CAPTURE_EXPORT ReadyFrameInBuffer { + ReadyFrameInBuffer(); ReadyFrameInBuffer( int buffer_id, int frame_feedback_id,
diff --git a/media/capture/video/win/gpu_memory_buffer_tracker.cc b/media/capture/video/win/gpu_memory_buffer_tracker.cc index 8a61c2192..daa88c6 100644 --- a/media/capture/video/win/gpu_memory_buffer_tracker.cc +++ b/media/capture/video/win/gpu_memory_buffer_tracker.cc
@@ -76,6 +76,14 @@ : dxgi_device_manager_(std::move(dxgi_device_manager)), d3d_device_(dxgi_device_manager_->GetDevice()) {} +GpuMemoryBufferTracker::GpuMemoryBufferTracker( + gfx::GpuMemoryBufferHandle gmb_handle, + scoped_refptr<DXGIDeviceManager> dxgi_device_manager) + : dxgi_device_manager_(std::move(dxgi_device_manager)), + d3d_device_(dxgi_device_manager_->GetDevice()), + external_dxgi_handle_(std::move(gmb_handle)), + is_external_dxgi_handle_(true) {} + GpuMemoryBufferTracker::~GpuMemoryBufferTracker() = default; bool GpuMemoryBufferTracker::Init(const gfx::Size& dimensions, @@ -87,24 +95,39 @@ return false; } - buffer_size_ = dimensions; + if (is_external_dxgi_handle_) { + return CreateBufferInternal(std::move(external_dxgi_handle_), + std::move(dimensions)); + } - return CreateBufferInternal(); + gfx::GpuMemoryBufferHandle gmb_handle; + gmb_handle.dxgi_handle = CreateNV12Texture(d3d_device_.Get(), dimensions); + gmb_handle.dxgi_token = gfx::DXGIHandleToken(); + return CreateBufferInternal(std::move(gmb_handle), std::move(dimensions)); } -bool GpuMemoryBufferTracker::CreateBufferInternal() { - gfx::GpuMemoryBufferHandle buffer_handle; - buffer_handle.dxgi_handle = - CreateNV12Texture(d3d_device_.Get(), buffer_size_); - buffer_handle.dxgi_token = gfx::DXGIHandleToken(); +bool GpuMemoryBufferTracker::IsSameGpuMemoryBuffer( + const gfx::GpuMemoryBufferHandle& handle) const { + // This function is used for reusing external buffer. + if (!is_external_dxgi_handle_) { + return false; + } + // On Windows, we need use 'dxgi_token' to decide whether the two handles + // point to same gmb instead of handle directly since handle could be + // duplicated, please see GpuMemoryBufferImplDXGI::CloneHandle. + return buffer_->GetToken() == handle.dxgi_token; +} +bool GpuMemoryBufferTracker::CreateBufferInternal( + gfx::GpuMemoryBufferHandle buffer_handle, + const gfx::Size& dimensions) { if (!buffer_handle.dxgi_handle.IsValid()) { - LOG(ERROR) << "Failed to create NV12 texture"; + LOG(ERROR) << "dxgi_handle is not valid."; return false; } buffer_ = gpu::GpuMemoryBufferImplDXGI::CreateFromHandle( - std::move(buffer_handle), buffer_size_, + std::move(buffer_handle), std::move(dimensions), gfx::BufferFormat::YUV_420_BIPLANAR, gfx::BufferUsage::GPU_READ, gpu::GpuMemoryBufferImpl::DestructionCallback(), nullptr, nullptr); if (!buffer_) { @@ -136,8 +159,9 @@ const gfx::Size& dimensions, VideoPixelFormat format, const mojom::PlaneStridesPtr& strides) { + // External buffer is never reused. return !IsD3DDeviceChanged() && (format == PIXEL_FORMAT_NV12) && - (dimensions == buffer_->GetSize()); + (dimensions == buffer_->GetSize()) && !is_external_dxgi_handle_; } std::unique_ptr<VideoCaptureBufferHandle>
diff --git a/media/capture/video/win/gpu_memory_buffer_tracker.h b/media/capture/video/win/gpu_memory_buffer_tracker.h index 9e2f47c..53d6f790 100644 --- a/media/capture/video/win/gpu_memory_buffer_tracker.h +++ b/media/capture/video/win/gpu_memory_buffer_tracker.h
@@ -25,6 +25,8 @@ public: explicit GpuMemoryBufferTracker( scoped_refptr<DXGIDeviceManager> dxgi_device_manager); + GpuMemoryBufferTracker(gfx::GpuMemoryBufferHandle gmb_handle, + scoped_refptr<DXGIDeviceManager> dxgi_device_manager); GpuMemoryBufferTracker(const GpuMemoryBufferTracker&) = delete; GpuMemoryBufferTracker& operator=(const GpuMemoryBufferTracker&) = delete; @@ -35,6 +37,8 @@ bool Init(const gfx::Size& dimensions, VideoPixelFormat format, const mojom::PlaneStridesPtr& strides) override; + bool IsSameGpuMemoryBuffer( + const gfx::GpuMemoryBufferHandle& handle) const override; bool IsReusableForFormat(const gfx::Size& dimensions, VideoPixelFormat format, const mojom::PlaneStridesPtr& strides) override; @@ -45,15 +49,22 @@ gfx::GpuMemoryBufferHandle GetGpuMemoryBufferHandle() override; private: + bool CreateBufferInternal(gfx::GpuMemoryBufferHandle buffer_handle, + const gfx::Size& dimensions); + bool IsD3DDeviceChanged(); + std::unique_ptr<gpu::GpuMemoryBufferImplDXGI> buffer_; scoped_refptr<DXGIDeviceManager> dxgi_device_manager_; Microsoft::WRL::ComPtr<ID3D11Device> d3d_device_; base::UnsafeSharedMemoryRegion region_; base::WritableSharedMemoryMapping mapping_; Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture_; - gfx::Size buffer_size_; - bool CreateBufferInternal(); - bool IsD3DDeviceChanged(); + // |external_dxgi_handle_| is valid until Init() call. + gfx::GpuMemoryBufferHandle external_dxgi_handle_; + // If |is_external_dxgi_handle_| is true, the handle originally isn't created + // by chromium. Currently it indicates the producer of handle is + // MFVideoCaptureEngine. + bool is_external_dxgi_handle_ = false; }; } // namespace media
diff --git a/media/capture/video/win/video_capture_buffer_tracker_factory_win.cc b/media/capture/video/win/video_capture_buffer_tracker_factory_win.cc index c89e739..eabbbe7 100644 --- a/media/capture/video/win/video_capture_buffer_tracker_factory_win.cc +++ b/media/capture/video/win/video_capture_buffer_tracker_factory_win.cc
@@ -37,9 +37,13 @@ std::unique_ptr<VideoCaptureBufferTracker> VideoCaptureBufferTrackerFactoryWin::CreateTrackerForExternalGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle) { - // Not supported - return nullptr; + gfx::GpuMemoryBufferHandle handle) { + if (handle.type != gfx::DXGI_SHARED_HANDLE) { + return nullptr; + } + + return std::make_unique<GpuMemoryBufferTracker>(std::move(handle), + dxgi_device_manager_); } -} // namespace media \ No newline at end of file +} // namespace media
diff --git a/media/capture/video/win/video_capture_buffer_tracker_factory_win.h b/media/capture/video/win/video_capture_buffer_tracker_factory_win.h index db8fdcd..04d5360 100644 --- a/media/capture/video/win/video_capture_buffer_tracker_factory_win.h +++ b/media/capture/video/win/video_capture_buffer_tracker_factory_win.h
@@ -24,7 +24,7 @@ VideoCaptureBufferType buffer_type) override; std::unique_ptr<VideoCaptureBufferTracker> CreateTrackerForExternalGpuMemoryBuffer( - const gfx::GpuMemoryBufferHandle& handle) override; + gfx::GpuMemoryBufferHandle handle) override; private: scoped_refptr<DXGIDeviceManager> dxgi_device_manager_; @@ -33,4 +33,4 @@ } // namespace media -#endif // MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_BUFFER_TRACKER_FACTORY_WIN_H_ \ No newline at end of file +#endif // MEDIA_CAPTURE_VIDEO_WIN_VIDEO_CAPTURE_BUFFER_TRACKER_FACTORY_WIN_H_
diff --git a/media/capture/video/win/video_capture_device_mf_win.cc b/media/capture/video/win/video_capture_device_mf_win.cc index eb07243..c69abbc 100644 --- a/media/capture/video/win/video_capture_device_mf_win.cc +++ b/media/capture/video/win/video_capture_device_mf_win.cc
@@ -11,7 +11,9 @@ #include <mferror.h> #include <stddef.h> #include <wincodec.h> +#include <wrl/implements.h> +#include <d3d11.h> #include <memory> #include <thread> #include <utility> @@ -32,6 +34,7 @@ #include "base/trace_event/trace_event.h" #include "base/win/scoped_co_mem.h" #include "base/win/windows_version.h" +#include "media/base/media_switches.h" #include "media/base/win/color_space_util_win.h" #include "media/capture/mojom/image_capture_types.h" #include "media/capture/video/blob_utils.h" @@ -39,6 +42,7 @@ #include "media/capture/video/win/sink_filter_win.h" #include "media/capture/video/win/video_capture_device_utils_win.h" #include "ui/gfx/color_space.h" +#include "ui/gfx/gpu_memory_buffer.h" using base::Location; using base::win::ScopedCoMem; @@ -59,6 +63,15 @@ namespace { +// Provide an unique GUID for reusing |handle| and |token| by +// SetPrivateDataInterface/GetPrivateData. +// {79BFE1AB-CE47-4C3D-BDB2-06E6B886368C} +constexpr GUID DXGIHandlePrivateDataGUID = { + 0x79bfe1ab, + 0xce47, + 0x4c3d, + {0xbd, 0xb2, 0x6, 0xe6, 0xb8, 0x86, 0x36, 0x8c}}; + // How many times we try to restart D3D11 path. constexpr int kMaxD3DRestarts = 2; @@ -555,9 +568,10 @@ return hr; } -void GetTextureSizeAndFormat(ID3D11Texture2D* texture, - gfx::Size& size, - VideoPixelFormat& format) { +void GetTextureInfo(ID3D11Texture2D* texture, + gfx::Size& size, + VideoPixelFormat& format, + bool& is_cross_process_shared_texture) { D3D11_TEXTURE2D_DESC desc; texture->GetDesc(&desc); size.set_width(desc.Width); @@ -574,19 +588,19 @@ break; } - // Log this in an UMA histogram to determine what proportion of frames might - // actually benefit from zero-copy. - // According to // https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_resource_misc_flag, // D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE and // D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE_DRIVER only support shared // texture on same process. - bool is_cross_process_shared_texture = + is_cross_process_shared_texture = (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED) && (desc.MiscFlags & D3D11_RESOURCE_MISC_SHARED_NTHANDLE) && !(desc.MiscFlags & D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE) && !(desc.MiscFlags & D3D11_RESOURCE_MISC_RESTRICT_SHARED_RESOURCE_DRIVER); + + // Log this in an UMA histogram to determine what proportion of frames might + // actually benefit from zero-copy. base::UmaHistogramBoolean("Media.VideoCapture.Win.Device.IsSharedTexture", is_cross_process_shared_texture); } @@ -637,6 +651,23 @@ // Destruction helper. Can't use base::DoNothingAs<> since ComPtr isn't POD. void DestroyCaptureEngine(Microsoft::WRL::ComPtr<IMFCaptureEngine>) {} +class DXGIHandlePrivateData + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IUnknown> { + public: + explicit DXGIHandlePrivateData(base::win::ScopedHandle texture_handle) + : texture_handle_(std::move(texture_handle)) {} + + gfx::DXGIHandleToken GetDXGIToken() { return dxgi_token_; } + HANDLE GetTextureHandle() { return texture_handle_.get(); } + + private: + gfx::DXGIHandleToken dxgi_token_; + const base::win::ScopedHandle texture_handle_; + ~DXGIHandlePrivateData() override = default; +}; + } // namespace class VideoCaptureDeviceMFWin::MFVideoCallback final @@ -1947,12 +1978,20 @@ gfx::Size texture_size; VideoPixelFormat pixel_format; - GetTextureSizeAndFormat(texture, texture_size, pixel_format); + bool is_cross_process_shared_texture; + GetTextureInfo(texture, texture_size, pixel_format, + is_cross_process_shared_texture); if (pixel_format != PIXEL_FORMAT_NV12) { return MF_E_UNSUPPORTED_FORMAT; } + if (base::FeatureList::IsEnabled(kMediaFoundationD3D11VideoCaptureZeroCopy) && + is_cross_process_shared_texture) { + return DeliverExternalBufferToClient(texture, texture_size, pixel_format, + reference_time, timestamp); + } + VideoCaptureDevice::Client::Buffer capture_buffer; constexpr int kDummyFrameFeedbackId = 0; auto result = client_->ReserveOutputBuffer( @@ -2020,6 +2059,72 @@ return hr; } +HRESULT VideoCaptureDeviceMFWin::DeliverExternalBufferToClient( + ID3D11Texture2D* texture, + const gfx::Size& texture_size, + const VideoPixelFormat& pixel_format, + base::TimeTicks reference_time, + base::TimeDelta timestamp) { + UINT private_data_size; + Microsoft::WRL::ComPtr<DXGIHandlePrivateData> private_data; + HRESULT hr = + texture->GetPrivateData(DXGIHandlePrivateDataGUID, &private_data_size, + static_cast<void**>(&private_data)); + + if (SUCCEEDED(hr) && private_data) { + DCHECK_EQ(private_data_size, static_cast<UINT>(sizeof(&private_data))); + } else { + // It's failed to get valid |private_data|, create and set a new value. + Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource; + hr = texture->QueryInterface(IID_PPV_ARGS(&dxgi_resource)); + if (FAILED(hr)) { + DLOG(ERROR) << logging::SystemErrorCodeToString(hr); + return hr; + } + HANDLE texture_handle; + hr = dxgi_resource->CreateSharedHandle( + nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, + nullptr, &texture_handle); + if (FAILED(hr)) { + DLOG(ERROR) << logging::SystemErrorCodeToString(hr); + return hr; + } + private_data = Microsoft::WRL::Make<DXGIHandlePrivateData>( + base::win::ScopedHandle(texture_handle)); + + hr = texture->SetPrivateDataInterface(DXGIHandlePrivateDataGUID, + private_data.Get()); + if (FAILED(hr)) { + DLOG(ERROR) << "failed to set private data to texture, " + << logging::SystemErrorCodeToString(hr); + return hr; + } + } + + // Set reused |token| and |share_handle| to gmb handle. + gfx::GpuMemoryBufferHandle gmb_handle; + gmb_handle.type = gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE; + HANDLE texture_handle_duplicated = nullptr; + CHECK(::DuplicateHandle(GetCurrentProcess(), private_data->GetTextureHandle(), + GetCurrentProcess(), &texture_handle_duplicated, 0, + FALSE, DUPLICATE_SAME_ACCESS)) + << "failed to reuse handle."; + + gmb_handle.dxgi_handle.Set(texture_handle_duplicated); + gmb_handle.dxgi_token = private_data->GetDXGIToken(); + + client_->OnIncomingCapturedExternalBuffer( + media::CapturedExternalVideoBuffer( + std::move(gmb_handle), + VideoCaptureFormat( + texture_size, + selected_video_capability_->supported_format.frame_rate, + pixel_format), + gfx::ColorSpace()), + {}, reference_time, timestamp, gfx::Rect(texture_size)); + return hr; +} + void VideoCaptureDeviceMFWin::OnIncomingCapturedDataInternal( Microsoft::WRL::ComPtr<IMFMediaBuffer> buffer, base::TimeTicks reference_time,
diff --git a/media/capture/video/win/video_capture_device_mf_win.h b/media/capture/video/win/video_capture_device_mf_win.h index 62800d2..1738b602 100644 --- a/media/capture/video/win/video_capture_device_mf_win.h +++ b/media/capture/video/win/video_capture_device_mf_win.h
@@ -166,6 +166,11 @@ HRESULT DeliverTextureToClient(ID3D11Texture2D* texture, base::TimeTicks reference_time, base::TimeDelta timestamp); + HRESULT DeliverExternalBufferToClient(ID3D11Texture2D* texture, + const gfx::Size& texture_size, + const VideoPixelFormat& pixel_format, + base::TimeTicks reference_time, + base::TimeDelta timestamp); void OnCameraControlChangeInternal(REFGUID control_set, UINT32 id); void OnIncomingCapturedDataInternal( Microsoft::WRL::ComPtr<IMFMediaBuffer> buffer,
diff --git a/media/capture/video/win/video_capture_device_mf_win_unittest.cc b/media/capture/video/win/video_capture_device_mf_win_unittest.cc index 44091f1..f53339f 100644 --- a/media/capture/video/win/video_capture_device_mf_win_unittest.cc +++ b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
@@ -88,7 +88,7 @@ std::vector<CapturedExternalVideoBuffer> scaled_buffers, base::TimeTicks reference_time, base::TimeDelta timestamp, - gfx::Rect visible_rect) override {} + const gfx::Rect& visible_rect) override {} MOCK_METHOD4(ReserveOutputBuffer, ReserveResult(const gfx::Size&, VideoPixelFormat, int, Buffer*));
diff --git a/media/filters/decrypting_demuxer_stream.cc b/media/filters/decrypting_demuxer_stream.cc index 60c8a08..e923620 100644 --- a/media/filters/decrypting_demuxer_stream.cc +++ b/media/filters/decrypting_demuxer_stream.cc
@@ -272,6 +272,16 @@ return; } + if (HasClearLead()) { + if (pending_buffer_to_decrypt_->decrypt_config()->encryption_scheme() != + EncryptionScheme::kUnencrypted && + !switched_clear_to_encrypted_) { + MEDIA_LOG(INFO, media_log_) + << "Stream switched from clear to encrypted buffers."; + switched_clear_to_encrypted_ = true; + } + } + decryptor_->Decrypt(GetDecryptorStreamType(), pending_buffer_to_decrypt_, base::BindPostTaskToCurrentDefault(base::BindOnce( &DecryptingDemuxerStream::OnBufferDecrypted,
diff --git a/media/filters/decrypting_demuxer_stream.h b/media/filters/decrypting_demuxer_stream.h index 7f00f05..07969de 100644 --- a/media/filters/decrypting_demuxer_stream.h +++ b/media/filters/decrypting_demuxer_stream.h
@@ -177,6 +177,8 @@ absl::optional<bool> has_clear_lead_; + bool switched_clear_to_encrypted_ = false; + // The buffer returned by the demuxer that needs to be decrypted. scoped_refptr<media::DecoderBuffer> pending_buffer_to_decrypt_;
diff --git a/media/filters/video_decoder_stream_unittest.cc b/media/filters/video_decoder_stream_unittest.cc index 5404e13..4ed49c27 100644 --- a/media/filters/video_decoder_stream_unittest.cc +++ b/media/filters/video_decoder_stream_unittest.cc
@@ -141,6 +141,8 @@ EXPECT_MEDIA_LOG(HasSubstr("audio")).Times(AnyNumber()); EXPECT_MEDIA_LOG(HasSubstr("Audio")).Times(AnyNumber()); EXPECT_MEDIA_LOG(HasSubstr("decryptor")).Times(AnyNumber()); + EXPECT_MEDIA_LOG(HasSubstr("clear to encrypted buffers")) + .Times(AnyNumber()); } VideoDecoderStreamTest(const VideoDecoderStreamTest&) = delete;
diff --git a/media/gpu/chromeos/oop_video_decoder.cc b/media/gpu/chromeos/oop_video_decoder.cc index 5fd2381..bc078b26 100644 --- a/media/gpu/chromeos/oop_video_decoder.cc +++ b/media/gpu/chromeos/oop_video_decoder.cc
@@ -249,7 +249,7 @@ void OnDecoderDisconnected() { base::AutoLock lock(lock_); - configs_ = {}; + configs_.emplace(); decoder_type_ = absl::nullopt; interface_version_ = absl::nullopt; disconnected_ = true; @@ -278,7 +278,7 @@ decoder_type_ = decoder_type; } else { // The remote decoder is of an unexpected type, so let's assume it's bad. - configs_ = {}; + configs_.emplace(); } MaybeNotifyWaitingCallbacks();
diff --git a/net/BUILD.gn b/net/BUILD.gn index b9ea9f3..382eaaa 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -1731,6 +1731,10 @@ "//third_party/boringssl", "//url", ] + + if (chrome_root_store_supported) { + public_deps += [ "//net/cert:root_store_proto_lite" ] + } } if (is_android) {
diff --git a/net/android/BUILD.gn b/net/android/BUILD.gn index b464c0e..c9b605d 100644 --- a/net/android/BUILD.gn +++ b/net/android/BUILD.gn
@@ -79,7 +79,6 @@ ":embedded_test_server_aidl_java", ":net_java", "//base:base_java", - "//base:base_java_test_support", "//base:base_java_url_utils_for_test", "//base:jni_java", "//third_party/androidx:androidx_annotation_annotation_java", @@ -145,7 +144,9 @@ # Used as an additional_apk in test scripts. never_incremental = true - enable_multidex = true + # Multidex requires a custom Application class to initialize it. Simpler to + # just disable it. + enable_multidex = false # Required on Android Q+ to read from /sdcard when installing certs. target_sdk_version = 28
diff --git a/net/android/java/src/org/chromium/net/X509Util.java b/net/android/java/src/org/chromium/net/X509Util.java index 54e02dec..a9e3dba1 100644 --- a/net/android/java/src/org/chromium/net/X509Util.java +++ b/net/android/java/src/org/chromium/net/X509Util.java
@@ -163,11 +163,6 @@ private static boolean sLoadedSystemKeyStore; /** - * A root that will be installed as a user-trusted root for testing purposes. - */ - private static X509Certificate sTestRoot; - - /** * Lock object used to synchronize all calls that modify or depend on the trust managers. */ private static final Object sLock = new Object(); @@ -324,24 +319,17 @@ new ByteArrayInputStream(derBytes)); } - /** - * Add a test root certificate for use by the Android Platform verifier. - */ public static void addTestRootCertificate(byte[] rootCertBytes) throws CertificateException, KeyStoreException, NoSuchAlgorithmException { X509Certificate rootCert = createCertificateFromBytes(rootCertBytes); synchronized (sLock) { ensureTestInitializedLocked(); - // Add the cert to be used by the Android Platform Verifier. sTestKeyStore.setCertificateEntry( "root_cert_" + Integer.toString(sTestKeyStore.size()), rootCert); reloadTestTrustManager(); } } - /** - * Clear test root certificates in use by the Android Platform verifier. - */ public static void clearTestRootCertificates() throws NoSuchAlgorithmException, CertificateException, KeyStoreException { synchronized (sLock) { @@ -355,22 +343,6 @@ } } - /** - * Set a test root certificate for use by CertVerifierBuiltin. - */ - public static void setTestRootCertificateForBuiltin(byte[] rootCertBytes) - throws NoSuchAlgorithmException, CertificateException, KeyStoreException { - X509Certificate rootCert = createCertificateFromBytes(rootCertBytes); - synchronized (sLock) { - // Add the cert to be used by CertVerifierBuiltin. - // - // This saves the root so it is returned from getUserAddedRoots, for TrustStoreAndroid. - // This is done for the Java EmbeddedTestServer implementation and must run before - // native code is loaded, when getUserAddedRoots is first run. - sTestRoot = rootCert; - } - } - private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', @@ -531,14 +503,6 @@ Log.e(TAG, "Error reading cert aliases: %s", e); return new byte[0][]; } - - if (sTestRoot != null) { - try { - userRootBytes.add(sTestRoot.getEncoded()); - } catch (CertificateEncodingException e) { - Log.e(TAG, "Error encoding test root cert, error %s", e); - } - } } return userRootBytes.toArray(new byte[0][]);
diff --git a/net/cert/BUILD.gn b/net/cert/BUILD.gn index 98c67ba..7b6ddcd 100644 --- a/net/cert/BUILD.gn +++ b/net/cert/BUILD.gn
@@ -22,6 +22,7 @@ cc_generator_options = "lite=true:" visibility = [ "//net:net", + "//net:net_public_deps", "//services/cert_verifier:lib", "//services/cert_verifier:tests", ]
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h index 923a6e8..38bc9fef 100644 --- a/net/cert/cert_verify_proc.h +++ b/net/cert/cert_verify_proc.h
@@ -63,6 +63,10 @@ // (Note that this entirely disables the online revocation/AIA code paths. // Theoretically we could still check for cached results.) VERIFY_DISABLE_NETWORK_FETCHES = 1 << 4, + + // Also update GetNetConstants() in net/log/net_log_util.cc when updating + // this enum. + VERIFY_FLAGS_LAST = VERIFY_DISABLE_NETWORK_FETCHES }; // These values are persisted to logs. Entries should not be renumbered and
diff --git a/net/cert/ct_objects_extractor.cc b/net/cert/ct_objects_extractor.cc index 4e4cb47..cce0d91f 100644 --- a/net/cert/ct_objects_extractor.cc +++ b/net/cert/ct_objects_extractor.cc
@@ -21,11 +21,6 @@ namespace { -// The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of -// RFC6962. -const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, - 0xD6, 0x79, 0x02, 0x04, 0x02}; - // The wire form of the OID 1.3.6.1.4.1.11129.2.4.5 - OCSP SingleExtension for // X.509v3 Certificate Transparency Signed Certificate Timestamp List, see // Section 3.3 of RFC6962.
diff --git a/net/cert/ct_objects_extractor.h b/net/cert/ct_objects_extractor.h index b4d2b5a..3ca4dbe 100644 --- a/net/cert/ct_objects_extractor.h +++ b/net/cert/ct_objects_extractor.h
@@ -13,6 +13,11 @@ namespace net::ct { +// The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of +// RFC6962. +inline constexpr uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, + 0xD6, 0x79, 0x02, 0x04, 0x02}; + struct SignedEntryData; // Extracts a SignedCertificateTimestampList that has been embedded within a
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc index c5ac6b3..605c010 100644 --- a/net/http/bidirectional_stream_unittest.cc +++ b/net/http/bidirectional_stream_unittest.cc
@@ -593,7 +593,7 @@ // First attempt receives client auth request. SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); ssl_data1.next_proto = kProtoHTTP2; - ssl_data1.cert_request_info = cert_request.get(); + ssl_data1.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); StaticSocketDataProvider socket_data1;
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc index 0b96947..255313f 100644 --- a/net/http/http_network_transaction_unittest.cc +++ b/net/http/http_network_transaction_unittest.cc
@@ -16813,7 +16813,7 @@ // CertificateRequest is received for the first time, the handshake will // be aborted to allow the caller to provide a certificate. SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_data1.cert_request_info = cert_request.get(); + ssl_data1.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); StaticSocketDataProvider data1; session_deps_.socket_factory->AddSocketDataProvider(&data1); @@ -16825,7 +16825,7 @@ // rather than a Finished message, because it requires a client // certificate and none was supplied. SSLSocketDataProvider ssl_data2(ASYNC, ERR_SSL_PROTOCOL_ERROR); - ssl_data2.cert_request_info = cert_request.get(); + ssl_data2.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); StaticSocketDataProvider data2; session_deps_.socket_factory->AddSocketDataProvider(&data2); @@ -16839,7 +16839,7 @@ // fail. SSLSocketDataProvider ssl_data3(ASYNC, ERR_SSL_PROTOCOL_ERROR); ssl_data3.expected_disable_sha1_server_signatures = false; - ssl_data3.cert_request_info = cert_request.get(); + ssl_data3.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); StaticSocketDataProvider data3; session_deps_.socket_factory->AddSocketDataProvider(&data3); @@ -16917,7 +16917,7 @@ // the peer, the handshake is aborted during the Connect() call. // [ssl_]data1 represents the initial SSL handshake with the peer. SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_data1.cert_request_info = cert_request.get(); + ssl_data1.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); StaticSocketDataProvider data1; session_deps_.socket_factory->AddSocketDataProvider(&data1); @@ -16930,7 +16930,7 @@ // peer sending a handshake_failure because it requires a client // certificate. SSLSocketDataProvider ssl_data2(ASYNC, OK); - ssl_data2.cert_request_info = cert_request.get(); + ssl_data2.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data2); MockRead data2_reads[] = { MockRead(ASYNC /* async */, ERR_SSL_PROTOCOL_ERROR), @@ -16942,7 +16942,7 @@ // the data for the SSL handshake once the TLSv1.1 connection falls back to // TLSv1. It has the same behaviour as [ssl_]data2. SSLSocketDataProvider ssl_data3(ASYNC, OK); - ssl_data3.cert_request_info = cert_request.get(); + ssl_data3.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data3); StaticSocketDataProvider data3(data2_reads, base::span<MockWrite>()); session_deps_.socket_factory->AddSocketDataProvider(&data3); @@ -16950,14 +16950,14 @@ // [ssl_]data4 is the data for the SSL handshake once the TLSv1 connection // falls back to SSLv3. It has the same behaviour as [ssl_]data2. SSLSocketDataProvider ssl_data4(ASYNC, OK); - ssl_data4.cert_request_info = cert_request.get(); + ssl_data4.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data4); StaticSocketDataProvider data4(data2_reads, base::span<MockWrite>()); session_deps_.socket_factory->AddSocketDataProvider(&data4); // Need one more if TLSv1.2 is enabled. SSLSocketDataProvider ssl_data5(ASYNC, OK); - ssl_data5.cert_request_info = cert_request.get(); + ssl_data5.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data5); StaticSocketDataProvider data5(data2_reads, base::span<MockWrite>()); session_deps_.socket_factory->AddSocketDataProvider(&data5); @@ -17067,7 +17067,7 @@ // See ClientAuthCertCache_Direct_NoFalseStart for the explanation of // [ssl_]data[1-3]. SSLSocketDataProvider ssl_data1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_data1.cert_request_info = cert_request.get(); + ssl_data1.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); StaticSocketDataProvider data1; session_deps_.socket_factory->AddSocketDataProvider(&data1); @@ -17180,7 +17180,7 @@ // The first connection's handshake succeeds, but we get // ERR_SSL_CLIENT_AUTH_CERT_NEEDED instead of an HTTP response. SSLSocketDataProvider ssl_data1(ASYNC, OK); - ssl_data1.cert_request_info = cert_request.get(); + ssl_data1.cert_request_info = cert_request; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_data1); MockWrite data1_writes[] = { MockWrite("GET / HTTP/1.1\r\n" @@ -22092,7 +22092,7 @@ // First, the client connects to the proxy, which requests a client // certificate. SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_proxy1.cert_request_info = cert_request_info_proxy.get(); + ssl_proxy1.cert_request_info = cert_request_info_proxy; ssl_proxy1.expected_send_client_cert = false; StaticSocketDataProvider data1; session_deps_.socket_factory->AddSocketDataProvider(&data1); @@ -22124,7 +22124,7 @@ mock_reads2.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n"); // The origin requests client certificates. SSLSocketDataProvider ssl_origin2(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_origin2.cert_request_info = cert_request_info_origin.get(); + ssl_origin2.cert_request_info = cert_request_info_origin; StaticSocketDataProvider data2(mock_reads2, mock_writes2); session_deps_.socket_factory->AddSocketDataProvider(&data2); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy2); @@ -22279,7 +22279,7 @@ // First, the client connects to the proxy, which requests a client // certificate. SSLSocketDataProvider ssl_proxy1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_proxy1.cert_request_info = cert_request_info_proxy.get(); + ssl_proxy1.cert_request_info = cert_request_info_proxy; ssl_proxy1.expected_send_client_cert = false; StaticSocketDataProvider data1; session_deps_.socket_factory->AddSocketDataProvider(&data1); @@ -22321,7 +22321,7 @@ mock_reads3.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n"); // The origin requests client certificates. SSLSocketDataProvider ssl_origin3(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_origin3.cert_request_info = cert_request_info_origin.get(); + ssl_origin3.cert_request_info = cert_request_info_origin; StaticSocketDataProvider data3(mock_reads3, mock_writes3); session_deps_.socket_factory->AddSocketDataProvider(&data3); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy3); @@ -22531,7 +22531,7 @@ mock_reads1.emplace_back("HTTP/1.1 200 Connection Established\r\n\r\n"); // The origin requests client certificates. SSLSocketDataProvider ssl_origin1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl_origin1.cert_request_info = cert_request_info_origin.get(); + ssl_origin1.cert_request_info = cert_request_info_origin; StaticSocketDataProvider data1(mock_reads1, mock_writes1); session_deps_.socket_factory->AddSocketDataProvider(&data1); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_proxy1); @@ -22625,7 +22625,7 @@ StaticSocketDataProvider data1; session_deps_.socket_factory->AddSocketDataProvider(&data1); SSLSocketDataProvider ssl1(ASYNC, ERR_SSL_CLIENT_AUTH_CERT_NEEDED); - ssl1.cert_request_info = cert_request_info.get(); + ssl1.cert_request_info = cert_request_info; ssl1.expected_send_client_cert = false; session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl1); @@ -23831,7 +23831,7 @@ }; SequencedSocketData data_auth(kAuthReads, kAuthWrites); SSLSocketDataProvider ssl_auth(ASYNC, OK); - ssl_auth.cert_request_info = cert_request_info.get(); + ssl_auth.cert_request_info = cert_request_info; session_deps_.socket_factory->AddSocketDataProvider(&data_auth); session_deps_.socket_factory->AddSSLSocketDataProvider(&ssl_auth);
diff --git a/net/log/OWNERS b/net/log/OWNERS index 53e68eb7..b4c9fb4 100644 --- a/net/log/OWNERS +++ b/net/log/OWNERS
@@ -1 +1,2 @@ mmenke@chromium.org +mattm@chromium.org
diff --git a/net/log/net_log_util.cc b/net/log/net_log_util.cc index 6ff8edf..f4b6c8b 100644 --- a/net/log/net_log_util.cc +++ b/net/log/net_log_util.cc
@@ -166,6 +166,24 @@ } { + static_assert(CertVerifyProc::VERIFY_FLAGS_LAST == (1 << 4), + "Update with new flags"); + constants_dict.Set( + "certVerifyFlags", + base::Value::Dict() + .Set("VERIFY_REV_CHECKING_ENABLED", + CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) + .Set("VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS", + CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) + .Set("VERIFY_ENABLE_SHA1_LOCAL_ANCHORS", + CertVerifyProc::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS) + .Set("VERIFY_DISABLE_SYMANTEC_ENFORCEMENT", + CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT) + .Set("VERIFY_DISABLE_NETWORK_FETCHES", + CertVerifyProc::VERIFY_DISABLE_NETWORK_FETCHES)); + } + + { static_assert(SimplePathBuilderDelegate::DigestPolicy::kMaxValue == SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1, "Update with new flags");
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h index cf8115e..b492d4c2 100644 --- a/net/socket/socket_test_util.h +++ b/net/socket/socket_test_util.h
@@ -495,9 +495,7 @@ SSLInfo ssl_info; // Result for GetSSLCertRequestInfo(). - // This field is not a raw_ptr<> because it was filtered by the rewriter for: - // #union - RAW_PTR_EXCLUSION SSLCertRequestInfo* cert_request_info = nullptr; + scoped_refptr<SSLCertRequestInfo> cert_request_info; // Result for GetECHRetryConfigs(). std::vector<uint8_t> ech_retry_configs;
diff --git a/net/test/android/javatests/AndroidManifest.xml b/net/test/android/javatests/AndroidManifest.xml index e3ad40b6..830392b 100644 --- a/net/test/android/javatests/AndroidManifest.xml +++ b/net/test/android/javatests/AndroidManifest.xml
@@ -11,8 +11,7 @@ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET"/> - <application android:label="ChromiumNetTestSupport" - android:name="androidx.multidex.MultiDexApplication"> + <application android:label="ChromiumNetTestSupport"> <uses-library android:name="android.test.runner" />
diff --git a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java index de076f49..1b560e5 100644 --- a/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java +++ b/net/test/android/javatests/src/org/chromium/net/test/EmbeddedTestServer.java
@@ -18,8 +18,6 @@ import org.chromium.base.Log; import org.chromium.base.ThreadUtils; -import org.chromium.base.test.BaseJUnit4ClassRunner.ClassHook; -import org.chromium.base.test.util.UrlUtils; import org.chromium.net.X509Util; import org.chromium.net.test.util.CertTestUtil; @@ -527,31 +525,4 @@ throw new EmbeddedTestServerFailure("Failed to get root cert's path", e); } } - - public static ClassHook getPreClassHook() { - return (targetContext, testClass) -> EmbeddedTestServer.setUpClass(testClass); - } - - private static boolean sTestRootInitDone; - - public static void setUpClass(Class<?> clazz) { - if (sTestRootInitDone) { - return; - } - - // Always try to add the testing HTTPS root to the cert verifier. We do this here because we - // need this to happen before the native code loads the user-added roots, and this is the - // safest place to put it. - try { - // Use the same PEM file as net/test/embedded_test_server/embedded_test_server.cc. - String rootCertPemPath = - UrlUtils.getIsolatedTestFilePath("net/data/ssl/certificates/root_ca_cert.pem"); - byte[] rootCertBytesDer = CertTestUtil.pemToDer(rootCertPemPath); - X509Util.setTestRootCertificateForBuiltin(rootCertBytesDer); - sTestRootInitDone = true; - } catch (Exception e) { - throw new EmbeddedTestServer.EmbeddedTestServerFailure( - "Failed to install root certificate.", e); - } - } }
diff --git a/services/network/public/cpp/network_param_mojom_traits.cc b/services/network/public/cpp/network_param_mojom_traits.cc index 7ffec4bd..e59f90f6 100644 --- a/services/network/public/cpp/network_param_mojom_traits.cc +++ b/services/network/public/cpp/network_param_mojom_traits.cc
@@ -6,7 +6,9 @@ #include "base/memory/scoped_refptr.h" #include "base/notreached.h" +#include "mojo/public/cpp/base/time_mojom_traits.h" #include "mojo/public/cpp/bindings/struct_traits.h" +#include "net/log/net_log_source_type.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_client_cert_type.h" @@ -207,4 +209,21 @@ return true; } +// static +bool StructTraits<network::mojom::NetLogSourceDataView, net::NetLogSource>:: + Read(network::mojom::NetLogSourceDataView data, net::NetLogSource* out) { + if (data.source_type() >= + static_cast<uint32_t>(net::NetLogSourceType::COUNT)) { + return false; + } + base::TimeTicks start_time; + if (!data.ReadStartTime(&start_time)) { + return false; + } + *out = + net::NetLogSource(static_cast<net::NetLogSourceType>(data.source_type()), + data.source_id(), start_time); + return true; +} + } // namespace mojo
diff --git a/services/network/public/cpp/network_param_mojom_traits.h b/services/network/public/cpp/network_param_mojom_traits.h index ebfad9ab..03823c5c 100644 --- a/services/network/public/cpp/network_param_mojom_traits.h +++ b/services/network/public/cpp/network_param_mojom_traits.h
@@ -13,6 +13,7 @@ #include "net/base/proxy_server.h" #include "net/dns/public/resolve_error_info.h" #include "net/http/http_version.h" +#include "net/log/net_log_source.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_client_cert_type.h" #include "services/network/public/mojom/network_param.mojom-shared.h" @@ -170,6 +171,23 @@ scoped_refptr<net::SSLCertRequestInfo>* out); }; +template <> +struct COMPONENT_EXPORT(NETWORK_CPP_NETWORK_PARAM) + StructTraits<network::mojom::NetLogSourceDataView, net::NetLogSource> { + static uint32_t source_id(const net::NetLogSource& params) { + return params.id; + } + static uint32_t source_type(const net::NetLogSource& params) { + return static_cast<uint32_t>(params.type); + } + static base::TimeTicks start_time(const net::NetLogSource& params) { + return params.start_time; + } + + static bool Read(network::mojom::NetLogSourceDataView data, + net::NetLogSource* out); +}; + } // namespace mojo #endif // SERVICES_NETWORK_PUBLIC_CPP_NETWORK_PARAM_MOJOM_TRAITS_H_
diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc index 07fd0387..5c5632b 100644 --- a/services/network/public/cpp/url_request_mojom_traits.cc +++ b/services/network/public/cpp/url_request_mojom_traits.cc
@@ -14,8 +14,6 @@ #include "mojo/public/cpp/base/file_path_mojom_traits.h" #include "mojo/public/cpp/base/time_mojom_traits.h" #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h" -#include "net/log/net_log_source.h" -#include "net/log/net_log_source_type.h" #include "services/network/public/cpp/crash_keys.h" #include "services/network/public/cpp/http_request_headers_mojom_traits.h" #include "services/network/public/cpp/isolation_info_mojom_traits.h" @@ -122,22 +120,6 @@ return true; } -bool StructTraits<network::mojom::NetLogSourceDataView, net::NetLogSource>:: - Read(network::mojom::NetLogSourceDataView data, net::NetLogSource* out) { - if (data.source_type() >= - static_cast<uint32_t>(net::NetLogSourceType::COUNT)) { - return false; - } - base::TimeTicks start_time; - if (!data.ReadStartTime(&start_time)) { - return false; - } - *out = - net::NetLogSource(static_cast<net::NetLogSourceType>(data.source_type()), - data.source_id(), start_time); - return true; -} - bool StructTraits< network::mojom::URLRequestDataView, network::ResourceRequest>::Read(network::mojom::URLRequestDataView data,
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h index d49c105..549b0da 100644 --- a/services/network/public/cpp/url_request_mojom_traits.h +++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -163,23 +163,6 @@ template <> struct COMPONENT_EXPORT(NETWORK_CPP_BASE) - StructTraits<network::mojom::NetLogSourceDataView, net::NetLogSource> { - static uint32_t source_id(const net::NetLogSource& params) { - return params.id; - } - static uint32_t source_type(const net::NetLogSource& params) { - return static_cast<uint32_t>(params.type); - } - static base::TimeTicks start_time(const net::NetLogSource& params) { - return params.start_time; - } - - static bool Read(network::mojom::NetLogSourceDataView data, - net::NetLogSource* out); -}; - -template <> -struct COMPONENT_EXPORT(NETWORK_CPP_BASE) StructTraits<network::mojom::URLRequestDataView, network::ResourceRequest> { static const std::string& method(const network::ResourceRequest& request) { return request.method;
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index e78805c..d0437a0d 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -537,10 +537,6 @@ cpp = "::network::ResourceRequest::WebBundleTokenParams" }, { - mojom = "network.mojom.NetLogSource" - cpp = "::net::NetLogSource" - }, - { mojom = "network.mojom.URLRequest" cpp = "::network::ResourceRequest" forward_declaration = "namespace network { struct ResourceRequest; }" @@ -845,6 +841,10 @@ mojom = "network.mojom.HostPortPair" cpp = "::net::HostPortPair" }, + { + mojom = "network.mojom.NetLogSource" + cpp = "::net::NetLogSource" + }, ] traits_headers = [ "//services/network/public/cpp/network_param_mojom_traits.h" ]
diff --git a/services/network/public/mojom/network_param.mojom b/services/network/public/mojom/network_param.mojom index 17ad41b..89071921 100644 --- a/services/network/public/mojom/network_param.mojom +++ b/services/network/public/mojom/network_param.mojom
@@ -4,6 +4,7 @@ module network.mojom; +import "mojo/public/mojom/base/time.mojom"; import "url/mojom/scheme_host_port.mojom"; // Information related to an authentication challenge in an HTTP response. @@ -100,3 +101,10 @@ [Native] struct X509Certificate; + +// Typemapped to net::NetLogSource. +struct NetLogSource { + uint32 source_type; + uint32 source_id; + mojo_base.mojom.TimeTicks start_time; +};
diff --git a/services/network/public/mojom/url_request.mojom b/services/network/public/mojom/url_request.mojom index 4767f2af..237e3fbf 100644 --- a/services/network/public/mojom/url_request.mojom +++ b/services/network/public/mojom/url_request.mojom
@@ -120,15 +120,6 @@ int32 render_process_id; }; -// Options that may be set when URLRequests need to take over NetLog related -// parameters. The URLRequest will use these parameters on logging. -// Typemapped to net::NetLogSource. -struct NetLogSource { - uint32 source_type; - uint32 source_id; - mojo_base.mojom.TimeTicks start_time; -}; - // Typemapped to network::ResourceRequest. struct URLRequest { // The request method: GET, POST, etc.
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 8912829..280db582 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -5704,9 +5704,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5717,8 +5717,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -5736,9 +5736,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5749,8 +5749,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -5870,9 +5870,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5883,8 +5883,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -5901,9 +5901,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -5914,8 +5914,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -6016,9 +6016,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -6029,8 +6029,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -6048,9 +6048,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -6061,8 +6061,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.coverage.json b/testing/buildbot/chromium.coverage.json index c95e3a7..2ad2f075 100644 --- a/testing/buildbot/chromium.coverage.json +++ b/testing/buildbot/chromium.coverage.json
@@ -25462,9 +25462,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -25475,8 +25475,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -25494,9 +25494,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -25507,8 +25507,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -25628,9 +25628,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -25641,8 +25641,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -25659,9 +25659,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -25672,8 +25672,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -25774,9 +25774,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -25787,8 +25787,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -25806,9 +25806,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -25819,8 +25819,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index da8f22c..970840d 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -6254,6 +6254,108 @@ "14c18", "--xctest" ], + "isolate_name": "components_browsertests", + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "components_browsertests iPad Pro (12.9-inch) (3rd generation) 16.2", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:3e597065cb23c1fe03aeb2ebd792d83e0709c5c2" + } + ], + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Mac-12|Mac-13" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14c18", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_16_2", + "path": "Runtime-ios-16.2" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://components:components_browsertests/", + "variant_id": "iPad Pro (12.9-inch) (3rd generation) 16.2" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "16.2", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14c18", + "--xctest" + ], + "isolate_name": "components_browsertests", + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "components_browsertests iPhone X 16.2", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:3e597065cb23c1fe03aeb2ebd792d83e0709c5c2" + } + ], + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Mac-12|Mac-13" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14c18", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_16_2", + "path": "Runtime-ios-16.2" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://components:components_browsertests/", + "variant_id": "iPhone X 16.2" + }, + { + "args": [ + "--platform", + "iPad Pro (12.9-inch) (3rd generation)", + "--version", + "16.2", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14c18", + "--xctest" + ], "isolate_name": "components_unittests", "merge": { "script": "//testing/merge_scripts/standard_isolated_script_merge.py" @@ -45552,9 +45654,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45564,8 +45666,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -45584,9 +45686,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45596,8 +45698,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -45718,9 +45820,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45730,8 +45832,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -45749,9 +45851,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45761,8 +45863,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -45864,9 +45966,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45876,8 +45978,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -45896,9 +45998,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -45908,8 +46010,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -47341,9 +47443,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -47353,8 +47455,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -47373,9 +47475,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -47385,8 +47487,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -47507,9 +47609,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -47519,8 +47621,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -47538,9 +47640,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -47550,8 +47652,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -47653,9 +47755,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -47665,8 +47767,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -47685,9 +47787,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -47697,8 +47799,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -48402,9 +48504,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -48414,8 +48516,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -48433,9 +48535,9 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome" + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" }, @@ -48445,8 +48547,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/chromium.memory.fyi.json b/testing/buildbot/chromium.memory.fyi.json index fbbb382..56190d9 100644 --- a/testing/buildbot/chromium.memory.fyi.json +++ b/testing/buildbot/chromium.memory.fyi.json
@@ -209,7 +209,8 @@ "os": "Ubuntu-22.04" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "blink_unittests", "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" @@ -254,26 +255,6 @@ }, { "args": [ - "--test-launcher-print-test-stdio=always" - ], - "merge": { - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-22.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 10 - }, - "test": "browser_tests", - "test_id_prefix": "ninja://chrome/test:browser_tests/" - }, - { - "args": [ "--gtest_filter=-*UsingRealWebcam*", "--test-launcher-print-test-stdio=always" ], @@ -325,7 +306,8 @@ "os": "Ubuntu-22.04" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 }, "test": "cc_unittests", "test_id_prefix": "ninja://cc:cc_unittests/" @@ -401,7 +383,8 @@ "os": "Ubuntu-22.04" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "components_browsertests", "test_id_prefix": "ninja://components:components_browsertests/" @@ -420,7 +403,8 @@ "os": "Ubuntu-22.04" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "components_unittests", "test_id_prefix": "ninja://components:components_unittests/" @@ -459,7 +443,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 8 + "shards": 30 }, "test": "content_browsertests", "test_id_prefix": "ninja://content/test:content_browsertests/" @@ -529,25 +513,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "crashpad_tests", - "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" - }, - { - "args": [ - "--test-launcher-print-test-stdio=always" - ], - "merge": { - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-22.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "cronet_tests", "test_id_prefix": "ninja://components/cronet:cronet_tests/" }, @@ -802,7 +767,9 @@ { "args": [ "--use-cmd-decoder=passthrough", - "--test-launcher-print-test-stdio=always" + "--test-launcher-print-test-stdio=always", + "--use-gpu-in-tests", + "--no-xvfb" ], "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -812,7 +779,9 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Ubuntu-22.04" + "gpu": "10de:2184", + "os": "Ubuntu", + "pool": "chromium.tests.gpu" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -950,7 +919,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 + "shards": 32 }, "test": "interactive_ui_tests", "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/" @@ -1143,25 +1112,6 @@ ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" }, - "test": "nacl_loader_unittests", - "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" - }, - { - "args": [ - "--test-launcher-print-test-stdio=always" - ], - "merge": { - "script": "//testing/merge_scripts/standard_gtest_merge.py" - }, - "swarming": { - "can_use_on_swarming_builders": true, - "dimension_sets": [ - { - "os": "Ubuntu-22.04" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" - }, "test": "native_theme_unittests", "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" }, @@ -1179,7 +1129,8 @@ "os": "Ubuntu-22.04" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 }, "test": "net_unittests", "test_id_prefix": "ninja://net:net_unittests/" @@ -1503,7 +1454,7 @@ } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 3 + "shards": 6 }, "test": "sync_integration_tests", "test_id_prefix": "ninja://chrome/test:sync_integration_tests/" @@ -1560,7 +1511,8 @@ "os": "Ubuntu-22.04" } ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 2 }, "test": "unit_tests", "test_id_prefix": "ninja://chrome/test:unit_tests/"
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json index 619d3586..d041b8c 100644 --- a/testing/buildbot/chromium.memory.json +++ b/testing/buildbot/chromium.memory.json
@@ -18045,12 +18045,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -18061,8 +18061,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -18080,12 +18080,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -18096,8 +18096,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -18231,12 +18231,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -18247,8 +18247,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -18265,12 +18265,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -18281,8 +18281,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [ @@ -18392,12 +18392,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 114.0.5735.37", + "description": "Run with ash-chrome version 114.0.5735.84", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -18408,8 +18408,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v114.0.5735.37", - "revision": "version:114.0.5735.37" + "location": "lacros_version_skew_tests_v114.0.5735.84", + "revision": "version:114.0.5735.84" } ], "dimension_sets": [ @@ -18427,12 +18427,12 @@ { "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter", - "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome", + "--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome", "--test-launcher-print-test-stdio=always", "--combine-ash-logs-on-bots", "--asan-symbolize-output" ], - "description": "Run with ash-chrome version 116.0.5793.0", + "description": "Run with ash-chrome version 116.0.5795.0", "isolate_profile_data": true, "merge": { "script": "//testing/merge_scripts/standard_gtest_merge.py" @@ -18443,8 +18443,8 @@ "cipd_packages": [ { "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip", - "location": "lacros_version_skew_tests_v116.0.5793.0", - "revision": "version:116.0.5793.0" + "location": "lacros_version_skew_tests_v116.0.5795.0", + "revision": "version:116.0.5795.0" } ], "dimension_sets": [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index b16473fa..072aed7a 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1017,6 +1017,7 @@ 'mac11-arm64-rel-tests', # https://crbug.com/1406364 'mac12-arm64-rel-tests', # https://crbug.com/1406364 'Linux TSan Tests', # https://crbug.com/368525 + 'linux-exp-tsan-fyi-rel', # https://crbug.com/368525 'Win10 Tests x64 (dbg)', ], 'modifications': { @@ -1351,6 +1352,11 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.debug.cc_unittests.filter', ], }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 3, + }, + }, }, }, 'check_static_initializers': { @@ -1684,6 +1690,11 @@ 'shards': 4, }, }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 2, + }, + }, }, }, 'components_unittests': { @@ -1725,6 +1736,11 @@ '--gtest_filter=-FieldFormatterTest.DifferentLocales', ], }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 2, + }, + }, 'win-asan': { # With a single shard seems to hit time limit. 'swarming': { @@ -2004,6 +2020,11 @@ 'shards': 12, }, }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 30, + }, + }, # https://crbug.com/1111979 'linux-lacros-tester-fyi-rel': { 'experiment_percentage': 100, @@ -2192,6 +2213,8 @@ 'linux-win_cross-rel', # https://crbug.com/762167 # https://crbug.com/crashpad/304 'Linux TSan Tests', + # https://crbug.com/crashpad/304 + 'linux-exp-tsan-fyi-rel', 'ToTLinuxTSan', # https://crbug.com/crashpad/306 'Linux CFI', @@ -2482,6 +2505,21 @@ ], }, }, + 'linux-exp-tsan-fyi-rel': { + 'args': [ + '--use-gpu-in-tests', + '--no-xvfb', + ], + 'swarming': { + 'dimension_sets': [ + { + 'gpu': '10de:2184', + 'os': 'Ubuntu', + 'pool': 'chromium.tests.gpu', + }, + ], + }, + }, }, }, 'gl_tests_validating': { @@ -2808,6 +2846,12 @@ 'shards': 10, }, }, + 'linux-exp-tsan-fyi-rel': { + # These are slow on the TSan bots for some reason, crbug.com/1257927 + 'swarming': { + 'shards': 32, # Adjusted for testing, see https://crbug.com/1179567 + }, + }, 'linux-rel-cft': { 'args': [ '--test-launcher-filter-file=../../testing/buildbot/filters/linux.linux-rel-cft.interactive_ui_tests.filter', @@ -3106,6 +3150,7 @@ 'ToTMacASan', # The mac asan tot bot sets enable_nacl=false 'linux-win_cross-rel', # Sets enable_nacl=false, https://crbug.com/774186 'Linux TSan Tests', # The TSan bot sets enable_nacl=false + 'linux-exp-tsan-fyi-rel', # The TSan bot sets enable_nacl=false 'Mac ASan 64 Tests (1)', # The mac asan bot sets enable_nacl=false 'win-arm64-rel', # Not available on arm64. ], @@ -3209,6 +3254,11 @@ 'shards': 2, }, }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 4, + } + }, 'win-asan': { # TODO(crbug.com/1257927): net_unittests is slow under ASan. 'swarming': { @@ -3686,6 +3736,11 @@ 'shards': 4, }, }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 6, + }, + }, 'mac-code-coverage': { 'args': [ '--coverage-continuous-mode=1', @@ -3947,6 +4002,11 @@ 'shards': 2, }, }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 2, + }, + }, 'linux-rel-dev': { 'swarming': { 'dimension_sets': [ @@ -4587,6 +4647,11 @@ 'shards': 2, }, }, + 'linux-exp-tsan-fyi-rel': { + 'swarming': { + 'shards': 2, + }, + }, 'win10-code-coverage': { 'swarming': { 'shards': 4,
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 2c55f66..7846364 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3784,6 +3784,7 @@ 'cast_unittests': {}, 'cc_unittests': {}, 'color_unittests': {}, + 'components_browsertests': {}, 'components_unittests': {}, 'content_unittests': {}, 'crashpad_tests': {},
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index f8335f8..6b69f1c 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -22,16 +22,16 @@ }, 'LACROS_VERSION_SKEW_CANARY': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5793.0/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v116.0.5795.0/test_ash_chrome', ], - 'description': 'Run with ash-chrome version 116.0.5793.0', + 'description': 'Run with ash-chrome version 116.0.5795.0', 'identifier': 'Lacros version skew testing ash canary', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v116.0.5793.0', - 'revision': 'version:116.0.5793.0', + 'location': 'lacros_version_skew_tests_v116.0.5795.0', + 'revision': 'version:116.0.5795.0', }, ], }, @@ -54,16 +54,16 @@ }, 'LACROS_VERSION_SKEW_BETA': { 'args': [ - '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.37/test_ash_chrome', + '--ash-chrome-path-override=../../lacros_version_skew_tests_v114.0.5735.84/test_ash_chrome', ], - 'description': 'Run with ash-chrome version 114.0.5735.37', + 'description': 'Run with ash-chrome version 114.0.5735.84', 'identifier': 'Lacros version skew testing ash beta', 'swarming': { 'cipd_packages': [ { 'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip', - 'location': 'lacros_version_skew_tests_v114.0.5735.37', - 'revision': 'version:114.0.5735.37', + 'location': 'lacros_version_skew_tests_v114.0.5735.84', + 'revision': 'version:114.0.5735.84', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index d54fa89a..8fa18db 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2659,21 +2659,6 @@ ] } ], - "CertVerifierBuiltin": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "ChromeRootStoreUsed" - ] - } - ] - } - ], "ChangeExtensionEventPageSuspendDelay": [ { "platforms": [ @@ -9200,6 +9185,26 @@ ] } ], + "OmniboxZaryaInNTPRealboxDesktopV1": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "OmniboxGroupingFrameworkForZPS", + "RealboxSecondaryZeroSuggest" + ] + } + ] + } + ], "OmniboxZeroSuggestPrefetchingAndroid": [ { "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore index bd923db..4bcd716 100644 --- a/third_party/.gitignore +++ b/third_party/.gitignore
@@ -80,6 +80,7 @@ /colorama/src /content_analysis_sdk/src /cpuinfo/src +/cpu_features/src /crc32c/src /cros /cros-components/src
diff --git a/third_party/blink/renderer/core/css/css_starting_style_rule.idl b/third_party/blink/renderer/core/css/css_starting_style_rule.idl index f26dd4b8..a81f474 100644 --- a/third_party/blink/renderer/core/css/css_starting_style_rule.idl +++ b/third_party/blink/renderer/core/css/css_starting_style_rule.idl
@@ -3,6 +3,7 @@ // found in the LICENSE file. [ - Exposes=Window, RuntimeEnabled = CSSInitialPseudo + Exposed=Window, + RuntimeEnabled=CSSInitialPseudo ] interface CSSStartingStyleRule : CSSConditionRule { };
diff --git a/third_party/blink/renderer/core/css/fullscreen.css b/third_party/blink/renderer/core/css/fullscreen.css index 45289aa..0ef163a 100644 --- a/third_party/blink/renderer/core/css/fullscreen.css +++ b/third_party/blink/renderer/core/css/fullscreen.css
@@ -31,7 +31,6 @@ position: fixed; inset: 0; background: black; - overlay: auto !important; } /* Anything below are extensions over what the Fullscreen API (29 May 2018) mandates. */
diff --git a/third_party/blink/renderer/core/css/popover.css b/third_party/blink/renderer/core/css/popover.css index e5d2a09..6ab8a7d 100644 --- a/third_party/blink/renderer/core/css/popover.css +++ b/third_party/blink/renderer/core/css/popover.css
@@ -56,5 +56,4 @@ /* Specific to [popover]: */ pointer-events: none !important; background-color: transparent; - overlay: auto !important; }
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc index 24be3255..762628d 100644 --- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc +++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -825,8 +825,7 @@ } if (!RuntimeEnabledFeatures::CSSTopLayerForTransitionsEnabled()) { - if ((element && element->IsInTopLayer()) || - builder.StyleType() == kPseudoIdBackdrop) { + if (element && element->IsInTopLayer()) { builder.SetOverlay(EOverlay::kAuto); } } @@ -838,6 +837,7 @@ // be left alone because the fullscreen.css doesn't apply any style to // them. if ((builder.Overlay() == EOverlay::kAuto && !is_document_element) || + builder.StyleType() == kPseudoIdBackdrop || builder.StyleType() == kPseudoIdViewTransition) { if (builder.GetPosition() == EPosition::kStatic || builder.GetPosition() == EPosition::kRelative) { @@ -915,6 +915,7 @@ } if (builder.Overlay() == EOverlay::kAuto || + builder.StyleType() == kPseudoIdBackdrop || builder.StyleType() == kPseudoIdViewTransition) { builder.SetForcesStackingContext(true); }
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 6c73cb6..1e9135e 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2364,6 +2364,20 @@ } else if (name == html_names::kExportpartsAttr) { EnsureElementRareData().SetPartNamesMap(params.new_value); GetDocument().GetStyleEngine().ExportpartsChangedForElement(*this); + } else if (name == html_names::kTabindexAttr) { + if (params.reason == AttributeModificationReason::kDirectly && + AdjustedFocusedElementInTreeScope() == this) { + // The attribute change may cause supportsFocus() to return false + // for the element which had focus. + // + // TODO(tkent): We should avoid updating style. We'd like to check only + // DOM-level focusability here. + GetDocument().UpdateStyleAndLayoutTreeForNode( + this, DocumentUpdateReason::kFocus); + if (!SupportsFocus() && !GetFocusableArea()) { + blur(); + } + } } else if (IsElementReflectionAttribute(name)) { SynchronizeContentAttributeAndElementReference(name); } else if (IsStyledElement()) { @@ -2389,21 +2403,6 @@ } } } - - if (params.reason == AttributeModificationReason::kDirectly && - name == html_names::kTabindexAttr && - AdjustedFocusedElementInTreeScope() == this) { - // The attribute change may cause supportsFocus() to return false - // for the element which had focus. - // - // TODO(tkent): We should avoid updating style. We'd like to check only - // DOM-level focusability here. - GetDocument().UpdateStyleAndLayoutTreeForNode(this, - DocumentUpdateReason::kFocus); - if (!SupportsFocus() && !GetFocusableArea()) { - blur(); - } - } } bool Element::HasLegalLinkAttribute(const QualifiedName&) const { @@ -2451,6 +2450,17 @@ void Element::ClassAttributeChanged(const AtomicString& new_class_string) { DCHECK(HasElementData()); + if (!element_data_->IsUnique()) { + ShareableElementData* shareable_element_data = + To<ShareableElementData>(element_data_.Get()); + if (!shareable_element_data->class_is_dirty() && !InActiveDocument()) { + // `element_data` is shared, class related state is up to date, and + // this is not in the active document. No additional processing is + // necessary (because ClassChangedForElement() does nothing if not + // in an active document). + return; + } + } ClassStringContent class_string_content_type = ClassStringHasClassName(new_class_string); const bool should_fold_case = GetDocument().InQuirksMode(); @@ -2469,6 +2479,9 @@ GetElementData()->ClearClass(); } } + if (!element_data_->IsUnique()) { + To<ShareableElementData>(element_data_.Get())->SetClassIsDirty(false); + } } void Element::UpdateClassList(const AtomicString& old_class_string, @@ -2531,14 +2544,14 @@ DCHECK(!element_data_); if (!attribute_vector.empty()) { - if (GetDocument().GetElementDataCache()) { - element_data_ = - GetDocument() - .GetElementDataCache() - ->CachedShareableElementDataWithAttributes(attribute_vector); - } else { + if (auto* cache = GetDocument().GetElementDataCache()) { + element_data_ = cache->ElementDataWithAttributes(attribute_vector); + } else if (attribute_vector.size() <= + ShareableElementData::kMaxNumberOfAttributes) { element_data_ = ShareableElementData::CreateWithAttributes(attribute_vector); + } else { + element_data_ = MakeGarbageCollected<UniqueElementData>(attribute_vector); } } @@ -3150,7 +3163,7 @@ // preceding sibling of the originating element's box which means we will not // reach the box for ::backdrop during layout. Don't skip style recalc for // children of containers in the top layer for this reason. - if (style.IsInTopLayer(*this)) { + if (style.IsRenderedInTopLayer(*this)) { return false; } @@ -6328,7 +6341,7 @@ // force-updating style on the locked subtree and reach this node. Note that // we already detached layout when this element was added to the top layer, so // we simply maintain the fact that it doesn't have a layout object/subtree. - if (style.IsInTopLayer(*this) && + if (style.IsRenderedInTopLayer(*this) && DisplayLockUtilities::LockedAncestorPreventingPaint(*this)) { return false; }
diff --git a/third_party/blink/renderer/core/dom/element_data.cc b/third_party/blink/renderer/core/dom/element_data.cc index 6b7a21c..19c7a6b1 100644 --- a/third_party/blink/renderer/core/dom/element_data.cc +++ b/third_party/blink/renderer/core/dom/element_data.cc
@@ -52,27 +52,31 @@ } ElementData::ElementData() - : bit_field_(IsUniqueFlag::encode(true) | ArraySize::encode(0) | + : bit_field_(IsUniqueFlag::encode(true) | ShareableArraySize::encode(0) | PresentationAttributeStyleIsDirty::encode(false) | StyleAttributeIsDirty::encode(false) | - SvgAttributesAreDirty::encode(false)) {} + SvgAttributesAreDirty::encode(false) | + ClassIsDirty::encode(true)) {} ElementData::ElementData(unsigned array_size) - : bit_field_(IsUniqueFlag::encode(false) | ArraySize::encode(array_size) | - PresentationAttributeStyleIsDirty::encode(false) | - StyleAttributeIsDirty::encode(false) | - SvgAttributesAreDirty::encode(false)) {} + : bit_field_( + IsUniqueFlag::encode(false) | ShareableArraySize::encode(array_size) | + PresentationAttributeStyleIsDirty::encode(false) | + StyleAttributeIsDirty::encode(false) | + SvgAttributesAreDirty::encode(false) | ClassIsDirty::encode(true)) {} ElementData::ElementData(const ElementData& other, bool is_unique) : bit_field_( IsUniqueFlag::encode(is_unique) | - ArraySize::encode(is_unique ? 0 : other.Attributes().size()) | + ShareableArraySize::encode(is_unique ? 0 + : other.Attributes().size()) | PresentationAttributeStyleIsDirty::encode( other.bit_field_.get<PresentationAttributeStyleIsDirty>()) | StyleAttributeIsDirty::encode( other.bit_field_.get<StyleAttributeIsDirty>()) | SvgAttributesAreDirty::encode( - other.bit_field_.get<SvgAttributesAreDirty>())), + other.bit_field_.get<SvgAttributesAreDirty>()) | + ClassIsDirty::encode(other.bit_field_.get<ClassIsDirty>())), class_names_(other.class_names_), id_for_style_resolution_(other.id_for_style_resolution_) { // NOTE: The inline style is copied by the subclass copy constructor since we @@ -125,13 +129,15 @@ ShareableElementData::ShareableElementData( const Vector<Attribute, kAttributePrealloc>& attributes) : ElementData(attributes.size()) { - for (unsigned i = 0; i < bit_field_.get<ArraySize>(); ++i) + for (unsigned i = 0; i < bit_field_.get<ShareableArraySize>(); ++i) { new (&attribute_array_[i]) Attribute(attributes[i]); + } } ShareableElementData::~ShareableElementData() { - for (unsigned i = 0; i < bit_field_.get<ArraySize>(); ++i) + for (unsigned i = 0; i < bit_field_.get<ShareableArraySize>(); ++i) { attribute_array_[i].~Attribute(); + } } ShareableElementData::ShareableElementData(const UniqueElementData& other) @@ -142,8 +148,9 @@ inline_style_ = other.inline_style_->ImmutableCopyIfNeeded(); } - for (unsigned i = 0; i < bit_field_.get<ArraySize>(); ++i) + for (unsigned i = 0; i < bit_field_.get<ShareableArraySize>(); ++i) { new (&attribute_array_[i]) Attribute(other.attribute_vector_.at(i)); + } } ShareableElementData* ShareableElementData::CreateWithAttributes( @@ -184,6 +191,10 @@ *this); } +UniqueElementData::UniqueElementData( + const Vector<Attribute, kAttributePrealloc>& attrs) + : attribute_vector_(attrs) {} + void UniqueElementData::TraceAfterDispatch(blink::Visitor* visitor) const { visitor->Trace(presentation_attribute_style_); ElementData::TraceAfterDispatch(visitor);
diff --git a/third_party/blink/renderer/core/dom/element_data.h b/third_party/blink/renderer/core/dom/element_data.h index cddb64b..78b9204d 100644 --- a/third_party/blink/renderer/core/dom/element_data.h +++ b/third_party/blink/renderer/core/dom/element_data.h
@@ -89,15 +89,24 @@ void Trace(Visitor*) const; protected: + static constexpr size_t kShareableArraySizeBits = 27; + using BitField = WTF::ConcurrentlyReadBitField<uint32_t>; using IsUniqueFlag = BitField::DefineFirstValue<bool, 1, WTF::BitFieldValueConstness::kConst>; - using ArraySize = IsUniqueFlag:: - DefineNextValue<uint32_t, 28, WTF::BitFieldValueConstness::kConst>; - using PresentationAttributeStyleIsDirty = ArraySize::DefineNextValue<bool, 1>; + // This is used solely by ShareableElementData. It gives the number of + // elements in the array. + using ShareableArraySize = + IsUniqueFlag::DefineNextValue<uint32_t, + kShareableArraySizeBits, + WTF::BitFieldValueConstness::kConst>; + using PresentationAttributeStyleIsDirty = + ShareableArraySize::DefineNextValue<bool, 1>; using StyleAttributeIsDirty = PresentationAttributeStyleIsDirty::DefineNextValue<bool, 1>; using SvgAttributesAreDirty = StyleAttributeIsDirty::DefineNextValue<bool, 1>; + // Used by ShareableElementData. Tracks if the `class` needs to be calculated. + using ClassIsDirty = SvgAttributesAreDirty::DefineNextValue<bool, 1>; ElementData(); explicit ElementData(unsigned array_size); @@ -112,6 +121,7 @@ bool svg_attributes_are_dirty() const { return bit_field_.get<SvgAttributesAreDirty>(); } + bool class_is_dirty() const { return bit_field_.get<ClassIsDirty>(); } // Following 3 fields are meant to be mutable and can change even when const. void SetPresentationAttributeStyleIsDirty( @@ -128,6 +138,9 @@ const_cast<BitField*>(&bit_field_) ->set<SvgAttributesAreDirty>(svg_attributes_are_dirty); } + void SetClassIsDirty(bool value) const { + const_cast<BitField*>(&bit_field_)->set<ClassIsDirty>(value); + } BitField bit_field_; @@ -159,6 +172,9 @@ // duplicate sets of attributes (ex. the same classes). class ShareableElementData final : public ElementData { public: + // Maximum number of attributes this can hold. + static constexpr size_t kMaxNumberOfAttributes = 2 ^ kShareableArraySizeBits; + static ShareableElementData* CreateWithAttributes( const Vector<Attribute, kAttributePrealloc>&); @@ -201,7 +217,8 @@ UniqueElementData(); explicit UniqueElementData(const ShareableElementData&); - explicit UniqueElementData(const UniqueElementData&); + UniqueElementData(const UniqueElementData&); + explicit UniqueElementData(const Vector<Attribute, kAttributePrealloc>&); void TraceAfterDispatch(blink::Visitor*) const; @@ -234,7 +251,8 @@ } inline AttributeCollection ShareableElementData::Attributes() const { - return AttributeCollection(attribute_array_, bit_field_.get<ArraySize>()); + return AttributeCollection(attribute_array_, + bit_field_.get<ShareableArraySize>()); } inline AttributeCollection UniqueElementData::Attributes() const {
diff --git a/third_party/blink/renderer/core/dom/element_data_cache.cc b/third_party/blink/renderer/core/dom/element_data_cache.cc index d2da8030..9dcd986 100644 --- a/third_party/blink/renderer/core/dom/element_data_cache.cc +++ b/third_party/blink/renderer/core/dom/element_data_cache.cc
@@ -69,8 +69,7 @@ attributes.size() * sizeof(Attribute)); } -ShareableElementData* -ElementDataCache::CachedShareableElementDataWithAttributes( +ElementData* ElementDataCache::ElementDataWithAttributes( const Vector<Attribute, kAttributePrealloc>& attributes) { DCHECK(!attributes.empty()); @@ -82,8 +81,13 @@ if (it->value && !HasSameAttributes(attributes, *it->value)) return ShareableElementData::CreateWithAttributes(attributes); - if (!it->value) - it->value = ShareableElementData::CreateWithAttributes(attributes); + if (!it->value) { + if (attributes.size() < ShareableElementData::kMaxNumberOfAttributes) { + it->value = ShareableElementData::CreateWithAttributes(attributes); + } else { + return MakeGarbageCollected<UniqueElementData>(attributes); + } + } return it->value.Get(); }
diff --git a/third_party/blink/renderer/core/dom/element_data_cache.h b/third_party/blink/renderer/core/dom/element_data_cache.h index 892ba615..03c0f915a 100644 --- a/third_party/blink/renderer/core/dom/element_data_cache.h +++ b/third_party/blink/renderer/core/dom/element_data_cache.h
@@ -34,13 +34,17 @@ namespace blink { +class ElementData; class ShareableElementData; class ElementDataCache final : public GarbageCollected<ElementDataCache> { public: ElementDataCache(); - ShareableElementData* CachedShareableElementDataWithAttributes( + // Returns an ElementData representing the specified attributes. This prefers + // returning a ShareableElementData, but in some cases returns an + // ElementData. + ElementData* ElementDataWithAttributes( const Vector<Attribute, kAttributePrealloc>&); void Trace(Visitor*) const;
diff --git a/third_party/blink/renderer/core/dom/layout_tree_builder.cc b/third_party/blink/renderer/core/dom/layout_tree_builder.cc index ec64568..8faa1295 100644 --- a/third_party/blink/renderer/core/dom/layout_tree_builder.cc +++ b/third_party/blink/renderer/core/dom/layout_tree_builder.cc
@@ -61,7 +61,7 @@ // ::view-transition is the last rendered child of LayoutView() return nullptr; } - if (style_->IsInTopLayer(*node_)) { + if (style_->IsRenderedInTopLayer(*node_)) { if (LayoutObject* next_in_top_layer = LayoutTreeBuilderTraversal::NextInTopLayer(*node_)) { return next_in_top_layer; @@ -81,7 +81,7 @@ LayoutObject* LayoutTreeBuilderForElement::ParentLayoutObject() const { if (style_->StyleType() == kPseudoIdViewTransition || - style_->IsInTopLayer(*node_)) { + style_->IsRenderedInTopLayer(*node_)) { return node_->GetDocument().GetLayoutView(); } return context_.parent; @@ -98,7 +98,7 @@ // If we are in the top layer and the parent layout object without top layer // adjustment can't have children, then don't render. // https://github.com/w3c/csswg-drafts/issues/6939#issuecomment-1016671534 - if (style_->IsInTopLayer(*node_) && context_.parent && + if (style_->IsRenderedInTopLayer(*node_) && context_.parent && !context_.parent->CanHaveChildren() && node_->GetPseudoId() != kPseudoIdBackdrop) { return;
diff --git a/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc b/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc index 440b65c..1c4b6c7 100644 --- a/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc +++ b/third_party/blink/renderer/core/dom/layout_tree_builder_traversal.cc
@@ -344,9 +344,9 @@ LayoutObject* LayoutTreeBuilderTraversal::NextInTopLayer( const Element& element) { - DCHECK(element.ComputedStyleRef().IsInTopLayer(element)) - << "This method should only be called with an element in the top layer " - "candidate list which is rendered in the top layer"; + CHECK(element.ComputedStyleRef().IsRenderedInTopLayer(element)) + << "This method should only be called with an element that is rendered in" + " the top layer"; const HeapVector<Member<Element>>& top_layer_elements = element.GetDocument().TopLayerElements(); wtf_size_t position = top_layer_elements.Find(&element); @@ -357,7 +357,8 @@ // not re-attached and not in the top layer yet, thus we can not use it as a // sibling LayoutObject. if (layout_object && - layout_object->StyleRef().Overlay() == EOverlay::kAuto && + layout_object->StyleRef().IsRenderedInTopLayer( + *top_layer_elements[i]) && IsA<LayoutView>(layout_object->Parent())) { return layout_object; }
diff --git a/third_party/blink/renderer/core/dom/node.h b/third_party/blink/renderer/core/dom/node.h index 6a7654b..6922be6 100644 --- a/third_party/blink/renderer/core/dom/node.h +++ b/third_party/blink/renderer/core/dom/node.h
@@ -993,9 +993,9 @@ private: enum NodeFlags : uint32_t { - // Let the NodeTypeMask comes first, so the shit operation can - // be eliminated when get NodeType for the reason of performance. - // Node type flags. These never change once created. + // getNodeType() is called extensively. As it's called quite a bit its + // value is first so that a bit-shift is not needed to extract the value. + // Also note the node-type never changes once created. kNodeTypeMask = 0xf, kIsContainerFlag = 1 << 4, kElementNamespaceTypeMask = 0x3 << kElementNamespaceTypeShift,
diff --git a/third_party/blink/renderer/core/editing/build.gni b/third_party/blink/renderer/core/editing/build.gni index d7dda29..a563e9c 100644 --- a/third_party/blink/renderer/core/editing/build.gni +++ b/third_party/blink/renderer/core/editing/build.gni
@@ -411,6 +411,7 @@ "markers/active_suggestion_marker_test.cc", "markers/composition_marker_list_impl_test.cc", "markers/composition_marker_test.cc", + "markers/custom_highlight_marker_test.cc", "markers/document_marker_controller_test.cc", "markers/document_marker_test.cc", "markers/grammar_marker_list_impl_test.cc",
diff --git a/third_party/blink/renderer/core/editing/markers/custom_highlight_marker_test.cc b/third_party/blink/renderer/core/editing/markers/custom_highlight_marker_test.cc new file mode 100644 index 0000000..fc108e3b --- /dev/null +++ b/third_party/blink/renderer/core/editing/markers/custom_highlight_marker_test.cc
@@ -0,0 +1,36 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/editing/markers/custom_highlight_marker.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/range.h" +#include "third_party/blink/renderer/core/dom/text.h" +#include "third_party/blink/renderer/core/highlight/highlight.h" +#include "third_party/blink/renderer/core/html/html_element.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" + +namespace blink { + +class CustomHighlightMarkerTest : public PageTestBase {}; + +TEST_F(CustomHighlightMarkerTest, CreationAndProperties) { + GetDocument().body()->setInnerHTML("1234"); + auto* text = To<Text>(GetDocument().body()->firstChild()); + auto* range04 = MakeGarbageCollected<Range>(GetDocument(), text, 0, text, 4); + HeapVector<Member<AbstractRange>> range_vector; + range_vector.push_back(range04); + auto* highlight = Highlight::Create(range_vector); + + DocumentMarker* marker = MakeGarbageCollected<CustomHighlightMarker>( + 0, 4, "TestHighlight", highlight); + // Check downcast operator. + CustomHighlightMarker* custom_marker = To<CustomHighlightMarker>(marker); + EXPECT_EQ(DocumentMarker::kCustomHighlight, custom_marker->GetType()); + EXPECT_EQ(kPseudoIdHighlight, custom_marker->GetPseudoId()); + EXPECT_EQ("TestHighlight", custom_marker->GetPseudoArgument()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/highlight/build.gni b/third_party/blink/renderer/core/highlight/build.gni index 03c05ba..978b2fc 100644 --- a/third_party/blink/renderer/core/highlight/build.gni +++ b/third_party/blink/renderer/core/highlight/build.gni
@@ -16,4 +16,8 @@ "highlight_style_utils.h", ] -blink_core_tests_highlight = [ "highlight_style_utils_test.cc" ] +blink_core_tests_highlight = [ + "highlight_registry_test.cc", + "highlight_style_utils_test.cc", + "highlight_test.cc", +]
diff --git a/third_party/blink/renderer/core/highlight/highlight_registry.cc b/third_party/blink/renderer/core/highlight/highlight_registry.cc index e1c42ac..38a1494 100644 --- a/third_party/blink/renderer/core/highlight/highlight_registry.cc +++ b/third_party/blink/renderer/core/highlight/highlight_registry.cc
@@ -104,6 +104,19 @@ ScheduleRepaint(); } +void HighlightRegistry::RemoveForTesting(AtomicString highlight_name, + Highlight* highlight) { + auto highlights_iterator = GetMapIterator(highlight_name); + if (highlights_iterator != highlights_.end()) { + highlights_iterator->Get()->highlight->DeregisterFrom(this); + // It's necessary to delete it and insert a new entry to the registry + // instead of just modifying the existing one so the insertion order is + // preserved. + highlights_.erase(highlights_iterator); + ScheduleRepaint(); + } +} + HighlightRegistry* HighlightRegistry::setForBinding( ScriptState* script_state, AtomicString highlight_name,
diff --git a/third_party/blink/renderer/core/highlight/highlight_registry.h b/third_party/blink/renderer/core/highlight/highlight_registry.h index 3343309..6680492 100644 --- a/third_party/blink/renderer/core/highlight/highlight_registry.h +++ b/third_party/blink/renderer/core/highlight/highlight_registry.h
@@ -43,6 +43,7 @@ void Trace(blink::Visitor*) const override; void SetForTesting(AtomicString, Highlight*); + void RemoveForTesting(AtomicString, Highlight*); HighlightRegistry* setForBinding(ScriptState*, AtomicString, Member<Highlight>,
diff --git a/third_party/blink/renderer/core/highlight/highlight_registry_test.cc b/third_party/blink/renderer/core/highlight/highlight_registry_test.cc new file mode 100644 index 0000000..610d15d --- /dev/null +++ b/third_party/blink/renderer/core/highlight/highlight_registry_test.cc
@@ -0,0 +1,262 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/highlight/highlight_registry.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/range.h" +#include "third_party/blink/renderer/core/dom/text.h" +#include "third_party/blink/renderer/core/editing/markers/custom_highlight_marker.h" +#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h" +#include "third_party/blink/renderer/core/highlight/highlight.h" +#include "third_party/blink/renderer/core/html/html_element.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" + +namespace blink { + +class HighlightRegistryTest : public PageTestBase { + public: + Highlight* CreateHighlight(Text* node_start, + int start, + Text* node_end, + int end) { + auto* range = MakeGarbageCollected<Range>(GetDocument(), node_start, start, + node_end, end); + HeapVector<Member<AbstractRange>> range_vector; + range_vector.push_back(range); + return Highlight::Create(range_vector); + } +}; + +TEST_F(HighlightRegistryTest, CompareStacking) { + GetDocument().body()->setInnerHTML("1234"); + auto* dom_window = GetDocument().domWindow(); + HighlightRegistry* registry = HighlightRegistry::From(*dom_window); + + auto* text = To<Text>(GetDocument().body()->firstChild()); + + auto* highlight1 = CreateHighlight(text, 0, text, 4); + AtomicString highlight1_name("TestHighlight1"); + + auto* highlight2 = CreateHighlight(text, 2, text, 4); + AtomicString highlight2_name("TestHighlight2"); + + registry->SetForTesting(highlight1_name, highlight1); + registry->SetForTesting(highlight2_name, highlight2); + + EXPECT_EQ(HighlightRegistry::kOverlayStackingPositionEquivalent, + registry->CompareOverlayStackingPosition( + highlight1_name, highlight1, highlight1_name, highlight1)); + EXPECT_EQ(HighlightRegistry::kOverlayStackingPositionBelow, + registry->CompareOverlayStackingPosition( + highlight1_name, highlight1, highlight2_name, highlight2)); + EXPECT_EQ(HighlightRegistry::kOverlayStackingPositionAbove, + registry->CompareOverlayStackingPosition( + highlight2_name, highlight2, highlight1_name, highlight1)); + highlight1->setPriority(2); + highlight1->setPriority(1); + EXPECT_EQ(HighlightRegistry::kOverlayStackingPositionAbove, + registry->CompareOverlayStackingPosition( + highlight1_name, highlight1, highlight2_name, highlight2)); +} + +TEST_F(HighlightRegistryTest, ValidateMarkers) { + GetDocument().body()->setInnerHTML( + "<p>aaaaaaaaaa</p><p>bbbbbbbbbb</p><p>cccccccccc</p>"); + auto* dom_window = GetDocument().domWindow(); + HighlightRegistry* registry = HighlightRegistry::From(*dom_window); + + auto* node_a = GetDocument().body()->firstChild(); + auto* node_b = node_a->nextSibling(); + auto* node_c = node_b->nextSibling(); + auto* text_a = To<Text>(node_a->firstChild()); + auto* text_b = To<Text>(node_b->firstChild()); + auto* text_c = To<Text>(node_c->firstChild()); + + // Create several ranges, including those crossing multiple nodes + HeapVector<Member<AbstractRange>> range_vector_1; + auto* range_aa = + MakeGarbageCollected<Range>(GetDocument(), text_a, 0, text_a, 4); + range_vector_1.push_back(range_aa); + auto* range_ab = + MakeGarbageCollected<Range>(GetDocument(), text_a, 5, text_b, 4); + range_vector_1.push_back(range_ab); + auto* highlight1 = Highlight::Create(range_vector_1); + AtomicString highlight1_name("TestHighlight1"); + + HeapVector<Member<AbstractRange>> range_vector_2; + auto* range_bb = + MakeGarbageCollected<Range>(GetDocument(), text_b, 5, text_b, 8); + range_vector_2.push_back(range_bb); + auto* highlight2 = Highlight::Create(range_vector_2); + AtomicString highlight2_name("TestHighlight2"); + + HeapVector<Member<AbstractRange>> range_vector_3; + auto* range_bc = + MakeGarbageCollected<Range>(GetDocument(), text_b, 9, text_c, 4); + range_vector_3.push_back(range_bc); + auto* range_cc = + MakeGarbageCollected<Range>(GetDocument(), text_c, 5, text_c, 9); + range_vector_3.push_back(range_cc); + auto* highlight3 = Highlight::Create(range_vector_3); + AtomicString highlight3_name("TestHighlight3"); + + registry->SetForTesting(highlight1_name, highlight1); + registry->SetForTesting(highlight2_name, highlight2); + registry->SetForTesting(highlight3_name, highlight3); + + // When the document lifecycle runs, marker invalidation should + // happen and create markers. Verify that it happens. + UpdateAllLifecyclePhasesForTest(); + + DocumentMarkerController& marker_controller = GetDocument().Markers(); + DocumentMarkerVector text_a_markers = marker_controller.MarkersFor( + *text_a, DocumentMarker::MarkerTypes::CustomHighlight()); + DocumentMarkerVector text_b_markers = marker_controller.MarkersFor( + *text_b, DocumentMarker::MarkerTypes::CustomHighlight()); + DocumentMarkerVector text_c_markers = marker_controller.MarkersFor( + *text_c, DocumentMarker::MarkerTypes::CustomHighlight()); + + EXPECT_EQ(2u, text_a_markers.size()); + EXPECT_EQ(3u, text_b_markers.size()); + EXPECT_EQ(2u, text_c_markers.size()); + + int index = 0; + for (auto& marker : text_a_markers) { + auto* custom_marker = To<CustomHighlightMarker>(marker.Get()); + switch (index) { + case 0: { + EXPECT_EQ(0u, custom_marker->StartOffset()); + EXPECT_EQ(4u, custom_marker->EndOffset()); + EXPECT_EQ(highlight1_name, custom_marker->GetPseudoArgument()); + } break; + case 1: { + EXPECT_EQ(5u, custom_marker->StartOffset()); + EXPECT_EQ(10u, custom_marker->EndOffset()); + EXPECT_EQ(highlight1_name, custom_marker->GetPseudoArgument()); + } break; + default: + EXPECT_TRUE(false); + } + ++index; + } + index = 0; + for (auto& marker : text_b_markers) { + auto* custom_marker = To<CustomHighlightMarker>(marker.Get()); + switch (index) { + case 0: { + EXPECT_EQ(0u, custom_marker->StartOffset()); + EXPECT_EQ(4u, custom_marker->EndOffset()); + EXPECT_EQ(highlight1_name, custom_marker->GetPseudoArgument()); + } break; + case 1: { + EXPECT_EQ(5u, custom_marker->StartOffset()); + EXPECT_EQ(8u, custom_marker->EndOffset()); + EXPECT_EQ(highlight2_name, custom_marker->GetPseudoArgument()); + } break; + case 2: { + EXPECT_EQ(9u, custom_marker->StartOffset()); + EXPECT_EQ(10u, custom_marker->EndOffset()); + EXPECT_EQ(highlight3_name, custom_marker->GetPseudoArgument()); + } break; + default: + EXPECT_TRUE(false); + } + ++index; + } + index = 0; + for (auto& marker : text_c_markers) { + auto* custom_marker = To<CustomHighlightMarker>(marker.Get()); + switch (index) { + case 0: { + EXPECT_EQ(0u, custom_marker->StartOffset()); + EXPECT_EQ(4u, custom_marker->EndOffset()); + EXPECT_EQ(highlight3_name, custom_marker->GetPseudoArgument()); + } break; + case 1: { + EXPECT_EQ(5u, custom_marker->StartOffset()); + EXPECT_EQ(9u, custom_marker->EndOffset()); + EXPECT_EQ(highlight3_name, custom_marker->GetPseudoArgument()); + } break; + default: + EXPECT_TRUE(false); + } + ++index; + } + + registry->RemoveForTesting(highlight2_name, highlight2); + UpdateAllLifecyclePhasesForTest(); + + text_a_markers = marker_controller.MarkersFor( + *text_a, DocumentMarker::MarkerTypes::CustomHighlight()); + text_b_markers = marker_controller.MarkersFor( + *text_b, DocumentMarker::MarkerTypes::CustomHighlight()); + text_c_markers = marker_controller.MarkersFor( + *text_c, DocumentMarker::MarkerTypes::CustomHighlight()); + + EXPECT_EQ(2u, text_a_markers.size()); + EXPECT_EQ(2u, text_b_markers.size()); + EXPECT_EQ(2u, text_c_markers.size()); + + index = 0; + for (auto& marker : text_a_markers) { + auto* custom_marker = To<CustomHighlightMarker>(marker.Get()); + switch (index) { + case 0: { + EXPECT_EQ(0u, custom_marker->StartOffset()); + EXPECT_EQ(4u, custom_marker->EndOffset()); + EXPECT_EQ(highlight1_name, custom_marker->GetPseudoArgument()); + } break; + case 1: { + EXPECT_EQ(5u, custom_marker->StartOffset()); + EXPECT_EQ(10u, custom_marker->EndOffset()); + EXPECT_EQ(highlight1_name, custom_marker->GetPseudoArgument()); + } break; + default: + EXPECT_TRUE(false); + } + ++index; + } + index = 0; + for (auto& marker : text_b_markers) { + auto* custom_marker = To<CustomHighlightMarker>(marker.Get()); + switch (index) { + case 0: { + EXPECT_EQ(0u, custom_marker->StartOffset()); + EXPECT_EQ(4u, custom_marker->EndOffset()); + EXPECT_EQ(highlight1_name, custom_marker->GetPseudoArgument()); + } break; + case 1: { + EXPECT_EQ(9u, custom_marker->StartOffset()); + EXPECT_EQ(10u, custom_marker->EndOffset()); + EXPECT_EQ(highlight3_name, custom_marker->GetPseudoArgument()); + } break; + default: + EXPECT_TRUE(false); + } + ++index; + } + index = 0; + for (auto& marker : text_c_markers) { + auto* custom_marker = To<CustomHighlightMarker>(marker.Get()); + switch (index) { + case 0: { + EXPECT_EQ(0u, custom_marker->StartOffset()); + EXPECT_EQ(4u, custom_marker->EndOffset()); + EXPECT_EQ(highlight3_name, custom_marker->GetPseudoArgument()); + } break; + case 1: { + EXPECT_EQ(5u, custom_marker->StartOffset()); + EXPECT_EQ(9u, custom_marker->EndOffset()); + EXPECT_EQ(highlight3_name, custom_marker->GetPseudoArgument()); + } break; + default: + EXPECT_TRUE(false); + } + ++index; + } +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/highlight/highlight_test.cc b/third_party/blink/renderer/core/highlight/highlight_test.cc new file mode 100644 index 0000000..cf552f4a --- /dev/null +++ b/third_party/blink/renderer/core/highlight/highlight_test.cc
@@ -0,0 +1,57 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/highlight/highlight.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/range.h" +#include "third_party/blink/renderer/core/dom/text.h" +#include "third_party/blink/renderer/core/html/html_element.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" + +namespace blink { + +class HighlightTest : public PageTestBase {}; + +TEST_F(HighlightTest, Creation) { + GetDocument().body()->setInnerHTML("1234"); + auto* text = To<Text>(GetDocument().body()->firstChild()); + + auto* range04 = MakeGarbageCollected<Range>(GetDocument(), text, 0, text, 4); + auto* range02 = MakeGarbageCollected<Range>(GetDocument(), text, 0, text, 2); + auto* range22 = MakeGarbageCollected<Range>(GetDocument(), text, 2, text, 2); + + HeapVector<Member<AbstractRange>> range_vector; + range_vector.push_back(range04); + range_vector.push_back(range02); + range_vector.push_back(range22); + + auto* highlight = Highlight::Create(range_vector); + CHECK_EQ(3u, highlight->size()); + CHECK_EQ(3u, highlight->GetRanges().size()); + EXPECT_TRUE(highlight->Contains(range04)); + EXPECT_TRUE(highlight->Contains(range02)); + EXPECT_TRUE(highlight->Contains(range22)); +} + +TEST_F(HighlightTest, Properties) { + GetDocument().body()->setInnerHTML("1234"); + auto* text = To<Text>(GetDocument().body()->firstChild()); + + auto* range04 = MakeGarbageCollected<Range>(GetDocument(), text, 0, text, 4); + + HeapVector<Member<AbstractRange>> range_vector; + range_vector.push_back(range04); + + auto* highlight = Highlight::Create(range_vector); + highlight->setPriority(1); + AtomicString test_string("testType"); + highlight->setType(test_string); + + CHECK_EQ(1, highlight->priority()); + CHECK_EQ(test_string, highlight->type()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/html/resources/html.css b/third_party/blink/renderer/core/html/resources/html.css index f39309c..4ecfd74c 100644 --- a/third_party/blink/renderer/core/html/resources/html.css +++ b/third_party/blink/renderer/core/html/resources/html.css
@@ -1428,7 +1428,6 @@ inset: 0; /* https://html.spec.whatwg.org/multipage/rendering.html#flow-content-3 */ background: rgba(0,0,0,0.1); - overlay: auto !important; } slot {
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h index f19d653b..e9c641e 100644 --- a/third_party/blink/renderer/core/layout/layout_object.h +++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -759,7 +759,7 @@ NOT_DESTROYED(); if (Element* element = DynamicTo<Element>(GetNode())) { return StyleRef().StyleType() == kPseudoIdViewTransition || - StyleRef().IsInTopLayer(*element); + StyleRef().IsRenderedInTopLayer(*element); } return false; }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc index cfb90e0..9e8c5d4 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -2917,7 +2917,8 @@ // finding the size of an fr using all the grid tracks that the item // crosses and a space to fill of the item’s max-content contribution. for (auto& grid_item : sizing_data.grid_items) { - if (grid_item.IsSpanningFlexibleTrack(track_direction)) { + if (grid_item.IsConsideredForSizing(track_direction) && + grid_item.IsSpanningFlexibleTrack(track_direction)) { double grid_item_fr_size = FindFrSize(GetSetIteratorForItem(grid_item, track_collection), ContributionSizeForGridItem(
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc index 898b2ba..dd4b488 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
@@ -720,9 +720,6 @@ // Opposite direction subgrids iterate backwards. const wtf_size_t first_set_index = is_opposite_direction_in_root_grid ? end_set_index : begin_set_index; - const wtf_size_t last_set_index = - is_opposite_direction_in_root_grid ? begin_set_index : end_set_index; - LayoutUnit first_set_offset = sets_geometry_[first_set_index].offset; if (is_opposite_direction_in_root_grid) { @@ -740,21 +737,36 @@ subgrid_sets_geometry.emplace_back(sets_geometry_[current_index]); if (is_opposite_direction_in_root_grid) { set.offset = first_set_offset - set.offset; + + // Opposite direction subgrids take their offset from the current index, + // but their track counts from the subsequent index. + const wtf_size_t next_index = current_index + 1; + DCHECK_LT(next_index, sets_geometry_.size()); + set.track_count = sets_geometry_[next_index].track_count; } else { set.offset -= first_set_offset; } + DCHECK_GT(set.track_count, 0U); set.offset += subgrid_gutter_size_delta / 2; } + const wtf_size_t last_set_index = + is_opposite_direction_in_root_grid ? begin_set_index : end_set_index; auto& last_set = subgrid_sets_geometry.emplace_back(sets_geometry_[last_set_index]); if (is_opposite_direction_in_root_grid) { last_set.offset = first_set_offset - last_set.offset; + // Opposite direction subgrids take their offset from the current index, + // but their track counts from the subsequent index. + const wtf_size_t next_index = last_set_index + 1; + DCHECK_LT(next_index, sets_geometry_.size()); + last_set.track_count = sets_geometry_[next_index].track_count; } else { last_set.offset -= first_set_offset; } last_set.offset += subgrid_gutter_size_delta - subgrid_margin_border_scrollbar_padding_end; + DCHECK_GT(last_set.track_count, 0U); } // Copy the last indefinite indices in the subgrid's span.
diff --git a/third_party/blink/renderer/core/page/frame_tree.cc b/third_party/blink/renderer/core/page/frame_tree.cc index d8d1711..70d4d28 100644 --- a/third_party/blink/renderer/core/page/frame_tree.cc +++ b/third_party/blink/renderer/core/page/frame_tree.cc
@@ -32,6 +32,7 @@ #include "third_party/blink/renderer/core/page/create_window.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/platform/instrumentation/use_counter.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" using std::swap; @@ -54,7 +55,8 @@ } bool ContainsNewLineAndLessThan(const AtomicString& name) { - return name.Contains('\n') && name.Contains('<'); + return (name.Contains('\n') || name.Contains('\r') || name.Contains('\t')) && + name.Contains('<'); } bool IsRequestFromHtml(FrameLoadRequest& request) { @@ -233,17 +235,21 @@ if (request.GetNavigationPolicy() != kNavigationPolicyCurrentTab) return FindResult(current_frame, false); + AtomicString cleanName = name; // Log use counters if the name contains both '\n' and '<'. if (ContainsNewLineAndLessThan(name) && IsRequestFromHtml(request) && current_frame->GetDocument()) { LogDanglingMarkupHistogram(current_frame->GetDocument(), name); + if (RuntimeEnabledFeatures::RemoveDanglingMarkupInTargetEnabled()) { + cleanName = AtomicString("_blank"); + } } const KURL& url = request.GetResourceRequest().Url(); - Frame* frame = FindFrameForNavigationInternal(name, url, &request); + Frame* frame = FindFrameForNavigationInternal(cleanName, url, &request); bool new_window = false; if (!frame) { - frame = CreateNewWindow(*current_frame, request, name); + frame = CreateNewWindow(*current_frame, request, cleanName); new_window = true; // CreateNewWindow() might have modified NavigationPolicy. // Set it back now that the new window is known to be the right one.
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 7ed8225..8814937e 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -2624,8 +2624,9 @@ return false; } -bool ComputedStyle::IsInTopLayer(const Element& element) const { - return element.IsInTopLayer() && Overlay() == EOverlay::kAuto; +bool ComputedStyle::IsRenderedInTopLayer(const Element& element) const { + return (element.IsInTopLayer() && Overlay() == EOverlay::kAuto) || + StyleType() == kPseudoIdBackdrop; } ComputedStyleBuilder::ComputedStyleBuilder(const ComputedStyle& style) {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index 230f6c6..6a5821e6 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2487,9 +2487,10 @@ return pseudo == kPseudoIdBefore || pseudo == kPseudoIdAfter; } - // Returns true if the element is a top layer candidate whose overlay property - // computes to 'auto'. - bool IsInTopLayer(const Element& element) const; + // Returns true if the element is rendered in the top layer. That is the case + // when the overlay property computes to 'auto', or when the element is a + // ::backdrop pseudo. + bool IsRenderedInTopLayer(const Element& element) const; // Load the images of CSS properties that were deferred by LazyLoad. void LoadDeferredImages(Document&) const;
diff --git a/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl b/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl index 6d4a53a3..fde8c37 100644 --- a/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl +++ b/third_party/blink/renderer/modules/ad_auction/navigator_auction.idl
@@ -31,13 +31,13 @@ [RuntimeEnabled=Fledge, CallWith=ScriptState, Measure, RaisesException] sequence<USVString> adAuctionComponents([Clamp] unsigned short numComponents); - [RuntimeEnable=AllowURLsinIframes, CallWith=ScriptState, Measure, RaisesException] + [RuntimeEnabled=AllowURNsInIframes, CallWith=ScriptState, Measure, RaisesException] Promise<USVString> deprecatedURNToURL(UrnOrConfig urn_or_config, optional boolean send_reports = false); - [RuntimeEnable=AllowURLsinIframes, CallWith=ScriptState, Measure, RaisesException] + [RuntimeEnabled=AllowURNsInIframes, CallWith=ScriptState, Measure, RaisesException] Promise<void> deprecatedReplaceInURN(UrnOrConfig urn_or_config, record<USVString, USVString> replacements); - [RuntimeEnable=FledgeBiddingAndAuctionServer, CallWith=ScriptState, Measure, RaisesException] + [RuntimeEnabled=FledgeBiddingAndAuctionServer, CallWith=ScriptState, Measure, RaisesException] Promise<Uint8Array> getInterestGroupAdAuctionData(AdAuctionDataConfig config); [RuntimeEnabled=Parakeet, CallWith=ScriptState, Measure, RaisesException]
diff --git a/third_party/blink/renderer/modules/shared_storage/private_aggregation.cc b/third_party/blink/renderer/modules/shared_storage/private_aggregation.cc index 1e504ae..6ca5bca9 100644 --- a/third_party/blink/renderer/modules/shared_storage/private_aggregation.cc +++ b/third_party/blink/renderer/modules/shared_storage/private_aggregation.cc
@@ -150,7 +150,7 @@ if (!maybe_debug_key || absl::Uint128High64(maybe_debug_key.value()) != 0) { exception_state.ThrowDOMException( DOMExceptionCode::kDataError, - "options['debug_key'] is negative or does not fit in 64 bits"); + "options['debugKey'] is negative or does not fit in 64 bits"); return; }
diff --git a/third_party/blink/renderer/modules/shared_storage/private_aggregation_debug_mode_options.idl b/third_party/blink/renderer/modules/shared_storage/private_aggregation_debug_mode_options.idl index 52348a3..b3c355f 100644 --- a/third_party/blink/renderer/modules/shared_storage/private_aggregation_debug_mode_options.idl +++ b/third_party/blink/renderer/modules/shared_storage/private_aggregation_debug_mode_options.idl
@@ -3,5 +3,5 @@ // found in the LICENSE file. dictionary PrivateAggregationDebugModeOptions { - required bigint debug_key; + required bigint debugKey; };
diff --git a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc index 3ac8451..012eed7 100644 --- a/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc +++ b/third_party/blink/renderer/modules/shared_storage/shared_storage_worklet_unittest.cc
@@ -2962,7 +2962,7 @@ R"( let error; try { - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); privateAggregation.enableDebugMode(); } catch (e) { error = e; @@ -2994,7 +2994,7 @@ class EnableDebugMode { async run() { - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); } } @@ -3032,7 +3032,7 @@ AddModuleResult add_module_result = AddModule(/*script_content=*/R"( class TestClass { async run() { - privateAggregation.enableDebugMode({debug_key: 1234n}); + privateAggregation.enableDebugMode({debugKey: 1234n}); privateAggregation.contributeToHistogram({bucket: 1n, value: 2}); privateAggregation.contributeToHistogram({bucket: 3n, value: 4}); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc index 31790df..21de6f9 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -551,7 +551,7 @@ return; } - WGPUTextureUsage dst_texture_usage = destination->texture()->Usage(); + WGPUTextureUsageFlags dst_texture_usage = destination->texture()->Usage(); if ((dst_texture_usage & WGPUTextureUsage_RenderAttachment) != WGPUTextureUsage_RenderAttachment ||
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_texture.h b/third_party/blink/renderer/modules/webgpu/gpu_texture.h index bb929659..efdaa2c 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_texture.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_texture.h
@@ -53,7 +53,7 @@ WGPUTextureDimension Dimension() { return dimension_; } WGPUTextureFormat Format() { return format_; } - WGPUTextureUsage Usage() { return usage_; } + WGPUTextureUsageFlags Usage() { return usage_; } void DissociateMailbox(); @@ -65,7 +65,7 @@ WGPUTextureDimension dimension_; WGPUTextureFormat format_; - WGPUTextureUsage usage_; + WGPUTextureUsageFlags usage_; scoped_refptr<WebGPUMailboxTexture> mailbox_texture_; };
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc index de431c4..07a236e 100644 --- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc +++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -470,9 +470,9 @@ gpu::Mailbox shared_image_mailbox; if (gpu_memory_buffer_) { shared_image_mailbox = shared_image_interface->CreateSharedImage( - gpu_memory_buffer_.get(), gpu_memory_buffer_manager, GetColorSpace(), - surface_origin, surface_alpha_type, shared_image_usage_flags, - "CanvasResourceRasterGmb"); + GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin, + surface_alpha_type, shared_image_usage_flags, "CanvasResourceRasterGmb", + gpu_memory_buffer_->CloneHandle()); } else { shared_image_mailbox = shared_image_interface->CreateSharedImage( GetSharedImageFormat(), Size(), GetColorSpace(), surface_origin,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index aac3aa7..006359c 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -318,6 +318,10 @@ base_feature: "none", }, { + name: "AllowURNsInIframes", + base_feature: "none", + }, + { name: "AndroidDownloadableFontsMatching", base_feature: "none", public: true, @@ -2921,6 +2925,11 @@ status: "stable", }, { + name: "RemoveDanglingMarkupInTarget", + status: "experimental", + base_feature: "none", + }, + { name: "RemoveDataUrlInSvgUse", status: "experimental", base_feature: "none",
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations index 325845b4..22c21638 100644 --- a/third_party/blink/web_tests/LeakExpectations +++ b/third_party/blink/web_tests/LeakExpectations
@@ -28,7 +28,7 @@ crbug.com/1103082 [ Linux ] fast/forms/select/select-change-layout-object-crash.html [ Failure ] # Sheriff 2021-02-25 -crbug.com/1182675 [ Linux ] dom/attr/id-update-map-crash.html [ Failure Pass ] +crbug.com/1182675 [ Linux ] dom/mutation-event-tests/dom/attr/id-update-map-crash.html [ Failure Pass ] # Sheriff 2021-03-02 crbug.com/1183788 [ Linux ] external/wpt/pointerevents/pointerevent_fractional_coordinates.html?touch [ Pass Failure ]
diff --git a/third_party/blink/web_tests/SmokeTests/Default.txt b/third_party/blink/web_tests/SmokeTests/Default.txt index b38b7ba..3e76da2e 100644 --- a/third_party/blink/web_tests/SmokeTests/Default.txt +++ b/third_party/blink/web_tests/SmokeTests/Default.txt
@@ -111,7 +111,6 @@ editing/selection/mouse/drag_user_select_none.html editing/selection/previous-line-position.html editing/selection/select_all/select_all_overflow_hidden_table.html -editing/selection/selection-forces-unrooted-repaint.html editing/selection/set_base_and_extent/set_base_and_extent_uneditable_table.html editing/shadow/505092-fieldset-is-not-ua-shadow-crash.html editing/shadow/getRangeAt-end-of-text-node.html @@ -562,7 +561,6 @@ fast/forms/time/time-validity-rangeunderflow.html fast/forms/time/time-validity-typemismatch.html fast/forms/url/url-sanitize-user-input.html -fast/forms/week-multiple-fields/week-multiple-fields-no-shadow-event.html fast/forms/week/ValidityState-rangeOverflow-week.html fast/forms/week/week-setrangetext.html fast/gradients/crash-on-tr.html
diff --git a/third_party/blink/web_tests/SmokeTests/skia-vulkan-swiftshader b/third_party/blink/web_tests/SmokeTests/skia-vulkan-swiftshader index d6c86bc..c87d5756 100644 --- a/third_party/blink/web_tests/SmokeTests/skia-vulkan-swiftshader +++ b/third_party/blink/web_tests/SmokeTests/skia-vulkan-swiftshader
@@ -780,7 +780,7 @@ media/track/track-language-preference.html media/video-controls-attribute-fullscreen.html media/video-controls-fullscreen-not-supported.html -media/video-controls-with-mutation-event-handler.html +dom/mutation-event-tests/media/video-controls-with-mutation-event-handler.html media/video-currentTime-before-have-metadata.html media/video-currentTime-delay.html media/video-move-to-new-document-srcobject.html
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index a31e8ae..6720dac 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2243,12 +2243,6 @@ crbug.com/723741 virtual/threaded/http/tests/devtools/tracing/idle-callback.js [ Crash Failure Pass Timeout ] -# Untriaged failures after https://crrev.com/c/543695/. -# These need to be updated but appear not to be related to that change. -crbug.com/626703 http/tests/devtools/indexeddb/database-refresh-view.js [ Failure Pass ] - - - # Failure messages are unstable so we cannot create baselines. crbug.com/832071 external/wpt/service-workers/service-worker/worker-client-id.https.html [ Failure ] @@ -2881,6 +2875,11 @@ crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/scroll-timeline-range-animation.html [ Timeout ] +crbug.com/626703 external/wpt/css/css-color/oklab-009.html [ Failure ] +crbug.com/626703 external/wpt/css/css-color/oklch-011.html [ Failure ] +crbug.com/626703 [ Mac13 ] virtual/threaded/external/wpt/scroll-animations/css/scroll-timeline-range-animation.html [ Timeout ] +crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/css/animation-timeline-view-functional-notation.tentative.html [ Timeout ] crbug.com/626703 [ Mac13 ] virtual/threaded-prefer-compositing/external/wpt/scroll-animations/view-timelines/view-timeline-inset.html [ Timeout ] crbug.com/626703 [ Mac11 ] external/wpt/mediacapture-record/MediaRecorder-mimetype.html [ Timeout ] crbug.com/626703 external/wpt/css/css-backgrounds/box-shadow-border-radius-001.html [ Failure ] @@ -5985,6 +5984,7 @@ crbug.com/1434123 media/video-source-type-params.html [ Failure Pass ] crbug.com/1418393 [ Debug Linux ] external/wpt/performance-timeline/not-restored-reasons/performance-navigation-timing-attributes.tentative.window.html [ Failure ] crbug.com/1445674 [ Linux ] webaudio/internals/audioworkletprocessor-gc.https.html [ Timeout ] +crbug.com/1427282 [ Debug Linux ] fast/dom/HTMLLinkElement/link-onload2.html [ Timeout ] # Suppress http/tests/inspector-protocol/network/navigate-iframe-in2out.js test cluster crbug.com/1395412 [ Mac ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/navigate-iframe-in2out.js [ Failure ] @@ -6740,7 +6740,7 @@ [ Debug Mac12 ] virtual/schemeful-same-site/external/wpt/cookies/attributes/domain.sub.html [ Failure ] [ Debug Mac12 ] virtual/shared-storage-fenced-frame-mparch-selecturl-limit/wpt_internal/shared_storage_selecturl_limit/run-url-selection-operation-limit-multiple-origins.https.html [ Failure ] [ Debug Mac12 ] virtual/shared-storage-fenced-frame-mparch/wpt_internal/shared_storage/embedder-context.https.html [ Failure ] -[ Debug Mac12 ] virtual/threaded/external/wpt/requestidlecallback/deadline-max-rAF.html [ Failure ] +crbug.com/1446992 [ Mac ] virtual/threaded/external/wpt/requestidlecallback/deadline-max-rAF.html [ Failure ] [ Debug Mac12 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/module/dynamic-import/microtasks/basic.any.worker.html [ Failure ] [ Debug Mac12 ] virtual/threaded-preload-scanner/external/wpt/html/semantics/scripting-1/the-script-element/moving-between-documents/ordering/delay-load-event-2.html [ Failure ] [ Debug Mac12 ] virtual/unified-autoplay/external/wpt/feature-policy/feature-policy-frame-policy-timing.https.sub.html [ Failure ] @@ -6831,15 +6831,11 @@ crbug.com/1430215 external/wpt/dom/events/scrolling/scrollend-event-for-user-scroll.html [ Failure Pass ] crbug.com/1434378 virtual/fenced-frame-mparch/http/tests/inspector-protocol/fenced-frame/permissions-policy-fenced-frame.https.js [ Pass Timeout ] -crbug.com/1448011 http/tests/devtools/application-panel/resources-panel-on-navigation.js [ Failure Pass ] -crbug.com/1448011 http/tests/devtools/application-panel/resources-panel-selection-on-reload.js [ Failure Pass ] -crbug.com/1448011 http/tests/devtools/indexeddb/delete-entry.js [ Failure Pass ] -crbug.com/1448011 http/tests/devtools/indexeddb/live-update-indexeddb-content.js [ Failure Pass ] -crbug.com/1448011 http/tests/devtools/indexeddb/resources-panel.js [ Failure Pass ] - # Sheriff 2023-05-26 crbug.com/1448255 [ Linux ] virtual/netinfo-constant-type/netinfo/multiple-frames.html [ Failure Pass ] crbug.com/1448011 http/tests/devtools/application-panel/resources-panel-resource-preview.js [ Failure Pass ] crbug.com/1448011 http/tests/devtools/application-panel/resources-panel-websql.js [ Failure Pass ] crbug.com/1448011 http/tests/devtools/oopif/oopif-storage.js [ Failure Pass ] + +crbug.com/1449347 http/tests/devtools/persistence/persistence-sync-content-nodejs.js [ Failure Pass ]
diff --git a/third_party/blink/web_tests/dom/mutation-event-tests/README.txt b/third_party/blink/web_tests/dom/mutation-event-tests/README.txt new file mode 100644 index 0000000..3818e9c0 --- /dev/null +++ b/third_party/blink/web_tests/dom/mutation-event-tests/README.txt
@@ -0,0 +1,26 @@ + +See crbug.com/1446498 for more context. + +The tests in this sub-folder only test Mutation Events. They were relocated here +from their original location (keeping the relative path structure) so that when +Mutation Events are removed, this entire folder can simply be deleted. + +These tests remain *outside* this folder, but still use Mutation Events, +because it isn't clear whether they should be re-written using other tech: + +- accessibility/details-summary-crash.html +- editing/pasteboard/drag-and-drop-image-contenteditable.html +- editing/pasteboard/drag-and-drop-inputimage-contenteditable.html +- editing/pasteboard/drag-and-drop-objectimage-contenteditable.html +- fast/dom/HTMLElement/set-inner-outer-optimization.html +- fast/dom/MutationObserver/observe-attributes.html +- fast/dom/MutationObserver/observe-characterdata.html +- fast/dom/dom-method-document-change.html +- fast/dom/move-nodes-across-documents.html +- fast/dom/shadow/shadow-boundary-crossing.html +- fast/events/window-onerror-isolatedworld-02.html +- http/tests/xmlhttprequest/reentrant-cancel-abort.html +- http/tests/xmlhttprequest/reentrant-cancel.html +- inspector-protocol/sessions/log-entry-added.js + +
diff --git a/third_party/blink/web_tests/dom/attr/id-update-map-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/dom/attr/id-update-map-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/dom/attr/id-update-map-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/attr/id-update-map-crash-expected.txt
diff --git a/third_party/blink/web_tests/dom/attr/id-update-map-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/dom/attr/id-update-map-crash.html similarity index 100% rename from third_party/blink/web_tests/dom/attr/id-update-map-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/attr/id-update-map-crash.html
diff --git a/third_party/blink/web_tests/dom/node/DOMNodeRemovedEvent-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/DOMNodeRemovedEvent-expected.txt similarity index 100% rename from third_party/blink/web_tests/dom/node/DOMNodeRemovedEvent-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/node/DOMNodeRemovedEvent-expected.txt
diff --git a/third_party/blink/web_tests/dom/node/DOMNodeRemovedEvent.html b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/DOMNodeRemovedEvent.html similarity index 79% rename from third_party/blink/web_tests/dom/node/DOMNodeRemovedEvent.html rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/node/DOMNodeRemovedEvent.html index ce35918..000232b7 100644 --- a/third_party/blink/web_tests/dom/node/DOMNodeRemovedEvent.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/DOMNodeRemovedEvent.html
@@ -1,7 +1,7 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/dom/node/fragment-mutation-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/fragment-mutation-expected.txt similarity index 100% rename from third_party/blink/web_tests/dom/node/fragment-mutation-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/node/fragment-mutation-expected.txt
diff --git a/third_party/blink/web_tests/dom/node/fragment-mutation.html b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/fragment-mutation.html similarity index 99% rename from third_party/blink/web_tests/dom/node/fragment-mutation.html rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/node/fragment-mutation.html index 9b77274..816df81 100644 --- a/third_party/blink/web_tests/dom/node/fragment-mutation.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/fragment-mutation.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <html> <head> <title>Fragment Mutation Tests</title>
diff --git a/third_party/blink/web_tests/dom/node/textContent-single-DOMSubtreeModified-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/textContent-single-DOMSubtreeModified-expected.txt similarity index 100% rename from third_party/blink/web_tests/dom/node/textContent-single-DOMSubtreeModified-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/node/textContent-single-DOMSubtreeModified-expected.txt
diff --git a/third_party/blink/web_tests/dom/node/textContent-single-DOMSubtreeModified.html b/third_party/blink/web_tests/dom/mutation-event-tests/dom/node/textContent-single-DOMSubtreeModified.html similarity index 100% rename from third_party/blink/web_tests/dom/node/textContent-single-DOMSubtreeModified.html rename to third_party/blink/web_tests/dom/mutation-event-tests/dom/node/textContent-single-DOMSubtreeModified.html
diff --git a/third_party/blink/web_tests/editing/deleting/delete-key-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-key-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/deleting/delete-key-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-key-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/deleting/delete-key-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-key-crash.html similarity index 100% rename from third_party/blink/web_tests/editing/deleting/delete-key-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-key-crash.html
diff --git a/third_party/blink/web_tests/editing/deleting/delete-node-after-DOMNodeRemoved-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-node-after-DOMNodeRemoved-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/deleting/delete-node-after-DOMNodeRemoved-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-node-after-DOMNodeRemoved-expected.txt
diff --git a/third_party/blink/web_tests/editing/deleting/delete-node-after-DOMNodeRemoved.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-node-after-DOMNodeRemoved.html similarity index 98% rename from third_party/blink/web_tests/editing/deleting/delete-node-after-DOMNodeRemoved.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-node-after-DOMNodeRemoved.html index b7688ea..9b6c339 100644 --- a/third_party/blink/web_tests/editing/deleting/delete-node-after-DOMNodeRemoved.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/deleting/delete-node-after-DOMNodeRemoved.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <p>This tests for a bug where delete would crash if a node just after the selection to delete is removed in a DOMNodeRemoved event handler for the last node in the selection to delete. <a href="rdar://problem/5156801"><rdar://problem/5156801></a></p> <div id="div" contenteditable="true">foo<span id="foo">x</span><span id="removeme">y</span></div> <p id="console"></p>
diff --git a/third_party/blink/web_tests/editing/execCommand/5120591-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/5120591-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/execCommand/5120591-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/5120591-expected.txt
diff --git a/third_party/blink/web_tests/editing/execCommand/5120591.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/5120591.html similarity index 96% rename from third_party/blink/web_tests/editing/execCommand/5120591.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/5120591.html index c01420be..42398a75 100644 --- a/third_party/blink/web_tests/editing/execCommand/5120591.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/5120591.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <p>Tests for a crash when creating a link inside a region with a subtree modified event listener.</p> <div contenteditable="true" id="div">This should be a link.</div>
diff --git a/third_party/blink/web_tests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/editing-command-while-executing-typing-command-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/execCommand/editing-command-while-executing-typing-command-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/editing-command-while-executing-typing-command-crash.html similarity index 85% rename from third_party/blink/web_tests/editing/execCommand/editing-command-while-executing-typing-command-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/editing-command-while-executing-typing-command-crash.html index b709acd..39c7bd8 100644 --- a/third_party/blink/web_tests/editing/execCommand/editing-command-while-executing-typing-command-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/editing-command-while-executing-typing-command-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <script> window.onload = function() { if (window.testRunner) @@ -8,7 +9,7 @@ document.execCommand("insertparagraph", false); document.execCommand("InsertText", false); - document.firstChild.appendChild(document.createElement('body')); + document.children[0].appendChild(document.createElement('body')); document.body.innerText = "This tests executing an editing command while executing a typing command.\nPASS"; };
diff --git a/third_party/blink/web_tests/editing/execCommand/insert-ordered-list-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insert-ordered-list-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/execCommand/insert-ordered-list-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insert-ordered-list-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/execCommand/insert-ordered-list-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insert-ordered-list-crash.html similarity index 91% rename from third_party/blink/web_tests/editing/execCommand/insert-ordered-list-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insert-ordered-list-crash.html index 70bfb23..a2909ec 100644 --- a/third_party/blink/web_tests/editing/execCommand/insert-ordered-list-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insert-ordered-list-crash.html
@@ -2,7 +2,7 @@ <html> <head> <title>Issue 344280</title> - <script src="../../resources/js-test.js"></script> + <script src="../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/editing/execCommand/insertHTML-mutation-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insertHTML-mutation-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/execCommand/insertHTML-mutation-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insertHTML-mutation-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/execCommand/insertHTML-mutation-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insertHTML-mutation-crash.html similarity index 100% rename from third_party/blink/web_tests/editing/execCommand/insertHTML-mutation-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/insertHTML-mutation-crash.html
diff --git a/third_party/blink/web_tests/editing/execCommand/resources/insert-ordered-list-crash-iframe.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/resources/insert-ordered-list-crash-iframe.html similarity index 97% rename from third_party/blink/web_tests/editing/execCommand/resources/insert-ordered-list-crash-iframe.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/resources/insert-ordered-list-crash-iframe.html index 3be7f5f..18486cf 100644 --- a/third_party/blink/web_tests/editing/execCommand/resources/insert-ordered-list-crash-iframe.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/resources/insert-ordered-list-crash-iframe.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <html> <body> <script>
diff --git a/third_party/blink/web_tests/editing/execCommand/resources/window-open-insert-list-crash-iframe.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/resources/window-open-insert-list-crash-iframe.html similarity index 96% rename from third_party/blink/web_tests/editing/execCommand/resources/window-open-insert-list-crash-iframe.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/resources/window-open-insert-list-crash-iframe.html index 1dbff88..4d7e7b5 100644 --- a/third_party/blink/web_tests/editing/execCommand/resources/window-open-insert-list-crash-iframe.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/resources/window-open-insert-list-crash-iframe.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <script> document.addEventListener("DOMSubtreeModified", function () {
diff --git a/third_party/blink/web_tests/editing/execCommand/window-open-insert-list-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/window-open-insert-list-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/execCommand/window-open-insert-list-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/window-open-insert-list-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/execCommand/window-open-insert-list-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/window-open-insert-list-crash.html similarity index 92% rename from third_party/blink/web_tests/editing/execCommand/window-open-insert-list-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/window-open-insert-list-crash.html index 10c7116..6cc897d5 100644 --- a/third_party/blink/web_tests/editing/execCommand/window-open-insert-list-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/execCommand/window-open-insert-list-crash.html
@@ -2,7 +2,7 @@ <html> <head> <title>Crash issue 338542</title> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/editing/inserting/delete-insignificant-text-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/delete-insignificant-text-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/inserting/delete-insignificant-text-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/delete-insignificant-text-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/inserting/delete-insignificant-text-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/delete-insignificant-text-crash.html similarity index 100% rename from third_party/blink/web_tests/editing/inserting/delete-insignificant-text-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/delete-insignificant-text-crash.html
diff --git a/third_party/blink/web_tests/editing/inserting/insert-html-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-html-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/inserting/insert-html-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-html-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/inserting/insert-html-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-html-crash.html similarity index 88% rename from third_party/blink/web_tests/editing/inserting/insert-html-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-html-crash.html index 9369dc4..383316d1 100644 --- a/third_party/blink/web_tests/editing/inserting/insert-html-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-html-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script> window.jsTestIsAsync = true;
diff --git a/third_party/blink/web_tests/editing/inserting/insert-paragraph-separator-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-paragraph-separator-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/inserting/insert-paragraph-separator-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-paragraph-separator-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/inserting/insert-paragraph-separator-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-paragraph-separator-crash.html similarity index 100% rename from third_party/blink/web_tests/editing/inserting/insert-paragraph-separator-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-paragraph-separator-crash.html
diff --git a/third_party/blink/web_tests/editing/inserting/insert-with-mutation-event-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-with-mutation-event-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/inserting/insert-with-mutation-event-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-with-mutation-event-expected.txt
diff --git a/third_party/blink/web_tests/editing/inserting/insert-with-mutation-event.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-with-mutation-event.html similarity index 100% rename from third_party/blink/web_tests/editing/inserting/insert-with-mutation-event.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/inserting/insert-with-mutation-event.html
diff --git a/third_party/blink/web_tests/editing/selection/crash-on-drag-with-mutation-events-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/crash-on-drag-with-mutation-events-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/selection/crash-on-drag-with-mutation-events-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/crash-on-drag-with-mutation-events-expected.txt
diff --git a/third_party/blink/web_tests/editing/selection/crash-on-drag-with-mutation-events.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/crash-on-drag-with-mutation-events.html similarity index 98% rename from third_party/blink/web_tests/editing/selection/crash-on-drag-with-mutation-events.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/crash-on-drag-with-mutation-events.html index d41147f..60e43332 100644 --- a/third_party/blink/web_tests/editing/selection/crash-on-drag-with-mutation-events.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/crash-on-drag-with-mutation-events.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <body style="margin: 0px"> <div>Make sure WebKit doesn't crash when web authors blast away everything in DOMNodeInserted handler! https://bugs.webkit.org/show_bug.cgi?id=22634</div> <div id="dragstart" contentEditable>Drag something from here to the document below</div> @@ -40,7 +41,7 @@ eventSender.mouseMoveTo(endX, endY); eventSender.mouseUp(); - + document.body.innerHTML = "PASSED, no crash"; }
diff --git a/third_party/blink/web_tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash.html similarity index 91% rename from third_party/blink/web_tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash.html index 1d2ea86..2f2a464 100644 --- a/third_party/blink/web_tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/deleteFromDocument-scoped-dispatch-event-crash.html
@@ -2,7 +2,7 @@ <html> <head> <title>Crash issue 339186</title> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/editing/selection/resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html similarity index 96% rename from third_party/blink/web_tests/editing/selection/resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html index 69cb999..a6cb429b 100644 --- a/third_party/blink/web_tests/editing/selection/resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/resources/deleteFromDocument-scoped-dispatch-event-crash-iframe.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <html> <head> <script>
diff --git a/third_party/blink/web_tests/editing/selection/selection-forces-unrooted-repaint-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/selection-forces-unrooted-repaint-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/selection/selection-forces-unrooted-repaint-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/selection-forces-unrooted-repaint-expected.txt
diff --git a/third_party/blink/web_tests/editing/selection/selection-forces-unrooted-repaint.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/selection-forces-unrooted-repaint.html similarity index 100% rename from third_party/blink/web_tests/editing/selection/selection-forces-unrooted-repaint.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/selection/selection-forces-unrooted-repaint.html
diff --git a/third_party/blink/web_tests/editing/style/apply-style-crash3-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-crash3-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/style/apply-style-crash3-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-crash3-expected.txt
diff --git a/third_party/blink/web_tests/editing/style/apply-style-crash3.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-crash3.html similarity index 93% rename from third_party/blink/web_tests/editing/style/apply-style-crash3.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-crash3.html index c168d9f..021739a 100644 --- a/third_party/blink/web_tests/editing/style/apply-style-crash3.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-crash3.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <unknown>
diff --git a/third_party/blink/web_tests/editing/style/apply-style-join-child-text-nodes-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-join-child-text-nodes-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/style/apply-style-join-child-text-nodes-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-join-child-text-nodes-crash-expected.txt
diff --git a/third_party/blink/web_tests/editing/style/apply-style-join-child-text-nodes-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-join-child-text-nodes-crash.html similarity index 91% rename from third_party/blink/web_tests/editing/style/apply-style-join-child-text-nodes-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-join-child-text-nodes-crash.html index 1d90184..8ed554b 100644 --- a/third_party/blink/web_tests/editing/style/apply-style-join-child-text-nodes-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/apply-style-join-child-text-nodes-crash.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <body> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script id="script1"> document.addEventListener("DOMCharacterDataModified",function(){ document.body.innerHTML = "PASS. WebKit didn't crash.";
diff --git a/third_party/blink/web_tests/editing/style/bold-with-dom-changes-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/bold-with-dom-changes-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/style/bold-with-dom-changes-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/style/bold-with-dom-changes-expected.txt
diff --git a/third_party/blink/web_tests/editing/style/bold-with-dom-changes.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/style/bold-with-dom-changes.html similarity index 100% rename from third_party/blink/web_tests/editing/style/bold-with-dom-changes.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/style/bold-with-dom-changes.html
diff --git a/third_party/blink/web_tests/editing/undo/undo-after-event-edited-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/editing/undo/undo-after-event-edited-expected.txt similarity index 100% rename from third_party/blink/web_tests/editing/undo/undo-after-event-edited-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/undo/undo-after-event-edited-expected.txt
diff --git a/third_party/blink/web_tests/editing/undo/undo-after-event-edited.html b/third_party/blink/web_tests/dom/mutation-event-tests/editing/undo/undo-after-event-edited.html similarity index 100% rename from third_party/blink/web_tests/editing/undo/undo-after-event-edited.html rename to third_party/blink/web_tests/dom/mutation-event-tests/editing/undo/undo-after-event-edited.html
diff --git a/third_party/blink/web_tests/fast/block/float/rubybase-children-made-inline-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/block/float/rubybase-children-made-inline-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/block/float/rubybase-children-made-inline-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/block/float/rubybase-children-made-inline-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/block/float/rubybase-children-made-inline-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/block/float/rubybase-children-made-inline-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/block/float/rubybase-children-made-inline-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/block/float/rubybase-children-made-inline-crash.html
diff --git a/third_party/blink/web_tests/fast/css/button-inner-child-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/button-inner-child-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/css/button-inner-child-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/css/button-inner-child-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/css/button-inner-child-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/button-inner-child-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/css/button-inner-child-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/css/button-inner-child-crash.html
diff --git a/third_party/blink/web_tests/fast/css/first-letter-associated-text-node-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-associated-text-node-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/css/first-letter-associated-text-node-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-associated-text-node-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/css/first-letter-associated-text-node-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-associated-text-node-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/css/first-letter-associated-text-node-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-associated-text-node-crash.html
diff --git a/third_party/blink/web_tests/fast/css/first-letter-range-insert-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-range-insert-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/css/first-letter-range-insert-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-range-insert-expected.txt
diff --git a/third_party/blink/web_tests/fast/css/first-letter-range-insert.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-range-insert.html similarity index 97% rename from third_party/blink/web_tests/fast/css/first-letter-range-insert.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-range-insert.html index d0fd66e..6c4c6d5 100644 --- a/third_party/blink/web_tests/fast/css/first-letter-range-insert.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/css/first-letter-range-insert.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <style> div:first-child {
diff --git a/third_party/blink/web_tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch.html similarity index 88% rename from third_party/blink/web_tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch.html index 715c8871..4f244fc 100644 --- a/third_party/blink/web_tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/HTMLImageElement/constructor-mutation-event-dispatch.html
@@ -1,9 +1,10 @@ +<!DOCTYPE html> <head> <script> function listen(event) { } - + function test() { if (window.testRunner) @@ -17,7 +18,7 @@ <body onload="test()"> <p> Test for <i><a href="http://bugs.webkit.org/show_bug.cgi?id=12353">http://bugs.webkit.org/show_bug.cgi?id=12353</a> - REGRESSION: Crash on load (mutation event dispatch under the image element constructor deletes the element)</i>. + REGRESSION: Crash on load (mutation event dispatch under the image element constructor deletes the element)</i>. </p> <p> No crash means test PASS.
diff --git a/third_party/blink/web_tests/fast/dom/MutationObserver/added-out-of-order-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/added-out-of-order-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/MutationObserver/added-out-of-order-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/added-out-of-order-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/MutationObserver/added-out-of-order.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/added-out-of-order.html similarity index 94% rename from third_party/blink/web_tests/fast/dom/MutationObserver/added-out-of-order.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/added-out-of-order.html index aa28966..73ad813 100644 --- a/third_party/blink/web_tests/fast/dom/MutationObserver/added-out-of-order.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/added-out-of-order.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <div id="sandbox" style="display:none"><span></span></div> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <script> description("Test MutationEvents interfering with MutationObservers: adding nodes 'out of order'"); var sandbox = document.getElementById('sandbox');
diff --git a/third_party/blink/web_tests/fast/dom/MutationObserver/removed-out-of-order-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/removed-out-of-order-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/MutationObserver/removed-out-of-order-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/removed-out-of-order-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/MutationObserver/removed-out-of-order.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/removed-out-of-order.html similarity index 94% rename from third_party/blink/web_tests/fast/dom/MutationObserver/removed-out-of-order.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/removed-out-of-order.html index 39479911..2b9c4fcb 100644 --- a/third_party/blink/web_tests/fast/dom/MutationObserver/removed-out-of-order.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/MutationObserver/removed-out-of-order.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <div id="sandbox" style="display:none"></div> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <script> description("Test MutationEvents interfering with MutationObservers: removing nodes 'out of order'"); var sandbox = document.getElementById('sandbox');
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-created-during-remove-children-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-created-during-remove-children-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-created-during-remove-children-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-created-during-remove-children-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-created-during-remove-children.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-created-during-remove-children.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/Range/range-created-during-remove-children.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-created-during-remove-children.html index e21fc9e..5dd53685 100644 --- a/third_party/blink/web_tests/fast/dom/Range/range-created-during-remove-children.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-created-during-remove-children.html
@@ -1,9 +1,10 @@ +<!DOCTYPE html> <div id="container"> <p id="description"></p> <div id="sample"><span contenteditable="true">foobar</span></div> </div> <div id="console"></div> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <script> description('Range objects should be updated after set innerHTML.');
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-delete-contents-event-fire-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-event-fire-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-delete-contents-event-fire-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-event-fire-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-delete-contents-event-fire-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-event-fire-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-delete-contents-event-fire-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-event-fire-crash.html
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-delete-contents-mutation-event-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-mutation-event-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-delete-contents-mutation-event-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-mutation-event-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-delete-contents-mutation-event-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-mutation-event-crash.html similarity index 97% rename from third_party/blink/web_tests/fast/dom/Range/range-delete-contents-mutation-event-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-mutation-event-crash.html index 1e45c6c..c5472bc5 100644 --- a/third_party/blink/web_tests/fast/dom/Range/range-delete-contents-mutation-event-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-delete-contents-mutation-event-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <div id="container"> <div id="sample">foobar</div>baz </div>
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash.html
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash2-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash2-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash2-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash2-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash2.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash2.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-extract-contents-event-fire-crash2.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extract-contents-event-fire-crash2.html
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-extractContents-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extractContents-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-extractContents-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extractContents-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-extractContents.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extractContents.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-extractContents.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-extractContents.html
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-insertNode-assertion-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-insertNode-assertion-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/range-insertNode-assertion-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-insertNode-assertion-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/range-insertNode-assertion.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-insertNode-assertion.html similarity index 94% rename from third_party/blink/web_tests/fast/dom/Range/range-insertNode-assertion.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-insertNode-assertion.html index 309da7f..d2be606 100644 --- a/third_party/blink/web_tests/fast/dom/Range/range-insertNode-assertion.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/range-insertNode-assertion.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <body> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <div id="parent1">text</div> <div id="parent2">text</div> <script>
diff --git a/third_party/blink/web_tests/fast/dom/Range/remove-twice-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/remove-twice-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/remove-twice-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/remove-twice-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/remove-twice-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/remove-twice-crash.html similarity index 97% rename from third_party/blink/web_tests/fast/dom/Range/remove-twice-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/remove-twice-crash.html index 2d3d2ac4..3f3a010 100644 --- a/third_party/blink/web_tests/fast/dom/Range/remove-twice-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/remove-twice-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <div id="container"> <div id="sample">foo</div> </div>
diff --git a/third_party/blink/web_tests/fast/dom/Range/split-text-in-range-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/split-text-in-range-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/split-text-in-range-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/split-text-in-range-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/split-text-in-range.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/split-text-in-range.html similarity index 91% rename from third_party/blink/web_tests/fast/dom/Range/split-text-in-range.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/split-text-in-range.html index 835a4da6..4e7abef 100644 --- a/third_party/blink/web_tests/fast/dom/Range/split-text-in-range.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/split-text-in-range.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <body> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <div id="parent1">text</div> <script> var parent = document.getElementById('parent1');
diff --git a/third_party/blink/web_tests/fast/dom/Range/surroundContents-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/surroundContents-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/Range/surroundContents-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/surroundContents-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/Range/surroundContents-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/surroundContents-crash.html similarity index 96% rename from third_party/blink/web_tests/fast/dom/Range/surroundContents-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/surroundContents-crash.html index b4b7dfe..15ac1e178 100644 --- a/third_party/blink/web_tests/fast/dom/Range/surroundContents-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/Range/surroundContents-crash.html
@@ -2,7 +2,7 @@ <html> <head> <title>Range.surroundContents() crash</title> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/fast/dom/append-multiple-document-elements-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/append-multiple-document-elements-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/append-multiple-document-elements-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/append-multiple-document-elements-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/append-multiple-document-elements.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/append-multiple-document-elements.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/append-multiple-document-elements.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/append-multiple-document-elements.html
diff --git a/third_party/blink/web_tests/fast/dom/class-attr-change-double-mutation-fire-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/class-attr-change-double-mutation-fire-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/class-attr-change-double-mutation-fire-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/class-attr-change-double-mutation-fire-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/class-attr-change-double-mutation-fire.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/class-attr-change-double-mutation-fire.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/class-attr-change-double-mutation-fire.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/class-attr-change-double-mutation-fire.html
diff --git a/third_party/blink/web_tests/fast/dom/cloneNode-below-body-attribute-merging-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/cloneNode-below-body-attribute-merging-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/cloneNode-below-body-attribute-merging-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/cloneNode-below-body-attribute-merging-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/cloneNode-below-body-attribute-merging.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/cloneNode-below-body-attribute-merging.html similarity index 89% rename from third_party/blink/web_tests/fast/dom/cloneNode-below-body-attribute-merging.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/cloneNode-below-body-attribute-merging.html index 5a18915c..1e27222 100644 --- a/third_party/blink/web_tests/fast/dom/cloneNode-below-body-attribute-merging.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/cloneNode-below-body-attribute-merging.html
@@ -8,7 +8,7 @@ }, false); </script> <meta charset="utf-8"> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body id="some_random_id_so_body_creates_attribute_data" class="another_random_attribute_to_increase_crash_surface_area"> <script>
diff --git a/third_party/blink/web_tests/fast/dom/containerNode-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/containerNode-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/containerNode-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/containerNode-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/containerNode.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/containerNode.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/containerNode.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/containerNode.html
diff --git a/third_party/blink/web_tests/fast/dom/document-set-title-mutation-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-mutation-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/document-set-title-mutation-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-mutation-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/document-set-title-mutation-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-mutation-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/document-set-title-mutation-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-mutation-crash.html
diff --git a/third_party/blink/web_tests/fast/dom/document-set-title-single-DOMSubtreeModified-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-single-DOMSubtreeModified-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/document-set-title-single-DOMSubtreeModified-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-single-DOMSubtreeModified-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/document-set-title-single-DOMSubtreeModified.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-single-DOMSubtreeModified.html similarity index 88% rename from third_party/blink/web_tests/fast/dom/document-set-title-single-DOMSubtreeModified.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-single-DOMSubtreeModified.html index 509a32b..06709ab 100644 --- a/third_party/blink/web_tests/fast/dom/document-set-title-single-DOMSubtreeModified.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/document-set-title-single-DOMSubtreeModified.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <title>document title and DOMSubtreeModified</title> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <body> <script> description("On setting document.title, only one DOMSubtreeModified event is created.");
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency.html index 1fce622d..0adf04e 100644 --- a/third_party/blink/web_tests/fast/dom/getElementById-consistency.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <div id=container> </div> <span id=el>
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency2-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency2-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency2-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency2-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency2.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency2.html similarity index 91% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency2.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency2.html index bcac7e7b..e3546ae 100644 --- a/third_party/blink/web_tests/fast/dom/getElementById-consistency2.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency2.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <div id=container> </div> <span id=el>
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency3-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency3-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency3-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency3-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency3.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency3.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency3.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency3.html index b30448d1..698f77d 100644 --- a/third_party/blink/web_tests/fast/dom/getElementById-consistency3.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency3.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <div id=container> <span id=el> </span>
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency4-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency4-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency4-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency4-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency4.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency4.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency4.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency4.html index 7d78fc4..8b6df3c8d 100644 --- a/third_party/blink/web_tests/fast/dom/getElementById-consistency4.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency4.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <div id=container> <span id=el> </span>
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency5-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency5-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency5-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency5-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/getElementById-consistency5.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency5.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/getElementById-consistency5.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency5.html index 39eec46..72fa556 100644 --- a/third_party/blink/web_tests/fast/dom/getElementById-consistency5.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/getElementById-consistency5.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <div id=container> <span id=el> </span>
diff --git a/third_party/blink/web_tests/fast/dom/hover-node-refcnt-asan-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/hover-node-refcnt-asan-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/hover-node-refcnt-asan-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/hover-node-refcnt-asan-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/hover-node-refcnt-asan-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/hover-node-refcnt-asan-crash.html similarity index 97% rename from third_party/blink/web_tests/fast/dom/hover-node-refcnt-asan-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/hover-node-refcnt-asan-crash.html index 8da97c0..f5cc5ba5 100644 --- a/third_party/blink/web_tests/fast/dom/hover-node-refcnt-asan-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/hover-node-refcnt-asan-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <div id=div0></div> <div id=div1> <div id=overflow style="width:500px; height:150px; padding:10px">
diff --git a/third_party/blink/web_tests/fast/dom/insertBefore-refChild-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/insertBefore-refChild-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/insertBefore-refChild-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/insertBefore-refChild-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/insertBefore-refChild-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/insertBefore-refChild-crash.html similarity index 89% rename from third_party/blink/web_tests/fast/dom/insertBefore-refChild-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/insertBefore-refChild-crash.html index 18de84af..bacbbe2 100644 --- a/third_party/blink/web_tests/fast/dom/insertBefore-refChild-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/insertBefore-refChild-crash.html
@@ -1,7 +1,8 @@ +<!DOCTYPE html> <div>Test passes if it does not crash.</div> <span id=container><span></span></span> <span id=newChild></span> -<script src="../../resources/gc.js"></script> +<script src="../../../../resources/gc.js"></script> <script> if (window.testRunner) testRunner.dumpAsText();
diff --git a/third_party/blink/web_tests/fast/dom/margin-height-guarded-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/margin-height-guarded-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/margin-height-guarded-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/margin-height-guarded-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/margin-height-guarded-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/margin-height-guarded-crash.html similarity index 88% rename from third_party/blink/web_tests/fast/dom/margin-height-guarded-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/margin-height-guarded-crash.html index 706e309..f0466ed5 100644 --- a/third_party/blink/web_tests/fast/dom/margin-height-guarded-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/margin-height-guarded-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> -<script src="../../resources/testharness.js"></script> -<script src="../../resources/testharnessreport.js"></script> +<script src="../../../../resources/testharness.js"></script> +<script src="../../../../resources/testharnessreport.js"></script> <body> <!-- Adapted from clusterfuzz case filed in https://crbug.com/778956.
diff --git a/third_party/blink/web_tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash.html similarity index 93% rename from third_party/blink/web_tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash.html index 4f06402..1165d53 100644 --- a/third_party/blink/web_tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-listener-with-dirty-inline-style-crash.html
@@ -4,7 +4,7 @@ <style> *[foo^=""] { border: inherit; } </style> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script> window.jsTestIsAsync = true; if (window.testRunner) {
diff --git a/third_party/blink/web_tests/fast/dom/mutation-event-remove-inserted-node-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-remove-inserted-node-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/mutation-event-remove-inserted-node-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-remove-inserted-node-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/mutation-event-remove-inserted-node.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-remove-inserted-node.html similarity index 95% rename from third_party/blink/web_tests/fast/dom/mutation-event-remove-inserted-node.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-remove-inserted-node.html index 3956b84..85858df 100644 --- a/third_party/blink/web_tests/fast/dom/mutation-event-remove-inserted-node.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/mutation-event-remove-inserted-node.html
@@ -1,6 +1,7 @@ +<!DOCTYPE html> <body> -<p>This test verifies that a mutation event that removes inserted nodes from the +<p>This test verifies that a mutation event that removes inserted nodes from the document doesn't crash upon the insertion of a new node into the document.</p> <p>PASS: You didn't crash.</p>
diff --git a/third_party/blink/web_tests/fast/dom/option-text-mutation-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/option-text-mutation-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/option-text-mutation-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/option-text-mutation-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/option-text-mutation-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/option-text-mutation-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/option-text-mutation-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/option-text-mutation-crash.html
diff --git a/third_party/blink/web_tests/fast/dom/shadow/cyclic-append-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/cyclic-append-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/shadow/cyclic-append-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/cyclic-append-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/shadow/cyclic-append-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/cyclic-append-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/dom/shadow/cyclic-append-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/cyclic-append-crash.html
diff --git a/third_party/blink/web_tests/fast/dom/shadow/remove-details-in-exec-command-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/remove-details-in-exec-command-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/shadow/remove-details-in-exec-command-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/remove-details-in-exec-command-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/shadow/remove-details-in-exec-command-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/remove-details-in-exec-command-crash.html similarity index 96% rename from third_party/blink/web_tests/fast/dom/shadow/remove-details-in-exec-command-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/remove-details-in-exec-command-crash.html index 79a38b4..6c43b271 100644 --- a/third_party/blink/web_tests/fast/dom/shadow/remove-details-in-exec-command-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/remove-details-in-exec-command-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <script> if (window.testRunner) testRunner.dumpAsText();
diff --git a/third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata.html similarity index 88% rename from third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata.html index 04539128..bc70fbe 100644 --- a/third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-characterdata.html
@@ -1,6 +1,7 @@ +<!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <div id="host"></div>
diff --git a/third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow.html similarity index 90% rename from third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow.html index 3564111a..f81720b 100644 --- a/third_party/blink/web_tests/fast/dom/shadow/suppress-mutation-events-in-shadow.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/shadow/suppress-mutation-events-in-shadow.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <body> <input> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <script> description('Test that mutation events are not triggered in shadow DOM'); var mutationEventTriggered = false;
diff --git a/third_party/blink/web_tests/fast/dom/subtree-modified-attributes-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/subtree-modified-attributes-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/subtree-modified-attributes-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/subtree-modified-attributes-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/subtree-modified-attributes.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/subtree-modified-attributes.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/subtree-modified-attributes.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/subtree-modified-attributes.html index 8c7fd58f..6c7c887 100644 --- a/third_party/blink/web_tests/fast/dom/subtree-modified-attributes.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/subtree-modified-attributes.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <body> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script> description('DOMSubtreeModified should fire when attributes are added or removed, but not modified (see bug 81141)');
diff --git a/third_party/blink/web_tests/fast/dom/text-node-append-data-remove-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/text-node-append-data-remove-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/text-node-append-data-remove-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/text-node-append-data-remove-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/text-node-append-data-remove-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/text-node-append-data-remove-crash.html similarity index 92% rename from third_party/blink/web_tests/fast/dom/text-node-append-data-remove-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/text-node-append-data-remove-crash.html index 5cc8d57f..56d47ab3 100644 --- a/third_party/blink/web_tests/fast/dom/text-node-append-data-remove-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/text-node-append-data-remove-crash.html
@@ -1,6 +1,7 @@ +<!DOCTYPE html> <html> <body onload="runTest()"> -<script src="../../resources/gc.js"></script> +<script src="../../../../resources/gc.js"></script> <script> var count = 0; if (window.testRunner) @@ -10,7 +11,7 @@ } function runTest() -{ +{ try { divBlock.addEventListener("DOMCharacterDataModified", eventListener, false); pBlock.outerText = "text";
diff --git a/third_party/blink/web_tests/fast/dom/xml-parser-error-message-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/dom/xml-parser-error-message-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/dom/xml-parser-error-message-crash.svg b/third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash.svg similarity index 100% rename from third_party/blink/web_tests/fast/dom/xml-parser-error-message-crash.svg rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/dom/xml-parser-error-message-crash.svg
diff --git a/third_party/blink/web_tests/fast/events/attribute-listener-deletion-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/attribute-listener-deletion-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/attribute-listener-deletion-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/attribute-listener-deletion-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/attribute-listener-deletion-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/attribute-listener-deletion-crash.html similarity index 98% rename from third_party/blink/web_tests/fast/events/attribute-listener-deletion-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/attribute-listener-deletion-crash.html index 6661b99..12c2049 100644 --- a/third_party/blink/web_tests/fast/events/attribute-listener-deletion-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/attribute-listener-deletion-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <html> <head> <script> @@ -42,4 +43,4 @@ <body> <span onclick="dispatchError()" id="root">This test passes if it doesn't crash</span> </body> -</html> \ No newline at end of file +</html>
diff --git a/third_party/blink/web_tests/fast/events/dom-character-data-modified-textarea-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/dom-character-data-modified-textarea-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/dom-character-data-modified-textarea-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/dom-character-data-modified-textarea-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/dom-character-data-modified-textarea-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/dom-character-data-modified-textarea-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/events/dom-character-data-modified-textarea-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/dom-character-data-modified-textarea-crash.html
diff --git a/third_party/blink/web_tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering.html similarity index 100% rename from third_party/blink/web_tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/domnodeinsertedintodocument-dispatched-post-rendering.html
diff --git a/third_party/blink/web_tests/fast/events/event-fire-disconnected-bubbling-mutation-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-bubbling-mutation-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/event-fire-disconnected-bubbling-mutation-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-bubbling-mutation-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/event-fire-disconnected-bubbling-mutation.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-bubbling-mutation.html similarity index 85% rename from third_party/blink/web_tests/fast/events/event-fire-disconnected-bubbling-mutation.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-bubbling-mutation.html index d3059118..e136d7e 100644 --- a/third_party/blink/web_tests/fast/events/event-fire-disconnected-bubbling-mutation.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-bubbling-mutation.html
@@ -1,7 +1,7 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/fast/events/event-fire-disconnected-shadow-dom-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-shadow-dom-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/event-fire-disconnected-shadow-dom-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-shadow-dom-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/event-fire-disconnected-shadow-dom-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-shadow-dom-crash.html similarity index 96% rename from third_party/blink/web_tests/fast/events/event-fire-disconnected-shadow-dom-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-shadow-dom-crash.html index 1b7069bf..9e9f3af 100644 --- a/third_party/blink/web_tests/fast/events/event-fire-disconnected-shadow-dom-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-fire-disconnected-shadow-dom-crash.html
@@ -1,5 +1,5 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <div id="root"> <span id="div1"></span>
diff --git a/third_party/blink/web_tests/fast/events/event-listener-moving-documents-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-moving-documents-expected.txt similarity index 92% rename from third_party/blink/web_tests/fast/events/event-listener-moving-documents-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-moving-documents-expected.txt index de3afe7..3f31119e 100644 --- a/third_party/blink/web_tests/fast/events/event-listener-moving-documents-expected.txt +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-moving-documents-expected.txt
@@ -1,6 +1,6 @@ CONSOLE WARNING: Listener added for a synchronous 'DOMNodeInserted' DOM Mutation Event. This event type is deprecated (https://w3c.github.io/uievents/#legacy-event-types) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead. CONSOLE WARNING: Listener added for a synchronous 'DOMNodeRemoved' DOM Mutation Event. This event type is deprecated (https://w3c.github.io/uievents/#legacy-event-types) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead. -Moving an event listener between documents should keep it active +Moving a Mutation Event listener between documents should keep it active On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
diff --git a/third_party/blink/web_tests/fast/events/event-listener-moving-documents.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-moving-documents.html similarity index 78% rename from third_party/blink/web_tests/fast/events/event-listener-moving-documents.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-moving-documents.html index 91b868f..555efc97 100644 --- a/third_party/blink/web_tests/fast/events/event-listener-moving-documents.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-moving-documents.html
@@ -1,8 +1,8 @@ <!DOCTYPE html> <body> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script> -description('Moving an event listener between documents should keep it active'); +description('Moving a Mutation Event listener between documents should keep it active'); var doc = document.implementation.createHTMLDocument(''); var div = doc.createElement('div');
diff --git a/third_party/blink/web_tests/fast/events/event-listener-on-link-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-on-link-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/event-listener-on-link-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-on-link-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/event-listener-on-link-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-on-link-crash.html similarity index 100% rename from third_party/blink/web_tests/fast/events/event-listener-on-link-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/event-listener-on-link-crash.html
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-append-child-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-append-child-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/mutation-during-append-child-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-append-child-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-append-child.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-append-child.html similarity index 91% rename from third_party/blink/web_tests/fast/events/mutation-during-append-child.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-append-child.html index e1aab114..293a6d59 100644 --- a/third_party/blink/web_tests/fast/events/mutation-during-append-child.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-append-child.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <div>
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-insert-before-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-insert-before-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/mutation-during-insert-before-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-insert-before-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-insert-before.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-insert-before.html similarity index 91% rename from third_party/blink/web_tests/fast/events/mutation-during-insert-before.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-insert-before.html index 7f240835..ab2942c54 100644 --- a/third_party/blink/web_tests/fast/events/mutation-during-insert-before.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-insert-before.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <div>
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-replace-child-2-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-2-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/mutation-during-replace-child-2-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-2-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-replace-child-2.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-2.html similarity index 93% rename from third_party/blink/web_tests/fast/events/mutation-during-replace-child-2.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-2.html index 4847a873..a33ea506 100644 --- a/third_party/blink/web_tests/fast/events/mutation-during-replace-child-2.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-2.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <div> @@ -26,7 +26,7 @@ document.removeEventListener("DOMNodeRemoved", handler, false); target.parentNode.removeChild(target); newChild.appendChild(target); -} +} document.addEventListener("DOMNodeRemoved", handler, false); shouldThrow("target.replaceChild(newChild, oldChild);", '"HierarchyRequestError: Failed to execute \'replaceChild\' on \'Node\': The new child element contains the parent."'); </script>
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-replace-child-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/mutation-during-replace-child-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/mutation-during-replace-child.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child.html similarity index 93% rename from third_party/blink/web_tests/fast/events/mutation-during-replace-child.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child.html index 21cb83f..7576c7e2 100644 --- a/third_party/blink/web_tests/fast/events/mutation-during-replace-child.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/mutation-during-replace-child.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <div> @@ -22,7 +22,7 @@ newChild.parentNode.removeChild(newChild); target.parentNode.removeChild(target); newChild.appendChild(target); -} +} document.addEventListener("DOMNodeRemoved", handler, false); shouldThrow("target.replaceChild(newChild, oldChild);", '"NotFoundError: Failed to execute \'replaceChild\' on \'Node\': The node to be removed is no longer a child of this node. Perhaps it was moved in response to a mutation?"'); </script>
diff --git a/third_party/blink/web_tests/fast/events/scoped/editing-commands-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/scoped/editing-commands-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/events/scoped/editing-commands-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/scoped/editing-commands-expected.txt
diff --git a/third_party/blink/web_tests/fast/events/scoped/editing-commands.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/events/scoped/editing-commands.html similarity index 100% rename from third_party/blink/web_tests/fast/events/scoped/editing-commands.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/events/scoped/editing-commands.html
diff --git a/third_party/blink/web_tests/fast/forms/mutation-event-recalc-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/mutation-event-recalc-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/mutation-event-recalc-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/mutation-event-recalc-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/mutation-event-recalc.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/mutation-event-recalc.html similarity index 99% rename from third_party/blink/web_tests/fast/forms/mutation-event-recalc.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/mutation-event-recalc.html index 2d605d413..da5fccf6 100644 --- a/third_party/blink/web_tests/fast/forms/mutation-event-recalc.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/mutation-event-recalc.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <body> <p>Test that HTMLSelectElement DOM is in a consistent state when handling mutation events.</p> <form>
diff --git a/third_party/blink/web_tests/fast/forms/select/add-and-remove-option-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-and-remove-option-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/add-and-remove-option-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-and-remove-option-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/add-and-remove-option.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-and-remove-option.html similarity index 98% rename from third_party/blink/web_tests/fast/forms/select/add-and-remove-option.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-and-remove-option.html index 57df475..f68633e1 100644 --- a/third_party/blink/web_tests/fast/forms/select/add-and-remove-option.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-and-remove-option.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <p>Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=13287">bug 13287</a>: Cannot change SELECT to a dynamically created option.</p> <p>Test that DOM is updated before DOMNodeInserted is dispatched.</p> @@ -22,7 +23,7 @@ function testResults(expectedArr) { var resultsArr = new Array(theSelect.options.length); - + var i; for (i=0; i < theSelect.options.length; i++) { resultsArr[i] = theSelect.options[i].selected; @@ -33,7 +34,7 @@ success = true; successString = "Passed"; } - + log(successString); if (!success) { log("<pre> Expected: " + expectedArr.join() + "<br>" + " Actual: " + resultsArr.join() + "</pre>");
diff --git a/third_party/blink/web_tests/fast/forms/select/add-remove-option-modification-event-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-remove-option-modification-event-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/add-remove-option-modification-event-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-remove-option-modification-event-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/add-remove-option-modification-event.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-remove-option-modification-event.html similarity index 98% rename from third_party/blink/web_tests/fast/forms/select/add-remove-option-modification-event.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-remove-option-modification-event.html index e45735f0..e7b3a9b8 100644 --- a/third_party/blink/web_tests/fast/forms/select/add-remove-option-modification-event.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/add-remove-option-modification-event.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <p>Test that SELECT is in correct state when handling a DOM modification event for option removing.</p> <form> <select ><option selected>1</option><option>2</option></select> @@ -20,7 +21,7 @@ function testResults(expectedArr) { var resultsArr = new Array(theSelect.options.length); - + var i; for (i=0; i < theSelect.options.length; i++) { resultsArr[i] = theSelect.options[i].selected; @@ -31,7 +32,7 @@ success = true; successString = "Passed"; } - + log(successString); if (!success) { log("<pre> Expected: " + expectedArr.join() + "<br>" + " Actual: " + resultsArr.join() + "</pre>");
diff --git a/third_party/blink/web_tests/fast/forms/select/option-add-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/option-add-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/option-add-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/option-add-crash-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/option-add-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/option-add-crash.html similarity index 90% rename from third_party/blink/web_tests/fast/forms/select/option-add-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/option-add-crash.html index 170e401d..9f390281 100644 --- a/third_party/blink/web_tests/fast/forms/select/option-add-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/option-add-crash.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <html> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> <script> function crash() {
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-remove-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-remove-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-remove-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-remove-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-remove.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-remove.html similarity index 90% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-remove.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-remove.html index 3d44bd08..db122f1 100644 --- a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-remove.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-remove.html
@@ -1,7 +1,7 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <p id="description"></p>
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reorder-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reorder-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reorder-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reorder-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reorder.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reorder.html similarity index 93% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reorder.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reorder.html index 7a8e956..c609e18 100644 --- a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reorder.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reorder.html
@@ -1,7 +1,7 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <p id="description"></p>
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reparent-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reparent-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reparent-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reparent-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reparent.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reparent.html similarity index 91% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reparent.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reparent.html index 0f3b732..dc69c26 100644 --- a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation-reparent.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation-reparent.html
@@ -1,7 +1,7 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <p id="description"></p>
diff --git a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation.html similarity index 84% rename from third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation.html index 65a717b2..2ae81c8 100644 --- a/third_party/blink/web_tests/fast/forms/select/select-set-length-with-mutation.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/select/select-set-length-with-mutation.html
@@ -1,7 +1,7 @@ -<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> +<!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <p id="description"></p>
diff --git a/third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-appending-text-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-appending-text-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-appending-text-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-appending-text-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-appending-text.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-appending-text.html similarity index 92% rename from third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-appending-text.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-appending-text.html index 05038ab..eb2454cc 100644 --- a/third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-appending-text.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-appending-text.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../../resources/js-test.js"></script> </head> <body> <script>
diff --git a/third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events.html similarity index 97% rename from third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events.html index a666b81..280d469 100644 --- a/third_party/blink/web_tests/fast/forms/textarea/textarea-and-mutation-events.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/textarea/textarea-and-mutation-events.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <html> <head> <style> @@ -33,4 +34,4 @@ </div> <div id="bar"></div> </body> -</html> \ No newline at end of file +</html>
diff --git a/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-no-shadow-event-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/week-multiple-fields-no-shadow-event-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-no-shadow-event-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/week-multiple-fields-no-shadow-event-expected.txt
diff --git a/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-no-shadow-event.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/week-multiple-fields-no-shadow-event.html similarity index 86% rename from third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-no-shadow-event.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/week-multiple-fields-no-shadow-event.html index 8bfbec5..e76ffb2 100644 --- a/third_party/blink/web_tests/fast/forms/week-multiple-fields/week-multiple-fields-no-shadow-event.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/forms/week-multiple-fields-no-shadow-event.html
@@ -1,6 +1,6 @@ <!DOCTYPE html> <body> -<script src="../../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script> var input = document.createElement("input"); var passed = true;
diff --git a/third_party/blink/web_tests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt similarity index 100% rename from third_party/blink/web_tests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/frames/iframe-onload-and-domnodeinserted-expected.txt
diff --git a/third_party/blink/web_tests/fast/frames/iframe-onload-and-domnodeinserted.html b/third_party/blink/web_tests/dom/mutation-event-tests/fast/frames/iframe-onload-and-domnodeinserted.html similarity index 94% rename from third_party/blink/web_tests/fast/frames/iframe-onload-and-domnodeinserted.html rename to third_party/blink/web_tests/dom/mutation-event-tests/fast/frames/iframe-onload-and-domnodeinserted.html index 87680f7..b0da225 100644 --- a/third_party/blink/web_tests/fast/frames/iframe-onload-and-domnodeinserted.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/fast/frames/iframe-onload-and-domnodeinserted.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <html> <head> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> </head> <body> <div id="g"></div>
diff --git a/third_party/blink/web_tests/html/details_summary/mutation-details-focus-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/html/details_summary/mutation-details-focus-expected.txt similarity index 100% rename from third_party/blink/web_tests/html/details_summary/mutation-details-focus-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/html/details_summary/mutation-details-focus-expected.txt
diff --git a/third_party/blink/web_tests/html/details_summary/mutation-details-focus.html b/third_party/blink/web_tests/dom/mutation-event-tests/html/details_summary/mutation-details-focus.html similarity index 84% rename from third_party/blink/web_tests/html/details_summary/mutation-details-focus.html rename to third_party/blink/web_tests/dom/mutation-event-tests/html/details_summary/mutation-details-focus.html index ae929a6..436612d 100644 --- a/third_party/blink/web_tests/html/details_summary/mutation-details-focus.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/html/details_summary/mutation-details-focus.html
@@ -1,5 +1,6 @@ +<!DOCTYPE html> <body> -<script src="../../resources/js-test.js"></script> +<script src="../../../../resources/js-test.js"></script> <script> (function() { (function() {
diff --git a/third_party/blink/web_tests/html/sections/body-inserting-iframe-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/body-inserting-iframe-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/html/sections/body-inserting-iframe-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/body-inserting-iframe-crash-expected.txt
diff --git a/third_party/blink/web_tests/html/sections/body-inserting-iframe-crash.html b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/body-inserting-iframe-crash.html similarity index 97% rename from third_party/blink/web_tests/html/sections/body-inserting-iframe-crash.html rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/body-inserting-iframe-crash.html index 35cece8..56084d2 100644 --- a/third_party/blink/web_tests/html/sections/body-inserting-iframe-crash.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/body-inserting-iframe-crash.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <script> if (window.testRunner) testRunner.dumpAsText();
diff --git a/third_party/blink/web_tests/html/sections/remove-body-during-body-replacement-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement-expected.txt similarity index 100% rename from third_party/blink/web_tests/html/sections/remove-body-during-body-replacement-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement-expected.txt
diff --git a/third_party/blink/web_tests/html/sections/remove-body-during-body-replacement.html b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement.html similarity index 100% rename from third_party/blink/web_tests/html/sections/remove-body-during-body-replacement.html rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement.html
diff --git a/third_party/blink/web_tests/html/sections/remove-body-during-body-replacement2-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement2-expected.txt similarity index 100% rename from third_party/blink/web_tests/html/sections/remove-body-during-body-replacement2-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement2-expected.txt
diff --git a/third_party/blink/web_tests/html/sections/remove-body-during-body-replacement2.html b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement2.html similarity index 100% rename from third_party/blink/web_tests/html/sections/remove-body-during-body-replacement2.html rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-body-replacement2.html
diff --git a/third_party/blink/web_tests/html/sections/remove-body-during-title-creation-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-title-creation-expected.txt similarity index 95% rename from third_party/blink/web_tests/html/sections/remove-body-during-title-creation-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-title-creation-expected.txt index 59676e7..309a441 100644 --- a/third_party/blink/web_tests/html/sections/remove-body-during-title-creation-expected.txt +++ b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-title-creation-expected.txt
@@ -1,3 +1,3 @@ CONSOLE WARNING: Listener added for a synchronous 'DOMNodeInsertedIntoDocument' DOM Mutation Event. This event type is deprecated (https://w3c.github.io/uievents/#legacy-event-types) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead. CONSOLE WARNING: Listener added for a synchronous 'DOMSubtreeModified' DOM Mutation Event. This event type is deprecated (https://w3c.github.io/uievents/#legacy-event-types) and work is underway to remove it from this browser. Usage of this event listener will cause performance issues today, and represents a risk of future incompatibility. Consider using MutationObserver instead. -PASS. WebKit didn't crash. +PASS. WebKit (or Blink) didn't crash.
diff --git a/third_party/blink/web_tests/html/sections/remove-body-during-title-creation.html b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-title-creation.html similarity index 90% rename from third_party/blink/web_tests/html/sections/remove-body-during-title-creation.html rename to third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-title-creation.html index e91c0abbf..b87aeba 100644 --- a/third_party/blink/web_tests/html/sections/remove-body-during-title-creation.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/html/sections/remove-body-during-title-creation.html
@@ -13,7 +13,7 @@ document.lastChild.removeChild(document.lastChild.firstChild); GCController.collect(); setTimeout(function () { - document.body.innerHTML = "PASS. WebKit didn't crash." + document.body.innerHTML = "PASS. WebKit (or Blink) didn't crash." testRunner.notifyDone(); }, 0); }
diff --git a/third_party/blink/web_tests/media/video-controls-with-mutation-event-handler-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/media/video-controls-with-mutation-event-handler-expected.txt similarity index 100% rename from third_party/blink/web_tests/media/video-controls-with-mutation-event-handler-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/media/video-controls-with-mutation-event-handler-expected.txt
diff --git a/third_party/blink/web_tests/media/video-controls-with-mutation-event-handler.html b/third_party/blink/web_tests/dom/mutation-event-tests/media/video-controls-with-mutation-event-handler.html similarity index 85% rename from third_party/blink/web_tests/media/video-controls-with-mutation-event-handler.html rename to third_party/blink/web_tests/dom/mutation-event-tests/media/video-controls-with-mutation-event-handler.html index 5a1aebcd..77edfe24 100644 --- a/third_party/blink/web_tests/media/video-controls-with-mutation-event-handler.html +++ b/third_party/blink/web_tests/dom/mutation-event-tests/media/video-controls-with-mutation-event-handler.html
@@ -1,3 +1,4 @@ +<!DOCTYPE html> <html> <head> <title><video> controls with mutation event handler</title> @@ -16,11 +17,11 @@ document.body.addEventListener("DOMSubtreeModified", function () { }, false); var video = document.createElement('video'); - video.setAttribute('id', 'vid'); - video.setAttribute('width', '320'); - video.setAttribute('height', '240'); + video.setAttribute('id', 'vid'); + video.setAttribute('width', '320'); + video.setAttribute('height', '240'); video.setAttribute('autoplay', ''); - video.setAttribute('controls', ''); + video.setAttribute('controls', ''); var paragraph = document.createElement('p'); paragraph.appendChild(video); document.body.appendChild(paragraph);
diff --git a/third_party/blink/web_tests/svg/custom/tref-nested-events-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/tref-nested-events-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/svg/custom/tref-nested-events-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/tref-nested-events-crash-expected.txt
diff --git a/third_party/blink/web_tests/svg/custom/tref-nested-events-crash.svg b/third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/tref-nested-events-crash.svg similarity index 100% rename from third_party/blink/web_tests/svg/custom/tref-nested-events-crash.svg rename to third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/tref-nested-events-crash.svg
diff --git a/third_party/blink/web_tests/svg/custom/use-mutation-event-crash-expected.txt b/third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/use-mutation-event-crash-expected.txt similarity index 100% rename from third_party/blink/web_tests/svg/custom/use-mutation-event-crash-expected.txt rename to third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/use-mutation-event-crash-expected.txt
diff --git a/third_party/blink/web_tests/svg/custom/use-mutation-event-crash.svg b/third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/use-mutation-event-crash.svg similarity index 100% rename from third_party/blink/web_tests/svg/custom/use-mutation-event-crash.svg rename to third_party/blink/web_tests/dom/mutation-event-tests/svg/custom/use-mutation-event-crash.svg
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 9a28c8e..8e665a436 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -3061,6 +3061,15 @@ {} ] ], + "overlay": { + "overlay-popover-backdrop-crash.html": [ + "f59fc5db4ae3fbbd383a1a9a7dfccf9597229119", + [ + null, + {} + ] + ] + }, "position-absolute-in-inline-crash.html": [ "e7b2ef49c713d5ee081b7319d81c4c4b3ee15524", [ @@ -6844,6 +6853,15 @@ {} ] ] + }, + "webtransport": { + "bidirectional-cancel-crash.https.html": [ + "6919c90aa84d6ecb9d03bb373a6ee85946f909a5", + [ + null, + {} + ] + ] } }, "manual": { @@ -97932,6 +97950,19 @@ {} ] ], + "oklab-009.html": [ + "49bd916f5d7b5ceadb07ce1bdcde703887c67866", + [ + null, + [ + [ + "/css/css-color/greensquare-ref.html", + "==" + ] + ], + {} + ] + ], "oklch-001.html": [ "f32b7fe888b304576790175a0f7e6b5bbe45b354", [ @@ -98062,6 +98093,19 @@ {} ] ], + "oklch-011.html": [ + "6944867cd8d434eeebe30038cd6ececc26e38428", + [ + null, + [ + [ + "/css/css-color/greensquare-ref.html", + "==" + ] + ], + {} + ] + ], "opacity-overlapping-letters.html": [ "65ab3742de39205341e04b18001deea3f7be192d", [ @@ -136182,6 +136226,19 @@ ], {} ] + ], + "writing-directions-003.html": [ + "1df5512d19e89addfcd75abfd94c6e5a9bd0bcaf", + [ + null, + [ + [ + "/css/css-grid/subgrid/writing-directions-003-ref.html", + "==" + ] + ], + {} + ] ] }, "table-grid-item-dynamic-001.html": [ @@ -160711,6 +160768,47 @@ ] ] }, + "overlay": { + "overlay-transition-finished.html": [ + "bf0aefac3f3d26376980bdb48ad8058210d77898", + [ + null, + [ + [ + "/css/css-position/overlay/green-ref.html", + "==" + ] + ], + {} + ] + ], + "overlay-transition-in-rendering.html": [ + "c794ec23a2d9bf9b6a2e44d760fcaef0cc550466", + [ + null, + [ + [ + "/css/css-position/overlay/green-ref.html", + "==" + ] + ], + {} + ] + ], + "overlay-transition-out-rendering.html": [ + "9c658c574cd99a17a2ab9679e925d3438a80491d", + [ + null, + [ + [ + "/css/css-position/overlay/green-ref.html", + "==" + ] + ], + {} + ] + ] + }, "position-absolute-center-001.html": [ "13af3f0e9f7184155b7edf09fb7a7a5580238fb2", [ @@ -209793,19 +209891,6 @@ {} ] ], - "appearance-push-button-001.html": [ - "3aecbb079809bb0f1e8c2a0786dee51bc6eb61d4", - [ - null, - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], "appearance-radio-001.html": [ "5a64ba7b0132201d5928837847aee446149a5663", [ @@ -209845,32 +209930,6 @@ {} ] ], - "appearance-slider-horizontal-001.html": [ - "4d5b1a94fc9485b3aad8744d09dfe7d8c4ea12eb", - [ - null, - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], - "appearance-square-button-001.html": [ - "8f8c84355d22ab332695f5092321b4f5768db774", - [ - null, - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], "appearance-textarea-001.html": [ "5c55ff9fbf6fd993aaf51114c175414a9ec8fe0b", [ @@ -221680,19 +221739,6 @@ {} ] ], - "webkit-appearance-push-button-001.html": [ - "6f44498d4660f58e6df2b32efd218c729edc0fc8", - [ - null, - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], "webkit-appearance-radio-001.html": [ "52d9fb22ac144c2ba932e4a97bc65796760414b7", [ @@ -221719,32 +221765,6 @@ {} ] ], - "webkit-appearance-slider-horizontal-001.html": [ - "a9375b5088ca995c545fb441cccef281242836dd", - [ - null, - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], - "webkit-appearance-square-button-001.html": [ - "f486329943bfba60fdf69dba0ef0065876b3b361", - [ - null, - [ - [ - "/css/css-ui/appearance-auto-ref.html", - "==" - ] - ], - {} - ] - ], "webkit-appearance-textarea-001.html": [ "cf3a15f4db6c9745de687cb38f593132d5ddf2f8", [ @@ -247594,6 +247614,84 @@ {} ] ], + "has-style-sharing-001.html": [ + "bf45e98cf2d40700c40cacec84edfb26b6cdb55f", + [ + null, + [ + [ + "/css/selectors/has-style-sharing-001-ref.html", + "==" + ] + ], + {} + ] + ], + "has-style-sharing-002.html": [ + "630a136186af4472e3ace0b084bf8ccf05696ed1", + [ + null, + [ + [ + "/css/selectors/has-style-sharing-002-ref.html", + "==" + ] + ], + {} + ] + ], + "has-style-sharing-003.html": [ + "480a23e368219e69fde2434559fa194089702fa8", + [ + null, + [ + [ + "/css/selectors/has-style-sharing-003-ref.html", + "==" + ] + ], + {} + ] + ], + "has-style-sharing-004.html": [ + "c0879f70ec7644196bfb9f35e8cbfd1e97f96ec6", + [ + null, + [ + [ + "/css/selectors/has-style-sharing-004-ref.html", + "==" + ] + ], + {} + ] + ], + "has-style-sharing-005.html": [ + "d6b05fc33d8a7df0e77373818a24eda28747d169", + [ + null, + [ + [ + "/css/selectors/has-style-sharing-005-ref.html", + "==" + ] + ], + {} + ] + ], + "has-style-sharing-006.html": [ + "e0d824f359f91aec0d30049e4312d3accf7281f5", + [ + null, + [ + [ + "/css/selectors/has-style-sharing-006-ref.html", + "==" + ] + ], + {} + ] + ], "has-visited.html": [ "8fe322c8b1751b2f4232e9898fa71bab5e203cde", [ @@ -265359,6 +265457,19 @@ {} ] ], + "deferred-timeline-composited.html": [ + "239c0ca50a97458f01402a104c40a4c4a8c2254e", + [ + null, + [ + [ + "/scroll-animations/css/deferred-timeline-composited-ref.html", + "==" + ] + ], + {} + ] + ], "scroll-animation-initial-offset.html": [ "34ae52d47927ee73c9c41c6f608bcd988e8f0cd7", [ @@ -267923,6 +268034,19 @@ {} ] ], + "pattern-text-01.svg": [ + "16c053590d0df65c01f57e3b454793bc93fbbc0a", + [ + null, + [ + [ + "/svg/pservers/reftests/reference/green-100x100.svg", + "==" + ] + ], + {} + ] + ], "pattern-viewbox-01.svg": [ "618b8fc29e69d2624d5556d6bbcdba600ce21a4a", [ @@ -272753,11 +272877,11 @@ "support": { ".cache": { "gitignore2.json": [ - "f97753ff5adf75dc9a199e1de764ce2b28ee5b64", + "911860e774a696c5b4e2376c3f3b188e7322d27d", [] ], "mtime.json": [ - "5b73a84878c7f0baf3a055f0226903181e10249b", + "317054789f21d498c84804d07095674fb3e16abb", [] ] }, @@ -280414,6 +280538,10 @@ "2ea5cc8b91d349c40df1e8a0ee03f3b4c6a2557b", [] ], + "background-017.xht.ini": [ + "ed39d57638594a7a4fed13a96a669163201cbd61", + [] + ], "background-022.xht.ini": [ "b94a73473cf6103ff48b6df0eca630d413ca558c", [] @@ -280430,6 +280558,10 @@ "86cbebe62e06f8f90f2801d348af7f84ced12312", [] ], + "background-082.xht.ini": [ + "a49592a4199ba582664c9803b187b36d633d699a", + [] + ], "background-087-ref.xht": [ "8fc44ffe7d61e021f56ce409d34eb4de5c334b01", [] @@ -281626,6 +281758,10 @@ "ff381421b7ac5f70952f610b93d18561d81136d6", [] ], + "border-bottom-applies-to-005.xht.ini": [ + "19fe0b81a8fc18989c1ea68c74705c4ad9a45a87", + [] + ], "border-bottom-applies-to-012.xht.ini": [ "52428072b1e3e839af08903f4547ec32194272cb", [] @@ -281882,6 +282018,10 @@ "a7e37e77a62ab18c7c93537db0a065abca66c830", [] ], + "border-bottom-style-002.xht.ini": [ + "24fb108b67436f14457d35732c400336208b91e6", + [] + ], "border-bottom-style-005-ref.xht": [ "be3e33274f9b84abc9f3ec76f6aa01c4fc05492d", [] @@ -284358,6 +284498,10 @@ "7345888e9a1eadbb866c4f5f7d2669644ca8da62", [] ], + "block-formatting-contexts-015.xht.ini": [ + "fec1bd970d5f97b050f6886d7d734ce7239b7806", + [] + ], "block-formatting-contexts-016.xht.ini": [ "bbedc86d3b26278acf37d3f8f0b633024a329378", [] @@ -289191,6 +289335,14 @@ "e72d38c6c19e0a45470eed8e3487b70070a057dd", [] ], + "background-image-cors-no-reload-expected.txt": [ + "2d5eff8acf8f7529dd18edf68ca0fd09ddddae3f", + [] + ], + "background-image-cors-no-reload.html.ini": [ + "6c63e3e5552665fed877719d1376007d7cb7df13", + [] + ], "background-image-gradient-currentcolor-conic-repaint-ref.html": [ "32158493df0409621ee8150f517eeed6119f8ca7", [] @@ -292693,6 +292845,10 @@ "c71e428aa2a88250fa5a09304885143fe6b9ae29", [] ], + "oklab-009.html.ini": [ + "1c1ba09c195f4d348558e1c203fca4a42bde3853", + [] + ], "oklch-004-ref.html": [ "58117583ee0a2aca2477b210c49dc339fdbe51fa", [] @@ -292717,6 +292873,10 @@ "a818f6989e120bcd28c814dba6c99ac4e525b169", [] ], + "oklch-011.html.ini": [ + "fac99a3e6514a6f38e0453ed51db2179a6559cb4", + [] + ], "opacity-overlapping-letters-ref.html": [ "bab1f80f685f9e52ea74b8b98f5153dcd9516624", [] @@ -293200,7 +293360,7 @@ [] ], "at-supports-005.html.ini": [ - "efcb890e9201f1abf7b9d556ec684129f79f5bd4", + "287846ac096ab85c51c2fec6fa9b9fb2247ce55a", [] ], "at-supports-020.html.ini": [ @@ -308351,6 +308511,10 @@ "writing-directions-002-ref.html": [ "cd1ee527ab1053bc5aa4b3e10466b09cfaa605e0", [] + ], + "writing-directions-003-ref.html": [ + "b8038a2b5095cbbf03ff82c667b759587a3a6389", + [] ] }, "support": { @@ -311961,7 +312125,7 @@ [] ], "clip-path-svg-text-backdrop-filter.html.ini": [ - "3bb4375ab7230eb45c547d7e5932a55a4520e93d", + "48943d7cf253e606f09dc2b7a79bf1843e769cdc", [] ], "clip-path-viewBox-1a.html.ini": [ @@ -312839,7 +313003,7 @@ [] ], "mask-with-rotation.svg.ini": [ - "80078da1f57382345acc2fc5895e34549a1fa9ff", + "3ed7d130c6f001ef21942deada9111860f0ed157", [] ], "reference": { @@ -314164,7 +314328,7 @@ [] ], "inheritance-expected.txt": [ - "59864d0f4d185ece259879a299f597b80f9babdc", + "36a41fd8da12a14850dfea06725f33270003d160", [] ], "inheritance.html.ini": [ @@ -315260,6 +315424,10 @@ "vrl-in-multicol-ref.html": [ "0e22219eabdbb3cdd6e748834080da412c5e69a3", [] + ], + "vrl-rtl-ltr-in-multicol.tentative.html.ini": [ + "bf1c33193e1c2084a634dd6c2345c879229ea1de", + [] ] }, "vlr-in-multicols-ref.html": [ @@ -315271,6 +315439,12 @@ [] ] }, + "overlay": { + "green-ref.html": [ + "bef7405e96f8181f88fb073ebd212b4af6382e33", + [] + ] + }, "position-absolute-dynamic-auto-overflow.html.ini": [ "436ec4eb5f38fed87cb73779b707210f63f310cb", [] @@ -327300,7 +327474,7 @@ [] ], "preserve3d-and-flattening-z-order-003.html.ini": [ - "3d7677e07b4db7b35dd0fc2969edae2a8260ce55", + "a7f8e81851d827783b2e26e6484b419a5e998e91", [] ], "preserve3d-and-flattening-z-order-004.html.ini": [ @@ -329880,11 +330054,11 @@ [] ], "appearance-cssom-001.html.ini": [ - "facca9599699b8bab8be62f778240559ade7d5fe", + "5d82f992f7d1462cb9af8726890742a434742492", [] ], "appearance-cssom-001_include=Invalid-expected.txt": [ - "0dd655a576c1eba20a5ebe9595b9ef8375cd489f", + "b0dbe1dd60483f0851e62de94e6c12ac94914bfd", [] ], "appearance-listbox-001.html.ini": [ @@ -330065,7 +330239,7 @@ [] ], "kind-of-widget-fallback-color-input-border-inline-end-color-001.html.ini": [ - "b02f68d4a4d147629a7f94909d43932fc7210000", + "accb4a10d95e9bb8c42de3288cc5f50edc60c9be", [] ], "kind-of-widget-fallback-color-input-border-inline-end-style-001.html.ini": [ @@ -330172,6 +330346,10 @@ "7dcd817f746113233616f393724f4c05bbefd158", [] ], + "kind-of-widget-fallback-input-button-border-start-end-radius-001.html.ini": [ + "0d50a5dcf3c721d64b86d56bd46ebcdc101267ce", + [] + ], "kind-of-widget-fallback-input-button-border-top-color-001.html.ini": [ "2c2002c0f81608453c7ab1ac2b732569bbe56885", [] @@ -330180,6 +330358,10 @@ "d8d05f85cdcff1cf718a9af855602ffd89e8b878", [] ], + "kind-of-widget-fallback-input-button-border-top-right-radius-001.html.ini": [ + "39e270c12b5db31c7358bf0b4a3e597ea4caa453", + [] + ], "kind-of-widget-fallback-input-reset-background-clip-001.html.ini": [ "35fd610ca98a59ca67e85a4a229c2604a0ff47e9", [] @@ -330393,7 +330575,7 @@ [] ], "kind-of-widget-fallback-input-search-border-top-style-001.html.ini": [ - "7e1c4b8d58815db61b77c2274e8869dd9894acc5", + "3802eb169924b89b8c9c537d6969932572e87c64", [] ], "kind-of-widget-fallback-input-search-border-top-width-001.html.ini": [ @@ -330693,7 +330875,7 @@ [] ], "kind-of-widget-fallback-input-text-border-block-start-color-001.html.ini": [ - "fcde24444057c513f11d2b9040adb5b436eb4208", + "a3d5414a29380888ee4ee2aba913ac990ceff559", [] ], "kind-of-widget-fallback-input-text-border-block-start-width-001.html.ini": [ @@ -332867,10 +333049,6 @@ "57f9dc3d27514209c8a30a8b7f90737e56d201c9", [] ], - "round-mod-rem-computed-expected.txt": [ - "fafcc400116bb73dc26bb49277fcb318ebabcb6b", - [] - ], "round-mod-rem-computed.html.ini": [ "3ca3cdcfc4bf67cbf12f189df42b5440f9309fc3", [] @@ -337786,7 +337964,7 @@ [] ], "clip-under-filter-003.html.ini": [ - "769107653a340aac5a45d2ce31b4a5c52fbc238a", + "080f0b845f117b12572d33920006d541f648e81d", [] ], "css-backdrop-filters-animation-blur-ref.html": [ @@ -339363,6 +339541,30 @@ "aea038f638a1ffcac18ed7e52a128c0c6bea9f89", [] ], + "has-style-sharing-001-ref.html": [ + "6013cb47d3f4ed5c490bca27ee017aba0cf1afeb", + [] + ], + "has-style-sharing-002-ref.html": [ + "c916ab074f38d6a5e663a12d59889f48062e3c26", + [] + ], + "has-style-sharing-003-ref.html": [ + "36aae7a103ee8761c22f5d3121241218094cce71", + [] + ], + "has-style-sharing-004-ref.html": [ + "f710924e31429903092a062ff08dea68ae679d5c", + [] + ], + "has-style-sharing-005-ref.html": [ + "eb95d473735b91f486ab0483cd0c3f48fa4e7e23", + [] + ], + "has-style-sharing-006-ref.html": [ + "4c03f2150ad15fdf08b49a2dee138d25e6e91aa1", + [] + ], "has-visited-ref.html": [ "3f54e2e3914f62a81c3199bbe3d8c0339b9c2ba8", [] @@ -340580,7 +340782,7 @@ ], "admin": { "index.md": [ - "dd7dfe2e72ae3aa2284cea498c0e36bbd7ab16fb", + "f42d3075b6b7011ec3966ecb2b9cfd8ef54e5609", [] ], "pywebsocket3.rst": [ @@ -342428,7 +342630,19 @@ [] ], "exec-command-with-text-editor.tentative.html.ini": [ - "ac14c6d5ea62212c3497091f0116e02908a0fd5c", + "085e2f1aea3b872071c696a8b8b669cdc53cc60c", + [] + ], + "exec-command-with-text-editor.tentative_type=password-expected.txt": [ + "4b3e8a4cc6e48d7eafaed3f8003681ede1b7b8c1", + [] + ], + "exec-command-with-text-editor.tentative_type=text-expected.txt": [ + "39d9207db41bc0d5ea67a67a4ee2f207f100e4bc", + [] + ], + "exec-command-with-text-editor.tentative_type=textarea-expected.txt": [ + "dd163b27abc8b862fd634d8e153e749b95f2a0bf", [] ], "exec-command-without-editable-element.tentative-expected.txt": [ @@ -346982,6 +347196,18 @@ "1130f249e167d39118bfc9eb330b2690b2fa7cce", [] ], + "cors-preflight-star.any-expected.txt": [ + "bc35e3d30981dd8a121832c193ed6ee870d77242", + [] + ], + "cors-preflight-star.any.js.ini": [ + "2f946f0bee5e702184de1f6a3749193f23241220", + [] + ], + "cors-preflight-star.any.worker-expected.txt": [ + "bc35e3d30981dd8a121832c193ed6ee870d77242", + [] + ], "cors-preflight.any-expected.txt": [ "d82e2352d1c1a0fdea4530b98cbe1de96fd314b4", [] @@ -351955,7 +352181,7 @@ [] ], "rc-helper.js": [ - "53bcdccf7c65b0b33cd7150c20e461325a8b6a10", + "cb73f52e15b0c27e7f7dacb9415d158e14291af0", [] ], "service-worker.js": [ @@ -352079,7 +352305,7 @@ ], "event-order": { "before-load-hash-twice.html.ini": [ - "46f2992a1b006effd80a729210b14cf08351a570", + "e2d946699c8a541e0281e0fda0b5e902d8aca9e8", [] ], "before-load-hash.html.ini": [ @@ -354706,7 +354932,7 @@ [] ], "window-name.sub.html": [ - "55fb8ebbbc5957cbabf7ce57ba9c6e818cced034", + "5bb8ebda8f85134ac2dd02fc5862e49ec7c76b8d", [] ], "window-opener.html": [ @@ -356551,16 +356777,40 @@ "2c48d688b6af35ef3c65da7c8cda127b80716571", [] ], + "2d.drawImage.svg-expected.txt": [ + "26f3a1a58bdb336e60300e16b8c934e427a98a23", + [] + ], "2d.drawImage.svg.html.ini": [ - "c66b96999799d78e66aa016ffb9ce8fe3445a67e", + "6879b65b15252084319d837459c0e1ed5cfc4e95", + [] + ], + "2d.drawImage.svg.worker-expected.txt": [ + "26f3a1a58bdb336e60300e16b8c934e427a98a23", + [] + ], + "2d.drawImage.svg.worker.js.ini": [ + "ee8c386c0989ab55e3f16a96aba489a829ed46ee", [] ], "2d.drawImage.transform.html.ini": [ "1f76e3507603b3deff7a598af11fe90c7d0ff199", [] ], + "2d.drawImage.zerosource.image-expected.txt": [ + "e7b3db3703a70fa11a5bdc8470c09bd6c400ab8b", + [] + ], "2d.drawImage.zerosource.image.html.ini": [ - "3f7b04de87c75b45767acb4ad0485be0927ba887", + "ceda955c52ad8437fc4cbe09ea1734143401e04f", + [] + ], + "2d.drawImage.zerosource.image.worker-expected.txt": [ + "e7b3db3703a70fa11a5bdc8470c09bd6c400ab8b", + [] + ], + "2d.drawImage.zerosource.image.worker.js.ini": [ + "7c323703c036b60488463a2c5c9a9b3c1f71ca68", [] ] }, @@ -356815,7 +357065,7 @@ [] ], "offscreencanvas.resize.html.ini": [ - "9df7bd34aae6e86dbbf9a8143c7a88015108b4ec", + "72f96f300060025117f9e4736b029a077b040b92", [] ], "offscreencanvas.transfer.to.imagebitmap.html.ini": [ @@ -357135,7 +357385,7 @@ [] ], "gentestutilsunion.py": [ - "2ffd37461656bc76c49323bee38436d92fc935e1", + "cf154c41894bd9c0863ccf7d3619efc74e5e3871", [] ], "name2dir-canvas.yaml": [ @@ -357256,7 +357506,7 @@ [] ], "drawing-images-to-the-canvas.yaml": [ - "75eed14ee63c8452a26cbc780fd05e5e907325e5", + "91b92b0092fc9de2d6729215aa192aef6aca07dc", [] ], "drawing-rectangles-to-the-canvas.yaml": [ @@ -358573,10 +358823,6 @@ "33abadd83dd9187bfa5ecf811f9fef7058412780", [] ], - "reporting-from-rp-ro.https-expected.txt": [ - "ea3108eb21ec47915e61e5d4b61c42d46a37754a", - [] - ], "reporting-from-rp-ro.https.html.ini": [ "c970a3b97eebd268427840cd7b3679d9815f48bf", [] @@ -358585,10 +358831,6 @@ "07ecad96f2493c7ddc70cc5f37d242c07f0cabb1", [] ], - "reporting-from-rp.https-expected.txt": [ - "840f72a3863b12bd0de8ac511cb5b050d4cce94e", - [] - ], "reporting-from-rp.https.html.ini": [ "1cc83dc3424e9781a28baa74b0013d7458f588f2", [] @@ -358597,10 +358839,6 @@ "a61e2919c8acb6be886ef16e764f1ba5dcabe9bc", [] ], - "reporting-to-rp-ro.https-expected.txt": [ - "3a82b8669737ca324805706473699e07b64dd4ba", - [] - ], "reporting-to-rp-ro.https.html.headers": [ "16903320bb50789e0a64f9620540f1cc8c0902fd", [] @@ -358609,10 +358847,6 @@ "c2354d4a6ca86fce7b82a394968d0751c3fd7ba4", [] ], - "reporting-to-rp.https-expected.txt": [ - "8ce5ad9da721b9f02612bab1b10d4b46d0acd83c", - [] - ], "reporting-to-rp.https.html.headers": [ "16903320bb50789e0a64f9620540f1cc8c0902fd", [] @@ -376586,7 +376820,7 @@ [] ], "mediasource-worker-play-terminate-worker.html.ini": [ - "391c16b580089c638ce0ea12e9cb14812932d80d", + "3f7a607d963e809fca162c61222cd1cd6ada79ee", [] ], "mediasource-worker-play-terminate-worker.js": [ @@ -377203,19 +377437,19 @@ [] ], "MediaDevices-enumerateDevices-returned-objects.https-expected.txt": [ - "d7fe4a5aa6e7cf953f39c36d01c58996c5874877", + "746b4ef4dcf7700fd7912af927a4cb305f295af9", [] ], "MediaDevices-enumerateDevices-returned-objects.https.html.ini": [ - "75fbe7801d8c5ddf63bce002817edb769182dc51", + "72f20494200151ad66b80f6bd7edd2f5ab92a837", [] ], "MediaDevices-enumerateDevices.https-expected.txt": [ - "973e380f7808eec4d031e62130107ec97297c6f5", + "b68158e043a4de4541ff989a845a679c4f6fad93", [] ], "MediaDevices-enumerateDevices.https.html.ini": [ - "b6d4a0024e1d04e904c1a56c984c44198551f3b1", + "0f4bb7c8a184f6c78fce09a9040ab5a088461e16", [] ], "MediaStream-MediaElement-firstframe.https-expected.txt": [ @@ -380286,6 +380520,10 @@ "cf64bb9502d87da0d69f03d96bd5114940e81e06", [] ], + "pointerevent_click_is_a_pointerevent_mouse-expected.txt": [ + "db2190d9f626b7a23f998796782e144d155a8ec4", + [] + ], "pointerevent_click_is_a_pointerevent_multiple_clicks.html.ini": [ "ecc7c827fb43e013d1f31314a8718d84106dc34d", [] @@ -380783,7 +381021,7 @@ [] ], "modulepreload-as.html.ini": [ - "e4272ef63b2b3dee93fda20f5a7b9dd8dd79cd72", + "8f8232e0c21fecfcafa00148167f7aa12728acf1", [] ], "modulepreload-expected.txt": [ @@ -384175,6 +384413,10 @@ "7e375a1df7f063ba6cdbbdad92beb73915b84d6e", [] ], + "deferred-timeline-composited-ref.html": [ + "088e93750afb9b502ae4183632b4b3a739b2887f", + [] + ], "printing": { "animation-timeline-none-with-progress-print.tentative.html.ini": [ "ecc9c4b5c027440e44c0979588022fe02a2aa4dd", @@ -393303,7 +393545,7 @@ [] ], "request-video-frame-callback-webrtc.https.html.ini": [ - "75eae59b5318187f61a3a97544187f4336dbb788", + "20571581481f78b37829a43493535217a0100531", [] ] }, @@ -394073,7 +394315,7 @@ [] ], "accumulation-per-property-002-expected.txt": [ - "ecda7e6fc6202f856c4ad0775e669b70d3047d73", + "bbba6751c715f8f41c066be6d3981c6a8491da59", [] ], "accumulation-per-property-002.html.ini": [ @@ -394089,7 +394331,7 @@ [] ], "addition-per-property-002-expected.txt": [ - "22aa3ffd03550a9e20cb9d2a93a6912ac99effa9", + "818aa702ea7be9fac1fac33b6113378cd456202b", [] ], "addition-per-property-002.html.ini": [ @@ -394105,7 +394347,7 @@ [] ], "interpolation-per-property-002-expected.txt": [ - "aa63ca0c11bf00e8825031cf5a8c25702232b487", + "f24ec17dd9f48cfe65e029f2962a4943861d13a7", [] ], "interpolation-per-property-002.html.ini": [ @@ -394113,7 +394355,7 @@ [] ], "property-list.js": [ - "53ab3a7d87c3b0cd5cfa54fba4115de7d8d955ff", + "bb75ab5f7ad0e92c9cccb9baec16dc839e80a3b5", [] ], "property-types.js": [ @@ -395543,7 +395785,7 @@ [] ], "full-cycle-test.https.any.js.ini": [ - "36fa0f322f5301750fb242b83ffb54e2b2850c3c", + "5aa0dd339983f306f8a4233d32a3245a618350b1", [] ], "h264.annexb": [ @@ -395579,7 +395821,7 @@ [] ], "reconfiguring-encoder.https.any.js.ini": [ - "633ca1e5343ab0725ba9a6ce0bcdabe373947cba", + "1f7e751a15d59bc88db8a185ad895a758fceedce", [] ], "sfx-aac.mp4": [ @@ -397851,7 +398093,7 @@ [] ], "RTCRtpSynchronizationSource-helper.js": [ - "10cfd651554a259817cd34521ab44556063f4f44", + "c8a3e45aae9ff952215d68a4a2b5cfdfc6278e4f", [] ], "RTCRtpTransceiver-headerExtensionControl.html.ini": [ @@ -419129,7 +419371,7 @@ ] ], "enumerateDevices-with-selectAudioOutput.https.html": [ - "51da44286a760b1f6df84d7cfdb24f6dbdf6f6a9", + "c1a825592a6030fb76c7b5cbd765973ecb1eb49c", [ null, { @@ -422915,7 +423157,7 @@ ] ], "max-length-exceeded-name-unicode.https.window.js": [ - "23de63d293f667db98533ae8533ee3c5df57205f", + "3458c92b65efa8314a2af6ab00c7084d469a103b", [ "bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.window.html", { @@ -422967,7 +423209,7 @@ ] ], "max-length-exceeded-namePrefix-unicode.https.window.js": [ - "aa832b2e764d5f897cf5d6114efa6c62ce630993", + "b2e6668e4b98a9a0e8a23803327a890f86e593ca", [ "bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-namePrefix-unicode.https.window.html", { @@ -423019,7 +423261,7 @@ ] ], "max-length-name-unicode.https.window.js": [ - "1232a030e9d52435d0b96923484228b9a2fc4fcc", + "6a3cf5bead0eefd561064785f3289797cb0a01e3", [ "bluetooth/requestDevice/canonicalizeFilter/max-length-name-unicode.https.window.html", { @@ -423071,7 +423313,7 @@ ] ], "max-length-namePrefix-unicode.https.window.js": [ - "2932dc1cde5c9b78191f04da5787c4c3fbf67b7b", + "2061e9863b4026024a4170fb9794f42692cba0f7", [ "bluetooth/requestDevice/canonicalizeFilter/max-length-namePrefix-unicode.https.window.html", { @@ -441981,6 +442223,13 @@ {} ] ], + "background-image-cors-no-reload.html": [ + "964ca0919c9dfbcbce95c8eb1e4b7a239e429bfd", + [ + null, + {} + ] + ], "background-origin-001.html": [ "a951bdd370a0127270a873b3c9fb8f26755216cf", [ @@ -455058,7 +455307,7 @@ }, "css-overflow": { "inheritance.html": [ - "976406be413b9bdc8cef4acab0a0cd29df2dd43d", + "ffc6b2f881965883e74d53b49c2495b141724a06", [ null, {} @@ -455255,7 +455504,7 @@ ] ], "scrollbar-gutter-invalid.html": [ - "4f669225ee4e57e878d13c18b7f0a91d0468dd1d", + "e59790c32eb6767f3a2d9594434f7886f57a532b", [ null, {} @@ -455788,6 +456037,13 @@ {} ] ], + "overlay-transition.html": [ + "2d641c5466709626572072737461737128f39f61", + [ + null, + {} + ] + ], "overlay-valid.html": [ "8d808ac6dcf582628f782b2e228b261a654ba212", [ @@ -467973,7 +468229,7 @@ ] }, "appearance-cssom-001.html": [ - "36402da51cf27dcb515ccc805eda2088f85fbd12", + "895ed2437390df435743e9d79f4359f692ab74ee", [ "css/css-ui/appearance-cssom-001.html?exclude=Invalid", {} @@ -469067,7 +469323,7 @@ ] ], "round-mod-rem-computed.html": [ - "db01cd0e18c9989bc419206c17e50094eb9b4c64", + "2210f6e1fb57591974cb14cfdd1b10d6f5400068", [ null, {} @@ -474235,6 +474491,13 @@ {} ] ], + "defined-in-has.html": [ + "d691c4a53fd063e5e361cef9ae12536d32b78076", + [ + null, + {} + ] + ], "defined.html": [ "565ed552e1bf9bf56934a2fc397b0bd7769ec21d", [ @@ -480731,9 +480994,17 @@ ] ], "exec-command-with-text-editor.tentative.html": [ - "f2c1fce52222c2d683728f91425a746df25cdc3b", + "207e74aef2dd62ed5bf8eb6d975170d873dbed2d", [ - null, + "editing/other/exec-command-with-text-editor.tentative.html?type=password", + {} + ], + [ + "editing/other/exec-command-with-text-editor.tentative.html?type=text", + {} + ], + [ + "editing/other/exec-command-with-text-editor.tentative.html?type=textarea", {} ] ], @@ -502057,7 +502328,7 @@ ] ], "cors-preflight-star.any.js": [ - "e8cbc80b808adfde7e50bf4c9d46b06a4393b344", + "f9fb20469cffa3642f38afe4febb11c702e4a35b", [ "fetch/api/cors/cors-preflight-star.any.html", { @@ -521732,6 +522003,15 @@ } ] ], + "dangling-markup-window-name.tentative.html": [ + "1bc8bb9f7ff558f60bda1dbacda617e34dfe2d19", + [ + null, + { + "timeout": "long" + } + ] + ], "document-domain-nested-navigate.window.js": [ "f51eed5ca941f591536c70187e4201c464f02ab3", [ @@ -530583,14 +530863,14 @@ ] ], "2d.drawImage.svg.html": [ - "50aeabd286db470b6d3b696dea3f0bf51bc0e32d", + "cd293595fe8f4e714b4703ce394eeab184da5fce", [ null, {} ] ], "2d.drawImage.svg.worker.js": [ - "a15371db39dbd31554eb3fdda2554e09f489af04", + "8293e89f247af9fe093b88b29daa32fe4da8c778", [ "html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.html", {} @@ -530646,14 +530926,14 @@ ] ], "2d.drawImage.zerosource.image.html": [ - "4941d37347f4d48278dfc2cfde4aec417fdc45a6", + "5dfb2f3002c24b1710ba800652790a8171cdb852", [ null, {} ] ], "2d.drawImage.zerosource.image.worker.js": [ - "a3182c9b73f12b1ee5768ba89bddae6189052d36", + "467beb4d12fac2c3251efeeb197547b065a96d27", [ "html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.html", {} @@ -534865,7 +535145,7 @@ ] ], "offscreencanvas.resize.html": [ - "e259f79ca2819936e33bafe8d0beb6ce610325f4", + "3ff0eea153f6c3d9ed393fea24d0947b1f8fb53d", [ null, {} @@ -545089,7 +545369,7 @@ ] ], "reporting-from-rp-ro.https.html": [ - "b1da8cf77cefba3ab3ebaa5261dcc1c0b5583470", + "b89030f218ffeb79da7269f70a3432f79700e95a", [ null, { @@ -545098,7 +545378,7 @@ ] ], "reporting-from-rp.https.html": [ - "a8c11d7a4a89f6885e73422510c9046e9faab7a5", + "6b31f7e0098da78db34e91ba179ac1ef86e3035d", [ null, { @@ -545107,7 +545387,7 @@ ] ], "reporting-to-rp-ro.https.html": [ - "eb80842863425fd60d04206354e60942c59232e1", + "c47e59cd8f1aeac7ee6b1dbe2177595730148a38", [ null, { @@ -545116,7 +545396,7 @@ ] ], "reporting-to-rp.https.html": [ - "ad57afccf8fa4703434d39e070cce7744f65600d", + "ff60e8c5afda67ff3ca1573dab5405769b2b2cc3", [ null, { @@ -557810,7 +558090,7 @@ ] ], "dialog-overlay.html": [ - "a366f61a355e639d3a918fb981c49fa57264684b", + "9cd2426b8cbb6ef7c03b1def07d7ae5e871eb3e2", [ null, {} @@ -576177,7 +576457,7 @@ ] ], "MediaDevices-enumerateDevices-returned-objects.https.html": [ - "2b5687f672b9f6ec288be7003c361f96af83a10c", + "6e6dbaf3bba4fa84d2ebd2a74fc56034afe33070", [ null, { @@ -576186,7 +576466,7 @@ ] ], "MediaDevices-enumerateDevices.https.html": [ - "4971f4fc48280c42388d24085e35dde07e0d9b10", + "88c07048a1b48940787f8659dc32cb78bf041b86", [ null, { @@ -576202,7 +576482,7 @@ ] ], "MediaDevices-getUserMedia.https.html": [ - "96399c804fcf35e5a2f554eae6f2e2dbc2ad8db5", + "9376f528974a95ebf57e920d10678e182ac6582d", [ null, { @@ -576371,7 +576651,7 @@ ] ], "MediaStreamTrack-getSettings.https.html": [ - "c1d90a4f4831abb2a7045dc79c5b662164f2616b", + "1bda4c748ac5a0c0711cc231710c18ed5afa7c25", [ null, { @@ -585778,7 +586058,7 @@ ] ], "pointerevent_click_is_a_pointerevent.html": [ - "2571c9c9034200e03bf2ad904cd859da9ccf6ddf", + "36b80b66f57fef9dd7b007e3c20889eaf2ca224f", [ "pointerevents/pointerevent_click_is_a_pointerevent.html?mouse", { @@ -632225,14 +632505,14 @@ ] ], "coep.https.tentative.html": [ - "4029fc6f815eb911745d4c1a471352b6c0952e45", + "5e48cb73524aac8eed838b6ab8570fce0ee207ae", [ null, {} ] ], "corp.https.tentative.html": [ - "ce18544b0bd8eea578f19daf041e9d79a72fe1f7", + "3c46de6c76890aec078cb576e87d67006620631d", [ null, {} @@ -632246,14 +632526,14 @@ ] ], "csp-allowed.https.tentative.html": [ - "55498eaa4e50fdc0255463bb08ef5c3301958cbe", + "890a5ba5bc999d4bdcf631d1257ff160d6dd6503", [ null, {} ] ], "csp-blocked.https.tentative.html": [ - "6700533b58cad6e4c47f71bb7e13002dd4df8a8e", + "6e5e82d5399cf1e3b7f99743e188ec8fc8af6881", [ null, {} @@ -632365,7 +632645,7 @@ ] ], "resource-timing.https.tentative.html": [ - "a2fe38de0f6206683e45e7b4ab628cfd40ff7634", + "c486cf1711fcf203756a4afc9b73ec52b2a71da2", [ null, {} @@ -632379,7 +632659,7 @@ ] ], "service-worker-controlled.https.tentative.html": [ - "d5c2a06837163d3416a9c4f7fcd083b024b12fba", + "b2e9abe5be3491f3976db746a691bb4de43c017e", [ null, {} @@ -632399,13 +632679,6 @@ {} ] ], - "subframe-from-web-bundle.https.tentative.html": [ - "9e08ccdd29c43a3f466dac081514a6842c992ce5", - [ - null, - {} - ] - ], "subresource-load.https.tentative.sub.html": [ "10c207020c2e3de5d8aaf053617adaa3d42786f2", [ @@ -635194,21 +635467,21 @@ ] ], "convolver-response-1-chan.html": [ - "300b43622bd96c51cd3a93c9627e31af9d1e2e5f", + "e239a5e86f9797c1fdaf8dfdc705937ef45e8110", [ null, {} ] ], "convolver-response-2-chan.html": [ - "9baf5f9f8d2c5ebda9c297647212eecb6fe9aa25", + "a73eb3f8abb1c974366d5e528c3d30353443edc7", [ null, {} ] ], "convolver-response-4-chan.html": [ - "cf3986e8d04ca203de979174a3db2bc1998a4ce8", + "f188d87b71f4c5d134feebd10ba95ffe165debb1", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/audio-output/enumerateDevices-with-selectAudioOutput.https.html b/third_party/blink/web_tests/external/wpt/audio-output/enumerateDevices-with-selectAudioOutput.https.html index 51da442..c1a8255 100644 --- a/third_party/blink/web_tests/external/wpt/audio-output/enumerateDevices-with-selectAudioOutput.https.html +++ b/third_party/blink/web_tests/external/wpt/audio-output/enumerateDevices-with-selectAudioOutput.https.html
@@ -40,9 +40,9 @@ const outputDevices = devices.filter(info => info.kind == "audiooutput"); assert_equals(outputDevices.length, 1, "number of audiooutput devices."); assert_not_equals(selected, undefined); - const info = outputDevices[0]; - assert_equals(info.deviceId, selected.deviceId); - assert_equals(info.groupId, selected.groupId); - assert_equals(info.label, selected.label); + const [info] = outputDevices; + assert_equals(info.deviceId, selected.deviceId, "deviceId exposed"); + assert_equals(info.groupId, selected.groupId, "groupId exposed"); + assert_equals(info.label, selected.label, "label exposed"); }, "enumerateDevices() after selectAudioOutput()"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.window.js b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.window.js index 23de63d..3458c92b 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.window.js +++ b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-name-unicode.https.window.js
@@ -9,7 +9,7 @@ 'Failed to execute \'requestDevice\' on \'Bluetooth\': ' + 'A device name can\'t be longer than 248 bytes.', new TypeError()); -// \u2764's UTF-8 respresentation is 3 bytes long. +// \u2764's UTF-8 representation is 3 bytes long. // 83 chars * 3 bytes/char = 249 bytes const unicode_name = '\u2764'.repeat(83);
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-namePrefix-unicode.https.window.js b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-namePrefix-unicode.https.window.js index aa832b2e..b2e6668 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-namePrefix-unicode.https.window.js +++ b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-exceeded-namePrefix-unicode.https.window.js
@@ -9,7 +9,7 @@ 'Failed to execute \'requestDevice\' on \'Bluetooth\': ' + 'A device name can\'t be longer than 248 bytes.', new TypeError()); -// \u2764's UTF-8 respresentation is 3 bytes long. +// \u2764's UTF-8 representation is 3 bytes long. // 83 chars * 3 bytes/char = 249 bytes const unicode_name = '\u2764'.repeat(83);
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-name-unicode.https.window.js b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-name-unicode.https.window.js index 1232a030..6a3cf5be 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-name-unicode.https.window.js +++ b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-name-unicode.https.window.js
@@ -4,7 +4,7 @@ // META: script=/bluetooth/resources/bluetooth-fake-devices.js 'use strict'; const test_desc = 'A unicode device name of 248 bytes is valid.'; -// \u00A1's UTF-8 respresentation is 2 bytes long. +// \u00A1's UTF-8 representation is 2 bytes long. // 124 chars * 2 bytes/char = 248 bytes const DEVICE_NAME = '\u00A1'.repeat(124);
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-namePrefix-unicode.https.window.js b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-namePrefix-unicode.https.window.js index 2932dc1..2061e98 100644 --- a/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-namePrefix-unicode.https.window.js +++ b/third_party/blink/web_tests/external/wpt/bluetooth/requestDevice/canonicalizeFilter/max-length-namePrefix-unicode.https.window.js
@@ -4,7 +4,7 @@ // META: script=/bluetooth/resources/bluetooth-fake-devices.js 'use strict'; const test_desc = 'A unicode device namePrefix of 248 bytes is valid.'; -// \u00A1's UTF-8 respresentation is 2 bytes long. +// \u00A1's UTF-8 representation is 2 bytes long. // 124 chars * 2 bytes/char = 248 bytes const DEVICE_NAME = '\u00A1'.repeat(124);
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/backgrounds/background-017.xht.ini b/third_party/blink/web_tests/external/wpt/css/CSS2/backgrounds/background-017.xht.ini new file mode 100644 index 0000000..ed39d57 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/backgrounds/background-017.xht.ini
@@ -0,0 +1,3 @@ +[background-017.xht] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/backgrounds/background-082.xht.ini b/third_party/blink/web_tests/external/wpt/css/CSS2/backgrounds/background-082.xht.ini new file mode 100644 index 0000000..a49592a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/backgrounds/background-082.xht.ini
@@ -0,0 +1,3 @@ +[background-082.xht] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/borders/border-bottom-applies-to-005.xht.ini b/third_party/blink/web_tests/external/wpt/css/CSS2/borders/border-bottom-applies-to-005.xht.ini new file mode 100644 index 0000000..19fe0b8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/borders/border-bottom-applies-to-005.xht.ini
@@ -0,0 +1,3 @@ +[border-bottom-applies-to-005.xht] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/borders/border-bottom-style-002.xht.ini b/third_party/blink/web_tests/external/wpt/css/CSS2/borders/border-bottom-style-002.xht.ini new file mode 100644 index 0000000..24fb108b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/borders/border-bottom-style-002.xht.ini
@@ -0,0 +1,3 @@ +[border-bottom-style-002.xht] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini new file mode 100644 index 0000000..fec1bd9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/normal-flow/block-formatting-contexts-015.xht.ini
@@ -0,0 +1,3 @@ +[block-formatting-contexts-015.xht] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload-expected.txt new file mode 100644 index 0000000..2d5eff8a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL CORS image from variable doesn't cause re-downloads assert_equals: should be loaded (twice, once with anon cors mode once without) expected 2 but got 1 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload.html b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload.html new file mode 100644 index 0000000..964ca09 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload.html
@@ -0,0 +1,50 @@ +<!doctype html> +<meta charset="utf-8"> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<link rel="author" title="Mozilla" href="https://mozilla.org"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1832528"> +<link rel="help" href="https://drafts.csswg.org/css-backgrounds/"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<style> +:root { + --icon: url("/images/green.png?variable-cors-no-reload"); +} +.item::before, +.item::after { + display: block; + content: ""; + height: 1.25rem; + width: 1.25rem; + transform: rotate(180deg); + background: var(--icon) 50%/2rem 2rem; +} +.item::after { + background: blue; + mask: var(--icon); +} +.item.toggled::after, +.item.toggled::before { + color: blue; +} +</style> +<div class="item"></div> +<script> +let t = async_test("CORS image from variable doesn't cause re-downloads"); + +function getEntries() { + let url = new URL("/images/green.png?variable-cors-no-reload", location.href).href; + return performance.getEntriesByName(url); +} + +onload = t.step_func(function() { + let entries = getEntries(); + assert_equals(entries.length, 2, "should be loaded (twice, once with anon cors mode once without)"); + document.querySelector(".item").classList.toggle("toggled"); + // Assume that at least some of the time the load would complete under a second. + t.step_timeout(t.step_func_done(function() { + let entries_after = getEntries(); + assert_equals(entries_after.length, entries.length, "Shouldn't have caused re-downloads"); + }), 1000); +}); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload.html.ini b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload.html.ini new file mode 100644 index 0000000..6c63e3e55 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-backgrounds/background-image-cors-no-reload.html.ini
@@ -0,0 +1,3 @@ +[background-image-cors-no-reload.html] + [CORS image from variable doesn't cause re-downloads] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/oklab-009.html b/third_party/blink/web_tests/external/wpt/css/css-color/oklab-009.html new file mode 100644 index 0000000..49bd916f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/oklab-009.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Color 4: OKLab and OKLCH</title> +<link rel="author" title="James Stuckey Weber" href="mailto:james@jamessw.com"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#specifying-oklab-oklch"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#predefined-to-lab-oklab"> +<link rel="match" href="greensquare-ref.html"> +<meta name="assert" content="oklab() specifying a and b with percentages"> +<style> + .test { background-color: red; width: 12em; height: 12em; } + .test { background-color: oklab(51.975% -35.075% 26.92%); } /* green (sRGB #008000) converted to OKLab */ +</style> +<body> + <p>Test passes if you see a green square, and no red.</p> + <div class="test"></div> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/oklab-009.html.ini b/third_party/blink/web_tests/external/wpt/css/css-color/oklab-009.html.ini new file mode 100644 index 0000000..1c1ba09 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/oklab-009.html.ini
@@ -0,0 +1,2 @@ +[oklab-009.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/oklch-011.html b/third_party/blink/web_tests/external/wpt/css/css-color/oklch-011.html new file mode 100644 index 0000000..6944867 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/oklch-011.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Color 4: OKLab and OKLCH</title> +<link rel="author" title="James Stuckey Weber" href="mailto:james@jamessw.com"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#specifying-oklab-oklch"> +<link rel="help" href="https://drafts.csswg.org/css-color-4/#predefined-to-lab-oklab"> +<link rel="match" href="greensquare-ref.html"> +<meta name="assert" content="oklch() specifying C with percentage"> +<style> + .test { background-color: red; width: 12em; height: 12em; } + .test { background-color: oklch(51.975% 44.215% 142.495); } /* green (sRGB #008000) converted to OKLCH */ +</style> +<body> + <p>Test passes if you see a green square, and no red.</p> + <div class="test"></div> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/oklch-011.html.ini b/third_party/blink/web_tests/external/wpt/css/css-color/oklch-011.html.ini new file mode 100644 index 0000000..fac99a3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-color/oklch-011.html.ini
@@ -0,0 +1,2 @@ +[oklch-011.html] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini b/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini index efcb890..287846a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-conditional/at-supports-005.html.ini
@@ -1,5 +1,6 @@ [at-supports-005.html] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contribution-size-flex-tracks-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contribution-size-flex-tracks-001.html new file mode 100644 index 0000000..cc99f639 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/contribution-size-flex-tracks-001.html
@@ -0,0 +1,42 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Grid Test: Subgrid contribution size to flexible tracks</title> +<link rel="author" title="Ethan Jimenez" href="mailto:ethavar@microsoft.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-size-contribution"> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<style> +.grid { + background: red; + display: inline-grid; + grid-template: repeat(4, minmax(0, 1fr)) / repeat(10, minmax(0, 1fr)); +} +.subgrid { + width: 50px; + height: 50px; + background: green; + display: grid; + grid-row: 1 / -1; + grid-column: 1 / -1; + grid-template: subgrid / subgrid; +} +.item { + width: 10px; + height: 25px; +} +</style> +</head> +<body> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class="grid"> + <div class="subgrid"> + <div class="item"></div> + </div> +</div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-001.html index e2fe1a3..f43c6f7 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-001.html
@@ -8,7 +8,7 @@ <meta charset="utf-8"> <title>CSS Grid Test: Subgrid with no grid items accommodates border and padding</title> <link rel="author" title="Ethan Jimenez" href="mailto:ethavar@microsoft.com"> -<link rel="help" href="https://drafts.csswg.org/css-grid-2"> +<link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-edge-placeholders"> <link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> <style> .wrapper {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-002.html index a2c73b1..aa90595 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/subgrid-no-items-on-edges-002.html
@@ -8,7 +8,7 @@ <meta charset="utf-8"> <title>CSS Grid Test: Subgrid with no grid items accommodates gutter size and padding</title> <link rel="author" title="Ethan Jimenez" href="mailto:ethavar@microsoft.com"> -<link rel="help" href="https://drafts.csswg.org/css-grid-2"> +<link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-edge-placeholders"> <link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> <style> .wrapper {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/writing-directions-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/writing-directions-003-ref.html new file mode 100644 index 0000000..b8038a2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/writing-directions-003-ref.html
@@ -0,0 +1,60 @@ +<!DOCTYPE HTML> +<html><head> + <meta charset="utf-8"> + <title>Reference: out-of-flow subgridded items properly map repetitions</title> + <link rel="author" title="Kurt Catti-Schmidt" href="mailto:kschmi@microsoft.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2"> + <style> + +.grid { + display: grid; + grid-template: repeat(5, 10px) repeat(5, 10px) / repeat(5, 10px) repeat(5, 10px); + background: grey; + border: 1px solid; + width: 100px; + height: 100px; +} + +.grid-item { + width: 10px; + height: 10px; + background: orange; + border: 1px solid; +} + +.rtl { direction:rtl; } + +.ltr { direction:ltr; } + + </style> +</head> +<body> + +<div class="grid rtl"> + <div class="grid-item" style="grid-column: 10; grid-row: 10;"></div> + <div class="grid-item" style="grid-column: 9; grid-row: 9;"></div> + <div class="grid-item" style="grid-column: 8; grid-row: 8;"></div> + <div class="grid-item" style="grid-column: 7; grid-row: 7;"></div> + <div class="grid-item" style="grid-column: 6; grid-row: 6;"></div> + <div class="grid-item" style="grid-column: 5; grid-row: 5;"></div> + <div class="grid-item" style="grid-column: 4; grid-row: 4;"></div> + <div class="grid-item" style="grid-column: 3; grid-row: 3;"></div> + <div class="grid-item" style="grid-column: 2; grid-row: 2;"></div> + <div class="grid-item" style="grid-column: 1; grid-row: 1;"></div> +</div> + +<div class="grid ltr"> + <div class="grid-item" style="grid-column: 10; grid-row: 10;"></div> + <div class="grid-item" style="grid-column: 9; grid-row: 9;"></div> + <div class="grid-item" style="grid-column: 8; grid-row: 8;"></div> + <div class="grid-item" style="grid-column: 7; grid-row: 7;"></div> + <div class="grid-item" style="grid-column: 6; grid-row: 6;"></div> + <div class="grid-item" style="grid-column: 5; grid-row: 5;"></div> + <div class="grid-item" style="grid-column: 4; grid-row: 4;"></div> + <div class="grid-item" style="grid-column: 3; grid-row: 3;"></div> + <div class="grid-item" style="grid-column: 2; grid-row: 2;"></div> + <div class="grid-item" style="grid-column: 1; grid-row: 1;"></div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/writing-directions-003.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/writing-directions-003.html new file mode 100644 index 0000000..1df5512 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/writing-directions-003.html
@@ -0,0 +1,74 @@ +<!DOCTYPE HTML> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: out-of-flow subgridded items properly map repetitions</title> + <link rel="author" title="Kurt Catti-Schmidt" href="mailto:kschmi@microsoft.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2"> + <link rel="match" href="writing-directions-003-ref.html"> + <style> + +.grid { + display: grid; + grid-template: repeat(5, 10px) repeat(5, 10px) / repeat(5, 10px) repeat(5, 10px); + width: 100px; + height: 100px; + border: 1px solid; + background: grey; +} + +.subgrid { + position: relative; + display: grid; + grid-template: subgrid / subgrid; + grid-column: span 10; + grid-row: span 10; +} + +.grid-item { + width: 10px; + height: 10px; + background: orange; + border: 1px solid; + position: absolute; +} + +.rtl { direction:rtl; } + +.ltr { direction:ltr; } + + </style> +</head> +<body> + +<div class="grid"> + <div class="subgrid rtl"> + <div class="grid-item" style="grid-column: 10; grid-row: 10;"></div> + <div class="grid-item" style="grid-column: 9; grid-row: 9;"></div> + <div class="grid-item" style="grid-column: 8; grid-row: 8;"></div> + <div class="grid-item" style="grid-column: 7; grid-row: 7;"></div> + <div class="grid-item" style="grid-column: 6; grid-row: 6;"></div> + <div class="grid-item" style="grid-column: 5; grid-row: 5;"></div> + <div class="grid-item" style="grid-column: 4; grid-row: 4;"></div> + <div class="grid-item" style="grid-column: 3; grid-row: 3;"></div> + <div class="grid-item" style="grid-column: 2; grid-row: 2;"></div> + <div class="grid-item" style="grid-column: 1; grid-row: 1;"></div> + </div> +</div> + +<div class="grid rtl"> + <div class="subgrid ltr"> + <div class="grid-item" style="grid-column: 10; grid-row: 10;"></div> + <div class="grid-item" style="grid-column: 9; grid-row: 9;"></div> + <div class="grid-item" style="grid-column: 8; grid-row: 8;"></div> + <div class="grid-item" style="grid-column: 7; grid-row: 7;"></div> + <div class="grid-item" style="grid-column: 6; grid-row: 6;"></div> + <div class="grid-item" style="grid-column: 5; grid-row: 5;"></div> + <div class="grid-item" style="grid-column: 4; grid-row: 4;"></div> + <div class="grid-item" style="grid-column: 3; grid-row: 3;"></div> + <div class="grid-item" style="grid-column: 2; grid-row: 2;"></div> + <div class="grid-item" style="grid-column: 1; grid-row: 1;"></div> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-text-backdrop-filter.html.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-text-backdrop-filter.html.ini index 3bb4375..48943d7 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-text-backdrop-filter.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-masking/clip-path/clip-path-svg-text-backdrop-filter.html.ini
@@ -1,4 +1,5 @@ [clip-path-svg-text-backdrop-filter.html] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-with-rotation.svg.ini b/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-with-rotation.svg.ini index 80078da1..3ed7d13 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-with-rotation.svg.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-with-rotation.svg.ini
@@ -1,6 +1,7 @@ [mask-with-rotation.svg] expected: if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance-expected.txt index 59864d0f..36a41fd8 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance-expected.txt
@@ -15,5 +15,7 @@ PASS Property overflow-y does not inherit PASS Property text-overflow has initial value clip PASS Property text-overflow does not inherit +PASS Property scrollbar-gutter has initial value auto +PASS Property scrollbar-gutter does not inherit Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance.html index 976406b..ffc6b2f8 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance.html +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/inheritance.html
@@ -23,6 +23,7 @@ assert_not_inherited('overflow-x', 'visible', 'scroll'); assert_not_inherited('overflow-y', 'visible', 'scroll'); assert_not_inherited('text-overflow', 'clip', 'ellipsis'); +assert_not_inherited('scrollbar-gutter', 'auto', 'stable'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/parsing/scrollbar-gutter-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/parsing/scrollbar-gutter-invalid.html index 4f66922..e59790c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-overflow/parsing/scrollbar-gutter-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/parsing/scrollbar-gutter-invalid.html
@@ -34,4 +34,10 @@ test_invalid_value("scrollbar-gutter", "always force"); test_invalid_value("scrollbar-gutter", "always both force"); + test_invalid_value("scrollbar-gutter", "auto stable"); + test_invalid_value("scrollbar-gutter", "auto both-edges"); + test_invalid_value("scrollbar-gutter", "both-edges"); + test_invalid_value("scrollbar-gutter", "both-edges auto"); + test_invalid_value("scrollbar-gutter", "stable auto"); + </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/multicol/static-position/vrl-rtl-ltr-in-multicol.tentative.html.ini b/third_party/blink/web_tests/external/wpt/css/css-position/multicol/static-position/vrl-rtl-ltr-in-multicol.tentative.html.ini new file mode 100644 index 0000000..bf1c3319 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/multicol/static-position/vrl-rtl-ltr-in-multicol.tentative.html.ini
@@ -0,0 +1,3 @@ +[vrl-rtl-ltr-in-multicol.tentative.html] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-position/overlay/overlay-popover-backdrop-crash.html b/third_party/blink/web_tests/external/wpt/css/css-position/overlay/overlay-popover-backdrop-crash.html new file mode 100644 index 0000000..f59fc5d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-position/overlay/overlay-popover-backdrop-crash.html
@@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>CSS Position Test: Chrome crash for ::backdrop transitioning overlay for popover</title> +<link rel="help" href="https://crbug.com/1446479"> +<script src="/common/reftest-wait.js"></script> +<style> + #popover { + transition: overlay 60s step-end; + display: block; + } + #popover::backdrop { + background: rgba(0, 0, 0, 0.2); + } +</style> +<p>PASS if no crash.</p> +<div id="popover" popover></div> +<script> + requestAnimationFrame(() => { + popover.showPopover(); + requestAnimationFrame(() => { + popover.hidePopover(); + takeScreenshot(); + }); + }); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini b/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini index 3d7677e0..a7f8e818 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/preserve3d-and-flattening-z-order-003.html.ini
@@ -1,3 +1,4 @@ [preserve3d-and-flattening-z-order-003.html] expected: if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html index 36402da5..895ed243 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html
@@ -28,9 +28,6 @@ "radio", "searchfield", "textarea", - "slider-horizontal", - "push-button", - "square-button", ]; const invalid_values = [ "bogus-button", @@ -100,6 +97,7 @@ "progressbar-vertical", "progresschunk", "progresschunk-vertical", + "push-button", "radio-container", "radio-label", "radiomenuitem", @@ -130,6 +128,7 @@ "searchfield-results-decoration", "separator", "sheet", + "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", @@ -139,6 +138,7 @@ "spinner-textfield", "spinner-upbutton", "splitter", + "square-button", "statusbar", "statusbarpanel", "tab",
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html.ini index facca95..5d82f992 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001.html.ini
@@ -1,6 +1,24 @@ [appearance-cssom-001.html?include=Invalid] + [-webkit-appearance: push-button (invalid)] + expected: FAIL + + [-webkit-appearance: slider-horizontal (invalid)] + expected: FAIL + [-webkit-appearance: slider-vertical (invalid)] expected: FAIL + [-webkit-appearance: square-button (invalid)] + expected: FAIL + + [appearance: push-button (invalid)] + expected: FAIL + + [appearance: slider-horizontal (invalid)] + expected: FAIL + [appearance: slider-vertical (invalid)] expected: FAIL + + [appearance: square-button (invalid)] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt index 0dd655a..b0dbe1d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-cssom-001_include=Invalid-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 294 tests; 292 PASS, 2 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 300 tests; 292 PASS, 8 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS -webkit-appearance: bogus-button (invalid) PASS -webkit-appearance: attachment (invalid) PASS -webkit-appearance: button-bevel (invalid) @@ -67,6 +67,7 @@ PASS -webkit-appearance: progressbar-vertical (invalid) PASS -webkit-appearance: progresschunk (invalid) PASS -webkit-appearance: progresschunk-vertical (invalid) +FAIL -webkit-appearance: push-button (invalid) assert_in_array: style.WebkitAppearance (uppercase W) value "push-button" not in array [""] PASS -webkit-appearance: radio-container (invalid) PASS -webkit-appearance: radio-label (invalid) PASS -webkit-appearance: radiomenuitem (invalid) @@ -97,6 +98,7 @@ PASS -webkit-appearance: searchfield-results-decoration (invalid) PASS -webkit-appearance: separator (invalid) PASS -webkit-appearance: sheet (invalid) +FAIL -webkit-appearance: slider-horizontal (invalid) assert_in_array: style.WebkitAppearance (uppercase W) value "slider-horizontal" not in array [""] FAIL -webkit-appearance: slider-vertical (invalid) assert_in_array: style.WebkitAppearance (uppercase W) value "slider-vertical" not in array [""] PASS -webkit-appearance: sliderthumb-horizontal (invalid) PASS -webkit-appearance: sliderthumb-vertical (invalid) @@ -106,6 +108,7 @@ PASS -webkit-appearance: spinner-textfield (invalid) PASS -webkit-appearance: spinner-upbutton (invalid) PASS -webkit-appearance: splitter (invalid) +FAIL -webkit-appearance: square-button (invalid) assert_in_array: style.WebkitAppearance (uppercase W) value "square-button" not in array [""] PASS -webkit-appearance: statusbar (invalid) PASS -webkit-appearance: statusbarpanel (invalid) PASS -webkit-appearance: tab (invalid) @@ -214,6 +217,7 @@ PASS appearance: progressbar-vertical (invalid) PASS appearance: progresschunk (invalid) PASS appearance: progresschunk-vertical (invalid) +FAIL appearance: push-button (invalid) assert_in_array: style.appearance value "push-button" not in array [""] PASS appearance: radio-container (invalid) PASS appearance: radio-label (invalid) PASS appearance: radiomenuitem (invalid) @@ -244,6 +248,7 @@ PASS appearance: searchfield-results-decoration (invalid) PASS appearance: separator (invalid) PASS appearance: sheet (invalid) +FAIL appearance: slider-horizontal (invalid) assert_in_array: style.appearance value "slider-horizontal" not in array [""] FAIL appearance: slider-vertical (invalid) assert_in_array: style.appearance value "slider-vertical" not in array [""] PASS appearance: sliderthumb-horizontal (invalid) PASS appearance: sliderthumb-vertical (invalid) @@ -253,6 +258,7 @@ PASS appearance: spinner-textfield (invalid) PASS appearance: spinner-upbutton (invalid) PASS appearance: splitter (invalid) +FAIL appearance: square-button (invalid) assert_in_array: style.appearance value "square-button" not in array [""] PASS appearance: statusbar (invalid) PASS appearance: statusbarpanel (invalid) PASS appearance: tab (invalid)
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-push-button-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-push-button-001.html deleted file mode 100644 index 3aecbb0..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-push-button-001.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: appearance: push-button</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="push-button is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { appearance: none; appearance: push-button; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-slider-horizontal-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-slider-horizontal-001.html deleted file mode 100644 index 4d5b1a9..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-slider-horizontal-001.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: appearance: slider-horizontal</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="slider-horizontal is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { appearance: none; appearance: slider-horizontal; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-square-button-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-square-button-001.html deleted file mode 100644 index 8f8c843..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/appearance-square-button-001.html +++ /dev/null
@@ -1,28 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: appearance: square-button</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="square-button is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { appearance: none; appearance: square-button; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-inline-end-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-inline-end-color-001.html.ini index b02f68d4..accb4a1 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-inline-end-color-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-color-input-border-inline-end-color-001.html.ini
@@ -1,4 +1,5 @@ [kind-of-widget-fallback-color-input-border-inline-end-color-001.html] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL + if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-button-border-start-end-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-button-border-start-end-radius-001.html.ini new file mode 100644 index 0000000..0d50a5dcf --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-button-border-start-end-radius-001.html.ini
@@ -0,0 +1,3 @@ +[kind-of-widget-fallback-input-button-border-start-end-radius-001.html] + expected: + if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-button-border-top-right-radius-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-button-border-top-right-radius-001.html.ini new file mode 100644 index 0000000..39e270c1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-button-border-top-right-radius-001.html.ini
@@ -0,0 +1,3 @@ +[kind-of-widget-fallback-input-button-border-top-right-radius-001.html] + expected: + if (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-style-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-style-001.html.ini index 7e1c4b8..3802eb16 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-style-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-search-border-top-style-001.html.ini
@@ -1,3 +1,4 @@ [kind-of-widget-fallback-input-search-border-top-style-001.html] expected: if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "win") and (port == "win11"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-border-block-start-color-001.html.ini b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-border-block-start-color-001.html.ini index fcde244..a3d5414 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-border-block-start-color-001.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/css-ui/compute-kind-widget-generated/kind-of-widget-fallback-input-text-border-block-start-color-001.html.ini
@@ -1,3 +1,4 @@ [kind-of-widget-fallback-input-text-border-block-start-color-001.html] expected: + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL if (product == "content_shell") and (os == "linux"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-push-button-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-push-button-001.html deleted file mode 100644 index 6f44498d..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-push-button-001.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- DO NOT EDIT THIS FILE. -Edit the appearance-* file instead and then run: - ./tools/appearance-build-webkit-reftests.py ---> -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: -webkit-appearance: push-button</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="push-button is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { -webkit-appearance: none; -webkit-appearance: push-button; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-slider-horizontal-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-slider-horizontal-001.html deleted file mode 100644 index a9375b50..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-slider-horizontal-001.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- DO NOT EDIT THIS FILE. -Edit the appearance-* file instead and then run: - ./tools/appearance-build-webkit-reftests.py ---> -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: -webkit-appearance: slider-horizontal</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="slider-horizontal is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { -webkit-appearance: none; -webkit-appearance: slider-horizontal; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-square-button-001.html b/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-square-button-001.html deleted file mode 100644 index f486329..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-ui/webkit-appearance-square-button-001.html +++ /dev/null
@@ -1,32 +0,0 @@ -<!-- DO NOT EDIT THIS FILE. -Edit the appearance-* file instead and then run: - ./tools/appearance-build-webkit-reftests.py ---> -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Basic User Interface Test: -webkit-appearance: square-button</title> -<link rel="help" href="https://drafts.csswg.org/css-ui-4/#appearance-switching"> -<meta name="assert" content="square-button is an alias to auto."> -<link rel="match" href="appearance-auto-ref.html"> -<style> - #container { width: 500px; } - #container > * { -webkit-appearance: none; -webkit-appearance: square-button; } -</style> -<div id="container"> - <a>a</a> - <button>button</button> - <input type="text" value="input-text"> - <input type="search" value="input-search"> - <textarea>textarea</textarea> - <input type="button" value="input-button"> - <input type="submit" value="input-submit"> - <input type="reset" value="input-reset"> - <input type="range"> - <input type="checkbox"> - <input type="radio"> - <input type="color"> - <select><option>select</option></select> - <select multiple><option>select-multiple</option></select> - <meter value=0.5></meter> - <progress value=0.5></progress> -</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/clip-under-filter-003.html.ini b/third_party/blink/web_tests/external/wpt/css/filter-effects/clip-under-filter-003.html.ini index 76910765..080f0b8 100644 --- a/third_party/blink/web_tests/external/wpt/css/filter-effects/clip-under-filter-003.html.ini +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/clip-under-filter-003.html.ini
@@ -1,4 +1,5 @@ [clip-under-filter-003.html] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-001-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-001-ref.html new file mode 100644 index 0000000..6013cb4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-001-ref.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + padding: 1em; + margin: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; + background-color: pink; +} +</style> +<div style="background: green;"><span></span></div> +<div></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-001.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-001.html new file mode 100644 index 0000000..bf45e98 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-001.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<link rel="match" href="has-style-sharing-001-ref.html"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + padding: 1em; + margin: 1em; +} + +:has(> span) { + background: green; +} + +span { + display: inline-block; + width: 1em; + height: 1em; + background-color: pink; +} +</style> +<div><span></span></div> +<div></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-002-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-002-ref.html new file mode 100644 index 0000000..c916ab07 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-002-ref.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + padding: 1em; + margin: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; + background-color: pink; +} +</style> +<div></div> +<div style="background: green;"><span></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-002.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-002.html new file mode 100644 index 0000000..630a136 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-002.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<link rel="match" href="has-style-sharing-002-ref.html"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + padding: 1em; + margin: 1em; +} + +:has(> span) { + background: green; +} + +span { + display: inline-block; + width: 1em; + height: 1em; + background-color: pink; +} +</style> +<div></div> +<div><span></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-003-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-003-ref.html new file mode 100644 index 0000000..36aae7a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-003-ref.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +.has-b { + background: green; +} + +.b { + background: purple; +} +</style> + +<div><span class="has-b"></span><span class="a"></span></div> +<div><span class="b"></span><span></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-003.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-003.html new file mode 100644 index 0000000..480a23e36 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-003.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<link rel="match" href="has-style-sharing-003-ref.html"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +:has(> .a) .b { + background: green; +} + +.b { + background: purple; +} +</style> + +<div><span class="b"></span><span class="a"></span></div> +<div><span class="b"></span><span></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-004-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-004-ref.html new file mode 100644 index 0000000..f710924 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-004-ref.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +.has-b { + background: green; +} + +.b { + background: purple; +} +</style> + +<div><span class="b"></span><span></span></div> +<div><span class="has-b"></span><span class="a"></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-004.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-004.html new file mode 100644 index 0000000..c0879f7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-004.html
@@ -0,0 +1,30 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<link rel="match" href="has-style-sharing-004-ref.html"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +:has(> .a) .b { + background: green; +} + +.b { + background: purple; +} +</style> + +<div><span class="b"></span><span></span></div> +<div><span class="b"></span><span class="a"></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-005-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-005-ref.html new file mode 100644 index 0000000..eb95d473 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-005-ref.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +.has-c { + background: green; +} + +.c { + background: purple; +} +</style> +<div><span class="b"><span class="has-c"></span></span><span class="a"></span></div> +<div><span class="b"><span class="c"></span></span><span></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-005.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-005.html new file mode 100644 index 0000000..d6b05fc3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-005.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<link rel="match" href="has-style-sharing-005-ref.html"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +:has(> .a) .b .c { + background: green; +} + +.c { + background: purple; +} +</style> +<div><span class="b"><span class="c"></span></span><span class="a"></span></div> +<div><span class="b"><span class="c"></span></span><span></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-006-ref.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-006-ref.html new file mode 100644 index 0000000..4c03f21 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-006-ref.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +.has-c { + background: green; +} + +.c { + background: purple; +} +</style> +<div><span class="b"><span class="c"></span></span><span></span></div> +<div><span class="b"><span class="has-c"></span></span><span class="a"></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-006.html b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-006.html new file mode 100644 index 0000000..e0d824f3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/has-style-sharing-006.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<link rel="author" title="David Shin" href="mailto:dshin@mozilla.com"> +<link rel="help" href="https://drafts.csswg.org/selectors-4/#relational"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1793012"> +<link rel="match" href="has-style-sharing-006-ref.html"> +<meta name="assert" content="Ensure that style sharing optimizations do not interfere with :has() selector matching."> +<style> +div { + background: blue; + margin: 1em; + padding: 1em; +} + +span { + display: inline-block; + width: 1em; + height: 1em; +} + +:has(> .a) .b .c { + background: green; +} + +.c { + background: purple; +} +</style> +<div><span class="b"><span class="c"></span></span><span></span></div> +<div><span class="b"><span class="c"></span></span><span class="a"></span></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/defined-in-has.html b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/defined-in-has.html new file mode 100644 index 0000000..d691c4a5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/selectors/invalidation/defined-in-has.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<title>:has() invalidation with :defined pseudo-class</title> +<link rel="author" title="Tim Nguyen" href="https://github.com/nt1m"> +<link rel="help" href="https://drafts.csswg.org/selectors/#relational"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/semantics-other.html#selector-defined"> +<style> + #subject { + background-color: red; + width: 100px; + height: 100px; + } + #subject:has(:defined) { + background-color: green; + } +</style> +<body> + Test :defined pseudo-class invalidation with :has() + <div id="subject"> + <my-element></my-element> + </div> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script> + const GREEN = "rgb(0, 128, 0)"; + const RED = "rgb(255, 0, 0)"; + + function assert_matches_defined(defined) { + assert_equals(getComputedStyle(subject).backgroundColor, defined ? GREEN : RED); + } + + test(() => { + assert_matches_defined(false); + customElements.define("my-element", class MyElement extends HTMLElement { }); + assert_matches_defined(true); + }, "Test :has() invalidation with :defined pseudo-class"); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/docs/admin/index.md b/third_party/blink/web_tests/external/wpt/docs/admin/index.md index dd7dfe2..f42d3075 100644 --- a/third_party/blink/web_tests/external/wpt/docs/admin/index.md +++ b/third_party/blink/web_tests/external/wpt/docs/admin/index.md
@@ -79,12 +79,10 @@ - smcgruer@google.com - boaz@bocoup.com - mike@bocoup.com - - simon@bocoup.com - [GitHub](https://github.com/): @wpt-pr-bot account - smcgruer@google.com - boaz@bocoup.com - mike@bocoup.com - - simon@bocoup.com ## Emergency playbook
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html index f2c1fce52..207e74a 100644 --- a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html +++ b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html
@@ -1,6 +1,9 @@ <!doctype html> <meta charset=utf-8> <title>Test that execCommand with <input> or <textarea></title> +<meta name="variant" content="?type=text"> +<meta name="variant" content="?type=textarea"> +<meta name="variant" content="?type=password"> <script src=/resources/testharness.js></script> <script src=/resources/testharnessreport.js></script> <div id="container"></div> @@ -8,6 +11,7 @@ "use strict"; setup({explicit_done: true}); +const testingType = new URLSearchParams(document.location.search).get("type"); /** * This test checks whether document.execCommand() does something expected or @@ -17,21 +21,28 @@ */ function runTests() { let container = document.getElementById("container"); - container.innerHTML = "Here <b>is</b> Text: <input id=\"target\">"; - runTest(document.getElementById("target"), "In <input>"); - container.innerHTML = "Here <b>is</b> Text: <textarea id=\"target\"></textarea>"; - runTest(document.getElementById("target"), "In <textarea>"); - container.setAttribute("contenteditable", "true"); - container.innerHTML = "Here <b>is</b> Text: <input id=\"target\">"; - runTest(document.getElementById("target"), "In <input> in contenteditable"); - container.innerHTML = "Here <b>is</b> Text: <textarea id=\"target\"></textarea>"; - runTest(document.getElementById("target"), "In <textarea> in contenteditable"); - + switch (testingType) { + case "text": + case "password": + container.innerHTML = `Here <b>is</b> Text: <input id="target" type="${testingType}">`; + runTest(document.getElementById("target"), `In <input type="${testingType}">`); + container.setAttribute("contenteditable", "true"); + container.innerHTML = `Here <b>is</b> Text: <input id="target" type="${testingType}">`; + runTest(document.getElementById("target"), `In <input type="${testingType}"> in contenteditable`); + break; + case "textarea": + container.innerHTML = "Here <b>is</b> Text: <textarea id=\"target\"></textarea>"; + runTest(document.getElementById("target"), "In <textarea>"); + container.setAttribute("contenteditable", "true"); + container.innerHTML = "Here <b>is</b> Text: <textarea id=\"target\"></textarea>"; + runTest(document.getElementById("target"), "In <textarea> in contenteditable"); + break; + } done(); } function runTest(aTarget, aDescription) { - const kIsTextArea = aTarget.tagName === "TEXTAREA"; + const kIsTextArea = testingType == "textarea"; const kTests = [ /** * command: command name of execCommand().
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html.ini b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html.ini index ac14c6d..085e2f1 100644 --- a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html.ini +++ b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative.html.ini
@@ -1,228 +1,446 @@ -[exec-command-with-text-editor.tentative.html] - [In <input> in contenteditable, execCommand("copy", false, null), a[bc\]d): The command should be enabled] +[exec-command-with-text-editor.tentative.html?type=password] + [In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc\]d): The command should be enabled] + expected: FAIL + + [In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc\]d): execCommand() should return true] expected: if product == "chrome": FAIL - [In <input> in contenteditable, execCommand("copy", false, null), a[bc\]d): execCommand() should return true] - expected: - if product == "chrome": FAIL - - [In <input> in contenteditable, execCommand("copy", false, null), abc[\]d): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[\]d): execCommand() should return false] expected: if product == "chrome": PASS FAIL - [In <input> in contenteditable, execCommand("cut", false, null), a[b\]c): <input>.value should be "a[\]c"] + [In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b\]c): <input>.value should be "a[\]c"] + expected: FAIL + + [In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b\]c): The command should be enabled] + expected: FAIL + + [In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b\]c): execCommand() should return true] expected: if product == "chrome": FAIL - [In <input> in contenteditable, execCommand("cut", false, null), a[b\]c): The command should be enabled] - expected: - if product == "chrome": FAIL + [In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b\]c): input.inputType should be deleteByCut] + expected: FAIL - [In <input> in contenteditable, execCommand("cut", false, null), a[b\]c): execCommand() should return true] - expected: - if product == "chrome": FAIL + [In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b\]c): input.target should be [object HTMLInputElement\]] + expected: FAIL - [In <input> in contenteditable, execCommand("cut", false, null), a[b\]c): input.inputType should be deleteByCut] - expected: - if product == "chrome": FAIL - - [In <input> in contenteditable, execCommand("cut", false, null), a[b\]c): input.target should be [object HTMLInputElement\]] - expected: - if product == "chrome": FAIL - - [In <input> in contenteditable, execCommand("cut", false, null), ab[\]c): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[\]c): execCommand() should return false] expected: if product == "chrome": PASS FAIL - [In <input> in contenteditable, execCommand("insertlinebreak", false, null), a[b\]c): The command should not be enabled] + [In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b\]c): The command should not be enabled] expected: FAIL - [In <input> in contenteditable, execCommand("insertlinebreak", false, null), a[b\]c): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b\]c): execCommand() should return false] expected: FAIL - [In <input> in contenteditable, execCommand("insertparagraph", false, null), a[b\]c): The command should not be enabled] + [In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b\]c): The command should not be enabled] expected: FAIL - [In <input> in contenteditable, execCommand("insertparagraph", false, null), a[b\]c): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b\]c): execCommand() should return false] expected: FAIL - [In <input> in contenteditable, execCommand("paste", false, null), a[\]c): <input>.value should be "a[bc\]c"] + [In <input type="password"> in contenteditable, execCommand("paste", false, null), a[\]c): <input>.value should be "a[bc\]c"] expected: FAIL - [In <input> in contenteditable, execCommand("paste", false, null), a[\]c): The command should be enabled] + [In <input type="password"> in contenteditable, execCommand("paste", false, null), a[\]c): The command should be enabled] expected: if product == "chrome": FAIL - [In <input> in contenteditable, execCommand("paste", false, null), a[\]c): The command should be supported] + [In <input type="password"> in contenteditable, execCommand("paste", false, null), a[\]c): The command should be supported] expected: if product == "chrome": FAIL - [In <input> in contenteditable, execCommand("redo", false, null), [a\]bc): The command should not be enabled] + [In <input type="password"> in contenteditable, execCommand("redo", false, null), [a\]bc): The command should not be enabled] expected: FAIL - [In <input> in contenteditable, execCommand("redo", false, null), [a\]bc): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("redo", false, null), [a\]bc): execCommand() should return false] expected: FAIL - [In <input> in contenteditable, execCommand("redo", false, null), [a\]bc): input.inputType should be undefined] + [In <input type="password"> in contenteditable, execCommand("redo", false, null), [a\]bc): input.inputType should be undefined] expected: FAIL - [In <input> in contenteditable, execCommand("redo", false, null), [a\]bc): input.target should be undefined] + [In <input type="password"> in contenteditable, execCommand("redo", false, null), [a\]bc): input.target should be undefined] expected: FAIL - [In <input> in contenteditable, execCommand("redo", false, null), a[b\]c): The command should be enabled] + [In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b\]c): The command should be enabled] expected: FAIL - [In <input> in contenteditable, execCommand("removeformat", false, null), a[b\]c): The command should not be enabled] + [In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b\]c): The command should not be enabled] expected: FAIL - [In <input> in contenteditable, execCommand("removeformat", false, null), a[b\]c): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b\]c): execCommand() should return false] expected: FAIL - [In <input> in contenteditable, execCommand("undo", false, null), [a\]bc): The command should not be enabled] + [In <input type="password"> in contenteditable, execCommand("undo", false, null), [a\]bc): The command should not be enabled] expected: FAIL - [In <input> in contenteditable, execCommand("undo", false, null), [a\]bc): execCommand() should return false] + [In <input type="password"> in contenteditable, execCommand("undo", false, null), [a\]bc): execCommand() should return false] expected: FAIL - [In <input> in contenteditable, execCommand("undo", false, null), [a\]bc): input.inputType should be undefined] + [In <input type="password"> in contenteditable, execCommand("undo", false, null), [a\]bc): input.inputType should be undefined] expected: FAIL - [In <input> in contenteditable, execCommand("undo", false, null), [a\]bc): input.target should be undefined] + [In <input type="password"> in contenteditable, execCommand("undo", false, null), [a\]bc): input.target should be undefined] expected: FAIL - [In <input>, execCommand("copy", false, null), a[bc\]d): The command should be enabled] + [In <input type="password">, execCommand("copy", false, null), a[bc\]d): The command should be enabled] + expected: FAIL + + [In <input type="password">, execCommand("copy", false, null), a[bc\]d): execCommand() should return true] expected: if product == "chrome": FAIL - [In <input>, execCommand("copy", false, null), a[bc\]d): execCommand() should return true] - expected: - if product == "chrome": FAIL - - [In <input>, execCommand("copy", false, null), abc[\]d): execCommand() should return false] + [In <input type="password">, execCommand("copy", false, null), abc[\]d): execCommand() should return false] expected: if product == "chrome": PASS FAIL - [In <input>, execCommand("cut", false, null), a[b\]c): <input>.value should be "a[\]c"] + [In <input type="password">, execCommand("cut", false, null), a[b\]c): <input>.value should be "a[\]c"] + expected: FAIL + + [In <input type="password">, execCommand("cut", false, null), a[b\]c): The command should be enabled] + expected: FAIL + + [In <input type="password">, execCommand("cut", false, null), a[b\]c): execCommand() should return true] expected: if product == "chrome": FAIL - [In <input>, execCommand("cut", false, null), a[b\]c): The command should be enabled] - expected: - if product == "chrome": FAIL + [In <input type="password">, execCommand("cut", false, null), a[b\]c): input.inputType should be deleteByCut] + expected: FAIL - [In <input>, execCommand("cut", false, null), a[b\]c): execCommand() should return true] - expected: - if product == "chrome": FAIL + [In <input type="password">, execCommand("cut", false, null), a[b\]c): input.target should be [object HTMLInputElement\]] + expected: FAIL - [In <input>, execCommand("cut", false, null), a[b\]c): input.inputType should be deleteByCut] - expected: - if product == "chrome": FAIL - - [In <input>, execCommand("cut", false, null), a[b\]c): input.target should be [object HTMLInputElement\]] - expected: - if product == "chrome": FAIL - - [In <input>, execCommand("cut", false, null), ab[\]c): execCommand() should return false] + [In <input type="password">, execCommand("cut", false, null), ab[\]c): execCommand() should return false] expected: if product == "chrome": PASS FAIL - [In <input>, execCommand("defaultParagraphSeparator", false, div), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("defaultParagraphSeparator", false, div), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("defaultParagraphSeparator", false, p), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> does not have focus] + [In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> does not have focus] expected: FAIL - [In <input>, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> has focus] + [In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> has focus] expected: FAIL - [In <input>, execCommand("defaultParagraphSeparator", false, p), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("insertlinebreak", false, null), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("insertlinebreak", false, null), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("insertlinebreak", false, null), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("insertlinebreak", false, null), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("insertparagraph", false, null), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("insertparagraph", false, null), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("insertparagraph", false, null), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("insertparagraph", false, null), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("paste", false, null), a[\]c): <input>.value should be "a[bc\]c"] + [In <input type="password">, execCommand("paste", false, null), a[\]c): <input>.value should be "a[bc\]c"] expected: FAIL - [In <input>, execCommand("paste", false, null), a[\]c): The command should be enabled] + [In <input type="password">, execCommand("paste", false, null), a[\]c): The command should be enabled] expected: if product == "chrome": FAIL - [In <input>, execCommand("paste", false, null), a[\]c): The command should be supported] + [In <input type="password">, execCommand("paste", false, null), a[\]c): The command should be supported] expected: if product == "chrome": FAIL - [In <input>, execCommand("redo", false, null), [a\]bc): The command should not be enabled] + [In <input type="password">, execCommand("redo", false, null), [a\]bc): The command should not be enabled] expected: FAIL - [In <input>, execCommand("redo", false, null), [a\]bc): execCommand() should return false] + [In <input type="password">, execCommand("redo", false, null), [a\]bc): execCommand() should return false] expected: FAIL - [In <input>, execCommand("redo", false, null), [a\]bc): input.inputType should be undefined] + [In <input type="password">, execCommand("redo", false, null), [a\]bc): input.inputType should be undefined] expected: FAIL - [In <input>, execCommand("redo", false, null), [a\]bc): input.target should be undefined] + [In <input type="password">, execCommand("redo", false, null), [a\]bc): input.target should be undefined] expected: FAIL - [In <input>, execCommand("redo", false, null), a[b\]c): The command should be enabled] + [In <input type="password">, execCommand("redo", false, null), a[b\]c): The command should be enabled] expected: FAIL - [In <input>, execCommand("removeformat", false, null), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("removeformat", false, null), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("removeformat", false, null), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("removeformat", false, null), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("styleWithCSS", false, false), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("styleWithCSS", false, false), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("styleWithCSS", false, false), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("styleWithCSS", false, false), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("styleWithCSS", false, true), a[b\]c): The command should not be enabled] + [In <input type="password">, execCommand("styleWithCSS", false, true), a[b\]c): The command should not be enabled] expected: FAIL - [In <input>, execCommand("styleWithCSS", false, true), a[b\]c): execCommand() should return false] + [In <input type="password">, execCommand("styleWithCSS", false, true), a[b\]c): execCommand() should return false] expected: FAIL - [In <input>, execCommand("styleWithCSS", false, true), a[b\]c): styleWithCSS state should be false when <input> does not have focus] + [In <input type="password">, execCommand("styleWithCSS", false, true), a[b\]c): styleWithCSS state should be false when <input> does not have focus] expected: FAIL - [In <input>, execCommand("styleWithCSS", false, true), a[b\]c): styleWithCSS state should be false when <input> has focus] + [In <input type="password">, execCommand("styleWithCSS", false, true), a[b\]c): styleWithCSS state should be false when <input> has focus] expected: FAIL - [In <input>, execCommand("undo", false, null), [a\]bc): The command should not be enabled] + [In <input type="password">, execCommand("undo", false, null), [a\]bc): The command should not be enabled] expected: FAIL - [In <input>, execCommand("undo", false, null), [a\]bc): execCommand() should return false] + [In <input type="password">, execCommand("undo", false, null), [a\]bc): execCommand() should return false] expected: FAIL - [In <input>, execCommand("undo", false, null), [a\]bc): input.inputType should be undefined] + [In <input type="password">, execCommand("undo", false, null), [a\]bc): input.inputType should be undefined] expected: FAIL - [In <input>, execCommand("undo", false, null), [a\]bc): input.target should be undefined] + [In <input type="password">, execCommand("undo", false, null), [a\]bc): input.target should be undefined] expected: FAIL + +[exec-command-with-text-editor.tentative.html?type=text] + [In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc\]d): The command should be enabled] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc\]d): execCommand() should return true] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[\]d): execCommand() should return false] + expected: + if product == "chrome": PASS + FAIL + + [In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b\]c): <input>.value should be "a[\]c"] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b\]c): The command should be enabled] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b\]c): execCommand() should return true] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b\]c): input.inputType should be deleteByCut] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b\]c): input.target should be [object HTMLInputElement\]] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[\]c): execCommand() should return false] + expected: + if product == "chrome": PASS + FAIL + + [In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("paste", false, null), a[\]c): <input>.value should be "a[bc\]c"] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("paste", false, null), a[\]c): The command should be enabled] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("paste", false, null), a[\]c): The command should be supported] + expected: + if product == "chrome": FAIL + + [In <input type="text"> in contenteditable, execCommand("redo", false, null), [a\]bc): The command should not be enabled] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("redo", false, null), [a\]bc): execCommand() should return false] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("redo", false, null), [a\]bc): input.inputType should be undefined] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("redo", false, null), [a\]bc): input.target should be undefined] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b\]c): The command should be enabled] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("undo", false, null), [a\]bc): The command should not be enabled] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("undo", false, null), [a\]bc): execCommand() should return false] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("undo", false, null), [a\]bc): input.inputType should be undefined] + expected: FAIL + + [In <input type="text"> in contenteditable, execCommand("undo", false, null), [a\]bc): input.target should be undefined] + expected: FAIL + + [In <input type="text">, execCommand("copy", false, null), a[bc\]d): The command should be enabled] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("copy", false, null), a[bc\]d): execCommand() should return true] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("copy", false, null), abc[\]d): execCommand() should return false] + expected: + if product == "chrome": PASS + FAIL + + [In <input type="text">, execCommand("cut", false, null), a[b\]c): <input>.value should be "a[\]c"] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("cut", false, null), a[b\]c): The command should be enabled] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("cut", false, null), a[b\]c): execCommand() should return true] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("cut", false, null), a[b\]c): input.inputType should be deleteByCut] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("cut", false, null), a[b\]c): input.target should be [object HTMLInputElement\]] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("cut", false, null), ab[\]c): execCommand() should return false] + expected: + if product == "chrome": PASS + FAIL + + [In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> does not have focus] + expected: FAIL + + [In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): defaultParagraphSeparator value should be "p" when <input> has focus] + expected: FAIL + + [In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("insertlinebreak", false, null), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("insertlinebreak", false, null), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("insertparagraph", false, null), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("insertparagraph", false, null), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("paste", false, null), a[\]c): <input>.value should be "a[bc\]c"] + expected: FAIL + + [In <input type="text">, execCommand("paste", false, null), a[\]c): The command should be enabled] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("paste", false, null), a[\]c): The command should be supported] + expected: + if product == "chrome": FAIL + + [In <input type="text">, execCommand("redo", false, null), [a\]bc): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("redo", false, null), [a\]bc): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("redo", false, null), [a\]bc): input.inputType should be undefined] + expected: FAIL + + [In <input type="text">, execCommand("redo", false, null), [a\]bc): input.target should be undefined] + expected: FAIL + + [In <input type="text">, execCommand("redo", false, null), a[b\]c): The command should be enabled] + expected: FAIL + + [In <input type="text">, execCommand("removeformat", false, null), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("removeformat", false, null), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("styleWithCSS", false, false), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("styleWithCSS", false, false), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("styleWithCSS", false, true), a[b\]c): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("styleWithCSS", false, true), a[b\]c): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("styleWithCSS", false, true), a[b\]c): styleWithCSS state should be false when <input> does not have focus] + expected: FAIL + + [In <input type="text">, execCommand("styleWithCSS", false, true), a[b\]c): styleWithCSS state should be false when <input> has focus] + expected: FAIL + + [In <input type="text">, execCommand("undo", false, null), [a\]bc): The command should not be enabled] + expected: FAIL + + [In <input type="text">, execCommand("undo", false, null), [a\]bc): execCommand() should return false] + expected: FAIL + + [In <input type="text">, execCommand("undo", false, null), [a\]bc): input.inputType should be undefined] + expected: FAIL + + [In <input type="text">, execCommand("undo", false, null), [a\]bc): input.target should be undefined] + expected: FAIL + + +[exec-command-with-text-editor.tentative.html?type=textarea] [In <textarea> in contenteditable, execCommand("copy", false, null), a[bc\]d): The command should be enabled] expected: if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=password-expected.txt b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=password-expected.txt new file mode 100644 index 0000000..4b3e8a4cc --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=password-expected.txt
@@ -0,0 +1,780 @@ +This is a testharness.js-based test. +Found 776 tests; 718 PASS, 58 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS In <input type="password">, execCommand("getHTML", false, null), a[b]c): The command should not be supported +PASS In <input type="password">, execCommand("getHTML", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("bold", false, bold), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("italic", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("underline", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("superscript", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): The command should be supported +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): The command should not be enabled +FAIL In <input type="password">, execCommand("cut", false, null), ab[]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c" +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("cut", false, null), ab[]c): input.target should be undefined +PASS In <input type="password">, execCommand("cut", false, null), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("cut", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <input type="password">, execCommand("cut", false, null), a[b]c): execCommand() should return true +FAIL In <input type="password">, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c" assert_equals: expected "a[]c" but got "a[b]c" +PASS In <input type="password">, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined +FAIL In <input type="password">, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut assert_equals: expected (string) "deleteByCut" but got (undefined) undefined +FAIL In <input type="password">, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement] assert_equals: expected (object) Element node <input id="target" type="password"></input> but got (undefined) undefined +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): The command should be supported +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): The command should not be enabled +FAIL In <input type="password">, execCommand("copy", false, null), abc[]d): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d" +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): input.inputType should be undefined +PASS In <input type="password">, execCommand("copy", false, null), abc[]d): input.target should be undefined +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): The command should be supported +FAIL In <input type="password">, execCommand("copy", false, null), a[bc]d): The command should be enabled assert_equals: expected true but got false +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): execCommand() should return true +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d" +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined +PASS In <input type="password">, execCommand("copy", false, null), a[bc]d): input.target should be undefined +PASS In <input type="password">, execCommand("paste", false, null), a[]c): The command should be supported +PASS In <input type="password">, execCommand("paste", false, null), a[]c): The command should be enabled +PASS In <input type="password">, execCommand("paste", false, null), a[]c): execCommand() should return true +FAIL In <input type="password">, execCommand("paste", false, null), a[]c): <input>.value should be "a[bc]c" assert_equals: expected "a[bc]c" but got "a[]c" +PASS In <input type="password">, execCommand("paste", false, null), a[]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("paste", false, null), a[]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("paste", false, null), a[]c): input.inputType should be insertFromPaste +PASS In <input type="password">, execCommand("paste", false, null), a[]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): The command should be supported +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): The command should be enabled +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): execCommand() should return true +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c" +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward +PASS In <input type="password">, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): The command should be enabled +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward +PASS In <input type="password">, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): The command should be supported +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c" +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward +PASS In <input type="password">, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): The command should be enabled +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]" +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("selectall", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("undo", false, null), [a]bc): The command should be supported +FAIL In <input type="password">, execCommand("undo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("undo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="password">, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="password">, execCommand("undo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyUndo" +FAIL In <input type="password">, execCommand("undo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input> +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): The command should be enabled +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo +PASS In <input type="password">, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("redo", false, null), [a]bc): The command should be supported +FAIL In <input type="password">, execCommand("redo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("redo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="password">, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="password">, execCommand("redo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyRedo" +FAIL In <input type="password">, execCommand("redo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input> +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("redo", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo +PASS In <input type="password">, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("indent", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("outdent", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="password">, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="password">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c" +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText +PASS In <input type="password">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c" +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText +PASS In <input type="password">, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("justifyright", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("removeformat", false, null), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("removeformat", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("removeformat", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("removeformat", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("unlink", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): The command should be supported +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): execCommand() should return false +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("formatblock", false, div), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("heading", false, h1), a[b]c): The command should not be supported +PASS In <input type="password">, execCommand("heading", false, h1), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined +FAIL In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> has focus assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> does not have focus assert_equals: expected false but got true +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus +PASS In <input type="password">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus +PASS In <input type="password">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported +PASS In <input type="password">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported +PASS In <input type="password">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined +FAIL In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus assert_equals: expected "div" but got "p" +FAIL In <input type="password">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus assert_equals: expected "div" but got "p" +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported +FAIL In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus +PASS In <input type="password">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus +PASS In <input type="password"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported +PASS In <input type="password"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled +FAIL In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c" +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true +FAIL In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c" assert_equals: expected "a[]c" but got "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined +FAIL In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut assert_equals: expected (string) "deleteByCut" but got (undefined) undefined +FAIL In <input type="password"> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement] assert_equals: expected (object) Element node <input id="target" type="password"></input> but got (undefined) undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled +FAIL In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d" +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled assert_equals: expected true but got false +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d" +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): execCommand() should return true +FAIL In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): <input>.value should be "a[bc]c" assert_equals: expected "a[bc]c" but got "a[]c" +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): input.inputType should be insertFromPaste +PASS In <input type="password"> in contenteditable, execCommand("paste", false, null), a[]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c" +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward +PASS In <input type="password"> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c" +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward +PASS In <input type="password"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]" +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyUndo" +FAIL In <input type="password"> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input> +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo +PASS In <input type="password"> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyRedo" +FAIL In <input type="password"> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="password"></input> +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo +PASS In <input type="password"> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="password"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="password"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c" +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText +PASS In <input type="password"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c" +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText +PASS In <input type="password"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported +FAIL In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported +PASS In <input type="password"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> has focus +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> does not have focus +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus +PASS In <input type="password"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus +PASS In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported +PASS In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported +PASS In <input type="password"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus +PASS In <input type="password"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=text-expected.txt b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=text-expected.txt new file mode 100644 index 0000000..39d9207d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=text-expected.txt
@@ -0,0 +1,780 @@ +This is a testharness.js-based test. +Found 776 tests; 728 PASS, 48 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS In <input type="text">, execCommand("getHTML", false, null), a[b]c): The command should not be supported +PASS In <input type="text">, execCommand("getHTML", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("bold", false, bold), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("italic", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("underline", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("superscript", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): The command should be supported +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): The command should not be enabled +FAIL In <input type="text">, execCommand("cut", false, null), ab[]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c" +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("cut", false, null), ab[]c): input.target should be undefined +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut +PASS In <input type="text">, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): The command should be supported +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): The command should not be enabled +FAIL In <input type="text">, execCommand("copy", false, null), abc[]d): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d" +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): input.inputType should be undefined +PASS In <input type="text">, execCommand("copy", false, null), abc[]d): input.target should be undefined +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): The command should be supported +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): The command should be enabled +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): execCommand() should return true +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d" +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined +PASS In <input type="text">, execCommand("copy", false, null), a[bc]d): input.target should be undefined +PASS In <input type="text">, execCommand("paste", false, null), a[]c): The command should be supported +PASS In <input type="text">, execCommand("paste", false, null), a[]c): The command should be enabled +PASS In <input type="text">, execCommand("paste", false, null), a[]c): execCommand() should return true +FAIL In <input type="text">, execCommand("paste", false, null), a[]c): <input>.value should be "a[bc]c" assert_equals: expected "a[bc]c" but got "abc[]c" +PASS In <input type="text">, execCommand("paste", false, null), a[]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("paste", false, null), a[]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("paste", false, null), a[]c): input.inputType should be insertFromPaste +PASS In <input type="text">, execCommand("paste", false, null), a[]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): The command should be supported +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): The command should be enabled +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): execCommand() should return true +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c" +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward +PASS In <input type="text">, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward +PASS In <input type="text">, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): The command should be supported +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c" +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward +PASS In <input type="text">, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]" +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("selectall", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("undo", false, null), [a]bc): The command should be supported +FAIL In <input type="text">, execCommand("undo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("undo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="text">, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="text">, execCommand("undo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyUndo" +FAIL In <input type="text">, execCommand("undo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input> +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo +PASS In <input type="text">, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("redo", false, null), [a]bc): The command should be supported +FAIL In <input type="text">, execCommand("redo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("redo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="text">, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="text">, execCommand("redo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyRedo" +FAIL In <input type="text">, execCommand("redo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input> +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("redo", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo +PASS In <input type="text">, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("indent", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("outdent", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="text">, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="text">, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c" +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText +PASS In <input type="text">, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c" +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText +PASS In <input type="text">, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("justifyright", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("removeformat", false, null), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("removeformat", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("removeformat", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("removeformat", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("unlink", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): The command should be supported +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): execCommand() should return false +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("formatblock", false, div), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("heading", false, h1), a[b]c): The command should not be supported +PASS In <input type="text">, execCommand("heading", false, h1), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined +FAIL In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> has focus assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <input> does not have focus assert_equals: expected false but got true +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus +PASS In <input type="text">, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus +PASS In <input type="text">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported +PASS In <input type="text">, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported +PASS In <input type="text">, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined +FAIL In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus assert_equals: expected "div" but got "p" +FAIL In <input type="text">, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus assert_equals: expected "div" but got "p" +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported +FAIL In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus +PASS In <input type="text">, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus +PASS In <input type="text"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported +PASS In <input type="text"> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled +FAIL In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): <input>.value should be "ab[]c" +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut +PASS In <input type="text"> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled +FAIL In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): <input>.value should be "abc[]d" +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): <input>.value should be "a[bc]d" +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): execCommand() should return true +FAIL In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): <input>.value should be "a[bc]c" assert_equals: expected "a[bc]c" but got "abc[]c" +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): input.inputType should be insertFromPaste +PASS In <input type="text"> in contenteditable, execCommand("paste", false, null), a[]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): <input>.value should be "a[]c" +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward +PASS In <input type="text"> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <input>.value should be "a[]c" +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward +PASS In <input type="text"> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): <input>.value should be "[abc]" +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported +FAIL In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyUndo" +FAIL In <input type="text"> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input> +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo +PASS In <input type="text"> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported +FAIL In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): <input>.value should be "[a]bc" +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyRedo" +FAIL In <input type="text"> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <input id="target" type="text"></input> +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported +FAIL In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): <input>.value should be "a[]c" +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo +PASS In <input type="text"> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="text"> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported +PASS In <input type="text"> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <input>.value should be "ainserted[]c" +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText +PASS In <input type="text"> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <input>.value should be "a**inserted**[]c" +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText +PASS In <input type="text"> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLInputElement] +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported +FAIL In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported +FAIL In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported +FAIL In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported +PASS In <input type="text"> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> has focus +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <input> does not have focus +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> has focus +PASS In <input type="text"> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <input> does not have focus +PASS In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported +PASS In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported +PASS In <input type="text"> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> has focus +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <input> does not have focus +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <input>.value should be "a[b]c" +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> has focus +PASS In <input type="text"> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <input> does not have focus +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=textarea-expected.txt b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=textarea-expected.txt new file mode 100644 index 0000000..dd163b2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/editing/other/exec-command-with-text-editor.tentative_type=textarea-expected.txt
@@ -0,0 +1,784 @@ +This is a testharness.js-based test. +Found 776 tests; 734 PASS, 42 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS In <textarea>, execCommand("getHTML", false, null), a[b]c): The command should not be supported +PASS In <textarea>, execCommand("getHTML", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): The command should be supported +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("bold", false, bold), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("italic", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("italic", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("italic", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("italic", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("italic", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("italic", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("underline", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("underline", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("underline", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("underline", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("underline", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("underline", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("superscript", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("cut", false, null), ab[]c): The command should be supported +PASS In <textarea>, execCommand("cut", false, null), ab[]c): The command should not be enabled +FAIL In <textarea>, execCommand("cut", false, null), ab[]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("cut", false, null), ab[]c): <textarea>.value should be "ab[]c" +PASS In <textarea>, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("cut", false, null), ab[]c): input.inputType should be undefined +PASS In <textarea>, execCommand("cut", false, null), ab[]c): input.target should be undefined +PASS In <textarea>, execCommand("cut", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("cut", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("cut", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("cut", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea>, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut +PASS In <textarea>, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("copy", false, null), abc[]d): The command should be supported +PASS In <textarea>, execCommand("copy", false, null), abc[]d): The command should not be enabled +FAIL In <textarea>, execCommand("copy", false, null), abc[]d): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("copy", false, null), abc[]d): <textarea>.value should be "abc[]d" +PASS In <textarea>, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined +PASS In <textarea>, execCommand("copy", false, null), abc[]d): input.inputType should be undefined +PASS In <textarea>, execCommand("copy", false, null), abc[]d): input.target should be undefined +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): The command should be supported +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): The command should be enabled +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): execCommand() should return true +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): <textarea>.value should be "a[bc]d" +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined +PASS In <textarea>, execCommand("copy", false, null), a[bc]d): input.target should be undefined +PASS In <textarea>, execCommand("paste", false, null), a[]c): The command should be supported +PASS In <textarea>, execCommand("paste", false, null), a[]c): The command should be enabled +PASS In <textarea>, execCommand("paste", false, null), a[]c): execCommand() should return true +FAIL In <textarea>, execCommand("paste", false, null), a[]c): <textarea>.value should be "a[bc]c" assert_equals: expected "a[bc]c" but got "abc[]c" +PASS In <textarea>, execCommand("paste", false, null), a[]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("paste", false, null), a[]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("paste", false, null), a[]c): input.inputType should be insertFromPaste +PASS In <textarea>, execCommand("paste", false, null), a[]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("delete", false, null), ab[]c): The command should be supported +PASS In <textarea>, execCommand("delete", false, null), ab[]c): The command should be enabled +PASS In <textarea>, execCommand("delete", false, null), ab[]c): execCommand() should return true +PASS In <textarea>, execCommand("delete", false, null), ab[]c): <textarea>.value should be "a[]c" +PASS In <textarea>, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward +PASS In <textarea>, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("delete", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("delete", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("delete", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("delete", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea>, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward +PASS In <textarea>, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward +PASS In <textarea>, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): The command should be supported +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): <textarea>.value should be "a[]c" +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward +PASS In <textarea>, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): <textarea>.value should be "[abc]" +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("selectall", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("undo", false, null), [a]bc): The command should be supported +FAIL In <textarea>, execCommand("undo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("undo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("undo", false, null), [a]bc): <textarea>.value should be "[a]bc" +PASS In <textarea>, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <textarea>, execCommand("undo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyUndo" +FAIL In <textarea>, execCommand("undo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea> +PASS In <textarea>, execCommand("undo", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("undo", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("undo", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("undo", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo +PASS In <textarea>, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("redo", false, null), [a]bc): The command should be supported +FAIL In <textarea>, execCommand("redo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("redo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("redo", false, null), [a]bc): <textarea>.value should be "[a]bc" +PASS In <textarea>, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <textarea>, execCommand("redo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyRedo" +FAIL In <textarea>, execCommand("redo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea> +PASS In <textarea>, execCommand("redo", false, null), a[b]c): The command should be supported +FAIL In <textarea>, execCommand("redo", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <textarea>, execCommand("redo", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("redo", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea>, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo +PASS In <textarea>, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("indent", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("indent", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("indent", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("indent", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("indent", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("indent", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("outdent", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): The command should be supported +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): The command should be supported +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): The command should be supported +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported +PASS In <textarea>, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported +PASS In <textarea>, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): The command should be supported +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <textarea>.value should be "ainserted[]c" +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined +FAIL In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText assert_equals: expected "insertText" but got "" +PASS In <textarea>, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): <textarea>.value should be "a**inserted**[]c" +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText +PASS In <textarea>, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("justifyright", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("removeformat", false, null), a[b]c): The command should be supported +FAIL In <textarea>, execCommand("removeformat", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("removeformat", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("removeformat", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("removeformat", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("unlink", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): <textarea>.value should be "a +[]c" +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be insertParagraph +PASS In <textarea>, execCommand("insertparagraph", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): The command should be enabled +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return true +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): <textarea>.value should be "a +[]c" +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be insertLineBreak +PASS In <textarea>, execCommand("insertlinebreak", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): The command should be supported +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): execCommand() should return false +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("formatblock", false, div), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("heading", false, h1), a[b]c): The command should not be supported +PASS In <textarea>, execCommand("heading", false, h1), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported +FAIL In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined +FAIL In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <textarea> has focus assert_equals: expected false but got true +FAIL In <textarea>, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be false when <textarea> does not have focus assert_equals: expected false but got true +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported +FAIL In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> has focus +PASS In <textarea>, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> does not have focus +PASS In <textarea>, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported +PASS In <textarea>, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported +PASS In <textarea>, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported +FAIL In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined +FAIL In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> has focus assert_equals: expected "div" but got "p" +FAIL In <textarea>, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> does not have focus assert_equals: expected "div" but got "p" +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported +FAIL In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> has focus +PASS In <textarea>, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> does not have focus +PASS In <textarea> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be supported +PASS In <textarea> in contenteditable, execCommand("getHTML", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("bold", false, bold), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("italic", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("underline", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("strikethrough", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("superscript", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): The command should not be enabled +FAIL In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): <textarea>.value should be "ab[]c" +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), ab[]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): input.inputType should be deleteByCut +PASS In <textarea> in contenteditable, execCommand("cut", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): The command should be supported +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): The command should not be enabled +FAIL In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): <textarea>.value should be "abc[]d" +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), abc[]d): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be supported +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): <textarea>.value should be "a[bc]d" +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("copy", false, null), a[bc]d): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): execCommand() should return true +FAIL In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): <textarea>.value should be "a[bc]c" assert_equals: expected "a[bc]c" but got "abc[]c" +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): input.inputType should be insertFromPaste +PASS In <textarea> in contenteditable, execCommand("paste", false, null), a[]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): <textarea>.value should be "a[]c" +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): input.inputType should be deleteContentBackward +PASS In <textarea> in contenteditable, execCommand("delete", false, null), ab[]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): input.inputType should be deleteContentBackward +PASS In <textarea> in contenteditable, execCommand("delete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.inputType should be deleteContentForward +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be supported +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): <textarea>.value should be "a[]c" +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.inputType should be deleteContentForward +PASS In <textarea> in contenteditable, execCommand("forwarddelete", false, null), a[]bc): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): <textarea>.value should be "[abc]" +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("selectall", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): The command should be supported +FAIL In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): <textarea>.value should be "[a]bc" +PASS In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyUndo" +FAIL In <textarea> in contenteditable, execCommand("undo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea> +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): input.inputType should be historyUndo +PASS In <textarea> in contenteditable, execCommand("undo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): The command should be supported +FAIL In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): <textarea>.value should be "[a]bc" +PASS In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): beforeinput.target should be undefined +FAIL In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): input.inputType should be undefined assert_equals: expected (undefined) undefined but got (string) "historyRedo" +FAIL In <textarea> in contenteditable, execCommand("redo", false, null), [a]bc): input.target should be undefined assert_equals: expected (undefined) undefined but got (object) Element node <textarea id="target"></textarea> +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be supported +FAIL In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): The command should be enabled assert_equals: expected true but got false +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): <textarea>.value should be "a[]c" +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): input.inputType should be historyRedo +PASS In <textarea> in contenteditable, execCommand("redo", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("indent", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("outdent", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("backcolor", false, #000000), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("forecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("hilitecolor", false, #000000), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("fontname", false, DummyFont), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("fontsize", false, 5), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be supported +PASS In <textarea> in contenteditable, execCommand("increasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be supported +PASS In <textarea> in contenteditable, execCommand("decreasefontsize", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("inserthorizontalrule", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("createlink", false, foo.html), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertimage", false, no-image.png), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): <textarea>.value should be "ainserted[]c" +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): beforeinput.target should be undefined +FAIL In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.inputType should be insertText assert_equals: expected "insertText" but got "" +PASS In <textarea> in contenteditable, execCommand("inserthtml", false, <b>inserted</b>), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): <textarea>.value should be "a**inserted**[]c" +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.inputType should be insertText +PASS In <textarea> in contenteditable, execCommand("inserttext", false, **inserted**), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyleft", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyright", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifycenter", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("justifyfull", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should be supported +FAIL In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): The command should not be enabled assert_equals: expected false but got true +FAIL In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): execCommand() should return false assert_equals: expected false but got true +PASS In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("removeformat", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("unlink", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertunorderedlist", false, null), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): <textarea>.value should be "a +[]c" +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.inputType should be insertParagraph +PASS In <textarea> in contenteditable, execCommand("insertparagraph", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): <textarea>.value should be "a +[]c" +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.inputType should be insertLineBreak +PASS In <textarea> in contenteditable, execCommand("insertlinebreak", false, null), a[b]c): input.target should be [object HTMLTextAreaElement] +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): execCommand() should return false +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("formatblock", false, div), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be supported +PASS In <textarea> in contenteditable, execCommand("heading", false, h1), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <textarea> has focus +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, true), a[b]c): styleWithCSS state should be true when <textarea> does not have focus +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> has focus +PASS In <textarea> in contenteditable, execCommand("styleWithCSS", false, false), a[b]c): styleWithCSS state should be false when <textarea> does not have focus +PASS In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be supported +PASS In <textarea> in contenteditable, execCommand("contentReadOnly", false, true), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be supported +PASS In <textarea> in contenteditable, execCommand("contentReadOnly", false, false), a[b]c): The command should not be enabled +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> has focus +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, p), a[b]c): defaultParagraphSeparator value should be "p" when <textarea> does not have focus +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be supported +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): The command should be enabled +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): execCommand() should return true +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): <textarea>.value should be "a[b]c" +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): beforeinput.target should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.inputType should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): input.target should be undefined +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> has focus +PASS In <textarea> in contenteditable, execCommand("defaultParagraphSeparator", false, div), a[b]c): defaultParagraphSeparator value should be "div" when <textarea> does not have focus +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any-expected.txt new file mode 100644 index 0000000..bc35e3d3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any-expected.txt
@@ -0,0 +1,37 @@ +This is a testharness.js-based test. +PASS CORS that succeeds with credentials: false; method: GET (allowed: get); header: X-Test,1 (allowed: x-test) +PASS CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) +PASS CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) +PASS CORS that fails with credentials: true; method: OK (allowed: *); header: X-Test,1 (allowed: *) +PASS CORS that fails with credentials: true; method: PUT (allowed: *); header: (allowed: ) +PASS CORS that fails with credentials: true; method: GET (allowed: get); header: X-Test,1 (allowed: *) +PASS CORS that fails with credentials: true; method: GET (allowed: *); header: X-Test,1 (allowed: *) +PASS CORS that succeeds with credentials: true; method: * (allowed: *); header: *,1 (allowed: *) +PASS CORS that succeeds with credentials: true; method: GET (allowed: GET); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: get (allowed: GET); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: GET (allowed: get); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: get (allowed: get); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: HEAD (allowed: HEAD); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: head (allowed: HEAD); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: HEAD (allowed: head); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: head (allowed: head); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: POST (allowed: POST); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: post (allowed: POST); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: POST (allowed: post); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: post (allowed: post); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: DELETE (allowed: DELETE); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: delete (allowed: DELETE); header: (allowed: *) +PASS CORS that fails with credentials: true; method: DELETE (allowed: delete); header: (allowed: *) +PASS CORS that fails with credentials: true; method: delete (allowed: delete); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: PUT (allowed: PUT); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: put (allowed: PUT); header: (allowed: *) +PASS CORS that fails with credentials: true; method: PUT (allowed: put); header: (allowed: *) +PASS CORS that fails with credentials: true; method: put (allowed: put); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: PATCH (allowed: PATCH); header: (allowed: *) +PASS CORS that fails with credentials: true; method: patch (allowed: PATCH); header: (allowed: *) +PASS CORS that fails with credentials: true; method: PATCH (allowed: patch); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: patch (allowed: patch); header: (allowed: *) +FAIL CORS that fails with credentials: false; method: POST (allowed: *); header: Authorization,123 (allowed: *) assert_unreached: Should have rejected: undefined Reached unreachable code +PASS CORS that succeeds with credentials: false; method: POST (allowed: *); header: Authorization,123 (allowed: *, Authorization) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js index e8cbc80..f9fb204 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js
@@ -80,3 +80,7 @@ preflightTest(false, true, "PATCH", "*", "patch", []) preflightTest(false, true, "patch", "*", "PATCH", []) preflightTest(true, true, "patch", "*", "patch", []) + +// "Authorization" header can't be wildcarded. +preflightTest(false, false, "*", "*", "POST", ["Authorization", "123"]) +preflightTest(true, false, "*", "*, Authorization", "POST", ["Authorization", "123"])
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js.ini b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js.ini new file mode 100644 index 0000000..2f946f0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.js.ini
@@ -0,0 +1,8 @@ +[cors-preflight-star.any.html] + [CORS that fails with credentials: false; method: POST (allowed: *); header: Authorization,123 (allowed: *)] + expected: FAIL + + +[cors-preflight-star.any.worker.html] + [CORS that fails with credentials: false; method: POST (allowed: *); header: Authorization,123 (allowed: *)] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt new file mode 100644 index 0000000..bc35e3d3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/fetch/api/cors/cors-preflight-star.any.worker-expected.txt
@@ -0,0 +1,37 @@ +This is a testharness.js-based test. +PASS CORS that succeeds with credentials: false; method: GET (allowed: get); header: X-Test,1 (allowed: x-test) +PASS CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) +PASS CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) +PASS CORS that fails with credentials: true; method: OK (allowed: *); header: X-Test,1 (allowed: *) +PASS CORS that fails with credentials: true; method: PUT (allowed: *); header: (allowed: ) +PASS CORS that fails with credentials: true; method: GET (allowed: get); header: X-Test,1 (allowed: *) +PASS CORS that fails with credentials: true; method: GET (allowed: *); header: X-Test,1 (allowed: *) +PASS CORS that succeeds with credentials: true; method: * (allowed: *); header: *,1 (allowed: *) +PASS CORS that succeeds with credentials: true; method: GET (allowed: GET); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: get (allowed: GET); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: GET (allowed: get); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: get (allowed: get); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: HEAD (allowed: HEAD); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: head (allowed: HEAD); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: HEAD (allowed: head); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: head (allowed: head); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: POST (allowed: POST); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: post (allowed: POST); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: POST (allowed: post); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: post (allowed: post); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: DELETE (allowed: DELETE); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: delete (allowed: DELETE); header: (allowed: *) +PASS CORS that fails with credentials: true; method: DELETE (allowed: delete); header: (allowed: *) +PASS CORS that fails with credentials: true; method: delete (allowed: delete); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: PUT (allowed: PUT); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: put (allowed: PUT); header: (allowed: *) +PASS CORS that fails with credentials: true; method: PUT (allowed: put); header: (allowed: *) +PASS CORS that fails with credentials: true; method: put (allowed: put); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: PATCH (allowed: PATCH); header: (allowed: *) +PASS CORS that fails with credentials: true; method: patch (allowed: PATCH); header: (allowed: *) +PASS CORS that fails with credentials: true; method: PATCH (allowed: patch); header: (allowed: *) +PASS CORS that succeeds with credentials: true; method: patch (allowed: patch); header: (allowed: *) +FAIL CORS that fails with credentials: false; method: POST (allowed: *); header: Authorization,123 (allowed: *) assert_unreached: Should have rejected: undefined Reached unreachable code +PASS CORS that succeeds with credentials: false; method: POST (allowed: *); header: Authorization,123 (allowed: *, Authorization) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini index 46f2992..e2d94669 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/history-traversal/event-order/before-load-hash-twice.html.ini
@@ -2,6 +2,7 @@ [when changing hash twice, before load] expected: if (product == "content_shell") and (os == "linux") and (flag_specific == ""): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): [FAIL, PASS]
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/windows/dangling-markup-window-name.tentative.html b/third_party/blink/web_tests/external/wpt/html/browsers/windows/dangling-markup-window-name.tentative.html new file mode 100644 index 0000000..1bc8bb9f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/browsers/windows/dangling-markup-window-name.tentative.html
@@ -0,0 +1,97 @@ +<!doctype html> +<html> +<head> + <title>Dangling Markup in target</title> + <meta name="timeout" content="long"> + <script src="/resources/testharness.js"></script> + <script src="/resources/testharnessreport.js"></script> + <script src="/common/utils.js"></script> +</head> +<body> + <script> + function anchorClick(target, id) { + const hyperlink = document.body.appendChild(document.createElement('a')); + if (target) { + hyperlink.target = target; + } + hyperlink.href = `resources/window-name.sub.html?report=${id}|close`; + hyperlink.click(); + } + + async function pollResultAndCheck(t, id, expected) { + const stashURL = new URL('resources/window-name-stash.py', location); + stashURL.searchParams.set('id', id); + + let res = 'NONE'; + while (res == 'NONE') { + await new Promise(resolve => { t.step_timeout(resolve, 100); }); + + const response = await fetch(stashURL); + res = await response.text(); + } + if (res !== expected) { + assert_unreached('Stash result does not equal expected result.') + } + } + + promise_test(async t => { + const id = token(); + const value = '\n<' + id; + + window.open(`resources/window-name.sub.html?report=${id}|close`, value); + await pollResultAndCheck(t, id, value); + }, 'Dangling Markup in target is not reset when set by window.open'); + + promise_test(async t => { + const id = token(); + const value = '\n<' + id; + + anchorClick(value, id) + await pollResultAndCheck(t, id, ''); + }, 'Dangling Markup with "\\n" in target is reset when set by <a> tag'); + + promise_test(async t => { + const id = token(); + const value = '\r<' + id; + + anchorClick(value, id) + await pollResultAndCheck(t, id, ''); + }, 'Dangling Markup with "\\r" in target is reset when set by <a> tag'); + + promise_test(async t => { + const id = token(); + const value = '\t<' + id; + + anchorClick(value, id) + await pollResultAndCheck(t, id, ''); + }, 'Dangling Markup with "\\t" in target is reset when set by <a> tag'); + + promise_test(async t => { + const id = token(); + const value = '\n<' + id; + + const form = document.body.appendChild(document.createElement('form')); + form.target = value; + form.method = 'GET'; + form.action = 'resources/window-name.sub.html'; + const input = form.appendChild(document.createElement('input')); + input.type = 'hidden'; + input.name = 'report'; + input.value = `${id}|close`; + form.submit(); + + await pollResultAndCheck(t, id, ''); + }, 'Dangling Markup in target is reset when set by <form> tag'); + + promise_test(async t => { + const id = token(); + const value = '\n<' + id; + const base = document.head.appendChild(document.createElement('base')); + base.target = value; + + anchorClick(null, id) + await pollResultAndCheck(t, id, ''); + }, 'Dangling Markup in target is reset when set by <base> tag'); + </script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/windows/resources/window-name.sub.html b/third_party/blink/web_tests/external/wpt/html/browsers/windows/resources/window-name.sub.html index 55fb8eb..5bb8ebd 100644 --- a/third_party/blink/web_tests/external/wpt/html/browsers/windows/resources/window-name.sub.html +++ b/third_party/blink/web_tests/external/wpt/html/browsers/windows/resources/window-name.sub.html
@@ -2,7 +2,7 @@ <title>popup helper</title> <script> -const search = window.location.search.replace("?", ""); + const search = decodeURIComponent(window.location.search.replace("?", "")); const steps = search.split("|"); async function proceedTest() {
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg-expected.txt b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg-expected.txt new file mode 100644 index 0000000..26f3a1a5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL drawImage() of an SVG image promise_test: Unhandled rejection with value: object "InvalidStateError: The source image could not be decoded." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html index 50aeabd2..cd29359 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html
@@ -15,21 +15,11 @@ var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); - var promise = new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", '/images/green.svg'); - xhr.responseType = 'blob'; - xhr.send(); - xhr.onload = function() { - resolve(xhr.response); - }; - }); - promise.then(function(response) { - createImageBitmap(response).then(bitmap => { - ctx.drawImage(bitmap, 0, 0); - _assertPixelApprox(canvas, 50,25, 0,255,0,255, 2); - }); - }); + const response = await fetch('/images/green.svg'); + const blob = await response.blob(); + const bitmap = await createImageBitmap(blob); + ctx.drawImage(bitmap, 0, 0); + _assertPixelApprox(canvas, 50,25, 0,255,0,255, 2); }, "drawImage() of an SVG image"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html.ini index c66b9699..6879b65b 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.html.ini
@@ -1,3 +1,3 @@ [2d.drawImage.svg.html] - expected: - if product == "chrome": ERROR + [drawImage() of an SVG image] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker-expected.txt b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker-expected.txt new file mode 100644 index 0000000..26f3a1a5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL drawImage() of an SVG image promise_test: Unhandled rejection with value: object "InvalidStateError: The source image could not be decoded." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js index a15371db..8293e89 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js
@@ -11,21 +11,11 @@ var canvas = new OffscreenCanvas(100, 50); var ctx = canvas.getContext('2d'); - var promise = new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", '/images/green.svg'); - xhr.responseType = 'blob'; - xhr.send(); - xhr.onload = function() { - resolve(xhr.response); - }; - }); - promise.then(function(response) { - createImageBitmap(response).then(bitmap => { - ctx.drawImage(bitmap, 0, 0); - _assertPixelApprox(canvas, 50,25, 0,255,0,255, 2); - }); - }); + const response = await fetch('/images/green.svg'); + const blob = await response.blob(); + const bitmap = await createImageBitmap(blob); + ctx.drawImage(bitmap, 0, 0); + _assertPixelApprox(canvas, 50,25, 0,255,0,255, 2); t.done(); }, "drawImage() of an SVG image"); done();
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js.ini new file mode 100644 index 0000000..ee8c386 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.svg.worker.js.ini
@@ -0,0 +1,3 @@ +[2d.drawImage.svg.worker.html] + [drawImage() of an SVG image] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image-expected.txt b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image-expected.txt new file mode 100644 index 0000000..e7b3db3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL drawImage with zero-sized source rectangle from image draws nothing without exception promise_test: Unhandled rejection with value: object "InvalidStateError: The source image could not be decoded." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html index 4941d37..5dfb2f3 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html
@@ -17,21 +17,11 @@ ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); - var promise = new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", '/images/red-zerowidth.svg'); - xhr.responseType = 'blob'; - xhr.send(); - xhr.onload = function() { - resolve(xhr.response); - }; - }); - promise.then(function(response) { - createImageBitmap(response).then(bitmap => { - ctx.drawImage(bitmap, 0, 0, 100, 50); - _assertPixel(canvas, 50,25, 0,255,0,255); - }); - }); + const response = await fetch('/images/red-zerowidth.svg'); + const blob = await response.blob(); + const bitmap = await createImageBitmap(blob); + ctx.drawImage(bitmap, 0, 0, 100, 50); + _assertPixel(canvas, 50,25, 0,255,0,255); }, "drawImage with zero-sized source rectangle from image draws nothing without exception"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html.ini index 3f7b04de8..ceda955 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html.ini +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.html.ini
@@ -1,3 +1,3 @@ [2d.drawImage.zerosource.image.html] - expected: - if product == "chrome": ERROR + [drawImage with zero-sized source rectangle from image draws nothing without exception] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker-expected.txt b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker-expected.txt new file mode 100644 index 0000000..e7b3db3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL drawImage with zero-sized source rectangle from image draws nothing without exception promise_test: Unhandled rejection with value: object "InvalidStateError: The source image could not be decoded." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js index a3182c9..467beb4 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js
@@ -13,21 +13,11 @@ ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); - var promise = new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", '/images/red-zerowidth.svg'); - xhr.responseType = 'blob'; - xhr.send(); - xhr.onload = function() { - resolve(xhr.response); - }; - }); - promise.then(function(response) { - createImageBitmap(response).then(bitmap => { - ctx.drawImage(bitmap, 0, 0, 100, 50); - _assertPixel(canvas, 50,25, 0,255,0,255); - }); - }); + const response = await fetch('/images/red-zerowidth.svg'); + const blob = await response.blob(); + const bitmap = await createImageBitmap(blob); + ctx.drawImage(bitmap, 0, 0, 100, 50); + _assertPixel(canvas, 50,25, 0,255,0,255); t.done(); }, "drawImage with zero-sized source rectangle from image draws nothing without exception"); done();
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js.ini b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js.ini new file mode 100644 index 0000000..7c323703 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/canvas/offscreen/drawing-images-to-the-canvas/2d.drawImage.zerosource.image.worker.js.ini
@@ -0,0 +1,3 @@ +[2d.drawImage.zerosource.image.worker.html] + [drawImage with zero-sized source rectangle from image draws nothing without exception] + expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml b/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml index 75eed14e..91b92b0 100644 --- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml +++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml-new/drawing-images-to-the-canvas.yaml
@@ -428,21 +428,11 @@ code: | ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); - var promise = new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", '/images/red-zerowidth.svg'); - xhr.responseType = 'blob'; - xhr.send(); - xhr.onload = function() { - resolve(xhr.response); - }; - }); - promise.then(function(response) { - createImageBitmap(response).then(bitmap => { - ctx.drawImage(bitmap, 0, 0, 100, 50); - _assertPixel(canvas, 50,25, 0,255,0,255); - }); - }); + const response = await fetch('/images/red-zerowidth.svg'); + const blob = await response.blob(); + const bitmap = await createImageBitmap(blob); + ctx.drawImage(bitmap, 0, 0, 100, 50); + _assertPixel(canvas, 50,25, 0,255,0,255); expected: green - name: 2d.drawImage.negativesource @@ -574,21 +564,11 @@ test_type: promise canvasType: ['OffscreenCanvas', 'Worker'] code: | - var promise = new Promise(function(resolve, reject) { - var xhr = new XMLHttpRequest(); - xhr.open("GET", '/images/green.svg'); - xhr.responseType = 'blob'; - xhr.send(); - xhr.onload = function() { - resolve(xhr.response); - }; - }); - promise.then(function(response) { - createImageBitmap(response).then(bitmap => { - ctx.drawImage(bitmap, 0, 0); - _assertPixelApprox(canvas, 50,25, 0,255,0,255, 2); - }); - }); + const response = await fetch('/images/green.svg'); + const blob = await response.blob(); + const bitmap = await createImageBitmap(blob); + ctx.drawImage(bitmap, 0, 0); + _assertPixelApprox(canvas, 50,25, 0,255,0,255, 2); expected: green - name: 2d.drawImage.animated.poster
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-overlay.html b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-overlay.html index a366f61..9cd2426 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-overlay.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/interactive-elements/the-dialog-element/dialog-overlay.html
@@ -11,10 +11,7 @@ test(() => { assert_equals(getComputedStyle(dialog).overlay, "none", "Computed overlay"); - // dialog::backdrop {} UA rule always sets overlay to 'auto' even if - // ::backdrop pseudo is not generated. ::backdrop is only generated when the - // dialog is in the top layer. - assert_equals(getComputedStyle(dialog, "::backdrop").overlay, "auto", + assert_equals(getComputedStyle(dialog, "::backdrop").overlay, "none", "Computed overlay for ::backdrop"); }, "dialog computed overlay initially 'none'"); @@ -23,15 +20,17 @@ assert_equals(getComputedStyle(dialog).overlay, "auto", "Computed overlay on open dialog"); - assert_equals(getComputedStyle(dialog, "::backdrop").overlay, "auto", + // ::backdrop pseudo element is always rendered in the top layer when its + // originating element is. It does not get its overlay property changed, + // though. + assert_equals(getComputedStyle(dialog, "::backdrop").overlay, "none", "Computed overlay for ::backdrop"); dialog.close(); assert_equals(getComputedStyle(dialog).overlay, "none", "Computed overlay on closed dialog"); - // ::backdrop is always overlay:auto. See comment above. - assert_equals(getComputedStyle(dialog, "::backdrop").overlay, "auto", + assert_equals(getComputedStyle(dialog, "::backdrop").overlay, "none", "Computed overlay for ::backdrop"); }, "Opening and closing a modal dialog changes computed overlay to 'auto' and back to 'none'"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html.ini b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html.ini index 391c16b5..3f7a607 100644 --- a/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html.ini +++ b/third_party/blink/web_tests/external/wpt/media-source/dedicated-worker/mediasource-worker-play-terminate-worker.html.ini
@@ -1,21 +1,23 @@ [mediasource-worker-play-terminate-worker.html] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac12"): [OK, TIMEOUT] [Test worker MediaSource termination after at least 5 main thread setTimeouts, starting counting before setting srcObject] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] - if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL [Test worker MediaSource termination after at least 6 main thread setTimeouts, starting counting before setting srcObject] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): [PASS, FAIL] + + [Test worker MediaSource termination after at least 7 main thread setTimeouts, starting counting before setting srcObject] + expected: + if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] [Test worker MediaSource termination after at least 8 main thread setTimeouts, starting counting before setting srcObject] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] - - [Test worker MediaSource termination after at least 9 main thread setTimeouts, starting counting before setting srcObject] - expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): [PASS, FAIL]
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https-expected.txt b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https-expected.txt index d7fe4a5..746b4ef4 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -FAIL enumerateDevices returns expected mostly empty objects in case device-info permission is not granted assert_equals: deviceId is empty before capture expected "" but got "default" -PASS enumerateDevices returns expected objects in case device-info permission is granted +FAIL enumerateDevices exposes mostly empty objects ahead of successful getUserMedia call assert_equals: deviceId is empty before capture expected "" but got "default" +PASS enumerateDevices exposes expected objects after successful getUserMedia call Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html index 2b5687f..6e6dbaf3 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html
@@ -36,7 +36,8 @@ assert_equals(device1.deviceId, "", "deviceId is empty before capture"); assert_equals(device1.groupId, "", "groupId is empty before capture"); assert_equals(device1.label, "", "label is empty before capture"); - assert_in_array(device1.kind, ["audioinput", "audiooutput", "videoinput", "kind is set to a valid value before capture"]); + assert_in_array(device1.kind, ["audioinput", "audiooutput", "videoinput"], + "kind is set to a valid value before capture"); } } /* Additionally, at most one device of each kind @@ -52,8 +53,8 @@ }, testName); } -doTest(false, "enumerateDevices returns expected mostly empty objects in case device-info permission is not granted"); -doTest(true, "enumerateDevices returns expected objects in case device-info permission is granted"); +doTest(false, "enumerateDevices exposes mostly empty objects ahead of successful getUserMedia call"); +doTest(true, "enumerateDevices exposes expected objects after successful getUserMedia call"); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html.ini b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html.ini index 75fbe78..72f2049 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html.ini +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices-returned-objects.https.html.ini
@@ -1,3 +1,7 @@ [MediaDevices-enumerateDevices-returned-objects.https.html] + [enumerateDevices exposes mostly empty objects ahead of successful getUserMedia call] + expected: + if product == "chrome": FAIL + [enumerateDevices returns expected mostly empty objects in case device-info permission is not granted] expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https-expected.txt b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https-expected.txt index 973e380..b68158e 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https-expected.txt
@@ -1,6 +1,7 @@ This is a testharness.js-based test. -FAIL mediaDevices.enumerateDevices() is present and working - before capture assert_equals: mediaInfo's deviceId should exist and be empty if getUserMedia was never called successfully. expected "" but got "default" -PASS mediaDevices.enumerateDevices() is present and working - after capture +FAIL mediaDevices.enumerateDevices() is present and working - before capture assert_equals: deviceId should be empty string if getUserMedia was never called successfully. expected "" but got "default" +FAIL mediaDevices.enumerateDevices() is working - after video capture assert_equals: audio deviceId should be empty. expected 0 but got 7 +PASS mediaDevices.enumerateDevices() is working - after video then audio capture PASS InputDeviceInfo is supported Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html index 4971f4f..88c0704 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html
@@ -23,36 +23,85 @@ promise_test(async () => { assert_not_equals(navigator.mediaDevices.enumerateDevices, undefined, "navigator.mediaDevices.enumerateDevices exists"); - const deviceList = await navigator.mediaDevices.enumerateDevices(); - for (const mediaInfo of deviceList) { - assert_not_equals(mediaInfo.kind, undefined, "mediaInfo's kind should exist."); - assert_equals(mediaInfo.deviceId, "", "mediaInfo's deviceId should exist and be empty if getUserMedia was never called successfully."); - assert_equals(mediaInfo.label, "", "mediaInfo's label should exist and be empty if getUserMedia was never called successfully."); - assert_equals(mediaInfo.groupId, "", "mediaInfo's groupId should exist and be empty if getUserMedia was never called successfully."); - assert_in_array(mediaInfo.kind, ["videoinput", "audioinput", "audiooutput"]); + const devices = await navigator.mediaDevices.enumerateDevices(); + for (const {kind, deviceId, label, groupId} of devices) { + assert_in_array(kind, ["videoinput", "audioinput", "audiooutput"]); + assert_equals(deviceId, "", "deviceId should be empty string if getUserMedia was never called successfully."); + assert_equals(label, "", "label should be empty string if getUserMedia was never called successfully."); + assert_equals(groupId, "", "groupId should be empty string if getUserMedia was never called successfully."); } - assert_less_than_equal(deviceList.filter((item) => { return item.kind == "audioinput"; }).length, 1, "there should be zero or one audio input device "); - assert_less_than_equal(deviceList.filter((item) => { return item.kind == "videoinput"; }).length, 1, "there should be zero or one video input device "); - + assert_less_than_equal(devices.filter(({kind}) => kind == "audioinput").length, + 1, "there should be zero or one audio input device."); + assert_less_than_equal(devices.filter(({kind}) => kind == "videoinput").length, + 1, "there should be zero or one video input device."); + assert_equals(devices.filter(({kind}) => kind == "audiooutput").length, + 0, "there should be no audio output devices."); + assert_less_than_equal(devices.length, 2, + "there should be no more than two devices."); + if (devices.length > 1) { + assert_equals(devices[0].kind, "audioinput", "audioinput is first"); + assert_equals(devices[1].kind, "videoinput", "videoinput is second"); + } }, "mediaDevices.enumerateDevices() is present and working - before capture"); -promise_test(async () => { - await setMediaPermission("granted", ["microphone"]); - await navigator.mediaDevices.getUserMedia({ audio : true }); - const deviceList = await navigator.mediaDevices.enumerateDevices(); - for (const mediaInfo of deviceList) { - assert_not_equals(mediaInfo.kind, undefined, "mediaInfo's kind should exist."); - assert_not_equals(mediaInfo.deviceId, "", "mediaInfo's deviceId should exist and not be empty."); - assert_in_array(mediaInfo.kind, ["videoinput", "audioinput", "audiooutput"]); +promise_test(async t => { + await setMediaPermission("granted"); + const stream = await navigator.mediaDevices.getUserMedia({ video: true }); + stream.getTracks()[0].stop(); + + const devices = await navigator.mediaDevices.enumerateDevices(); + const kinds = ["audioinput", "videoinput"]; + for (const {kind, deviceId} of devices) { + assert_in_array(kind, kinds, "camera doesn't expose audiooutput"); + assert_equals(typeof deviceId, "string", "deviceId is a string."); + switch (kind) { + case "videoinput": + assert_greater_than(deviceId.length, 0, "video deviceId should not be empty."); + break; + case "audioinput": + assert_equals(deviceId.length, 0, "audio deviceId should be empty."); + break; + } } -}, "mediaDevices.enumerateDevices() is present and working - after capture"); +}, "mediaDevices.enumerateDevices() is working - after video capture"); + +// This test is designed to come after its video counterpart directly above +promise_test(async t => { + const devices1 = await navigator.mediaDevices.enumerateDevices(); + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + stream.getTracks()[0].stop(); + const devices = await navigator.mediaDevices.enumerateDevices(); + assert_equals(devices.filter(({kind}) => kind == "videoinput").length, + devices1.filter(({kind}) => kind == "videoinput").length, + "same number of (previously exposed) videoinput devices"); + assert_greater_than_equal(devices.filter(d => d.kind == "audioinput").length, + devices1.filter(d => d.kind == "audioinput").length, + "same number or more audioinput devices"); + const order = ["audioinput", "videoinput", "audiooutput"]; + for (const {kind, deviceId} of devices) { + assert_in_array(kind, order, "expected kind"); + assert_equals(typeof deviceId, "string", "deviceId is a string."); + switch (kind) { + case "videoinput": + assert_greater_than(deviceId.length, 0, "video deviceId should not be empty."); + break; + case "audioinput": + assert_greater_than(deviceId.length, 0, "audio deviceId should not be empty."); + break; + } + } + const kinds = devices.map(({kind}) => kind); + const correct = [...kinds].sort((a, b) => order.indexOf(a) - order.indexOf(b)); + assert_equals(JSON.stringify(kinds), JSON.stringify(correct), "correct order"); +}, "mediaDevices.enumerateDevices() is working - after video then audio capture"); promise_test(async () => { - const deviceList = await navigator.mediaDevices.enumerateDevices(); - for (const mediaInfo of deviceList) { + const devices = await navigator.mediaDevices.enumerateDevices(); + for (const mediaInfo of devices) { if (mediaInfo.kind == "audioinput" || mediaInfo.kind == "videoinput") { + assert_true("InputDeviceInfo" in window, "InputDeviceInfo exists"); assert_true(mediaInfo instanceof InputDeviceInfo); - } else if ( mediaInfo.kind == "audiooutput" ) { + } else if (mediaInfo.kind == "audiooutput") { assert_true(mediaInfo instanceof MediaDeviceInfo); } else { assert_unreached("mediaInfo.kind should be one of 'audioinput', 'videoinput', or 'audiooutput'.")
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini index b6d4a002..0f4bb7c 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-enumerateDevices.https.html.ini
@@ -1,3 +1,7 @@ [MediaDevices-enumerateDevices.https.html] [mediaDevices.enumerateDevices() is present and working - before capture] expected: FAIL + + [mediaDevices.enumerateDevices() is working - after video capture] + expected: + if product == "chrome": FAIL
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-getUserMedia.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-getUserMedia.https.html index 96399c80..9376f52 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-getUserMedia.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaDevices-getUserMedia.https.html
@@ -43,6 +43,10 @@ promise_test(async t => { // Both permissions are needed at some point, asking both at once await setMediaPermission(); + // A successful camera gUM call is needed to expose camera information + const afterGum = await navigator.mediaDevices.getUserMedia({video: true}); + afterGum.getTracks()[0].stop(); + assert_true(navigator.mediaDevices.getSupportedConstraints()["groupId"], "groupId should be supported"); const devices = await navigator.mediaDevices.enumerateDevices(); @@ -66,6 +70,10 @@ }, 'groupId is correctly supported by getUserMedia() for video devices'); promise_test(async t => { + // A successful microphone gUM call is needed to expose microphone information + const afterGum = await navigator.mediaDevices.getUserMedia({audio: true}); + afterGum.getTracks()[0].stop(); + assert_true(navigator.mediaDevices.getSupportedConstraints()["groupId"], "groupId should be supported"); const devices = await navigator.mediaDevices.enumerateDevices();
diff --git a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getSettings.https.html b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getSettings.https.html index c1d90a4..1bda4c7 100644 --- a/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getSettings.https.html +++ b/third_party/blink/web_tests/external/wpt/mediacapture-streams/MediaStreamTrack-getSettings.https.html
@@ -67,18 +67,25 @@ }, 'A device can be opened twice with different resolutions requested'); promise_test(async t => { - const devices = await navigator.mediaDevices.enumerateDevices(); - const inputDevices = devices.filter(d => d.kind != "audiooutput"); - assert_greater_than(inputDevices.length, 0); - for (const device of inputDevices) { - const device_id_constraint = {deviceId: {exact: device.deviceId}}; - const constraints = device.kind == "audioinput" - ? {audio: device_id_constraint} - : {video: device_id_constraint}; + // getUserMedia needs to be called before deviceIds and groupIds are exposed + const afterGum = await navigator.mediaDevices.getUserMedia({ + video: true, audio: true + }); + afterGum.getTracks().forEach(track => track.stop()); - const stream = await navigator.mediaDevices.getUserMedia(constraints); - assert_true(stream.getTracks()[0].getSettings().groupId === device.groupId, "device groupId"); - assert_greater_than(device.groupId.length, 0); + const devices = await navigator.mediaDevices.enumerateDevices(); + const inputDevices = devices.filter(({kind}) => kind != "audiooutput"); + assert_greater_than(inputDevices.length, 1, "have at least 2 test devices"); + for (const {kind, deviceId, groupId} of inputDevices) { + const type = {videoinput: "video", audioinput: "audio"}[kind]; + const stream = await navigator.mediaDevices.getUserMedia({ + [type]: {deviceId: {exact: deviceId}} + }); + const [track] = stream.getTracks(); + const settings = track.getSettings(); + track.stop(); + assert_true(settings.groupId == groupId, "device groupId"); + assert_greater_than(settings.groupId.length, 0, "groupId is not empty"); } }, 'groupId is correctly reported by getSettings() for all input devices');
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent.html b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent.html index 2571c9c..36b80b6 100644 --- a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent.html +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent.html
@@ -58,6 +58,8 @@ assert_click_construction(click_event, this); assert_click_attributes(click_event, pointerdown_event, pointerup_event); + assert_not_equals(click_event.pointerId, -1, + "Click event triggered by a pointing device should not have -1 as the pointerId"); }, "click using " + pointer_type + " is a PointerEvent"); promise_test(async () => { @@ -77,4 +79,28 @@ assert_click_construction(click_event, frames[0]); assert_click_attributes(click_event, pointerdown_event, pointerup_event); }, "click in a subframe using " + pointer_type + " is a PointerEvent"); + +// Run this part of the test only once, since it doesn't rely on the pointer_type. +if (pointer_type == "mouse") { + promise_test(async () => { + const target = document.getElementById("target"); + let click_promise = getEvent("click", target); + target.click(); + let click_event = await click_promise; + assert_equals(click_event.pointerId, -1, + "Click event triggered by a non-pointing device should have -1 as the pointerId"); + + target.type = "button"; + target.focus(); + click_promise = getEvent("click", target); + // Press enter + let actions = new test_driver.Actions() + .keyDown("\uE007") + .keyUp("\uE007"); + await actions.send(); + click_event = await click_promise; + assert_equals(click_event.pointerId, -1, + "Click event triggered by a non-pointing device should have -1 as the pointerId"); + }, "Click event triggered by a non-pointing device should have -1 as the pointerId"); +} </script>
diff --git a/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent_mouse-expected.txt b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent_mouse-expected.txt new file mode 100644 index 0000000..db2190d9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/pointerevents/pointerevent_click_is_a_pointerevent_mouse-expected.txt
@@ -0,0 +1,6 @@ +This is a testharness.js-based test. +PASS click using mouse is a PointerEvent +PASS click in a subframe using mouse is a PointerEvent +FAIL Click event triggered by a non-pointing device should have -1 as the pointerId promise_test: Unhandled rejection with value: object "Error: We do not support keydown and keyup actions, please use test_driver.send_keys. See crbug.com/893480." +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini index e4272ef..8f8232e0 100644 --- a/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini +++ b/third_party/blink/web_tests/external/wpt/preload/modulepreload-as.html.ini
@@ -1,147 +1,200 @@ [modulepreload-as.html] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): OK - if (product == "content_shell") and (os == "mac") and (port == "mac12"): OK - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [ERROR, OK] - if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK - if (product == "content_shell") and (os == "win") and (port == "win11"): TIMEOUT - ERROR + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): ERROR + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): TIMEOUT + if (product == "content_shell") and (os == "win") and (port == "win11"): ERROR + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): TIMEOUT + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [ERROR, OK] + if (product == "content_shell") and (os == "mac") and (port == "mac13"): ERROR + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [ERROR, OK] + if product == "chrome": [ERROR, TIMEOUT] + [Modulepreload with as=""] + expected: + if product == "chrome": [PASS, TIMEOUT] + [Modulepreload with as="audio"] - expected: FAIL + expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if product == "chrome": [FAIL, PASS, TIMEOUT, NOTRUN] + FAIL [Modulepreload with as="audioworklet"] - expected: FAIL + expected: + if product == "chrome": [FAIL, NOTRUN] + FAIL [Modulepreload with as="document"] - expected: FAIL + expected: + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "linux"): PASS + if product == "chrome": [FAIL, NOTRUN, PASS] + FAIL [Modulepreload with as="embed"] expected: if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if product == "chrome": NOTRUN + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if product == "chrome": [PASS, NOTRUN, FAIL] FAIL [Modulepreload with as="fetch"] expected: - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if product == "chrome": [PASS, NOTRUN] [Modulepreload with as="font"] expected: + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if product == "chrome": NOTRUN + if product == "chrome": [PASS, FAIL, NOTRUN] FAIL [Modulepreload with as="frame"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if product == "chrome": NOTRUN - FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if product == "chrome": [PASS, NOTRUN, FAIL] [Modulepreload with as="iMaGe"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): FAIL + if product == "chrome": [PASS, NOTRUN] [Modulepreload with as="iframe"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": NOTRUN - FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if product == "chrome": [PASS, FAIL, NOTRUN] [Modulepreload with as="image"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if product == "chrome": NOTRUN - FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if product == "chrome": [PASS, FAIL, NOTRUN] [Modulepreload with as="invalid-dest"] - expected: FAIL + expected: + if product == "chrome": [FAIL, NOTRUN] + FAIL [Modulepreload with as="manifest"] expected: - if (product == "content_shell") and (os == "win") and (port == "win11"): PASS - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS - if product == "chrome": PASS - FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if product == "chrome": [PASS, NOTRUN, FAIL] [Modulepreload with as="object"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [PASS, FAIL] - if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] + if product == "chrome": [PASS, NOTRUN] [Modulepreload with as="paintworklet"] - expected: FAIL + expected: + if product == "chrome": [FAIL, NOTRUN] + FAIL [Modulepreload with as="report"] expected: if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): [PASS, FAIL] + if product == "chrome": [PASS, NOTRUN] + + [Modulepreload with as="sCrIpT"] + expected: + if product == "chrome": [PASS, NOTRUN] + + [Modulepreload with as="script"] + expected: + if product == "chrome": [PASS, NOTRUN] [Modulepreload with as="serviceworker"] - expected: FAIL + expected: + if product == "chrome": [FAIL, NOTRUN] + FAIL [Modulepreload with as="sharedworker"] - expected: FAIL + expected: + if product == "chrome": [FAIL, NOTRUN] + FAIL [Modulepreload with as="style"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if product == "chrome": NOTRUN + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "linux"): PASS + if product == "chrome": [PASS, NOTRUN, FAIL] FAIL [Modulepreload with as="track"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": NOTRUN + if product == "chrome": [PASS, NOTRUN] FAIL [Modulepreload with as="video"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": PASS + if product == "chrome": [PASS, NOTRUN] FAIL [Modulepreload with as="webidentity"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] - if (product == "content_shell") and (os == "mac") and (port == "mac12"): PASS + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": PASS + if product == "chrome": [PASS, NOTRUN, FAIL] FAIL [Modulepreload with as="worker"] - expected: FAIL + expected: + if product == "chrome": [FAIL, NOTRUN] + FAIL [Modulepreload with as="xslt"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac13"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS + if (product == "content_shell") and (os == "win") and (port == "win11"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): [FAIL, PASS] if (product == "content_shell") and (os == "linux"): PASS - if product == "chrome": PASS + if product == "chrome": [PASS, NOTRUN] FAIL
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/pattern-text-01.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/pattern-text-01.svg new file mode 100644 index 0000000..16c0535 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/pattern-text-01.svg
@@ -0,0 +1,21 @@ +<svg height="100px" width="100px" viewBox="0 0 1000 300" preserveAspectRatio="none" xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml"> + <metadata> + <h:title>pattern on text elements</h:title> + <h:link rel="help" href="https://www.w3.org/TR/SVG2/pservers.html#Patterns"/> + <h:link rel="match" href="reference/green-100x100.svg"/> + <h:link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> + </metadata> + <defs> + <pattern id="green" width="10%" height="10%" patternUnits="userSpaceOnUse"> + <rect width="8%" height="8%" fill="green"/> + </pattern> + <pattern id="red" width="10%" height="10%" patternUnits="userSpaceOnUse"> + <rect x="0.5%" y="0.5%" width="7%" height="7%" fill="red"/> + </pattern> + </defs> + <rect fill="green" width="1000" height="300"/> + + <!-- the text should be covered by the rect that follows --> + <text fill="url(#red)" font-family="Ahem" font-size="100px" x="50" y="150">XXXXXXXX</text> + <rect fill="url(#green)" width="1000" height="300"/> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini index 75eae59b..20571581 100644 --- a/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini +++ b/third_party/blink/web_tests/external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html.ini
@@ -4,9 +4,7 @@ if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): TIMEOUT [Test video.requestVideoFrameCallback() parameters for WebRTC applications.] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] + if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS if (product == "content_shell") and (os == "mac") and (port == "mac12"): PASS if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): PASS - if (product == "content_shell") and (os == "win") and (port == "win10.20h2"): PASS - if product == "chrome": PASS FAIL
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt index ecda7e6fc..bbba675 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/accumulation-per-property-002-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 291 tests; 279 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 298 tests; 286 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Setup PASS isolation (type: discrete) has testAccumulation function PASS isolation: "isolate" onto "auto" @@ -134,6 +134,13 @@ PASS scroll-behavior (type: discrete) has testAccumulation function PASS scroll-behavior: "smooth" onto "auto" PASS scroll-behavior: "auto" onto "smooth" +PASS scrollbar-gutter (type: discrete) has testAccumulation function +PASS scrollbar-gutter: "stable" onto "auto" +PASS scrollbar-gutter: "auto" onto "stable" +PASS scrollbar-gutter: "stable both-edges" onto "auto" +PASS scrollbar-gutter: "auto" onto "stable both-edges" +PASS scrollbar-gutter: "stable both-edges" onto "stable" +PASS scrollbar-gutter: "stable" onto "stable both-edges" PASS scrollbar-width (type: discrete) has testAccumulation function PASS scrollbar-width: "thin" onto "auto" PASS scrollbar-width: "auto" onto "thin"
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt index 22aa3ffd..818aa70 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/addition-per-property-002-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 287 tests; 278 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 294 tests; 285 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Setup PASS isolation (type: discrete) has testAddition function PASS isolation: "isolate" onto "auto" @@ -134,6 +134,13 @@ PASS scroll-behavior (type: discrete) has testAddition function PASS scroll-behavior: "smooth" onto "auto" PASS scroll-behavior: "auto" onto "smooth" +PASS scrollbar-gutter (type: discrete) has testAddition function +PASS scrollbar-gutter: "stable" onto "auto" +PASS scrollbar-gutter: "auto" onto "stable" +PASS scrollbar-gutter: "stable both-edges" onto "auto" +PASS scrollbar-gutter: "auto" onto "stable both-edges" +PASS scrollbar-gutter: "stable both-edges" onto "stable" +PASS scrollbar-gutter: "stable" onto "stable both-edges" PASS scrollbar-width (type: discrete) has testAddition function PASS scrollbar-width: "thin" onto "auto" PASS scrollbar-width: "auto" onto "thin"
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt index aa63ca0..f24ec17 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/interpolation-per-property-002-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 354 tests; 343 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 364 tests; 353 PASS, 11 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Setup PASS isolation (type: discrete) has testInterpolation function PASS isolation uses discrete animation when animating between "auto" and "isolate" with linear easing @@ -161,6 +161,16 @@ PASS scroll-behavior uses discrete animation when animating between "auto" and "smooth" with linear easing PASS scroll-behavior uses discrete animation when animating between "auto" and "smooth" with effect easing PASS scroll-behavior uses discrete animation when animating between "auto" and "smooth" with keyframe easing +PASS scrollbar-gutter (type: discrete) has testInterpolation function +PASS scrollbar-gutter uses discrete animation when animating between "auto" and "stable" with linear easing +PASS scrollbar-gutter uses discrete animation when animating between "auto" and "stable" with effect easing +PASS scrollbar-gutter uses discrete animation when animating between "auto" and "stable" with keyframe easing +PASS scrollbar-gutter uses discrete animation when animating between "auto" and "stable both-edges" with linear easing +PASS scrollbar-gutter uses discrete animation when animating between "auto" and "stable both-edges" with effect easing +PASS scrollbar-gutter uses discrete animation when animating between "auto" and "stable both-edges" with keyframe easing +PASS scrollbar-gutter uses discrete animation when animating between "stable" and "stable both-edges" with linear easing +PASS scrollbar-gutter uses discrete animation when animating between "stable" and "stable both-edges" with effect easing +PASS scrollbar-gutter uses discrete animation when animating between "stable" and "stable both-edges" with keyframe easing PASS scrollbar-width (type: discrete) has testInterpolation function PASS scrollbar-width uses discrete animation when animating between "auto" and "thin" with linear easing PASS scrollbar-width uses discrete animation when animating between "auto" and "thin" with effect easing
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js index 53ab3a7d..bb75ab5 100644 --- a/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js +++ b/third_party/blink/web_tests/external/wpt/web-animations/animation-model/animation-types/property-list.js
@@ -1172,6 +1172,12 @@ { type: 'discrete', options: [ [ 'auto', 'smooth' ] ] } ] }, + 'scrollbar-gutter': { + // https://drafts.csswg.org/css-overflow/#propdef-scrollbar-gutter + types: [ + { type: 'discrete', options: [ [ 'auto', 'stable' ], [ 'auto', 'stable both-edges' ], [ 'stable', 'stable both-edges' ] ] } + ] + }, 'scrollbar-width': { // https://drafts.csswg.org/css-scrollbars/#propdef-scrollbar-width types: [
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-1-chan.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-1-chan.html index 300b436..e239a5e 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-1-chan.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-1-chan.html
@@ -20,7 +20,7 @@ const absoluteThreshold = Math.pow(2, -21); // Fairly arbitrary sample rate, except that we want the rate to be a - // power of two so that 1/sampleRate is exactly respresentable as a + // power of two so that 1/sampleRate is exactly representable as a // single-precision float. let sampleRate = 8192;
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-2-chan.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-2-chan.html index 9baf5f9..a73eb3f 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-2-chan.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-2-chan.html
@@ -20,7 +20,7 @@ const absoluteThreshold = Math.pow(2, -21); // Fairly arbitrary sample rate, except that we want the rate to be a - // power of two so that 1/sampleRate is exactly respresentable as a + // power of two so that 1/sampleRate is exactly representable as a // single-precision float. let sampleRate = 8192;
diff --git a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-4-chan.html b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-4-chan.html index cf3986e8..f188d87b 100644 --- a/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-4-chan.html +++ b/third_party/blink/web_tests/external/wpt/webaudio/the-audio-api/the-convolvernode-interface/convolver-response-4-chan.html
@@ -20,7 +20,7 @@ const absoluteThreshold = 3 * Math.pow(2, -22); // Fairly arbitrary sample rate, except that we want the rate to be a - // power of two so that 1/sampleRate is exactly respresentable as a + // power of two so that 1/sampleRate is exactly representable as a // single-precision float. let sampleRate = 8192;
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini b/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini index 36fa0f32..5aa0dd3 100644 --- a/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini +++ b/third_party/blink/web_tests/external/wpt/webcodecs/full-cycle-test.https.any.js.ini
@@ -1,20 +1,24 @@ [full-cycle-test.https.any.html?h264_annexb] expected: + if (product == "content_shell") and (os == "mac") and (port == "mac11"): ERROR if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): ERROR + if (product == "content_shell") and (os == "mac") and (port == "mac12"): ERROR + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): ERROR if (product == "content_shell") and (os == "mac") and (port == "mac13"): ERROR if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): TIMEOUT - if (product == "content_shell") and (os == "mac") and (port == "mac11"): ERROR - if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): ERROR - if (product == "content_shell") and (os == "mac") and (port == "mac12"): ERROR [Encoding and decoding cycle] expected: - if (product == "content_shell") and (os == "mac"): FAIL - PRECONDITION_FAILED + if (product == "content_shell") and (os == "win"): PRECONDITION_FAILED + if (product == "content_shell") and (os == "linux"): PRECONDITION_FAILED + if product == "chrome": PRECONDITION_FAILED + FAIL [Encoding and decoding cycle w/ stripped color space] expected: - if (product == "content_shell") and (os == "mac"): FAIL - PRECONDITION_FAILED + if (product == "content_shell") and (os == "win"): PRECONDITION_FAILED + if (product == "content_shell") and (os == "linux"): PRECONDITION_FAILED + if product == "chrome": PRECONDITION_FAILED + FAIL [full-cycle-test.https.any.html?h264_avc]
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/reconfiguring-encoder.https.any.js.ini b/third_party/blink/web_tests/external/wpt/webcodecs/reconfiguring-encoder.https.any.js.ini index 633ca1e..1f7e751 100644 --- a/third_party/blink/web_tests/external/wpt/webcodecs/reconfiguring-encoder.https.any.js.ini +++ b/third_party/blink/web_tests/external/wpt/webcodecs/reconfiguring-encoder.https.any.js.ini
@@ -15,16 +15,16 @@ [reconfiguring-encoder.https.any.html?h264_avc] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): ERROR - if (product == "content_shell") and (os == "mac") and (port == "mac13"): ERROR if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): ERROR if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): ERROR + if (product == "content_shell") and (os == "mac") and (port == "mac12"): ERROR + if (product == "content_shell") and (os == "mac") and (port == "mac13"): ERROR [Reconfiguring encoder] expected: + if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac13"): FAIL PRECONDITION_FAILED
diff --git a/third_party/blink/web_tests/external/wpt/webtransport/bidirectional-cancel-crash.https.html b/third_party/blink/web_tests/external/wpt/webtransport/bidirectional-cancel-crash.https.html new file mode 100644 index 0000000..6919c90 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webtransport/bidirectional-cancel-crash.https.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<html class="test-wait"> +<script src="/common/get-host-info.sub.js"></script> +<script src="resources/webtransport-test-helpers.sub.js"></script> +<script type="module"> + const WT_CODE = 127; + const HTTP_CODE = webtransport_code_to_http_code(WT_CODE); + const wt = new WebTransport( + webtransport_url(`abort-stream-from-server.py?code=${HTTP_CODE}`)); + await wt.ready; + + const bidi = await wt.createBidirectionalStream(); + const writer = bidi.writable.getWriter(); + + const reader = bidi.readable.getReader(); + reader.read(); + + // Write something, to make the stream visible to the server side. + await writer.write(new Uint8Array([64])); + + const e = await reader.closed.catch(e => e); + document.documentElement.classList.remove("test-wait"); +</script>
diff --git a/third_party/blink/web_tests/fast/css-grid-layout/crash-opposite-subgrid.html b/third_party/blink/web_tests/fast/css-grid-layout/crash-opposite-subgrid.html new file mode 100644 index 0000000..17311137 --- /dev/null +++ b/third_party/blink/web_tests/fast/css-grid-layout/crash-opposite-subgrid.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<title>Opposite direction subgrids do not crash</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> + +<div id="target" style="display: grid; grid-template-columns: 1fr 1fr 1fr;"> + <div id="subgrid" style="display: grid; grid-template-columns: subgrid; direction: rtl; grid-column: span 4;">x</div> +</div> +<script> + test(() => { + let subgrid = document.getElementById("subgrid"); + let actual = window.getComputedStyle(subgrid)['grid-template-columns']; + assert_equals(actual, "subgrid [] [] [] [] []"); + }, 'Opposite direction subgrids do not crash'); +</script>
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt index 42f257b..ee586d7 100644 --- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-on-navigation-expected.txt
@@ -15,7 +15,7 @@ Session Storage http://127.0.0.1:8000/ IndexedDB - Database1 - http://127.0.0.1:8000/ + Database1 Web SQL database-for-test Cookies @@ -55,7 +55,7 @@ Session Storage http://127.0.0.1:8000/ IndexedDB - Database1 - http://127.0.0.1:8000/ + Database1 Web SQL Cookies http://127.0.0.1:8000
diff --git a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt index 4662a12e..2683b3d 100644 --- a/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/application-panel/resources-panel-selection-on-reload-expected.txt
@@ -15,7 +15,7 @@ Session Storage http://127.0.0.1:8000/ IndexedDB - Database1 - http://127.0.0.1:8000/ + Database1 Web SQL database-for-test Cookies @@ -56,7 +56,7 @@ Session Storage http://127.0.0.1:8000/ IndexedDB - Database1 - http://127.0.0.1:8000/ + Database1 Web SQL Cookies http://127.0.0.1:8000
diff --git a/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view-expected.txt b/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view-expected.txt index 0cf9566..d509e40b 100644 --- a/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view-expected.txt
@@ -4,16 +4,16 @@ (empty) Created database. Dumping IndexedDB tree: - database: testDatabase - http://127.0.0.1:8000 + database: testDatabase (no object stores) Created first objectstore. Dumping IndexedDB tree: - database: testDatabase - http://127.0.0.1:8000 + database: testDatabase Object store: testObjectStore1 Index: testIndex Created second objectstore. Dumping IndexedDB tree: - database: testDatabase - http://127.0.0.1:8000 + database: testDatabase Object store: testObjectStore1 Index: testIndex Object store: testObjectStore2
diff --git a/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view.js b/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view.js index 33ef44e..a3bf149 100644 --- a/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view.js +++ b/third_party/blink/web_tests/http/tests/devtools/indexeddb/database-refresh-view.js
@@ -22,25 +22,27 @@ var keyPath = 'testKey'; var indexedDBModel = TestRunner.mainTarget.model(Resources.IndexedDBModel); - indexedDBModel._throttler._timeout = 100000; // Disable live updating. + indexedDBModel.throttler['#timeout'] = 100000; // Disable live updating. var databaseId; function waitRefreshDatabase() { - var view = UI.panels.resources._sidebar.indexedDBListTreeElement._idbDatabaseTreeElements[0]._view; - view._refreshDatabaseButtonClicked(); - return new Promise((resolve) => { - TestRunner.addSniffer(Resources.IDBDatabaseView.prototype, '_updatedForTests', resolve, false); + var view = UI.panels.resources.sidebar.indexedDBListTreeElement.idbDatabaseTreeElements[0].view; + const promise = new Promise((resolve) => { + TestRunner.addSniffer(Resources.IDBDatabaseView.prototype, 'updatedForTests', resolve, false); }); + + view.getComponent().refreshDatabaseButtonClicked(); + return promise; } function waitRefreshDatabaseRightClick() { - idbDatabaseTreeElement._refreshIndexedDB(); + idbDatabaseTreeElement.refreshIndexedDB(); return waitUpdateDataView(); } function waitUpdateDataView() { return new Promise((resolve) => { - TestRunner.addSniffer(Resources.IDBDataView.prototype, '_updatedDataForTests', resolve, false); + TestRunner.addSniffer(Resources.IDBDataView.prototype, 'updatedDataForTests', resolve, false); }); } @@ -56,7 +58,7 @@ Common.EventTarget.removeEventListeners([event]); callback(); }); - UI.panels.resources._sidebar.indexedDBListTreeElement.refreshIndexedDB(); + UI.panels.resources.sidebar.indexedDBListTreeElement.refreshIndexedDB(); } // Initial tree @@ -65,8 +67,8 @@ // Create database await ApplicationTestRunner.createDatabaseAsync(databaseName); await new Promise(waitDatabaseAdded); - var idbDatabaseTreeElement = UI.panels.resources._sidebar.indexedDBListTreeElement._idbDatabaseTreeElements[0]; - databaseId = idbDatabaseTreeElement._databaseId; + var idbDatabaseTreeElement = UI.panels.resources.sidebar.indexedDBListTreeElement.idbDatabaseTreeElements[0]; + databaseId = idbDatabaseTreeElement.databaseId; TestRunner.addResult('Created database.'); ApplicationTestRunner.dumpIndexedDBTree(); @@ -74,11 +76,12 @@ indexedDBModel.refreshDatabase(databaseId); // Initial database refresh. await new Promise(waitDatabaseLoaded); // Needed to initialize database view, otherwise idbDatabaseTreeElement.onselect(false); // IDBDatabaseTreeElement.database would be undefined. - var databaseView = idbDatabaseTreeElement._view; + var databaseView = idbDatabaseTreeElement.view; // Create first objectstore await ApplicationTestRunner.createObjectStoreAsync(databaseName, objectStoreName1, indexName, keyPath); await waitRefreshDatabase(); + await new Promise(resolve => setTimeout(resolve, 0)); TestRunner.addResult('Created first objectstore.'); ApplicationTestRunner.dumpIndexedDBTree();
diff --git a/third_party/blink/web_tests/http/tests/devtools/indexeddb/delete-entry-expected.txt b/third_party/blink/web_tests/http/tests/devtools/indexeddb/delete-entry-expected.txt index abce03e7..91ee093 100644 --- a/third_party/blink/web_tests/http/tests/devtools/indexeddb/delete-entry-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/indexeddb/delete-entry-expected.txt
@@ -1,7 +1,7 @@ Tests object store and index entry deletion. Dumping IndexedDB tree: - database: database1 - http://127.0.0.1:8000/ + database: database1 Object store: objectStore1 Index: index1 Dumping ObjectStore data:
diff --git a/third_party/blink/web_tests/http/tests/devtools/indexeddb/live-update-indexeddb-content-expected.txt b/third_party/blink/web_tests/http/tests/devtools/indexeddb/live-update-indexeddb-content-expected.txt index 7e6ad58..a1c02fc 100644 --- a/third_party/blink/web_tests/http/tests/devtools/indexeddb/live-update-indexeddb-content-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/indexeddb/live-update-indexeddb-content-expected.txt
@@ -1,7 +1,7 @@ Tests that the IndexedDB database content live updates. Dumping IndexedDB tree: - database: database1 - http://127.0.0.1:8000/ + database: database1 Object store: objectStore1 Index: index1 Object store marked needs refresh = false
diff --git a/third_party/blink/web_tests/http/tests/devtools/indexeddb/resources-panel-expected.txt b/third_party/blink/web_tests/http/tests/devtools/indexeddb/resources-panel-expected.txt index 22e31fe..a7b17fbf 100644 --- a/third_party/blink/web_tests/http/tests/devtools/indexeddb/resources-panel-expected.txt +++ b/third_party/blink/web_tests/http/tests/devtools/indexeddb/resources-panel-expected.txt
@@ -8,7 +8,7 @@ Refreshing. Refreshed. Dumping IndexedDB tree: - database: testDatabase - http://127.0.0.1:8000/ + database: testDatabase Object store: testObjectStore Index: testIndexName Navigating to another security origin. @@ -20,7 +20,7 @@ Refreshing. Refreshed. Dumping IndexedDB tree: - database: testDatabase - http://127.0.0.1:8000/ + database: testDatabase Object store: testObjectStore Index: testIndexName Deleting database.
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/console/console-dom-mutation-violations.js b/third_party/blink/web_tests/http/tests/inspector-protocol/console/console-dom-mutation-violations.js index b87197ea..962e9b8 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/console/console-dom-mutation-violations.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/console/console-dom-mutation-violations.js
@@ -1,4 +1,5 @@ (async function(testRunner) { + // TODO(crbug.com/1446498) This test can be deleted once Mutation Events are removed. var {page, session, dp} = await testRunner.startBlank('Tests that dom modification event listener produces a violation.'); dp.Log.onEntryAdded(testRunner.log.bind(testRunner)); dp.Log.enable();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mutation-events-issue.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mutation-events-issue.js index 1ef4c6e..3d5b3b6 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mutation-events-issue.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/mutation-events-issue.js
@@ -1,4 +1,5 @@ (async function (testRunner) { + // TODO(crbug.com/1446498) This test can be deleted once Mutation Events are removed. const { session, dp } = await testRunner.startBlank( 'Verifies that adding Mutation Event listeners triggers a deprecation issue.'); await dp.Audits.enable();
diff --git a/third_party/blink/web_tests/virtual/text-antialias/split-text-crash.xhtml b/third_party/blink/web_tests/virtual/text-antialias/split-text-crash.xhtml index f0114445..0ba822fe 100644 --- a/third_party/blink/web_tests/virtual/text-antialias/split-text-crash.xhtml +++ b/third_party/blink/web_tests/virtual/text-antialias/split-text-crash.xhtml
@@ -1,6 +1,9 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <body></body> <script> + +// TODO(crbug.com/1446498) This test can be deleted once Mutation Events are removed. + if (window.testRunner) { testRunner.waitUntilDone(); testRunner.dumpAsText();
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index a8455577..ae3ce84 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -947,6 +947,9 @@ getter ay method constructor setter ay +interface CSSStartingStyleRule : CSSConditionRule + attribute @@toStringTag + method constructor interface CSSStyleDeclaration attribute @@toStringTag getter cssFloat
diff --git a/third_party/cardboard/BUILD.gn b/third_party/cardboard/BUILD.gn index d0a1f35..5e391b1 100644 --- a/third_party/cardboard/BUILD.gn +++ b/third_party/cardboard/BUILD.gn
@@ -32,7 +32,13 @@ "src/sdk/device_params/android/java/com/google/cardboard/sdk/deviceparams/DeviceParamsUtils.java", "src/sdk/java_utils/android/java/com/google/cardboard/sdk/UsedByNative.java", "src/sdk/qrcode/android/java/com/google/cardboard/sdk/HeadsetDetectionActivity.java", - "src/sdk/qrcode/android/java/com/google/cardboard/sdk/QrCodeCaptureActivity.java", + + # TODO(https://crbug.com/1429091): There's a build error because a JNI in + # this class isn't used. Once we begin consuming it, it'll likely go away. + # If not, or in the mean time we can either comment it out (as done + # currently), or pursue a workaround as described in + # https://crbug.com/1407278. + # "src/sdk/qrcode/android/java/com/google/cardboard/sdk/QrCodeCaptureActivity.java", "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/AsyncTask.java", "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/CardboardParamsUtils.java", "src/sdk/qrcode/android/java/com/google/cardboard/sdk/qrcode/InputStreamProvider.java", @@ -92,6 +98,7 @@ "src/sdk/qrcode/ios/qr_scan_view_controller.h", "src/sdk/rendering/android/shaders/distortion_frag.spv.h", "src/sdk/rendering/android/shaders/distortion_vert.spv.h", + "src/sdk/rendering/opengl_es2_distortion_renderer.cc", "src/sdk/screen_params.h", "src/sdk/screen_params/android/screen_params.cc", "src/sdk/sensors/accelerometer_data.h", @@ -132,7 +139,6 @@ "src/sdk/util/vectorutils.cc", "src/sdk/util/vectorutils.h", "src_overrides/sdk/jni_utils/android/jni_utils.cc", - "src_overrides/sdk/rendering/opengl_es2_distortion_renderer.cc", ] deps = [ "//base" ]
diff --git a/third_party/cardboard/README.chromium b/third_party/cardboard/README.chromium index 7d354c8..4698fd0 100644 --- a/third_party/cardboard/README.chromium +++ b/third_party/cardboard/README.chromium
@@ -1,7 +1,7 @@ Name: Cardboard SDK Short Name: cardboard URL: https://github.com/googlevr/cardboard -Version: 1.20.0 +Version: 1.21.0 License: Apache 2.0 License File: LICENSE Security Critical: yes @@ -14,4 +14,3 @@ * Created local top-level BUILD.gn based on src/sdk/build.gradle * Created local proguard-rules.pro to remove proto-specific rule * Created local override for LoadJClass in jni_utils to leaverage //base JNI loading due to splits. -* Created local override for opengl_es2_distortion_renderer to allow using external_oes textures.
diff --git a/third_party/cardboard/src_overrides/sdk/rendering/opengl_es2_distortion_renderer.cc b/third_party/cardboard/src_overrides/sdk/rendering/opengl_es2_distortion_renderer.cc deleted file mode 100644 index 717a690..0000000 --- a/third_party/cardboard/src_overrides/sdk/rendering/opengl_es2_distortion_renderer.cc +++ /dev/null
@@ -1,316 +0,0 @@ -/* - * Copyright 2019 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#include <array> -#include <vector> - -#ifdef __ANDROID__ -#include <GLES2/gl2.h> -#endif -#ifdef __APPLE__ -#include <OpenGLES/ES2/gl.h> -#endif -#include "third_party/cardboard/src/sdk/distortion_renderer.h" -#include "third_party/cardboard/src/sdk/include/cardboard.h" -#include "third_party/cardboard/src/sdk/util/is_initialized.h" -#include "third_party/cardboard/src/sdk/util/logging.h" - -namespace { - -constexpr const char* kDistortionVertexShader = - R"glsl( - attribute vec2 a_Position; - attribute vec2 a_TexCoords; - varying vec2 v_TexCoords; - - void main() { - gl_Position = vec4(a_Position, 0, 1); - v_TexCoords = a_TexCoords; - })glsl"; - -constexpr const char* kDistortionFragmentShader = - R"glsl( - #extension GL_OES_EGL_image_external : require - precision mediump float; - - uniform samplerExternalOES u_Texture; - uniform vec2 u_Start; - uniform vec2 u_End; - varying vec2 v_TexCoords; - - void main() { - vec2 coords = u_Start + v_TexCoords * (u_End - u_Start); - gl_FragColor = texture2D(u_Texture, coords); - })glsl"; - -void CheckGlError(const char* label) { - int gl_error = glGetError(); - if (gl_error != GL_NO_ERROR) { - CARDBOARD_LOGE("GL error %s: %d", label, gl_error); - } -} - -GLuint LoadShader(GLenum shader_type, const char* source) { - GLuint shader = glCreateShader(shader_type); - glShaderSource(shader, 1, &source, nullptr); - glCompileShader(shader); - CheckGlError("glCompileShader"); - GLint result = GL_FALSE; - glGetShaderiv(shader, GL_COMPILE_STATUS, &result); - if (result == GL_FALSE) { - int log_length; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_length); - if (log_length == 0) { - return 0; - } - - std::vector<char> log_string(log_length); - glGetShaderInfoLog(shader, log_length, nullptr, log_string.data()); - CARDBOARD_LOGE("Could not compile shader of type %d: %s", shader_type, - log_string.data()); - - shader = 0; - } - - return shader; -} - -GLuint CreateProgram(const char* vertex, const char* fragment) { - GLuint vertex_shader = LoadShader(GL_VERTEX_SHADER, vertex); - if (vertex_shader == 0) { - return 0; - } - - GLuint fragment_shader = LoadShader(GL_FRAGMENT_SHADER, fragment); - if (fragment_shader == 0) { - return 0; - } - - GLuint program = glCreateProgram(); - - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - glLinkProgram(program); - CheckGlError("glLinkProgram"); - - GLint result = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &result); - if (result == GL_FALSE) { - int log_length; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_length); - if (log_length == 0) { - return 0; - } - - std::vector<char> log_string(log_length); - glGetShaderInfoLog(program, log_length, nullptr, log_string.data()); - CARDBOARD_LOGE("Could not compile program: %s", log_string.data()); - - return 0; - } - - glDetachShader(program, vertex_shader); - glDetachShader(program, fragment_shader); - glDeleteShader(vertex_shader); - glDeleteShader(fragment_shader); - CheckGlError("GlCreateProgram"); - - return program; -} - -} // namespace - -namespace cardboard::rendering { - -// @brief OpenGL ES 2.0 concrete implementation of DistortionRenderer. -class OpenGlEs2DistortionRenderer : public DistortionRenderer { - public: - OpenGlEs2DistortionRenderer() - : vertices_vbo_{0, 0}, - uvs_vbo_{0, 0}, - elements_vbo_{0, 0}, - elements_count_{0, 0} { - program_ = - CreateProgram(kDistortionVertexShader, kDistortionFragmentShader); - attrib_pos_ = glGetAttribLocation(program_, "a_Position"); - attrib_tex_ = glGetAttribLocation(program_, "a_TexCoords"); - uniform_start_ = glGetUniformLocation(program_, "u_Start"); - uniform_end_ = glGetUniformLocation(program_, "u_End"); - - // Gen buffers, one per eye. - glGenBuffers(2, &vertices_vbo_[0]); - glGenBuffers(2, &uvs_vbo_[0]); - glGenBuffers(2, &elements_vbo_[0]); - CheckGlError("OpenGlEs2DistortionRendererSetUp"); - } - - ~OpenGlEs2DistortionRenderer() { - glDeleteBuffers(2, &vertices_vbo_[0]); - glDeleteBuffers(2, &uvs_vbo_[0]); - glDeleteBuffers(2, &elements_vbo_[0]); - CheckGlError("~OpenGlEs2DistortionRenderer"); - } - - /* - * Modifies the OpenGL global state. In particular: - * - glGet(GL_ARRAY_BUFFER_BINDING) - * - glGet(GL_ELEMENT_ARRAY_BUFFER_BINDING) - */ - void SetMesh(const CardboardMesh* mesh, CardboardEye eye) override { - glBindBuffer(GL_ARRAY_BUFFER, vertices_vbo_[eye]); - glBufferData( - GL_ARRAY_BUFFER, - mesh->n_vertices * sizeof(float) * 2, // Two components per vertex - mesh->vertices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, uvs_vbo_[eye]); - glBufferData(GL_ARRAY_BUFFER, - mesh->n_vertices * sizeof(float) * 2, // Two components per uv - mesh->uvs, GL_STATIC_DRAW); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elements_vbo_[eye]); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh->n_indices * sizeof(int), - mesh->indices, GL_STATIC_DRAW); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - CheckGlError("OpenGlEs2DistortionRenderer::SetMesh"); - elements_count_[eye] = mesh->n_indices; - } - - /* - * Modifies the OpenGL global state. In particular: - * - glGet(GL_VIEWPORT) - * - glGet(GL_FRAMEBUFFER_BINDING) - * - glIsEnabled(GL_SCISSOR_TEST) - * - glIsEnabled(GL_CULL_FACE) - * - glGet(GL_CLEAR_COLOR_VALUE) - * - glGet(GL_CURRENT_PROGRAM) - * - glGet(GL_SCISSOR_BOX) - * - glGet(GL_ACTIVE_TEXTURE+i) - * - glGet(GL_ARRAY_BUFFER_BINDING) - * - glGet(GL_ELEMENT_ARRAY_BUFFER_BINDING) - */ - void RenderEyeToDisplay( - uint64_t target, - int x, - int y, - int width, - int height, - const CardboardEyeTextureDescription* left_eye, - const CardboardEyeTextureDescription* right_eye) override { - if (elements_count_[0] == 0 || elements_count_[1] == 0) { - CARDBOARD_LOGE( - "Distortion mesh is empty. OpenGlEs2DistortionRenderer::SetMesh was " - "not called yet."); - return; - } - - glViewport(x, y, width, height); - glBindFramebuffer(GL_FRAMEBUFFER, static_cast<GLuint>(target)); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_CULL_FACE); - glClearColor(.0f, .0f, .0f, 1.0f); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - - glUseProgram(program_); - - glEnable(GL_SCISSOR_TEST); - glScissor(x, y, width / 2, height); - RenderDistortionMesh(left_eye, kLeft); - - glScissor(x + width / 2, y, width / 2, height); - RenderDistortionMesh(right_eye, kRight); - - // Active GL_TEXTURE0 effectively enables the first texture that is - // deactiviated by the DistortionRenderer. Binding array buffer and element - // array buffer to the reserved value zero effectively unbinds the buffer - // objects that are previously bound by the DistortionRenderer. - glActiveTexture(GL_TEXTURE0); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - - // Disable scissor test. - glDisable(GL_SCISSOR_TEST); - CheckGlError("OpenGlEs2DistortionRenderer::RenderEyeToDisplay"); - } - - private: - /* - * Modifies the OpenGL global state. In particular: - * - glGet(GL_ARRAY_BUFFER_BINDING) - * - glGet(GL_ELEMENT_ARRAY_BUFFER_BINDING) - * - glGetVertexAttrib(i, GL_VERTEX_ATTRIB_*) - * - glGetVertextAttrib(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED) - * - glGet(GL_ACTIVE_TEXTURE+i) - * - glGet(GL_TEXTURE_BINDING_2D) - * - glGetUniform(program, location) - * - glGet(GL_ARRAY_BUFFER_BINDING) - * - glGet(GL_ELEMENT_ARRAY_BUFFER_BINDING) - */ - void RenderDistortionMesh( - const CardboardEyeTextureDescription* eye_description, - CardboardEye eye) const { - glBindBuffer(GL_ARRAY_BUFFER, vertices_vbo_[eye]); - glVertexAttribPointer( - attrib_pos_, - 2, // 2 components per vertex - GL_FLOAT, false, - 0, // Stride and offset 0, as we are using different vbos. - 0); - glEnableVertexAttribArray(attrib_pos_); - - glBindBuffer(GL_ARRAY_BUFFER, uvs_vbo_[eye]); - glVertexAttribPointer(attrib_tex_, - 2, // 2 components per uv - GL_FLOAT, false, 0, 0); - glEnableVertexAttribArray(attrib_tex_); - - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(eye_description->texture)); - - glUniform2f(uniform_start_, eye_description->left_u, - eye_description->bottom_v); - glUniform2f(uniform_end_, eye_description->right_u, eye_description->top_v); - - // Draw with indices - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elements_vbo_[eye]); - glDrawElements(GL_TRIANGLE_STRIP, elements_count_[eye], GL_UNSIGNED_INT, 0); - CheckGlError("OpenGlEs2DistortionRenderer::RenderDistortionMesh"); - } - - std::array<GLuint, 2> vertices_vbo_; // One per eye. - std::array<GLuint, 2> uvs_vbo_; - std::array<GLuint, 2> elements_vbo_; - std::array<int, 2> elements_count_; - - GLuint program_; - GLuint attrib_pos_; - GLuint attrib_tex_; - GLuint uniform_start_; - GLuint uniform_end_; -}; - -} // namespace cardboard::rendering - -extern "C" { - -CardboardDistortionRenderer* CardboardOpenGlEs2DistortionRenderer_create() { - if (CARDBOARD_IS_NOT_INITIALIZED()) { - return nullptr; - } - return reinterpret_cast<CardboardDistortionRenderer*>( - new cardboard::rendering::OpenGlEs2DistortionRenderer()); -} - -} // extern "C"
diff --git a/third_party/cpu_features/BUILD.gn b/third_party/cpu_features/BUILD.gn new file mode 100644 index 0000000..5d0e12d --- /dev/null +++ b/third_party/cpu_features/BUILD.gn
@@ -0,0 +1,61 @@ +# Copyright 2023 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. + +config("cpu_features_config") { + cflags = [ "-Wno-unused-function" ] + defines = [ "STACK_LINE_READER_BUFFER_SIZE=1024" ] + include_dirs = [ "src/include" ] +} + +config("ndk_compat_headers") { + include_dirs = [ "src/ndk_compat" ] +} + +source_set("cpuinfo") { + sources = [ + "src/src/copy.inl", + "src/src/define_introspection.inl", + "src/src/define_introspection_and_hwcaps.inl", + "src/src/equals.inl", + "src/src/filesystem.c", + "src/src/hwcaps.c", + "src/src/stack_line_reader.c", + "src/src/string_view.c", + ] + if (current_cpu == "x64") { + sources += [ + "src/src/impl_x86__base_implementation.inl", + "src/src/impl_x86_freebsd.c", + "src/src/impl_x86_linux_or_android.c", + "src/src/impl_x86_macos.c", + "src/src/impl_x86_windows.c", + ] + } else if (current_cpu == "arm") { + sources += [ "src/src/impl_arm_linux_or_android.c" ] + } else if (current_cpu == "arm64") { + sources += [ "src/src/impl_aarch64_linux_or_android.c" ] + } else if (current_cpu == "mips") { + sources += [ "src/src/impl_mips_linux_or_android.c" ] + } else if (current_cpu == "ppc") { + sources += [ "src/src/impl_ppc_linux.c" ] + } else { + error("Missing definition for architecture: $current_cpu") + } + configs += [ ":cpu_features_config" ] +} + +source_set("ndk_compat") { + sources = [ + "src/ndk_compat/cpu-features.c", + "src/ndk_compat/cpu-features.h", + ] + configs += [ ":cpu_features_config" ] + public_configs = [ ":ndk_compat_headers" ] + deps = [ + ":cpuinfo", + ":filesystem", + ":stack_line_reader", + ":string_view", + ] +}
diff --git a/third_party/cpu_features/OWNERS b/third_party/cpu_features/OWNERS new file mode 100644 index 0000000..9719fdcb --- /dev/null +++ b/third_party/cpu_features/OWNERS
@@ -0,0 +1,3 @@ +prashanthsw@google.com +nellyv@google.com +kgong@google.com
diff --git a/third_party/cpu_features/README.chromium b/third_party/cpu_features/README.chromium new file mode 100644 index 0000000..b1a8ff7 --- /dev/null +++ b/third_party/cpu_features/README.chromium
@@ -0,0 +1,14 @@ +Name: cpu_features +Short Name: cpu_features +URL: https://github.com/google/cpu_features +Version: v0.8.0 +Date: 2023/05/17 +License: Apache 2.0 +License File: src/LICENSE +Security Critical: Yes + +Description: +cpu_features is a library to retrieve CPU features at runtime. It is used to +make decisions about performance optimization and features a drop-in replacement +for Android's cpu-features.h. It is Android's recommended replacement for libraries +that utilize cpu-features.h.
diff --git a/third_party/libvpx/BUILD.gn b/third_party/libvpx/BUILD.gn index c5aad48..94a97685 100644 --- a/third_party/libvpx/BUILD.gn +++ b/third_party/libvpx/BUILD.gn
@@ -31,6 +31,10 @@ } } else if (current_cpu == "arm64") { if (is_chromeos || is_mac) { + # This is necessary for CrOS and macOS as they reuse the Linux + # configuration, of which there are two (see the later definition of + # os_category). Windows is configured with highbd enabled in its arm64 + # path. cpu_arch_full = "arm64-highbd" } else { cpu_arch_full = current_cpu
diff --git a/third_party/nearby/BUILD.gn b/third_party/nearby/BUILD.gn index a59883d..be856aa 100644 --- a/third_party/nearby/BUILD.gn +++ b/third_party/nearby/BUILD.gn
@@ -789,10 +789,7 @@ ":nearby_include_config", ":nearby_defines", ] - sources = [ - "src/presence/presence_client.cc", - "src/presence/presence_service.cc", - ] + sources = [ "src/presence/presence_service.cc" ] public = [ "src/presence/presence_client.h", "src/presence/presence_service.h",
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index 32672a35..33a95cf 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 55750a0843e7c972fc9d4820b450a62b651eaa0b +Version: 9c09f325e0fc3c96791020f99d0ecaba8714b4d7 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/pthreadpool/BUILD.gn b/third_party/pthreadpool/BUILD.gn index 0e6212f..f2a6864 100644 --- a/third_party/pthreadpool/BUILD.gn +++ b/third_party/pthreadpool/BUILD.gn
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/config/android/config.gni") + config("pthreadpool_config") { include_dirs = [ "src/include", @@ -37,3 +39,36 @@ deps = [ "//third_party/fxdiv" ] } + +# This is a target that cannot depend on //base. +source_set("pthreadpool_standalone") { + public = [ "src/include/pthreadpool.h" ] + + sources = [ + "src/src/fastpath.c", + "src/src/memory.c", + "src/src/portable-api.c", + "src/src/threadpool-atomics.h", + "src/src/threadpool-common.h", + "src/src/threadpool-object.h", + "src/src/threadpool-utils.h", + ] + + if (is_win) { + sources += [ "src/src/windows.c" ] + } else { + sources += [ "src/src/pthreads.c" ] + } + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_disable" ] + + public_configs = [ ":pthreadpool_config" ] + + deps = [ "//third_party/fxdiv" ] +}
diff --git a/third_party/rust/Cargo.toml b/third_party/rust/Cargo.toml index d1f6706..a4c9edf 100644 --- a/third_party/rust/Cargo.toml +++ b/third_party/rust/Cargo.toml
@@ -51,7 +51,6 @@ [dependencies.rustversion] version = "1" -build-script-outputs = ["version.rs"] [dependencies.serde_json_lenient] version = "0.1" @@ -67,7 +66,6 @@ [dependencies.unicode-linebreak] version = "0.1" -build-script-outputs = ["tables.rs"] [patch.crates-io.aho-corasick_v0_7] path = "aho_corasick/v0_7/crate" package = "aho-corasick"
diff --git a/third_party/tflite/BUILD.gn b/third_party/tflite/BUILD.gn index 649277a..5c2b41de 100644 --- a/third_party/tflite/BUILD.gn +++ b/third_party/tflite/BUILD.gn
@@ -2,6 +2,7 @@ # 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/chromeos/ui_mode.gni") import("//build/config/sanitizers/sanitizers.gni") import("//third_party/cpuinfo/cpuinfo.gni") @@ -279,6 +280,155 @@ visibility = [ ":*" ] } +# This is a target that cannot depend on //base. +source_set("tflite_kernels_standalone") { + sources = [ + "src/tensorflow/lite/kernels/activations.cc", + "src/tensorflow/lite/kernels/add.cc", + "src/tensorflow/lite/kernels/add_n.cc", + "src/tensorflow/lite/kernels/arg_min_max.cc", + "src/tensorflow/lite/kernels/assign_variable.cc", + "src/tensorflow/lite/kernels/basic_rnn.cc", + "src/tensorflow/lite/kernels/batch_matmul.cc", + "src/tensorflow/lite/kernels/batch_to_space_nd.cc", + "src/tensorflow/lite/kernels/bidirectional_sequence_lstm.cc", + "src/tensorflow/lite/kernels/bidirectional_sequence_rnn.cc", + "src/tensorflow/lite/kernels/builtin_op_kernels.h", + "src/tensorflow/lite/kernels/cast.cc", + "src/tensorflow/lite/kernels/ceil.cc", + "src/tensorflow/lite/kernels/comparisons.cc", + "src/tensorflow/lite/kernels/concatenation.cc", + "src/tensorflow/lite/kernels/conv.cc", + "src/tensorflow/lite/kernels/cpu_backend_context.cc", + "src/tensorflow/lite/kernels/cpu_backend_gemm_custom_gemv.h", + "src/tensorflow/lite/kernels/cpu_backend_gemm_eigen.cc", + "src/tensorflow/lite/kernels/cpu_backend_gemm_eigen.h", + "src/tensorflow/lite/kernels/cpu_backend_gemm_ruy.h", + "src/tensorflow/lite/kernels/cumsum.cc", + "src/tensorflow/lite/kernels/densify.cc", + "src/tensorflow/lite/kernels/depth_to_space.cc", + "src/tensorflow/lite/kernels/depthwise_conv.cc", + "src/tensorflow/lite/kernels/dequantize.cc", + "src/tensorflow/lite/kernels/dequantize.h", + "src/tensorflow/lite/kernels/div.cc", + "src/tensorflow/lite/kernels/eigen_support.cc", + "src/tensorflow/lite/kernels/eigen_support.h", + "src/tensorflow/lite/kernels/elementwise.cc", + "src/tensorflow/lite/kernels/embedding_lookup.cc", + "src/tensorflow/lite/kernels/embedding_lookup_sparse.cc", + "src/tensorflow/lite/kernels/exp.cc", + "src/tensorflow/lite/kernels/expand_dims.cc", + "src/tensorflow/lite/kernels/fake_quant.cc", + "src/tensorflow/lite/kernels/fill.cc", + "src/tensorflow/lite/kernels/floor.cc", + "src/tensorflow/lite/kernels/floor_div.cc", + "src/tensorflow/lite/kernels/floor_mod.cc", + "src/tensorflow/lite/kernels/fully_connected.cc", + "src/tensorflow/lite/kernels/gather.cc", + "src/tensorflow/lite/kernels/gather_nd.cc", + "src/tensorflow/lite/kernels/hashtable_lookup.cc", + "src/tensorflow/lite/kernels/if.cc", + "src/tensorflow/lite/kernels/internal/optimized/4bit/fully_connected_reference.cc", + "src/tensorflow/lite/kernels/internal/optimized/4bit/fully_connected_reference.h", + "src/tensorflow/lite/kernels/internal/optimized/4bit/fully_connected_reference_impl.h", + "src/tensorflow/lite/kernels/kernel_util.cc", + "src/tensorflow/lite/kernels/kernel_util.h", + "src/tensorflow/lite/kernels/l2norm.cc", + "src/tensorflow/lite/kernels/local_response_norm.cc", + "src/tensorflow/lite/kernels/logical.cc", + "src/tensorflow/lite/kernels/lsh_projection.cc", + "src/tensorflow/lite/kernels/lstm.cc", + "src/tensorflow/lite/kernels/lstm_eval.cc", + "src/tensorflow/lite/kernels/lstm_eval.h", + "src/tensorflow/lite/kernels/lstm_shared.h", + "src/tensorflow/lite/kernels/matrix_diag.cc", + "src/tensorflow/lite/kernels/matrix_set_diag.cc", + "src/tensorflow/lite/kernels/maximum_minimum.cc", + "src/tensorflow/lite/kernels/mirror_pad.cc", + "src/tensorflow/lite/kernels/mul.cc", + "src/tensorflow/lite/kernels/neg.cc", + "src/tensorflow/lite/kernels/non_max_suppression.cc", + "src/tensorflow/lite/kernels/numeric_verify.cc", + "src/tensorflow/lite/kernels/one_hot.cc", + "src/tensorflow/lite/kernels/pack.cc", + "src/tensorflow/lite/kernels/pad.cc", + "src/tensorflow/lite/kernels/padding.h", + "src/tensorflow/lite/kernels/pooling.cc", + "src/tensorflow/lite/kernels/pow.cc", + "src/tensorflow/lite/kernels/quantize.cc", + "src/tensorflow/lite/kernels/range.cc", + "src/tensorflow/lite/kernels/rank.cc", + "src/tensorflow/lite/kernels/read_variable.cc", + "src/tensorflow/lite/kernels/reduce.cc", + "src/tensorflow/lite/kernels/reshape.cc", + "src/tensorflow/lite/kernels/resize_bilinear.cc", + "src/tensorflow/lite/kernels/resize_nearest_neighbor.cc", + "src/tensorflow/lite/kernels/reverse.cc", + "src/tensorflow/lite/kernels/reverse_sequence.cc", + "src/tensorflow/lite/kernels/rfft2d.cc", + "src/tensorflow/lite/kernels/round.cc", + "src/tensorflow/lite/kernels/scatter_nd.cc", + "src/tensorflow/lite/kernels/segment_sum.cc", + "src/tensorflow/lite/kernels/select.cc", + "src/tensorflow/lite/kernels/shape.cc", + "src/tensorflow/lite/kernels/skip_gram.cc", + "src/tensorflow/lite/kernels/slice.cc", + "src/tensorflow/lite/kernels/space_to_batch_nd.cc", + "src/tensorflow/lite/kernels/space_to_depth.cc", + "src/tensorflow/lite/kernels/sparse_to_dense.cc", + "src/tensorflow/lite/kernels/split.cc", + "src/tensorflow/lite/kernels/split_v.cc", + "src/tensorflow/lite/kernels/squared_difference.cc", + "src/tensorflow/lite/kernels/squeeze.cc", + "src/tensorflow/lite/kernels/strided_slice.cc", + "src/tensorflow/lite/kernels/sub.cc", + "src/tensorflow/lite/kernels/svdf.cc", + "src/tensorflow/lite/kernels/tile.cc", + "src/tensorflow/lite/kernels/topk_v2.cc", + "src/tensorflow/lite/kernels/transpose.cc", + "src/tensorflow/lite/kernels/transpose_conv.cc", + "src/tensorflow/lite/kernels/unidirectional_sequence_lstm.cc", + "src/tensorflow/lite/kernels/unidirectional_sequence_rnn.cc", + "src/tensorflow/lite/kernels/unique.cc", + "src/tensorflow/lite/kernels/unpack.cc", + "src/tensorflow/lite/kernels/where.cc", + "src/tensorflow/lite/kernels/while.cc", + "src/tensorflow/lite/kernels/zeros_like.cc", + ] + + if (!build_tflite_with_ruy) { + sources += [ "src/tensorflow/lite/kernels/cpu_backend_gemm_gemmlowp.h" ] + } + + deps = [ + ":fft2d_deps", + ":tflite_kernel_common_headers", + ":tflite_kernel_internals", + ":tflite_public_headers", + "//third_party/abseil-cpp:absl", + "//third_party/farmhash", + "//third_party/flatbuffers", + "//third_party/fp16", + "//third_party/gemmlowp", + "//third_party/neon_2_sse", + "//third_party/pthreadpool:pthreadpool_standalone", + "//third_party/ruy", + ] + + if (use_cpuinfo) { + defines = [ "TFLITE_HAVE_CPUINFO" ] + deps += [ "//third_party/cpuinfo" ] + include_dirs = [ "//third_party/cpuinfo/src" ] + } + + configs += [ + ":tflite_config", + ":tflite_flags", + "//third_party/eigen3:eigen_includes", + ] + visibility = [ ":*" ] +} + source_set("tflite_kernels") { sources = [ "src/tensorflow/lite/kernels/activations.cc", @@ -429,6 +579,178 @@ # TODO(crbug.com/1147996): Update to a component build. Will require updating the # tflite version. +# This is a target that cannot depend on //base. +static_library("tflite_standalone") { + sources = [ + "src/tensorflow/lite/acceleration/configuration/flatbuffer_to_proto.cc", + "src/tensorflow/lite/acceleration/configuration/flatbuffer_to_proto.h", + "src/tensorflow/lite/acceleration/configuration/proto_to_flatbuffer.cc", + "src/tensorflow/lite/acceleration/configuration/proto_to_flatbuffer.h", + "src/tensorflow/lite/allocation.cc", + "src/tensorflow/lite/arena_planner.cc", + "src/tensorflow/lite/builtin_ops.h", + "src/tensorflow/lite/c/common_internal.cc", + "src/tensorflow/lite/c/common_internal.h", + "src/tensorflow/lite/core/acceleration/configuration/delegate_registry.cc", + "src/tensorflow/lite/core/acceleration/configuration/delegate_registry.h", + "src/tensorflow/lite/core/api/error_reporter.cc", + "src/tensorflow/lite/core/api/error_reporter.h", + "src/tensorflow/lite/core/api/flatbuffer_conversions.cc", + "src/tensorflow/lite/core/api/flatbuffer_conversions.h", + "src/tensorflow/lite/core/api/op_resolver.cc", + "src/tensorflow/lite/core/api/profiler.h", + "src/tensorflow/lite/core/api/tensor_utils.cc", + "src/tensorflow/lite/core/api/tensor_utils.h", + "src/tensorflow/lite/core/async/async_kernel_internal.h", + "src/tensorflow/lite/core/async/async_signature_runner.cc", + "src/tensorflow/lite/core/async/async_signature_runner.h", + "src/tensorflow/lite/core/async/async_subgraph.cc", + "src/tensorflow/lite/core/async/async_subgraph.h", + "src/tensorflow/lite/core/async/task_internal.cc", + "src/tensorflow/lite/core/async/task_internal.h", + "src/tensorflow/lite/core/c/common.cc", + "src/tensorflow/lite/core/c/common.h", + "src/tensorflow/lite/core/interpreter.cc", + "src/tensorflow/lite/core/interpreter_builder.cc", + "src/tensorflow/lite/core/interpreter_experimental.cc", + "src/tensorflow/lite/core/model_builder.cc", + "src/tensorflow/lite/core/model_builder.h", + "src/tensorflow/lite/core/subgraph.cc", + "src/tensorflow/lite/core/tools/verifier.cc", + "src/tensorflow/lite/core/tools/verifier_internal.cc", + "src/tensorflow/lite/core/tools/verifier_internal.h", + "src/tensorflow/lite/delegates/interpreter_utils.cc", + "src/tensorflow/lite/delegates/interpreter_utils.h", + "src/tensorflow/lite/delegates/nnapi/nnapi_delegate.h", + "src/tensorflow/lite/delegates/nnapi/nnapi_delegate_disabled.cc", + "src/tensorflow/lite/experimental/acceleration/mini_benchmark/mini_benchmark.cc", + "src/tensorflow/lite/experimental/acceleration/mini_benchmark/mini_benchmark.h", + "src/tensorflow/lite/experimental/remat/metadata_util.cc", + "src/tensorflow/lite/experimental/remat/metadata_util.h", + "src/tensorflow/lite/experimental/resource/initialization_status.cc", + "src/tensorflow/lite/experimental/resource/initialization_status.h", + "src/tensorflow/lite/experimental/resource/lookup_interfaces.h", + "src/tensorflow/lite/experimental/resource/lookup_util.h", + "src/tensorflow/lite/experimental/resource/resource_base.h", + "src/tensorflow/lite/experimental/resource/resource_variable.cc", + "src/tensorflow/lite/experimental/resource/static_hashtable.cc", + "src/tensorflow/lite/experimental/resource/static_hashtable.h", + "src/tensorflow/lite/external_cpu_backend_context.cc", + "src/tensorflow/lite/graph_info.cc", + "src/tensorflow/lite/kernels/internal/portable_tensor_utils.cc", + "src/tensorflow/lite/memory_planner.h", + "src/tensorflow/lite/minimal_logging.cc", + "src/tensorflow/lite/minimal_logging.h", + "src/tensorflow/lite/model.h", + "src/tensorflow/lite/mutable_op_resolver.cc", + "src/tensorflow/lite/nnapi/NeuralNetworksTypes.h", + "src/tensorflow/lite/nnapi/nnapi_implementation.h", + "src/tensorflow/lite/nnapi/nnapi_implementation_disabled.cc", + "src/tensorflow/lite/optional_debug_tools.cc", + "src/tensorflow/lite/profiling/memory_info.cc", + "src/tensorflow/lite/profiling/memory_info.h", + "src/tensorflow/lite/profiling/platform_profiler.cc", + "src/tensorflow/lite/profiling/platform_profiler.h", + "src/tensorflow/lite/profiling/root_profiler.cc", + "src/tensorflow/lite/profiling/root_profiler.h", + "src/tensorflow/lite/profiling/telemetry/profiler.cc", + "src/tensorflow/lite/profiling/telemetry/profiler.h", + "src/tensorflow/lite/profiling/telemetry/telemetry.cc", + "src/tensorflow/lite/profiling/telemetry/telemetry.h", + "src/tensorflow/lite/profiling/time.cc", + "src/tensorflow/lite/profiling/time.h", + "src/tensorflow/lite/schema/schema_utils.cc", + "src/tensorflow/lite/signature_runner.cc", + "src/tensorflow/lite/simple_memory_arena.cc", + "src/tensorflow/lite/simple_memory_arena.h", + "src/tensorflow/lite/stderr_reporter.cc", + "src/tensorflow/lite/stderr_reporter.h", + "src/tensorflow/lite/string_util.cc", + "src/tensorflow/lite/tflite_with_xnnpack_optional.cc", + "src/tensorflow/lite/tflite_with_xnnpack_optional.h", + "src/tensorflow/lite/tools/command_line_flags.h", + "src/tensorflow/lite/tools/delegates/delegate_provider.h", + "src/tensorflow/lite/tools/logging.h", + "src/tensorflow/lite/tools/tool_params.h", + "src/tensorflow/lite/type_to_tflitetype.h", + "src/tensorflow/lite/util.cc", + "src/tensorflow/lite/version.h", + ] + + if (build_tflite_with_xnnpack) { + sources += [ + "src/tensorflow/lite/delegates/xnnpack/quantization_util.cc", + "src/tensorflow/lite/delegates/xnnpack/quantization_util.h", + "src/tensorflow/lite/delegates/xnnpack/xnnpack_delegate.cc", + "src/tensorflow/lite/delegates/xnnpack/xnnpack_delegate.h", + ] + } + + if (is_win) { + sources += [ "src/tensorflow/lite/mmap_allocation_disabled.cc" ] + } else { + sources += [ "src/tensorflow/lite/mmap_allocation.cc" ] + } + + if (is_ios) { + sources += [ + "src/tensorflow/lite/minimal_logging_ios.cc", + "src/tensorflow/lite/profiling/signpost_profiler.h", + "src/tensorflow/lite/profiling/signpost_profiler.mm", + ] + } else if (is_android) { + sources += [ + "src/tensorflow/lite/minimal_logging_android.cc", + "src/tensorflow/lite/profiling/atrace_profiler.cc", + "src/tensorflow/lite/profiling/atrace_profiler.h", + ] + } else { + sources += [ "src/tensorflow/lite/minimal_logging_default.cc" ] + } + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } + + deps = [ + "//third_party/abseil-cpp:absl", + "//third_party/farmhash", + "//third_party/fft2d", + "//third_party/fp16", + "//third_party/gemmlowp", + "//third_party/neon_2_sse", + "//third_party/pthreadpool:pthreadpool_standalone", + "//third_party/ruy", + ] + + if (build_tflite_with_xnnpack) { + deps += [ + ":tflite_kernel_internals", + "//third_party/cpuinfo", + "//third_party/xnnpack:xnnpack_standalone", + ] + } + + public_deps = [ + ":tflite-config-proto", + ":tflite_kernel_common_headers", + ":tflite_kernels_standalone", + ":tflite_public_headers", + "//third_party/flatbuffers", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ + "//build/config/compiler:no_chromium_code", + "//third_party/eigen3:eigen_includes", + ":tflite_flags", + ] + + public_configs = [ ":tflite_config" ] +} + +# TODO(crbug.com/1147996): Update to a component build. Will require updating the +# tflite version. static_library("tflite") { sources = [ "src/tensorflow/lite/acceleration/configuration/flatbuffer_to_proto.cc",
diff --git a/third_party/xnnpack/BUILD.gn b/third_party/xnnpack/BUILD.gn index 623c47b..ad26cb1 100644 --- a/third_party/xnnpack/BUILD.gn +++ b/third_party/xnnpack/BUILD.gn
@@ -14,6 +14,8 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +import("//build/config/android/config.gni") + config("xnnpack_config") { include_dirs = [ "//third_party/pthreadpool/src/include", @@ -124,6 +126,94 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("xnnpack_standalone") { + public = [ "src/include/xnnpack.h" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + sources = [ + "src/src/allocator.c", + "src/src/argmaxpool-config.c", + "src/src/avgpool-config.c", + "src/src/binary-elementwise-config.c", + "src/src/cache.c", + "src/src/conv-hwc2chw-config.c", + "src/src/dwconv-config.c", + "src/src/dwconv2d-chw-config.c", + "src/src/gavgpool-config.c", + "src/src/gavgpool-cw-config.c", + "src/src/gemm-config.c", + "src/src/hardware-config.c", + "src/src/ibilinear-chw-config.c", + "src/src/ibilinear-config.c", + "src/src/indirection.c", + "src/src/init.c", + "src/src/log.c", + "src/src/lut32norm-config.c", + "src/src/maxpool-config.c", + "src/src/memory-planner.c", + "src/src/memory.c", + "src/src/microkernel-utils.c", + "src/src/microparams-init.c", + "src/src/mutex.c", + "src/src/normalization.c", + "src/src/operator-delete.c", + "src/src/operator-run.c", + "src/src/operator-utils.c", + "src/src/packing.c", + "src/src/params.c", + "src/src/pavgpool-config.c", + "src/src/prelu-config.c", + "src/src/raddstoreexpminusmax-config.c", + "src/src/rmax-config.c", + "src/src/runtime.c", + "src/src/spmm-config.c", + "src/src/subgraph.c", + "src/src/tensor.c", + "src/src/transpose-config.c", + "src/src/unary-elementwise-config.c", + "src/src/unpool-config.c", + "src/src/vmulcaddc-config.c", + "src/src/x8-lut-config.c", + "src/src/xx-fill-config.c", + "src/src/xx-pad-config.c", + "src/src/zip-config.c", + ] + + deps = [ + ":amalgam_avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vbmi_standalone", + ":amalgam_avx512f-avx512cd-avx512bw-avx512dq-avx512vl_standalone", + ":amalgam_avx512f_standalone", + ":amalgam_avx_standalone", + ":amalgam_f16c-fma-avx2_standalone", + ":amalgam_f16c-fma_standalone", + ":amalgam_f16c_standalone", + ":amalgam_sse2_standalone", + ":amalgam_sse4.1_standalone", + ":amalgam_ssse3_standalone", + ":amalgam_standalone", + ":amalgam_xop_standalone", + ":enums_standalone", + ":jit_standalone", + ":operators_standalone", + ":subgraph_standalone", + ":tables_standalone", + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam") { cflags = [] @@ -143,6 +233,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_standalone") { + cflags = [] + + sources = [ "src/src/amalgam/gen/scalar.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_avx") { cflags = [ "-mavx" ] @@ -162,6 +276,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_avx_standalone") { + cflags = [ "-mavx" ] + + sources = [ "src/src/amalgam/gen/avx.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_avx512f") { cflags = [ "-mavx512f" ] @@ -181,6 +319,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_avx512f_standalone") { + cflags = [ "-mavx512f" ] + + sources = [ "src/src/amalgam/gen/avx512f.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_avx512f-avx512cd-avx512bw-avx512dq-avx512vl") { cflags = [ "-mavx512bw", @@ -206,6 +368,36 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_avx512f-avx512cd-avx512bw-avx512dq-avx512vl_standalone") { + cflags = [ + "-mavx512bw", + "-mavx512cd", + "-mavx512dq", + "-mavx512f", + "-mavx512vl", + ] + + sources = [ "src/src/amalgam/gen/avx512skx.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vbmi") { cflags = [ "-mavx512bw", @@ -232,6 +424,38 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set( + "amalgam_avx512f-avx512cd-avx512bw-avx512dq-avx512vl-avx512vbmi_standalone") { + cflags = [ + "-mavx512bw", + "-mavx512cd", + "-mavx512dq", + "-mavx512f", + "-mavx512vbmi", + "-mavx512vl", + ] + + sources = [ "src/src/amalgam/gen/avx512vbmi.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_f16c") { cflags = [ "-mf16c" ] @@ -251,6 +475,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_f16c_standalone") { + cflags = [ "-mf16c" ] + + sources = [ "src/src/amalgam/gen/f16c.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_f16c-fma") { cflags = [ "-mf16c", @@ -273,6 +521,33 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_f16c-fma_standalone") { + cflags = [ + "-mf16c", + "-mfma", + ] + + sources = [ "src/src/amalgam/gen/fma3.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_f16c-fma-avx2") { cflags = [ "-mavx2", @@ -296,6 +571,34 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_f16c-fma-avx2_standalone") { + cflags = [ + "-mavx2", + "-mf16c", + "-mfma", + ] + + sources = [ "src/src/amalgam/gen/avx2.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_sse2") { cflags = [ "-msse2" ] @@ -318,6 +621,33 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_sse2_standalone") { + cflags = [ "-msse2" ] + + sources = [ + "src/src/amalgam/gen/sse.c", + "src/src/amalgam/gen/sse2.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_sse4.1") { cflags = [ "-msse4.1" ] @@ -337,6 +667,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_sse4.1_standalone") { + cflags = [ "-msse4.1" ] + + sources = [ "src/src/amalgam/gen/sse41.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_ssse3") { cflags = [ "-mssse3" ] @@ -356,6 +710,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_ssse3_standalone") { + cflags = [ "-mssse3" ] + + sources = [ "src/src/amalgam/gen/ssse3.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("amalgam_xop") { cflags = [ "-mxop" ] @@ -375,6 +753,30 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("amalgam_xop_standalone") { + cflags = [ "-mxop" ] + + sources = [ "src/src/amalgam/gen/xop.c" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("enums") { cflags = [] @@ -399,6 +801,35 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("enums_standalone") { + cflags = [] + + sources = [ + "src/src/enums/datatype-strings.c", + "src/src/enums/microkernel-type.c", + "src/src/enums/node-type.c", + "src/src/enums/operator-type.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("jit") { cflags = [] @@ -422,6 +853,34 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("jit_standalone") { + cflags = [] + + sources = [ + "src/src/jit/aarch32-assembler.cc", + "src/src/jit/aarch64-assembler.cc", + "src/src/jit/assembler.cc", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("operators") { cflags = [] @@ -465,6 +924,54 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("operators_standalone") { + cflags = [] + + sources = [ + "src/src/operators/argmax-pooling-nhwc.c", + "src/src/operators/average-pooling-nhwc.c", + "src/src/operators/binary-elementwise-nd.c", + "src/src/operators/channel-shuffle-nc.c", + "src/src/operators/constant-pad-nd.c", + "src/src/operators/convolution-nchw.c", + "src/src/operators/convolution-nhwc.c", + "src/src/operators/deconvolution-nhwc.c", + "src/src/operators/dynamic-fully-connected-nc.c", + "src/src/operators/fully-connected-nc.c", + "src/src/operators/global-average-pooling-ncw.c", + "src/src/operators/global-average-pooling-nwc.c", + "src/src/operators/lut-elementwise-nc.c", + "src/src/operators/max-pooling-nhwc.c", + "src/src/operators/post-operation.c", + "src/src/operators/prelu-nc.c", + "src/src/operators/resize-bilinear-nchw.c", + "src/src/operators/resize-bilinear-nhwc.c", + "src/src/operators/slice-nd.c", + "src/src/operators/softmax-nc.c", + "src/src/operators/transpose-nd.c", + "src/src/operators/unary-elementwise-nc.c", + "src/src/operators/unpooling-nhwc.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("subgraph") { cflags = [] @@ -529,6 +1036,75 @@ public_configs = [ ":xnnpack_config" ] } +# This is a target that cannot depend on //base. +source_set("subgraph_standalone") { + cflags = [] + + sources = [ + "src/src/subgraph/abs.c", + "src/src/subgraph/add2.c", + "src/src/subgraph/argmax-pooling-2d.c", + "src/src/subgraph/average-pooling-2d.c", + "src/src/subgraph/bankers-rounding.c", + "src/src/subgraph/ceiling.c", + "src/src/subgraph/clamp.c", + "src/src/subgraph/concatenate.c", + "src/src/subgraph/convert.c", + "src/src/subgraph/convolution-2d.c", + "src/src/subgraph/copy.c", + "src/src/subgraph/deconvolution-2d.c", + "src/src/subgraph/depth-to-space.c", + "src/src/subgraph/depthwise-convolution-2d.c", + "src/src/subgraph/divide.c", + "src/src/subgraph/elu.c", + "src/src/subgraph/even-split.c", + "src/src/subgraph/floor.c", + "src/src/subgraph/fully-connected.c", + "src/src/subgraph/global-average-pooling.c", + "src/src/subgraph/global-sum-pooling.c", + "src/src/subgraph/hardswish.c", + "src/src/subgraph/leaky-relu.c", + "src/src/subgraph/max-pooling-2d.c", + "src/src/subgraph/maximum2.c", + "src/src/subgraph/minimum2.c", + "src/src/subgraph/multiply2.c", + "src/src/subgraph/negate.c", + "src/src/subgraph/prelu.c", + "src/src/subgraph/sigmoid.c", + "src/src/subgraph/softmax.c", + "src/src/subgraph/space-to-depth-2d.c", + "src/src/subgraph/square-root.c", + "src/src/subgraph/square.c", + "src/src/subgraph/squared-difference.c", + "src/src/subgraph/static-constant-pad.c", + "src/src/subgraph/static-reshape.c", + "src/src/subgraph/static-resize-bilinear-2d.c", + "src/src/subgraph/static-slice.c", + "src/src/subgraph/static-transpose.c", + "src/src/subgraph/subtract.c", + "src/src/subgraph/tanh.c", + "src/src/subgraph/unpooling-2d.c", + "src/src/subgraph/validation.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} + source_set("tables") { cflags = [] @@ -557,3 +1133,37 @@ public_configs = [ ":xnnpack_config" ] } + +# This is a target that cannot depend on //base. +source_set("tables_standalone") { + cflags = [] + + sources = [ + "src/src/tables/exp2-k-over-2048.c", + "src/src/tables/exp2-k-over-64.c", + "src/src/tables/exp2minus-k-over-16.c", + "src/src/tables/exp2minus-k-over-2048.c", + "src/src/tables/exp2minus-k-over-32.c", + "src/src/tables/exp2minus-k-over-4.c", + "src/src/tables/exp2minus-k-over-64.c", + "src/src/tables/exp2minus-k-over-8.c", + "src/src/tables/vlog.c", + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +}
diff --git a/third_party/xnnpack/generate_build_gn.py b/third_party/xnnpack/generate_build_gn.py index 634162d9..26a1f1c5 100644 --- a/third_party/xnnpack/generate_build_gn.py +++ b/third_party/xnnpack/generate_build_gn.py
@@ -51,6 +51,8 @@ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +import("//build/config/android/config.gni") + config("xnnpack_config") { include_dirs = [ "//third_party/pthreadpool/src/include", @@ -102,6 +104,33 @@ public_configs = [ ":xnnpack_config" ] } + +# This is a target that cannot depend on //base. +source_set("xnnpack_standalone") { + public = [ "src/include/xnnpack.h" ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + sources = [ +%SRCS% + ] + + deps = [ +%STANDALONE_TARGETS%, + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} '''.strip() _TARGET_TMPL = ''' @@ -127,6 +156,34 @@ public_configs = [ ":xnnpack_config" ] } + +# This is a target that cannot depend on //base. +source_set("%TARGET_NAME%_standalone") { + cflags = [ +%ARGS% + ] + + sources = [ +%SRCS% + ] + + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + configs += [ "//build/config/sanitizers:cfi_icall_generalize_pointers" ] + + deps = [ + "//third_party/cpuinfo", + "//third_party/fp16", + "//third_party/fxdiv", + "//third_party/pthreadpool:pthreadpool_standalone", + ] + + public_configs = [ ":xnnpack_config" ] + + if (!(is_android && use_order_profiling)) { + assert_no_deps = [ "//base" ] + } +} '''.strip() # This is the latest version of the Android NDK that is compatible with @@ -353,6 +410,9 @@ target = target.replace('%TARGETS%', ',\n'.join([ ' ":%s"' % t for t in sorted(other_targets) ])) + target = target.replace('%STANDALONE_TARGETS%', ',\n'.join([ + ' ":%s_standalone"' % t for t in sorted(other_targets) + ])) return target def main():
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index 2cd48c7..2919d39 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -217,8 +217,8 @@ def LoadAndPostProcessDeltaSizeInfo(path, file_obj=None): """Returns a tuple of SizeInfos for the given |path|.""" logging.debug('Loading results from: %s', path) - before_size_info, after_size_info = file_format.LoadDeltaSizeInfo( - path, file_obj=file_obj) + before_size_info, after_size_info, _, _ = (file_format.LoadDeltaSizeInfo( + path, file_obj=file_obj)) logging.info('Normalizing symbol names') _NormalizeNames(before_size_info.raw_symbols) _NormalizeNames(after_size_info.raw_symbols)
diff --git a/tools/binary_size/libsupersize/diff.py b/tools/binary_size/libsupersize/diff.py index 7a35006..e1a542b 100644 --- a/tools/binary_size/libsupersize/diff.py +++ b/tools/binary_size/libsupersize/diff.py
@@ -163,7 +163,9 @@ is_sparse = before.is_sparse and after.is_sparse symbol_diff = _DiffSymbolGroups(containers_diff, before.raw_symbols, after.raw_symbols, is_sparse) - ret = models.DeltaSizeInfo(before, after, containers_diff, symbol_diff) + removed_sources, added_sources = symbol_diff.GetEntireAddOrRemoveSources() + ret = models.DeltaSizeInfo(before, after, containers_diff, symbol_diff, + removed_sources, added_sources) if sort: syms = ret.symbols # Triggers clustering.
diff --git a/tools/binary_size/libsupersize/file_format.py b/tools/binary_size/libsupersize/file_format.py index b8ddcca..8a764d8 100644 --- a/tools/binary_size/libsupersize/file_format.py +++ b/tools/binary_size/libsupersize/file_format.py
@@ -620,6 +620,24 @@ yield fz +def _SaveCompressedStringList(string_list, file_obj): + with _OpenGzipForWrite('', file_obj=file_obj) as f: + w = _Writer(f) + w.WriteLine(str(len(string_list))) + for s in string_list: + w.WriteLine(s) + + +def _LoadCompressedStringList(file_obj, size): + bytesio = io.BytesIO() + bytesio.write(file_obj.read(size)) + bytesio.seek(0) + with gzip.GzipFile(filename='', fileobj=bytesio) as f: + toks = f.read().decode('utf-8', errors='surrogatepass').splitlines() + assert int(toks[0]) == len(toks) - 1 + return toks[1:] + + def SaveSizeInfo(size_info, path, file_obj=None, @@ -683,6 +701,17 @@ include_padding=True, sparse_symbols=before_symbols) + removed_sources_file = None + if delta_size_info.removed_sources: + removed_sources_file = io.BytesIO() + _SaveCompressedStringList(delta_size_info.removed_sources, + removed_sources_file) + + added_sources_file = None + if delta_size_info.added_sources: + added_sources_file = io.BytesIO() + _SaveCompressedStringList(delta_size_info.added_sources, added_sources_file) + w = _Writer(file_obj) w.WriteBytes(_COMMON_HEADER + _SIZEDIFF_HEADER) # JSON header fields @@ -690,11 +719,21 @@ 'version': _SIZEDIFF_VERSION, 'before_length': before_size_file.tell(), } + if removed_sources_file: + fields['removed_sources_length'] = removed_sources_file.tell() + if added_sources_file: + fields['added_sources_length'] = added_sources_file.tell() + fields_str = json.dumps(fields, indent=2, sort_keys=True) w.WriteLine(str(len(fields_str))) w.WriteLine(fields_str) + if removed_sources_file: + w.WriteBytes(removed_sources_file.getvalue()) + if added_sources_file: + w.WriteBytes(added_sources_file.getvalue()) + w.WriteBytes(before_size_file.getvalue()) after_promise.get() w.WriteBytes(after_size_file.getvalue()) @@ -717,14 +756,27 @@ raise Exception('Bad file header.') json_len = int(file_obj.readline()) - json_str = file_obj.read(json_len + 1) # + 1 for \n + json_str = file_obj.read(1 + json_len) # + 1 for \n fields = json.loads(json_str) - assert fields['version'] == _SIZEDIFF_VERSION - after_pos = file_obj.tell() + fields['before_length'] + pos = file_obj.tell() + + removed_sources = [] + removed_sources_length = fields.get('removed_sources_length', 0) + if removed_sources_length: + removed_sources = _LoadCompressedStringList(file_obj, + removed_sources_length) + pos += removed_sources_length + + added_sources = [] + added_sources_length = fields.get('added_sources_length', 0) + if added_sources_length: + added_sources = _LoadCompressedStringList(file_obj, added_sources_length) + pos += added_sources_length before_size_info = LoadSizeInfo(path, file_obj, is_sparse=True) - file_obj.seek(after_pos) + pos += fields['before_length'] + file_obj.seek(pos) after_size_info = LoadSizeInfo(path, file_obj, is_sparse=True) - return before_size_info, after_size_info + return before_size_info, after_size_info, removed_sources, added_sources
diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py index 910ac5c..550f87eb 100644 --- a/tools/binary_size/libsupersize/models.py +++ b/tools/binary_size/libsupersize/models.py
@@ -371,6 +371,7 @@ Fields: size_path: Path to .size file this was loaded from (or None). + is_sparse: Whether the list of symbols is sparse. """ __slots__ = ( 'size_path', @@ -408,16 +409,28 @@ Fields: before: SizeInfo for "before". after: SizeInfo for "after". + removed_sources: List of removed source files from "before". + added_sources: List of added source files from "after". """ __slots__ = ( 'before', 'after', + 'removed_sources', + 'added_sources', ) - def __init__(self, before, after, containers, raw_symbols): + def __init__(self, + before, + after, + containers, + raw_symbols, + removed_sources=None, + added_sources=None): super().__init__(None, containers, raw_symbols) self.before = before self.after = after + self.removed_sources = removed_sources or [] + self.added_sources = added_sources or [] @property def is_sparse(self): @@ -1476,6 +1489,16 @@ def WhereDiffStatusIs(self, diff_status): return self.Filter(lambda s: s.diff_status == diff_status) + def GetEntireAddOrRemoveSources(self): + """Return source paths with entirely added or removed symbols.""" + source_flags = collections.defaultdict(int) + for sym in self: + source_flags[sym.source_path] |= 1 << sym.diff_status + add_flag = 1 << DIFF_STATUS_ADDED + remove_flag = 1 << DIFF_STATUS_REMOVED + return (sorted(k for k, v in source_flags.items() if v == remove_flag), + sorted(k for k, v in source_flags.items() if v == add_flag)) + def _ExtractPrefixBeforeSeparator(string, separator, count): idx = -len(separator)
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden index 5b7ced7..1846c94 100644 --- a/tools/binary_size/libsupersize/testdata/Console.golden +++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -6,9 +6,9 @@ SymbolGroup (extends Symbol): CountUniqueSymbols, Filter, GroupedBy, GroupedByAliases, GroupedByComponent, GroupedByContainer, GroupedByContainerAndSectionName, GroupedByFullName, GroupedByName, GroupedByPath, GroupedBySectionName, Inverted, IterUniqueSymbols, Sorted, SortedByAddress, SortedByCount, SortedByName, WhereAddressInRange, WhereComponentMatches, WhereFullNameMatches, WhereGeneratedByToolchain, WhereHasAnyAttribution, WhereHasComponent, WhereHasFlag, WhereHasPath, WhereInContainer, WhereInSection, WhereIsDex, WhereIsGroup, WhereIsNative, WhereIsOnDemand, WhereIsPak, WhereIsPlaceholder, WhereIsTemplate, WhereMatches, WhereNameMatches, WhereObjectPathMatches, WherePathMatches, WherePssBiggerThan, WhereSizeBiggerThan, WhereSourceIsGenerated, WhereSourcePathMatches, WhereTemplateNameMatches, index, is_default_sorted -DeltaSizeInfo: ContainerForName, after, before, build_config, containers, is_sparse, native_symbols, pak_symbols, raw_symbols, section_sizes, symbols +DeltaSizeInfo: ContainerForName, added_sources, after, before, build_config, containers, is_sparse, native_symbols, pak_symbols, raw_symbols, removed_sources, section_sizes, symbols DeltaSymbol (extends Symbol): after_symbol, before_symbol, diff_status -DeltaSymbolGroup (extends SymbolGroup): CountsByDiffStatus, WhereDiffStatusIs, diff_status +DeltaSymbolGroup (extends SymbolGroup): CountsByDiffStatus, GetEntireAddOrRemoveSources, WhereDiffStatusIs, diff_status canned_queries: CategorizeByChromeComponent, CategorizeGenerated, LargeFiles, PakByPath, StaticInitializers, TemplatesByName
diff --git a/tools/binary_size/libsupersize/viewer/caspian/README.md b/tools/binary_size/libsupersize/viewer/caspian/README.md index c99c916..f4f4756 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/README.md +++ b/tools/binary_size/libsupersize/viewer/caspian/README.md
@@ -44,7 +44,7 @@ ```sh # Omit is_official_build=true if developing locally. -gn gen out/caspian --args='is_official_build=true treat_warnings_as_errors=false fatal_linker_warnings=false chrome_pgo_phase=0' +gn gen out/caspian --args='is_official_build=true treat_warnings_as_errors=false fatal_linker_warnings=false chrome_pgo_phase=0 enable_rust=false' # Build and copy into static/ directory: ( cd out/caspian; autoninja caspian_web && cp wasm/caspian_web.* ../../tools/binary_size/libsupersize/viewer/static/ ) ```
diff --git a/tools/binary_size/libsupersize/viewer/caspian/caspian_web.cc b/tools/binary_size/libsupersize/viewer/caspian/caspian_web.cc index e157668..dc42032 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/caspian_web.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/caspian_web.cc
@@ -58,6 +58,8 @@ std::unique_ptr<SizeInfo> info; std::unique_ptr<SizeInfo> before_info; +std::vector<std::string> removed_sources; +std::vector<std::string> added_sources; std::unique_ptr<DeltaSizeInfo> diff_info; std::unique_ptr<TreeBuilder> builder; @@ -121,6 +123,8 @@ diff_info.reset(nullptr); before_info.reset(nullptr); info.reset(nullptr); + removed_sources = {}; + added_sources = {}; } } // namespace @@ -131,8 +135,11 @@ if (IsDiffSizeInfo(compressed, size)) { info = std::make_unique<SizeInfo>(); before_info = std::make_unique<SizeInfo>(); + ParseDiffSizeInfo(compressed, size, before_info.get(), info.get(), + &removed_sources, &added_sources); // DeltaSizeInfo instantiation for sparse diff. - ParseDiffSizeInfo(compressed, size, before_info.get(), info.get()); + diff_info.reset(new DeltaSizeInfo( + Diff(before_info.get(), info.get(), &removed_sources, &added_sources))); } else { info = std::make_unique<SizeInfo>(); ParseSizeInfo(compressed, size, info.get()); @@ -248,7 +255,8 @@ // and let the TreeBuilder filter the symbols we care about. if (diff_mode && !diff_info) { // DeltaSizeInfo instantiation for dense diff. - diff_info.reset(new DeltaSizeInfo(Diff(before_info.get(), info.get()))); + diff_info.reset(new DeltaSizeInfo( + Diff(before_info.get(), info.get(), nullptr, nullptr))); } if (diff_mode) {
diff --git a/tools/binary_size/libsupersize/viewer/caspian/cli.cc b/tools/binary_size/libsupersize/viewer/caspian/cli.cc index 92a283c..b0e98ee 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/cli.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/cli.cc
@@ -9,6 +9,8 @@ #include <algorithm> #include <fstream> #include <iostream> +#include <string> +#include <vector> #include "tools/binary_size/libsupersize/viewer/caspian/diff.h" #include "tools/binary_size/libsupersize/viewer/caspian/file_format.h" @@ -33,9 +35,24 @@ std::cerr << "Unable to open file: " << filename << std::endl; exit(1); } + std::vector<std::string> removed_sources; + std::vector<std::string> added_sources; std::string compressed((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); - caspian::ParseDiffSizeInfo(&compressed[0], compressed.size(), before, after); + caspian::ParseDiffSizeInfo(&compressed[0], compressed.size(), before, after, + &removed_sources, &added_sources); + if (removed_sources.size()) { + std::cout << "Removed " << removed_sources.size() << " files:" << std::endl; + for (const std::string& s : removed_sources) { + std::cout << " " << s << std::endl; + } + } + if (added_sources.size()) { + std::cout << "Added " << added_sources.size() << " files:" << std::endl; + for (const std::string& s : added_sources) { + std::cout << " " << s << std::endl; + } + } } void Diff(const char* before_filename, const char* after_filename) { @@ -45,7 +62,7 @@ caspian::SizeInfo after; ParseSizeInfoFromFile(after_filename, &after); - caspian::DeltaSizeInfo diff = Diff(&before, &after); + caspian::DeltaSizeInfo diff = Diff(&before, &after, nullptr, nullptr); float pss = 0.0f; float size = 0.0f;
diff --git a/tools/binary_size/libsupersize/viewer/caspian/diff.cc b/tools/binary_size/libsupersize/viewer/caspian/diff.cc index d1747648..7dcc75a0 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/diff.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/diff.cc
@@ -204,8 +204,11 @@ namespace caspian { // See docs/diffs.md for diffing algorithm. -DeltaSizeInfo Diff(const SizeInfo* before, const SizeInfo* after) { - DeltaSizeInfo ret(before, after); +DeltaSizeInfo Diff(const SizeInfo* before, + const SizeInfo* after, + const std::vector<std::string>* removed_sources, + const std::vector<std::string>* added_sources) { + DeltaSizeInfo ret(before, after, removed_sources, added_sources); bool is_sparse = before->IsSparse() && after->IsSparse(); std::vector<const Symbol*> unmatched_before;
diff --git a/tools/binary_size/libsupersize/viewer/caspian/diff.h b/tools/binary_size/libsupersize/viewer/caspian/diff.h index 4fcd363..4de3c6a 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/diff.h +++ b/tools/binary_size/libsupersize/viewer/caspian/diff.h
@@ -5,10 +5,16 @@ #ifndef TOOLS_BINARY_SIZE_LIBSUPERSIZE_VIEWER_CASPIAN_DIFF_H_ #define TOOLS_BINARY_SIZE_LIBSUPERSIZE_VIEWER_CASPIAN_DIFF_H_ +#include <string> +#include <vector> + #include "tools/binary_size/libsupersize/viewer/caspian/model.h" namespace caspian { -DeltaSizeInfo Diff(const SizeInfo* before, const SizeInfo* after); +DeltaSizeInfo Diff(const SizeInfo* before, + const SizeInfo* after, + const std::vector<std::string>* removed_sources, + const std::vector<std::string>* added_sources); } #endif // TOOLS_BINARY_SIZE_LIBSUPERSIZE_VIEWER_CASPIAN_DIFF_H_
diff --git a/tools/binary_size/libsupersize/viewer/caspian/diff_test.cc b/tools/binary_size/libsupersize/viewer/caspian/diff_test.cc index fb536d9..85e3073 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/diff_test.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/diff_test.cc
@@ -92,23 +92,33 @@ } } -TEST(DiffTest, TestIdentity) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); +class DiffTest : public testing::Test { + public: + void SetUp() override { + size_info1_ = CreateSizeInfo(); + size_info2_ = CreateSizeInfo(); + } - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + protected: + std::unique_ptr<SizeInfo> size_info1_; + std::unique_ptr<SizeInfo> size_info2_; + std::vector<std::string> removed_sources_; + std::vector<std::string> added_sources_; +}; + +TEST_F(DiffTest, TestIdentity) { + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); for (const DeltaSymbol& sym : diff.delta_symbols) { EXPECT_EQ(sym.Size(), 0); EXPECT_EQ(sym.Padding(), 0); } } -TEST(DiffTest, TestSimpleAdd) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info1->raw_symbols.erase(size_info1->raw_symbols.begin()); - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); +TEST_F(DiffTest, TestSimpleAdd) { + size_info1_->raw_symbols.erase(size_info1_->raw_symbols.begin()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{5, 0, 1, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); @@ -116,12 +126,10 @@ EXPECT_EQ(10, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestSimpleDelete) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info2->raw_symbols.erase(size_info2->raw_symbols.begin()); - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); +TEST_F(DiffTest, TestSimpleDelete) { + size_info2_->raw_symbols.erase(size_info2_->raw_symbols.begin()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{5, 0, 0, 1}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); @@ -129,14 +137,12 @@ EXPECT_EQ(-10, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestSimpleChange) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info2->raw_symbols[0].size_ += 11; - size_info2->raw_symbols[0].padding_ += 20; - size_info2->raw_symbols.back().size_ += 11; - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); +TEST_F(DiffTest, TestSimpleChange) { + size_info2_->raw_symbols[0].size_ += 11; + size_info2_->raw_symbols[0].padding_ += 20; + size_info2_->raw_symbols.back().size_ += 11; + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{4, 2, 1, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); @@ -144,77 +150,68 @@ EXPECT_EQ(22, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestDontMatchAcrossSections) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info1->raw_symbols.push_back( +TEST_F(DiffTest, TestDontMatchAcrossSections) { + size_info1_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 11, "asdf", "Hello")); - size_info2->raw_symbols.push_back( + size_info2_->raw_symbols.push_back( MakeSymbol(SectionId::kRoData, 11, "asdf", "Hello")); - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{6, 0, 1, 1}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestDontMatchAcrossContainers) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - size_info1->containers.emplace_back("C2"); - Container::AssignShortNames(&size_info1->containers); - size_info2->containers.emplace_back("C2"); - Container::AssignShortNames(&size_info2->containers); +TEST_F(DiffTest, TestDontMatchAcrossContainers) { + size_info1_->containers.emplace_back("C2"); + Container::AssignShortNames(&size_info1_->containers); + size_info2_->containers.emplace_back("C2"); + Container::AssignShortNames(&size_info2_->containers); - size_info1->raw_symbols[0].container_ = &size_info1->containers[1]; + size_info1_->raw_symbols[0].container_ = &size_info1_->containers[1]; - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{5, 0, 1, 1}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestAliasesRemove) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); +TEST_F(DiffTest, TestAliasesRemove) { + MakeAliasGroup(size_info1_.get(), 0, 3); + MakeAliasGroup(size_info2_.get(), 0, 2); - MakeAliasGroup(size_info1.get(), 0, 3); - MakeAliasGroup(size_info2.get(), 0, 2); - - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{3, 3, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestAliasesAdd) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); +TEST_F(DiffTest, TestAliasesAdd) { + MakeAliasGroup(size_info1_.get(), 0, 2); + MakeAliasGroup(size_info2_.get(), 0, 3); - MakeAliasGroup(size_info1.get(), 0, 2); - MakeAliasGroup(size_info2.get(), 0, 3); - - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{3, 3, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestAliasesChangeGroup) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); +TEST_F(DiffTest, TestAliasesChangeGroup) { + MakeAliasGroup(size_info1_.get(), 0, 2); + MakeAliasGroup(size_info1_.get(), 2, 5); + MakeAliasGroup(size_info2_.get(), 0, 3); + MakeAliasGroup(size_info2_.get(), 3, 5); - MakeAliasGroup(size_info1.get(), 0, 2); - MakeAliasGroup(size_info1.get(), 2, 5); - MakeAliasGroup(size_info2.get(), 0, 3); - MakeAliasGroup(size_info2.get(), 3, 5); - - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{2, 4, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); @@ -223,107 +220,96 @@ // These tests currently fail because _ doesn't rewrite. -TEST(DiffTest, TestStarSymbolNormalization) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); +TEST_F(DiffTest, TestStarSymbolNormalization) { + SetName(&size_info1_->raw_symbols[0], "* symbol gap 1 (end of section)"); + SetName(&size_info2_->raw_symbols[0], "* symbol gap 2 (end of section)"); - SetName(&size_info1->raw_symbols[0], "* symbol gap 1 (end of section)"); - SetName(&size_info2->raw_symbols[0], "* symbol gap 2 (end of section)"); - - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{6, 0, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestNumberNormalization) { - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info1->raw_symbols.push_back( +TEST_F(DiffTest, TestNumberNormalization) { + size_info1_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 11, "a", ".L__unnamed_1193")); - size_info1->raw_symbols.push_back( + size_info1_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 22, "a", ".L__unnamed_1194")); - size_info1->raw_symbols.push_back(MakeSymbol( + size_info1_->raw_symbols.push_back(MakeSymbol( SectionId::kText, 33, "a", "SingleCategoryPreferences$3#this$0")); - size_info1->raw_symbols.push_back( + size_info1_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 44, "a", ".L.ref.tmp.2")); - size_info2->raw_symbols.push_back( + size_info2_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 11, "a", ".L__unnamed_2194")); - size_info2->raw_symbols.push_back( + size_info2_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 22, "a", ".L__unnamed_2195")); - size_info2->raw_symbols.push_back(MakeSymbol( + size_info2_->raw_symbols.push_back(MakeSymbol( SectionId::kText, 33, "a", "SingleCategoryPreferences$9#this$009")); - size_info2->raw_symbols.push_back( + size_info2_->raw_symbols.push_back( MakeSymbol(SectionId::kText, 44, "a", ".L.ref.tmp.137")); - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{10, 0, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestChangedParams) { +TEST_F(DiffTest, TestChangedParams) { // Ensure that params changes match up so long as path doesn't change. - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); + size_info1_->raw_symbols[0].full_name_ = "Foo()"; + size_info1_->raw_symbols[0].name_ = "Foo"; + size_info2_->raw_symbols[0].full_name_ = "Foo(bool)"; + size_info2_->raw_symbols[0].name_ = "Foo"; - size_info1->raw_symbols[0].full_name_ = "Foo()"; - size_info1->raw_symbols[0].name_ = "Foo"; - size_info2->raw_symbols[0].full_name_ = "Foo(bool)"; - size_info2->raw_symbols[0].name_ = "Foo"; - - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{6, 0, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestChangedPathsNative) { +TEST_F(DiffTest, TestChangedPathsNative) { // Ensure that non-globally-unique symbols are not matched when path changes. - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info2->raw_symbols[1].object_path_ = "asdf"; - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + size_info2_->raw_symbols[1].object_path_ = "asdf"; + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{5, 0, 1, 1}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestChangedPathsJava) { +TEST_F(DiffTest, TestChangedPathsJava) { // Ensure that Java symbols are matched up. - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info2->raw_symbols[0].object_path_ = "asdf"; - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + size_info2_->raw_symbols[0].object_path_ = "asdf"; + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{6, 0, 0, 0}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } -TEST(DiffTest, TestChangedPathsChangedParams) { +TEST_F(DiffTest, TestChangedPathsChangedParams) { // Ensure that path changes are not matched when params also change. - std::unique_ptr<SizeInfo> size_info1 = CreateSizeInfo(); - std::unique_ptr<SizeInfo> size_info2 = CreateSizeInfo(); - - size_info1->raw_symbols[0].full_name_ = "Foo()"; - size_info1->raw_symbols[0].name_ = "Foo"; - size_info2->raw_symbols[0].full_name_ = "Foo(bool)"; - size_info2->raw_symbols[0].name_ = "Foo"; - size_info2->raw_symbols[0].object_path_ = "asdf"; - DeltaSizeInfo diff = Diff(size_info1.get(), size_info2.get()); + size_info1_->raw_symbols[0].full_name_ = "Foo()"; + size_info1_->raw_symbols[0].name_ = "Foo"; + size_info2_->raw_symbols[0].full_name_ = "Foo(bool)"; + size_info2_->raw_symbols[0].name_ = "Foo"; + size_info2_->raw_symbols[0].object_path_ = "asdf"; + DeltaSizeInfo diff = Diff(size_info1_.get(), size_info2_.get(), + &removed_sources_, &added_sources_); DeltaSizeInfo::Results expected_counts{5, 0, 1, 1}; EXPECT_EQ(expected_counts, diff.CountsByDiffStatus()); EXPECT_EQ(0, SumOfSymbolSizes(diff)); } + } // namespace } // namespace caspian
diff --git a/tools/binary_size/libsupersize/viewer/caspian/file_format.cc b/tools/binary_size/libsupersize/viewer/caspian/file_format.cc index e363e6a..1e7ee1d 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/file_format.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/file_format.cc
@@ -460,6 +460,19 @@ std::cout << "Parsed " << info->raw_symbols.size() << " symbols" << std::endl; } +void ParseCompressedStringList(const char* gzipped, + unsigned long len, + std::vector<std::string>* string_list) { + std::vector<char> decompressed; + Decompress(gzipped, len, &decompressed); + char* rest = &decompressed[0]; + int n_strings = ReadLoneInt(&rest); + string_list->resize(n_strings); + for (int i = 0; i < n_strings; i++) { + (*string_list)[i] = strsep(&rest, "\n"); + } +} + bool IsDiffSizeInfo(const char* file, unsigned long len) { return !strncmp(file, kDiffHeader, 4); } @@ -467,7 +480,9 @@ void ParseDiffSizeInfo(char* file, unsigned long len, SizeInfo* before, - SizeInfo* after) { + SizeInfo* after, + std::vector<std::string>* removed_sources, + std::vector<std::string>* added_sources) { // Skip "DIFF" header. char* rest = file; rest += strlen(kDiffHeader); @@ -485,8 +500,20 @@ }; unsigned long header_len = rest - file; + unsigned long removed_sources_len = get_uint_field("removed_sources_length"); + unsigned long added_sources_len = get_uint_field("added_sources_length"); unsigned long before_len = get_uint_field("before_length"); - unsigned long after_len = len - header_len - before_len; + unsigned long after_len = + len - header_len - before_len - removed_sources_len - added_sources_len; + + if (removed_sources_len) { + ParseCompressedStringList(rest, removed_sources_len, removed_sources); + rest += removed_sources_len; + } + if (added_sources_len) { + ParseCompressedStringList(rest, added_sources_len, added_sources); + rest += added_sources_len; + } ParseSizeInfo(rest, before_len, before); rest += before_len;
diff --git a/tools/binary_size/libsupersize/viewer/caspian/file_format.h b/tools/binary_size/libsupersize/viewer/caspian/file_format.h index cde7a192..8220106 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/file_format.h +++ b/tools/binary_size/libsupersize/viewer/caspian/file_format.h
@@ -5,6 +5,9 @@ #ifndef TOOLS_BINARY_SIZE_LIBSUPERSIZE_VIEWER_CASPIAN_FILE_FORMAT_H_ #define TOOLS_BINARY_SIZE_LIBSUPERSIZE_VIEWER_CASPIAN_FILE_FORMAT_H_ +#include <string> +#include <vector> + namespace caspian { struct SizeInfo; @@ -17,7 +20,9 @@ void ParseDiffSizeInfo(char* file, unsigned long len, SizeInfo* before, - SizeInfo* after); + SizeInfo* after, + std::vector<std::string>* removed_sources, + std::vector<std::string>* added_sources); // Parses a .size file. void ParseSizeInfo(const char* gzipped, unsigned long len, SizeInfo* info);
diff --git a/tools/binary_size/libsupersize/viewer/caspian/model.cc b/tools/binary_size/libsupersize/viewer/caspian/model.cc index f0bb3e7..c88b118 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/model.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/model.cc
@@ -375,8 +375,13 @@ } DeltaSizeInfo::DeltaSizeInfo(const SizeInfo* before_in, - const SizeInfo* after_in) - : before(before_in), after(after_in) {} + const SizeInfo* after_in, + const std::vector<std::string>* removed_sources_in, + const std::vector<std::string>* added_sources_in) + : before(before_in), + after(after_in), + removed_sources(removed_sources_in), + added_sources(added_sources_in) {} DeltaSizeInfo::~DeltaSizeInfo() = default; DeltaSizeInfo::DeltaSizeInfo(const DeltaSizeInfo&) = default; @@ -415,7 +420,10 @@ } else { (*out)["idPath"] = id_path.ToString(); if (opts.is_sparse) { - // TODO(crbug.com/1047572): Impose diffStatus if data is available. + if (node_stats.imposed_diff_status != DiffStatus::kUnchanged) { + (*out)["diffStatus"] = + static_cast<uint8_t>(node_stats.imposed_diff_status); + } } else if (!children.empty()) { // Add tag to containers in which all child symbols were added/removed. DiffStatus diff_status = node_stats.GetGlobalDiffStatus();
diff --git a/tools/binary_size/libsupersize/viewer/caspian/model.h b/tools/binary_size/libsupersize/viewer/caspian/model.h index edaf22e6..ab4d517c 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/model.h +++ b/tools/binary_size/libsupersize/viewer/caspian/model.h
@@ -308,7 +308,10 @@ }; struct DeltaSizeInfo : BaseSizeInfo { - DeltaSizeInfo(const SizeInfo* before_in, const SizeInfo* after_in); + DeltaSizeInfo(const SizeInfo* before_in, + const SizeInfo* after_in, + const std::vector<std::string>* removed_sources_in, + const std::vector<std::string>* added_sources_in); ~DeltaSizeInfo() override; DeltaSizeInfo(const DeltaSizeInfo&); DeltaSizeInfo& operator=(const DeltaSizeInfo&); @@ -325,6 +328,8 @@ const SizeInfo* before = nullptr; const SizeInfo* after = nullptr; + const std::vector<std::string>* removed_sources; + const std::vector<std::string>* added_sources; std::vector<DeltaSymbol> delta_symbols; // Symbols created during diffing, e.g. aggregated padding symbols. std::deque<Symbol> owned_symbols; @@ -365,6 +370,7 @@ DiffStatus GetGlobalDiffStatus() const; std::map<SectionId, Stat> child_stats; + DiffStatus imposed_diff_status = DiffStatus::kUnchanged; }; struct TreeNode {
diff --git a/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc b/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc index cd1f00c..1175a56 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc +++ b/tools/binary_size/libsupersize/viewer/caspian/tree_builder.cc
@@ -32,6 +32,16 @@ for (const DeltaSymbol& sym : size_info->delta_symbols) { symbols_.push_back(&sym); } + if (size_info->removed_sources) { + for (const auto& s : *size_info->removed_sources) { + source_to_diff_status_[s] = DiffStatus::kRemoved; + } + } + if (size_info->added_sources) { + for (const auto& s : *size_info->added_sources) { + source_to_diff_status_[s] = DiffStatus::kAdded; + } + } size_info_ = size_info; } @@ -186,6 +196,11 @@ file_node->id_path.size() - file_node->id_path.ShortName(sep_).size(); _parents[file_node->id_path] = file_node; file_node->node_stats = node_stats; + auto it = source_to_diff_status_.find(grouped_path.path); + std::string p(grouped_path.path); + if (it != source_to_diff_status_.end()) { + file_node->node_stats.imposed_diff_status = it->second; + } } for (TreeNode* symbol_node : symbol_nodes) {
diff --git a/tools/binary_size/libsupersize/viewer/caspian/tree_builder.h b/tools/binary_size/libsupersize/viewer/caspian/tree_builder.h index dec573e2..40f7dcd 100644 --- a/tools/binary_size/libsupersize/viewer/caspian/tree_builder.h +++ b/tools/binary_size/libsupersize/viewer/caspian/tree_builder.h
@@ -67,6 +67,7 @@ char sep_; std::vector<FilterFunc> filters_; std::vector<const BaseSymbol*> symbols_; + std::unordered_map<std::string_view, DiffStatus> source_to_diff_status_; }; // TreeBuilder } // namespace caspian #endif // TOOLS_BINARY_SIZE_LIBSUPERSIZE_VIEWER_CASPIAN_TREE_BUILDER_H_
diff --git a/tools/cast3p/cast_core.version b/tools/cast3p/cast_core.version index 01cddae..45c8f32 100644 --- a/tools/cast3p/cast_core.version +++ b/tools/cast3p/cast_core.version
@@ -1 +1 @@ -cast_20230523_2001_RC00 +cast_20230526_1144_RC00
diff --git a/tools/crates/gnrt/gen.rs b/tools/crates/gnrt/gen.rs index 6d41dfc..1021eb50 100644 --- a/tools/crates/gnrt/gen.rs +++ b/tools/crates/gnrt/gen.rs
@@ -48,14 +48,9 @@ .into_iter() .flat_map(|(list, vis)| list.iter().map(move |(name, spec)| (name, spec, vis))) { - let full_dep: FullDependency = dep_spec.clone().into_full(); - let version_req = semver::VersionReq::parse( - &full_dep - .version - .as_ref() - .ok_or_else(|| format_err!("{dep_name} is missing a version in third_party.toml"))? - .0, - )?; + let full_dep: ThirdPartyFullDependency = dep_spec.clone().into_full(); + + let version_req = full_dep.version.to_version_req(); let crate_id = source.find_match(dep_name, &version_req).ok_or_else(|| { format_err!( "{dep_name} {version_req} was requested in third_party.toml \
diff --git a/tools/crates/gnrt/lib/crates.rs b/tools/crates/gnrt/lib/crates.rs index de1fe9c..afa8035a1 100644 --- a/tools/crates/gnrt/lib/crates.rs +++ b/tools/crates/gnrt/lib/crates.rs
@@ -18,6 +18,7 @@ use log::{error, warn}; use semver::Version; +use serde::{Deserialize, Serialize}; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Visibility { @@ -43,7 +44,10 @@ /// A crate version is identified by the major version, if it's >= 1, or the /// minor version, if the major version is 0. There is a many-to-one /// relationship between crate versions and epochs. -#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +/// +/// `Epoch` is serialized as a version string: e.g. "1" or "0.2". +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)] +#[serde(from = "EpochString", into = "EpochString")] pub enum Epoch { /// Epoch with major version == 0. The field is the minor version. It is an /// error to use 0: methods may panic in this case. @@ -72,6 +76,24 @@ } } + /// A `semver::VersionReq` that matches any version of this epoch. + pub fn to_version_req(&self) -> semver::VersionReq { + let (major, minor) = match self { + Self::Minor(x) => (0, Some(*x)), + Self::Major(x) => (*x, None), + }; + semver::VersionReq { + comparators: vec![semver::Comparator { + // "^1" is the same as "1" in Cargo.toml. + op: semver::Op::Caret, + major, + minor, + patch: None, + pre: semver::Prerelease::EMPTY, + }], + } + } + /// Compute the Epoch from a `semver::Version`. This is useful since we can /// parse versions from `cargo_metadata` and in Cargo.toml files using the /// `semver` library. @@ -447,3 +469,20 @@ ) -> io::Result<T> { result.map_err(|e| io::Error::new(io::ErrorKind::Other, e)) } + +/// Proxy for [de]serializing epochs to/from strings. This uses the "1" or "0.1" +/// format rather than the `Display` format for `Epoch`. +#[derive(Debug, Deserialize, Serialize)] +struct EpochString(String); + +impl From<Epoch> for EpochString { + fn from(epoch: Epoch) -> Self { + Self(epoch.to_version_string()) + } +} + +impl From<EpochString> for Epoch { + fn from(epoch: EpochString) -> Self { + Epoch::from_version_req_str(&epoch.0) + } +}
diff --git a/tools/crates/gnrt/lib/manifest.rs b/tools/crates/gnrt/lib/manifest.rs index d7a0003..990a420 100644 --- a/tools/crates/gnrt/lib/manifest.rs +++ b/tools/crates/gnrt/lib/manifest.rs
@@ -4,6 +4,8 @@ //! Utilities for parsing and generating Cargo.toml and related manifest files. +use crate::crates::Epoch; + use std::collections::BTreeMap; use std::path::PathBuf; @@ -11,7 +13,7 @@ /// Set of dependencies for a particular usage: final artifacts, tests, or /// build scripts. -pub type DependencySet = BTreeMap<String, Dependency>; +pub type DependencySet<Type> = BTreeMap<String, Type>; /// Set of patches to replace upstream dependencies with local crates. Maps /// arbitrary patch names to `CargoPatch` which includes the actual package name /// and the local path. @@ -40,7 +42,7 @@ skip_serializing_if = "DependencySet::is_empty", serialize_with = "toml::ser::tables_last" )] - pub dependencies: DependencySet, + pub dependencies: ThirdPartyDependencySet, /// Dependencies to allow only in testonly code. These still participate in /// the same dependency resolution. #[serde( @@ -48,7 +50,7 @@ skip_serializing_if = "DependencySet::is_empty", serialize_with = "toml::ser::tables_last" )] - pub testonly_dependencies: DependencySet, + pub testonly_dependencies: ThirdPartyDependencySet, } #[derive(Clone, Debug, Deserialize, Serialize)] @@ -57,37 +59,70 @@ pub members: Vec<String>, } -/// A single crate dependency. +/// A single crate dependency. Cargo.toml and third_party.toml have different +/// version formats and some different fields. This is generic to share the same +/// type between them. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[serde(untagged)] -pub enum Dependency { +pub enum Dependency<VersionType, DepType> { /// A dependency of the form `foo = "1.0.11"`: just the package name as key /// and the version as value. The sole field is the crate version. - Short(VersionConstraint), + Short(VersionType), /// A dependency that specifies other fields in the form of `foo = { ... }` /// or `[dependencies.foo] ... `. - Full(FullDependency), + Full(DepType), } -impl Dependency { - pub fn into_full(self) -> FullDependency { +/// A single third_party.toml dependency. +pub type ThirdPartyDependency = Dependency<Epoch, ThirdPartyFullDependency>; +pub type ThirdPartyDependencySet = DependencySet<ThirdPartyDependency>; + +/// A single Cargo.toml dependency. +pub type CargoDependency = Dependency<String, CargoFullDependency>; +pub type CargoDependencySet = DependencySet<CargoDependency>; + +impl ThirdPartyDependency { + /// Expand the short form spec, filling other fields in with their defaults. + pub fn into_full(self) -> ThirdPartyFullDependency { match self { - Self::Short(version) => FullDependency { version: Some(version), ..Default::default() }, + Self::Short(version) => ThirdPartyFullDependency { + default_features: true, + version, + features: vec![], + allow_first_party_usage: true, + build_script_outputs: vec![], + gn_variables_lib: None, + }, Self::Full(full) => full, } } + + /// Generate a Cargo.toml dependency entry with the custom fields stripped + /// away. + pub fn into_cargo(self) -> CargoDependency { + match self { + Self::Short(version) => CargoDependency::Short(version.to_version_string()), + Self::Full(full) => CargoDependency::Full(CargoFullDependency { + default_features: full.default_features, + version: Some(VersionConstraint(full.version.to_version_string())), + features: full.features, + }), + } + } } /// A single crate dependency with some extra fields from third_party.toml. +/// Unlike `CargoFullDependency` this will reject unknown fields on +/// deserialization. This is desirable since we control the third_party.toml +/// format. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] -#[serde(rename_all = "kebab-case")] -pub struct FullDependency { +#[serde(deny_unknown_fields, rename_all = "kebab-case")] +pub struct ThirdPartyFullDependency { /// Include the package's default features. Influences Cargo behavior. #[serde(default = "get_true", skip_serializing_if = "is_true")] pub default_features: bool, /// Version constraint on dependency. - #[serde(default, skip_serializing_if = "Option::is_none")] - pub version: Option<VersionConstraint>, + pub version: Epoch, /// Required features. #[serde(default, skip_serializing_if = "Vec::is_empty")] pub features: Vec<String>, @@ -104,16 +139,23 @@ pub gn_variables_lib: Option<String>, } -impl Default for FullDependency { +#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] +#[serde(rename_all = "kebab-case")] +pub struct CargoFullDependency { + /// Include the package's default features. Influences Cargo behavior. + #[serde(default = "get_true", skip_serializing_if = "is_true")] + pub default_features: bool, + /// Version constraint on dependency. + #[serde(default, skip_serializing_if = "Option::is_none")] + pub version: Option<VersionConstraint>, + /// Required features. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub features: Vec<String>, +} + +impl Default for CargoFullDependency { fn default() -> Self { - FullDependency { - default_features: true, - version: None, - features: vec![], - allow_first_party_usage: true, - build_script_outputs: vec![], - gn_variables_lib: None, - } + Self { default_features: true, version: None, features: vec![] } } } @@ -130,7 +172,7 @@ skip_serializing_if = "DependencySet::is_empty", serialize_with = "toml::ser::tables_last" )] - pub dependencies: DependencySet, + pub dependencies: CargoDependencySet, #[serde(default, rename = "patch")] pub patches: BTreeMap<String, CargoPatchSet>, } @@ -209,6 +251,9 @@ } } + let dependencies: BTreeMap<_, _> = + dependencies.into_iter().map(|(pkg, dep)| (pkg, dep.into_cargo())).collect(); + let mut patch_sections = CargoPatchSet::new(); // Generate patch section. for PatchSpecification { package_name, patch_name, path } in patches {
diff --git a/tools/crates/gnrt/lib/manifest_unittest.rs b/tools/crates/gnrt/lib/manifest_unittest.rs index 55df9b7d..c31db848 100644 --- a/tools/crates/gnrt/lib/manifest_unittest.rs +++ b/tools/crates/gnrt/lib/manifest_unittest.rs
@@ -4,13 +4,14 @@ use rust_gtest_interop::prelude::*; +use gnrt_lib::crates::Epoch; use gnrt_lib::manifest::*; #[gtest(ManifestTest, ParseSingleFullDependency)] fn test() { expect_eq!( toml::de::from_str(concat!( - "version = \"1.0.0\"\n", + "version = \"1\"\n", "features = [\"foo\", \"bar\"]\n", "allow-first-party-usage = false\n", "build-script-outputs = [\"stuff.rs\"]\n", @@ -19,9 +20,9 @@ configs = [] \"\"\"" )), - Ok(FullDependency { + Ok(ThirdPartyFullDependency { default_features: true, - version: Some(VersionConstraint("1.0.0".to_string())), + version: Epoch::Major(1), features: vec!["foo".to_string(), "bar".to_string()], allow_first_party_usage: false, build_script_outputs: vec!["stuff.rs".to_string()], @@ -33,12 +34,12 @@ expect_eq!( toml::de::from_str(concat!( - "version = \"3.14.159\"\n", + "version = \"3\"\n", "build-script-outputs = [\"generated.rs\"]\n", )), - Ok(FullDependency { + Ok(ThirdPartyFullDependency { default_features: true, - version: Some(VersionConstraint("3.14.159".to_string())), + version: Epoch::Major(3), features: vec![], allow_first_party_usage: true, build_script_outputs: vec!["generated.rs".to_string()], @@ -52,7 +53,7 @@ expect_eq!( toml::de::from_str(concat!( "default-features = false\n", - "version = \"1.0.0\"\n", + "version = \"1\"\n", "features = [\"foo\", \"bar\"]\n", "allow-first-party-usage = false\n", "build-script-outputs = [\"stuff.rs\"]\n", @@ -61,9 +62,9 @@ configs = [] \"\"\"" )), - Ok(FullDependency { + Ok(ThirdPartyFullDependency { default_features: false, - version: Some(VersionConstraint("1.0.0".to_string())), + version: Epoch::Major(1), features: vec!["foo".to_string(), "bar".to_string()], allow_first_party_usage: false, build_script_outputs: vec!["stuff.rs".to_string()], @@ -98,18 +99,18 @@ expect_eq!( manifest.dependencies.get("cxx"), - Some(&Dependency::Short(VersionConstraint("1".to_string()))) + Some(&ThirdPartyDependency::Short(Epoch::Major(1))) ); expect_eq!( manifest.dependencies.get("serde"), - Some(&Dependency::Short(VersionConstraint("1".to_string()))) + Some(&ThirdPartyDependency::Short(Epoch::Major(1))) ); expect_eq!( manifest.dependencies.get("rustversion"), - Some(&Dependency::Full(FullDependency { + Some(&Dependency::Full(ThirdPartyFullDependency { default_features: true, - version: Some(VersionConstraint("1".to_string())), + version: Epoch::Major(1), features: vec![], allow_first_party_usage: true, build_script_outputs: vec!["version.rs".to_string()], @@ -119,9 +120,9 @@ expect_eq!( manifest.dependencies.get("unicode-linebreak"), - Some(&Dependency::Full(FullDependency { + Some(&Dependency::Full(ThirdPartyFullDependency { default_features: true, - version: Some(VersionConstraint("0.1".to_string())), + version: Epoch::Minor(1), features: vec![], allow_first_party_usage: false, build_script_outputs: vec!["table.rs".to_string()], @@ -131,9 +132,9 @@ expect_eq!( manifest.dependencies.get("special-stuff"), - Some(&Dependency::Full(FullDependency { + Some(&Dependency::Full(ThirdPartyFullDependency { default_features: true, - version: Some(VersionConstraint("0.1".to_string())), + version: Epoch::Minor(1), features: vec![], allow_first_party_usage: true, build_script_outputs: vec![], @@ -143,9 +144,9 @@ expect_eq!( manifest.testonly_dependencies.get("syn"), - Some(&Dependency::Full(FullDependency { + Some(&Dependency::Full(ThirdPartyFullDependency { default_features: true, - version: Some(VersionConstraint("1".to_string())), + version: Epoch::Major(1), features: vec!["full".to_string()], allow_first_party_usage: true, build_script_outputs: vec![], @@ -166,7 +167,7 @@ license: "funtimes".to_string(), }, workspace: None, - dependencies: DependencySet::new(), + dependencies: CargoDependencySet::new(), patches: vec![( "crates-io".to_string(), vec![(
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 7968d37..a3f8f45 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -247,6 +247,10 @@ "META": {"sizes": {"includes": [20],}}, "includes": [3040], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/location_internals/resources.grd": { + "META": {"sizes": {"includes": [10],}}, + "includes": [3050], + }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/management/resources.grd": { "META": {"sizes": {"includes": [10]}}, "includes": [3060],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 04964f7..833e9569 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -60593,6 +60593,7 @@ <int value="-1196814719" label="TrafficCountersEnabled:disabled"/> <int value="-1195194959" label="XGEOVisibleNetworks:disabled"/> <int value="-1195034892" label="ContinuousSearch:disabled"/> + <int value="-1194747282" label="kNearbySharingSelfShare:enabled"/> <int value="-1194129602" label="ClientSideDetectionModelOnAndroid:disabled"/> <int value="-1193375480" label="DownloadBubble:enabled"/> <int value="-1192790333" label="ArcUseHighMemoryDalvikProfile:disabled"/> @@ -61572,6 +61573,7 @@ <int value="-680589442" label="MacRTL:disabled"/> <int value="-679585025" label="CaptureModeSelfieCamera:disabled"/> <int value="-679500267" label="UseXpsForPrinting:disabled"/> + <int value="-678281465" label="force-companion-pinned-state:enabled"/> <int value="-678184617" label="TranslateSubFrames:disabled"/> <int value="-677978627" label="ZeroCopyTabCapture:enabled"/> <int value="-677938988" label="AssistantConsentSimplifiedText:disabled"/> @@ -61773,6 +61775,7 @@ <int value="-572112724" label="DialogTouchBar:disabled"/> <int value="-572012175" label="AssistantEnableStereoAudioInput:disabled"/> <int value="-571655232" label="SideSearch:enabled"/> + <int value="-571623630" label="kNearbySharingSelfShare:disabled"/> <int value="-571236436" label="AppManagement:disabled"/> <int value="-570889908" label="CCTModuleDexLoading:enabled"/> <int value="-570005880" @@ -65052,6 +65055,7 @@ <int value="1196670943" label="WebAuthFlowInBrowserTab:enabled"/> <int value="1196834473" label="disable-smart-virtual-keyboard"/> <int value="1197336536" label="printing-ppd-channel"/> + <int value="1197363734" label="force-companion-pinned-state:disabled"/> <int value="1198604672" label="DiscardExceptionsImprovements:disabled"/> <int value="1198839129" label="OfflinePagesLivePageSharing:enabled"/> <int value="1199276782" label="HighEfficiencyMultistateMode:enabled"/> @@ -79318,10 +79322,10 @@ <int value="2" label="Optimization Guide"/> </enum> -<enum name="PageImageServiceOptimizationGuideResult"> +<enum name="PageImageServiceResult"> <int value="0" label="Success"/> - <int value="1" label="Decision missing"> - The entire Decision for Images is missing. + <int value="1" label="Response missing"> + The entire response (or Decision for Optimization Guide) is missing. </int> <int value="2" label="No Image"> No image was available for the requested Page URL.
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 356d69c0..992e9c8 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -1742,6 +1742,84 @@ </histogram> <histogram + name="Ash.CaptureModeController.GameDashboard.CaptureConfiguration.{TabletOrClamshell}" + enum="CaptureModeConfiguration" expires_after="2024-05-27"> + <owner>michelefan@chromium.org</owner> + <owner>gzadina@google.com</owner> + <summary> + Recorded whenever a Game Dashboard initiated a screen capture is performed + in {TabletOrClamshell}. The recorded enum indicates the configuration used + for the Game Dashboard initiated capture, i.e. the capture source and the + capture type. + </summary> + <token key="TabletOrClamshell" variants="DisplayModes"/> +</histogram> + +<histogram + name="Ash.CaptureModeController.GameDashboard.DemoToolsEnabledOnRecordingStart.{TabletOrClamshell}" + enum="BooleanEnabled" expires_after="2024-05-27"> + <owner>michelefan@chromium.org</owner> + <owner>gzadina@google.com</owner> + <summary> + Records whether a Game Dashboard initiated recording starts with demo tools + feature enabled or not in {TabletOrClamshell}. + </summary> + <token key="TabletOrClamshell" variants="DisplayModes"/> +</histogram> + +<histogram + name="Ash.CaptureModeController.GameDashboard.RecordingStartsWithCamera.{TabletOrClamshell}" + enum="BooleanEnabled" expires_after="2024-05-27"> + <owner>michelefan@chromium.org</owner> + <owner>gzadina@google.com</owner> + <summary> + Records whether a Game Dashboard initiated recording starts with camera on + or not in {TabletOrClamshell}. + </summary> + <token key="TabletOrClamshell" variants="DisplayModes"/> +</histogram> + +<histogram + name="Ash.CaptureModeController.GameDashboard.SaveLocation.{TabletOrClamshell}" + enum="CaptureModeSaveToLocation" expires_after="2024-05-27"> + <owner>michelefan@chromium.org</owner> + <owner>gzadina@google.com</owner> + <summary> + Recorded whenever the screen capture is saved in {TabletOrClamshell} when + captured by the Game Dashboard intiated capture session. The recorded enum + value indicates the location that the screen capture is saved. + </summary> + <token key="TabletOrClamshell" variants="DisplayModes"/> +</histogram> + +<histogram + name="Ash.CaptureModeController.GameDashboard.ScreenRecordingFileSize.{TabletOrClamshell}" + units="KB" expires_after="2024-05-27"> + <owner>michelefan@chromium.org</owner> + <owner>gzadina@google.com</owner> + <summary> + Records the size of the successfully recorded WebM file by the Game + Dashboard initiated capture mode in {TabletOrClamshell}. This metric will + not be recorded if a file was not successfully saved. + </summary> + <token key="TabletOrClamshell" variants="DisplayModes"/> +</histogram> + +<histogram + name="Ash.CaptureModeController.GameDashboard.ScreenRecordingLength.{TabletOrClamshell}" + units="seconds" expires_after="2024-05-27"> + <owner>michelefan@chromium.org</owner> + <owner>gzadina@google.com</owner> + <summary> + Records the time of a successful video recording in capture mode entered + from the Game Dashboard in {TabletOrClamshell}. This metric will not be + recorded if a file was not successfully saved. The upper limit of this + histogram is 3 hours. + </summary> + <token key="TabletOrClamshell" variants="DisplayModes"/> +</histogram> + +<histogram name="Ash.CaptureModeController.GIFRecordingFileSize.{TabletOrClamshell}" units="KB" expires_after="2024-03-01"> <owner>afakhry@chromium.org</owner> @@ -6745,6 +6823,18 @@ </summary> </histogram> +<histogram name="Ash.Wallpaper.IsSetToTimeOfDayAfterOobe" enum="Boolean" + expires_after="2024-05-23"> + <owner>jasontt@chromium.org</owner> + <owner>assistive-eng@google.com</owner> + <summary> + Tracks whether the time of day wallpaper is set to be the default wallpaper + successfully on supported devices. Recorded each time the user goes through + OOBE flow and they did not have any synced wallpaper on any of their + previous devices. + </summary> +</histogram> + <histogram name="Ash.Wallpaper.Preview.Show" enum="BooleanHit" expires_after="2024-02-13"> <owner>jasontt@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/companion/histograms.xml b/tools/metrics/histograms/metadata/companion/histograms.xml index dfa2a32..b838a006 100644 --- a/tools/metrics/histograms/metadata/companion/histograms.xml +++ b/tools/metrics/histograms/metadata/companion/histograms.xml
@@ -65,6 +65,16 @@ </summary> </histogram> +<histogram name="Companion.SidePanel.OpenTrigger" enum="SidePanelOpenTrigger" + expires_after="2023-10-20"> + <owner>shaktisahu@chromium.org</owner> + <owner>src/chrome/browser/companion/OWNERS</owner> + <summary> + Records the UI location from which the companion side panel was triggered to + be opened. Recorded after the companion is opened and loaded. + </summary> +</histogram> + <histogram name="Companion.{UiSurface}.Clicked" enum="BooleanClicked" expires_after="2023-10-20"> <owner>shaktisahu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index a572df4..eb49d0d 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1146,6 +1146,30 @@ </token> </histogram> +<histogram name="History.Clusters.Backend.NumVisitsBelowFold" + units="number visits" expires_after="2023-12-01"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + Logs the number of visits that are "below the fold" in each + cluster after hidden and done visits have been culled. Logged for each + cluster that is shown to the user in the Journeys WebUI. + </summary> +</histogram> + +<histogram name="History.Clusters.Backend.NumVisitsBelowFoldPercentage" + units="%" expires_after="2023-12-01"> + <owner>sophiechang@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + Logs the percentage of visits that are "below the fold" in each + cluster after hidden and done visits have been culled. Logged for each + cluster that is shown to the user in the Journeys WebUI. + </summary> +</histogram> + <histogram name="History.Clusters.Backend.NumVisitsPerCluster" units="number visits" expires_after="2022-12-01"> <obsolete>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 6eb279d..1a044e4 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -9086,7 +9086,7 @@ </histogram> <histogram name="PageImageService.Backend.OptimizationGuide.Result{ClientId}" - enum="PageImageServiceOptimizationGuideResult" expires_after="2023-08-08"> + enum="PageImageServiceResult" expires_after="2023-08-08"> <owner>sophiechang@chromium.org</owner> <owner>chrome-journeys@google.com</owner> <component>Internals>OptimizationGuide</component> @@ -9100,6 +9100,20 @@ <token key="ClientId" variants="PageImageServiceClientId"/> </histogram> +<histogram name="PageImageService.Backend.Suggest.Result{ClientId}" + enum="PageImageServiceResult" expires_after="2023-08-08"> + <owner>tommycli@chromium.org</owner> + <owner>chrome-journeys@google.com</owner> + <component>UI>Browser>Journeys</component> + <summary> + Records the result of requests to the Suggest backend. + + Recorded for each request to Suggest, so the total count of this UMA should + match that bucket count in PageImageService.Backend. + </summary> + <token key="ClientId" variants="PageImageServiceClientId"/> +</histogram> + <histogram name="PageImageService.Backend{ClientId}" enum="PageImageServiceBackend" expires_after="2023-08-08"> <owner>tommycli@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/translate/histograms.xml b/tools/metrics/histograms/metadata/translate/histograms.xml index d6fff06..f457b0ee 100644 --- a/tools/metrics/histograms/metadata/translate/histograms.xml +++ b/tools/metrics/histograms/metadata/translate/histograms.xml
@@ -584,21 +584,6 @@ </summary> </histogram> -<histogram name="Translate.Ranker.Model.Status" enum="RankerModelStatus" - expires_after="M109"> - <obsolete> - Logged on profile open, including for system and ash-internal profiles that - don't use the Translate feature. Replaced in M-110 by the histogram - Translate.Ranker.Model.Status2, which is similar but only emitted on regular - and guest profiles. - </obsolete> - <owner>megjablon@google.com</owner> - <owner>chrome-language@google.com</owner> - <summary> - Tracks the outcome of attempts to download a Translate Ranker Model. - </summary> -</histogram> - <histogram name="Translate.Ranker.Model.Status2" enum="RankerModelStatus" expires_after="2023-11-12"> <owner>megjablon@google.com</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 6692123b..e973ec0 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -13666,6 +13666,23 @@ </metric> </event> +<event name="MediaStream.Device"> + <owner>mfoltz@chromium.org</owner> + <owner>openscreen-eng@google.com</owner> + <summary> + Events recorded when a page requests access device media, i.e. by starting + screen capture or opening a webcam or microphone, and the result of that + request. + </summary> + <metric name="VideoCaptureGenerateStreamResult" + enum="MediaStreamRequestResult2"> + <summary> + The result of a page's request to open a video capture device (e.g., + webcam). + </summary> + </metric> +</event> + <event name="Memory.Experimental"> <owner>erikchen@chromium.org</owner> <owner>ssid@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index e3101d6e..65e98ca9 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@ "full_remote_path": "perfetto-luci-artifacts/v34.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "0ffd698000278bbd56ac558fdab05ddcb64902d7", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/61d24e07b779260b3fb22dee4a53fdcfb415ab1a/trace_processor_shell.exe" + "hash": "daf5a52d35a7f07e053dcc794250525b84a81538", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/ebb76a18fc52001180325a413c2b33c078ba5c5c/trace_processor_shell.exe" }, "linux_arm": { "hash": "336a42cb9ec3c417e13a97816271fec10cdf67e5", "full_remote_path": "perfetto-luci-artifacts/v34.0/linux-arm/trace_processor_shell" }, "mac": { - "hash": "1700346a398cf4ef67b162f44779987b7b48e1f1", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/61d24e07b779260b3fb22dee4a53fdcfb415ab1a/trace_processor_shell" + "hash": "ce981645424edb12cd1da97341a0073d312f25df", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/ebb76a18fc52001180325a413c2b33c078ba5c5c/trace_processor_shell" }, "mac_arm64": { "hash": "c32364e05e22cdf82ee0866aedd11c0e2050809c", "full_remote_path": "perfetto-luci-artifacts/v34.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "ee56d0de0689d557fb411194fd17e966b2b91300", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/61d24e07b779260b3fb22dee4a53fdcfb415ab1a/trace_processor_shell" + "hash": "8523faa1309716b224c3e56b8dbe08ec1ff4f556", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/ebb76a18fc52001180325a413c2b33c078ba5c5c/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml index 2658e202..0954a0b 100644 --- a/tools/traffic_annotation/summary/annotations.xml +++ b/tools/traffic_annotation/summary/annotations.xml
@@ -297,7 +297,8 @@ <item id="download_bitmap" added_in_milestone="98" content_hash_code="0632ef37" os_list="android" file_path="chrome/browser/share/bitmap_download_request.cc" /> <item id="permission_request_creator" added_in_milestone="98" content_hash_code="04629d73" os_list="android,chromeos,linux,windows" file_path="chrome/browser/supervised_user/child_accounts/permission_request_creator_apiary.cc" /> <item id="kids_chrome_management_client_classify_url" added_in_milestone="98" content_hash_code="003a8b30" os_list="android,chromeos,linux,windows" file_path="components/supervised_user/core/browser/kids_chrome_management_client.cc" /> - <item id="kids_chrome_management_list_family_members" added_in_milestone="106" content_hash_code="023f7fa9" os_list="android,chromeos,windows,linux" file_path="components/supervised_user/core/browser/fetcher_config.cc" /> + <item id="supervised_user_classify_url" added_in_milestone="98" content_hash_code="05877932" os_list="android,chromeos,linux,windows" file_path="components/supervised_user/core/browser/fetcher_config.cc" /> + <item id="supervised_user_list_family_members" added_in_milestone="98" content_hash_code="00627698" os_list="android,chromeos,linux,windows" file_path="components/supervised_user/core/browser/fetcher_config.cc" /> <item id="cached_image_fetcher" added_in_milestone="98" content_hash_code="06334a2d" os_list="android" file_path="components/image_fetcher/image_fetcher_bridge.cc" /> <item id="chrome_cast_discovery_api" added_in_milestone="98" content_hash_code="0502b792" os_list="linux,windows,chromeos" file_path="chrome/browser/media/router/discovery/access_code/access_code_cast_discovery_interface.cc" /> <item id="fedcm" added_in_milestone="98" content_hash_code="082197eb" os_list="linux,windows,chromeos,android" file_path="content/browser/webid/idp_network_request_manager.cc" />
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml index ac35859..75bd052d 100644 --- a/tools/traffic_annotation/summary/grouping.xml +++ b/tools/traffic_annotation/summary/grouping.xml
@@ -26,6 +26,7 @@ <annotation id="download_bitmap"/> <annotation id="download_manager_service_retry"/> <annotation id="kids_chrome_management_client_classify_url"/> + <annotation id="supervised_user_classify_url"/> <annotation id="minidump_uploader_android"/> <annotation id="oma_download_handler_android"/> <annotation id="partner_bookmarks_reader_get_favicon"/> @@ -333,7 +334,7 @@ <group name="Child-protection and Safe Browsing Features" hidden="true"> <sender name="Safe Browsing"> <annotation id="client_download_request"/> - <annotation id="kids_chrome_management_list_family_members"/> + <annotation id="supervised_user_list_family_members"/> <annotation id="password_protection_request"/> <annotation id="permission_predictions"/> <annotation id="safe_browsing_certificate_error_reporting"/>
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index c10eb3b..7bc55f9 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -566,7 +566,10 @@ if (is_mac) { public_deps += [ "//ui/base/cursor" ] - deps += [ "//ui/resources:ui_resources_grd" ] + deps += [ + "//base:base_arc", + "//ui/resources:ui_resources_grd", + ] } if (toolkit_views) {
diff --git a/ui/base/cocoa/menu_controller.mm b/ui/base/cocoa/menu_controller.mm index da1ce12..283ae09 100644 --- a/ui/base/cocoa/menu_controller.mm +++ b/ui/base/cocoa/menu_controller.mm
@@ -4,6 +4,7 @@ #import "ui/base/cocoa/menu_controller.h" +#include "base/apple/owned_objc.h" #include "base/check_op.h" #include "base/functional/bind.h" #include "base/mac/foundation_util.h" @@ -326,8 +327,9 @@ ui::ElementTrackerMac::GetInstance()->NotifyMenuItemActivated([sender menu], identifier); } - model->ActivatedAt(modelIndex, - ui::EventFlagsFromNative([NSApp currentEvent])); + model->ActivatedAt( + modelIndex, + ui::EventFlagsFromNative(base::apple::OwnedNSEvent(NSApp.currentEvent))); // Note: |self| may be destroyed by the call to ActivatedAt(). }
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index 7a5f8669..c507a8e 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -431,7 +431,8 @@ "EnableVariableRefreshRate", base::FEATURE_DISABLED_BY_DEFAULT); bool IsVariableRefreshRateEnabled() { - return base::FeatureList::IsEnabled(kEnableVariableRefreshRate); + return base::FeatureList::GetStateIfOverridden(kEnableVariableRefreshRate) + .value_or(base::FeatureList::IsEnabled(kEnableVariableRefreshRate)); } // Fixes b/267944900. @@ -444,19 +445,6 @@ "WaylandCancelComposition", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kWaylandScreenCoordinatesEnabled, - "WaylandScreenCoordinatesEnabled", -#if BUILDFLAG(IS_CHROMEOS_LACROS) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -); - -bool IsWaylandScreenCoordinatesEnabled() { - return base::FeatureList::IsEnabled(kWaylandScreenCoordinatesEnabled); -} - // Enables chrome color management wayland protocol for lacros. BASE_FEATURE(kLacrosColorManagement, "LacrosColorManagement",
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 02ba086..0e376b9a 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -207,10 +207,6 @@ // Fixes b/267944900. COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kWaylandCancelComposition); -COMPONENT_EXPORT(UI_BASE_FEATURES) -BASE_DECLARE_FEATURE(kWaylandScreenCoordinatesEnabled); -COMPONENT_EXPORT(UI_BASE_FEATURES) -bool IsWaylandScreenCoordinatesEnabled(); COMPONENT_EXPORT(UI_BASE_FEATURES) BASE_DECLARE_FEATURE(kLacrosColorManagement); COMPONENT_EXPORT(UI_BASE_FEATURES)
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5 index 2d84b3a..6761361 100644 --- a/ui/chromeos/styles/cros_sys_colors.json5 +++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -450,82 +450,102 @@ 'illo.color1': { light: '$cros.ref.primary30', dark: '$cros.ref.primary80', + generate_per_mode: true, }, 'illo.color1.1': { light: '$cros.ref.primary80', dark: '$cros.ref.secondary40', + generate_per_mode: true, }, 'illo.color1.2': { light: '$cros.ref.primary90', dark: '$cros.ref.secondary30', + generate_per_mode: true, }, 'illo.color2': { light: '$cros.ref.green60', dark: '$cros.ref.green70', + generate_per_mode: true, }, 'illo.color3': { light: '$cros.ref.yellow70', dark: '$cros.ref.yellow80', + generate_per_mode: true, }, 'illo.color4': { light: '$cros.ref.red60', dark: '$cros.ref.red60', + generate_per_mode: true, }, 'illo.color5': { light: '$cros.ref.tertiary70', dark: '$cros.ref.tertiary40', + generate_per_mode: true, }, 'illo.color6': { light: '$cros.ref.secondary90', dark: '$cros.ref.secondary50', + generate_per_mode: true, }, 'illo.base': { light: '$cros.ref.secondary100', dark: '$cros.ref.secondary0', + generate_per_mode: true, }, 'illo.secondary': { light: '$cros.ref.neutralvariant90', dark: '$cros.ref.neutralvariant40', + generate_per_mode: true, }, 'illo.card.color1' : { light: '#fce3e0', dark: '#4d2726', + generate_per_mode: true, }, 'illo.card.on-color1' : { light: '#a50e0e', dark: '#f6aea9', + generate_per_mode: true, }, 'illo.card.color2' : { light: '#fef2cb', dark: '#443117', + generate_per_mode: true, }, 'illo.card.on-color2' : { light: '#9b6100', dark: '#fde293', + generate_per_mode: true, }, 'illo.card.color3' : { light: '#dcf4e3', dark: '#16341e', + generate_per_mode: true, }, 'illo.card.on-color3' : { light: '#0d652d', dark: '#a8dab5', + generate_per_mode: true, }, 'illo.card.color4' : { light: '#d6e5fc', dark: '#20314e', + generate_per_mode: true, }, 'illo.card.on-color4' : { light: '#185abc', dark: '#aecbfa', + generate_per_mode: true, }, 'illo.card.color5' : { light: '#f4e3fe', dark: '#433355', + generate_per_mode: true, }, 'illo.card.on-color5' : { light: '#75099b', dark: '#d7aefb', + generate_per_mode: true, }, /* Icon colors. */
diff --git a/ui/events/BUILD.gn b/ui/events/BUILD.gn index 0305cc2..75d47712 100644 --- a/ui/events/BUILD.gn +++ b/ui/events/BUILD.gn
@@ -376,6 +376,7 @@ } if (is_mac) { + deps += [ "//base:base_arc" ] frameworks = [ "AppKit.framework" ] } @@ -723,6 +724,10 @@ deps += [ "//ui/events:keyboard_hook" ] } + if (is_mac) { + deps += [ "//base:base_arc" ] + } + if (is_castos) { sources += [ "chromecast/scroller_unittest.cc" ] }
diff --git a/ui/events/cocoa/events_mac.mm b/ui/events/cocoa/events_mac.mm index e6279e1..1f048c4 100644 --- a/ui/events/cocoa/events_mac.mm +++ b/ui/events/cocoa/events_mac.mm
@@ -21,13 +21,14 @@ namespace ui { -EventType EventTypeFromNative(const PlatformEvent& native_event) { - NSEventType type = [native_event type]; +EventType EventTypeFromNative(const PlatformEvent& platform_event) { + NSEvent* event = platform_event.Get(); + NSEventType type = event.type; switch (type) { case NSEventTypeKeyDown: case NSEventTypeKeyUp: case NSEventTypeFlagsChanged: - return IsKeyUpEvent(native_event) ? ET_KEY_RELEASED : ET_KEY_PRESSED; + return IsKeyUpEvent(event) ? ET_KEY_RELEASED : ET_KEY_PRESSED; case NSEventTypeLeftMouseDown: case NSEventTypeRightMouseDown: case NSEventTypeOtherMouseDown: @@ -72,45 +73,47 @@ return ET_UNKNOWN; } -int EventFlagsFromNative(const PlatformEvent& event) { +int EventFlagsFromNative(const PlatformEvent& platform_event) { + NSEvent* event = platform_event.Get(); NSUInteger modifiers = [event modifierFlags]; return EventFlagsFromNSEventWithModifiers(event, modifiers); } -base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) { +base::TimeTicks EventTimeFromNative(const PlatformEvent& platform_event) { base::TimeTicks timestamp = - ui::EventTimeStampFromSeconds([native_event timestamp]); + ui::EventTimeStampFromSeconds([platform_event.Get() timestamp]); ValidateEventTimeClock(×tamp); return timestamp; } -base::TimeTicks EventLatencyTimeFromNative(const PlatformEvent& native_event, +base::TimeTicks EventLatencyTimeFromNative(const PlatformEvent& platform_event, base::TimeTicks current_time) { - return EventTimeFromNative(native_event); + return EventTimeFromNative(platform_event); } -gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) { - NSWindow* window = [native_event window]; - NSPoint location = [native_event locationInWindow]; +gfx::PointF EventLocationFromNative(const PlatformEvent& platform_event) { + NSEvent* event = platform_event.Get(); + NSWindow* window = event.window; + NSPoint location = event.locationInWindow; // If there's no window, the event is in screen coordinates. - NSRect frame = window ? [window contentRectForFrameRect:[window frame]] - : [[[NSScreen screens] firstObject] frame]; + NSRect frame = window ? [window contentRectForFrameRect:window.frame] + : NSScreen.screens.firstObject.frame; // In Cocoa, the y coordinate anchors to the bottom, so we need to flip it. return gfx::PointF(location.x, NSHeight(frame) - location.y); } -gfx::Point EventSystemLocationFromNative(const PlatformEvent& native_event) { +gfx::Point EventSystemLocationFromNative(const PlatformEvent& platform_event) { NOTIMPLEMENTED(); return gfx::Point(); } -int EventButtonFromNative(const PlatformEvent& native_event) { +int EventButtonFromNative(const PlatformEvent& platform_event) { NOTIMPLEMENTED(); return 0; } -int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& native_event) { - NSEventType type = [native_event type]; +int GetChangedMouseButtonFlagsFromNative(const PlatformEvent& platform_event) { + NSEventType type = [platform_event.Get() type]; switch (type) { case NSEventTypeLeftMouseDown: case NSEventTypeLeftMouseUp: @@ -131,18 +134,19 @@ } PointerDetails GetMousePointerDetailsFromNative( - const PlatformEvent& native_event) { + const PlatformEvent& platform_event) { return PointerDetails(EventPointerType::kMouse); } -gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& event) { - if ([event hasPreciseScrollingDeltas]) { +gfx::Vector2d GetMouseWheelOffset(const PlatformEvent& platform_event) { + NSEvent* event = platform_event.Get(); + if (event.hasPreciseScrollingDeltas) { // Handle continuous scrolling devices such as a Magic Mouse or a trackpad. // -scrollingDelta{X|Y} have float return types but they return values that // are already rounded to integers. // The values are the same as the values returned from calling // CGEventGetIntegerValueField(kCGScrollWheelEventPointDeltaAxis{1|2}). - return gfx::Vector2d([event scrollingDeltaX], [event scrollingDeltaY]); + return gfx::Vector2d(event.scrollingDeltaX, event.scrollingDeltaY); } else { // Empirically, a value of 0.1 is typical for one mousewheel click. Positive // values when scrolling up or to the left. Scrolling quickly results in a @@ -151,13 +155,13 @@ // Use the same multiplier as content::WebMouseWheelEventBuilder. Note this // differs from the value returned by CGEventSourceGetPixelsPerLine(), which // is typically 10. - return gfx::Vector2d(kScrollbarPixelsPerCocoaTick * [event deltaX], - kScrollbarPixelsPerCocoaTick * [event deltaY]); + return gfx::Vector2d(kScrollbarPixelsPerCocoaTick * event.deltaX, + kScrollbarPixelsPerCocoaTick * event.deltaY); } } gfx::Vector2d GetMouseWheelTick120ths(const PlatformEvent& event) { - CGEventRef cg_event = [event CGEvent]; + CGEventRef cg_event = [event.Get() CGEvent]; if (!cg_event || CGEventGetIntegerValueField(cg_event, kCGScrollWheelEventIsContinuous)) { @@ -172,42 +176,47 @@ 120); } -PlatformEvent CopyNativeEvent(const PlatformEvent& event) { - return [event copy]; +bool ShouldCopyPlatformEvents() { + return true; } -void ReleaseCopiedNativeEvent(const PlatformEvent& event) { - [event release]; +PlatformEvent CreateInvalidPlatformEvent() { + return PlatformEvent(); } -void ClearTouchIdIfReleased(const PlatformEvent& native_event) { +bool IsPlatformEventValid(const PlatformEvent& event) { + return event.IsValid(); +} + +void ClearTouchIdIfReleased(const PlatformEvent& platform_event) { NOTIMPLEMENTED(); } PointerDetails GetTouchPointerDetailsFromNative( - const PlatformEvent& native_event) { + const PlatformEvent& platform_event) { NOTIMPLEMENTED(); return PointerDetails(EventPointerType::kUnknown, - /* pointer_id*/ 0, - /* radius_x */ 1.0, - /* radius_y */ 1.0, - /* force */ 0.f); + /*pointer_id=*/0, + /*radius_x=*/1.0, + /*radius_y=*/1.0, + /*force=*/0.f); } -bool GetScrollOffsets(const PlatformEvent& native_event, +bool GetScrollOffsets(const PlatformEvent& platform_event, float* x_offset, float* y_offset, float* x_offset_ordinal, float* y_offset_ordinal, int* finger_count, EventMomentumPhase* momentum_phase) { - gfx::Vector2d offset = GetMouseWheelOffset(native_event); + NSEvent* event = platform_event.Get(); + gfx::Vector2d offset = GetMouseWheelOffset(platform_event); *x_offset = *x_offset_ordinal = offset.x(); *y_offset = *y_offset_ordinal = offset.y(); // For non-scrolling events, the finger count can be determined with - // [[native_event touchesMatchingPhase:NSTouchPhaseTouching inView:nil] count] - // but it's illegal to ask that of scroll events, so say two fingers. + // [[platform_event touchesMatchingPhase:NSTouchPhaseTouching inView:nil] + // count] but it's illegal to ask that of scroll events, so say two fingers. *finger_count = 2; // If a user just rests two fingers on the touchpad without moving, AppKit @@ -223,21 +232,21 @@ // needs tests in events_mac_unittest.mm. DCHECK_EQ(EventMomentumPhase::NONE, *momentum_phase); - if ([native_event phase] & kBeginPhaseMask) + if (event.phase & kBeginPhaseMask) { *momentum_phase = EventMomentumPhase::MAY_BEGIN; + } - if (([native_event phase] | [native_event momentumPhase]) & kEndPhaseMask) { + if ((event.phase | event.momentumPhase) & kEndPhaseMask) { DCHECK_EQ(EventMomentumPhase::NONE, *momentum_phase); *momentum_phase = EventMomentumPhase::END; - } else if ([native_event momentumPhase] != NSEventPhaseNone) { + } else if (event.momentumPhase != NSEventPhaseNone) { DCHECK_EQ(EventMomentumPhase::NONE, *momentum_phase); *momentum_phase = EventMomentumPhase::INERTIAL_UPDATE; } // If the event completely lacks phase information, there won't be further // updates, so they must be treated as an end. - if (([native_event phase] | [native_event momentumPhase]) == - NSEventPhaseNone) { + if ((event.phase | event.momentumPhase) == NSEventPhaseNone) { DCHECK_EQ(EventMomentumPhase::NONE, *momentum_phase); *momentum_phase = EventMomentumPhase::END; } @@ -245,7 +254,7 @@ return true; } -bool GetFlingData(const PlatformEvent& native_event, +bool GetFlingData(const PlatformEvent& platform_event, float* vx, float* vy, float* vx_ordinal, @@ -255,25 +264,27 @@ return false; } -KeyboardCode KeyboardCodeFromNative(const PlatformEvent& native_event) { - return KeyboardCodeFromNSEvent(native_event); +KeyboardCode KeyboardCodeFromNative(const PlatformEvent& platform_event) { + return KeyboardCodeFromNSEvent(platform_event.Get()); } -DomCode CodeFromNative(const PlatformEvent& native_event) { - return DomCodeFromNSEvent(native_event); +DomCode CodeFromNative(const PlatformEvent& platform_event) { + return DomCodeFromNSEvent(platform_event.Get()); } -uint32_t WindowsKeycodeFromNative(const PlatformEvent& native_event) { - return static_cast<uint32_t>(KeyboardCodeFromNSEvent(native_event)); +uint32_t WindowsKeycodeFromNative(const PlatformEvent& platform_event) { + return static_cast<uint32_t>(KeyboardCodeFromNSEvent(platform_event.Get())); } -uint16_t TextFromNative(const PlatformEvent& native_event) { +uint16_t TextFromNative(const PlatformEvent& platform_event) { + NSEvent* event = platform_event.Get(); NSString* text = @""; - if ([native_event type] != NSEventTypeFlagsChanged) - text = [native_event characters]; + if (event.type != NSEventTypeFlagsChanged) { + text = event.characters; + } // These exceptions are based on web_input_event_builders_mac.mm: - uint32_t windows_keycode = WindowsKeycodeFromNative(native_event); + uint32_t windows_keycode = WindowsKeycodeFromNative(platform_event); if (windows_keycode == '\r') text = @"\r"; if ([text isEqualToString:@"\x7F"]) @@ -286,13 +297,15 @@ return return_value; } -uint16_t UnmodifiedTextFromNative(const PlatformEvent& native_event) { +uint16_t UnmodifiedTextFromNative(const PlatformEvent& platform_event) { + NSEvent* event = platform_event.Get(); NSString* text = @""; - if ([native_event type] != NSEventTypeFlagsChanged) - text = [native_event charactersIgnoringModifiers]; + if (event.type != NSEventTypeFlagsChanged) { + text = event.charactersIgnoringModifiers; + } // These exceptions are based on web_input_event_builders_mac.mm: - uint32_t windows_keycode = WindowsKeycodeFromNative(native_event); + uint32_t windows_keycode = WindowsKeycodeFromNative(platform_event); if (windows_keycode == '\r') text = @"\r"; if ([text isEqualToString:@"\x7F"]) @@ -305,7 +318,7 @@ return return_value; } -bool IsCharFromNative(const PlatformEvent& native_event) { +bool IsCharFromNative(const PlatformEvent& platform_event) { return false; }
diff --git a/ui/events/cocoa/events_mac_unittest.mm b/ui/events/cocoa/events_mac_unittest.mm index ebd29890..67204f7 100644 --- a/ui/events/cocoa/events_mac_unittest.mm +++ b/ui/events/cocoa/events_mac_unittest.mm
@@ -9,6 +9,7 @@ #include <memory> #include <utility> +#include "base/apple/owned_objc.h" #include "base/mac/scoped_cftyperef.h" #include "testing/gtest/include/gtest/gtest.h" #import "ui/base/test/cocoa_helper.h" @@ -29,7 +30,7 @@ class EventsMacTest : public CocoaTest { public: - EventsMacTest() {} + EventsMacTest() = default; EventsMacTest(const EventsMacTest&) = delete; EventsMacTest& operator=(const EventsMacTest&) = delete; @@ -150,66 +151,75 @@ // Left click. NSEvent* left = cocoa_test_event_utils::MouseEventWithType(NSEventTypeLeftMouseUp, 0); - EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, EventFlagsFromNative(left)); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON, + EventFlagsFromNative(base::apple::OwnedNSEvent(left))); // Right click. NSEvent* right = cocoa_test_event_utils::MouseEventWithType(NSEventTypeRightMouseUp, 0); - EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, EventFlagsFromNative(right)); + EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, + EventFlagsFromNative(base::apple::OwnedNSEvent(right))); // Middle click. NSEvent* middle = cocoa_test_event_utils::MouseEventWithType(NSEventTypeOtherMouseUp, 0); - EXPECT_EQ(EF_MIDDLE_MOUSE_BUTTON, EventFlagsFromNative(middle)); + EXPECT_EQ(EF_MIDDLE_MOUSE_BUTTON, + EventFlagsFromNative(base::apple::OwnedNSEvent(middle))); // Caps + Left NSEvent* caps = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagCapsLock); - EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_CAPS_LOCK_ON, EventFlagsFromNative(caps)); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_CAPS_LOCK_ON, + EventFlagsFromNative(base::apple::OwnedNSEvent(caps))); // Shift + Left NSEvent* shift = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagShift); - EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_SHIFT_DOWN, EventFlagsFromNative(shift)); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_SHIFT_DOWN, + EventFlagsFromNative(base::apple::OwnedNSEvent(shift))); // Ctrl + Left. Note we map this to a right click on Mac and remove Control. NSEvent* ctrl = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagControl); - EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, EventFlagsFromNative(ctrl)); + EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON, + EventFlagsFromNative(base::apple::OwnedNSEvent(ctrl))); // Ctrl + Right. Remains a right click. NSEvent* ctrl_right = cocoa_test_event_utils::MouseEventWithType( NSEventTypeRightMouseUp, NSEventModifierFlagControl); EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON | EF_CONTROL_DOWN, - EventFlagsFromNative(ctrl_right)); + EventFlagsFromNative(base::apple::OwnedNSEvent(ctrl_right))); // Alt + Left NSEvent* alt = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagOption); - EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_ALT_DOWN, EventFlagsFromNative(alt)); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_ALT_DOWN, + EventFlagsFromNative(base::apple::OwnedNSEvent(alt))); // Cmd + Left NSEvent* cmd = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagCommand); - EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN, EventFlagsFromNative(cmd)); + EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN, + EventFlagsFromNative(base::apple::OwnedNSEvent(cmd))); // Shift + Ctrl + Left. Also mapped to a right-click. Control removed. NSEvent* shiftctrl = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagShift | NSEventModifierFlagControl); EXPECT_EQ(EF_RIGHT_MOUSE_BUTTON | EF_SHIFT_DOWN, - EventFlagsFromNative(shiftctrl)); + EventFlagsFromNative(base::apple::OwnedNSEvent(shiftctrl))); // Cmd + Alt + Right NSEvent* cmdalt = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseUp, NSEventModifierFlagCommand | NSEventModifierFlagOption); EXPECT_EQ(EF_LEFT_MOUSE_BUTTON | EF_COMMAND_DOWN | EF_ALT_DOWN, - EventFlagsFromNative(cmdalt)); + EventFlagsFromNative(base::apple::OwnedNSEvent(cmdalt))); // Make sure a repeat key-down event gets ui::EF_IS_REPEAT set. NSEvent* repeat_key_down = cocoa_test_event_utils::KeyDownEventWithRepeat(); - EXPECT_EQ(ui::EF_IS_REPEAT, EventFlagsFromNative(repeat_key_down)); + EXPECT_EQ(ui::EF_IS_REPEAT, + EventFlagsFromNative(base::apple::OwnedNSEvent(repeat_key_down))); } // Tests mouse button presses and mouse wheel events. @@ -219,55 +229,71 @@ NSEvent* event = TestMouseEvent(kCGEventLeftMouseDown, location, kNoEventFlags); - EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); - EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + EXPECT_EQ(ui::ET_MOUSE_PRESSED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, + ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); event = TestMouseEvent(kCGEventOtherMouseDown, location, kCGEventFlagMaskShift); - EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_PRESSED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); EXPECT_EQ(ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_SHIFT_DOWN, - ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); event = TestMouseEvent(kCGEventRightMouseUp, location, kNoEventFlags); - EXPECT_EQ(ui::ET_MOUSE_RELEASED, ui::EventTypeFromNative(event)); - EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + EXPECT_EQ(ui::ET_MOUSE_RELEASED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(ui::EF_RIGHT_MOUSE_BUTTON, + ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); // Scroll up. event = TestScrollEvent(location, 0, 1); - EXPECT_EQ(ui::ET_SCROLL, ui::EventTypeFromNative(event)); - EXPECT_EQ(0, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); - offset = ui::GetMouseWheelOffset(event); + EXPECT_EQ(ui::ET_SCROLL, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(0, ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); + offset = ui::GetMouseWheelOffset(base::apple::OwnedNSEvent(event)); EXPECT_GT(offset.y(), 0); EXPECT_EQ(0, offset.x()); // Scroll down. event = TestScrollEvent(location, 0, -1); - EXPECT_EQ(ui::ET_SCROLL, ui::EventTypeFromNative(event)); - EXPECT_EQ(0, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); - offset = ui::GetMouseWheelOffset(event); + EXPECT_EQ(ui::ET_SCROLL, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(0, ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); + offset = ui::GetMouseWheelOffset(base::apple::OwnedNSEvent(event)); EXPECT_LT(offset.y(), 0); EXPECT_EQ(0, offset.x()); // Scroll left. event = TestScrollEvent(location, 1, 0); - EXPECT_EQ(ui::ET_SCROLL, ui::EventTypeFromNative(event)); - EXPECT_EQ(0, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); - offset = ui::GetMouseWheelOffset(event); + EXPECT_EQ(ui::ET_SCROLL, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(0, ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); + offset = ui::GetMouseWheelOffset(base::apple::OwnedNSEvent(event)); EXPECT_EQ(0, offset.y()); EXPECT_GT(offset.x(), 0); // Scroll right. event = TestScrollEvent(location, -1, 0); - EXPECT_EQ(ui::ET_SCROLL, ui::EventTypeFromNative(event)); - EXPECT_EQ(0, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); - offset = ui::GetMouseWheelOffset(event); + EXPECT_EQ(ui::ET_SCROLL, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(0, ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); + offset = ui::GetMouseWheelOffset(base::apple::OwnedNSEvent(event)); EXPECT_EQ(0, offset.y()); EXPECT_LT(offset.x(), 0); } @@ -287,12 +313,15 @@ // EventLocationFromNative should behave the same as the ButtonEvents test. NSEvent* event = TestMouseEvent(kCGEventLeftMouseDown, location, kNoEventFlags); - EXPECT_EQ(ui::ET_MOUSE_PRESSED, ui::EventTypeFromNative(event)); - EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, ui::EventFlagsFromNative(event)); - EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + EXPECT_EQ(ui::ET_MOUSE_PRESSED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON, + ui::EventFlagsFromNative(base::apple::OwnedNSEvent(event))); + EXPECT_EQ(location, gfx::ToFlooredPoint(ui::EventLocationFromNative( + base::apple::OwnedNSEvent(event)))); // And be explicit, to ensure the test doesn't depend on some property of the - // test harness. The change to the frame rect could be OS-specfic, so set it + // test harness. The change to the frame rect could be OS-specific, so set it // to a known value. const CGFloat kTestHeight = 400; NSRect content_rect = NSMakeRect(0, 0, 600, kTestHeight); @@ -309,7 +338,8 @@ pressure:1.0]; // Bottom-left corner should be flipped. EXPECT_EQ(gfx::Point(0, kTestHeight), - gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + gfx::ToFlooredPoint( + ui::EventLocationFromNative(base::apple::OwnedNSEvent(event)))); // Removing the border, and sending the same event should move it down in the // toolkit-views coordinate system. @@ -318,7 +348,8 @@ [test_window() setStyleMask:NSWindowStyleMaskBorderless]; [test_window() setFrame:frame_rect display:YES]; EXPECT_EQ(gfx::Point(0, kTestHeight + height_change), - gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + gfx::ToFlooredPoint( + ui::EventLocationFromNative(base::apple::OwnedNSEvent(event)))); } // Test that window-less events preserve location (are in screen coordinates). @@ -331,35 +362,44 @@ NSEvent* event = [NSEvent eventWithCGEvent:mouse]; EXPECT_FALSE(event.window); EXPECT_EQ(gfx::Point(location), - gfx::ToFlooredPoint(ui::EventLocationFromNative(event))); + gfx::ToFlooredPoint( + ui::EventLocationFromNative(base::apple::OwnedNSEvent(event)))); } // Testing for ui::EventTypeFromNative() not covered by ButtonEvents. TEST_F(EventsMacTest, EventTypeFromNative) { NSEvent* event = cocoa_test_event_utils::KeyEventWithType(NSEventTypeKeyDown, 0); - EXPECT_EQ(ui::ET_KEY_PRESSED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_KEY_PRESSED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::KeyEventWithType(NSEventTypeKeyUp, 0); - EXPECT_EQ(ui::ET_KEY_RELEASED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_KEY_RELEASED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::MouseEventWithType( NSEventTypeLeftMouseDragged, 0); - EXPECT_EQ(ui::ET_MOUSE_DRAGGED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_DRAGGED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::MouseEventWithType( NSEventTypeRightMouseDragged, 0); - EXPECT_EQ(ui::ET_MOUSE_DRAGGED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_DRAGGED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::MouseEventWithType( NSEventTypeOtherMouseDragged, 0); - EXPECT_EQ(ui::ET_MOUSE_DRAGGED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_DRAGGED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::MouseEventWithType(NSEventTypeMouseMoved, 0); - EXPECT_EQ(ui::ET_MOUSE_MOVED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_MOVED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::EnterEvent(); - EXPECT_EQ(ui::ET_MOUSE_ENTERED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_ENTERED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); event = cocoa_test_event_utils::ExitEvent(); - EXPECT_EQ(ui::ET_MOUSE_EXITED, ui::EventTypeFromNative(event)); + EXPECT_EQ(ui::ET_MOUSE_EXITED, + ui::EventTypeFromNative(base::apple::OwnedNSEvent(event))); } // Verify that a mouse wheel scroll event is correctly lacking phase data. @@ -368,7 +408,7 @@ NSEvent* ns_wheel = TestScrollEvent(default_location_, 0, wheel_delta_y); EXPECT_FALSE([ns_wheel hasPreciseScrollingDeltas]); - ui::ScrollEvent wheel(ns_wheel); + ui::ScrollEvent wheel((base::apple::OwnedNSEvent(ns_wheel))); EXPECT_EQ(ui::ET_SCROLL, wheel.type()); // Currently wheel events still say two for finger count, but this may change. @@ -397,14 +437,14 @@ ASSERT_EQ(2u, [ns_events count]); EXPECT_TRUE([ns_events[0] hasPreciseScrollingDeltas]); - ui::ScrollEvent rest(ns_events[0]); + ui::ScrollEvent rest((base::apple::OwnedNSEvent(ns_events[0]))); EXPECT_EQ(ui::ET_SCROLL, rest.type()); EXPECT_EQ(2, rest.finger_count()); EXPECT_EQ(ui::EventMomentumPhase::MAY_BEGIN, rest.momentum_phase()); EXPECT_EQ(0, rest.y_offset_ordinal()); EXPECT_EQ(default_location_, rest.location()); - ui::ScrollEvent cancel(ns_events[1]); + ui::ScrollEvent cancel((base::apple::OwnedNSEvent(ns_events[1]))); EXPECT_EQ(ui::ET_SCROLL, cancel.type()); EXPECT_EQ(2, cancel.finger_count()); EXPECT_EQ(ui::EventMomentumPhase::END, cancel.momentum_phase()); @@ -428,17 +468,17 @@ NSArray* ns_events = TrackpadScrollSequence(false, delta_y, 0); ASSERT_EQ(3u, [ns_events count]); - ui::ScrollEvent begin(ns_events[0]); + ui::ScrollEvent begin((base::apple::OwnedNSEvent(ns_events[0]))); EXPECT_EQ(ui::EventMomentumPhase::MAY_BEGIN, begin.momentum_phase()); EXPECT_EQ(0, begin.y_offset_ordinal()); - ui::ScrollEvent update(ns_events[1]); + ui::ScrollEvent update((base::apple::OwnedNSEvent(ns_events[1]))); // There's no momentum yet, so phase is none. EXPECT_EQ(ui::EventMomentumPhase::NONE, update.momentum_phase()); // Note: No pixel conversion for "precise" deltas. EXPECT_EQ(delta_y, update.y_offset_ordinal()); - ui::ScrollEvent end(ns_events[2]); + ui::ScrollEvent end((base::apple::OwnedNSEvent(ns_events[2]))); EXPECT_EQ(ui::EventMomentumPhase::END, end.momentum_phase()); EXPECT_EQ(0, end.y_offset_ordinal()); } @@ -451,19 +491,19 @@ NSArray* ns_events = TrackpadScrollSequence(true, delta_y, 0); ASSERT_EQ(4u, [ns_events count]); - ui::ScrollEvent rest(ns_events[0]); + ui::ScrollEvent rest((base::apple::OwnedNSEvent(ns_events[0]))); EXPECT_EQ(ui::EventMomentumPhase::MAY_BEGIN, rest.momentum_phase()); EXPECT_EQ(0, rest.y_offset_ordinal()); - ui::ScrollEvent begin(ns_events[1]); + ui::ScrollEvent begin((base::apple::OwnedNSEvent(ns_events[1]))); EXPECT_EQ(ui::EventMomentumPhase::MAY_BEGIN, begin.momentum_phase()); EXPECT_EQ(0, begin.y_offset_ordinal()); - ui::ScrollEvent update(ns_events[2]); + ui::ScrollEvent update((base::apple::OwnedNSEvent(ns_events[2]))); EXPECT_EQ(ui::EventMomentumPhase::NONE, update.momentum_phase()); EXPECT_EQ(delta_y, update.y_offset_ordinal()); - ui::ScrollEvent end(ns_events[3]); + ui::ScrollEvent end((base::apple::OwnedNSEvent(ns_events[3]))); EXPECT_EQ(ui::EventMomentumPhase::END, end.momentum_phase()); EXPECT_EQ(0, end.y_offset_ordinal()); } @@ -491,15 +531,15 @@ // Non-momentum part. { - ui::ScrollEvent begin(ns_events[0]); + ui::ScrollEvent begin((base::apple::OwnedNSEvent(ns_events[0]))); EXPECT_EQ(ui::EventMomentumPhase::MAY_BEGIN, begin.momentum_phase()); EXPECT_EQ(0, begin.y_offset_ordinal()); - ui::ScrollEvent update(ns_events[1]); + ui::ScrollEvent update((base::apple::OwnedNSEvent(ns_events[1]))); EXPECT_EQ(ui::EventMomentumPhase::NONE, update.momentum_phase()); EXPECT_EQ(delta_y, update.y_offset_ordinal()); - ui::ScrollEvent end(ns_events[2]); + ui::ScrollEvent end((base::apple::OwnedNSEvent(ns_events[2]))); // Even though the event stream continues, AppKit doesn't provide a way to // know this without peeking at future events. So this "end" mid-stream is // unavoidable. @@ -508,17 +548,17 @@ } // Momentum part. { - ui::ScrollEvent begin(ns_events[3]); + ui::ScrollEvent begin((base::apple::OwnedNSEvent(ns_events[3]))); // Since a momentum "begin" is really a continuation of the stream, it's // currently treated as an update, but the offsets should always be zero. EXPECT_EQ(ui::EventMomentumPhase::INERTIAL_UPDATE, begin.momentum_phase()); EXPECT_EQ(0, begin.y_offset_ordinal()); - ui::ScrollEvent update(ns_events[4]); + ui::ScrollEvent update((base::apple::OwnedNSEvent(ns_events[4]))); EXPECT_EQ(ui::EventMomentumPhase::INERTIAL_UPDATE, update.momentum_phase()); EXPECT_EQ(momentum_delta_y, update.y_offset_ordinal()); - ui::ScrollEvent end(ns_events[5]); + ui::ScrollEvent end((base::apple::OwnedNSEvent(ns_events[5]))); EXPECT_EQ(ui::EventMomentumPhase::END, end.momentum_phase()); EXPECT_EQ(0, end.y_offset_ordinal()); } @@ -560,7 +600,8 @@ << test_case.description); NSEvent* native_event = cocoa_test_event_utils::KeyEventWithModifierOnly( test_case.key_code, test_case.modifier_flags); - std::unique_ptr<ui::Event> event = EventFromNative(native_event); + std::unique_ptr<ui::Event> event = + EventFromNative(base::apple::OwnedNSEvent(native_event)); EXPECT_TRUE(event); EXPECT_EQ(test_case.expected_type, event->type()); EXPECT_EQ(test_case.expected_key_code, event->AsKeyEvent()->key_code());
diff --git a/ui/events/event.cc b/ui/events/event.cc index 510641b..68ec492 100644 --- a/ui/events/event.cc +++ b/ui/events/event.cc
@@ -164,16 +164,13 @@ //////////////////////////////////////////////////////////////////////////////// // Event -Event::~Event() { - if (delete_native_event_) - ReleaseCopiedNativeEvent(native_event_); -} +Event::~Event() = default; void Event::SetNativeEvent(const PlatformEvent& event) { - if (delete_native_event_) - ReleaseCopiedNativeEvent(native_event_); - native_event_ = CopyNativeEvent(event); - delete_native_event_ = true; + if (!ShouldCopyPlatformEvents()) { + return; + } + native_event_ = event; } const char* Event::GetName() const { @@ -265,9 +262,7 @@ } bool Event::HasNativeEvent() const { - PlatformEvent null_event; - std::memset(&null_event, 0, sizeof(null_event)); - return !!std::memcmp(&native_event_, &null_event, sizeof(null_event)); + return IsPlatformEventValid(native_event_); } void Event::StopPropagation() { @@ -296,7 +291,7 @@ : type_(type), time_stamp_(time_stamp.is_null() ? EventTimeForNow() : time_stamp), flags_(flags), - native_event_(PlatformEvent()) { + native_event_(CreateInvalidPlatformEvent()) { if (type_ < ET_LAST) latency()->set_source_event_type(EventTypeToLatencySourceEventType(type)); } @@ -305,6 +300,8 @@ : type_(type), time_stamp_(EventTimeFromNative(native_event)), flags_(flags), + // Note that the construction of an Event directly from a PlatformEvent + // is the only time that ShouldCopyPlatformEvents() is not consulted. native_event_(native_event) { if (type_ < ET_LAST) latency()->set_source_event_type(EventTypeToLatencySourceEventType(type)); @@ -322,8 +319,8 @@ time_stamp_(copy.time_stamp_), latency_(copy.latency_), flags_(copy.flags_), - native_event_(CopyNativeEvent(copy.native_event_)), - delete_native_event_(true), + native_event_(ShouldCopyPlatformEvents() ? copy.native_event_ + : CreateInvalidPlatformEvent()), source_device_id_(copy.source_device_id_), properties_(copy.properties_ ? std::make_unique<Properties>(*copy.properties_) @@ -331,15 +328,12 @@ Event& Event::operator=(const Event& rhs) { if (this != &rhs) { - if (delete_native_event_) - ReleaseCopiedNativeEvent(native_event_); - type_ = rhs.type_; time_stamp_ = rhs.time_stamp_; latency_ = rhs.latency_; flags_ = rhs.flags_; - native_event_ = CopyNativeEvent(rhs.native_event_); - delete_native_event_ = true; + native_event_ = ShouldCopyPlatformEvents() ? rhs.native_event_ + : CreateInvalidPlatformEvent(); cancelable_ = rhs.cancelable_; phase_ = rhs.phase_; result_ = rhs.result_; @@ -974,7 +968,7 @@ // Native Windows character events always have is_char_ == true, // so this is a synthetic or native keystroke event. // Therefore, perform only the fallback action. - if (native_event()) { + if (IsPlatformEventValid(native_event())) { DCHECK(EventTypeFromNative(native_event()) == ET_KEY_PRESSED || EventTypeFromNative(native_event()) == ET_KEY_RELEASED); }
diff --git a/ui/events/event.h b/ui/events/event.h index fd0cacb..467d08fb 100644 --- a/ui/events/event.h +++ b/ui/events/event.h
@@ -318,7 +318,6 @@ LatencyInfo latency_; int flags_; PlatformEvent native_event_; - bool delete_native_event_ = false; bool cancelable_ = true; // Neither Event copy constructor nor the assignment operator copies // `target_`, as `target_` should be explicitly set so the setter will be @@ -667,7 +666,6 @@ : LocatedEvent(model, source, target), unique_event_id_(model.unique_event_id_), may_cause_scrolling_(model.may_cause_scrolling_), - hovering_(false), pointer_details_(model.pointer_details_) {} TouchEvent(EventType type,
diff --git a/ui/events/event_utils.h b/ui/events/event_utils.h index 00be9cd..0ecf50d1 100644 --- a/ui/events/event_utils.h +++ b/ui/events/event_utils.h
@@ -126,12 +126,14 @@ EVENTS_EXPORT gfx::Vector2d GetMouseWheelTick120ths( const PlatformEvent& native_event); -// Returns a copy of |native_event|. Depending on the platform, this copy may -// need to be deleted with ReleaseCopiedNativeEvent(). -PlatformEvent CopyNativeEvent(const PlatformEvent& native_event); +// Returns whether platform events should be copied when ui::Events are copied. +EVENTS_EXPORT bool ShouldCopyPlatformEvents(); -// Delete a |native_event| previously created by CopyNativeEvent(). -void ReleaseCopiedNativeEvent(const PlatformEvent& native_event); +// Creates a new, invalid event. +EVENTS_EXPORT PlatformEvent CreateInvalidPlatformEvent(); + +// Returns if the platform event is valid. +EVENTS_EXPORT bool IsPlatformEventValid(const PlatformEvent& platform_event); // Returns the detailed pointer information for touch events. EVENTS_EXPORT PointerDetails
diff --git a/ui/events/events_default.cc b/ui/events/events_default.cc index 531e707f..593dc01 100644 --- a/ui/events/events_default.cc +++ b/ui/events/events_default.cc
@@ -103,11 +103,17 @@ return event->tick_120ths(); } -PlatformEvent CopyNativeEvent(const PlatformEvent& event) { - return NULL; +bool ShouldCopyPlatformEvents() { + return false; } -void ReleaseCopiedNativeEvent(const PlatformEvent& event) {} +PlatformEvent CreateInvalidPlatformEvent() { + return nullptr; +} + +bool IsPlatformEventValid(const PlatformEvent& event) { + return event != nullptr; +} PointerDetails GetTouchPointerDetailsFromNative( const PlatformEvent& native_event) {
diff --git a/ui/events/events_stub.cc b/ui/events/events_stub.cc index ca5f77d..c05a0a2 100644 --- a/ui/events/events_stub.cc +++ b/ui/events/events_stub.cc
@@ -72,12 +72,20 @@ return gfx::Vector2d(); } -PlatformEvent CopyNativeEvent(const PlatformEvent& event) { - NOTIMPLEMENTED() << "Don't know how to copy PlatformEvent for this platform"; - return NULL; +bool ShouldCopyPlatformEvents() { + NOTIMPLEMENTED(); + return false; } -void ReleaseCopiedNativeEvent(const PlatformEvent& event) {} +PlatformEvent CreateInvalidPlatformEvent() { + NOTIMPLEMENTED(); + return nullptr; +} + +bool IsPlatformEventValid(const PlatformEvent& native_event) { + NOTIMPLEMENTED(); + return false; +} PointerDetails GetTouchPointerDetailsFromNative( const PlatformEvent& native_event) {
diff --git a/ui/events/ios/events_ios.mm b/ui/events/ios/events_ios.mm index 64c64b2..c40e6c4 100644 --- a/ui/events/ios/events_ios.mm +++ b/ui/events/ios/events_ios.mm
@@ -28,7 +28,7 @@ base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) { base::TimeTicks timestamp = - ui::EventTimeStampFromSeconds([native_event timestamp]); + ui::EventTimeStampFromSeconds(native_event.Get().timestamp); ValidateEventTimeClock(×tamp); return timestamp; } @@ -73,23 +73,26 @@ return gfx::Vector2d(); } -PlatformEvent CopyNativeEvent(const PlatformEvent& event) { - NOTIMPLEMENTED() << "Don't know how to copy PlatformEvent for this platform"; - return NULL; +bool ShouldCopyPlatformEvents() { + return true; } -void ReleaseCopiedNativeEvent(const PlatformEvent& event) {} +PlatformEvent CreateInvalidPlatformEvent() { + return PlatformEvent(); +} + +bool IsPlatformEventValid(const PlatformEvent& event) { + return event.IsValid(); +} PointerDetails GetTouchPointerDetailsFromNative( const PlatformEvent& native_event) { NOTIMPLEMENTED(); return PointerDetails(EventPointerType::kUnknown, - /* radius_x */ 1.0, - /* radius_y */ 1.0, - /* force */ 0.f, - /* twist */ 0.f, - /* tilt_x */ 0.f, - /* tilt_y */ 0.f); + /*pointer_id=*/0, + /*radius_x=*/1.0, + /*radius_y=*/1.0, + /*force=*/0.f); } bool GetScrollOffsets(const PlatformEvent& native_event,
diff --git a/ui/events/platform/platform_event_source_unittest.cc b/ui/events/platform/platform_event_source_unittest.cc index 199fd75d..daab847 100644 --- a/ui/events/platform/platform_event_source_unittest.cc +++ b/ui/events/platform/platform_event_source_unittest.cc
@@ -17,6 +17,8 @@ #include "base/task/single_thread_task_runner.h" #include "base/test/task_environment.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/events/event_utils.h" #include "ui/events/platform/platform_event_dispatcher.h" #include "ui/events/platform/platform_event_observer.h" #include "ui/events/platform/scoped_event_dispatcher.h" @@ -25,12 +27,6 @@ namespace { -std::unique_ptr<PlatformEvent> CreatePlatformEvent() { - std::unique_ptr<PlatformEvent> event = std::make_unique<PlatformEvent>(); - memset(event.get(), 0, sizeof(PlatformEvent)); - return event; -} - void RemoveDispatcher(PlatformEventDispatcher* dispatcher) { PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(dispatcher); } @@ -60,9 +56,7 @@ class TestPlatformEventDispatcher : public PlatformEventDispatcher { public: TestPlatformEventDispatcher(int id, std::vector<int>* list) - : id_(id), - list_(list), - post_dispatch_action_(POST_DISPATCH_NONE) { + : id_(id), list_(list) { PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this); } @@ -90,7 +84,7 @@ private: int id_; raw_ptr<std::vector<int>> list_; - uint32_t post_dispatch_action_; + uint32_t post_dispatch_action_ = POST_DISPATCH_NONE; }; class TestPlatformEventObserver : public PlatformEventObserver { @@ -123,12 +117,12 @@ class PlatformEventTest : public testing::Test { public: - PlatformEventTest() {} + PlatformEventTest() = default; PlatformEventTest(const PlatformEventTest&) = delete; PlatformEventTest& operator=(const PlatformEventTest&) = delete; - ~PlatformEventTest() override {} + ~PlatformEventTest() override = default; TestPlatformEventSource* source() { return source_.get(); } @@ -145,20 +139,20 @@ // Tests that a dispatcher receives an event. TEST_F(PlatformEventTest, DispatcherBasic) { std::vector<int> list_dispatcher; - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); EXPECT_EQ(0u, list_dispatcher.size()); { TestPlatformEventDispatcher dispatcher(1, &list_dispatcher); - event = CreatePlatformEvent(); + event = CreateInvalidPlatformEvent(); source()->Dispatch(*event); ASSERT_EQ(1u, list_dispatcher.size()); EXPECT_EQ(1, list_dispatcher[0]); } list_dispatcher.clear(); - event = CreatePlatformEvent(); + event = CreateInvalidPlatformEvent(); source()->Dispatch(*event); EXPECT_EQ(0u, list_dispatcher.size()); } @@ -172,7 +166,7 @@ dispatchers.push_back( std::make_unique<TestPlatformEventDispatcher>(id, &list_dispatcher)); } - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(std::size(sequence), list_dispatcher.size()); EXPECT_EQ(std::vector<int>(sequence, sequence + std::size(sequence)), @@ -186,7 +180,7 @@ TestPlatformEventDispatcher first(12, &list_dispatcher); TestPlatformEventDispatcher second(23, &list_dispatcher); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(2u, list_dispatcher.size()); EXPECT_EQ(12, list_dispatcher[0]); @@ -194,7 +188,7 @@ list_dispatcher.clear(); first.set_post_dispatch_action(POST_DISPATCH_STOP_PROPAGATION); - event = CreatePlatformEvent(); + event = CreateInvalidPlatformEvent(); source()->Dispatch(*event); ASSERT_EQ(1u, list_dispatcher.size()); EXPECT_EQ(12, list_dispatcher[0]); @@ -203,20 +197,20 @@ // Tests that observers receive events. TEST_F(PlatformEventTest, ObserverBasic) { std::vector<int> list_observer; - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); EXPECT_EQ(0u, list_observer.size()); { TestPlatformEventObserver observer(31, &list_observer); - event = CreatePlatformEvent(); + event = CreateInvalidPlatformEvent(); source()->Dispatch(*event); ASSERT_EQ(1u, list_observer.size()); EXPECT_EQ(31, list_observer[0]); } list_observer.clear(); - event = CreatePlatformEvent(); + event = CreateInvalidPlatformEvent(); source()->Dispatch(*event); EXPECT_EQ(0u, list_observer.size()); } @@ -230,7 +224,7 @@ observers.push_back( std::make_unique<TestPlatformEventObserver>(id, &list_observer)); } - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(std::size(sequence), list_observer.size()); EXPECT_EQ(std::vector<int>(sequence, sequence + std::size(sequence)), @@ -244,7 +238,7 @@ TestPlatformEventObserver first_o(10, &list); TestPlatformEventDispatcher second_d(23, &list); TestPlatformEventObserver second_o(20, &list); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); const int expected[] = {10, 20, 12, 23}; EXPECT_EQ(std::vector<int>(expected, expected + std::size(expected)), list); @@ -256,7 +250,7 @@ std::vector<int> list; TestPlatformEventDispatcher dispatcher(10, &list); TestPlatformEventObserver observer(15, &list); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(2u, list.size()); EXPECT_EQ(15, list[0]); @@ -285,7 +279,7 @@ source()->OverrideDispatcher(&overriding_dispatcher); overriding_dispatcher.set_post_dispatch_action(POST_DISPATCH_PERFORM_DEFAULT); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); // First the observer, then the overriding dispatcher, then the default // dispatcher. @@ -357,7 +351,7 @@ second.set_callback( base::BindOnce(&RemoveDispatcher, base::Unretained(&third))); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); // |second| removes |third| from the dispatcher list during dispatch. So the // event should only reach |first|, |second|, and |fourth|. @@ -378,7 +372,7 @@ second.set_callback( base::BindOnce(&RemoveDispatcher, base::Unretained(&second))); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); // |second| removes itself from the dispatcher list during dispatch. So the // event should reach all three dispatchers in the list. @@ -399,7 +393,7 @@ second.set_callback( base::BindOnce(&RemoveDispatcher, base::Unretained(&second))); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); // |second| removes itself during dispatch. So both dispatchers will have // received the event. @@ -419,7 +413,7 @@ second.set_callback( base::BindOnce(&RemoveDispatcher, base::Unretained(&first))); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); // |second| removes |first| from the dispatcher list during dispatch. The // event should reach all three dispatchers. @@ -441,7 +435,7 @@ third.set_callback(base::BindOnce( &RemoveDispatchers, base::Unretained(&first), base::Unretained(&second))); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); // |third| removes |first| and |second| from the dispatcher list during // dispatch. The event should reach all three dispatchers. @@ -462,7 +456,7 @@ TestPlatformEventDispatcher fourth(30, &list); RemoveDispatchers(&third, &fourth); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(2u, list.size()); EXPECT_EQ(10, list[0]); @@ -540,7 +534,7 @@ std::unique_ptr<ScopedEventDispatcher> second_override_handle = source()->OverrideDispatcher(&second_overriding); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(2u, list.size()); EXPECT_EQ(15, list[0]); @@ -603,7 +597,7 @@ public: void NestedTask(std::unique_ptr<ScopedEventDispatcher> dispatch_handle, std::vector<int>* list) { - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(2u, list->size()); EXPECT_EQ(15, (*list)[0]); @@ -660,7 +654,7 @@ std::unique_ptr<ScopedEventDispatcher> override_handle = source()->OverrideDispatcher(&overriding); - std::unique_ptr<PlatformEvent> event = CreatePlatformEvent(); + absl::optional<PlatformEvent> event(CreateInvalidPlatformEvent()); source()->Dispatch(*event); ASSERT_EQ(2u, list.size()); EXPECT_EQ(15, list[0]);
diff --git a/ui/events/platform_event.h b/ui/events/platform_event.h index 189a876..898199bd 100644 --- a/ui/events/platform_event.h +++ b/ui/events/platform_event.h
@@ -13,18 +13,8 @@ #if BUILDFLAG(IS_WIN) #include "base/win/windows_types.h" -#elif BUILDFLAG(IS_MAC) -#if defined(__OBJC__) -@class NSEvent; -#else // __OBJC__ -class NSEvent; -#endif // __OBJC__ -#elif BUILDFLAG(IS_IOS) -#if defined(__OBJC__) -@class UIEvent; -#else // __OBJC__ -class UIEvent; -#endif // __OBJC__ +#elif BUILDFLAG(IS_APPLE) +#include "base/apple/owned_objc.h" #endif namespace ui { @@ -39,9 +29,9 @@ #elif BUILDFLAG(IS_WIN) using PlatformEvent = CHROME_MSG; #elif BUILDFLAG(IS_MAC) -using PlatformEvent = NSEvent*; +using PlatformEvent = base::apple::OwnedNSEvent; #elif BUILDFLAG(IS_IOS) -using PlatformEvent = UIEvent*; +using PlatformEvent = base::apple::OwnedUIEvent; #else using PlatformEvent = void*; #endif
diff --git a/ui/events/win/events_win.cc b/ui/events/win/events_win.cc index e11ba47..93053ba 100644 --- a/ui/events/win/events_win.cc +++ b/ui/events/win/events_win.cc
@@ -4,6 +4,7 @@ #include "base/notreached.h" #include "ui/events/event_utils.h" +#include "ui/events/platform_event.h" #include "ui/events/win/events_win_utils.h" namespace ui { @@ -69,11 +70,20 @@ return GetMouseWheelOffsetFromMSG(native_event); } -CHROME_MSG CopyNativeEvent(const CHROME_MSG& event) { - return CopyMSGEvent(event); +bool ShouldCopyPlatformEvents() { + return true; } -void ReleaseCopiedNativeEvent(const CHROME_MSG& event) {} +PlatformEvent CreateInvalidPlatformEvent() { + CHROME_MSG msg = {0}; + return msg; +} + +bool IsPlatformEventValid(const PlatformEvent& event) { + return !(event.hwnd == 0 && event.message == 0 && event.wParam == 0 && + event.lParam == 0 && event.time == 0 && event.pt.x == 0 && + event.pt.y == 0); +} PointerDetails GetTouchPointerDetailsFromNative( const CHROME_MSG& native_event) {
diff --git a/ui/events/win/events_win_utils.cc b/ui/events/win/events_win_utils.cc index 6288628..ad3439c 100644 --- a/ui/events/win/events_win_utils.cc +++ b/ui/events/win/events_win_utils.cc
@@ -391,12 +391,6 @@ return gfx::Vector2d(GET_WHEEL_DELTA_WPARAM(native_event.wParam), 0); } -CHROME_MSG CopyMSGEvent(const CHROME_MSG& event) { - return event; -} - -void ReleaseCopiedMSGEvent(const CHROME_MSG& event) {} - void ClearTouchIdIfReleasedFromMSG(const CHROME_MSG& xev) { NOTIMPLEMENTED(); }
diff --git a/ui/events/win/events_win_utils.h b/ui/events/win/events_win_utils.h index c407a30..0f413f2 100644 --- a/ui/events/win/events_win_utils.h +++ b/ui/events/win/events_win_utils.h
@@ -93,13 +93,6 @@ EVENTS_EXPORT gfx::Vector2d GetMouseWheelOffsetFromMSG( const CHROME_MSG& native_event); -// Returns a copy of |native_event|. Depending on the platform, this copy may -// need to be deleted with ReleaseCopiedMSGEvent(). -EVENTS_EXPORT CHROME_MSG CopyMSGEvent(const CHROME_MSG& native_event); - -// Delete a |native_event| previously created by CopyMSGEvent(). -EVENTS_EXPORT void ReleaseCopiedMSGEvent(const CHROME_MSG& native_event); - // Returns the detailed pointer information for touch events. EVENTS_EXPORT PointerDetails GetTouchPointerDetailsFromMSG(const CHROME_MSG& native_event);
diff --git a/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h index 6a546bda..377331a 100644 --- a/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h +++ b/ui/ozone/platform/wayland/host/shell_toplevel_wrapper.h
@@ -146,9 +146,11 @@ // screen coordinates. virtual bool SupportsScreenCoordinates() const = 0; +#if BUILDFLAG(IS_CHROMEOS_LACROS) // Enables screen coordinates support. This is no-op if the server does not // support the screen coordinates. virtual void EnableScreenCoordinates() = 0; +#endif // Sets/usets a native window to float state. This places it on top of other // windows.
diff --git a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc index faaa0356..f778101 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen_unittest.cc
@@ -14,7 +14,6 @@ #include "ui/display/display.h" #include "ui/display/display_observer.h" #include "ui/display/display_switches.h" -#include "ui/display/types/display_constants.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/native_widget_types.h" @@ -1002,6 +1001,9 @@ display::Display::ResetForceDeviceScaleFactorForTesting(); } +// Lacros uses screen coordinates so this test doesn't make any sense there. +#if !BUILDFLAG(IS_CHROMEOS_LACROS) + // Regression test for https://crbug.com/1346534. // // Scenario: With (at least) one output connected and a surface, with no output @@ -1040,6 +1042,8 @@ EXPECT_EQ(window_->ui_scale(), 2); } +#endif // !BUILDFLAG(IS_CHROMEOS_LACROS) + // Checks that output transform is properly translated into Display orientation. // The first one is counter-clockwise, while the latter is clockwise. TEST_P(WaylandScreenTest, Transform) { @@ -1109,6 +1113,8 @@ EXPECT_EQ(3u, platform_screen_->GetAllDisplays().size()); } +#if BUILDFLAG(IS_CHROMEOS_LACROS) + class WaylandAuraShellScreenTest : public WaylandScreenTest { public: void SetUp() override { @@ -1307,9 +1313,6 @@ } TEST_P(WaylandAuraShellScreenTest, UseCorrectScreenBeforeEnterEvent) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kWaylandScreenCoordinatesEnabled); - // These have to be stored on the client thread, but must be used only on the // server thread. wl::TestOutput* output1 = nullptr; @@ -1350,10 +1353,14 @@ EXPECT_EQ(2.f, window_->ui_scale()); } +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, WaylandScreenTest, Values(wl::ServerConfig{})); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + INSTANTIATE_TEST_SUITE_P( XdgVersionStableTestWithAuraShell, WaylandScreenTest, @@ -1372,4 +1379,6 @@ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, .use_aura_output_manager = true})); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc index 2608064..840b5ec6 100644 --- a/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc +++ b/ui/ozone/platform/wayland/host/wayland_toplevel_window.cc
@@ -69,8 +69,7 @@ WaylandConnection* connection) : WaylandWindow(delegate, connection), state_(PlatformWindowState::kNormal), - screen_coordinates_enabled_( - features::IsWaylandScreenCoordinatesEnabled()) { + screen_coordinates_enabled_(kDefaultScreenCoordinateEnabled) { // Set a class property key, which allows |this| to be used for interactive // events, e.g. move or resize. SetWmMoveResizeHandler(this, AsWmMoveResizeHandler()); @@ -90,11 +89,15 @@ LOG(ERROR) << "Failed to create a ShellToplevel."; return false; } + +#if BUILDFLAG(IS_CHROMEOS_LACROS) screen_coordinates_enabled_ &= shell_toplevel_->SupportsScreenCoordinates(); screen_coordinates_enabled_ &= !use_native_frame_; - if (screen_coordinates_enabled_) + if (screen_coordinates_enabled_) { shell_toplevel_->EnableScreenCoordinates(); + } +#endif #if BUILDFLAG(IS_CHROMEOS_LACROS) shell_toplevel_->SetAppId(window_unique_id_);
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc index 4a7f27d9..217fb7c9 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -272,10 +272,15 @@ return; // Forward cursor location update info to the input handling delegate. +#if BUILDFLAG(IS_CHROMEOS_LACROS) should_process_drag_motion_events_ = - !(features::IsWaylandScreenCoordinatesEnabled() && - static_cast<WaylandToplevelWindow*>(drag_target_window_) + !(static_cast<WaylandToplevelWindow*>(drag_target_window_) ->IsScreenCoordinatesEnabled()); +#else + // non-lacros platforms never use global coordinates so they always process + // drag events. + should_process_drag_motion_events_ = true; +#endif pointer_location_ = location;
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc index 3efba839..efa8c1a 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -77,6 +77,33 @@ MockWaylandPlatformWindowDelegate& delegate() { return delegate_; } WaylandWindow* window() { return window_.get(); } + void SendPointerMotion(WaylandWindow* window, + MockPlatformWindowDelegate* delegate, + gfx::Point location, + bool ensure_dispatched = true) { + if (ensure_dispatched) { + EXPECT_CALL(*delegate, DispatchEvent(_)).WillOnce([](Event* event) { + EXPECT_TRUE(event->IsMouseEvent()); + EXPECT_EQ(ET_MOUSE_DRAGGED, event->type()); + }); + } + + PostToServerAndWait([location](wl::TestWaylandServerThread* server) { + wl_fixed_t x = wl_fixed_from_int(location.x()); + wl_fixed_t y = wl_fixed_from_int(location.y()); + ASSERT_TRUE(server->seat()->pointer()); + wl_resource* pointer_resource = server->seat()->pointer()->resource(); + wl_pointer_send_motion(pointer_resource, server->GetNextTime(), x, y); + wl_pointer_send_frame(pointer_resource); + }); + + if (ensure_dispatched) { + Mock::VerifyAndClearExpectations(delegate); + EXPECT_EQ(window->GetWidget(), + screen_->GetLocalProcessWidgetAtPoint(location, {})); + } + } + protected: using State = WaylandWindowDragController::State; @@ -109,33 +136,6 @@ window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } - void SendPointerMotion(WaylandWindow* window, - MockPlatformWindowDelegate* delegate, - gfx::Point location, - bool ensure_dispatched = true) { - if (ensure_dispatched) { - EXPECT_CALL(*delegate, DispatchEvent(_)).WillOnce([](Event* event) { - EXPECT_TRUE(event->IsMouseEvent()); - EXPECT_EQ(ET_MOUSE_DRAGGED, event->type()); - }); - } - - PostToServerAndWait([location](wl::TestWaylandServerThread* server) { - wl_fixed_t x = wl_fixed_from_int(location.x()); - wl_fixed_t y = wl_fixed_from_int(location.y()); - ASSERT_TRUE(server->seat()->pointer()); - wl_resource* pointer_resource = server->seat()->pointer()->resource(); - wl_pointer_send_motion(pointer_resource, server->GetNextTime(), x, y); - wl_pointer_send_frame(pointer_resource); - }); - - if (ensure_dispatched) { - Mock::VerifyAndClearExpectations(delegate); - EXPECT_EQ(window->GetWidget(), - screen_->GetLocalProcessWidgetAtPoint(location, {})); - } - } - // TODO(crbug.com/1116431): Support extended-drag in test compositor. void SendTouchDown(WaylandWindow* window, @@ -163,11 +163,18 @@ } }; +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_DragInsideWindowAndDrop DISABLED_DragInsideWindowAndDrop +#else +#define MAYBE_DragInsideWindowAndDrop DragInsideWindowAndDrop +#endif // Check the following flow works as expected: // 1. With a single 1 window open, // 2. Move pointer into it, press left button, move cursor a bit (drag), // 3. Run move loop, drag it within the window bounds and drop. -TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) { +TEST_P(WaylandWindowDragControllerTest, MAYBE_DragInsideWindowAndDrop) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -255,11 +262,19 @@ screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_DragInsideWindowAndDrop_TOUCH \ + DISABLED_DragInsideWindowAndDrop_TOUCH +#else +#define MAYBE_DragInsideWindowAndDrop_TOUCH DragInsideWindowAndDrop_TOUCH +#endif // Check the following flow works as expected: // 1. With a single window open, // 2. Touch down and move the touch point a bit (drag), // 3. Run move loop, drag it within the window bounds and drop. -TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop_TOUCH) { +TEST_P(WaylandWindowDragControllerTest, MAYBE_DragInsideWindowAndDrop_TOUCH) { ASSERT_TRUE(GetWmMoveLoopHandler(*window_)); ASSERT_TRUE(GetWaylandExtension(*window_)); @@ -432,6 +447,13 @@ SendTouchUp(0 /*touch id*/); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_DragExitWindowAndDrop DISABLED_DragExitWindowAndDrop +#else +#define MAYBE_DragExitWindowAndDrop DragExitWindowAndDrop +#endif // Check the following flow works as expected: // 1. With only 1 window open; // 2. Move pointer into it, press left button, move cursor a bit (drag); @@ -439,7 +461,7 @@ // 4. Drag pointer to outside the window and release the mouse button, and make // sure RELEASE and EXIT mouse events are delivered even when the drop // happens outside the bounds of any surface. -TEST_P(WaylandWindowDragControllerTest, DragExitWindowAndDrop) { +TEST_P(WaylandWindowDragControllerTest, MAYBE_DragExitWindowAndDrop) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -528,6 +550,14 @@ screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_DragToOtherWindowSnapDragDrop \ + DISABLED_DragToOtherWindowSnapDragDrop +#else +#define MAYBE_DragToOtherWindowSnapDragDrop DragToOtherWindowSnapDragDrop +#endif // Check the following flow works as expected: // 1. With 2 windows open, // 2. Focus window 1, starts dragging, @@ -536,7 +566,7 @@ // 5. Drag it a bit more (within window 2) and then calls EndMoveLoop(), // emulating a window snap), and then // 6. With the window in "snapped" state, drag it further and then drop. -TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop) { +TEST_P(WaylandWindowDragControllerTest, MAYBE_DragToOtherWindowSnapDragDrop) { // Init and open |target_window|. PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; properties.type = PlatformWindowType::kWindow; @@ -693,6 +723,15 @@ screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_DragToOtherWindowSnapDragDrop_TOUCH \ + DISABLED_DragToOtherWindowSnapDragDrop_TOUCH +#else +#define MAYBE_DragToOtherWindowSnapDragDrop_TOUCH \ + DragToOtherWindowSnapDragDrop_TOUCH +#endif // Check the following flow works as expected: // 1. With 2 windows open, // 2. Focus window 1, starts dragging, @@ -701,7 +740,8 @@ // 5. Drag it a bit more (within window 2) and then calls EndMoveLoop(), // emulating a window snap), and then // 6. With the window in "snapped" state, drag it further and then drop. -TEST_P(WaylandWindowDragControllerTest, DragToOtherWindowSnapDragDrop_TOUCH) { +TEST_P(WaylandWindowDragControllerTest, + MAYBE_DragToOtherWindowSnapDragDrop_TOUCH) { // Init and open |target_window|. PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; properties.type = PlatformWindowType::kWindow; @@ -823,6 +863,15 @@ EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_DragToOtherWindowIgnoringSpuriousPointerEnterEvent \ + DISABLED_DragToOtherWindowIgnoringSpuriousPointerEnterEvent +#else +#define MAYBE_DragToOtherWindowIgnoringSpuriousPointerEnterEvent \ + DragToOtherWindowIgnoringSpuriousPointerEnterEvent +#endif // Check the following flow works as expected: // 1. With 2 windows open, // 2. Focus window 1, starts dragging, @@ -833,7 +882,7 @@ // 6. Drag it a bit more (within window 2) and then calls EndMoveLoop(), // emulating a window snap), and then drop. TEST_P(WaylandWindowDragControllerTest, - DragToOtherWindowIgnoringSpuriousPointerEnterEvent) { + MAYBE_DragToOtherWindowIgnoringSpuriousPointerEnterEvent) { // Init and open |target_window|. PlatformWindowInitProperties properties{gfx::Rect{80, 80}}; properties.type = PlatformWindowType::kWindow; @@ -1071,6 +1120,13 @@ EXPECT_EQ(PlatformWindowState::kMaximized, window_->GetPlatformWindowState()); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_IgnorePointerEventsUntilDrop DISABLED_IgnorePointerEventsUntilDrop +#else +#define MAYBE_IgnorePointerEventsUntilDrop IgnorePointerEventsUntilDrop +#endif // Check the following flow works as expected: // // 1. With a single 1 window open, @@ -1081,7 +1137,7 @@ // // Verifies window drag controller is resistant to issues such as // https://crbug.com/1148021. -TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) { +TEST_P(WaylandWindowDragControllerTest, MAYBE_IgnorePointerEventsUntilDrop) { // Ensure there is no window currently focused EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, @@ -1170,16 +1226,14 @@ // it must complete before getting the below commands processed by the // server and received by the client. Thus, prepare a task to avoid that // and let the WaylandWindowDragController to do what it needs to do. - base::OnceClosure send_pointer_motion_30_30 = base::BindOnce( - &WaylandWindowDragControllerTest_IgnorePointerEventsUntilDrop_Test:: - SendPointerMotion, - base::Unretained(this), nullptr, nullptr, gfx::Point(30, 30), - false); - base::OnceClosure send_pointer_motion_20_20 = base::BindOnce( - &WaylandWindowDragControllerTest_IgnorePointerEventsUntilDrop_Test:: - SendPointerMotion, - base::Unretained(this), nullptr, nullptr, gfx::Point(20, 20), - false); + base::OnceClosure send_pointer_motion_30_30 = + base::BindOnce(&WaylandWindowDragControllerTest::SendPointerMotion, + base::Unretained(this), nullptr, nullptr, + gfx::Point(30, 30), false); + base::OnceClosure send_pointer_motion_20_20 = + base::BindOnce(&WaylandWindowDragControllerTest::SendPointerMotion, + base::Unretained(this), nullptr, nullptr, + gfx::Point(20, 20), false); base::OnceClosure send_drop = base::BindOnce( &WaylandDragDropTest::SendDndDrop, base::Unretained(this)); @@ -1213,8 +1267,18 @@ screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_MotionEventsSkippedWhileReattaching \ + DISABLED_MotionEventsSkippedWhileReattaching +#else +#define MAYBE_MotionEventsSkippedWhileReattaching \ + MotionEventsSkippedWhileReattaching +#endif // Regression test for https://crbug.com/1169446. -TEST_P(WaylandWindowDragControllerTest, MotionEventsSkippedWhileReattaching) { +TEST_P(WaylandWindowDragControllerTest, + MAYBE_MotionEventsSkippedWhileReattaching) { auto* dragged_window = window_.get(); EXPECT_TRUE(dragged_window); @@ -1279,9 +1343,17 @@ EXPECT_EQ(State::kIdle, drag_controller()->state()); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_CursorPositionIsUpdatedOnMotion \ + DISABLED_CursorPositionIsUpdatedOnMotion +#else +#define MAYBE_CursorPositionIsUpdatedOnMotion CursorPositionIsUpdatedOnMotion +#endif // Test that cursor position is using DIP coordinates and is updated correctly // on DragMotion event. -TEST_P(WaylandWindowDragControllerTest, CursorPositionIsUpdatedOnMotion) { +TEST_P(WaylandWindowDragControllerTest, MAYBE_CursorPositionIsUpdatedOnMotion) { constexpr gfx::Rect kOutputBounds(0, 0, 1920, 1080); PostToServerAndWait([&](wl::TestWaylandServerThread* server) { // Configure the first output with scale 1. @@ -1450,10 +1522,19 @@ screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_HandleWindowsDestructionDuringMoveLoop \ + DISABLED_HandleWindowsDestructionDuringMoveLoop +#else +#define MAYBE_HandleWindowsDestructionDuringMoveLoop \ + HandleWindowsDestructionDuringMoveLoop +#endif // Ensure no memory issues happen when the dragged and/or events grabber windows // get destroyed while the move loop is running. TEST_P(WaylandWindowDragControllerTest, - HandleWindowsDestructionDuringMoveLoop) { + MAYBE_HandleWindowsDestructionDuringMoveLoop) { // 1. Send some initial pointer events to |window_|. ASSERT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); SendPointerEnter(window_.get(), &delegate_); @@ -1659,11 +1740,20 @@ ASSERT_EQ(State::kIdle, drag_controller()->state()); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_HandleTargetWindowDestruction_DetachedState \ + DISABLED_HandleTargetWindowDestruction_DetachedState +#else +#define MAYBE_HandleTargetWindowDestruction_DetachedState \ + HandleTargetWindowDestruction_DetachedState +#endif // Ensure events are handled appropriately when the target window is destroyed // while the move loop is running (i.e. dragging in the detached state). // Regression test for crbug.com/1433577. TEST_P(WaylandWindowDragControllerTest, - HandleTargetWindowDestruction_DetachedState) { + MAYBE_HandleTargetWindowDestruction_DetachedState) { // Send some initial pointer events to `window_`. ASSERT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); SendPointerEnter(window_.get(), &delegate_);
diff --git a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc index b6dcb0a..7d93e75 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_unittest.cc
@@ -3445,9 +3445,16 @@ }); } +// TODO(https://crbug.com/1448391): Reenable for Lacros when adjusted for screen +// coordinates. +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#define MAYBE_SetsPropertiesOnShow DISABLED_SetsPropertiesOnShow +#else +#define MAYBE_SetsPropertiesOnShow SetsPropertiesOnShow +#endif // Tests that if the window gets hidden and shown again, the title, app id and // size constraints remain the same. -TEST_P(WaylandWindowTest, SetsPropertiesOnShow) { +TEST_P(WaylandWindowTest, MAYBE_SetsPropertiesOnShow) { constexpr char kAppId[] = "wayland_test"; const std::u16string kTitle(u"WaylandWindowTest"); @@ -4591,6 +4598,8 @@ INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, WaylandWindowTest, Values(wl::ServerConfig{})); + +#if BUILDFLAG(IS_CHROMEOS_LACROS) INSTANTIATE_TEST_SUITE_P( XdgVersionStableTestWithAuraShell, WaylandWindowTest, @@ -4599,9 +4608,13 @@ wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, .use_aura_output_manager = true})); +#endif + INSTANTIATE_TEST_SUITE_P(XdgVersionStableTest, WaylandSubsurfaceTest, Values(wl::ServerConfig{})); + +#if BUILDFLAG(IS_CHROMEOS_LACROS) INSTANTIATE_TEST_SUITE_P( XdgVersionStableTestWithAuraShell, WaylandSubsurfaceTest, @@ -4610,4 +4623,6 @@ wl::ServerConfig{ .enable_aura_shell = wl::EnableAuraShellProtocol::kEnabled, .use_aura_output_manager = true})); +#endif + } // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_shell.h b/ui/ozone/platform/wayland/host/wayland_zaura_shell.h index f257021..42d113b5 100644 --- a/ui/ozone/platform/wayland/host/wayland_zaura_shell.h +++ b/ui/ozone/platform/wayland/host/wayland_zaura_shell.h
@@ -7,6 +7,7 @@ #include "base/containers/flat_set.h" #include "base/memory/raw_ptr.h" +#include "build/chromeos_buildflags.h" #include "ui/display/tablet_state.h" #include "ui/ozone/platform/wayland/common/wayland_object.h" @@ -14,6 +15,13 @@ class WaylandConnection; +constexpr bool kDefaultScreenCoordinateEnabled = +#if BUILDFLAG(IS_CHROMEOS_LACROS) + true; +#else + false; +#endif + // Wraps the zaura_shell object. class WaylandZAuraShell : public wl::GlobalObjectRegistrar<WaylandZAuraShell> { public:
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc index d84976f..244d518f 100644 --- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.cc
@@ -511,9 +511,8 @@ ZAURA_TOPLEVEL_SET_SUPPORTS_SCREEN_COORDINATES_SINCE_VERSION; } +#if BUILDFLAG(IS_CHROMEOS_LACROS) void XDGToplevelWrapperImpl::EnableScreenCoordinates() { - if (!features::IsWaylandScreenCoordinatesEnabled()) - return; if (!SupportsScreenCoordinates()) { LOG(WARNING) << "Server implementation of wayland is incompatible, " "WaylandScreenCoordinatesEnabled has no effect."; @@ -527,6 +526,7 @@ zaura_toplevel_add_listener(aura_toplevel_.get(), &aura_toplevel_listener, this); } +#endif void XDGToplevelWrapperImpl::SetZOrder(ZOrderLevel z_order) { if (aura_toplevel_ && zaura_toplevel_get_version(aura_toplevel_.get()) >=
diff --git a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h index 75a1426f..fe6cd3e1 100644 --- a/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h +++ b/ui/ozone/platform/wayland/host/xdg_toplevel_wrapper_impl.h
@@ -56,7 +56,9 @@ void SetRestoreInfoWithWindowIdSource(int32_t, const std::string&) override; void SetSystemModal(bool modal) override; bool SupportsScreenCoordinates() const override; +#if BUILDFLAG(IS_CHROMEOS_LACROS) void EnableScreenCoordinates() override; +#endif void SetFloat() override; void UnSetFloat() override; void SetZOrder(ZOrderLevel z_order) override;
diff --git a/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/ui/ozone/platform/wayland/ozone_platform_wayland.cc index c2511b3e..1de5c418 100644 --- a/ui/ozone/platform/wayland/ozone_platform_wayland.cc +++ b/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -310,8 +310,7 @@ // their position on screens and always assume they are located at some // arbitrary position. properties->supports_global_screen_coordinates = - features::IsWaylandScreenCoordinatesEnabled(); - + kDefaultScreenCoordinateEnabled; initialised = true; }
diff --git a/ui/ozone/platform/wayland/test/wayland_test.cc b/ui/ozone/platform/wayland/test/wayland_test.cc index 5a48ca4..0561a80 100644 --- a/ui/ozone/platform/wayland/test/wayland_test.cc +++ b/ui/ozone/platform/wayland/test/wayland_test.cc
@@ -60,7 +60,6 @@ void WaylandTestBase::SetUp() { disabled_features_.push_back(ui::kWaylandSurfaceSubmissionInPixelCoordinates); - disabled_features_.push_back(features::kWaylandScreenCoordinatesEnabled); feature_list_.InitWithFeatures(enabled_features_, disabled_features_);
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index 3b730a6..561b4a7 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -667,6 +667,7 @@ ] public_deps += [ "//components/remote_cocoa/common:mojo" ] deps += [ + "//base:base_arc", "//components/crash/core/common", "//components/remote_cocoa/app_shim", "//components/remote_cocoa/browser",
diff --git a/ui/views/event_monitor_mac.mm b/ui/views/event_monitor_mac.mm index 1ecf19a..9114b71 100644 --- a/ui/views/event_monitor_mac.mm +++ b/ui/views/event_monitor_mac.mm
@@ -8,6 +8,7 @@ #include <memory> +#include "base/apple/owned_objc.h" #include "base/check.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" @@ -57,7 +58,8 @@ } if (!target_window || [event window] == target_window) { - std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event); + std::unique_ptr<ui::Event> ui_event = + ui::EventFromNative(base::apple::OwnedNSEvent(event)); if (ui_event && types_.find(ui_event->type()) != types_.end()) { event_observer->OnEvent(*ui_event); }
diff --git a/ui/webui/resources/tools/bundle_js_test.py b/ui/webui/resources/tools/bundle_js_test.py index bc71634..1e9a8876 100755 --- a/ui/webui/resources/tools/bundle_js_test.py +++ b/ui/webui/resources/tools/bundle_js_test.py
@@ -17,213 +17,88 @@ class BundleJsTest(unittest.TestCase): def setUp(self): - self._tmp_dirs = [] - self._tmp_src_dir = None - self._out_folder = self._create_tmp_dir() + self._out_folder = tempfile.mkdtemp(dir=_HERE_DIR) def tearDown(self): - for tmp_dir in self._tmp_dirs: - shutil.rmtree(tmp_dir) - - def _write_file_to_dir(self, file_path, file_contents): - file_dir = os.path.dirname(file_path) - if not os.path.exists(file_dir): - os.makedirs(file_dir) - with open(file_path, 'w') as tmp_file: - tmp_file.write(file_contents) - - def _write_file_to_src_dir(self, file_path, file_contents): - if not self._tmp_src_dir: - self._tmp_src_dir = self._create_tmp_dir() - file_path_normalized = os.path.normpath( - os.path.join(self._tmp_src_dir, file_path)) - self._write_file_to_dir(file_path_normalized, file_contents) - - def _create_tmp_dir(self): - # TODO(dbeam): support cross-drive paths (i.e. d:\ vs c:\). - tmp_dir = tempfile.mkdtemp(dir=_HERE_DIR) - self._tmp_dirs.append(tmp_dir) - return tmp_dir + shutil.rmtree(self._out_folder) def _read_out_file(self, file_name): assert self._out_folder with open(os.path.join(self._out_folder, file_name), 'r') as f: return f.read() + def _check_dep_file(self, paths_from_test_dir, depfile_content): + for path in paths_from_test_dir: + abs_path = os.path.join(_HERE_DIR, 'tests', 'bundle_js', path) + rel_path = os.path.relpath(abs_path, _CWD) + self.assertIn(os.path.normpath(rel_path), depfile_content) + def _run_bundle(self, input_args): - # TODO(dbeam): make it possible to _run_bundle twice? Is that useful? + input_path = os.path.join(_HERE_DIR, 'tests', 'bundle_js', 'src') + resources_path = os.path.join(_HERE_DIR, 'tests', 'bundle_js', 'resources') + custom_dir_foo = os.path.join(_HERE_DIR, 'tests', 'bundle_js', 'external', + 'foo') + custom_dir_bar = os.path.join(_HERE_DIR, 'tests', 'bundle_js', 'external', + 'bar') args = input_args + [ '--depfile', os.path.join(self._out_folder, 'depfile.d'), '--target_name', 'dummy_target_name', '--input', - self._tmp_src_dir, + input_path, '--out_folder', self._out_folder, + '--external_paths', + '//resources|%s' % resources_path, + 'chrome://resources|%s' % resources_path, + 'chrome-untrusted://resources|%s' % resources_path, + 'some-fake-scheme://foo|%s' % os.path.abspath(custom_dir_foo), + 'some-fake-scheme://bar|%s' % os.path.abspath(custom_dir_bar), ] bundle_js.main(args) - def _write_files_to_src_dir(self): - self._write_file_to_src_dir('element.js', "alert('yay');") - self._write_file_to_src_dir('element_in_dir/element_in_dir.js', - "alert('hello from element_in_dir');") - self._write_file_to_src_dir( - 'ui.js', ''' -import './element.js'; -import './element_in_dir/element_in_dir.js'; -''') - self._write_file_to_src_dir( - 'ui.html', ''' -<script type="module" src="ui.js"></script> -''') - - def _write_files_with_custom_path_to_src_dir(self, custom_path): - self._write_file_to_dir( - os.path.join(custom_path, 'external_dir', 'external_element.js'), ''' -import './sub_dir/external_element_dep.js'; -alert('hello from external_element'); -''') - - self._write_file_to_dir( - os.path.join(custom_path, 'external_dir', 'sub_dir', - 'external_element_dep.js'), - "alert('hello from external_element_dep');") - - self._write_file_to_src_dir('element.js', "alert('yay');") - self._write_file_to_src_dir( - 'ui.js', ''' -import './element.js'; -import 'some-fake-scheme://foo/external_dir/external_element.js'; -''') - self._write_file_to_src_dir( - 'ui.html', ''' -<script type="module" src="ui.js"></script> -''') - - def _write_files_with_resources_to_src_dir(self, resources_scheme): - resources_path = os.path.join( - _HERE_DIR.replace('\\', '/'), 'gen', 'ui', 'webui', 'resources', 'tsc', - 'js') - fake_resource_path = os.path.join(resources_path, 'fake_resource.js') - scheme_relative_resource_path = os.path.join(resources_path, - 'scheme_relative_resource.js') - os.makedirs(os.path.dirname(resources_path)) - - self._tmp_dirs.append('gen') - self._write_file_to_dir( - fake_resource_path, ''' -export const foo = 5; -alert('hello from shared resource');''') - self._write_file_to_dir( - scheme_relative_resource_path, ''' -export const bar = 6; -alert('hello from another shared resource');''') - - self._write_file_to_src_dir( - 'element.js', ''' -import '%s//resources/js/fake_resource.js'; -import {bar} from '//resources/js/scheme_relative_resource.js'; -alert('yay ' + bar); -''' % resources_scheme) - self._write_file_to_src_dir( - 'element_in_dir/element_in_dir.js', ''' -import {foo} from '%s//resources/js/fake_resource.js'; -import '../strings.m.js'; -alert('hello from element_in_dir ' + foo); -''' % resources_scheme) - self._write_file_to_src_dir( - 'ui.js', ''' -import './strings.m.js'; -import './element.js'; -import './element_in_dir/element_in_dir.js'; -''') - self._write_file_to_src_dir( - 'ui.html', ''' -<script type="module" src="ui.js"></script> -''') - - def _check_output_html(self, out_html): - self.assertNotIn('element.html', out_html) - self.assertNotIn('element.js', out_html) - self.assertNotIn('element_in_dir.html', out_html) - self.assertNotIn('element_in_dir.js', out_html) - self.assertIn('got here!', out_html) - - def _check_output_js(self, output_js_name): - output_js = self._read_out_file(output_js_name) - self.assertIn('yay', output_js) - self.assertIn('hello from element_in_dir', output_js) - - def _check_output_depfile(self, has_html): - depfile_d = self._read_out_file('depfile.d') - self.assertIn('element.js', depfile_d) - self.assertIn( - os.path.normpath('element_in_dir/element_in_dir.js'), depfile_d) - if (has_html): - self.assertIn('element.html', depfile_d) - self.assertIn( - os.path.normpath('element_in_dir/element_in_dir.html'), depfile_d) - def testSimpleBundle(self): - self._write_files_to_src_dir() args = [ '--host', 'fake-host', '--js_module_in_files', - 'ui.js', + 'foo_ui.js', ] self._run_bundle(args) - self._check_output_js('ui.rollup.js') - self._check_output_depfile(False) + output_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from src/foo.js', output_js) + self.assertIn('Hello from src/subdir/baz.js', output_js) + + depfile_d = self._read_out_file('depfile.d') + self._check_dep_file(['src/foo.js', 'src/subdir/baz.js'], depfile_d) def testBundleWithResources(self): - self._write_files_with_resources_to_src_dir('chrome:') - resources_path = os.path.join('gen', 'ui', 'webui', 'resources', 'tsc') + resources_path = './tests/bundle_js/resources' args = [ '--host', 'fake-host', '--js_module_in_files', - 'ui.js', - '--external_paths', - 'chrome://resources|%s' % resources_path, + 'foo_ui.js', ] self._run_bundle(args) - ui_rollup_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', ui_rollup_js) - self.assertIn('hello from element_in_dir', ui_rollup_js) - self.assertIn('hello from shared resource', ui_rollup_js) + ui_rollup_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from resources/foo_resource.js', ui_rollup_js) + self.assertIn('Hello from resources/bar_resource.js', ui_rollup_js) depfile_d = self._read_out_file('depfile.d') - self.assertIn('element.js', depfile_d) - self.assertIn( - os.path.normpath('element_in_dir/element_in_dir.js'), depfile_d) - self.assertIn( - os.path.normpath( - 'gen/ui/webui/resources/tsc/js/scheme_relative_resource.js'), - depfile_d) - self.assertIn( - os.path.normpath('gen/ui/webui/resources/tsc/js/fake_resource.js'), - depfile_d) + self._check_dep_file( + ['resources/foo_resource.js', 'resources/bar_resource.js'], depfile_d) def testMultiBundleBundle(self): - self._write_files_to_src_dir() - self._write_file_to_src_dir('lazy_element.js', - "alert('hello from lazy_element');") - self._write_file_to_src_dir( - 'lazy.js', ''' -import './lazy_element.js'; -import './element_in_dir/element_in_dir.js'; -''') - args = [ '--host', 'fake-host', '--js_module_in_files', - 'ui.js', - 'lazy.js', + 'foo_ui.js', + 'bar_ui.js', '--out-manifest', os.path.join(self._out_folder, 'out_manifest.json'), ] @@ -231,213 +106,131 @@ # Check that the shared element is in the shared bundle and the non-shared # elements are in the individual bundles. - ui_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', ui_js) - self.assertNotIn('hello from lazy_element', ui_js) - self.assertNotIn('hello from element_in_dir', ui_js) + foo_ui_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from src/foo.js', foo_ui_js) + self.assertNotIn('Hello from src/bar.js', foo_ui_js) + self.assertNotIn('Hello from src/subdir/baz.js', foo_ui_js) - lazy_js = self._read_out_file('lazy.rollup.js') - self.assertNotIn('yay', lazy_js) - self.assertIn('hello from lazy_element', lazy_js) - self.assertNotIn('hello from element_in_dir', lazy_js) + bar_ui_js = self._read_out_file('bar_ui.rollup.js') + self.assertNotIn('Hello from src/foo.js', bar_ui_js) + self.assertIn('Hello from src/bar.js', bar_ui_js) + self.assertNotIn('Hello from src/subdir/baz.js', bar_ui_js) shared_js = self._read_out_file('shared.rollup.js') - self.assertNotIn('yay', shared_js) - self.assertNotIn('hello from lazy_element', shared_js) - self.assertIn('hello from element_in_dir', shared_js) + self.assertNotIn('Hello from src/foo.js', shared_js) + self.assertNotIn('Hello from src/bar.js', shared_js) + self.assertIn('Hello from src/subdir/baz.js', shared_js) # All 3 JS files should be in the depfile. - self._check_output_depfile(False) depfile_d = self._read_out_file('depfile.d') - self.assertIn('lazy_element.js', depfile_d) + self._check_dep_file(['src/foo.js', 'src/bar.js', 'src/subdir/baz.js'], + depfile_d) manifest = json.loads(self._read_out_file('out_manifest.json')) self.assertEqual(3, len(manifest['files'])) - self.assertTrue('lazy.rollup.js' in manifest['files']) - self.assertTrue('ui.rollup.js' in manifest['files']) + self.assertTrue('foo_ui.rollup.js' in manifest['files']) + self.assertTrue('bar_ui.rollup.js' in manifest['files']) self.assertTrue('shared.rollup.js' in manifest['files']) self.assertEqual( os.path.relpath(self._out_folder, _CWD).replace('\\', '/'), os.path.relpath(manifest['base_dir'], _CWD)) - def testBundleWithCustomPaths(self): - custom_dir = os.path.join(self._create_tmp_dir(), 'foo_root') - self._write_files_with_custom_path_to_src_dir(custom_dir) - resources_path = os.path.join('gen', 'ui', 'webui', 'resources', 'tsc') - args = [ - '--host', - 'fake-host', - '--js_module_in_files', - 'ui.js', - '--external_paths', - 'chrome://resources|%s' % resources_path, - 'some-fake-scheme://foo|%s' % os.path.abspath(custom_dir), - ] - self._run_bundle(args) - - ui_rollup_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', ui_rollup_js) - self.assertIn('hello from external_element', ui_rollup_js) - self.assertIn('hello from external_element_dep', ui_rollup_js) - - depfile_d = self._read_out_file('depfile.d') - self.assertIn('element.js', depfile_d) - relpath = os.path.relpath(custom_dir, _CWD) - self.assertIn( - os.path.normpath( - os.path.join(relpath, 'external_dir', 'external_element.js')), - depfile_d) - self.assertIn( - os.path.normpath( - os.path.join(relpath, 'external_dir', 'sub_dir', - 'external_element_dep.js')), depfile_d) - def testSimpleBundleExcludes(self): - self._write_files_to_src_dir() args = [ '--host', 'chrome-extension://myextensionid/', '--js_module_in_files', - 'ui.js', + 'foo_ui.js', '--exclude', - 'element_in_dir/element_in_dir.js', + 'foo.js', ] self._run_bundle(args) - output_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', output_js) - self.assertNotIn('hello from element_in_dir', output_js) + output_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from src/subdir/baz.js', output_js) + self.assertNotIn('Hello from src/foo.js', output_js) depfile_d = self._read_out_file('depfile.d') - self.assertIn('element.js', depfile_d) - self.assertNotIn('element_in_dir', depfile_d) + self._check_dep_file(['src/subdir/baz.js'], depfile_d) + self.assertNotIn('src/foo.js', depfile_d) # Tests that bundling resources for an untrusted UI can successfully exclude # resources imported from both chrome-untrusted://resources and scheme # relative paths. def testSimpleBundleExcludesResources(self): - self._write_files_with_resources_to_src_dir('chrome-untrusted:') - resources_path = os.path.join('gen', 'ui', 'webui', 'resources', 'tsc') args = [ '--host', 'chrome-untrusted://fake-host', '--js_module_in_files', - 'ui.js', - '--external_paths', - '//resources|%s' % resources_path, - 'chrome-untrusted://resources|%s' % resources_path, + 'foo_ui.js', '--exclude', - '//resources/js/scheme_relative_resource.js', - 'chrome-untrusted://resources/js/fake_resource.js', + '//resources/bar_resource.js', + 'chrome-untrusted://resources/foo_untrusted.js', ] self._run_bundle(args) - output_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', output_js) - self.assertIn('//resources/js/scheme_relative_resource.js', output_js) - self.assertIn('chrome-untrusted://resources/js/fake_resource.js', output_js) - self.assertNotIn('hello from another shared resource', output_js) - self.assertNotIn('hello from shared resource', output_js) + output_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from src/foo.js', output_js) + self.assertIn('chrome-untrusted://resources/foo_untrusted.js', output_js) + self.assertIn('//resources/bar_resource.js', output_js) + self.assertNotIn('Hello from resources/foo_untrusted.js', output_js) + self.assertNotIn('Hello from resources/bar_resource.js', output_js) depfile_d = self._read_out_file('depfile.d') - self.assertNotIn('fake_resource', depfile_d) - self.assertNotIn('scheme_relative_resource', depfile_d) + self.assertNotIn('resources/foo_untrusted.js', depfile_d) + self.assertNotIn('resources/bar_resource.js', depfile_d) # Tests that bundling resources for an untrusted UI successfully bundles # resources from both chrome-untrusted://resources and //resources. def testSimpleBundleUntrustedResources(self): - self._write_files_with_resources_to_src_dir('chrome-untrusted:') - resources_path = os.path.join('gen', 'ui', 'webui', 'resources', 'tsc') args = [ '--host', 'chrome-untrusted://fake-host', '--js_module_in_files', - 'ui.js', - '--external_paths', - '//resources|%s' % resources_path, - 'chrome-untrusted://resources|%s' % resources_path, + 'foo_ui.js', ] self._run_bundle(args) - output_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', output_js) - self.assertIn('hello from another shared resource', output_js) - self.assertIn('hello from shared resource', output_js) + output_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from src/foo.js', output_js) + self.assertIn('Hello from resources/foo_untrusted.js', output_js) + self.assertIn('Hello from resources/bar_resource.js', output_js) depfile_d = self._read_out_file('depfile.d') - self.assertIn('fake_resource', depfile_d) - self.assertIn('scheme_relative_resource', depfile_d) + self._check_dep_file( + ['resources/foo_untrusted.js', 'resources/bar_resource.js'], depfile_d) def testBundleWithCustomLayeredPaths(self): - tmp_dir = self._create_tmp_dir() - custom_dir_foo = os.path.join(tmp_dir, 'foo_root') - custom_dir_bar = os.path.join(tmp_dir, 'bar_root') - - self._write_files_with_custom_path_to_src_dir(custom_dir_foo) - - # Overwrite one of the foo files to import something from - # some-fake-scheme://bar. - self._write_file_to_dir( - os.path.join(custom_dir_foo, 'external_dir', 'sub_dir', - 'external_element_dep.js'), ''' -import 'some-fake-scheme://bar/another_element.js'; -alert('hello from external_element_dep');''') - - # Write that file to the bar_root directory. - self._write_file_to_dir( - os.path.join(custom_dir_bar, 'another_element.js'), - "alert('hello from another external dep');") - - resources_path = os.path.join('gen', 'ui', 'webui', 'resources', 'tsc') args = [ '--host', 'fake-host', '--js_module_in_files', - 'ui.js', - '--external_paths', - '//resources|%s' % resources_path, - 'some-fake-scheme://foo|%s' % os.path.abspath(custom_dir_foo), - 'some-fake-scheme://bar|%s' % os.path.abspath(custom_dir_bar), + 'foo_ui.js', ] self._run_bundle(args) - ui_rollup_js = self._read_out_file('ui.rollup.js') - self.assertIn('yay', ui_rollup_js) - self.assertIn('hello from external_element', ui_rollup_js) - self.assertIn('hello from external_element_dep', ui_rollup_js) - self.assertIn('hello from another external dep', ui_rollup_js) + ui_rollup_js = self._read_out_file('foo_ui.rollup.js') + self.assertIn('Hello from src/foo.js', ui_rollup_js) + self.assertIn('Hello from external/foo/foo.js', ui_rollup_js) + self.assertIn('Hello from external/bar/bar.js', ui_rollup_js) depfile_d = self._read_out_file('depfile.d') - self.assertIn('element.js', depfile_d) - relpath = os.path.relpath(custom_dir_foo, _CWD) - self.assertIn( - os.path.normpath( - os.path.join(relpath, 'external_dir', 'external_element.js')), - depfile_d) - self.assertIn( - os.path.normpath( - os.path.join(relpath, 'external_dir', 'sub_dir', - 'external_element_dep.js')), depfile_d) - relpath_bar = os.path.relpath(custom_dir_bar, _CWD) - self.assertIn( - os.path.normpath(os.path.join(relpath_bar, 'another_element.js')), - depfile_d) + self._check_dep_file( + ['src/foo.js', 'external/foo/foo.js', 'external/bar/bar.js'], depfile_d) def testBundleWithBundleSubpath(self): - self._write_files_to_src_dir() - self._write_file_to_src_dir( - 'subfolder/ui.js', ''' -import '../element.js'; -import '../element_in_dir/element_in_dir.js'; -''') args = [ '--host', 'fake-host', '--js_module_in_files', - 'subfolder/ui.js', + 'subdir/baz_ui.js', ] self._run_bundle(args) - self._check_output_js(os.path.normpath('subfolder/ui.rollup.js')) - self._check_output_depfile(False) + ui_rollup_js = self._read_out_file('subdir/baz_ui.rollup.js') + self.assertIn('Hello from src/foo.js', ui_rollup_js) + self.assertIn('Hello from src/subdir/baz.js', ui_rollup_js) + + depfile_d = self._read_out_file('depfile.d') + self._check_dep_file(['src/foo.js', 'src/subdir/baz.js'], depfile_d) if __name__ == '__main__':
diff --git a/ui/webui/resources/tools/tests/bundle_js/external/bar/bar.js b/ui/webui/resources/tools/tests/bundle_js/external/bar/bar.js new file mode 100644 index 0000000..44b7468 --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/external/bar/bar.js
@@ -0,0 +1,5 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +alert('Hello from external/bar/bar.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/external/foo/foo.js b/ui/webui/resources/tools/tests/bundle_js/external/foo/foo.js new file mode 100644 index 0000000..0868a86 --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/external/foo/foo.js
@@ -0,0 +1,6 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'some-fake-scheme://bar/bar.js'; +alert('Hello from external/foo/foo.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/resources/bar_resource.js b/ui/webui/resources/tools/tests/bundle_js/resources/bar_resource.js new file mode 100644 index 0000000..e3b45a1f --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/resources/bar_resource.js
@@ -0,0 +1,6 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export const bar = 6; +alert('Hello from resources/bar_resource.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/resources/foo_resource.js b/ui/webui/resources/tools/tests/bundle_js/resources/foo_resource.js new file mode 100644 index 0000000..730532c --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/resources/foo_resource.js
@@ -0,0 +1,6 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +export const foo = 5; +alert('Hello from resources/foo_resource.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/resources/foo_untrusted.js b/ui/webui/resources/tools/tests/bundle_js/resources/foo_untrusted.js new file mode 100644 index 0000000..477f7f3 --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/resources/foo_untrusted.js
@@ -0,0 +1,5 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +alert('Hello from resources/foo_untrusted.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/src/bar.js b/ui/webui/resources/tools/tests/bundle_js/src/bar.js new file mode 100644 index 0000000..f63cfd6 --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/src/bar.js
@@ -0,0 +1,5 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +alert('Hello from src/bar.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/src/bar_ui.js b/ui/webui/resources/tools/tests/bundle_js/src/bar_ui.js new file mode 100644 index 0000000..cb7f4309 --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/src/bar_ui.js
@@ -0,0 +1,6 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './subdir/baz.js'; +import './bar.js';
diff --git a/ui/webui/resources/tools/tests/bundle_js/src/foo.js b/ui/webui/resources/tools/tests/bundle_js/src/foo.js new file mode 100644 index 0000000..eae84c0e --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/src/foo.js
@@ -0,0 +1,8 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/foo_resource.js'; +import 'some-fake-scheme://foo/foo.js'; + +alert('Hello from src/foo.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/src/foo_ui.js b/ui/webui/resources/tools/tests/bundle_js/src/foo_ui.js new file mode 100644 index 0000000..737feff --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/src/foo_ui.js
@@ -0,0 +1,6 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import './subdir/baz.js'; +import './foo.js';
diff --git a/ui/webui/resources/tools/tests/bundle_js/src/subdir/baz.js b/ui/webui/resources/tools/tests/bundle_js/src/subdir/baz.js new file mode 100644 index 0000000..74d376c --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/src/subdir/baz.js
@@ -0,0 +1,9 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome-untrusted://resources/foo_untrusted.js'; + +import {bar} from '//resources/bar_resource.js'; + +alert('Hello from src/subdir/baz.js');
diff --git a/ui/webui/resources/tools/tests/bundle_js/src/subdir/baz_ui.js b/ui/webui/resources/tools/tests/bundle_js/src/subdir/baz_ui.js new file mode 100644 index 0000000..edd0169 --- /dev/null +++ b/ui/webui/resources/tools/tests/bundle_js/src/subdir/baz_ui.js
@@ -0,0 +1,6 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../foo.js'; +import './baz.js';