diff --git a/DEPS b/DEPS index ba90f741..48d0210c 100644 --- a/DEPS +++ b/DEPS
@@ -300,15 +300,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '3d667452da4d6078766044683c53a7d3adf53036', + 'skia_revision': '693ec9acd30c058da5bd2614b99fab64aabb6456', # 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': 'f2bec7884ccae8af1bce5d38639c7c1dbc999646', + 'v8_revision': 'bee171e60cee5676c25dacda5a954d194700678d', # 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': '6f959e07eaef58e231556c3348295484497f6aa2', + 'angle_revision': '293b19018eeff63f38a91d27d6e6935eef507467', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -803,7 +803,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '9f08c839ebbd1b1edf5d119aaaf382709a7d8f3c', + '773d6c3c7144ff3a329df012ff182e603d57de13', 'condition': 'checkout_android and checkout_src_internal', }, @@ -812,7 +812,7 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '88ee16bd9915655a25bde242c41390cb428db4f8', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '28f70174b853444a055156b7013e52ef2b8c839d', 'condition': 'checkout_ios', }, @@ -992,7 +992,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'vv6gLGjLJt8gQ6SLVQS20u4Lm3OhOfUab6d6-cWG5KAC', + 'version': '2gllZYexJMbLOJ1m0-DqSix5DxCMTOiX18-N1bef33sC', }, ], 'condition': 'checkout_android', @@ -1975,7 +1975,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': Var('chrome_git') + '/chrome/src-internal.git@39c6181024662833a77fc2d16aba5e79f6f9d14e', + 'url': Var('chrome_git') + '/chrome/src-internal.git@b097668dcf7986fe6711de45906a77f2621f21f5', 'condition': 'checkout_src_internal', },
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 38a221a7..063a7c7 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -3805,6 +3805,7 @@ "system/ime/ime_detailed_view_pixeltest.cc", "system/locale/locale_detailed_view_pixeltest.cc", "system/message_center/ash_notification_view_pixeltest.cc", + "system/network/network_detailed_network_view_pixeltest.cc", "system/network/network_feature_tile_pixeltest.cc", "system/network/vpn_detailed_view_pixeltest.cc", "system/time/calendar_unittest_utils.cc", @@ -3831,6 +3832,7 @@ "//chromeos/ash/services/bluetooth_config:test_support", "//chromeos/dbus/power:power", "//chromeos/dbus/power:power_manager_proto", + "//chromeos/services/network_config/public/cpp:test_support", "//components/user_education/common", "//components/user_education/views", "//components/viz/test:test_support", @@ -4103,8 +4105,8 @@ "test/test_window_builder.h", "test/toplevel_window.cc", "test/toplevel_window.h", - "test/ui_controls_factory_ash.cc", - "test/ui_controls_factory_ash.h", + "test/ui_controls_ash.cc", + "test/ui_controls_ash.h", "test/view_drawn_waiter.cc", "test/view_drawn_waiter.h", "test_media_client.cc",
diff --git a/ash/system/network/network_detailed_network_view_pixeltest.cc b/ash/system/network/network_detailed_network_view_pixeltest.cc new file mode 100644 index 0000000..33e2667 --- /dev/null +++ b/ash/system/network/network_detailed_network_view_pixeltest.cc
@@ -0,0 +1,99 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "ash/constants/ash_features.h" +#include "ash/shell.h" +#include "ash/system/model/system_tray_model.h" +#include "ash/system/network/tray_network_state_model.h" +#include "ash/system/unified/quick_settings_view.h" +#include "ash/system/unified/unified_system_tray.h" +#include "ash/system/unified/unified_system_tray_bubble.h" +#include "ash/system/unified/unified_system_tray_controller.h" +#include "ash/test/ash_test_base.h" +#include "ash/test/ash_test_helper.h" +#include "ash/test/pixel/ash_pixel_differ.h" +#include "ash/test/pixel/ash_pixel_test_init_params.h" +#include "base/test/scoped_feature_list.h" +#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h" +#include "chromeos/constants/chromeos_features.h" +#include "chromeos/services/network_config/public/cpp/fake_cros_network_config.h" + +namespace ash { +namespace { + +using ::chromeos::network_config::FakeCrosNetworkConfig; +using ::chromeos::network_config::mojom::ConnectionStateType; +using ::chromeos::network_config::mojom::DeviceStateType; +using ::chromeos::network_config::mojom::NetworkType; +using network_config::CrosNetworkConfigTestHelper; + +// Pixel tests for the quick settings network detailed view. +class NetworkDetailedNetworkViewPixelTest : public AshTestBase { + public: + NetworkDetailedNetworkViewPixelTest() { + feature_list_.InitWithFeatures( + {features::kQsRevamp, chromeos::features::kJelly}, {}); + } + + // AshTestBase: + void SetUp() override { + AshTestBase::SetUp(); + cros_network_ = std::make_unique<FakeCrosNetworkConfig>(); + Shell::Get() + ->system_tray_model() + ->network_state_model() + ->ConfigureRemoteForTesting(cros_network_->GetPendingRemote()); + base::RunLoop().RunUntilIdle(); + } + + absl::optional<pixel_test::InitParams> CreatePixelTestInitParams() + const override { + return pixel_test::InitParams(); + } + + FakeCrosNetworkConfig* cros_network() { return cros_network_.get(); } + + private: + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<FakeCrosNetworkConfig> cros_network_; +}; + +TEST_F(NetworkDetailedNetworkViewPixelTest, Basics) { + cros_network()->AddNetworkAndDevice( + CrosNetworkConfigTestHelper::CreateStandaloneNetworkProperties( + "My Ethernet", NetworkType::kEthernet, + ConnectionStateType::kConnected)); + + cros_network()->AddNetworkAndDevice( + CrosNetworkConfigTestHelper::CreateStandaloneNetworkProperties( + "My Cellular", NetworkType::kCellular, + ConnectionStateType::kConnected)); + + cros_network()->AddNetworkAndDevice( + CrosNetworkConfigTestHelper::CreateStandaloneNetworkProperties( + "My Wi-Fi", NetworkType::kWiFi, ConnectionStateType::kConnected)); + + // Show the system tray bubble. + UnifiedSystemTray* system_tray = GetPrimaryUnifiedSystemTray(); + system_tray->ShowBubble(); + ASSERT_TRUE(system_tray->bubble()); + + // Show the detailed view. + system_tray->bubble() + ->unified_system_tray_controller() + ->ShowNetworkDetailedView(/*force=*/true); + views::View* detailed_view = + system_tray->bubble()->quick_settings_view()->detailed_view(); + ASSERT_TRUE(detailed_view); + + // Compare pixels. + EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( + "check_view", + /*revision_number=*/0, detailed_view)); +} + +} // namespace +} // namespace ash
diff --git a/ash/system/unified/feature_tile.cc b/ash/system/unified/feature_tile.cc index a6336d3..95b1f37 100644 --- a/ash/system/unified/feature_tile.cc +++ b/ash/system/unified/feature_tile.cc
@@ -44,7 +44,6 @@ constexpr float kFocusRingPadding = 3.0f; // Primary tile constants -constexpr int kPrimarySubtitleLineHeight = 18; constexpr gfx::Size kDefaultSize(180, kFeatureTileHeight); constexpr gfx::Size kIconButtonSize(36, 52); constexpr int kIconButtonCornerRadius = 12; @@ -166,8 +165,6 @@ label_->SetHorizontalAlignment(is_compact ? gfx::ALIGN_CENTER : gfx::ALIGN_LEFT); label_->SetAutoColorReadabilityEnabled(false); - label_->SetFontList(ash::TypographyProvider::Get()->ResolveTypographyToken( - ash::TypographyToken::kCrosButton2)); if (is_compact) { label_->SetPreferredSize(kCompactTitleLabelSize); @@ -175,28 +172,19 @@ // clipping and center aligned. label_->SetMultiLine(true); label_->SetMaxLines(2); // Elide after 2 lines. + // Compact labels use kCrosAnnotation2 with a shorter custom line height. + label_->SetFontList(TypographyProvider::Get()->ResolveTypographyToken( + TypographyToken::kCrosAnnotation2)); label_->SetLineHeight(kCompactTitleLineHeight); - label_->SetFontList(ash::TypographyProvider::Get()->ResolveTypographyToken( - ash::TypographyToken::kCrosAnnotation2)); } else { + TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosButton2, + *label_); sub_label_ = title_container->AddChildView(std::make_unique<views::Label>()); sub_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); sub_label_->SetAutoColorReadabilityEnabled(false); - sub_label_->SetFontList( - ash::TypographyProvider::Get()->ResolveTypographyToken( - ash::TypographyToken::kCrosAnnotation1)); - sub_label_->SetLineHeight(kPrimarySubtitleLineHeight); - if (chromeos::features::IsJellyEnabled()) { - TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosAnnotation1, - *sub_label_); - } - } - if (chromeos::features::IsJellyEnabled()) { - TypographyProvider::Get()->StyleLabel( - is_compact ? TypographyToken::kCrosAnnotation2 - : TypographyToken::kCrosButton2, - *label_); + TypographyProvider::Get()->StyleLabel(TypographyToken::kCrosAnnotation1, + *sub_label_); } }
diff --git a/ash/system/unified/feature_tile_pixeltest.cc b/ash/system/unified/feature_tile_pixeltest.cc index 57490c5b..5993d29 100644 --- a/ash/system/unified/feature_tile_pixeltest.cc +++ b/ash/system/unified/feature_tile_pixeltest.cc
@@ -113,22 +113,28 @@ EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "basic", - /*revision_number=*/0, widget_.get())); + /*revision_number=*/1, widget_.get())); widget_->GetFocusManager()->SetFocusedView(tile); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "focused", - /*revision_number=*/0, widget_.get())); + /*revision_number=*/1, widget_.get())); tile->SetToggled(true); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "toggled", - /*revision_number=*/0, widget_.get())); + /*revision_number=*/1, widget_.get())); // Test eliding. tile->SetLabel(u"A very very long label"); EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( "elided", + /*revision_number=*/1, widget_.get())); + + // Test font descenders ("g"). + tile->SetLabel(u"Multi-line ggggg"); + EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen( + "descenders", /*revision_number=*/0, widget_.get())); }
diff --git a/ash/test/ash_interactive_ui_test_base.cc b/ash/test/ash_interactive_ui_test_base.cc index f1314da..148a150 100644 --- a/ash/test/ash_interactive_ui_test_base.cc +++ b/ash/test/ash_interactive_ui_test_base.cc
@@ -4,13 +4,11 @@ #include "ash/test/ash_interactive_ui_test_base.h" -#include "ash/test/ui_controls_factory_ash.h" #include "base/lazy_instance.h" #include "base/path_service.h" #include "mojo/core/embedder/embedder.h" #include "ui/aura/env.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/base/test/ui_controls_aura.h" #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_paths.h" #include "ui/gl/test/gl_surface_test_support.h" @@ -52,7 +50,6 @@ ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath( resources_pack_path, ui::kScaleFactorNone); env_ = aura::Env::CreateInstance(); - ui_controls::InstallUIControlsAura(test::CreateAshUIControls()); AshTestBase::SetUp(); }
diff --git a/ash/test/ui_controls_factory_ash.cc b/ash/test/ui_controls_ash.cc similarity index 95% rename from ash/test/ui_controls_factory_ash.cc rename to ash/test/ui_controls_ash.cc index 3a05224d..03b78fa50 100644 --- a/ash/test/ui_controls_factory_ash.cc +++ b/ash/test/ui_controls_ash.cc
@@ -18,12 +18,10 @@ DEFINE_UI_CLASS_PROPERTY_TYPE(ui_controls::UIControlsAura*) -namespace ash { -namespace test { namespace { -using ui_controls::UIControlsAura; using ui_controls::MouseButton; +using ui_controls::UIControlsAura; DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(UIControlsAura, kUIControlsKey, NULL) @@ -45,11 +43,9 @@ UIControlsAura* GetUIControlsAt(const gfx::Point& point_in_screen) { // TODO(mazda): Support the case passive grab is taken. return GetUIControlsForRootWindow( - window_util::GetRootWindowAt(point_in_screen)); + ash::window_util::GetRootWindowAt(point_in_screen)); } -} // namespace - class UIControlsAsh : public UIControlsAura { public: UIControlsAsh() = default; @@ -139,9 +135,12 @@ } }; -ui_controls::UIControlsAura* CreateAshUIControls() { - return new ash::test::UIControlsAsh(); +} // namespace + +namespace ash::test { + +void EnableUIControlsAsh() { + ui_controls::InstallUIControlsAura(new UIControlsAsh()); } -} // namespace test -} // namespace ash +} // namespace ash::test
diff --git a/ash/test/ui_controls_ash.h b/ash/test/ui_controls_ash.h new file mode 100644 index 0000000..a011399e --- /dev/null +++ b/ash/test/ui_controls_ash.h
@@ -0,0 +1,14 @@ +// Copyright 2013 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_TEST_UI_CONTROLS_ASH_H_ +#define ASH_TEST_UI_CONTROLS_ASH_H_ + +namespace ash::test { + +void EnableUIControlsAsh(); + +} // namespace ash::test + +#endif // ASH_TEST_UI_CONTROLS_ASH_H_
diff --git a/ash/test/ui_controls_factory_ash.h b/ash/test/ui_controls_factory_ash.h deleted file mode 100644 index b3f53735..0000000 --- a/ash/test/ui_controls_factory_ash.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright 2013 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_TEST_UI_CONTROLS_FACTORY_ASH_H_ -#define ASH_TEST_UI_CONTROLS_FACTORY_ASH_H_ - -namespace ui_controls { -class UIControlsAura; -} - -namespace ash { -namespace test { - -ui_controls::UIControlsAura* CreateAshUIControls(); - -} // namespace test -} // namespace ash - -#endif // ASH_TEST_UI_CONTROLS_FACTORY_ASH_H_
diff --git a/base/allocator/partition_allocator/partition_address_space.cc b/base/allocator/partition_allocator/partition_address_space.cc index b65e5d7b..07ad6bc7 100644 --- a/base/allocator/partition_allocator/partition_address_space.cc +++ b/base/allocator/partition_allocator/partition_address_space.cc
@@ -159,28 +159,28 @@ size_t glued_pool_sizes = regular_pool_size * 2; // Note, BRP pool requires to be preceded by a "forbidden zone", which is // conveniently taken care of by the last guard page of the regular pool. - setup_.regular_pool_base_address_ = + setup_.aligned.regular_pool_base_address_ = AllocPages(glued_pool_sizes, glued_pool_sizes, PageAccessibilityConfiguration( PageAccessibilityConfiguration::kInaccessible), PageTag::kPartitionAlloc, pools_fd); - if (!setup_.regular_pool_base_address_) { + if (!setup_.aligned.regular_pool_base_address_) { HandlePoolAllocFailure(); } - setup_.brp_pool_base_address_ = - setup_.regular_pool_base_address_ + regular_pool_size; + setup_.aligned.brp_pool_base_address_ = + setup_.aligned.regular_pool_base_address_ + regular_pool_size; #else // BUILDFLAG(GLUE_CORE_POOLS) #if PA_CONFIG(ENABLE_SHADOW_METADATA) int regular_pool_fd = memfd_create("/regular_pool", MFD_CLOEXEC); #else int regular_pool_fd = -1; #endif - setup_.regular_pool_base_address_ = + setup_.aligned.regular_pool_base_address_ = AllocPages(regular_pool_size, regular_pool_size, PageAccessibilityConfiguration( PageAccessibilityConfiguration::kInaccessible), PageTag::kPartitionAlloc, regular_pool_fd); - if (!setup_.regular_pool_base_address_) { + if (!setup_.aligned.regular_pool_base_address_) { HandlePoolAllocFailure(); } @@ -203,60 +203,69 @@ if (!base_address) { HandlePoolAllocFailure(); } - setup_.brp_pool_base_address_ = base_address + kForbiddenZoneSize; + setup_.aligned.brp_pool_base_address_ = base_address + kForbiddenZoneSize; #endif // BUILDFLAG(GLUE_CORE_POOLS) #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - setup_.regular_pool_base_mask_ = ~(regular_pool_size - 1); - setup_.brp_pool_base_mask_ = ~(brp_pool_size - 1); + setup_.aligned.regular_pool_base_mask_ = ~(regular_pool_size - 1); + setup_.aligned.brp_pool_base_mask_ = ~(brp_pool_size - 1); #if BUILDFLAG(GLUE_CORE_POOLS) // When PA_GLUE_CORE_POOLS is on, the BRP pool is placed at the end of the // regular pool, effectively forming one virtual pool of a twice bigger // size. Adjust the mask appropriately. - setup_.core_pools_base_mask_ = setup_.regular_pool_base_mask_ << 1; - PA_DCHECK(setup_.core_pools_base_mask_ == (setup_.brp_pool_base_mask_ << 1)); + setup_.aligned.core_pools_base_mask_ = setup_.aligned.regular_pool_base_mask_ + << 1; + PA_DCHECK(setup_.aligned.core_pools_base_mask_ == + (setup_.aligned.brp_pool_base_mask_ << 1)); #endif #endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) AddressPoolManager::GetInstance().Add( - kRegularPoolHandle, setup_.regular_pool_base_address_, regular_pool_size); + kRegularPoolHandle, setup_.aligned.regular_pool_base_address_, + regular_pool_size); AddressPoolManager::GetInstance().Add( - kBRPPoolHandle, setup_.brp_pool_base_address_, brp_pool_size); + kBRPPoolHandle, setup_.aligned.brp_pool_base_address_, brp_pool_size); // Sanity check pool alignment. - PA_DCHECK(!(setup_.regular_pool_base_address_ & (regular_pool_size - 1))); - PA_DCHECK(!(setup_.brp_pool_base_address_ & (brp_pool_size - 1))); + PA_DCHECK( + !(setup_.aligned.regular_pool_base_address_ & (regular_pool_size - 1))); + PA_DCHECK(!(setup_.aligned.brp_pool_base_address_ & (brp_pool_size - 1))); #if BUILDFLAG(GLUE_CORE_POOLS) - PA_DCHECK(!(setup_.regular_pool_base_address_ & (glued_pool_sizes - 1))); + PA_DCHECK( + !(setup_.aligned.regular_pool_base_address_ & (glued_pool_sizes - 1))); #endif // Sanity check pool belonging. - PA_DCHECK(!IsInRegularPool(setup_.regular_pool_base_address_ - 1)); - PA_DCHECK(IsInRegularPool(setup_.regular_pool_base_address_)); - PA_DCHECK(IsInRegularPool(setup_.regular_pool_base_address_ + + PA_DCHECK(!IsInRegularPool(setup_.aligned.regular_pool_base_address_ - 1)); + PA_DCHECK(IsInRegularPool(setup_.aligned.regular_pool_base_address_)); + PA_DCHECK(IsInRegularPool(setup_.aligned.regular_pool_base_address_ + regular_pool_size - 1)); + PA_DCHECK(!IsInRegularPool(setup_.aligned.regular_pool_base_address_ + + regular_pool_size)); + PA_DCHECK(!IsInBRPPool(setup_.aligned.brp_pool_base_address_ - 1)); + PA_DCHECK(IsInBRPPool(setup_.aligned.brp_pool_base_address_)); PA_DCHECK( - !IsInRegularPool(setup_.regular_pool_base_address_ + regular_pool_size)); - PA_DCHECK(!IsInBRPPool(setup_.brp_pool_base_address_ - 1)); - PA_DCHECK(IsInBRPPool(setup_.brp_pool_base_address_)); - PA_DCHECK(IsInBRPPool(setup_.brp_pool_base_address_ + brp_pool_size - 1)); - PA_DCHECK(!IsInBRPPool(setup_.brp_pool_base_address_ + brp_pool_size)); + IsInBRPPool(setup_.aligned.brp_pool_base_address_ + brp_pool_size - 1)); + PA_DCHECK( + !IsInBRPPool(setup_.aligned.brp_pool_base_address_ + brp_pool_size)); #if BUILDFLAG(GLUE_CORE_POOLS) - PA_DCHECK(!IsInCorePools(setup_.regular_pool_base_address_ - 1)); - PA_DCHECK(IsInCorePools(setup_.regular_pool_base_address_)); + PA_DCHECK(!IsInCorePools(setup_.aligned.regular_pool_base_address_ - 1)); + PA_DCHECK(IsInCorePools(setup_.aligned.regular_pool_base_address_)); + PA_DCHECK(IsInCorePools(setup_.aligned.regular_pool_base_address_ + + regular_pool_size - 1)); + PA_DCHECK(IsInCorePools(setup_.aligned.regular_pool_base_address_ + + regular_pool_size)); + PA_DCHECK(IsInCorePools(setup_.aligned.brp_pool_base_address_ - 1)); + PA_DCHECK(IsInCorePools(setup_.aligned.brp_pool_base_address_)); PA_DCHECK( - IsInCorePools(setup_.regular_pool_base_address_ + regular_pool_size - 1)); + IsInCorePools(setup_.aligned.brp_pool_base_address_ + brp_pool_size - 1)); PA_DCHECK( - IsInCorePools(setup_.regular_pool_base_address_ + regular_pool_size)); - PA_DCHECK(IsInCorePools(setup_.brp_pool_base_address_ - 1)); - PA_DCHECK(IsInCorePools(setup_.brp_pool_base_address_)); - PA_DCHECK(IsInCorePools(setup_.brp_pool_base_address_ + brp_pool_size - 1)); - PA_DCHECK(!IsInCorePools(setup_.brp_pool_base_address_ + brp_pool_size)); + !IsInCorePools(setup_.aligned.brp_pool_base_address_ + brp_pool_size)); #endif // BUILDFLAG(GLUE_CORE_POOLS) #if PA_CONFIG(STARSCAN_USE_CARD_TABLE) // Reserve memory for PCScan quarantine card table. - uintptr_t requested_address = setup_.regular_pool_base_address_; + uintptr_t requested_address = setup_.aligned.regular_pool_base_address_; uintptr_t actual_address = AddressPoolManager::GetInstance().Reserve( kRegularPoolHandle, requested_address, kSuperPageSize); PA_CHECK(requested_address == actual_address) @@ -272,7 +281,7 @@ PageAccessibilityConfiguration::kInaccessible), PageTag::kPartitionAlloc, regular_pool_fd); regular_pool_shadow_offset_ = - regular_pool_shadow_address - setup_.regular_pool_base_address_; + regular_pool_shadow_address - setup_.aligned.regular_pool_base_address_; uintptr_t brp_pool_shadow_address = AllocPagesWithAlignOffset( 0, brp_pool_size + kForbiddenZoneSize, brp_pool_size, @@ -281,11 +290,12 @@ PageAccessibilityConfiguration::kInaccessible), PageTag::kPartitionAlloc, brp_pool_fd); brp_pool_shadow_offset_ = - brp_pool_shadow_address - setup_.brp_pool_base_address_; + brp_pool_shadow_address - setup_.aligned.brp_pool_base_address_; #endif #if BUILDFLAG(ENABLE_POINTER_COMPRESSION) - CompressedPointerBaseGlobal::SetBase(setup_.regular_pool_base_address_); + CompressedPointerBaseGlobal::SetBase( + setup_.aligned.regular_pool_base_address_); #endif // BUILDFLAG(ENABLE_POINTER_COMPRESSION) } @@ -309,16 +319,17 @@ PA_CHECK(base::bits::IsPowerOfTwo(size)); PA_CHECK(pool_base % size == 0); - setup_.configurable_pool_base_address_ = pool_base; - setup_.configurable_pool_base_mask_ = ~(size - 1); + setup_.aligned.configurable_pool_base_address_ = pool_base; + setup_.aligned.configurable_pool_base_mask_ = ~(size - 1); AddressPoolManager::GetInstance().Add( - kConfigurablePoolHandle, setup_.configurable_pool_base_address_, size); + kConfigurablePoolHandle, setup_.aligned.configurable_pool_base_address_, + size); #if BUILDFLAG(ENABLE_THREAD_ISOLATION) // Put the metadata protection back in place. if (IsThreadIsolatedPoolInitialized()) { - WriteProtectThreadIsolatedGlobals(setup_.thread_isolation_); + WriteProtectThreadIsolatedGlobals(setup_.aligned.thread_isolation_); } #endif } @@ -328,33 +339,35 @@ ThreadIsolationOption thread_isolation) { // The ThreadIsolated pool can't be initialized with conflicting settings. if (IsThreadIsolatedPoolInitialized()) { - PA_CHECK(setup_.thread_isolation_ == thread_isolation); + PA_CHECK(setup_.aligned.thread_isolation_ == thread_isolation); return; } size_t pool_size = ThreadIsolatedPoolSize(); - setup_.thread_isolated_pool_base_address_ = + setup_.aligned.thread_isolated_pool_base_address_ = AllocPages(pool_size, pool_size, PageAccessibilityConfiguration( PageAccessibilityConfiguration::kInaccessible), PageTag::kPartitionAlloc); - if (!setup_.thread_isolated_pool_base_address_) { + if (!setup_.aligned.thread_isolated_pool_base_address_) { HandlePoolAllocFailure(); } - PA_DCHECK(!(setup_.thread_isolated_pool_base_address_ & (pool_size - 1))); - setup_.thread_isolation_ = thread_isolation; - AddressPoolManager::GetInstance().Add( - kThreadIsolatedPoolHandle, setup_.thread_isolated_pool_base_address_, - pool_size); - PA_DCHECK( - !IsInThreadIsolatedPool(setup_.thread_isolated_pool_base_address_ - 1)); - PA_DCHECK(IsInThreadIsolatedPool(setup_.thread_isolated_pool_base_address_)); - PA_DCHECK(IsInThreadIsolatedPool(setup_.thread_isolated_pool_base_address_ + - pool_size - 1)); - PA_DCHECK(!IsInThreadIsolatedPool(setup_.thread_isolated_pool_base_address_ + - pool_size)); + !(setup_.aligned.thread_isolated_pool_base_address_ & (pool_size - 1))); + setup_.aligned.thread_isolation_ = thread_isolation; + AddressPoolManager::GetInstance().Add( + kThreadIsolatedPoolHandle, + setup_.aligned.thread_isolated_pool_base_address_, pool_size); + + PA_DCHECK(!IsInThreadIsolatedPool( + setup_.aligned.thread_isolated_pool_base_address_ - 1)); + PA_DCHECK(IsInThreadIsolatedPool( + setup_.aligned.thread_isolated_pool_base_address_)); + PA_DCHECK(IsInThreadIsolatedPool( + setup_.aligned.thread_isolated_pool_base_address_ + pool_size - 1)); + PA_DCHECK(!IsInThreadIsolatedPool( + setup_.aligned.thread_isolated_pool_base_address_ + pool_size)); // TODO(1362969): support PA_ENABLE_SHADOW_METADATA } @@ -367,21 +380,22 @@ #if BUILDFLAG(GLUE_CORE_POOLS) // The core pools (regular & BRP) were allocated using a single allocation of // double size. - FreePages(setup_.regular_pool_base_address_, 2 * RegularPoolSize()); + FreePages(setup_.aligned.regular_pool_base_address_, 2 * RegularPoolSize()); #else // BUILDFLAG(GLUE_CORE_POOLS) - FreePages(setup_.regular_pool_base_address_, RegularPoolSize()); + FreePages(setup_.aligned.regular_pool_base_address_, RegularPoolSize()); // For BRP pool, the allocation region includes a "forbidden zone" before the // pool. const size_t kForbiddenZoneSize = PageAllocationGranularity(); - FreePages(setup_.brp_pool_base_address_ - kForbiddenZoneSize, + FreePages(setup_.aligned.brp_pool_base_address_ - kForbiddenZoneSize, BRPPoolSize() + kForbiddenZoneSize); #endif // BUILDFLAG(GLUE_CORE_POOLS) // Do not free pages for the configurable pool, because its memory is owned // by someone else, but deinitialize it nonetheless. - setup_.regular_pool_base_address_ = kUninitializedPoolBaseAddress; - setup_.brp_pool_base_address_ = kUninitializedPoolBaseAddress; - setup_.configurable_pool_base_address_ = kUninitializedPoolBaseAddress; - setup_.configurable_pool_base_mask_ = 0; + setup_.aligned.regular_pool_base_address_ = kUninitializedPoolBaseAddress; + setup_.aligned.brp_pool_base_address_ = kUninitializedPoolBaseAddress; + setup_.aligned.configurable_pool_base_address_ = + kUninitializedPoolBaseAddress; + setup_.aligned.configurable_pool_base_mask_ = 0; AddressPoolManager::GetInstance().ResetForTesting(); #if BUILDFLAG(ENABLE_POINTER_COMPRESSION) CompressedPointerBaseGlobal::ResetBaseForTesting(); @@ -398,12 +412,13 @@ } #endif AddressPoolManager::GetInstance().Remove(kConfigurablePoolHandle); - setup_.configurable_pool_base_address_ = kUninitializedPoolBaseAddress; - setup_.configurable_pool_base_mask_ = 0; + setup_.aligned.configurable_pool_base_address_ = + kUninitializedPoolBaseAddress; + setup_.aligned.configurable_pool_base_mask_ = 0; #if BUILDFLAG(ENABLE_THREAD_ISOLATION) // Put the metadata protection back in place. if (IsThreadIsolatedPoolInitialized()) { - WriteProtectThreadIsolatedGlobals(setup_.thread_isolation_); + WriteProtectThreadIsolatedGlobals(setup_.aligned.thread_isolation_); } #endif } @@ -416,11 +431,12 @@ ThreadIsolationSettings::settings.enabled = false; #endif - FreePages(setup_.thread_isolated_pool_base_address_, + FreePages(setup_.aligned.thread_isolated_pool_base_address_, ThreadIsolatedPoolSize()); AddressPoolManager::GetInstance().Remove(kThreadIsolatedPoolHandle); - setup_.thread_isolated_pool_base_address_ = kUninitializedPoolBaseAddress; - setup_.thread_isolation_.enabled = false; + setup_.aligned.thread_isolated_pool_base_address_ = + kUninitializedPoolBaseAddress; + setup_.aligned.thread_isolation_.enabled = false; } } #endif
diff --git a/base/allocator/partition_allocator/partition_address_space.h b/base/allocator/partition_allocator/partition_address_space.h index bd8726d7..0e910d6 100644 --- a/base/allocator/partition_allocator/partition_address_space.h +++ b/base/allocator/partition_allocator/partition_address_space.h
@@ -39,7 +39,7 @@ public: #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) PA_ALWAYS_INLINE static uintptr_t RegularPoolBaseMask() { - return setup_.regular_pool_base_mask_; + return setup_.aligned.regular_pool_base_mask_; } #else PA_ALWAYS_INLINE static constexpr uintptr_t RegularPoolBaseMask() { @@ -57,20 +57,20 @@ uintptr_t base = 0; if (IsInRegularPool(address)) { pool = kRegularPoolHandle; - base = setup_.regular_pool_base_address_; + base = setup_.aligned.regular_pool_base_address_; #if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) } else if (IsInBRPPool(address)) { pool = kBRPPoolHandle; - base = setup_.brp_pool_base_address_; + base = setup_.aligned.brp_pool_base_address_; #endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) } else if (IsInConfigurablePool(address)) { PA_DCHECK(IsConfigurablePoolInitialized()); pool = kConfigurablePoolHandle; - base = setup_.configurable_pool_base_address_; + base = setup_.aligned.configurable_pool_base_address_; #if BUILDFLAG(ENABLE_THREAD_ISOLATION) } else if (IsInThreadIsolatedPool(address)) { pool = kThreadIsolatedPoolHandle; - base = setup_.thread_isolated_pool_base_address_; + base = setup_.aligned.thread_isolated_pool_base_address_; #endif } else { PA_NOTREACHED(); @@ -104,23 +104,26 @@ PA_ALWAYS_INLINE static bool IsInitialized() { // Either neither or both regular and BRP pool are initialized. The // configurable and thread isolated pool are initialized separately. - if (setup_.regular_pool_base_address_ != kUninitializedPoolBaseAddress) { - PA_DCHECK(setup_.brp_pool_base_address_ != kUninitializedPoolBaseAddress); + if (setup_.aligned.regular_pool_base_address_ != + kUninitializedPoolBaseAddress) { + PA_DCHECK(setup_.aligned.brp_pool_base_address_ != + kUninitializedPoolBaseAddress); return true; } - PA_DCHECK(setup_.brp_pool_base_address_ == kUninitializedPoolBaseAddress); + PA_DCHECK(setup_.aligned.brp_pool_base_address_ == + kUninitializedPoolBaseAddress); return false; } PA_ALWAYS_INLINE static bool IsConfigurablePoolInitialized() { - return setup_.configurable_pool_base_address_ != + return setup_.aligned.configurable_pool_base_address_ != kUninitializedPoolBaseAddress; } #if BUILDFLAG(ENABLE_THREAD_ISOLATION) PA_ALWAYS_INLINE static bool IsThreadIsolatedPoolInitialized() { - return setup_.thread_isolated_pool_base_address_ != + return setup_.aligned.thread_isolated_pool_base_address_ != kUninitializedPoolBaseAddress; } #endif @@ -128,26 +131,28 @@ // Returns false for nullptr. PA_ALWAYS_INLINE static bool IsInRegularPool(uintptr_t address) { #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - const uintptr_t regular_pool_base_mask = setup_.regular_pool_base_mask_; + const uintptr_t regular_pool_base_mask = + setup_.aligned.regular_pool_base_mask_; #else constexpr uintptr_t regular_pool_base_mask = kRegularPoolBaseMask; #endif return (address & regular_pool_base_mask) == - setup_.regular_pool_base_address_; + setup_.aligned.regular_pool_base_address_; } PA_ALWAYS_INLINE static uintptr_t RegularPoolBase() { - return setup_.regular_pool_base_address_; + return setup_.aligned.regular_pool_base_address_; } // Returns false for nullptr. PA_ALWAYS_INLINE static bool IsInBRPPool(uintptr_t address) { #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - const uintptr_t brp_pool_base_mask = setup_.brp_pool_base_mask_; + const uintptr_t brp_pool_base_mask = setup_.aligned.brp_pool_base_mask_; #else constexpr uintptr_t brp_pool_base_mask = kBRPPoolBaseMask; #endif - return (address & brp_pool_base_mask) == setup_.brp_pool_base_address_; + return (address & brp_pool_base_mask) == + setup_.aligned.brp_pool_base_address_; } #if BUILDFLAG(GLUE_CORE_POOLS) @@ -155,15 +160,15 @@ // Returns false for nullptr. PA_ALWAYS_INLINE static bool IsInCorePools(uintptr_t address) { #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - const uintptr_t core_pools_base_mask = setup_.core_pools_base_mask_; + const uintptr_t core_pools_base_mask = setup_.aligned.core_pools_base_mask_; #else // When PA_GLUE_CORE_POOLS is on, the BRP pool is placed at the end of the // regular pool, effectively forming one virtual pool of a twice bigger // size. Adjust the mask appropriately. constexpr uintptr_t core_pools_base_mask = kRegularPoolBaseMask << 1; #endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - bool ret = - (address & core_pools_base_mask) == setup_.regular_pool_base_address_; + bool ret = (address & core_pools_base_mask) == + setup_.aligned.regular_pool_base_address_; PA_DCHECK(ret == (IsInRegularPool(address) || IsInBRPPool(address))); return ret; } @@ -180,24 +185,24 @@ PA_ALWAYS_INLINE static uintptr_t OffsetInBRPPool(uintptr_t address) { PA_DCHECK(IsInBRPPool(address)); - return address - setup_.brp_pool_base_address_; + return address - setup_.aligned.brp_pool_base_address_; } // Returns false for nullptr. PA_ALWAYS_INLINE static bool IsInConfigurablePool(uintptr_t address) { - return (address & setup_.configurable_pool_base_mask_) == - setup_.configurable_pool_base_address_; + return (address & setup_.aligned.configurable_pool_base_mask_) == + setup_.aligned.configurable_pool_base_address_; } PA_ALWAYS_INLINE static uintptr_t ConfigurablePoolBase() { - return setup_.configurable_pool_base_address_; + return setup_.aligned.configurable_pool_base_address_; } #if BUILDFLAG(ENABLE_THREAD_ISOLATION) // Returns false for nullptr. PA_ALWAYS_INLINE static bool IsInThreadIsolatedPool(uintptr_t address) { return (address & kThreadIsolatedPoolBaseMask) == - setup_.thread_isolated_pool_base_address_; + setup_.aligned.thread_isolated_pool_base_address_; } #endif @@ -318,53 +323,38 @@ // Before PartitionAddressSpace::Init(), no allocation are allocated from a // reserved address space. Therefore, set *_pool_base_address_ initially to // -1, so that PartitionAddressSpace::IsIn*Pool() always returns false. - constexpr PoolSetup() - : regular_pool_base_address_(kUninitializedPoolBaseAddress), - brp_pool_base_address_(kUninitializedPoolBaseAddress), - configurable_pool_base_address_(kUninitializedPoolBaseAddress), -#if BUILDFLAG(ENABLE_THREAD_ISOLATION) - thread_isolated_pool_base_address_(kUninitializedPoolBaseAddress), -#endif -#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - regular_pool_base_mask_(0), - brp_pool_base_mask_(0), -#if BUILDFLAG(GLUE_CORE_POOLS) - core_pools_base_mask_(0), -#endif -#endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - configurable_pool_base_mask_(0) { - } + constexpr PoolSetup() = default; - // Using a union to enforce padding. - union { - struct { - uintptr_t regular_pool_base_address_; - uintptr_t brp_pool_base_address_; - uintptr_t configurable_pool_base_address_; + // Using a struct to enforce alignment and padding + struct Aligned { + uintptr_t regular_pool_base_address_ = kUninitializedPoolBaseAddress; + uintptr_t brp_pool_base_address_ = kUninitializedPoolBaseAddress; + uintptr_t configurable_pool_base_address_ = kUninitializedPoolBaseAddress; #if BUILDFLAG(ENABLE_THREAD_ISOLATION) - uintptr_t thread_isolated_pool_base_address_; + uintptr_t thread_isolated_pool_base_address_ = + kUninitializedPoolBaseAddress; #endif #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - uintptr_t regular_pool_base_mask_; - uintptr_t brp_pool_base_mask_; + uintptr_t regular_pool_base_mask_ = 0; + uintptr_t brp_pool_base_mask_ = 0; #if BUILDFLAG(GLUE_CORE_POOLS) - uintptr_t core_pools_base_mask_; + uintptr_t core_pools_base_mask_ = 0; #endif #endif // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE) - uintptr_t configurable_pool_base_mask_; + uintptr_t configurable_pool_base_mask_ = 0; #if BUILDFLAG(ENABLE_THREAD_ISOLATION) ThreadIsolationOption thread_isolation_; #endif - }; + } aligned; #if BUILDFLAG(ENABLE_THREAD_ISOLATION) - // With thread isolation support, we want to be able to write-protect all - // global metadata which requires page granularity. - char one_page_[SystemPageSize()]; + // With thread isolation support, we want to be able to write-protect all + // global metadata which requires page granularity. + char pad_[SystemPageSize() - sizeof(Aligned)] = {}; #else - char one_cacheline_[kPartitionCachelineSize]; + char pad_[kPartitionCachelineSize - + (sizeof(Aligned) % kPartitionCachelineSize)] = {}; #endif - }; }; #if BUILDFLAG(ENABLE_THREAD_ISOLATION) static_assert(sizeof(PoolSetup) % SystemPageSize() == 0,
diff --git a/base/allocator/partition_allocator/thread_isolation/alignment.h b/base/allocator/partition_allocator/thread_isolation/alignment.h index 84b2b31..493a1bd 100644 --- a/base/allocator/partition_allocator/thread_isolation/alignment.h +++ b/base/allocator/partition_allocator/thread_isolation/alignment.h
@@ -19,7 +19,7 @@ #define PA_THREAD_ISOLATED_FILL_PAGE_SZ(size) \ ((PA_THREAD_ISOLATED_ALIGN_SZ - \ - (size & PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK)) % \ + ((size)&PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK)) % \ PA_THREAD_ISOLATED_ALIGN_SZ) // Calculate the required padding so that the last element of a page-aligned // array lands on a page boundary. In other words, calculate that padding so
diff --git a/build/config/win/BUILD.gn b/build/config/win/BUILD.gn index e7a194de..c51ad03 100644 --- a/build/config/win/BUILD.gn +++ b/build/config/win/BUILD.gn
@@ -95,7 +95,7 @@ cflags += [ "/D__WRL_ENABLE_FUNCTION_STATICS__" ] # Tell clang which version of MSVC to emulate. - cflags += [ "-fmsc-version=1916" ] + cflags += [ "-fmsc-version=1934" ] if (is_component_build) { cflags += [
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 8076f11..7fe5222 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2211,13 +2211,12 @@ } // If we're not visible, we likely released resources, so we want to - // aggressively flush here to make sure those DeleteTextures make it to the - // GPU process to free up the memory. + // aggressively flush here to make sure those DeleteSharedImage() calls make + // it to the GPU process to free up the memory. if (!visible_ && layer_tree_frame_sink_->context_provider()) { - auto* compositor_context = layer_tree_frame_sink_->context_provider(); - compositor_context->ContextGL()->ShallowFlushCHROMIUM(); if (base::FeatureList::IsEnabled( features::kReclaimResourcesFlushInBackground)) { + auto* compositor_context = layer_tree_frame_sink_->context_provider(); compositor_context->ContextSupport()->FlushPendingWork(); } }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 2cf59b0..7a66578 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -759,6 +759,7 @@ "//chrome/browser/tabmodel/internal:java", "//chrome/browser/touch_to_fill/android/internal:java", "//chrome/browser/touch_to_fill/common/android:java", + "//chrome/browser/touch_to_fill/password_generation/android/internal:java", "//chrome/browser/touch_to_fill/payments/android/internal:java", "//chrome/browser/ui/android/appmenu/internal:java", "//chrome/browser/ui/android/autofill/internal:java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 32e12ce8..482cbc2 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -534,6 +534,8 @@ "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java", "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java", "java/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialog.java", + "java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivity.java", + "java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityLauncherImpl.java", "java/src/org/chromium/chrome/browser/directactions/ChromeDirectActionIds.java", "java/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandler.java", "java/src/org/chromium/chrome/browser/directactions/DirectActionCoordinator.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 95b2a80..6f6e1d9b 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -248,6 +248,7 @@ "junit/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragmentTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/SingleThreadBarrierClosureTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/TimedCallbackDelayerTest.java", + "junit/src/org/chromium/chrome/browser/payments/AddressEditorTest.java", "junit/src/org/chromium/chrome/browser/payments/ContactEditorTest.java", "junit/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerImplTest.java", "junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index a3f9673c..ad279e562 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -161,6 +161,7 @@ "javatests/src/org/chromium/chrome/browser/device_dialog/BluetoothScanningPermissionDialogTest.java", "javatests/src/org/chromium/chrome/browser/device_dialog/ItemChooserDialogTest.java", "javatests/src/org/chromium/chrome/browser/device_dialog/UsbChooserDialogTest.java", + "javatests/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityTest.java", "javatests/src/org/chromium/chrome/browser/directactions/CloseTabDirectActionHandlerTest.java", "javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityCustomTabTest.java", "javatests/src/org/chromium/chrome/browser/directactions/DirectActionAvailabilityTabbedTest.java",
diff --git a/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected b/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected index c5007e8..c46158a9 100644 --- a/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected +++ b/chrome/android/expectations/monochrome_public_bundle__chrome.AndroidManifest.expected
@@ -209,6 +209,12 @@ <category android:name="com.google.intent.category.DAYDREAM"/> </intent-filter> # DIFF-ANCHOR: dea53031 </activity> # DIFF-ANCHOR: 4d923622 + <activity # DIFF-ANCHOR: 6ad7b5dd + android:name="org.chromium.chrome.browser.device_lock.DeviceLockActivity" + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize" + android:exported="false" + android:theme="@style/Theme.Chromium.DialogWhenLarge"> + </activity> # DIFF-ANCHOR: 6ad7b5dd <activity # DIFF-ANCHOR: 1acdfd19 android:name="org.chromium.chrome.browser.document.ChromeLauncherActivity" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize|uiMode|density"
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayout.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayout.java index fb366e2..b55ca18 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayout.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayout.java
@@ -107,7 +107,6 @@ private boolean mIsInitialized; private float mBackgroundAlpha; - private int mTabListTopOffset; private int mFrameCount; private long mStartTime; @@ -303,7 +302,7 @@ // until the next layout pass. mDeferredAnimationRunnable = () -> { showOverviewWithTabShrink(shouldAnimate, () -> { - return getGridTabListDelegate().getThumbnailLocationOfCurrentTab(); + return getGridTabListDelegate().getThumbnailLocationOfCurrentTab(false); }, isShowingStartSurfaceHomepage, quick); }; getGridTabListDelegate().runAnimationOnNextLayout(() -> { @@ -510,8 +509,7 @@ showShrinkingAnimation &= quick; } - final Rect targetRect = target.get(); - if (!showShrinkingAnimation || targetRect == null) { + if (!showShrinkingAnimation || target.get() == null) { mStartSurface.showOverview(animate); return; } @@ -533,13 +531,13 @@ // Step 1: zoom out the source tab Supplier<Float> scaleStartValueSupplier = () -> 1.0f; - Supplier<Float> scaleEndValueSupplier = () -> targetRect.width() / (getWidth() * mDpToPx); + Supplier<Float> scaleEndValueSupplier = () -> target.get().width() / (getWidth() * mDpToPx); Supplier<Float> xStartValueSupplier = () -> 0f; - Supplier<Float> xEndValueSupplier = () -> targetRect.left / mDpToPx; + Supplier<Float> xEndValueSupplier = () -> target.get().left / mDpToPx; Supplier<Float> yStartValueSupplier = () -> 0f; - Supplier<Float> yEndValueSupplier = () -> targetRect.top / mDpToPx; + Supplier<Float> yEndValueSupplier = () -> target.get().top / mDpToPx; animationList.add(CompositorAnimator.ofWritableFloatPropertyKey(handler, sourceLayoutTab, LayoutTab.SCALE, scaleStartValueSupplier, scaleEndValueSupplier, ZOOMING_DURATION, @@ -560,7 +558,6 @@ : getWidth(), ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); - mTabListTopOffset = getLastUsedTabListDelegate().getTabListTopOffset(); CompositorAnimator backgroundAlpha = CompositorAnimator.ofFloat(handler, 0f, 1f, BACKGROUND_FADING_DURATION_MS, animator -> mBackgroundAlpha = animator.getAnimatedValue()); @@ -626,7 +623,6 @@ sourceLayoutTab.getUnclampedOriginalContentHeight(), ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); - mTabListTopOffset = getLastUsedTabListDelegate().getTabListTopOffset(); CompositorAnimator backgroundAlpha = CompositorAnimator.ofFloat(handler, 1f, 0f, BACKGROUND_FADING_DURATION_MS, animator -> mBackgroundAlpha = animator.getAnimatedValue()); @@ -732,9 +728,9 @@ private Rect getThumbnailLocationOfCurrentTab() { if (isHidingStartSurfaceHomepage()) { - return getCarouselOrSingleTabListDelegate().getThumbnailLocationOfCurrentTab(); + return getCarouselOrSingleTabListDelegate().getThumbnailLocationOfCurrentTab(true); } else { - return getGridTabListDelegate().getThumbnailLocationOfCurrentTab(); + return getGridTabListDelegate().getThumbnailLocationOfCurrentTab(true); } } @@ -852,7 +848,7 @@ mSceneLayer.pushLayers(getContext(), contentViewport, contentViewport, this, tabContentManager, resourceManager, browserControls, isTabGtsAnimationEnabled() ? currentTabListDelegate.getResourceId() : 0, - mBackgroundAlpha, mTabListTopOffset); + mBackgroundAlpha, currentTabListDelegate.getTabListTopOffset()); mFrameCount++; if (mLastFrameTime != 0) { long elapsed = SystemClock.elapsedRealtime() - mLastFrameTime;
diff --git a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java index 7bf42d3..964a71c9 100644 --- a/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java +++ b/chrome/android/features/start_surface/java/src/org/chromium/chrome/features/tasks/SingleTabSwitcherCoordinator.java
@@ -137,7 +137,7 @@ public void postHiding() {} @Override - public Rect getThumbnailLocationOfCurrentTab() { + public Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate) { assert false : "should not reach here"; return null; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java index e064bf7b..db8f53d 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinder.java
@@ -43,7 +43,6 @@ public static void bind( PropertyModel model, TabListRecyclerView view, PropertyKey propertyKey) { if (IS_VISIBLE == propertyKey) { - updateMargins(model, view); if (model.get(IS_VISIBLE)) { view.startShowing(model.get(ANIMATE_VISIBILITY_CHANGES)); } else { @@ -64,9 +63,16 @@ ((LinearLayoutManager) view.getLayoutManager()) .scrollToPositionWithOffset(index, offset); } else if (TOP_MARGIN == propertyKey) { - updateMargins(model, view); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams(); + final int newTopMargin = model.get(TOP_MARGIN); + if (newTopMargin == params.topMargin) return; + + params.topMargin = newTopMargin; + ViewUtils.requestLayout(view, "TabListContainerViewBinder.bind TOP_MARGIN"); } else if (BOTTOM_CONTROLS_HEIGHT == propertyKey) { - updateMargins(model, view); + FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams(); + params.bottomMargin = model.get(BOTTOM_CONTROLS_HEIGHT); + ViewUtils.requestLayout(view, "TabListContainerViewBinder.bind BOTTOM_CONTROLS_HEIGHT"); } else if (SHADOW_TOP_OFFSET == propertyKey) { view.setShadowTopOffset(model.get(SHADOW_TOP_OFFSET)); } else if (BOTTOM_PADDING == propertyKey) { @@ -74,31 +80,6 @@ } } - private static void updateMargins(PropertyModel model, TabListRecyclerView view) { - FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) view.getLayoutParams(); - final int oldTopMargin = params.topMargin; - final int oldBottomMargin = params.bottomMargin; - if (model.get(IS_VISIBLE)) { - params.topMargin = model.get(TOP_MARGIN); - params.bottomMargin = model.get(BOTTOM_CONTROLS_HEIGHT); - } else { - // Treat the bottom margin as 0 to avoid layout shift in tab shrink animations. - // IS_VISIBLE will be set to true after the tab shrink animation see - // {@link TabSwitcherMediator#showTabSwitcherView(boolean)}. - params.bottomMargin = 0; - - // Leave the top margin unchanged to avoid relayouts during scrolls and for top - // toolbar indicators while the view is not visible. Once visible the offset will - // adjust accordingly. - } - if (!model.get(IS_VISIBLE) - || (oldTopMargin == params.topMargin && oldBottomMargin == params.bottomMargin)) { - return; - } - - ViewUtils.requestLayout(view, "TabListContainerViewBinder.bind updateMargins"); - } - private static int computeOffset(TabListRecyclerView view, PropertyModel model) { int width = view.getWidth(); int height = view.getHeight();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java index 3df85d5..b11097a9 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -17,6 +17,7 @@ import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.ImageView; import androidx.annotation.IntDef; @@ -92,6 +93,7 @@ private final ViewGroup mRootView; private boolean mIsInitialized; + private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener; private OnLayoutChangeListener mListLayoutListener; private boolean mLayoutListenerRegistered; private @Nullable TabStripSnapshotter mTabStripSnapshotter; @@ -261,6 +263,7 @@ } if (mMode == TabListMode.GRID) { + mGlobalLayoutListener = this::updateThumbnailLocation; mListLayoutListener = (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> updateGridCardLayout(right - left); } else if (mMode == TabListMode.STRIP) { @@ -379,7 +382,6 @@ } } } - /** * Update the location of the selected thumbnail. * @return Whether a valid {@link Rect} is obtained. @@ -505,6 +507,9 @@ } void prepareTabSwitcherView() { + if (mGlobalLayoutListener != null) { + mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener); + } registerLayoutChangeListener(); mRecyclerView.prepareTabSwitcherView(); mMediator.prepareTabSwitcherView(); @@ -520,6 +525,9 @@ } void postHiding() { + if (mGlobalLayoutListener != null) { + mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener); + } unregisterLayoutChangeListener(); mRecyclerView.postHiding(); mMediator.postHiding(); @@ -531,6 +539,9 @@ @Override public void onDestroy() { mMediator.destroy(); + if (mGlobalLayoutListener != null) { + mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener); + } if (mListLayoutListener != null) { mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener); mLayoutListenerRegistered = false;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java index ea4cc80..a226890 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
@@ -211,11 +211,13 @@ void postHiding(); /** + * @param forceUpdate Whether to measure the current location again. If not, return the last + * location measured on last layout, which can be wrong after scrolling. * @return The {@link Rect} of the thumbnail of the current tab, relative to the * TabSwitcher {@link TabListRecyclerView} coordinates. */ @NonNull - Rect getThumbnailLocationOfCurrentTab(); + Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate); /** * Set a hook to receive all the {@link Bitmap}s returned by
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java index 03fe277..a3048e2 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -595,15 +595,16 @@ @Override @NonNull - public Rect getThumbnailLocationOfCurrentTab() { + public Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate) { if (mTabGridDialogCoordinator != null && mTabGridDialogCoordinator.isVisible()) { + assert forceUpdate; Rect thumbnail = mTabGridDialogCoordinator.getGlobalLocationOfCurrentThumbnail(); // Adjust to the relative coordinate. Rect root = mTabListCoordinator.getRecyclerViewLocation(); thumbnail.offset(-root.left, -root.top); return thumbnail; } - mTabListCoordinator.updateThumbnailLocation(); + if (forceUpdate) mTabListCoordinator.updateThumbnailLocation(); return mTabListCoordinator.getThumbnailLocationOfCurrentTab(); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java index c56ca5d3b..b1e26ae2 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherLayout.java
@@ -99,7 +99,6 @@ private boolean mIsInitialized; private float mBackgroundAlpha; - private int mTabListTopOffset; private int mFrameCount; private long mStartTime; @@ -233,7 +232,7 @@ boolean quick = mGridTabListDelegate.prepareTabSwitcherView(); // Skip animation when there is no tab in current tab model, we don't show the shrink - // tab animation. + // tab animatio. boolean isCurrentTabModelEmpty = mTabModelSelector.getCurrentModel().getCount() == 0; final boolean shouldAnimate = animate && !isCurrentTabModelEmpty; @@ -251,7 +250,9 @@ } else { mDeferredAnimationRunnable = () -> { showOverviewWithTabShrink(shouldAnimate, - () -> mGridTabListDelegate.getThumbnailLocationOfCurrentTab(), quick); + () + -> mGridTabListDelegate.getThumbnailLocationOfCurrentTab(false), + quick); }; mGridTabListDelegate.runAnimationOnNextLayout(() -> { if (mDeferredAnimationRunnable != null) { @@ -416,8 +417,7 @@ showShrinkingAnimation &= quick; } - final Rect targetRect = target.get(); - if (!showShrinkingAnimation || targetRect == null) { + if (!showShrinkingAnimation || target.get() == null) { mController.showTabSwitcherView(animate); return; } @@ -439,13 +439,13 @@ // Step 1: zoom out the source tab Supplier<Float> scaleStartValueSupplier = () -> 1.0f; - Supplier<Float> scaleEndValueSupplier = () -> targetRect.width() / (getWidth() * mDpToPx); + Supplier<Float> scaleEndValueSupplier = () -> target.get().width() / (getWidth() * mDpToPx); Supplier<Float> xStartValueSupplier = () -> 0f; - Supplier<Float> xEndValueSupplier = () -> targetRect.left / mDpToPx; + Supplier<Float> xEndValueSupplier = () -> target.get().left / mDpToPx; Supplier<Float> yStartValueSupplier = () -> 0f; - Supplier<Float> yEndValueSupplier = () -> targetRect.top / mDpToPx; + Supplier<Float> yEndValueSupplier = () -> target.get().top / mDpToPx; animationList.add(CompositorAnimator.ofWritableFloatPropertyKey(handler, sourceLayoutTab, LayoutTab.SCALE, scaleStartValueSupplier, scaleEndValueSupplier, ZOOMING_DURATION, @@ -466,7 +466,6 @@ : getWidth(), ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); - int mTabListTopOffset = mGridTabListDelegate.getTabListTopOffset(); CompositorAnimator backgroundAlpha = CompositorAnimator.ofFloat(handler, 0f, 1f, BACKGROUND_FADING_DURATION_MS, animator -> mBackgroundAlpha = animator.getAnimatedValue()); @@ -529,7 +528,6 @@ sourceLayoutTab.getUnclampedOriginalContentHeight(), ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); - int mTabListTopOffset = mGridTabListDelegate.getTabListTopOffset(); CompositorAnimator backgroundAlpha = CompositorAnimator.ofFloat(handler, 1f, 0f, BACKGROUND_FADING_DURATION_MS, animator -> mBackgroundAlpha = animator.getAnimatedValue()); @@ -625,7 +623,7 @@ } private Rect getThumbnailLocationOfCurrentTab() { - return mGridTabListDelegate.getThumbnailLocationOfCurrentTab(); + return mGridTabListDelegate.getThumbnailLocationOfCurrentTab(true); } private TabListDelegate getGridTabListDelegate() { @@ -695,7 +693,7 @@ mSceneLayer.pushLayers(getContext(), contentViewport, contentViewport, this, tabContentManager, resourceManager, browserControls, isTabGtsAnimationEnabled() ? mGridTabListDelegate.getResourceId() : 0, - mBackgroundAlpha, mTabListTopOffset); + mBackgroundAlpha, mGridTabListDelegate.getTabListTopOffset()); mFrameCount++; if (mLastFrameTime != 0) { long elapsed = SystemClock.elapsedRealtime() - mLastFrameTime;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java index d9f26a88..8ef7b0e 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListContainerViewBinderTest.java
@@ -328,59 +328,26 @@ @MediumTest @UiThreadTest public void testTopMarginSetsTopMargin() { - TestThreadUtils.runOnUiThreadBlocking(() -> { - mContainerModel.set( - TabListContainerProperties.VISIBILITY_LISTENER, mMockVisibilityListener); - mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, false); - }); assertThat(mRecyclerView.getLayoutParams(), instanceOf(FrameLayout.LayoutParams.class)); assertThat( ((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, equalTo(0)); - mContainerModel.set(TabListContainerProperties.IS_VISIBLE, false); mContainerModel.set(TabListContainerProperties.TOP_MARGIN, CONTAINER_HEIGHT); - assertThat( - ((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, equalTo(0)); - - mContainerModel.set(TabListContainerProperties.IS_VISIBLE, true); assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, equalTo(CONTAINER_HEIGHT)); - - mContainerModel.set(TabListContainerProperties.TOP_MARGIN, CONTAINER_HEIGHT + 1); - assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, - equalTo(CONTAINER_HEIGHT + 1)); - - mContainerModel.set(TabListContainerProperties.IS_VISIBLE, false); - mContainerModel.set(TabListContainerProperties.TOP_MARGIN, CONTAINER_HEIGHT); - assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, - equalTo(CONTAINER_HEIGHT + 1)); } @Test @MediumTest @UiThreadTest public void testBottomContainerHeightSetsBottomMargin() { - TestThreadUtils.runOnUiThreadBlocking(() -> { - mContainerModel.set( - TabListContainerProperties.VISIBILITY_LISTENER, mMockVisibilityListener); - mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, false); - }); assertThat(mRecyclerView.getLayoutParams(), instanceOf(FrameLayout.LayoutParams.class)); assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).bottomMargin, equalTo(0)); - mContainerModel.set(TabListContainerProperties.IS_VISIBLE, false); mContainerModel.set(TabListContainerProperties.BOTTOM_CONTROLS_HEIGHT, CONTAINER_HEIGHT); assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).bottomMargin, - equalTo(0)); - - mContainerModel.set(TabListContainerProperties.IS_VISIBLE, true); - assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).bottomMargin, equalTo(CONTAINER_HEIGHT)); - - mContainerModel.set(TabListContainerProperties.BOTTOM_CONTROLS_HEIGHT, 0); - assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).bottomMargin, - equalTo(0)); } @Test
diff --git a/chrome/android/java/AndroidManifest.xml b/chrome/android/java/AndroidManifest.xml index 7f44ecf..ab63b00 100644 --- a/chrome/android/java/AndroidManifest.xml +++ b/chrome/android/java/AndroidManifest.xml
@@ -622,6 +622,11 @@ android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize" android:exported="false"> </activity> + <activity android:name="org.chromium.chrome.browser.device_lock.DeviceLockActivity" + android:theme="@style/Theme.Chromium.DialogWhenLarge" + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize" + android:exported="false"> + </activity> <activity android:name="org.chromium.chrome.browser.settings.SettingsActivity" android:theme="@style/Theme.Chromium.Settings" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|mcc|mnc|screenLayout|smallestScreenSize"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActionDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActionDelegateImpl.java index ba575f4..9ecccd0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActionDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/creator/CreatorActionDelegateImpl.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; import org.chromium.chrome.browser.creator.CreatorCoordinator; +import org.chromium.chrome.browser.device_lock.DeviceLockActivityLauncherImpl; import org.chromium.chrome.browser.feed.FeedActionDelegate; import org.chromium.chrome.browser.feed.R; import org.chromium.chrome.browser.feed.signinbottomsheet.SigninBottomSheetCoordinator; @@ -96,7 +97,8 @@ public void showSignInInterstitial(int signinAccessPoint, BottomSheetController mBottomSheetController, WindowAndroid mWindowAndroid) { SigninBottomSheetCoordinator signinCoordinator = new SigninBottomSheetCoordinator( - mWindowAndroid, mBottomSheetController, mProfile, new CormorantBottomSheetStrings(), + mWindowAndroid, DeviceLockActivityLauncherImpl.get(), mBottomSheetController, + mProfile, new CormorantBottomSheetStrings(), () -> { showSyncConsentActivity(signinAccessPoint); }, signinAccessPoint); signinCoordinator.show(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java index 9a0aabf..837e9071f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/feed/FeedActionDelegateImpl.java
@@ -13,6 +13,7 @@ import org.chromium.chrome.browser.app.creator.CreatorActivity; import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.bookmarks.BookmarkUtils; +import org.chromium.chrome.browser.device_lock.DeviceLockActivityLauncherImpl; import org.chromium.chrome.browser.feed.FeedActionDelegate; import org.chromium.chrome.browser.feed.SingleWebFeedEntryPoint; import org.chromium.chrome.browser.feed.signinbottomsheet.SigninBottomSheetCoordinator; @@ -152,9 +153,9 @@ if (ChromeFeatureList.isEnabled(ChromeFeatureList.FEED_BOC_SIGN_IN_INTERSTITIAL)) { SigninMetricsUtils.logSigninStartAccessPoint(signinAccessPoint); SigninMetricsUtils.logSigninUserActionForAccessPoint(signinAccessPoint); - SigninBottomSheetCoordinator signinCoordinator = - new SigninBottomSheetCoordinator(windowAndroid, bottomSheetController, - Profile.getLastUsedRegularProfile(), null, null, signinAccessPoint); + SigninBottomSheetCoordinator signinCoordinator = new SigninBottomSheetCoordinator( + windowAndroid, DeviceLockActivityLauncherImpl.get(), bottomSheetController, + Profile.getLastUsedRegularProfile(), null, null, signinAccessPoint); signinCoordinator.show(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java index 5fa6abc..4efe216 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -69,6 +69,7 @@ // clang-format off List<CachedFlag> featuresToCache = List.of(ChromeFeatureList.sAppMenuMobileSiteOption, ChromeFeatureList.sBackGestureActivityTabProvider, + ChromeFeatureList.sBackGestureRefactorActivityAndroid, ChromeFeatureList.sBackGestureRefactorAndroid, ChromeFeatureList.sBaselineGm3SurfaceColors, ChromeFeatureList.sBottomSheetGtsSupport,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivity.java new file mode 100644 index 0000000..b38ad3b --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivity.java
@@ -0,0 +1,107 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.device_lock; + +import android.accounts.Account; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.CallSuper; + +import org.chromium.chrome.browser.SynchronousInitializationActivity; +import org.chromium.chrome.browser.ui.device_lock.DeviceLockCoordinator; +import org.chromium.components.signin.AccountUtils; +import org.chromium.ui.base.ActivityWindowAndroid; +import org.chromium.ui.base.IntentRequestTracker; +import org.chromium.ui.base.WindowAndroid; +import org.chromium.ui.modaldialog.ModalDialogManager; + +/** + * Informs the user on using a device lock to protect their privacy and data on the device. If + * the device does not currently have a device lock, the user will be prompted to create one. + */ +public class DeviceLockActivity + extends SynchronousInitializationActivity implements DeviceLockCoordinator.Delegate { + private static final String ARGUMENT_FRAGMENT_ARGS = "DeviceLockActivity.FragmentArgs"; + private static final String ARGUMENT_IN_SIGN_IN_FLOW = + "DeviceLockActivity.FragmentArgs.InSignInFlow"; + private static final String ARGUMENT_SELECTED_ACCOUNT = + "DeviceLockActivity.FragmentArgs.SelectedAccount"; + + private FrameLayout mFrameLayout; + private WindowAndroid mWindowAndroid; + private DeviceLockCoordinator mDeviceLockCoordinator; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mFrameLayout = new FrameLayout(this); + setContentView(mFrameLayout); + mWindowAndroid = new ActivityWindowAndroid(this, /* listenToActivityState= */ true, + IntentRequestTracker.createFromActivity(this)); + + Bundle fragmentArgs = getIntent().getBundleExtra(ARGUMENT_FRAGMENT_ARGS); + Account selectedAccount = AccountUtils.createAccountFromName( + fragmentArgs.getString(ARGUMENT_SELECTED_ACCOUNT)); + mDeviceLockCoordinator = + new DeviceLockCoordinator(fragmentArgs.getBoolean(ARGUMENT_IN_SIGN_IN_FLOW), this, + mWindowAndroid, this, selectedAccount); + } + + @CallSuper + @Override + protected void onDestroy() { + mWindowAndroid.destroy(); + mDeviceLockCoordinator.destroy(); + super.onDestroy(); + } + + @Override + protected ModalDialogManager createModalDialogManager() { + return null; + } + + protected static Bundle createArguments(boolean inSignInFlow, String selectedAccount) { + Bundle result = new Bundle(); + result.putBoolean(ARGUMENT_IN_SIGN_IN_FLOW, inSignInFlow); + result.putString(ARGUMENT_SELECTED_ACCOUNT, selectedAccount); + return result; + } + + /** + * Creates a new intent to start the {@link DeviceLockActivity}. + */ + protected static Intent createIntent( + Context context, boolean inSignInFlow, String selectedAccount) { + Intent intent = new Intent(context, DeviceLockActivity.class); + intent.putExtra(ARGUMENT_FRAGMENT_ARGS, + DeviceLockActivity.createArguments(inSignInFlow, selectedAccount)); + return intent; + } + + @Override + public void setView(View view) { + mFrameLayout.removeAllViews(); + mFrameLayout.addView(view); + } + + @Override + public void onDeviceLockReady() { + Intent intent = new Intent(); + setResult(Activity.RESULT_OK, intent); + finish(); + } + + @Override + public void onDeviceLockRefused() { + Intent intent = new Intent(); + setResult(Activity.RESULT_CANCELED, intent); + finish(); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityLauncherImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityLauncherImpl.java new file mode 100644 index 0000000..c03ac1c --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityLauncherImpl.java
@@ -0,0 +1,39 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.device_lock; + +import android.content.Context; +import android.content.Intent; + +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; +import org.chromium.ui.base.WindowAndroid; + +/** + * DeviceLockActivityLauncher creates the proper intent and then launches the + * {@link DeviceLockActivity} in different scenarios. + */ +public class DeviceLockActivityLauncherImpl implements DeviceLockActivityLauncher { + private static DeviceLockActivityLauncherImpl sLauncher; + + /** + * Singleton instance getter + */ + public static DeviceLockActivityLauncherImpl get() { + if (sLauncher == null) { + sLauncher = new DeviceLockActivityLauncherImpl(); + } + return sLauncher; + } + + private DeviceLockActivityLauncherImpl() {} + + @Override + public void launchDeviceLockActivity(Context context, boolean inSignInFlow, + String selectedAccount, WindowAndroid windowAndroid, + WindowAndroid.IntentCallback callback) { + Intent intent = DeviceLockActivity.createIntent(context, inSignInFlow, selectedAccount); + windowAndroid.showIntent(intent, callback, null); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/device_lock/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/device_lock/OWNERS new file mode 100644 index 0000000..da4fc781 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/device_lock/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/ui/android/device_lock/OWNERS
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java index 455c81e8..df447c2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
@@ -16,6 +16,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.AppHooks; +import org.chromium.chrome.browser.device_lock.DeviceLockActivityLauncherImpl; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.history_clusters.HistoryClustersTabHelper; @@ -288,7 +289,8 @@ new ShareSheetCoordinator(controller, lifecycleDispatcher, tabProvider, printCallback, new LargeIconBridge(profile), isIncognito, AppHooks.get().getImageEditorModuleProvider(), - TrackerFactory.getTrackerForProfile(profile), profile); + TrackerFactory.getTrackerForProfile(profile), profile, + DeviceLockActivityLauncherImpl.get()); coordinator.showInitialShareSheet(params, chromeShareExtras, shareStartTime); RecordHistogram.recordEnumeratedHistogram( "Sharing.SharingHubAndroid.ShareContentType", @@ -300,7 +302,8 @@ "Sharing.DefaultSharesheetAndroid.ShareContentType", getShareContentType(params, chromeShareExtras), ShareContentType.COUNT); AndroidShareSheetController.showShareSheet(params, chromeShareExtras, controller, - tabProvider, tabModelSelectorSupplier, profileSupplier, printCallback); + tabProvider, tabModelSelectorSupplier, profileSupplier, printCallback, + DeviceLockActivityLauncherImpl.get()); RecordHistogram.recordEnumeratedHistogram( "Sharing.SharingHubAndroid.ShareContentType", getShareContentType(params, chromeShareExtras), ShareContentType.COUNT);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java index 672c91be..611bd3f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java
@@ -12,6 +12,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.device_lock.DeviceLockActivityLauncherImpl; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; @@ -116,7 +117,7 @@ new AccountPickerBottomSheetCoordinator(windowAndroid, bottomSheetController, new WebSigninAccountPickerDelegate(TabModelUtils.getCurrentTab(regularTabModel), new WebSigninBridge.Factory(), continueUrl), - new AccountPickerBottomSheetStrings() {}); + new AccountPickerBottomSheetStrings() {}, DeviceLockActivityLauncherImpl.get()); } private SigninBridge() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java index c85f3f6c..4b901481 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -1288,14 +1288,7 @@ mIsLoading = false; RewindableIterator<TabObserver> observers = getTabObservers(); - // When the renderer crashes for a hidden tab, we can skip notifying the observers to crash - // the underlying tab. This is because it is safe to keep the tab around without a renderer - // process, and since the tab is hidden, we don't need to show a sad tab. Since we already - // call setNeedsReload, when the tab goes foreground it will be reloaded instead of showing - // a sad tab. - if (!isHidden()) { - while (observers.hasNext()) observers.next().onCrash(this); - } + while (observers.hasNext()) observers.next().onCrash(this); mIsBeingRestored = false; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java index 54e33d6..3849979 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java
@@ -436,26 +436,26 @@ histogramWatcher.assertExpected(); } - /** Tests that when SpareTab is not destroyed when the renderer is killed. */ + /** Tests that when SpareTab is destroyed when the renderer is killed. */ @Test @MediumTest @Feature({"SpareTab"}) @EnableFeatures(ChromeFeatureList.SPARE_TAB) @UiThreadTest - public void testDontDestroySpareTabWhenRendererKilled() { + public void testDestroySpareTabWhenRendererKilled() { // Set the param to true allowing renderer initialization. WarmupManager.SPARE_TAB_INITIALIZE_RENDERER.setForTesting(true); var histogramWatcher = HistogramWatcher.newSingleRecordWatcher( - HISTOGRAM_SPARE_TAB_FINAL_STATUS, SpareTabFinalStatus.TAB_USED); + HISTOGRAM_SPARE_TAB_FINAL_STATUS, SpareTabFinalStatus.TAB_CRASHED); mWarmupManager.createSpareTab(mActivityTestRule.getActivity().getCurrentTabCreator(), TabLaunchType.FROM_START_SURFACE); - // Kill the renderer process, this shouldn't kill the associated spare tab and record - // TAB_CREATED status. + // Kill the renderer process, this should kill the associated spare tab and record + // TAB_CRASHED status. WebContentsUtils.simulateRendererKilled(mWarmupManager.mSpareTab.getWebContents()); - Assert.assertNotNull(mWarmupManager.takeSpareTab(false, TabLaunchType.FROM_START_SURFACE)); + Assert.assertNull(mWarmupManager.takeSpareTab(false, TabLaunchType.FROM_START_SURFACE)); histogramWatcher.assertExpected(); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java index e1db3fd..1f91dce 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionTest.java
@@ -257,7 +257,7 @@ } /** - * Tests that if the renderer backing a hidden tab is killed, the speculation is not + * Tests that if the renderer backing a hidden tab is killed, the speculation is * canceled. */ @Test @@ -277,9 +277,15 @@ mCustomTabsConnection.getSpeculationParamsForTesting()); Tab speculationTab = mCustomTabsConnection.getSpeculationParamsForTesting().tab; Assert.assertNotNull("Null speculation tab", speculationTab); + speculationTab.addObserver(new EmptyTabObserver() { + @Override + public void onDestroyed(Tab tab) { + tabDestroyedHelper.notifyCalled(); + } + }); WebContentsUtils.simulateRendererKilled(speculationTab.getWebContents()); - Assert.assertNotNull("Null speculation tab", speculationTab); }); + tabDestroyedHelper.waitForCallback("The speculated tab was not destroyed", 0); } @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityTest.java new file mode 100644 index 0000000..888e4b4 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/device_lock/DeviceLockActivityTest.java
@@ -0,0 +1,82 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +package org.chromium.chrome.browser.device_lock; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.assertion.ViewAssertions.matches; +import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +import static org.junit.Assert.assertEquals; + +import android.app.Activity; +import android.content.Intent; +import android.os.Build; + +import androidx.lifecycle.Lifecycle; +import androidx.test.core.app.ActivityScenario; +import androidx.test.filters.MediumTest; + +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ContextUtils; +import org.chromium.base.test.util.DoNotBatch; +import org.chromium.base.test.util.MinAndroidSdkLevel; +import org.chromium.chrome.R; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; + +/** + * Tests for the Device Lock Activity. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@DoNotBatch(reason = "ActivityScenario tests should run separately, ActivityScenarioRule does " + + "not support #launchActivityForResult") +public class DeviceLockActivityTest { + private DeviceLockActivity mDeviceLockActivity; + private ActivityScenario<DeviceLockActivity> mActivityScenario; + + @After + public void tearDown() { + mActivityScenario.close(); + mActivityScenario = null; + } + + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.O) + public void testDeviceLockReady_finishesActivityWithResultOk() { + launchActivity(); + onView(withText(R.string.device_lock_title)).check(matches(isDisplayed())); + + mDeviceLockActivity.onDeviceLockReady(); + assertEquals("Activity should be finished", Lifecycle.State.DESTROYED, + mActivityScenario.getState()); + assertEquals("Setting a device lock should set activity result to OK", Activity.RESULT_OK, + mActivityScenario.getResult().getResultCode()); + } + + @Test + @MediumTest + @MinAndroidSdkLevel(Build.VERSION_CODES.O) + public void testDeviceLockRefused_finishesActivityWithResultCanceled() { + launchActivity(); + onView(withText(R.string.device_lock_title)).check(matches(isDisplayed())); + + mDeviceLockActivity.onDeviceLockRefused(); + assertEquals("Activity should be finished", Lifecycle.State.DESTROYED, + mActivityScenario.getState()); + assertEquals("Refusing a device lock should set activity result to CANCELED", + Activity.RESULT_CANCELED, mActivityScenario.getResult().getResultCode()); + } + + public void launchActivity() { + Intent intent = DeviceLockActivity.createIntent( + ContextUtils.getApplicationContext(), true, "testSelectedAccount"); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mActivityScenario = ActivityScenario.launchActivityForResult(intent); + mActivityScenario.onActivity(activity -> mDeviceLockActivity = activity); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AddressEditorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AddressEditorTest.java index 7313eda1..0f2bdcef 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AddressEditorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/autofill/settings/AddressEditorTest.java
@@ -76,7 +76,7 @@ ChromeFeatureList.AUTOFILL_ENABLE_SUPPORT_FOR_HONORIFIC_PREFIXES}) public class AddressEditorTest { private static final String USER_EMAIL = "example@gmail.com"; - private static final Locale DEFAULT_LOCALTE = Locale.getDefault(); + private static final Locale DEFAULT_LOCALE = Locale.getDefault(); private static final List<AddressUiComponent> SUPPORTED_ADDRESS_FIELDS = List.of( new AddressUiComponent(AddressField.RECIPIENT, "full name label", true, true), new AddressUiComponent(AddressField.ADMIN_AREA, "admin area label", false, true), @@ -178,16 +178,16 @@ @After public void tearDown() { // Reset default locale to avoid changing it for other tests. - Locale.setDefault(DEFAULT_LOCALTE); + Locale.setDefault(DEFAULT_LOCALE); PersonalDataManager.setInstanceForTesting(null); } - private void setUpSupportedCountries(List<DropdownKeyValue> supportedContries) { + private void setUpSupportedCountries(List<DropdownKeyValue> supportedCountries) { doAnswer(invocation -> { List<String> contryCodes = (List<String>) invocation.getArguments()[0]; List<String> contryNames = (List<String>) invocation.getArguments()[1]; - for (DropdownKeyValue keyValue : supportedContries) { + for (DropdownKeyValue keyValue : supportedCountries) { contryCodes.add(keyValue.getKey()); contryNames.add(keyValue.getValue().toString()); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/payments/AddressEditorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/payments/AddressEditorTest.java new file mode 100644 index 0000000..416cb97 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/payments/AddressEditorTest.java
@@ -0,0 +1,503 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.payments; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyList; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.Activity; + +import androidx.annotation.Nullable; +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; + +import org.chromium.base.Callback; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.autofill.PersonalDataManager; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.autofill.Source; +import org.chromium.chrome.browser.autofill.prefeditor.EditorDialog; +import org.chromium.chrome.browser.autofill.prefeditor.EditorModel; +import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge; +import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressField; +import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridge.AddressUiComponent; +import org.chromium.chrome.browser.autofill.settings.AutofillProfileBridgeJni; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.components.autofill.prefeditor.EditorFieldModel; +import org.chromium.components.autofill.prefeditor.EditorFieldModel.DropdownKeyValue; +import org.chromium.ui.base.TestActivity; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + +/** Unit tests for {@link AddressEditor}. */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class AddressEditorTest { + private static final Locale DEFAULT_LOCALE = Locale.getDefault(); + private static final List<AddressUiComponent> SUPPORTED_ADDRESS_FIELDS = List.of( + new AddressUiComponent(AddressField.RECIPIENT, /*label=*/"full name label", + /*isRequired=*/false, /*isFullLine=*/true), + new AddressUiComponent(AddressField.ADMIN_AREA, /*label=*/"admin area label", + /*isRequired=*/true, /*isFullLine=*/true), + new AddressUiComponent(AddressField.LOCALITY, /*label=*/"locality label", + /*isRequired=*/true, /*isFullLine=*/false), + new AddressUiComponent(AddressField.DEPENDENT_LOCALITY, + /*label=*/"dependent locality label", /*isRequired=*/true, + /*isFullLine=*/false), + new AddressUiComponent(AddressField.ORGANIZATION, /*label=*/"organization label", + /*isRequired=*/false, /*isFullLine=*/true), + new AddressUiComponent(AddressField.SORTING_CODE, /*label=*/"sorting code label", + /*isRequired=*/false, /*isFullLine=*/false), + new AddressUiComponent(AddressField.POSTAL_CODE, /*label=*/"postal code label", + /*isRequired=*/true, /*isFullLine=*/false), + new AddressUiComponent(AddressField.STREET_ADDRESS, /*label=*/"street address label", + /*isRequired=*/true, /*isFullLine=*/true)); + + private static final AutofillProfile sProfile = new AutofillProfile(/*guid=*/"", + /*isLocal=*/true, Source.LOCAL_OR_SYNCABLE, /*honorific prefix=*/"", + /*fullName=*/"Seb Doe", /*companyName=*/"Google", /*streetAddress=*/"111 First St", + /*region=*/"CA", /*locality=*/"Los Angeles", /*dependentLocality=*/"", + /*postalCode=*/"90291", /*sortingCode=*/"", /*countryCode*/ "US", + /*phoneNumber=*/"650-253-0000", /*emailAddress=*/"first@gmail.com", + /*languageCode=*/"en-US"); + + @Rule + public TestRule mProcessor = new Features.JUnitProcessor(); + @Rule + public JniMocker mJniMocker = new JniMocker(); + + @Mock + private AutofillProfileBridge.Natives mAutofillProfileBridgeJni; + + @Mock + private EditorDialog mEditorDialog; + @Mock + private PersonalDataManager mPersonalDataManager; + @Mock + private Callback<AutofillAddress> mDoneCallback; + @Mock + private Callback<AutofillAddress> mCancelCallback; + + @Captor + private ArgumentCaptor<EditorModel> mEditorModelCapture; + @Captor + private ArgumentCaptor<AutofillAddress> mAddressCapture; + + // Note: can't initialize this list statically because of how Robolectric + // initializes Android library dependencies. + private final List<DropdownKeyValue> mSupportedCountries = + List.of(new DropdownKeyValue("US", "United States"), + new DropdownKeyValue("DE", "Germany"), new DropdownKeyValue("CU", "Cuba")); + + private Activity mActivity; + private AddressEditor mAddressEditor; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + Locale.setDefault(Locale.US); + + mJniMocker.mock(AutofillProfileBridgeJni.TEST_HOOKS, mAutofillProfileBridgeJni); + doAnswer(invocation -> { + List<Integer> requiredFields = (List<Integer>) invocation.getArguments()[1]; + requiredFields.addAll(List.of(AddressField.RECIPIENT, AddressField.LOCALITY, + AddressField.DEPENDENT_LOCALITY, AddressField.POSTAL_CODE)); + return null; + }) + .when(mAutofillProfileBridgeJni) + .getRequiredFields(anyString(), anyList()); + + mActivity = Robolectric.setupActivity(TestActivity.class); + + PersonalDataManager.setInstanceForTesting(mPersonalDataManager); + + setUpSupportedCountries(mSupportedCountries); + + when(mEditorDialog.getContext()).thenReturn(mActivity); + doNothing().when(mEditorDialog).show(mEditorModelCapture.capture()); + } + + @After + public void tearDown() { + // Reset default values to avoid changing them for other batched tests. + Locale.setDefault(DEFAULT_LOCALE); + PersonalDataManager.setInstanceForTesting(null); + } + + private void setUpSupportedCountries(List<DropdownKeyValue> supportedCountries) { + doAnswer(invocation -> { + List<String> contryCodes = (List<String>) invocation.getArguments()[0]; + List<String> contryNames = (List<String>) invocation.getArguments()[1]; + + for (DropdownKeyValue keyValue : supportedCountries) { + contryCodes.add(keyValue.getKey()); + contryNames.add(keyValue.getValue().toString()); + } + + return null; + }) + .when(mAutofillProfileBridgeJni) + .getSupportedCountries(anyList(), anyList()); + } + + private void setUpAddressUiComponents( + List<AddressUiComponent> addressUiComponents, String countryCode) { + doAnswer(invocation -> { + List<Integer> componentIds = (List<Integer>) invocation.getArguments()[3]; + List<String> componentNames = (List<String>) invocation.getArguments()[4]; + List<Integer> componentRequired = (List<Integer>) invocation.getArguments()[5]; + List<Integer> componentLength = (List<Integer>) invocation.getArguments()[6]; + + for (AddressUiComponent component : addressUiComponents) { + componentIds.add(component.id); + componentNames.add(component.label); + componentRequired.add(component.isRequired ? 1 : 0); + componentLength.add(component.isFullLine ? 1 : 0); + } + return "EN"; + }) + .when(mAutofillProfileBridgeJni) + .getAddressUiComponents(eq(countryCode), anyString(), anyInt(), anyList(), + anyList(), anyList(), anyList()); + } + + private static void validateTextField(EditorFieldModel field, String value, int inputTypeHint, + String label, boolean isRequired, boolean isFullLine, boolean hasLengthCounter) { + assertTrue(field.isTextField()); + assertEquals(field.getValue(), value); + assertEquals(inputTypeHint, field.getInputTypeHint()); + assertEquals(label, field.getLabel()); + assertEquals(isRequired, field.isRequired()); + assertEquals(isFullLine, field.isFullLine()); + assertEquals(hasLengthCounter, field.hasLengthCounter()); + } + + private static void checkUiStringsHaveExpectedValues(EditorModel editorModel, + String expectedDeleteTitle, String expectedDeleteText, + @Nullable String expectedSourceNotice) { + assertNotNull(editorModel); + + assertEquals(expectedDeleteTitle, editorModel.getDeleteConfirmationTitle()); + assertEquals(expectedDeleteText, editorModel.getDeleteConfirmationText()); + assertEquals(expectedSourceNotice, editorModel.getFooterMessageText()); + } + + private void validateShownFields(EditorModel editorModel, AutofillProfile profile) { + assertNotNull(editorModel); + List<EditorFieldModel> editorFields = editorModel.getFields(); + // editorFields[0] - country dropdown. + // editorFields[1] - full name field. + // editorFields[2] - admin area field. + // editorFields[3] - locality field. + // editorFields[4] - dependent locality field. + // editorFields[5] - organization field. + // editorFields[6] - sorting code field. + // editorFields[7] - postal code field. + // editorFields[8] - street address field. + // editorFields[9] - phone number field. + assertEquals(10, editorFields.size()); + + // Fields obtained from backend must be placed after the country dropdown. + validateTextField(editorFields.get(1), profile.getFullName(), + EditorFieldModel.INPUT_TYPE_HINT_PERSON_NAME, /*label=*/"full name label", + /*isRequired=*/true, /*isFullLine=*/true, /*hasLengthCounter=*/false); + validateTextField(editorFields.get(2), profile.getRegion(), + EditorFieldModel.INPUT_TYPE_HINT_REGION, /*label=*/"admin area label", + /*isRequired=*/true, /*isFullLine=*/true, /*hasLengthCounter=*/false); + // Locality field is forced to occupy full line. + validateTextField(editorFields.get(3), profile.getLocality(), + EditorFieldModel.INPUT_TYPE_HINT_NONE, /*label=*/"locality label", + /*isRequired=*/true, /*isFullLine=*/true, /*hasLengthCounter=*/false); + + // Note: dependent locality is a required field for address profiles stored in Google + // account, but it's still marked as optional by the editor when the corresponding field in + // the existing address profile is empty. It is considered required for new address + // profiles. + validateTextField(editorFields.get(4), profile.getDependentLocality(), + EditorFieldModel.INPUT_TYPE_HINT_NONE, /*label=*/"dependent locality label", + /*isRequired=*/true, /*isFullLine=*/true, + /*hasLengthCounter=*/false); + + validateTextField(editorFields.get(5), profile.getCompanyName(), + EditorFieldModel.INPUT_TYPE_HINT_NONE, /*label=*/"organization label", + /*isRequired=*/false, /*isFullLine=*/true, /*hasLengthCounter=*/false); + + validateTextField(editorFields.get(6), profile.getSortingCode(), + EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC, /*label=*/"sorting code label", + /*isRequired=*/false, /*isFullLine=*/false, + /*hasLengthCounter=*/false); + validateTextField(editorFields.get(7), profile.getPostalCode(), + EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC, /*label=*/"postal code label", + /*isRequired=*/true, /*isFullLine=*/false, + /*hasLengthCounter=*/false); + validateTextField(editorFields.get(8), profile.getStreetAddress(), + EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES, /*label=*/"street address label", + /*isRequired=*/true, /*isFullLine=*/true, + /*hasLengthCounter=*/false); + validateTextField(editorFields.get(9), profile.getPhoneNumber(), + EditorFieldModel.INPUT_TYPE_HINT_PHONE, + mActivity.getString(R.string.autofill_profile_editor_phone_number), + /*isRequired=*/true, /*isFullLine=*/true, + /*hasLengthCounter=*/false); + } + + @Test + @SmallTest + public void validateDefaultFields() { + setUpAddressUiComponents(new ArrayList(), /*countryCode=*/"US"); + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + mAddressEditor.setEditorDialog(mEditorDialog); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(null, null); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.edit(new AutofillAddress(mActivity, sProfile), unused -> {}); + + assertNotNull(mEditorModelCapture.getValue()); + List<EditorFieldModel> editorFields = mEditorModelCapture.getValue().getFields(); + // Following values are set regardless of the UI components list + // received from backend when nicknames are disabled: + // editorFields[0] - country dropdown. + // editorFields[1] - phone field. + assertEquals(2, editorFields.size()); + + EditorFieldModel countryDropdown = editorFields.get(0); + assertTrue(countryDropdown.isDropdownField()); + assertTrue(countryDropdown.isFullLine()); + assertEquals(countryDropdown.getValue(), AutofillAddress.getCountryCode(sProfile)); + assertEquals(countryDropdown.getLabel(), + mActivity.getString(R.string.autofill_profile_editor_country)); + assertEquals(mSupportedCountries.size(), countryDropdown.getDropdownKeyValues().size()); + assertThat(mSupportedCountries, + containsInAnyOrder(countryDropdown.getDropdownKeyValues().toArray())); + + validateTextField(editorFields.get(1), sProfile.getPhoneNumber(), + EditorFieldModel.INPUT_TYPE_HINT_PHONE, + mActivity.getString(R.string.autofill_profile_editor_phone_number), + /*isRequired=*/true, /*isFullLine=*/true, + /*hasLengthCounter=*/false); + } + + @Test + @SmallTest + public void validateAdminAreaDropdown() { + // Configure only admin area field to keep the test focused. + setUpAddressUiComponents( + List.of(new AddressUiComponent(AddressField.ADMIN_AREA, "admin area label", + /*isRequired=*/true, /*isFullLine=*/true)), + /*countryCode=*/"US"); + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + mAddressEditor.setEditorDialog(mEditorDialog); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(new String[] {"CA", "NY", "TX"}, + new String[] {"California", "New York", "Texas"}); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.edit(new AutofillAddress(mActivity, sProfile), unused -> {}); + + assertNotNull(mEditorModelCapture.getValue()); + List<EditorFieldModel> editorFields = mEditorModelCapture.getValue().getFields(); + // Following values are set regardless of the UI components list + // received from backend when nicknames are disabled: + // editorFields[0] - country dropdown. + // editorFields[1] - admin area dropdown. + // editorFields[2] - phone field. + assertEquals(3, editorFields.size()); + + EditorFieldModel adminAreaDropdown = editorFields.get(1); + + List<DropdownKeyValue> adminAreas = List.of(new DropdownKeyValue("CA", "California"), + new DropdownKeyValue("NY", "New York"), new DropdownKeyValue("TX", "Texas")); + assertThat( + adminAreas, containsInAnyOrder(adminAreaDropdown.getDropdownKeyValues().toArray())); + + assertTrue(adminAreaDropdown.isDropdownField()); + assertTrue(adminAreaDropdown.isFullLine()); + assertEquals(adminAreaDropdown.getValue(), sProfile.getRegion()); + assertEquals(adminAreaDropdown.getLabel(), "admin area label"); + } + + @Test + @SmallTest + public void validateShownFields_NewAddressProfile() { + setUpAddressUiComponents(SUPPORTED_ADDRESS_FIELDS, /*countryCode=*/"US"); + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(null, null); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.setEditorDialog(mEditorDialog); + mAddressEditor.edit(null, unused -> {}); + + validateShownFields(mEditorModelCapture.getValue(), new AutofillProfile()); + } + + @Test + @SmallTest + public void validateShownFields_ExistingAddressProfile() { + setUpAddressUiComponents(SUPPORTED_ADDRESS_FIELDS, /*countryCode=*/"US"); + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(null, null); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.setEditorDialog(mEditorDialog); + mAddressEditor.edit(new AutofillAddress(mActivity, sProfile), unused -> {}); + + validateShownFields(mEditorModelCapture.getValue(), sProfile); + } + + @Test + @SmallTest + public void edit_ChangeCountry_FieldsSetChanges() { + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + setUpAddressUiComponents( + List.of(new AddressUiComponent(AddressField.SORTING_CODE, "sorting code label", + /*isRequired=*/false, /*isFullLine=*/true)), + /*countryCode=*/"US"); + setUpAddressUiComponents( + List.of(new AddressUiComponent(AddressField.STREET_ADDRESS, "street address label", + /*isRequired=*/true, /*isFullLine=*/true)), + /*countryCode=*/"DE"); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(null, null); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.setEditorDialog(mEditorDialog); + mAddressEditor.edit(null, unused -> {}); + + assertNotNull(mEditorModelCapture.getValue()); + List<EditorFieldModel> editorFields = mEditorModelCapture.getValue().getFields(); + + // editorFields[0] - country dropdown. + // editorFields[1] - sorting code field. + // editorFields[2] - phone number field. + assertEquals(3, editorFields.size()); + assertThat(editorFields.stream() + .map(EditorFieldModel::getInputTypeHint) + .collect(Collectors.toList()), + containsInAnyOrder(EditorFieldModel.INPUT_TYPE_HINT_DROPDOWN, + EditorFieldModel.INPUT_TYPE_HINT_ALPHA_NUMERIC, + EditorFieldModel.INPUT_TYPE_HINT_PHONE)); + EditorFieldModel countryDropdown = editorFields.get(0); + + countryDropdown.setDropdownKey("DE", () -> {}); + // editorFields[0] - country dropdown. + // editorFields[1] - street address field. + // editorFields[2] - phone number field. + assertEquals(3, editorFields.size()); + assertThat(editorFields.stream() + .map(EditorFieldModel::getInputTypeHint) + .collect(Collectors.toList()), + containsInAnyOrder(EditorFieldModel.INPUT_TYPE_HINT_DROPDOWN, + EditorFieldModel.INPUT_TYPE_HINT_STREET_LINES, + EditorFieldModel.INPUT_TYPE_HINT_PHONE)); + } + + @Test + @SmallTest + public void edit_AlterAddressProfile_Cancel() { + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + setUpAddressUiComponents(SUPPORTED_ADDRESS_FIELDS, /*countryCode=*/"US"); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(null, null); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.setEditorDialog(mEditorDialog); + mAddressEditor.edit(new AutofillAddress(mActivity, new AutofillProfile(sProfile)), + mDoneCallback, mCancelCallback); + + EditorModel editorModel = mEditorModelCapture.getValue(); + assertNotNull(editorModel); + List<EditorFieldModel> editorFields = editorModel.getFields(); + assertEquals(10, editorFields.size()); + + // Verify behaviour only on the relevant subset of fields. + editorFields.get(1).setValue("New Name"); + editorFields.get(2).setValue("New admin area"); + editorFields.get(3).setValue("New locality"); + editorModel.cancel(); + + verify(mDoneCallback, times(0)).onResult(any()); + verify(mCancelCallback, times(1)).onResult(any()); + } + + @Test + @SmallTest + public void edit_AlterAddressProfile_CommitChanges() { + mAddressEditor = new AddressEditor(/*saveToDisk=*/false); + setUpAddressUiComponents(SUPPORTED_ADDRESS_FIELDS, /*countryCode=*/"US"); + doAnswer(unused -> { + mAddressEditor.onSubKeysReceived(null, null); + return null; + }) + .when(mPersonalDataManager) + .getRegionSubKeys(anyString(), any()); + mAddressEditor.setEditorDialog(mEditorDialog); + mAddressEditor.edit(new AutofillAddress(mActivity, new AutofillProfile(sProfile)), + mDoneCallback, mCancelCallback); + + assertNotNull(mEditorModelCapture.getValue()); + EditorModel editorModel = mEditorModelCapture.getValue(); + List<EditorFieldModel> editorFields = editorModel.getFields(); + assertEquals(10, editorFields.size()); + + // Verify behaviour only on the relevant subset of fields. + editorFields.get(3).setValue("New locality"); + editorFields.get(4).setValue("New dependent locality"); + editorFields.get(5).setValue("New organization"); + editorModel.done(); + + verify(mDoneCallback, times(1)).onResult(mAddressCapture.capture()); + verify(mCancelCallback, times(0)).onResult(any()); + AutofillAddress address = mAddressCapture.getValue(); + assertNotNull(address); + assertEquals("New locality", address.getProfile().getLocality()); + assertEquals("New dependent locality", address.getProfile().getDependentLocality()); + assertEquals("New organization", address.getProfile().getCompanyName()); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareDelegateImplUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareDelegateImplUnitTest.java index 8c83567..fb4601c 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareDelegateImplUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/share/ShareDelegateImplUnitTest.java
@@ -48,6 +48,7 @@ import org.chromium.chrome.browser.share.share_sheet.ShareSheetCoordinator; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.modules.image_editor.ImageEditorModuleProvider; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -368,7 +369,8 @@ public static void showShareSheet(ShareParams params, ChromeShareExtras chromeShareExtras, BottomSheetController controller, Supplier<Tab> tabProvider, Supplier<TabModelSelector> tabModelSelectorSupplier, - Supplier<Profile> profileSupplier, Callback<Tab> printCallback) { + Supplier<Profile> profileSupplier, Callback<Tab> printCallback, + DeviceLockActivityLauncher deviceLockActivityLauncher) { sShareWithSystemShareSheetUiCalled = true; }
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 7534891..57fc490 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3313,6 +3313,7 @@ "//chrome/browser/signin/services/android:jni_headers", "//chrome/browser/sync/android:jni_headers", "//chrome/browser/tab:jni_headers", + "//chrome/browser/touch_to_fill/password_generation/android", "//chrome/browser/touch_to_fill/password_generation/android:public", "//chrome/browser/touch_to_fill/payments/android:public", "//chrome/browser/ui/android/layouts:android",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6483a2e..e936ddb 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -6552,6 +6552,10 @@ flag_descriptions::kDownloadRangeDescription, kOsAll, FEATURE_VALUE_TYPE(download::features::kDownloadRange)}, + {"tab-hover-card-images", flag_descriptions::kTabHoverCardImagesName, + flag_descriptions::kTabHoverCardImagesDescription, kOsDesktop, + FEATURE_VALUE_TYPE(features::kTabHoverCardImages)}, + {"enable-storage-pressure-event", flag_descriptions::kStoragePressureEventName, flag_descriptions::kStoragePressureEventDescription, kOsAll,
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc index 1ded7129..5cc5c3c 100644 --- a/chrome/browser/android/shortcut_helper.cc +++ b/chrome/browser/android/shortcut_helper.cc
@@ -33,7 +33,8 @@ void AddWebappWithSkBitmap(content::WebContents* web_contents, const webapps::ShortcutInfo& info, const std::string& webapp_id, - const SkBitmap& icon_bitmap) { + const SkBitmap& icon_bitmap, + bool is_icon_maskable) { // Send the data to the Java side to create the shortcut. JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jstring> java_webapp_id = @@ -58,7 +59,7 @@ Java_ShortcutHelper_addWebapp( env, java_webapp_id, java_url, java_scope_url, java_user_title, java_name, java_short_name, java_best_primary_icon_url, java_bitmap, - info.is_primary_icon_maskable, static_cast<int>(info.display), + is_icon_maskable, static_cast<int>(info.display), static_cast<int>(info.orientation), info.source, ui::OptionalSkColorToJavaColor(info.theme_color), ui::OptionalSkColorToJavaColor(info.background_color)); @@ -74,7 +75,8 @@ // Adds a shortcut which opens in a browser tab to the launcher. void AddShortcutWithSkBitmap(const webapps::ShortcutInfo& info, const std::string& id, - const SkBitmap& icon_bitmap) { + const SkBitmap& icon_bitmap, + bool is_icon_maskable) { JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jstring> java_id = base::android::ConvertUTF8ToJavaString(env, id); @@ -89,8 +91,8 @@ if (!icon_bitmap.drawsNothing()) java_bitmap = gfx::ConvertToJavaBitmap(icon_bitmap); Java_ShortcutHelper_addShortcut(env, java_id, java_url, java_user_title, - java_bitmap, info.is_primary_icon_maskable, - info.source, java_best_primary_icon_url); + java_bitmap, is_icon_maskable, info.source, + java_best_primary_icon_url); } void RecordAddToHomeScreenUKM( @@ -117,6 +119,7 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& info, const SkBitmap& icon_bitmap, + bool is_icon_maskable, webapps::InstallableStatusCode installable_status) { RecordAddToHomeScreenUKM(web_contents, info, installable_status); @@ -124,10 +127,11 @@ if (info.display == blink::mojom::DisplayMode::kStandalone || info.display == blink::mojom::DisplayMode::kFullscreen || info.display == blink::mojom::DisplayMode::kMinimalUi) { - AddWebappWithSkBitmap(web_contents, info, webapp_id, icon_bitmap); + AddWebappWithSkBitmap(web_contents, info, webapp_id, icon_bitmap, + is_icon_maskable); return; } - AddShortcutWithSkBitmap(info, webapp_id, icon_bitmap); + AddShortcutWithSkBitmap(info, webapp_id, icon_bitmap, is_icon_maskable); } // static
diff --git a/chrome/browser/android/shortcut_helper.h b/chrome/browser/android/shortcut_helper.h index 0f678b8..d55d0f4 100644 --- a/chrome/browser/android/shortcut_helper.h +++ b/chrome/browser/android/shortcut_helper.h
@@ -40,6 +40,7 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& info, const SkBitmap& icon_bitmap, + bool is_icon_maskable, webapps::InstallableStatusCode installable_status); // Stores the webapp splash screen in the WebappDataStorage associated with
diff --git a/chrome/browser/android/webapk/webapk_install_service.cc b/chrome/browser/android/webapk/webapk_install_service.cc index 7626d75..c647a37 100644 --- a/chrome/browser/android/webapk/webapk_install_service.cc +++ b/chrome/browser/android/webapk/webapk_install_service.cc
@@ -46,6 +46,7 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, webapps::WebappInstallSource install_source) { if (IsInstallInProgress(shortcut_info.manifest_id)) { webapps::WebappsUtils::ShowWebApkInstallResultToast( @@ -56,18 +57,19 @@ install_ids_.insert(shortcut_info.manifest_id); webapps::InstallableMetrics::TrackInstallEvent(install_source); - ShowInstallInProgressNotification( - shortcut_info.manifest_id, shortcut_info.short_name, shortcut_info.url, - primary_icon, shortcut_info.is_primary_icon_maskable); + ShowInstallInProgressNotification(shortcut_info.manifest_id, + shortcut_info.short_name, shortcut_info.url, + primary_icon, is_primary_icon_maskable); // We pass an weak ptr to a WebContents to the callback, since the // installation may take more than 10 seconds so there is a chance that the // WebContents has been destroyed before the install is finished. WebApkInstaller::InstallAsync( browser_context_, web_contents, shortcut_info, primary_icon, + is_primary_icon_maskable, base::BindOnce(&WebApkInstallService::OnFinishedInstall, weak_ptr_factory_.GetWeakPtr(), web_contents->GetWeakPtr(), - shortcut_info, primary_icon)); + shortcut_info, primary_icon, is_primary_icon_maskable)); } void WebApkInstallService::InstallForServiceAsync( @@ -100,7 +102,8 @@ WebApkInstaller::InstallWithProtoAsync( browser_context_, std::move(serialized_proto), short_name, - webapps::ShortcutInfo::SOURCE_CHROME_SERVICE, primary_icon, manifest_url, + webapps::ShortcutInfo::SOURCE_CHROME_SERVICE, primary_icon, + is_primary_icon_maskable, manifest_url, base::BindOnce(&WebApkInstallService::OnFinishedInstallWithProto, weak_ptr_factory_.GetWeakPtr(), manifest_id, manifest_start_url, short_name, primary_icon, @@ -136,7 +139,8 @@ WebApkInstaller::InstallWithProtoAsync( browser_context_, std::move(serialized_proto), short_name, - webapps::ShortcutInfo::SOURCE_INSTALL_RETRY, primary_icon, manifest_url, + webapps::ShortcutInfo::SOURCE_INSTALL_RETRY, primary_icon, + is_primary_icon_maskable, manifest_url, base::BindOnce(&WebApkInstallService::OnFinishedInstallWithProto, weak_ptr_factory_.GetWeakPtr(), manifest_id, manifest_start_url, short_name, primary_icon, @@ -156,6 +160,7 @@ base::WeakPtr<content::WebContents> web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, webapps::WebApkInstallResult result, std::unique_ptr<std::string> serialized_proto, bool relax_updates, @@ -163,9 +168,8 @@ install_ids_.erase(shortcut_info.manifest_id); HandleFinishInstallNotifications( shortcut_info.manifest_id, shortcut_info.url, shortcut_info.short_name, - primary_icon, shortcut_info.is_primary_icon_maskable, - shortcut_info.source, result, std::move(serialized_proto), - webapk_package_name); + primary_icon, is_primary_icon_maskable, shortcut_info.source, result, + std::move(serialized_proto), webapk_package_name); if (base::FeatureList::IsEnabled( webapps::features::kWebApkInstallFailureNotification)) { @@ -184,6 +188,7 @@ // TODO(https://crbug.com/861643): Support maskable icons here. ShortcutHelper::AddToLauncherWithSkBitmap( web_contents.get(), shortcut_info, primary_icon, + /*is_icon_maskable=*/false, webapps::InstallableStatusCode::WEBAPK_INSTALL_FAILED); } }
diff --git a/chrome/browser/android/webapk/webapk_install_service.h b/chrome/browser/android/webapk/webapk_install_service.h index 01847646..e6e85784 100644 --- a/chrome/browser/android/webapk/webapk_install_service.h +++ b/chrome/browser/android/webapk/webapk_install_service.h
@@ -76,6 +76,7 @@ void InstallAsync(content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, webapps::WebappInstallSource install_source); void RetryInstallAsync(std::unique_ptr<std::string> serialized_web_apk, @@ -107,6 +108,7 @@ void OnFinishedInstall(base::WeakPtr<content::WebContents> web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_priamry_icon_maskable, webapps::WebApkInstallResult result, std::unique_ptr<std::string> serialized_webapk, bool relax_updates,
diff --git a/chrome/browser/android/webapk/webapk_installer.cc b/chrome/browser/android/webapk/webapk_installer.cc index a69959e..69a0a78 100644 --- a/chrome/browser/android/webapk/webapk_installer.cc +++ b/chrome/browser/android/webapk/webapk_installer.cc
@@ -135,11 +135,12 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, FinishCallback finish_callback) { // The installer will delete itself when it is done. WebApkInstaller* installer = new WebApkInstaller(context); installer->InstallAsync(web_contents, shortcut_info, primary_icon, - std::move(finish_callback)); + is_primary_icon_maskable, std::move(finish_callback)); } // static @@ -149,13 +150,14 @@ const std::u16string& short_name, webapps::ShortcutInfo::Source source, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, GURL& manifest_url, FinishCallback finish_callback) { // The installer will delete itself when it is done. WebApkInstaller* installer = new WebApkInstaller(context); - installer->InstallWithProtoAsync(std::move(serialized_webapk), short_name, - source, primary_icon, manifest_url, - std::move(finish_callback)); + installer->InstallWithProtoAsync( + std::move(serialized_webapk), short_name, source, primary_icon, + is_primary_icon_maskable, manifest_url, std::move(finish_callback)); } // static @@ -173,9 +175,10 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, FinishCallback callback) { installer->InstallAsync(web_contents, shortcut_info, primary_icon, - std::move(callback)); + is_primary_icon_maskable, std::move(callback)); } // static @@ -185,11 +188,12 @@ const std::u16string& short_name, webapps::ShortcutInfo::Source source, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, GURL& manifest_url, FinishCallback callback) { - installer->InstallWithProtoAsync(std::move(serialized_webapk), short_name, - source, primary_icon, manifest_url, - std::move(callback)); + installer->InstallWithProtoAsync( + std::move(serialized_webapk), short_name, source, primary_icon, + is_primary_icon_maskable, manifest_url, std::move(callback)); } // static @@ -214,6 +218,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -225,12 +230,12 @@ base::OnceCallback<void(bool)> callback) { GetBackgroundTaskRunner()->PostTaskAndReplyWithResult( FROM_HERE, - base::BindOnce(&webapps::StoreUpdateRequestToFileInBackground, - update_request_path, shortcut_info, app_key, - primary_icon_data, splash_icon_data, package_name, version, - std::move(icon_url_to_murmur2_hash), is_manifest_stale, - is_app_identity_update_supported, - std::move(update_reasons)), + base::BindOnce( + &webapps::StoreUpdateRequestToFileInBackground, update_request_path, + shortcut_info, app_key, primary_icon_data, is_primary_icon_maskable, + splash_icon_data, package_name, version, + std::move(icon_url_to_murmur2_hash), is_manifest_stale, + is_app_identity_update_supported, std::move(update_reasons)), std::move(callback)); } @@ -308,6 +313,7 @@ void WebApkInstaller::InstallAsync(content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, FinishCallback finish_callback) { DCHECK(!install_from_webapk_service_); install_duration_timer_ = std::make_unique<base::ElapsedTimer>(); @@ -316,6 +322,7 @@ install_shortcut_info_ = std::make_unique<webapps::ShortcutInfo>(shortcut_info); install_primary_icon_ = primary_icon; + is_primary_icon_maskable_ = is_primary_icon_maskable; short_name_ = shortcut_info.short_name; finish_callback_ = std::move(finish_callback); source_ = install_shortcut_info_->source; @@ -335,6 +342,7 @@ const std::u16string& short_name, webapps::ShortcutInfo::Source source, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, GURL& manifest_url, FinishCallback finish_callback) { install_duration_timer_ = std::make_unique<base::ElapsedTimer>(); @@ -343,6 +351,7 @@ short_name_ = short_name; manifest_url_ = manifest_url; install_primary_icon_ = primary_icon; + is_primary_icon_maskable_ = is_primary_icon_maskable; source_ = source; serialized_webapk_ = std::move(serialized_webapk); finish_callback_ = std::move(finish_callback); @@ -595,7 +604,7 @@ // because in WebApk installs, we are using the icon data from |hashes|. webapps::BuildProto( *install_shortcut_info_, install_shortcut_info_->manifest_id, - std::string() /* primary_icon_data */, + std::string() /* primary_icon_data */, is_primary_icon_maskable_, std::string() /* splash_icon_data */, "" /* package_name */, "" /* version */, std::move(*hashes), false /* is_manifest_stale */, false /* is_app_identity_update_supported */,
diff --git a/chrome/browser/android/webapk/webapk_installer.h b/chrome/browser/android/webapk/webapk_installer.h index ba03e3a..919af6d2 100644 --- a/chrome/browser/android/webapk/webapk_installer.h +++ b/chrome/browser/android/webapk/webapk_installer.h
@@ -74,6 +74,7 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, FinishCallback finish_callback); // Creates a self-owned WebApkInstaller instance and talks to the Chrome @@ -88,6 +89,7 @@ const std::u16string& short_name, webapps::ShortcutInfo::Source source, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, GURL& manifest_url, FinishCallback finish_callback); @@ -105,6 +107,7 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, FinishCallback callback); // Calls the private function |InstallWithProtoAsync| for testing. @@ -115,6 +118,7 @@ const std::u16string& short_name, webapps::ShortcutInfo::Source source, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, GURL& manifest_url, FinishCallback callback); @@ -144,6 +148,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -184,6 +189,7 @@ void InstallAsync(content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, FinishCallback finish_callback); // Talks to the Chrome WebAPK server to update a WebAPK on the server and to @@ -200,6 +206,7 @@ const std::u16string& short_name, webapps::ShortcutInfo::Source source, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, GURL& manifest_url, FinishCallback finish_callback); @@ -262,6 +269,7 @@ std::unique_ptr<webapps::ShortcutInfo> install_shortcut_info_; SkBitmap install_primary_icon_; + bool is_primary_icon_maskable_; std::u16string short_name_;
diff --git a/chrome/browser/android/webapk/webapk_installer_unittest.cc b/chrome/browser/android/webapk/webapk_installer_unittest.cc index 5117dee2..b693f3f 100644 --- a/chrome/browser/android/webapk/webapk_installer_unittest.cc +++ b/chrome/browser/android/webapk/webapk_installer_unittest.cc
@@ -122,7 +122,7 @@ // WebApkInstaller owns itself. WebApkInstaller::InstallAsyncForTesting( - installer.release(), web_contents, info, SkBitmap(), + installer.release(), web_contents, info, SkBitmap(), false, base::BindOnce(&WebApkInstallerRunner::OnCompleted, base::Unretained(this))); @@ -141,7 +141,7 @@ // WebApkInstaller owns itself. WebApkInstaller::InstallWithProtoAsyncForTesting( installer.release(), std::move(serialized_webapk), short_name, source, - SkBitmap(), manifest_url, + SkBitmap(), false, manifest_url, base::BindOnce(&WebApkInstallerRunner::OnCompleted, base::Unretained(this))); @@ -193,9 +193,9 @@ base::RunLoop run_loop; quit_closure_ = run_loop.QuitClosure(); WebApkInstaller::StoreUpdateRequestToFile( - update_request_path, webapps::ShortcutInfo((GURL())), GURL(), "", "", - "", "", std::map<std::string, webapps::WebApkIconHasher::Icon>(), false, - false, {webapps::WebApkUpdateReason::PRIMARY_ICON_HASH_DIFFERS}, + update_request_path, webapps::ShortcutInfo((GURL())), GURL(), "", false, + "", "", "", std::map<std::string, webapps::WebApkIconHasher::Icon>(), + false, false, {webapps::WebApkUpdateReason::PRIMARY_ICON_HASH_DIFFERS}, base::BindOnce(&UpdateRequestStorer::OnComplete, base::Unretained(this))); run_loop.Run(); @@ -299,7 +299,7 @@ webapps::ShortcutInfo info(GURL::EmptyGURL()); return webapps::BuildProtoInBackground( - info, info.manifest_id, primary_icon_data, splash_icon_data, + info, info.manifest_id, primary_icon_data, false, splash_icon_data, /*package_name*/ "", /*version*/ "", std::move(icon_url_to_murmur2_hash), true /* is_manifest_stale */, true /* is_app_identity_update_supported */,
diff --git a/chrome/browser/android/webapk/webapk_update_manager.cc b/chrome/browser/android/webapk/webapk_update_manager.cc index 430b532..85a4711 100644 --- a/chrome/browser/android/webapk/webapk_update_manager.cc +++ b/chrome/browser/android/webapk/webapk_update_manager.cc
@@ -113,7 +113,6 @@ info.background_color = ui::JavaColorToOptionalSkColor(java_background_color); info.best_primary_icon_url = GURL(ConvertJavaStringToUTF8(env, java_primary_icon_url)); - info.is_primary_icon_maskable = java_is_primary_icon_maskable; info.splash_image_url = GURL(ConvertJavaStringToUTF8(env, java_splash_icon_url)); info.is_splash_image_maskable = java_is_splash_icon_maskable; @@ -224,7 +223,7 @@ WebApkInstaller::StoreUpdateRequestToFile( base::FilePath(update_request_path), info, app_key, primary_icon_data, - splash_icon_data, webapk_package, + java_is_primary_icon_maskable, splash_icon_data, webapk_package, base::NumberToString(java_webapk_version), std::move(icon_url_to_murmur2_hash), java_is_manifest_stale, java_is_app_identity_update_supported, std::move(update_reasons),
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 3234109..d965ac5f 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -1041,9 +1041,8 @@ download_core_service->HasCreatedDownloadManager() ? profile->GetDownloadManager() : nullptr; - if (download_manager && - download_manager->NonMaliciousInProgressCount() > 0) { - int downloadCount = download_manager->NonMaliciousInProgressCount(); + if (download_manager && download_manager->BlockingShutdownCount() > 0) { + int downloadCount = download_manager->BlockingShutdownCount(); if ([self userWillWaitForInProgressDownloads:downloadCount]) { // Create a new browser window (if necessary) and navigate to the // downloads page if the user chooses to wait.
diff --git a/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc b/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc index fe10cb0c..3766658 100644 --- a/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc +++ b/chrome/browser/ash/arc/fileapi/arc_select_files_handler.cc
@@ -414,7 +414,7 @@ owner.window = owner_window; owner.android_task_id = task_id; owner.dialog_caller = - policy::DlpFileDestination(policy::DlpRulesManager::Component::kArc); + policy::DlpFileDestination(data_controls::Component::kArc); select_file_dialog_->SelectFileWithFileManagerParams( type, /*title=*/std::u16string(), default_path, file_types,
diff --git a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc index df983d4..4f87a17 100644 --- a/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc +++ b/chrome/browser/ash/dbus/dlp_files_policy_service_provider.cc
@@ -43,25 +43,25 @@ } } -// Maps |component| to DlpRulesManager::Component. -policy::DlpRulesManager::Component MapProtoToPolicyComponent( +// Maps |component| to data_controls::Component. +data_controls::Component MapProtoToPolicyComponent( ::dlp::DlpComponent component) { switch (component) { case ::dlp::DlpComponent::ARC: - return policy::DlpRulesManager::Component::kArc; + return data_controls::Component::kArc; case ::dlp::DlpComponent::CROSTINI: - return policy::DlpRulesManager::Component::kCrostini; + return data_controls::Component::kCrostini; case ::dlp::DlpComponent::PLUGIN_VM: - return policy::DlpRulesManager::Component::kPluginVm; + return data_controls::Component::kPluginVm; case ::dlp::DlpComponent::USB: - return policy::DlpRulesManager::Component::kUsb; + return data_controls::Component::kUsb; case ::dlp::DlpComponent::GOOGLE_DRIVE: - return policy::DlpRulesManager::Component::kDrive; + return data_controls::Component::kDrive; case ::dlp::DlpComponent::MICROSOFT_ONEDRIVE: // TODO(b/280575394): Handle // OneDrive properly. case ::dlp::DlpComponent::UNKNOWN_COMPONENT: case ::dlp::DlpComponent::SYSTEM: - return policy::DlpRulesManager::Component::kUnknownComponent; + return data_controls::Component::kUnknownComponent; } }
diff --git a/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc b/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc index c7cd369..60c1160 100644 --- a/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc +++ b/chrome/browser/ash/dbus/vm/vm_applications_service_provider.cc
@@ -239,8 +239,8 @@ ui::EndpointType source = ui::EndpointType::kUnknownVm; if (request.vm_name() == crostini::kCrostiniDefaultVmName) { source = ui::EndpointType::kCrostini; - owner.dialog_caller = policy::DlpFileDestination( - policy::DlpRulesManager::Component::kCrostini); + owner.dialog_caller = + policy::DlpFileDestination(data_controls::Component::kCrostini); } std::vector<base::FilePath> paths = TranslateVMPathsToHost(source, file_infos);
diff --git a/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc b/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc index 8932047..41c8724 100644 --- a/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc +++ b/chrome/browser/ash/extensions/file_manager/file_manager_private_apitest.cc
@@ -914,15 +914,15 @@ "https://internal.com"); policy::DlpRulesManager::AggregatedComponents components; components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kArc); + data_controls::Component::kArc); components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kCrostini); + data_controls::Component::kCrostini); components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kPluginVm); + data_controls::Component::kPluginVm); components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kUsb); + data_controls::Component::kUsb); components[policy::DlpRulesManager::Level::kAllow].insert( - policy::DlpRulesManager::Component::kDrive); + data_controls::Component::kDrive); EXPECT_CALL(*mock_rules_manager_, GetAggregatedDestinations) .WillOnce(testing::Return(destinations)); EXPECT_CALL(*mock_rules_manager_, GetAggregatedComponents) @@ -943,15 +943,15 @@ policy::DlpRulesManager::AggregatedComponents components; components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kArc); + data_controls::Component::kArc); components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kCrostini); + data_controls::Component::kCrostini); components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kPluginVm); + data_controls::Component::kPluginVm); components[policy::DlpRulesManager::Level::kBlock].insert( - policy::DlpRulesManager::Component::kUsb); + data_controls::Component::kUsb); components[policy::DlpRulesManager::Level::kAllow].insert( - policy::DlpRulesManager::Component::kDrive); + data_controls::Component::kDrive); EXPECT_CALL(*mock_rules_manager_, GetAggregatedComponents) .WillOnce(testing::Return(components));
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc b/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc index 2a305d8..58cc3291 100644 --- a/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc +++ b/chrome/browser/ash/extensions/file_manager/private_api_file_system.cc
@@ -256,10 +256,9 @@ } extensions::api::file_manager_private::VolumeType -DlpRulesManagerComponentToApiEnum( - policy::DlpRulesManager::Component component) { +DlpRulesManagerComponentToApiEnum(data_controls::Component component) { using ::extensions::api::file_manager_private::VolumeType; - using Component = ::policy::DlpRulesManager::Component; + using Component = ::data_controls::Component; switch (component) { case Component::kArc: return VolumeType::VOLUME_TYPE_ANDROID_FILES; @@ -1124,7 +1123,7 @@ const absl::optional<Params> params = Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - const std::vector<policy::DlpRulesManager::Component> components = + const std::vector<data_controls::Component> components = files_controller->GetBlockedComponents(params->source_url); using extensions::api::file_manager_private::VolumeType;
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest.cc b/chrome/browser/ash/file_manager/file_manager_browsertest.cc index 61fd427..8d904a6 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest.cc
@@ -558,8 +558,7 @@ auto* component_str = value.FindString("component"); EXPECT_TRUE(component_str); auto component = MapToPolicyComponent(*component_str); - EXPECT_NE(policy::DlpRulesManager::Component::kUnknownComponent, - component); + EXPECT_NE(data_controls::Component::kUnknownComponent, component); policy::DlpRulesManager::AggregatedComponents components; components[policy::DlpRulesManager::Level::kBlock].insert(component); EXPECT_CALL(*mock_rules_manager_, GetAggregatedComponents) @@ -631,25 +630,24 @@ return dlp_rules_manager; } - // Maps |component| to DlpRulesManager::Component. - policy::DlpRulesManager::Component MapToPolicyComponent( - const std::string& component) { + // Maps |component| to data_controls::Component. + data_controls::Component MapToPolicyComponent(const std::string& component) { if (component == "arc") { - return policy::DlpRulesManager::Component::kArc; + return data_controls::Component::kArc; } if (component == "crostini") { - return policy::DlpRulesManager::Component::kCrostini; + return data_controls::Component::kCrostini; } if (component == "pluginVm") { - return policy::DlpRulesManager::Component::kPluginVm; + return data_controls::Component::kPluginVm; } if (component == "usb") { - return policy::DlpRulesManager::Component::kUsb; + return data_controls::Component::kUsb; } if (component == "drive") { - return policy::DlpRulesManager::Component::kDrive; + return data_controls::Component::kDrive; } - return policy::DlpRulesManager::Component::kUnknownComponent; + return data_controls::Component::kUnknownComponent; } // Returns the inode value for |path|, if found.
diff --git a/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc b/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc index 52ccb2cb..40b32648 100644 --- a/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc +++ b/chrome/browser/ash/policy/dlp/data_transfer_dlp_controller_ash_browsertest.cc
@@ -269,7 +269,7 @@ ASSERT_EQ(events.size(), 1u); EXPECT_THAT(events[0], IsDlpPolicyEvent(CreateDlpPolicyEvent( - kMailUrl, DlpRulesManager::Component::kArc, + kMailUrl, data_controls::Component::kArc, DlpRulesManager::Restriction::kClipboard, kRuleName, kRuleId, DlpRulesManager::Level::kBlock))); @@ -281,7 +281,7 @@ ASSERT_EQ(events.size(), 2u); EXPECT_THAT(events[1], IsDlpPolicyEvent(CreateDlpPolicyEvent( - kMailUrl, DlpRulesManager::Component::kCrostini, + kMailUrl, data_controls::Component::kCrostini, DlpRulesManager::Restriction::kClipboard, kRuleName, kRuleId, DlpRulesManager::Level::kBlock))); } @@ -324,7 +324,7 @@ ASSERT_EQ(events.size(), 1u); EXPECT_THAT(events[0], IsDlpPolicyEvent(CreateDlpPolicyEvent( - kMailUrl, DlpRulesManager::Component::kArc, + kMailUrl, data_controls::Component::kArc, DlpRulesManager::Restriction::kClipboard, kRuleName, kRuleId, DlpRulesManager::Level::kWarn))); @@ -336,7 +336,7 @@ ASSERT_EQ(events.size(), 2u); EXPECT_THAT(events[1], IsDlpPolicyEvent(CreateDlpPolicyEvent( - kMailUrl, DlpRulesManager::Component::kCrostini, + kMailUrl, data_controls::Component::kCrostini, DlpRulesManager::Restriction::kClipboard, kRuleName, kRuleId, DlpRulesManager::Level::kWarn))); }
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc index 2ada382..12ec16c2 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.cc
@@ -126,11 +126,11 @@ return DlpFileDestination(base::StrCat( {extensions::kExtensionScheme, "://", app_update.AppId()})); case apps::AppType::kArc: - return DlpFileDestination(DlpRulesManager::Component::kArc); + return DlpFileDestination(data_controls::Component::kArc); case apps::AppType::kCrostini: - return DlpFileDestination(DlpRulesManager::Component::kCrostini); + return DlpFileDestination(data_controls::Component::kCrostini); case apps::AppType::kPluginVm: - return DlpFileDestination(DlpRulesManager::Component::kPluginVm); + return DlpFileDestination(data_controls::Component::kPluginVm); case apps::AppType::kWeb: return DlpFileDestination(app_update.PublisherId()); case apps::AppType::kUnknown: @@ -155,38 +155,38 @@ return inodes; } -// Maps |file_path| to DlpRulesManager::Component if possible. -absl::optional<DlpRulesManager::Component> MapFilePathtoPolicyComponent( +// Maps |file_path| to data_controls::Component if possible. +absl::optional<data_controls::Component> MapFilePathtoPolicyComponent( Profile* profile, const base::FilePath file_path) { if (base::FilePath(file_manager::util::GetAndroidFilesPath()) .IsParent(file_path)) { - return DlpRulesManager::Component::kArc; + return data_controls::Component::kArc; } if (base::FilePath(file_manager::util::kRemovableMediaPath) .IsParent(file_path)) { - return DlpRulesManager::Component::kUsb; + return data_controls::Component::kUsb; } drive::DriveIntegrationService* integration_service = drive::DriveIntegrationServiceFactory::FindForProfile(profile); if (integration_service && integration_service->is_enabled() && integration_service->GetMountPointPath().IsParent(file_path)) { - return DlpRulesManager::Component::kDrive; + return data_controls::Component::kDrive; } base::FilePath linux_files = file_manager::util::GetCrostiniMountDirectory(profile); if (linux_files == file_path || linux_files.IsParent(file_path)) { - return DlpRulesManager::Component::kCrostini; + return data_controls::Component::kCrostini; } return {}; } // Gets the component out of |destination| if possible. -absl::optional<DlpRulesManager::Component> MaybeGetComponent( +absl::optional<data_controls::Component> MaybeGetComponent( Profile* profile, const DlpFileDestination& destination) { if (destination.component().has_value()) { @@ -199,19 +199,19 @@ // Maps |component| to ::dlp::DlpComponent. ::dlp::DlpComponent MapPolicyComponentToProto( - DlpRulesManager::Component component) { + data_controls::Component component) { switch (component) { - case DlpRulesManager::Component::kUnknownComponent: + case data_controls::Component::kUnknownComponent: return ::dlp::DlpComponent::UNKNOWN_COMPONENT; - case DlpRulesManager::Component::kArc: + case data_controls::Component::kArc: return ::dlp::DlpComponent::ARC; - case DlpRulesManager::Component::kCrostini: + case data_controls::Component::kCrostini: return ::dlp::DlpComponent::CROSTINI; - case DlpRulesManager::Component::kPluginVm: + case data_controls::Component::kPluginVm: return ::dlp::DlpComponent::PLUGIN_VM; - case DlpRulesManager::Component::kUsb: + case data_controls::Component::kUsb: return ::dlp::DlpComponent::USB; - case DlpRulesManager::Component::kDrive: + case data_controls::Component::kDrive: return ::dlp::DlpComponent::GOOGLE_DRIVE; } } @@ -426,19 +426,19 @@ } ::dlp::DlpComponent MapPolicyToProtoComponent( - DlpRulesManager::Component component) { + data_controls::Component component) { switch (component) { - case DlpRulesManager::Component::kUnknownComponent: + case data_controls::Component::kUnknownComponent: return ::dlp::DlpComponent::UNKNOWN_COMPONENT; - case DlpRulesManager::Component::kArc: + case data_controls::Component::kArc: return ::dlp::DlpComponent::ARC; - case DlpRulesManager::Component::kCrostini: + case data_controls::Component::kCrostini: return ::dlp::DlpComponent::CROSTINI; - case DlpRulesManager::Component::kPluginVm: + case data_controls::Component::kPluginVm: return ::dlp::DlpComponent::PLUGIN_VM; - case DlpRulesManager::Component::kUsb: + case data_controls::Component::kUsb: return ::dlp::DlpComponent::USB; - case DlpRulesManager::Component::kDrive: + case data_controls::Component::kDrive: return ::dlp::DlpComponent::GOOGLE_DRIVE; } } @@ -523,20 +523,20 @@ return DlpFileDestination(endpoint->GetURL()->spec()); case ui::EndpointType::kArc: - return DlpFileDestination(DlpRulesManager::Component::kArc); + return DlpFileDestination(data_controls::Component::kArc); case ui::EndpointType::kCrostini: - return DlpFileDestination(DlpRulesManager::Component::kCrostini); + return DlpFileDestination(data_controls::Component::kCrostini); case ui::EndpointType::kPluginVm: - return DlpFileDestination(DlpRulesManager::Component::kPluginVm); + return DlpFileDestination(data_controls::Component::kPluginVm); case ui::EndpointType::kLacros: case ui::EndpointType::kDefault: case ui::EndpointType::kClipboardHistory: case ui::EndpointType::kBorealis: case ui::EndpointType::kUnknownVm: - return DlpFileDestination(DlpRulesManager::Component::kUnknownComponent); + return DlpFileDestination(data_controls::Component::kUnknownComponent); } } @@ -645,13 +645,13 @@ } Profile* profile = ProfileManager::GetPrimaryUserProfile(); - absl::optional<DlpRulesManager::Component> dst_component = + absl::optional<data_controls::Component> dst_component = MapFilePathtoPolicyComponent(profile, destination.path()); - absl::optional<DlpRulesManager::Component> src_component = + absl::optional<data_controls::Component> src_component = MapFilePathtoPolicyComponent(profile, source_file.path()); ::dlp::DlpComponent component_proto; if (!src_component.has_value()) { - src_component = DlpRulesManager::Component::kUnknownComponent; + src_component = data_controls::Component::kUnknownComponent; } if (dst_component.has_value()) { component_proto = MapPolicyToProtoComponent(dst_component.value()); @@ -662,7 +662,7 @@ } // Copy from external is not limited by DLP. - if (src_component != DlpRulesManager::Component::kUnknownComponent) { + if (src_component != data_controls::Component::kUnknownComponent) { std::move(result_callback) .Run(std::make_unique<file_access::ScopedFileAccess>( file_access::ScopedFileAccess::Allowed())); @@ -921,7 +921,7 @@ IsFilesTransferRestrictedCallback result_callback) { auto* profile = ProfileManager::GetPrimaryUserProfile(); DCHECK(profile); - absl::optional<DlpRulesManager::Component> dst_component = + absl::optional<data_controls::Component> dst_component = MaybeGetComponent(profile, destination); DlpFileDestination actual_dst = destination; @@ -1055,14 +1055,14 @@ return result; } -std::vector<DlpRulesManager::Component> +std::vector<data_controls::Component> DlpFilesControllerAsh::GetBlockedComponents(const std::string& source_url) { const GURL source(source_url); const DlpRulesManager::AggregatedComponents aggregated_components = rules_manager_->GetAggregatedComponents( source, DlpRulesManager::Restriction::kFiles); - std::vector<DlpRulesManager::Component> result; + std::vector<data_controls::Component> result; const auto it = aggregated_components.find(DlpRulesManager::Level::kBlock); if (it != aggregated_components.end()) { base::ranges::move(it->second.begin(), it->second.end(), @@ -1096,7 +1096,7 @@ MaybeReportEvent( file.inode, file.path, src_pattern, - DlpFileDestination(DlpRulesManager::Component::kUnknownComponent), + DlpFileDestination(data_controls::Component::kUnknownComponent), absl::nullopt, rule_metadata, level); return restricted; @@ -1275,7 +1275,7 @@ if (level == DlpRulesManager::Level::kBlock && destination.has_value()) { auto* profile = ProfileManager::GetPrimaryUserProfile(); DCHECK(profile); - absl::optional<DlpRulesManager::Component> dst_component = + absl::optional<data_controls::Component> dst_component = MaybeGetComponent(profile, destination.value()); if (dst_component.has_value()) { DlpRulesManager::Level dst_level =
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h index 15f43829..b2d48e7d1 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash.h
@@ -87,7 +87,7 @@ // List of URLs for which the restriction is enforced. std::vector<std::string> urls; // List of components for which the restriction is enforced. - std::vector<DlpRulesManager::Component> components; + std::vector<data_controls::Component> components; }; // FileDaemonInfo represents file info used for communication with the DLP @@ -202,7 +202,7 @@ // Returns a list of components to which the transfer of a file with // `source_url` is blocked. - std::vector<DlpRulesManager::Component> GetBlockedComponents( + std::vector<data_controls::Component> GetBlockedComponents( const std::string& source_url); // Returns whether a dlp policy matches for the `file`.
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc index 53bdf6f..4dad80a8 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_browsertest.cc
@@ -189,7 +189,7 @@ EXPECT_CALL(*mock_rules_manager_, GetReportingManager); EXPECT_CALL(*mock_rules_manager_, IsRestrictedComponent( - GURL(kExampleUrl), DlpRulesManager::Component::kDrive, + GURL(kExampleUrl), data_controls::Component::kDrive, DlpRulesManager::Restriction::kFiles, testing::_, testing::_)) .WillOnce(testing::Return(DlpRulesManager::Level::kWarn)); @@ -198,7 +198,7 @@ kExampleUrl); EXPECT_EQ(files_controller_->GetWarnDialogForTesting(), nullptr); files_controller_->IsFilesTransferRestricted( - transferred_files, DlpFileDestination(DlpRulesManager::Component::kDrive), + transferred_files, DlpFileDestination(data_controls::Component::kDrive), DlpFilesControllerAsh::FileAction::kMove, base::DoNothing()); EXPECT_NE(files_controller_->GetWarnDialogForTesting(), nullptr); } @@ -231,7 +231,7 @@ EXPECT_CALL(*mock_rules_manager_, GetReportingManager); EXPECT_CALL(*mock_rules_manager_, IsRestrictedComponent( - GURL(kExampleUrl), DlpRulesManager::Component::kDrive, + GURL(kExampleUrl), data_controls::Component::kDrive, DlpRulesManager::Restriction::kFiles, testing::_, testing::_)) .WillOnce(testing::Return(DlpRulesManager::Level::kWarn)); @@ -240,7 +240,7 @@ kExampleUrl); EXPECT_EQ(files_controller_->GetWarnDialogForTesting(), nullptr); files_controller_->IsFilesTransferRestricted( - transferred_files, DlpFileDestination(DlpRulesManager::Component::kDrive), + transferred_files, DlpFileDestination(data_controls::Component::kDrive), DlpFilesControllerAsh::FileAction::kDownload, base::DoNothing()); EXPECT_NE(files_controller_->GetWarnDialogForTesting(), nullptr); }
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc index a030d9b9..d2b620d 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_ash_unittest.cc
@@ -911,7 +911,7 @@ future; ASSERT_TRUE(files_controller_); files_controller_->GetDlpMetadata( - files_to_check, DlpFileDestination(DlpRulesManager::Component::kUsb), + files_to_check, DlpFileDestination(data_controls::Component::kUsb), future.GetCallback()); EXPECT_TRUE(future.Wait()); EXPECT_EQ(dlp_metadata, future.Take()); @@ -994,9 +994,9 @@ DlpRulesManager::AggregatedComponents components; components[DlpRulesManager::Level::kBlock].insert( - DlpRulesManager::Component::kUsb); + data_controls::Component::kUsb); components[DlpRulesManager::Level::kWarn].insert( - DlpRulesManager::Component::kDrive); + data_controls::Component::kDrive); EXPECT_CALL(*rules_manager_, GetAggregatedDestinations) .WillOnce(testing::Return(destinations)); @@ -1008,10 +1008,10 @@ ASSERT_EQ(result.size(), 3u); std::vector<std::string> expected_urls; - std::vector<DlpRulesManager::Component> expected_components; + std::vector<data_controls::Component> expected_components; // Block: expected_urls.push_back(kExampleUrl2); - expected_components.push_back(DlpRulesManager::Component::kUsb); + expected_components.push_back(data_controls::Component::kUsb); EXPECT_EQ(result[0].level, DlpRulesManager::Level::kBlock); EXPECT_EQ(result[0].urls, expected_urls); EXPECT_EQ(result[0].components, expected_components); @@ -1025,7 +1025,7 @@ // Warn: expected_urls.clear(); expected_components.clear(); - expected_components.push_back(DlpRulesManager::Component::kDrive); + expected_components.push_back(data_controls::Component::kDrive); EXPECT_EQ(result[2].level, DlpRulesManager::Level::kWarn); EXPECT_EQ(result[2].urls, expected_urls); EXPECT_EQ(result[2].components, expected_components); @@ -1035,7 +1035,7 @@ DlpRulesManager::AggregatedDestinations destinations; DlpRulesManager::AggregatedComponents components; components[DlpRulesManager::Level::kBlock].insert( - DlpRulesManager::Component::kUsb); + data_controls::Component::kUsb); EXPECT_CALL(*rules_manager_, GetAggregatedDestinations) .WillOnce(testing::Return(destinations)); @@ -1046,8 +1046,8 @@ auto result = files_controller_->GetDlpRestrictionDetails(kExampleUrl1); ASSERT_EQ(result.size(), 1u); std::vector<std::string> expected_urls; - std::vector<DlpRulesManager::Component> expected_components; - expected_components.push_back(DlpRulesManager::Component::kUsb); + std::vector<data_controls::Component> expected_components; + expected_components.push_back(data_controls::Component::kUsb); EXPECT_EQ(result[0].level, DlpRulesManager::Level::kBlock); EXPECT_EQ(result[0].urls, expected_urls); EXPECT_EQ(result[0].components, expected_components); @@ -1056,13 +1056,13 @@ TEST_F(DlpFilesControllerAshTest, GetBlockedComponents) { DlpRulesManager::AggregatedComponents components; components[DlpRulesManager::Level::kBlock].insert( - DlpRulesManager::Component::kArc); + data_controls::Component::kArc); components[DlpRulesManager::Level::kBlock].insert( - DlpRulesManager::Component::kCrostini); + data_controls::Component::kCrostini); components[DlpRulesManager::Level::kWarn].insert( - DlpRulesManager::Component::kUsb); + data_controls::Component::kUsb); components[DlpRulesManager::Level::kReport].insert( - DlpRulesManager::Component::kDrive); + data_controls::Component::kDrive); EXPECT_CALL(*rules_manager_, GetAggregatedComponents) .WillOnce(testing::Return(components)); @@ -1070,9 +1070,9 @@ ASSERT_TRUE(files_controller_); auto result = files_controller_->GetBlockedComponents(kExampleUrl1); ASSERT_EQ(result.size(), 2u); - std::vector<DlpRulesManager::Component> expected_components; - expected_components.push_back(DlpRulesManager::Component::kArc); - expected_components.push_back(DlpRulesManager::Component::kCrostini); + std::vector<data_controls::Component> expected_components; + expected_components.push_back(data_controls::Component::kArc); + expected_components.push_back(data_controls::Component::kCrostini); EXPECT_EQ(result, expected_components); } @@ -1156,7 +1156,7 @@ src_pattern, rule_name, rule_id, DlpRulesManager::Restriction::kFiles, level); event_builder->SetDestinationComponent( - DlpRulesManager::Component::kUnknownComponent); + data_controls::Component::kUnknownComponent); event_builder->SetContentName(filename); return event_builder->Create(); }; @@ -1262,9 +1262,8 @@ testing::SetArgPointee<5>(kRuleMetadata2), testing::Return(DlpRulesManager::Level::kAllow))); - EXPECT_CALL( - *rules_manager_, - IsRestrictedComponent(_, DlpRulesManager::Component::kUsb, _, _, _)) + EXPECT_CALL(*rules_manager_, + IsRestrictedComponent(_, data_controls::Component::kUsb, _, _, _)) .WillOnce( testing::DoAll(testing::SetArgPointee<3>(kExampleSourcePattern1), testing::SetArgPointee<4>(kRuleMetadata1), @@ -1325,7 +1324,7 @@ event_builder->SetDestinationPattern(dst_pattern); const auto event1 = event_builder->Create(); - event_builder->SetDestinationComponent(DlpRulesManager::Component::kUsb); + event_builder->SetDestinationComponent(data_controls::Component::kUsb); const auto event2 = event_builder->Create(); base::TimeDelta cooldown_time = @@ -1816,7 +1815,7 @@ class DlpFilesExternalDestinationTest : public DlpFilesTestWithMounts, public ::testing::WithParamInterface< - std::tuple<std::string, std::string, DlpRulesManager::Component>> { + std::tuple<std::string, std::string, data_controls::Component>> { public: DlpFilesExternalDestinationTest(const DlpFilesExternalDestinationTest&) = delete; @@ -1835,16 +1834,16 @@ ::testing::Values( std::make_tuple("android_files", "path/in/android/filename", - DlpRulesManager::Component::kArc), + data_controls::Component::kArc), std::make_tuple("removable", "MyUSB/path/in/removable/filename", - DlpRulesManager::Component::kUsb), + data_controls::Component::kUsb), std::make_tuple("crostini_test_termina_penguin", "path/in/crostini/filename", - DlpRulesManager::Component::kCrostini), + data_controls::Component::kCrostini), std::make_tuple("drivefs-84675c855b63e12f384d45f033826980", "root/path/in/mydrive/filename", - DlpRulesManager::Component::kDrive))); + data_controls::Component::kDrive))); TEST_P(DlpFilesExternalDestinationTest, IsFilesTransferRestricted_Component) { auto [mount_name, path, expected_component] = GetParam(); @@ -2128,9 +2127,8 @@ MockCheckIfDlpAllowedCallback cb; EXPECT_CALL(cb, Run(/*is_allowed=*/choice_result)).Times(1); - EXPECT_CALL( - *rules_manager_, - IsRestrictedComponent(_, DlpRulesManager::Component::kUsb, _, _, _)) + EXPECT_CALL(*rules_manager_, + IsRestrictedComponent(_, data_controls::Component::kUsb, _, _, _)) .WillOnce( testing::DoAll(testing::SetArgPointee<3>(kExampleSourcePattern1), testing::SetArgPointee<4>(kRuleMetadata1), @@ -2158,7 +2156,7 @@ : DlpPolicyEventBuilder::WarningProceededEvent( kExampleSourcePattern1, kRuleName1, kRuleId1, DlpRulesManager::Restriction::kFiles); - event_builder->SetDestinationComponent(DlpRulesManager::Component::kUsb); + event_builder->SetDestinationComponent(data_controls::Component::kUsb); event_builder->SetContentName(file_path.BaseName().value()); return event_builder->Create(); }; @@ -2377,9 +2375,8 @@ } } - EXPECT_CALL( - *rules_manager_, - IsRestrictedComponent(_, DlpRulesManager::Component::kUsb, _, _, _)) + EXPECT_CALL(*rules_manager_, + IsRestrictedComponent(_, data_controls::Component::kUsb, _, _, _)) .WillRepeatedly(testing::Return(DlpRulesManager::Level::kWarn)); EXPECT_CALL(*rules_manager_, GetReportingManager()) @@ -2388,7 +2385,7 @@ EXPECT_CALL(*mock_dlp_warn_notifier, ShowDlpFilesWarningDialog( base::test::IsNotNullCallback(), expected_files, - DlpFileDestination(DlpRulesManager::Component::kUsb), + DlpFileDestination(data_controls::Component::kUsb), transfer_info.files_action, _)) .WillOnce([](OnDlpRestrictionCheckedCallback callback, const std::vector<DlpConfidentialFile>& confidential_files,
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc b/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc index f5de9ab..06f6d3e 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_event_storage.cc
@@ -50,7 +50,7 @@ // `events_`. return (dst.component().has_value() && dst.component().value() != - DlpRulesManager::Component::kUnknownComponent) || + data_controls::Component::kUnknownComponent) || dst.url_or_path().has_value(); }
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc index 2f97493..88f3d038 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_event_storage_unittest.cc
@@ -68,7 +68,7 @@ storage.SetTaskRunnerForTesting(task_runner); const auto dst1 = DlpFileDestination(kExampleUrl1); - const auto dst2 = DlpFileDestination(DlpRulesManager::Component::kDrive); + const auto dst2 = DlpFileDestination(data_controls::Component::kDrive); // Insertion ASSERT_TRUE(storage.StoreEventAndCheckIfItShouldBeReported(kInode1, dst1));
diff --git a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc index a807c69..a70191b 100644 --- a/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc +++ b/chrome/browser/ash/system_web_apps/system_web_app_manager_browsertest.cc
@@ -1425,7 +1425,9 @@ .GetAppIdForSystemApp(SystemWebAppType::SHORTCUT_CUSTOMIZATION) .value(); Browser* browser; - EXPECT_TRUE(LaunchApp(SystemWebAppType::SHORTCUT_CUSTOMIZATION, &browser)); + content::WebContents* web_contents = + LaunchApp(SystemWebAppType::SHORTCUT_CUSTOMIZATION, &browser); + EXPECT_TRUE(web_contents); std::unique_ptr<ui::SimpleMenuModel> menu_model; { @@ -1459,9 +1461,7 @@ check_shortcut(menu_model->GetItemCount() - 1, 1, u"Two"); const int command_id = LAUNCH_APP_SHORTCUT_FIRST + 1; - ui_test_utils::UrlLoadObserver url_observer( - GURL("chrome://test-system-app/pwa.html#two"), - content::NotificationService::AllSources()); + content::LoadStopObserver url_observer(web_contents); menu_model->ActivatedAt(menu_model->GetIndexOfCommandId(command_id).value(), ui::EF_LEFT_MOUSE_BUTTON); url_observer.Wait();
diff --git a/chrome/browser/bookmarks/bookmark_model_factory.cc b/chrome/browser/bookmarks/bookmark_model_factory.cc index e63ebfca..42556eb 100644 --- a/chrome/browser/bookmarks/bookmark_model_factory.cc +++ b/chrome/browser/bookmarks/bookmark_model_factory.cc
@@ -41,7 +41,8 @@ auto bookmark_model = std::make_unique<BookmarkModel>(std::make_unique<ChromeBookmarkClient>( profile, ManagedBookmarkServiceFactory::GetForProfile(profile), - BookmarkSyncServiceFactory::GetForProfile(profile))); + BookmarkSyncServiceFactory::GetForProfile(profile), + BookmarkUndoServiceFactory::GetForProfile(profile))); #if defined(TOOLKIT_VIEWS) // BookmarkExpandedStateTracker depends on the loading event, so this // coupling must happen before the loading happens.
diff --git a/chrome/browser/bookmarks/chrome_bookmark_client.cc b/chrome/browser/bookmarks/chrome_bookmark_client.cc index 9dcb44c..56fd8bd 100644 --- a/chrome/browser/bookmarks/chrome_bookmark_client.cc +++ b/chrome/browser/bookmarks/chrome_bookmark_client.cc
@@ -21,6 +21,7 @@ #include "components/history/core/browser/url_database.h" #include "components/offline_pages/buildflags/buildflags.h" #include "components/sync_bookmarks/bookmark_sync_service.h" +#include "components/undo/bookmark_undo_service.h" #if BUILDFLAG(ENABLE_OFFLINE_PAGES) #include "chrome/browser/offline_pages/offline_page_bookmark_observer.h" @@ -29,10 +30,12 @@ ChromeBookmarkClient::ChromeBookmarkClient( Profile* profile, bookmarks::ManagedBookmarkService* managed_bookmark_service, - sync_bookmarks::BookmarkSyncService* bookmark_sync_service) + sync_bookmarks::BookmarkSyncService* bookmark_sync_service, + BookmarkUndoService* bookmark_undo_service) : profile_(profile), managed_bookmark_service_(managed_bookmark_service), - bookmark_sync_service_(bookmark_sync_service) {} + bookmark_sync_service_(bookmark_sync_service), + bookmark_undo_service_(bookmark_undo_service) {} ChromeBookmarkClient::~ChromeBookmarkClient() = default; @@ -148,3 +151,13 @@ bookmark_sync_service_->DecodeBookmarkSyncMetadata( metadata_str, schedule_save_closure, model_); } + +void ChromeBookmarkClient::OnBookmarkNodeRemovedUndoable( + bookmarks::BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const bookmarks::BookmarkNode* parent, + size_t index, + std::unique_ptr<bookmarks::BookmarkNode> node) { + bookmark_undo_service_->AddUndoEntryForRemovedNode( + model, undo_provider, parent, index, std::move(node)); +}
diff --git a/chrome/browser/bookmarks/chrome_bookmark_client.h b/chrome/browser/bookmarks/chrome_bookmark_client.h index eda56cf1..1d7b97a8 100644 --- a/chrome/browser/bookmarks/chrome_bookmark_client.h +++ b/chrome/browser/bookmarks/chrome_bookmark_client.h
@@ -16,6 +16,7 @@ #include "components/bookmarks/browser/bookmark_client.h" #include "components/offline_pages/buildflags/buildflags.h" +class BookmarkUndoService; class GURL; class Profile; @@ -23,16 +24,16 @@ class BookmarkModel; class BookmarkNode; class ManagedBookmarkService; -} +} // namespace bookmarks namespace sync_bookmarks { class BookmarkSyncService; -} +} // namespace sync_bookmarks #if BUILDFLAG(ENABLE_OFFLINE_PAGES) namespace offline_pages { class OfflinePageBookmarkObserver; -} +} // namespace offline_pages #endif class ChromeBookmarkClient : public bookmarks::BookmarkClient { @@ -40,7 +41,8 @@ ChromeBookmarkClient( Profile* profile, bookmarks::ManagedBookmarkService* managed_bookmark_service, - sync_bookmarks::BookmarkSyncService* bookmark_sync_service); + sync_bookmarks::BookmarkSyncService* bookmark_sync_service, + BookmarkUndoService* bookmark_undo_service); ChromeBookmarkClient(const ChromeBookmarkClient&) = delete; ChromeBookmarkClient& operator=(const ChromeBookmarkClient&) = delete; @@ -67,20 +69,29 @@ void DecodeBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) override; + void OnBookmarkNodeRemovedUndoable( + bookmarks::BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const bookmarks::BookmarkNode* parent, + size_t index, + std::unique_ptr<bookmarks::BookmarkNode> node) override; private: // Pointer to the associated Profile. Must outlive ChromeBookmarkClient. - raw_ptr<Profile> profile_; + const raw_ptr<Profile> profile_; // Pointer to the ManagedBookmarkService responsible for bookmark policy. May // be null during testing. - raw_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_; - - raw_ptr<bookmarks::BookmarkModel> model_; + const raw_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_; // Pointer to the BookmarkSyncService responsible for encoding and decoding // sync metadata persisted together with the bookmarks model. - raw_ptr<sync_bookmarks::BookmarkSyncService> bookmark_sync_service_; + const raw_ptr<sync_bookmarks::BookmarkSyncService> bookmark_sync_service_; + + // Pointer to BookmarkUndoService, responsible for making operations undoable. + const raw_ptr<BookmarkUndoService> bookmark_undo_service_; + + raw_ptr<bookmarks::BookmarkModel> model_ = nullptr; #if BUILDFLAG(ENABLE_OFFLINE_PAGES) // Owns the observer used by Offline Page listening to Bookmark Model events.
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc index 140d541..0068bfe 100644 --- a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc +++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
@@ -128,7 +128,7 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) case ui::EndpointType::kCrostini: { level = dlp_rules_manager.IsRestrictedComponent( - src_url, DlpRulesManager::Component::kCrostini, + src_url, data_controls::Component::kCrostini, DlpRulesManager::Restriction::kClipboard, src_pattern, out_rule_metadata); break; @@ -136,7 +136,7 @@ case ui::EndpointType::kPluginVm: { level = dlp_rules_manager.IsRestrictedComponent( - src_url, DlpRulesManager::Component::kPluginVm, + src_url, data_controls::Component::kPluginVm, DlpRulesManager::Restriction::kClipboard, src_pattern, out_rule_metadata); break; @@ -144,7 +144,7 @@ case ui::EndpointType::kArc: { level = dlp_rules_manager.IsRestrictedComponent( - src_url, DlpRulesManager::Component::kArc, + src_url, data_controls::Component::kArc, DlpRulesManager::Restriction::kClipboard, src_pattern, out_rule_metadata); break; @@ -539,21 +539,21 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) case ui::EndpointType::kCrostini: reporting_manager->ReportEvent( - src_pattern, DlpRulesManager::Component::kCrostini, + src_pattern, data_controls::Component::kCrostini, DlpRulesManager::Restriction::kClipboard, level, rule_metadata.name, rule_metadata.obfuscated_id); break; case ui::EndpointType::kPluginVm: reporting_manager->ReportEvent( - src_pattern, DlpRulesManager::Component::kPluginVm, + src_pattern, data_controls::Component::kPluginVm, DlpRulesManager::Restriction::kClipboard, level, rule_metadata.name, rule_metadata.obfuscated_id); break; case ui::EndpointType::kArc: reporting_manager->ReportEvent( - src_pattern, DlpRulesManager::Component::kArc, + src_pattern, data_controls::Component::kArc, DlpRulesManager::Restriction::kClipboard, level, rule_metadata.name, rule_metadata.obfuscated_id); break;
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc index 264efd15..58f8649 100644 --- a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc
@@ -117,16 +117,16 @@ } #if BUILDFLAG(IS_CHROMEOS_ASH) -DlpRulesManager::Component GetComponent(ui::EndpointType endpoint_type) { +data_controls::Component GetComponent(ui::EndpointType endpoint_type) { switch (endpoint_type) { case ui::EndpointType::kArc: - return DlpRulesManager::Component::kArc; + return data_controls::Component::kArc; case ui::EndpointType::kCrostini: - return DlpRulesManager::Component::kCrostini; + return data_controls::Component::kCrostini; case ui::EndpointType::kPluginVm: - return DlpRulesManager::Component::kPluginVm; + return data_controls::Component::kPluginVm; default: - return DlpRulesManager::Component::kUnknownComponent; + return data_controls::Component::kUnknownComponent; } } #endif // BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc b/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc index 99b2a972..de9de482 100644 --- a/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc +++ b/chrome/browser/chromeos/policy/dlp/dialogs/files_policy_dialog.cc
@@ -43,20 +43,20 @@ const std::u16string GetDestinationComponent(DlpFileDestination destination) { DCHECK(destination.component().has_value()); switch (destination.component().value()) { - case DlpRulesManager::Component::kArc: + case data_controls::Component::kArc: return l10n_util::GetStringUTF16( IDS_FILE_BROWSER_ANDROID_FILES_ROOT_LABEL); - case DlpRulesManager::Component::kCrostini: + case data_controls::Component::kCrostini: return l10n_util::GetStringUTF16(IDS_FILE_BROWSER_LINUX_FILES_ROOT_LABEL); - case DlpRulesManager::Component::kPluginVm: + case data_controls::Component::kPluginVm: return l10n_util::GetStringUTF16( IDS_FILE_BROWSER_PLUGIN_VM_DIRECTORY_LABEL); - case DlpRulesManager::Component::kUsb: + case data_controls::Component::kUsb: return l10n_util::GetStringUTF16( IDS_POLICY_DLP_FILES_DESTINATION_REMOVABLE_STORAGE); - case DlpRulesManager::Component::kDrive: + case data_controls::Component::kDrive: return l10n_util::GetStringUTF16(IDS_FILE_BROWSER_DRIVE_DIRECTORY_LABEL); - case DlpRulesManager::Component::kUnknownComponent: + case data_controls::Component::kUnknownComponent: NOTREACHED(); return u""; }
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc index 22f70da..06299a2b 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.cc
@@ -8,8 +8,7 @@ DlpFileDestination::DlpFileDestination(const std::string& url) : url_or_path_(url) {} -DlpFileDestination::DlpFileDestination( - const DlpRulesManager::Component component) +DlpFileDestination::DlpFileDestination(const data_controls::Component component) : component_(component) {} DlpFileDestination::DlpFileDestination(const DlpFileDestination&) = default; @@ -54,8 +53,7 @@ return url_or_path_; } -absl::optional<DlpRulesManager::Component> DlpFileDestination::component() - const { +absl::optional<data_controls::Component> DlpFileDestination::component() const { return component_; }
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h index a136e25..71b2ca9 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_file_destination.h
@@ -17,7 +17,7 @@ public: DlpFileDestination() = delete; explicit DlpFileDestination(const std::string& url); - explicit DlpFileDestination(const DlpRulesManager::Component component); + explicit DlpFileDestination(const data_controls::Component component); DlpFileDestination(const DlpFileDestination&); DlpFileDestination& operator=(const DlpFileDestination&); @@ -35,13 +35,13 @@ absl::optional<std::string> url_or_path() const; - absl::optional<DlpRulesManager::Component> component() const; + absl::optional<data_controls::Component> component() const; private: // Destination url or destination path. absl::optional<std::string> url_or_path_; // Destination component. - absl::optional<DlpRulesManager::Component> component_; + absl::optional<data_controls::Component> component_; }; } // namespace policy
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc index 35a4c0d..90ae5577 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.cc
@@ -184,28 +184,28 @@ } void DlpPolicyEventBuilder::SetDestinationComponent( - DlpRulesManager::Component dst_component) { + data_controls::Component dst_component) { DlpPolicyEventDestination* event_destination = new DlpPolicyEventDestination; switch (dst_component) { - case (DlpRulesManager::Component::kArc): + case (data_controls::Component::kArc): event_destination->set_component(DlpPolicyEventDestination_Component_ARC); break; - case (DlpRulesManager::Component::kCrostini): + case (data_controls::Component::kCrostini): event_destination->set_component( DlpPolicyEventDestination_Component_CROSTINI); break; - case (DlpRulesManager::Component::kPluginVm): + case (data_controls::Component::kPluginVm): event_destination->set_component( DlpPolicyEventDestination_Component_PLUGIN_VM); break; - case (DlpRulesManager::Component::kUsb): + case (data_controls::Component::kUsb): event_destination->set_component(DlpPolicyEventDestination_Component_USB); break; - case (DlpRulesManager::Component::kDrive): + case (data_controls::Component::kDrive): event_destination->set_component( DlpPolicyEventDestination_Component_DRIVE); break; - case (DlpRulesManager::Component::kUnknownComponent): + case (data_controls::Component::kUnknownComponent): event_destination->set_component( DlpPolicyEventDestination_Component_UNDEFINED_COMPONENT); break; @@ -256,7 +256,7 @@ } DlpPolicyEvent CreateDlpPolicyEvent(const std::string& src_pattern, - DlpRulesManager::Component dst_component, + data_controls::Component dst_component, DlpRulesManager::Restriction restriction, const std::string& rule_name, const std::string& rule_id, @@ -306,7 +306,7 @@ void DlpReportingManager::ReportEvent( const std::string& src_pattern, - const DlpRulesManager::Component dst_component, + const data_controls::Component dst_component, DlpRulesManager::Restriction restriction, DlpRulesManager::Level level, const std::string& rule_name,
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h index d4cc4a61..d0e87c4 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager.h
@@ -35,7 +35,7 @@ // Setters used to define event properties. void SetDestinationPattern(const std::string& dst_pattern); - void SetDestinationComponent(DlpRulesManager::Component dst_component); + void SetDestinationComponent(data_controls::Component dst_component); void SetContentName(const std::string& content_name); // Stops the creation and returns the created event. @@ -66,7 +66,7 @@ const std::string& rule_id, DlpRulesManager::Level level); DlpPolicyEvent CreateDlpPolicyEvent(const std::string& src_pattern, - DlpRulesManager::Component dst_component, + data_controls::Component dst_component, DlpRulesManager::Restriction restriction, const std::string& rule_name, const std::string& rule_id, @@ -108,7 +108,7 @@ const std::string& rule_name, const std::string& rule_id); void ReportEvent(const std::string& src_pattern, - DlpRulesManager::Component dst_component, + data_controls::Component dst_component, DlpRulesManager::Restriction restriction, DlpRulesManager::Level level, const std::string& rule_name,
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc index d821870..cf6db22 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_reporting_manager_unittest.cc
@@ -56,7 +56,7 @@ protected: void ReportEventAndCheckComponent( - DlpRulesManager::Component rule_component, + data_controls::Component rule_component, DlpPolicyEventDestination_Component event_component, unsigned int event_number) { manager_.ReportEvent(kCompanyPattern, rule_component, @@ -150,20 +150,20 @@ } TEST_F(DlpReportingManagerTest, ReportEventWithComponentDst) { - ReportEventAndCheckComponent(DlpRulesManager::Component::kArc, + ReportEventAndCheckComponent(data_controls::Component::kArc, DlpPolicyEventDestination_Component_ARC, 0u); - ReportEventAndCheckComponent(DlpRulesManager::Component::kCrostini, + ReportEventAndCheckComponent(data_controls::Component::kCrostini, DlpPolicyEventDestination_Component_CROSTINI, 1u); - ReportEventAndCheckComponent(DlpRulesManager::Component::kPluginVm, + ReportEventAndCheckComponent(data_controls::Component::kPluginVm, DlpPolicyEventDestination_Component_PLUGIN_VM, 2u); - ReportEventAndCheckComponent(DlpRulesManager::Component::kUsb, + ReportEventAndCheckComponent(data_controls::Component::kUsb, DlpPolicyEventDestination_Component_USB, 3u); - ReportEventAndCheckComponent(DlpRulesManager::Component::kDrive, + ReportEventAndCheckComponent(data_controls::Component::kDrive, DlpPolicyEventDestination_Component_DRIVE, 4u); ReportEventAndCheckComponent( - DlpRulesManager::Component::kUnknownComponent, + data_controls::Component::kUnknownComponent, DlpPolicyEventDestination_Component_UNDEFINED_COMPONENT, 5u); EXPECT_EQ(manager_.events_reported(), 6u); }
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h index 943e47a..92e5526 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h
@@ -10,6 +10,7 @@ #include <string> #include "build/chromeos_buildflags.h" +#include "chrome/browser/enterprise/data_controls/component.h" #include "chrome/browser/enterprise/data_controls/dlp_rules_manager_base.h" #include "url/gurl.h" @@ -23,24 +24,12 @@ // can be queried anytime about the restrictions set by the policy. class DlpRulesManager : public policy::DlpRulesManagerBase { public: - // A representation of destinations to which sharing confidential data is - // restricted by DataLeakPreventionRulesList policy. - // When adding new values, make sure to update the `components` below as well. - enum class Component { - kUnknownComponent, - kArc, // ARC++ as a Guest OS. - kCrostini, // Crostini as a Guest OS. - kPluginVm, // Plugin VM (Parallels/Windows) as a Guest OS. - kUsb, // Removable disk. - kDrive, // Google drive for file storage. - kMaxValue = kDrive - }; - // List of all possible component values, used to simplify iterating over all // the options. - constexpr static const std::array<Component, 5> components = { - Component::kArc, Component::kCrostini, Component::kPluginVm, - Component::kUsb, Component::kDrive}; + constexpr static const std::array<data_controls::Component, 5> components = { + data_controls::Component::kArc, data_controls::Component::kCrostini, + data_controls::Component::kPluginVm, data_controls::Component::kUsb, + data_controls::Component::kDrive}; // Represents file metadata. struct FileMetadata { @@ -58,7 +47,8 @@ // Mapping from a level to the set of components for which that level is // enforced. - using AggregatedComponents = std::map<Level, std::set<Component>>; + using AggregatedComponents = + std::map<Level, std::set<data_controls::Component>>; ~DlpRulesManager() override = default; @@ -71,7 +61,7 @@ // matched rule metadata. virtual Level IsRestrictedComponent( const GURL& source, - const Component& destination, + const data_controls::Component& destination, Restriction restriction, std::string* out_source_pattern, RuleMetadata* out_rule_metadata) const = 0;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc index c15e55b..ef9dad0 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.cc
@@ -95,18 +95,18 @@ : it->second; } -DlpRulesManager::Component GetComponentMapping(const std::string& component) { +data_controls::Component GetComponentMapping(const std::string& component) { static constexpr auto kComponentsMap = - base::MakeFixedFlatMap<base::StringPiece, DlpRulesManager::Component>( - {{dlp::kArc, DlpRulesManager::Component::kArc}, - {dlp::kCrostini, DlpRulesManager::Component::kCrostini}, - {dlp::kPluginVm, DlpRulesManager::Component::kPluginVm}, - {dlp::kDrive, DlpRulesManager::Component::kDrive}, - {dlp::kUsb, DlpRulesManager::Component::kUsb}}); + base::MakeFixedFlatMap<base::StringPiece, data_controls::Component>( + {{dlp::kArc, data_controls::Component::kArc}, + {dlp::kCrostini, data_controls::Component::kCrostini}, + {dlp::kPluginVm, data_controls::Component::kPluginVm}, + {dlp::kDrive, data_controls::Component::kDrive}, + {dlp::kUsb, data_controls::Component::kUsb}}); auto* it = kComponentsMap.find(component); return (it == kComponentsMap.end()) - ? DlpRulesManager::Component::kUnknownComponent + ? data_controls::Component::kUnknownComponent : it->second; } @@ -175,9 +175,9 @@ // Returns the URLs associated with the given component. An empty vector is // returned if there are none. std::vector<std::string> GetAssociatedUrlsConditions( - DlpRulesManager::Component component) { + data_controls::Component component) { switch (component) { - case DlpRulesManager::Component::kDrive: + case data_controls::Component::kDrive: return {kDrivePattern}; default: return {}; @@ -186,7 +186,7 @@ // Add URL conditions associated with the given `component`. void AddAssociatedUrlConditions( - DlpRulesManager::Component component, + data_controls::Component component, url_matcher::URLMatcher* matcher, UrlConditionId& condition_id, url_matcher::URLMatcherConditionSet::Vector& conditions, @@ -419,7 +419,7 @@ DlpRulesManager::Level DlpRulesManagerImpl::IsRestrictedComponent( const GURL& source, - const Component& destination, + const data_controls::Component& destination, Restriction restriction, std::string* out_source_pattern, RuleMetadata* out_rule_metadata) const { @@ -427,7 +427,7 @@ DCHECK(restriction == Restriction::kClipboard || restriction == Restriction::kFiles); - if (destination == Component::kUnknownComponent) { + if (destination == data_controls::Component::kUnknownComponent) { return DlpRulesManager::Level::kAllow; } @@ -540,8 +540,8 @@ DCHECK(restriction == Restriction::kClipboard || restriction == Restriction::kFiles); - std::map<Level, std::set<Component>> result; - for (Component component : components) { + std::map<Level, std::set<data_controls::Component>> result; + for (data_controls::Component component : components) { std::string out_source_pattern; Level level = IsRestrictedComponent(source, component, restriction, &out_source_pattern, nullptr); @@ -701,7 +701,7 @@ if (destinations_components) { for (const auto& component : *destinations_components) { DCHECK(component.is_string()); - DlpRulesManager::Component component_mapping = + data_controls::Component component_mapping = GetComponentMapping(component.GetString()); components_rules_[component_mapping].insert(rules_counter); AddAssociatedUrlConditions(component_mapping, dst_url_matcher_.get(),
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h index caf966c..44fa63f 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl.h
@@ -49,7 +49,7 @@ std::string* out_destination_pattern, RuleMetadata* out_rule_metadata) const override; Level IsRestrictedComponent(const GURL& source, - const Component& destination, + const data_controls::Component& destination, Restriction restriction, std::string* out_source_pattern, RuleMetadata* out_rule_metadata) const override; @@ -86,7 +86,7 @@ PrefChangeRegistrar pref_change_registrar_; // Map from the components to their configured rules IDs. - std::map<Component, std::set<RuleId>> components_rules_; + std::map<data_controls::Component, std::set<RuleId>> components_rules_; // Map from the restrictions to their configured rules IDs and levels. std::map<Restriction, std::map<RuleId, Level>> restrictions_map_;
diff --git a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc index 063951c..13a049ca 100644 --- a/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc +++ b/chrome/browser/chromeos/policy/dlp/dlp_rules_manager_impl_unittest.cc
@@ -87,7 +87,7 @@ void CheckIsRestrictedComponent( const std::string& src_url, - DlpRulesManager::Component dst_component, + data_controls::Component dst_component, DlpRulesManager::Restriction restriction, DlpRulesManager::Level expected_level, const std::string& expected_src_pattern, @@ -207,7 +207,7 @@ 1); CheckIsRestrictedComponent( - kExampleUrl, DlpRulesManager::Component::kUnknownComponent, + kExampleUrl, data_controls::Component::kUnknownComponent, DlpRulesManager::Restriction::kClipboard, DlpRulesManager::Level::kAllow, /*expected_src_pattern=*/"", DlpRulesManager::RuleMetadata(/*name=*/"", /*obfuscated_id=*/"")); @@ -322,12 +322,12 @@ UpdatePolicyPref({rule}); CheckIsRestrictedComponent( - kExampleUrl, DlpRulesManager::Component::kArc, + kExampleUrl, data_controls::Component::kArc, DlpRulesManager::Restriction::kClipboard, DlpRulesManager::Level::kBlock, kExampleUrl, DlpRulesManager::RuleMetadata(kRuleName1, kRuleId1)); CheckIsRestrictedComponent( - kExampleUrl, DlpRulesManager::Component::kCrostini, + kExampleUrl, data_controls::Component::kCrostini, DlpRulesManager::Restriction::kClipboard, DlpRulesManager::Level::kAllow, /*expected_src_pattern=*/"", DlpRulesManager::RuleMetadata(/*name=*/"", /*obfuscated_id=*/"")); @@ -348,7 +348,7 @@ UpdatePolicyPref({rule}); CheckIsRestrictedComponent( - kExampleUrl, DlpRulesManager::Component::kDrive, + kExampleUrl, data_controls::Component::kDrive, DlpRulesManager::Restriction::kFiles, DlpRulesManager::Level::kBlock, kExampleUrl, DlpRulesManager::RuleMetadata(kRuleName1, kRuleId1)); @@ -876,8 +876,7 @@ TEST_F(DlpRulesManagerImplTest, GetAggregatedComponents_NoMatch) { auto result = dlp_rules_manager_.GetAggregatedComponents( GURL(kExampleUrl), DlpRulesManager::Restriction::kClipboard); - std::map<DlpRulesManager::Level, std::set<DlpRulesManager::Component>> - expected; + std::map<DlpRulesManager::Level, std::set<data_controls::Component>> expected; for (auto component : DlpRulesManager::components) { expected[DlpRulesManager::Level::kAllow].insert(component); } @@ -908,18 +907,17 @@ auto result = dlp_rules_manager_.GetAggregatedComponents( GURL(kExampleUrl), DlpRulesManager::Restriction::kFiles); - std::map<DlpRulesManager::Level, std::set<DlpRulesManager::Component>> - expected; + std::map<DlpRulesManager::Level, std::set<data_controls::Component>> expected; expected[DlpRulesManager::Level::kBlock].insert( - DlpRulesManager::Component::kArc); + data_controls::Component::kArc); expected[DlpRulesManager::Level::kBlock].insert( - DlpRulesManager::Component::kCrostini); + data_controls::Component::kCrostini); expected[DlpRulesManager::Level::kAllow].insert( - DlpRulesManager::Component::kPluginVm); + data_controls::Component::kPluginVm); expected[DlpRulesManager::Level::kAllow].insert( - DlpRulesManager::Component::kUsb); + data_controls::Component::kUsb); expected[DlpRulesManager::Level::kAllow].insert( - DlpRulesManager::Component::kDrive); + data_controls::Component::kDrive); EXPECT_EQ(result, expected); @@ -1026,7 +1024,7 @@ DlpRulesManager::RuleMetadata(kRuleName2, kRuleId2)); CheckIsRestrictedComponent( - kExampleUrl, DlpRulesManager::Component::kCrostini, + kExampleUrl, data_controls::Component::kCrostini, DlpRulesManager::Restriction::kClipboard, DlpRulesManager::Level::kBlock, kExampleUrl, DlpRulesManager::RuleMetadata(kRuleName2, kRuleId2)); }
diff --git a/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h b/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h index fb56645..5d573cb 100644 --- a/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h +++ b/chrome/browser/chromeos/policy/dlp/mock_dlp_rules_manager.h
@@ -37,7 +37,7 @@ MOCK_CONST_METHOD5(IsRestrictedComponent, Level(const GURL& source, - const Component& destination, + const data_controls::Component& destination, Restriction restriction, std::string* out_source_pattern, RuleMetadata* out_rule_metadata));
diff --git a/chrome/browser/download/bubble/download_display_controller_unittest.cc b/chrome/browser/download/bubble/download_display_controller_unittest.cc index df01d8d..8a4af606 100644 --- a/chrome/browser/download/bubble/download_display_controller_unittest.cc +++ b/chrome/browser/download/bubble/download_display_controller_unittest.cc
@@ -219,7 +219,7 @@ GetExtensionEventRouter, ()); MOCK_METHOD(bool, HasCreatedDownloadManager, ()); - MOCK_METHOD(int, NonMaliciousDownloadCount, (), (const)); + MOCK_METHOD(int, BlockingShutdownCount, (), (const)); MOCK_METHOD(void, CancelDownloads, ()); MOCK_METHOD(void, SetDownloadManagerDelegateForTesting,
diff --git a/chrome/browser/download/download_browsertest_utils.cc b/chrome/browser/download/download_browsertest_utils.cc index 175cc6d9..e6bee9a3 100644 --- a/chrome/browser/download/download_browsertest_utils.cc +++ b/chrome/browser/download/download_browsertest_utils.cc
@@ -288,7 +288,7 @@ DownloadManager* manager = DownloadManagerForBrowser(browser()); - EXPECT_EQ(0, manager->NonMaliciousInProgressCount()); + EXPECT_EQ(0, manager->BlockingShutdownCount()); EXPECT_EQ(0, manager->InProgressCount()); if (manager->InProgressCount() != 0) { return nullptr;
diff --git a/chrome/browser/download/download_core_service.cc b/chrome/browser/download/download_core_service.cc index e8df10a3..108a52e0 100644 --- a/chrome/browser/download/download_core_service.cc +++ b/chrome/browser/download/download_core_service.cc
@@ -14,7 +14,7 @@ DownloadCoreService::~DownloadCoreService() = default; // static -int DownloadCoreService::NonMaliciousDownloadCountAllProfiles() { +int DownloadCoreService::BlockingShutdownCountAllProfiles() { std::vector<Profile*> profiles( g_browser_process->profile_manager()->GetLoadedProfiles()); @@ -24,7 +24,7 @@ // profiles, like the System Profile. if (DownloadCoreService* service = DownloadCoreServiceFactory::GetForBrowserContext(*it)) { - count += service->NonMaliciousDownloadCount(); + count += service->BlockingShutdownCount(); } std::vector<Profile*> otr_profiles = (*it)->GetAllOffTheRecordProfiles(); @@ -33,7 +33,7 @@ // profiles, like the System Profile. if (DownloadCoreService* otr_service = DownloadCoreServiceFactory::GetForBrowserContext(otr)) { - count += otr_service->NonMaliciousDownloadCount(); + count += otr_service->BlockingShutdownCount(); } } }
diff --git a/chrome/browser/download/download_core_service.h b/chrome/browser/download/download_core_service.h index 3033fa5..1579e92 100644 --- a/chrome/browser/download/download_core_service.h +++ b/chrome/browser/download/download_core_service.h
@@ -53,15 +53,15 @@ // Has a download manager been created? virtual bool HasCreatedDownloadManager() = 0; - // Number of non-malicious downloads associated with this instance of the + // Number of downloads blocking shutdown associated with this instance of the // service. - virtual int NonMaliciousDownloadCount() const = 0; + virtual int BlockingShutdownCount() const = 0; // Cancels all in-progress downloads for this profile. virtual void CancelDownloads() = 0; - // Number of non-malicious downloads associated with all profiles. - static int NonMaliciousDownloadCountAllProfiles(); + // Number of downloads blocking shutdown associated with all profiles. + static int BlockingShutdownCountAllProfiles(); // Cancels all in-progress downloads for all profiles. static void CancelAllDownloads();
diff --git a/chrome/browser/download/download_core_service_impl.cc b/chrome/browser/download/download_core_service_impl.cc index 13c02a7e..01dd185 100644 --- a/chrome/browser/download/download_core_service_impl.cc +++ b/chrome/browser/download/download_core_service_impl.cc
@@ -117,10 +117,10 @@ return download_manager_created_; } -int DownloadCoreServiceImpl::NonMaliciousDownloadCount() const { +int DownloadCoreServiceImpl::BlockingShutdownCount() const { if (!download_manager_created_) return 0; - return profile_->GetDownloadManager()->NonMaliciousInProgressCount(); + return profile_->GetDownloadManager()->BlockingShutdownCount(); } void DownloadCoreServiceImpl::CancelDownloads() {
diff --git a/chrome/browser/download/download_core_service_impl.h b/chrome/browser/download/download_core_service_impl.h index c4c9931..6d92443e 100644 --- a/chrome/browser/download/download_core_service_impl.h +++ b/chrome/browser/download/download_core_service_impl.h
@@ -48,7 +48,7 @@ extensions::ExtensionDownloadsEventRouter* GetExtensionEventRouter() override; #endif bool HasCreatedDownloadManager() override; - int NonMaliciousDownloadCount() const override; + int BlockingShutdownCount() const override; void CancelDownloads() override; void SetDownloadManagerDelegateForTesting( std::unique_ptr<ChromeDownloadManagerDelegate> delegate) override;
diff --git a/chrome/browser/download/download_item_model.cc b/chrome/browser/download/download_item_model.cc index 62eff20..f9ba968 100644 --- a/chrome/browser/download/download_item_model.cc +++ b/chrome/browser/download/download_item_model.cc
@@ -362,7 +362,7 @@ } // If you change this definition of malicious, also update -// DownloadManagerImpl::NonMaliciousInProgressCount. +// DownloadManagerImpl::BlockingShutdownCount. bool DownloadItemModel::IsMalicious() const { if (!MightBeMalicious()) return false;
diff --git a/chrome/browser/enterprise/connectors/common.cc b/chrome/browser/enterprise/connectors/common.cc index adaa8f1..5149b3e 100644 --- a/chrome/browser/enterprise/connectors/common.cc +++ b/chrome/browser/enterprise/connectors/common.cc
@@ -12,7 +12,10 @@ #include "chrome/browser/enterprise/connectors/analysis/content_analysis_downloads_delegate.h" #include "chrome/browser/enterprise/connectors/connectors_prefs.h" #include "chrome/browser/enterprise/connectors/connectors_service.h" +#include "chrome/browser/enterprise/util/affiliation.h" +#include "chrome/browser/policy/dm_token_utils.h" #include "chrome/browser/profiles/profile.h" +#include "components/enterprise/browser/controller/browser_dm_token_storage.h" #if BUILDFLAG(IS_CHROMEOS_ASH) #include "chrome/browser/ash/profiles/profile_helper.h" @@ -348,7 +351,19 @@ #elif BUILDFLAG(IS_CHROMEOS_LACROS) return policy::PolicyLoaderLacros::IsMainUserAffiliated(); #else - return !per_profile; + // A browser managed through the device can send device info. + if (!per_profile) { + return true; + } + + // An unmanaged browser shouldn't share its device info for privacy reasons. + if (!policy::GetDMToken(profile).is_valid()) { + return false; + } + + // A managed device can share its info with the profile if they are + // affiliated. + return chrome::enterprise_util::IsProfileAffiliated(profile); #endif }
diff --git a/chrome/browser/enterprise/connectors/connectors_service.cc b/chrome/browser/enterprise/connectors/connectors_service.cc index 8dcb5bf..d020120 100644 --- a/chrome/browser/enterprise/connectors/connectors_service.cc +++ b/chrome/browser/enterprise/connectors/connectors_service.cc
@@ -170,8 +170,7 @@ #if BUILDFLAG(IS_CHROMEOS) Profile* profile = Profile::FromBrowserContext(context_); - if (enterprise_connectors::IncludeDeviceInfo(profile, - /*per_profile=*/false)) { + if (IncludeDeviceInfo(profile, /*per_profile=*/false)) { // The device dm token includes additional information like a device id, // which is relevant for reporting and should only be used for // IncludeDeviceInfo==true. @@ -546,9 +545,9 @@ // Device info is only useful for cloud service providers since local // provider can already determine all this info themselves. - const bool include_device_info = - is_cloud && enterprise_connectors::IncludeDeviceInfo( - profile, reporting_settings.value().per_profile); + bool include_device_info = + is_cloud && + IncludeDeviceInfo(profile, reporting_settings.value().per_profile); // Always include browser metadata for local service providers, but include // it for cloud service providers only if device info is included.
diff --git a/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc b/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc index c25eb82..b95afe4 100644 --- a/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc +++ b/chrome/browser/enterprise/connectors/connectors_service_browsertest.cc
@@ -385,7 +385,9 @@ bool includes_device_info = management_status() == ManagementStatus::AFFILIATED; #else - bool includes_device_info = !profile_reporting && is_cloud; + bool includes_device_info = + !profile_reporting || + (management_status() == ManagementStatus::AFFILIATED && is_cloud); #endif base::Value::Dict reporting_metadata = ReportingMetadata(is_cloud, includes_device_info); @@ -424,11 +426,16 @@ if (includes_device_info) { // The device DM token should only be populated when reporting is set at // the device level, aka not the profile level. - ASSERT_TRUE(metadata.device().has_dm_token()); - ASSERT_EQ(metadata.device().dm_token(), kFakeBrowserDMToken); - ASSERT_TRUE(reporting_metadata.FindStringByDottedPath("device.dmToken")); - ASSERT_EQ(metadata.device().dm_token(), - *reporting_metadata.FindStringByDottedPath("device.dmToken")); + if (profile_reporting) { + ASSERT_FALSE(metadata.device().has_dm_token()); + } else { + ASSERT_TRUE(metadata.device().has_dm_token()); + ASSERT_EQ(metadata.device().dm_token(), kFakeBrowserDMToken); + ASSERT_TRUE( + reporting_metadata.FindStringByDottedPath("device.dmToken")); + ASSERT_EQ(metadata.device().dm_token(), + *reporting_metadata.FindStringByDottedPath("device.dmToken")); + } #if !BUILDFLAG(IS_CHROMEOS) ASSERT_TRUE(metadata.device().has_client_id());
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto b/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto index 25253e1..65b2f87 100644 --- a/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto +++ b/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto
@@ -109,6 +109,14 @@ optional string device_trust_signals_json = 10; // DM token to be used for this request. optional string dm_token = 11; + // The identifier of the customer for the managed user, as defined by the + // Google Admin SDK at + // https://developers.google.com/admin-sdk/directory/v1/guides/manage-customers. + optional string user_customer_id = 12; + // Obfuscated gaia ID associated with the signed in managed user. + optional string obfuscated_gaia_id = 13; + // The ID of a profile on the device. + optional string profile_id = 14; } // Device Trust Signals
diff --git a/chrome/browser/enterprise/data_controls/BUILD.gn b/chrome/browser/enterprise/data_controls/BUILD.gn index 94bf08c..67140e6 100644 --- a/chrome/browser/enterprise/data_controls/BUILD.gn +++ b/chrome/browser/enterprise/data_controls/BUILD.gn
@@ -15,6 +15,10 @@ "//components/prefs", "//url", ] + + if (is_chromeos) { + sources += [ "component.h" ] + } } source_set("test_support") {
diff --git a/chrome/browser/enterprise/data_controls/component.h b/chrome/browser/enterprise/data_controls/component.h new file mode 100644 index 0000000..f8d2031 --- /dev/null +++ b/chrome/browser/enterprise/data_controls/component.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 CHROME_BROWSER_ENTERPRISE_DATA_CONTROLS_COMPONENT_H_ +#define CHROME_BROWSER_ENTERPRISE_DATA_CONTROLS_COMPONENT_H_ + +namespace data_controls { + +// A representation of destinations to which sharing confidential data is +// restricted by DataLeakPreventionRulesList policy. This is only applicable to +// ChromeOS as other platforms don't have the same visibility into applications +// directly outside of Chrome. +enum class Component { + kUnknownComponent, + kArc, // ARC++ as a Guest OS. + kCrostini, // Crostini as a Guest OS. + kPluginVm, // Plugin VM (Parallels/Windows) as a Guest OS. + kUsb, // Removable disk. + kDrive, // Google drive for file storage. + kMaxValue = kDrive +}; + +} // namespace data_controls + +#endif // CHROME_BROWSER_ENTERPRISE_DATA_CONTROLS_COMPONENT_H_
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index acc59969..d7dfebcdf 100644 --- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -551,7 +551,7 @@ DownloadItem* CreateFirstSlowTestDownload() { DownloadManager* manager = GetCurrentManager(); - EXPECT_EQ(0, manager->NonMaliciousInProgressCount()); + EXPECT_EQ(0, manager->BlockingShutdownCount()); EXPECT_EQ(0, manager->InProgressCount()); if (manager->InProgressCount() != 0) return nullptr; @@ -4337,7 +4337,7 @@ std::unique_ptr<content::DownloadTestObserver> observer( new JustInProgressDownloadObserver(manager, 1)); ASSERT_EQ(0, manager->InProgressCount()); - ASSERT_EQ(0, manager->NonMaliciousInProgressCount()); + ASSERT_EQ(0, manager->BlockingShutdownCount()); // Tabs created just for a download are automatically closed, invalidating // the download's WebContents. Downloads without WebContents cannot be // resumed. http://crbug.com/225901
diff --git a/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc b/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc index 695b492..020d47eb 100644 --- a/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc +++ b/chrome/browser/extensions/api/web_view/chrome_web_view_internal_api.cc
@@ -149,7 +149,7 @@ EXTENSION_FUNCTION_VALIDATE(params); // TODO(lazyboy): Actually implement filtering menu items. - guest_->ShowContextMenu(params->request_id); + GetGuest().ShowContextMenu(params->request_id); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/extensions/webstore_domain_browsertest.cc b/chrome/browser/extensions/webstore_domain_browsertest.cc index 2c2b3776..7c0b7b0 100644 --- a/chrome/browser/extensions/webstore_domain_browsertest.cc +++ b/chrome/browser/extensions/webstore_domain_browsertest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/extensions/extension_apitest.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/ui_test_utils.h" #include "components/network_session_configurator/common/network_switches.h" @@ -10,6 +11,9 @@ #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" +#include "extensions/browser/event_router.h" +#include "extensions/browser/extension_event_histogram_value.h" +#include "extensions/common/api/management.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "services/network/public/cpp/network_switches.h" @@ -94,6 +98,45 @@ EXPECT_FALSE(is_api_available("webstorePrivate")); } +// Test that the webstore can register and receive management events. Normally +// we have a check that the receiver of an extension event can never be a +// webpage context. The old webstore gets around this by appearing as a hosted +// app extension context, but the new webstore has the APIs exposed directly to +// the webpage context it uses. Regression test for crbug.com/1441136. +IN_PROC_BROWSER_TEST_P(WebstoreDomainBrowserTest, CanReceiveEvents) { + const GURL webstore_url = GetParam().Resolve("/webstore/mock_store.html"); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), webstore_url)); + EXPECT_EQ(web_contents->GetPrimaryMainFrame()->GetLastCommittedURL(), + webstore_url); + constexpr char kAddListener[] = R"( + chrome.management.onInstalled.addListener(() => { + domAutomationController.send('received event'); + }); + 'listener added'; + )"; + ASSERT_EQ("listener added", content::EvalJs(web_contents, kAddListener)); + + content::DOMMessageQueue message_queue( + browser()->tab_strip_model()->GetActiveWebContents()); + // Directly broadcast the management.onInstalled event from the EventRouter + // and verify it arrived to the page without causing a crash. + EventRouter* event_router = EventRouter::Get(profile()); + api::management::ExtensionInfo info; + info.install_type = api::management::ExtensionInstallType::kNormal; + info.type = api::management::ExtensionType::kExtension; + event_router->BroadcastEvent(std::make_unique<Event>( + events::FOR_TEST, api::management::OnInstalled::kEventName, + api::management::OnInstalled::Create(info))); + + std::string message; + EXPECT_TRUE(message_queue.WaitForMessage(&message)); + EXPECT_EQ("\"received event\"", message); +} + // Tests that a webstore page with misconfigured or missing X-Frame-Options // headers that is embedded in an iframe has the headers adjusted to SAMEORIGIN // and that the subframe navigation is subsequently blocked.
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinator.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinator.java index 1cf376c..dd1f965 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinator.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinator.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetCoordinator; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetCoordinator.EntryPoint; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetStrings; @@ -32,6 +33,7 @@ public class SigninBottomSheetCoordinator implements AccountPickerDelegate { private final Profile mProfile; private final WindowAndroid mWindowAndroid; + private final DeviceLockActivityLauncher mDeviceLockActivityLauncher; private final BottomSheetController mController; private final SigninManager mSigninManager; private boolean mSetTestToast; @@ -41,10 +43,11 @@ private final AccountPickerBottomSheetStrings mBottomSheetStrings; public SigninBottomSheetCoordinator(WindowAndroid windowAndroid, - BottomSheetController controller, Profile profile, - @Nullable AccountPickerBottomSheetStrings bottomSheetStrings, + DeviceLockActivityLauncher deviceLockActivityLauncher, BottomSheetController controller, + Profile profile, @Nullable AccountPickerBottomSheetStrings bottomSheetStrings, @Nullable Runnable onSigninSuccessCallback, @SigninAccessPoint int signinAccessPoint) { mWindowAndroid = windowAndroid; + mDeviceLockActivityLauncher = deviceLockActivityLauncher; mController = controller; mProfile = profile; mSigninManager = IdentityServicesProvider.get().getSigninManager(mProfile); @@ -104,8 +107,9 @@ } public void show() { - mAccountPickerBottomSheetCoordinator = new AccountPickerBottomSheetCoordinator( - mWindowAndroid, mController, this, mBottomSheetStrings); + mAccountPickerBottomSheetCoordinator = + new AccountPickerBottomSheetCoordinator(mWindowAndroid, mController, this, + mBottomSheetStrings, mDeviceLockActivityLauncher); } private void makeSigninNotAllowedToast() {
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinatorTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinatorTest.java index 3e3d073..84dd914 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinatorTest.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/signinbottomsheet/SigninBottomSheetCoordinatorTest.java
@@ -74,9 +74,9 @@ .thenReturn(mSigninManagerMock); when(mSigninManagerMock.isSigninAllowed()).thenReturn(true); mAccountManagerTestRule.addAccount(TEST_EMAIL); - mSigninCoordinator = - new SigninBottomSheetCoordinator(mWindowAndroidMock, mBottomSheetControllerMock, - mProfileMock, null, null, SigninAccessPoint.NTP_FEED_CARD_MENU_PROMO); + mSigninCoordinator = new SigninBottomSheetCoordinator(mWindowAndroidMock, null, + mBottomSheetControllerMock, mProfileMock, null, null, + SigninAccessPoint.NTP_FEED_CARD_MENU_PROMO); } @Test @@ -133,7 +133,7 @@ @Test public void testSigninCompleted_callSigninSuccessCallback() { SigninBottomSheetCoordinator coordinator = new SigninBottomSheetCoordinator( - mWindowAndroidMock, mBottomSheetControllerMock, mProfileMock, null, + mWindowAndroidMock, null, mBottomSheetControllerMock, mProfileMock, null, mOnSigninSuccessCallbackMock, SigninAccessPoint.NTP_FEED_BOTTOM_PROMO); doAnswer(invocation -> { SigninManager.SignInCallback callback = invocation.getArgument(2); @@ -150,7 +150,7 @@ @Test public void testSigninAborted_doesNotCallSigninSuccessCallback() { SigninBottomSheetCoordinator coordinator = new SigninBottomSheetCoordinator( - mWindowAndroidMock, mBottomSheetControllerMock, mProfileMock, null, + mWindowAndroidMock, null, mBottomSheetControllerMock, mProfileMock, null, mOnSigninSuccessCallbackMock, SigninAccessPoint.NTP_FEED_BOTTOM_PROMO); doAnswer(invocation -> { SigninManager.SignInCallback callback = invocation.getArgument(2);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 4b3e8a6..bd33f80 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -2946,11 +2946,6 @@ "expiry_milestone": 118 }, { - "name": "enable-open-in-download", - "owners": [ "alionadangla", "gambard", "bling-flags@google.com" ], - "expiry_milestone": 120 - }, - { "name": "enable-openscreen-cast-streaming-session", "owners": [ "jophba", "openscreen-eng" ], "expiry_milestone": 120 @@ -7172,6 +7167,11 @@ "expiry_milestone": 120 }, { + "name": "tab-hover-card-images", + "owners": [ "dfried", "estalin" ], + "expiry_milestone": 116 + }, + { "name": "tab-inactivity-threshold", "owners": [ "alionadangla", "lpromero", "bling-flags@google.com" ], "expiry_milestone": 120
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 37d1714..6cd49b4 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3113,6 +3113,10 @@ const char kTabGroupsSaveDescription[] = "Enables users to explicitly save and recall tab groups."; +const char kTabHoverCardImagesName[] = "Tab Hover Card Images"; +const char kTabHoverCardImagesDescription[] = + "Shows a preview image in tab hover cards, if tab hover cards are enabled."; + const char kTabSearchFuzzySearchName[] = "Fuzzy search for Tab Search"; const char kTabSearchFuzzySearchDescription[] = "Enable fuzzy search for Tab Search.";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 56faa326..7505a03 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1768,6 +1768,9 @@ extern const char kTabGroupsSaveName[]; extern const char kTabGroupsSaveDescription[]; +extern const char kTabHoverCardImagesName[]; +extern const char kTabHoverCardImagesDescription[]; + extern const char kTabSearchFuzzySearchName[]; extern const char kTabSearchFuzzySearchDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 71a1d7e..965000a 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -175,7 +175,6 @@ &kCloseTabSaveTabList, &kCriticalPersistedTabData, &kCreateNewTabInitializeRenderer, - &kCCTAllowCrossUidActivitySwitchFromBelow, &kCCTBackgroundTab, &kCCTBottomBarSwipeUpGesture, &kCCTBrandTransparency, @@ -253,7 +252,6 @@ &kOmniboxConsumesImeInsets, &kOmniboxWarmRecycledViewPool, &kOpaqueOriginForIncomingIntents, - &kPartnerHomepageInitialLoadImprovement, &kProbabilisticCryptidRenderer, &kQuickDeleteForAndroid, &kReachedCodeProfiler, @@ -510,10 +508,6 @@ "CriticalPersistedTabData", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kCCTAllowCrossUidActivitySwitchFromBelow, - "CCTAllowCrossUidActivitySwitchFromBelow", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kCCTBottomBarSwipeUpGesture, "CCTBottomBarSwipeUpGesture", base::FEATURE_ENABLED_BY_DEFAULT); @@ -832,10 +826,6 @@ "OpaqueOriginForIncomingIntents", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kPartnerHomepageInitialLoadImprovement, - "PartnerHomepageInitialLoadImprovement", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kProbabilisticCryptidRenderer, "ProbabilisticCryptidRenderer", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index 3506d4a..ae8440a 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -38,7 +38,6 @@ BASE_DECLARE_FEATURE(kCreateNewTabInitializeRenderer); BASE_DECLARE_FEATURE(kCriticalPersistedTabData); BASE_DECLARE_FEATURE(kCastDeviceFilter); -BASE_DECLARE_FEATURE(kCCTAllowCrossUidActivitySwitchFromBelow); BASE_DECLARE_FEATURE(kCCTBackgroundTab); BASE_DECLARE_FEATURE(kCCTBottomBarSwipeUpGesture); BASE_DECLARE_FEATURE(kCCTBrandTransparency); @@ -125,7 +124,6 @@ BASE_DECLARE_FEATURE(kBookmarksImprovedSaveFlow); BASE_DECLARE_FEATURE(kBookmarksRefresh); BASE_DECLARE_FEATURE(kOpaqueOriginForIncomingIntents); -BASE_DECLARE_FEATURE(kPartnerHomepageInitialLoadImprovement); BASE_DECLARE_FEATURE(kProbabilisticCryptidRenderer); BASE_DECLARE_FEATURE(kQuickDeleteForAndroid); BASE_DECLARE_FEATURE(kReachedCodeProfiler);
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 023e8846..7d48b5d 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
@@ -155,8 +155,6 @@ public static final String CAPTIVE_PORTAL_CERTIFICATE_LIST = "CaptivePortalCertificateList"; public static final String CAST_ANOTHER_CONTENT_WHILE_CASTING = "CastAnotherContentWhileCasting"; - public static final String CCT_ALLOW_CROSS_UID_ACTIVITY_SWITCH_FROM_BELOW = - "CCTAllowCrossUidActivitySwitchFromBelow"; public static final String CCT_AUTO_TRANSLATE = "CCTAutoTranslate"; public static final String CCT_BOTTOM_BAR_SWIPE_UP_GESTURE = "CCTBottomBarSwipeUpGesture"; public static final String CCT_BRAND_TRANSPARENCY = "CCTBrandTransparency"; @@ -338,8 +336,6 @@ public static final String PAGE_INFO_ABOUT_THIS_SITE_NEW_ICON = "PageInfoAboutThisSiteNewIcon"; public static final String PAGE_INFO_ABOUT_THIS_SITE_NON_EN = "PageInfoAboutThisSiteNonEn"; public static final String PAINT_PREVIEW_DEMO = "PaintPreviewDemo"; - public static final String PARTNER_HOMEPAGE_INITIAL_LOAD_IMPROVEMENT = - "PartnerHomepageInitialLoadImprovement"; public static final String PASSKEY_MANAGEMENT_USING_ACCOUNT_SETTINGS_ANDROID = "PasskeyManagementUsingAccountSettingsAndroid"; public static final String PASSWORD_EDIT_DIALOG_WITH_DETAILS = "PasswordEditDialogWithDetails"; @@ -489,8 +485,6 @@ new CachedFlag(BASELINE_GM3_SURFACE_COLORS, false); public static final CachedFlag sBottomSheetGtsSupport = new CachedFlag(BOTTOM_SHEET_GTS_SUPPORT, true); - public static final CachedFlag sCctAllowCrossUidActivitySwitchFromBelow = - new CachedFlag(CCT_ALLOW_CROSS_UID_ACTIVITY_SWITCH_FROM_BELOW, 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); @@ -541,10 +535,6 @@ public static final CachedFlag sInstanceSwitcher = new CachedFlag(INSTANCE_SWITCHER, true); public static final CachedFlag sInstantStart = new CachedFlag(INSTANT_START, false); public static final CachedFlag sInterestFeedV2 = new CachedFlag(INTEREST_FEED_V2, true); - public static final CachedFlag sLensCameraAssistedSearch = - new CachedFlag(LENS_CAMERA_ASSISTED_SEARCH, true); - public static final CachedFlag sOmahaMinSdkVersionAndroid = - new CachedFlag(OMAHA_MIN_SDK_VERSION_ANDROID, false); public static final CachedFlag sOmniboxMatchToolbarAndStatusBarColor = new CachedFlag(OMNIBOX_MATCH_TOOLBAR_AND_STATUS_BAR_COLOR, false); public static final CachedFlag sOmniboxModernizeVisualUpdate = @@ -554,10 +544,6 @@ public static final CachedFlag sOptimizationGuidePushNotifications = new CachedFlag(OPTIMIZATION_GUIDE_PUSH_NOTIFICATIONS, false); public static final CachedFlag sPaintPreviewDemo = new CachedFlag(PAINT_PREVIEW_DEMO, false); - public static final CachedFlag sPartnerHomepageInitialLoadImprovement = - new CachedFlag(PARTNER_HOMEPAGE_INITIAL_LOAD_IMPROVEMENT, true); - public static final CachedFlag sPrefetchNotificationSchedulingIntegration = - new CachedFlag(PREFETCH_NOTIFICATION_SCHEDULING_INTEGRATION, false); public static final CachedFlag sQueryTiles = new CachedFlag(QUERY_TILES, false); public static final CachedFlag sQueryTilesOnStart = new CachedFlag(QUERY_TILES_ON_START, false); public static final CachedFlag sShouldIgnoreIntentSkipInternalCheck =
diff --git a/chrome/browser/lifetime/application_lifetime_desktop.cc b/chrome/browser/lifetime/application_lifetime_desktop.cc index 64f37e2e..670aa78b 100644 --- a/chrome/browser/lifetime/application_lifetime_desktop.cc +++ b/chrome/browser/lifetime/application_lifetime_desktop.cc
@@ -308,8 +308,9 @@ // If there are any downloads active, all browsers are not closeable. // However, this does not block for malicious downloads. - if (DownloadCoreService::NonMaliciousDownloadCountAllProfiles() > 0) + if (DownloadCoreService::BlockingShutdownCountAllProfiles() > 0) { return false; + } // Check TabsNeedBeforeUnloadFired(). for (auto* browser : *BrowserList::GetInstance()) {
diff --git a/chrome/browser/lifetime/browser_close_manager.cc b/chrome/browser/lifetime/browser_close_manager.cc index ac79a59e..1fbc225 100644 --- a/chrome/browser/lifetime/browser_close_manager.cc +++ b/chrome/browser/lifetime/browser_close_manager.cc
@@ -39,7 +39,7 @@ DownloadCoreService* download_core_service = DownloadCoreServiceFactory::GetForBrowserContext(profile); if (download_core_service && - download_core_service->NonMaliciousDownloadCount() > 0) { + download_core_service->BlockingShutdownCount() > 0) { chrome::ScopedTabbedBrowserDisplayer displayer(profile); chrome::ShowDownloads(displayer.browser()); } @@ -105,8 +105,7 @@ // Mac has its own in-progress downloads prompt in app_controller_mac.mm. CloseBrowsers(); #else - int download_count = - DownloadCoreService::NonMaliciousDownloadCountAllProfiles(); + int download_count = DownloadCoreService::BlockingShutdownCountAllProfiles(); if (download_count == 0) { CloseBrowsers(); return;
diff --git a/chrome/browser/lifetime/browser_close_manager_browsertest.cc b/chrome/browser/lifetime/browser_close_manager_browsertest.cc index 51fc930..3f3790c 100644 --- a/chrome/browser/lifetime/browser_close_manager_browsertest.cc +++ b/chrome/browser/lifetime/browser_close_manager_browsertest.cc
@@ -934,7 +934,7 @@ WaitForAllBrowsersToClose(); EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); EXPECT_TRUE(BrowserList::GetInstance()->empty()); - EXPECT_EQ(1, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(1, DownloadCoreService::BlockingShutdownCountAllProfiles()); // Attempting to close again should not crash. TestBrowserCloseManager::AttemptClose( @@ -966,10 +966,8 @@ // Check that the download manager has the expected state. EXPECT_EQ(1, browser()->profile()->GetDownloadManager()->InProgressCount()); - EXPECT_EQ(0, browser() - ->profile() - ->GetDownloadManager() - ->NonMaliciousInProgressCount()); + EXPECT_EQ( + 0, browser()->profile()->GetDownloadManager()->BlockingShutdownCount()); // Close the browser with no user action. TestBrowserCloseManager::AttemptClose( @@ -999,9 +997,9 @@ EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); EXPECT_TRUE(BrowserList::GetInstance()->empty()); if (browser_defaults::kBrowserAliveWithNoWindows) - EXPECT_EQ(1, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(1, DownloadCoreService::BlockingShutdownCountAllProfiles()); else - EXPECT_EQ(0, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(0, DownloadCoreService::BlockingShutdownCountAllProfiles()); } // Test shutdown with a download in progress in an off-the-record profile. @@ -1030,7 +1028,7 @@ ui_test_utils::WaitForBrowserToClose(); EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); EXPECT_TRUE(BrowserList::GetInstance()->empty()); - EXPECT_EQ(0, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(0, DownloadCoreService::BlockingShutdownCountAllProfiles()); } // Test shutdown with a download in progress in a regular profile an inconito @@ -1076,9 +1074,9 @@ EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); EXPECT_TRUE(BrowserList::GetInstance()->empty()); if (browser_defaults::kBrowserAliveWithNoWindows) - EXPECT_EQ(1, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(1, DownloadCoreService::BlockingShutdownCountAllProfiles()); else - EXPECT_EQ(0, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(0, DownloadCoreService::BlockingShutdownCountAllProfiles()); } // Test shutdown with a download in progress from one profile, where the only @@ -1130,9 +1128,9 @@ EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); EXPECT_TRUE(BrowserList::GetInstance()->empty()); if (browser_defaults::kBrowserAliveWithNoWindows) - EXPECT_EQ(1, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(1, DownloadCoreService::BlockingShutdownCountAllProfiles()); else - EXPECT_EQ(0, DownloadCoreService::NonMaliciousDownloadCountAllProfiles()); + EXPECT_EQ(0, DownloadCoreService::BlockingShutdownCountAllProfiles()); } // Fails on ChromeOS and Linux, times out on Win. crbug.com/749098
diff --git a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java index 02ded62..3a69e9268 100644 --- a/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java +++ b/chrome/browser/partnercustomizations/java/src/org/chromium/chrome/browser/partnercustomizations/PartnerBrowserCustomizations.java
@@ -17,7 +17,6 @@ import org.chromium.base.task.AsyncTask; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; @@ -209,23 +208,16 @@ CustomizationProviderDelegateImpl delegate = new CustomizationProviderDelegateImpl(); - if (ChromeFeatureList.sPartnerHomepageInitialLoadImprovement.isEnabled()) { - // Refresh the homepage first, as it has potential impact on the URL to use - // for the initial tab. - if (isCancelled()) return null; - mHomepageUriChanged = refreshHomepage(delegate); - } + // Refresh the homepage first, as it has potential impact on the URL to use + // for the initial tab. + if (isCancelled()) return null; + mHomepageUriChanged = refreshHomepage(delegate); if (isCancelled()) return null; refreshIncognitoModeDisabled(delegate); if (isCancelled()) return null; refreshBookmarksEditingDisabled(delegate); - - if (!ChromeFeatureList.sPartnerHomepageInitialLoadImprovement.isEnabled()) { - if (isCancelled()) return null; - mHomepageUriChanged = refreshHomepage(delegate); - } } catch (Exception e) { Log.w(TAG, "Fetching partner customizations failed", e); }
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index 83d88c4..29bdef4 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -452,6 +452,8 @@ "//chrome/browser", "//chrome/browser/autofill", "//chrome/browser/password_manager/android/pwd_migration:utils", + "//chrome/browser/touch_to_fill/password_generation/android:public", + "//chrome/browser/touch_to_fill/password_generation/android:test_support", "//chrome/test:test_support", "//components/autofill/core/browser", "//components/autofill/core/common",
diff --git a/chrome/browser/password_manager/android/password_generation_controller.h b/chrome/browser/password_manager/android/password_generation_controller.h index 2f80050..f55a0813 100644 --- a/chrome/browser/password_manager/android/password_generation_controller.h +++ b/chrome/browser/password_manager/android/password_generation_controller.h
@@ -105,10 +105,14 @@ virtual void GeneratedPasswordRejected( autofill::password_generation::PasswordGenerationType type) = 0; - // Should be reset on page navigation. + // The bottom sheet is only shown once per page. This method is called on page + // navigation to reset the bottom sheet state and allow it to be shown again + // on the next page. virtual void HideBottomSheetIfNeeded() = 0; // Called when content::WebContents render frame is deleted. + // Ensures that the password generation bottom sheet is hidden when the frame + // is removed. virtual void RenderFrameDeleted( content::RenderFrameHost* render_frame_host) = 0;
diff --git a/chrome/browser/password_manager/android/password_generation_controller_impl.cc b/chrome/browser/password_manager/android/password_generation_controller_impl.cc index 8e7816c7..9e08fd5 100644 --- a/chrome/browser/password_manager/android/password_generation_controller_impl.cc +++ b/chrome/browser/password_manager/android/password_generation_controller_impl.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/check.h" #include "base/functional/bind.h" #include "base/functional/callback.h" #include "base/memory/ptr_util.h" @@ -16,6 +17,7 @@ #include "chrome/browser/password_manager/android/password_accessory_controller.h" #include "chrome/browser/password_manager/android/password_generation_dialog_view_interface.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.h" #include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h" #include "components/autofill/core/browser/ui/accessory_sheet_enums.h" #include "components/autofill/core/common/autofill_features.h" @@ -110,17 +112,10 @@ generation_element_data_ = std::make_unique<GenerationElementData>(ui_data); - if (base::FeatureList::IsEnabled( - password_manager::features::kPasswordGenerationBottomSheet) && - touch_to_fill_generation_state_ == TouchToFillState::kNone) { - touch_to_fill_generation_controller_ = - std::make_unique<TouchToFillPasswordGenerationController>( - active_frame_driver_); - touch_to_fill_generation_controller_->ShowTouchToFill(); - touch_to_fill_generation_state_ = TouchToFillState::kIsShowing; + if (touch_to_fill_generation_state_ == TouchToFillState::kIsShowing) { return; } - if (touch_to_fill_generation_state_ == TouchToFillState::kIsShowing) { + if (TryToShowGenerationTouchToFill()) { return; } @@ -214,7 +209,9 @@ content::WebContents* web_contents, password_manager::PasswordManagerClient* client, base::WeakPtr<ManualFillingController> manual_filling_controller, - CreateDialogFactory create_dialog_factory) { + CreateDialogFactory create_dialog_factory, + CreateTouchToFillGenerationControllerFactory + create_touch_to_fill_generation_controller) { DCHECK(web_contents) << "Need valid WebContents to attach controller to!"; DCHECK(!FromWebContents(web_contents)) << "Controller already attached!"; DCHECK(manual_filling_controller); @@ -223,7 +220,7 @@ UserDataKey(), base::WrapUnique(new PasswordGenerationControllerImpl( web_contents, client, std::move(manual_filling_controller), - create_dialog_factory))); + create_dialog_factory, create_touch_to_fill_generation_controller))); } PasswordGenerationControllerImpl::PasswordGenerationControllerImpl( @@ -232,19 +229,33 @@ *web_contents), client_(ChromePasswordManagerClient::FromWebContents(web_contents)), create_dialog_factory_( - base::BindRepeating(&PasswordGenerationDialogViewInterface::Create)) { -} + base::BindRepeating(&PasswordGenerationDialogViewInterface::Create)), + create_touch_to_fill_generation_controller_( + base::BindRepeating(&PasswordGenerationControllerImpl:: + CreateTouchToFillGenerationController, + base::Unretained(this))) {} PasswordGenerationControllerImpl::PasswordGenerationControllerImpl( content::WebContents* web_contents, password_manager::PasswordManagerClient* client, base::WeakPtr<ManualFillingController> manual_filling_controller, - CreateDialogFactory create_dialog_factory) + CreateDialogFactory create_dialog_factory, + CreateTouchToFillGenerationControllerFactory + create_touch_to_fill_generation_controller) : content::WebContentsUserData<PasswordGenerationControllerImpl>( *web_contents), client_(client), manual_filling_controller_(std::move(manual_filling_controller)), - create_dialog_factory_(create_dialog_factory) {} + create_dialog_factory_(create_dialog_factory), + create_touch_to_fill_generation_controller_( + create_touch_to_fill_generation_controller) {} + +std::unique_ptr<TouchToFillPasswordGenerationController> +PasswordGenerationControllerImpl::CreateTouchToFillGenerationController() { + return std::make_unique<TouchToFillPasswordGenerationController>( + active_frame_driver_, &GetWebContents(), + std::make_unique<TouchToFillPasswordGenerationBridgeImpl>()); +} void PasswordGenerationControllerImpl::ShowDialog(PasswordGenerationType type) { if (!active_frame_driver_ || dialog_view_) { @@ -269,6 +280,25 @@ dialog_view_->Show(password, active_frame_driver_, type); } +bool PasswordGenerationControllerImpl::TryToShowGenerationTouchToFill() { + CHECK(touch_to_fill_generation_state_ != TouchToFillState::kIsShowing); + + if (!base::FeatureList::IsEnabled( + password_manager::features::kPasswordGenerationBottomSheet) || + touch_to_fill_generation_state_ == TouchToFillState::kWasShown) { + return false; + } + + touch_to_fill_generation_controller_ = + create_touch_to_fill_generation_controller_.Run(); + if (!touch_to_fill_generation_controller_->ShowTouchToFill()) { + return false; + } + + touch_to_fill_generation_state_ = TouchToFillState::kIsShowing; + return true; +} + bool PasswordGenerationControllerImpl::IsActiveFrameDriver( const password_manager::ContentPasswordManagerDriver* driver) const { if (!active_frame_driver_) @@ -285,6 +315,7 @@ generation_element_data_.reset(); dialog_view_.reset(); manual_generation_requested_ = false; + // TODO (crbug.com/1421753): Do we need to hide the bottom sheet here? } void PasswordGenerationControllerImpl::HideBottomSheetIfNeeded() {
diff --git a/chrome/browser/password_manager/android/password_generation_controller_impl.h b/chrome/browser/password_manager/android/password_generation_controller_impl.h index beaf52b3..bc4b54d 100644 --- a/chrome/browser/password_manager/android/password_generation_controller_impl.h +++ b/chrome/browser/password_manager/android/password_generation_controller_impl.h
@@ -10,6 +10,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/password_manager/android/password_generation_controller.h" +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h" #include "components/autofill/core/common/password_generation_util.h" #include "content/public/browser/web_contents_user_data.h" #include "ui/gfx/geometry/rect.h" @@ -35,6 +36,8 @@ public: using CreateDialogFactory = base::RepeatingCallback<std::unique_ptr< PasswordGenerationDialogViewInterface>(PasswordGenerationController*)>; + using CreateTouchToFillGenerationControllerFactory = base::RepeatingCallback< + std::unique_ptr<TouchToFillPasswordGenerationController>()>; PasswordGenerationControllerImpl(const PasswordGenerationControllerImpl&) = delete; @@ -81,7 +84,9 @@ content::WebContents* web_contents, password_manager::PasswordManagerClient* client, base::WeakPtr<ManualFillingController> manual_filling_controller, - CreateDialogFactory create_dialog_callback); + CreateDialogFactory create_dialog_callback, + CreateTouchToFillGenerationControllerFactory + create_touch_to_fill_generation_controller); protected: // Callable in tests. @@ -105,7 +110,12 @@ content::WebContents* web_contents, password_manager::PasswordManagerClient* client, base::WeakPtr<ManualFillingController> manual_filling_controller, - CreateDialogFactory create_dialog_callback); + CreateDialogFactory create_dialog_callback, + CreateTouchToFillGenerationControllerFactory + create_touch_to_fill_generation_controller); + + std::unique_ptr<TouchToFillPasswordGenerationController> + CreateTouchToFillGenerationController(); // Checks if the given PasswordManagerDriver is the same as the one // belonging to the currently considered active frame for generation. @@ -119,6 +129,8 @@ // for metrics. void ShowDialog(autofill::password_generation::PasswordGenerationType type); + bool TryToShowGenerationTouchToFill(); + // Resets the current active frame driver, as well as the dialog if shown // and the generation element data. void ResetFocusState(); @@ -149,6 +161,11 @@ // Creation callback for the modal dialog view meant to facilitate testing. CreateDialogFactory create_dialog_factory_; + // Creation callback for the password generation bottom sheet controller to + // facilitate testing. + CreateTouchToFillGenerationControllerFactory + create_touch_to_fill_generation_controller_; + // Whether manual generation was requested from the UI. Used to filter out // unexpected or delayed manual generation responses from the renderer. bool manual_generation_requested_ = false;
diff --git a/chrome/browser/password_manager/android/password_generation_controller_impl_unittest.cc b/chrome/browser/password_manager/android/password_generation_controller_impl_unittest.cc index 72876488..3b255c6 100644 --- a/chrome/browser/password_manager/android/password_generation_controller_impl_unittest.cc +++ b/chrome/browser/password_manager/android/password_generation_controller_impl_unittest.cc
@@ -2,8 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/password_manager/android/password_generation_controller_impl.h" +#include "base/allocator/partition_allocator/pointers/raw_ptr.h" +#include "base/functional/bind.h" #include <map> +#include <memory> #include <utility> #include "base/functional/callback.h" @@ -14,6 +17,8 @@ #include "chrome/browser/autofill/mock_manual_filling_controller.h" #include "chrome/browser/password_manager/android/password_generation_dialog_view_interface.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" +#include "chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.h" +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/autofill/core/browser/autofill_client.h" #include "components/autofill/core/browser/test_autofill_client.h" @@ -137,6 +142,9 @@ class PasswordGenerationControllerTest : public ChromeRenderViewHostTestHarness { public: + using CreateTouchToFillGenerationControllerFactory = base::RepeatingCallback< + std::unique_ptr<TouchToFillPasswordGenerationController>()>; + void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); @@ -146,11 +154,6 @@ ON_CALL(*test_pwd_manager_client_, GetPasswordManager()) .WillByDefault(Return(password_manager_.get())); - PasswordGenerationControllerImpl::CreateForWebContentsForTesting( - web_contents(), test_pwd_manager_client_.get(), - mock_manual_filling_controller_.AsWeakPtr(), - mock_dialog_factory_.Get()); - password_manager_driver_ = std::make_unique<ContentPasswordManagerDriver>( main_rfh(), test_pwd_manager_client_.get(), &test_autofill_client_); another_password_manager_driver_ = @@ -167,6 +170,16 @@ mock_dialog_ = std::make_unique<NiceMock<MockPasswordGenerationDialogView>>(); + ON_CALL(create_ttf_generation_controller_, Run).WillByDefault([this]() { + return std::make_unique<TouchToFillPasswordGenerationController>( + active_driver(), web_contents(), + std::make_unique<MockTouchToFillPasswordGenerationBridge>()); + }); + + PasswordGenerationControllerImpl::CreateForWebContentsForTesting( + web_contents(), test_pwd_manager_client_.get(), + mock_manual_filling_controller_.AsWeakPtr(), mock_dialog_factory_.Get(), + create_ttf_generation_controller_.Get()); EXPECT_CALL(mock_manual_filling_controller_, OnAccessoryActionAvailabilityChanged( ShouldShowAction(false), @@ -203,6 +216,8 @@ std::unique_ptr<ContentPasswordManagerDriver> another_password_manager_driver_; std::unique_ptr<NiceMock<MockPasswordGenerationDialogView>> mock_dialog_; + base::MockCallback<CreateTouchToFillGenerationControllerFactory> + create_ttf_generation_controller_; private: NiceMock< @@ -225,6 +240,9 @@ } TEST_F(PasswordGenerationControllerTest, RelaysAutomaticGenerationAvailable) { + // TODO (crbug.com/1421753): Test this is for the + // PasswordGenerationBottomSheet flag disabled. Add one more test for the case + // after the bottom sheet is dismissed. EXPECT_CALL(mock_manual_filling_controller_, OnAccessoryActionAvailabilityChanged( ShouldShowAction(true), @@ -466,12 +484,73 @@ feature_list.InitAndEnableFeature( password_manager::features::kPasswordGenerationBottomSheet); + auto ttf_password_generation_bridge = + std::make_unique<MockTouchToFillPasswordGenerationBridge>(); + MockTouchToFillPasswordGenerationBridge* ttf_password_generation_bridge_ptr = + ttf_password_generation_bridge.get(); + EXPECT_CALL(create_ttf_generation_controller_, Run) + .WillOnce(Return( + ByMove(std::make_unique<TouchToFillPasswordGenerationController>( + active_driver(), web_contents(), + std::move(ttf_password_generation_bridge))))); + + // Keyboard accessory shouldn't show up. + EXPECT_CALL(mock_manual_filling_controller_, + OnAccessoryActionAvailabilityChanged( + ShouldShowAction(true), + autofill::AccessoryAction::GENERATE_PASSWORD_AUTOMATIC)) + .Times(0); + EXPECT_CALL(*ttf_password_generation_bridge_ptr, Show); + controller()->OnAutomaticGenerationAvailable( + active_driver(), GetTestGenerationUIData1(), gfx::RectF(100, 20)); + // Removes the keyboard suppression callback from the render widget host. It + // needs to be done before the `PasswordGenerationController` destructor is + // called. + controller()->HideBottomSheetIfNeeded(); +} + +TEST_F(PasswordGenerationControllerTest, + DoesNotCallKeyboardAccessoryWhenBottomSheetIsDisplayed) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + password_manager::features::kPasswordGenerationBottomSheet); + controller()->OnAutomaticGenerationAvailable( + active_driver(), GetTestGenerationUIData1(), gfx::RectF(100, 20)); + // Keyboard accessory shouldn't be called. EXPECT_CALL(mock_manual_filling_controller_, OnAccessoryActionAvailabilityChanged( _, autofill::AccessoryAction::GENERATE_PASSWORD_AUTOMATIC)) .Times(0); + EXPECT_CALL(create_ttf_generation_controller_, Run).Times(0); controller()->OnAutomaticGenerationAvailable( active_driver(), GetTestGenerationUIData1(), gfx::RectF(100, 20)); + // Removes the keyboard suppression callback from the render widget host. It + // needs to be done before the `PasswordGenerationController` destructor is + // called. controller()->HideBottomSheetIfNeeded(); } + +TEST_F(PasswordGenerationControllerTest, + CallsKeyboardAccessoryWhenGenerationBottomSheetFailedToShow) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature( + password_manager::features::kPasswordGenerationBottomSheet); + + auto ttf_password_generation_bridge = + std::make_unique<MockTouchToFillPasswordGenerationBridge>(); + EXPECT_CALL(*ttf_password_generation_bridge, Show).WillOnce(Return(false)); + EXPECT_CALL(create_ttf_generation_controller_, Run) + .WillOnce(Return( + ByMove(std::make_unique<TouchToFillPasswordGenerationController>( + active_driver(), web_contents(), + std::move(ttf_password_generation_bridge))))); + + // Keyboard accessory should show up. + EXPECT_CALL(mock_manual_filling_controller_, + OnAccessoryActionAvailabilityChanged( + ShouldShowAction(true), + autofill::AccessoryAction::GENERATE_PASSWORD_AUTOMATIC)); + controller()->OnAutomaticGenerationAvailable( + active_driver(), GetTestGenerationUIData1(), gfx::RectF(100, 20)); +}
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java index 70797e1a..bf392bc 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningRenderTest.java
@@ -27,7 +27,6 @@ import org.chromium.base.test.util.ApplicationTestUtils; import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; @@ -111,7 +110,6 @@ @Test @MediumTest @Feature({"RenderTest"}) - @DisabledTest(message = "https://crbug.com/1445909") public void testShowsPasswordMigrationWwarningFirstPage() throws Exception { runOnUiThreadBlocking(() -> mModel.set(VISIBLE, true));
diff --git a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java index 0f1e4116..fb312989 100644 --- a/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java +++ b/chrome/browser/password_manager/android/pwd_migration/java/src/org/chromium/chrome/browser/pwd_migration/PasswordMigrationWarningView.java
@@ -63,11 +63,6 @@ mFragmentManager = ((AppCompatActivity) context).getSupportFragmentManager(); mIntroFragment = new PasswordMigrationWarningIntroFragment(context); - mFragmentManager.beginTransaction() - .setReorderingAllowed(true) - .add(R.id.fragment_container_view, mIntroFragment, - "PasswordMigrationWarningFragment") - .commit(); } void setDismissHandler(Callback<Integer> dismissHandler) { @@ -84,6 +79,11 @@ mBottomSheetController.removeObserver(mBottomSheetObserver); return false; } + mFragmentManager.beginTransaction() + .setReorderingAllowed(true) + .add(R.id.fragment_container_view, mIntroFragment, + "PasswordMigrationWarningFragment") + .commit(); return true; }
diff --git a/chrome/browser/profiles/delete_profile_helper.cc b/chrome/browser/profiles/delete_profile_helper.cc index eb48f06..ce55384 100644 --- a/chrome/browser/profiles/delete_profile_helper.cc +++ b/chrome/browser/profiles/delete_profile_helper.cc
@@ -108,7 +108,7 @@ DownloadCoreService* service = DownloadCoreServiceFactory::GetForBrowserContext(profile); service->CancelDownloads(); - DCHECK_EQ(0, service->NonMaliciousDownloadCount()); + DCHECK_EQ(0, service->BlockingShutdownCount()); // Take a ScopedProfileKeepAlive for the the deletion process to avoid the // profile from being randomly unloaded.
diff --git a/chrome/browser/profiles/profile_statistics_unittest.cc b/chrome/browser/profiles/profile_statistics_unittest.cc index 3b29af72..7ed9485 100644 --- a/chrome/browser/profiles/profile_statistics_unittest.cc +++ b/chrome/browser/profiles/profile_statistics_unittest.cc
@@ -22,6 +22,7 @@ #include "chrome/browser/profiles/profile_statistics_common.h" #include "chrome/browser/profiles/profile_statistics_factory.h" #include "chrome/browser/sync/bookmark_sync_service_factory.h" +#include "chrome/browser/undo/bookmark_undo_service_factory.h" #include "chrome/browser/web_data_service_factory.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" @@ -46,7 +47,8 @@ std::unique_ptr<bookmarks::BookmarkModel> bookmark_model( new bookmarks::BookmarkModel(std::make_unique<ChromeBookmarkClient>( profile, ManagedBookmarkServiceFactory::GetForProfile(profile), - BookmarkSyncServiceFactory::GetForProfile(profile)))); + BookmarkSyncServiceFactory::GetForProfile(profile), + BookmarkUndoServiceFactory::GetForProfile(profile)))); return std::move(bookmark_model); }
diff --git a/chrome/browser/quick_delete/android/javatests/src/org/chromium/chrome/browser/quick_delete/QuickDeleteControllerTest.java b/chrome/browser/quick_delete/android/javatests/src/org/chromium/chrome/browser/quick_delete/QuickDeleteControllerTest.java index 8574369..4affb5a 100644 --- a/chrome/browser/quick_delete/android/javatests/src/org/chromium/chrome/browser/quick_delete/QuickDeleteControllerTest.java +++ b/chrome/browser/quick_delete/android/javatests/src/org/chromium/chrome/browser/quick_delete/QuickDeleteControllerTest.java
@@ -15,6 +15,8 @@ import static org.chromium.ui.test.util.ViewUtils.onViewWaiting; +import android.os.Build; + import androidx.test.espresso.matcher.ViewMatchers; import androidx.test.filters.MediumTest; @@ -27,6 +29,7 @@ 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.DisableIf; import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.chrome.browser.browsing_data.BrowsingDataBridge; @@ -55,6 +58,7 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) @EnableFeatures({ChromeFeatureList.QUICK_DELETE_FOR_ANDROID}) @Batch(Batch.PER_CLASS) +@DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.O, message = "crbug.com/1446002") public class QuickDeleteControllerTest { private static final String TEST_FILE = "/content/test/data/browsing_data/site_data.html"; @@ -123,7 +127,7 @@ openQuickDeleteDialog(); onViewWaiting(withId(R.id.positive_button)).perform(click()); - onView(withId(R.id.snackbar)).check(matches(isDisplayed())); + onViewWaiting(withId(R.id.snackbar)).check(matches(isDisplayed())); onView(withText(R.string.quick_delete_snackbar_message)).check(matches(isDisplayed())); mRenderTestRule.render(mActivityTestRule.getActivity().findViewById(R.id.snackbar),
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index 8bb5115..6622b03 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1108,7 +1108,8 @@ // Show Read Anything option if text is selected and if it's not already open // in the side panel. if (features::IsReadAnythingEnabled()) { - if (GetBrowser() && !IsReadAnythingEntryShowing(GetBrowser()) && + if (GetBrowser() && GetBrowser()->is_type_normal() && + !IsReadAnythingEntryShowing(GetBrowser()) && (content_type_->SupportsGroup( ContextMenuContentType::ITEM_GROUP_COPY) || content_type_->SupportsGroup(
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 d7b5e74b..83f06892 100644 --- a/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts +++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmarks_list.ts
@@ -677,6 +677,7 @@ this.push('activeFolderPath_', event.detail.bookmark); // Cancel search when changing active folder. this.$.searchField.setValue(''); + this.$.shownBookmarksIronList.focusItem(0); } else { this.bookmarksApi_.openBookmark( event.detail.bookmark.id, this.activeFolderPath_.length, {
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc b/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc index 959c94b..090386f8 100644 --- a/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc +++ b/chrome/browser/safe_browsing/client_side_detection_service_browsertest.cc
@@ -35,6 +35,10 @@ #include "chrome/test/base/ui_test_utils.h" #endif // defined ( +#if BUILDFLAG(IS_MAC) +#include "base/mac/mac_util.h" +#endif + namespace safe_browsing { namespace { @@ -123,6 +127,11 @@ #endif IN_PROC_BROWSER_TEST_P(ClientSideDetectionServiceBrowserTest, MAYBE_ModelUpdatesPropagated) { +#if BUILDFLAG(IS_MAC) + if (base::mac::IsAtLeastOS13()) { + GTEST_SKIP() << "Flaky on macOS 13: https://crbug.com/1433315"; + } +#endif GURL url(embedded_test_server()->GetURL("/empty.html")); ASSERT_TRUE(content::NavigateToURL(web_contents(), url)); @@ -224,6 +233,12 @@ #endif IN_PROC_BROWSER_TEST_P(ClientSideDetectionServiceBrowserTest, MAYBE_TfLiteClassification) { +#if BUILDFLAG(IS_MAC) + if (base::mac::IsAtLeastOS13()) { + GTEST_SKIP() << "Flaky on macOS 13: https://crbug.com/1433315"; + } +#endif + GURL url(embedded_test_server()->GetURL("/empty.html")); ASSERT_TRUE(content::NavigateToURL(web_contents(), url)); @@ -366,6 +381,12 @@ #endif IN_PROC_BROWSER_TEST_P(ClientSideDetectionServiceBrowserTest, MAYBE_TfLiteClassificationAfterTwoModelUploads) { +#if BUILDFLAG(IS_MAC) + if (base::mac::IsAtLeastOS13()) { + GTEST_SKIP() << "Flaky on macOS 13: https://crbug.com/1433315"; + } +#endif + if (!base::FeatureList::IsEnabled( kClientSideDetectionModelOptimizationGuide)) { return;
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java index 62cef19..f512b4c78 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderBase.java
@@ -30,6 +30,7 @@ import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfCoordinator; import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.share.ShareImageFileUtils; import org.chromium.components.browser_ui.share.ShareParams; @@ -81,6 +82,7 @@ protected final String mUrl; protected final Tracker mFeatureEngagementTracker; protected final Profile mProfile; + protected final DeviceLockActivityLauncher mDeviceLockActivityLauncher; /** * Constructs a new {@link ChromeProvidedSharingOptionsProviderBase}. @@ -97,13 +99,14 @@ * @param featureEngagementTracker feature engagement tracker. * @param url Url to share. * @param profile The current profile of the User. + * @param deviceLockActivityLauncher The launcher to start up the device lock page. */ protected ChromeProvidedSharingOptionsProviderBase(Activity activity, WindowAndroid windowAndroid, Supplier<Tab> tabProvider, BottomSheetController bottomSheetController, ShareParams shareParams, Callback<Tab> printTab, boolean isIncognito, ChromeOptionShareCallback chromeOptionShareCallback, Tracker featureEngagementTracker, - String url, Profile profile) { + String url, Profile profile, DeviceLockActivityLauncher deviceLockActivityLauncher) { mActivity = activity; mWindowAndroid = windowAndroid; mTabProvider = tabProvider; @@ -115,6 +118,7 @@ mChromeOptionShareCallback = chromeOptionShareCallback; mUrl = url; mProfile = profile; + mDeviceLockActivityLauncher = deviceLockActivityLauncher; mOrderedFirstPartyOptions = new ArrayList<>(); initializeFirstPartyOptionsInOrder(); @@ -418,9 +422,9 @@ .setIcon(R.drawable.send_tab, R.string.send_tab_to_self_share_activity_title) .setFeatureNameForMetrics(USER_ACTION_SEND_TAB_TO_SELF_SELECTED) .setOnClickCallback((view) -> { - SendTabToSelfCoordinator sttsCoordinator = - new SendTabToSelfCoordinator(mActivity, mWindowAndroid, mUrl, - mShareParams.getTitle(), mBottomSheetController, mProfile); + SendTabToSelfCoordinator sttsCoordinator = new SendTabToSelfCoordinator( + mActivity, mWindowAndroid, mUrl, mShareParams.getTitle(), + mBottomSheetController, mProfile, mDeviceLockActivityLauncher); sttsCoordinator.show(); }) .build();
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java index 786b690..5b4885f 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidCustomActionProvider.java
@@ -28,6 +28,7 @@ import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback; import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleCoordinator.LinkToggleState; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.share.ShareParams; import org.chromium.components.feature_engagement.EventConstants; @@ -75,15 +76,18 @@ * @param chromeShareExtras The {@link ChromeShareExtras} for the current share, if exists. * @param isMultiWindow Whether the current activity is in multi-window mode. * @param linkToTextCoordinator Link to text generator used for this share. + * @param deviceLockActivityLauncher The launcher to start up the device lock page. */ AndroidCustomActionProvider(Activity activity, WindowAndroid windowAndroid, Supplier<Tab> tabProvider, BottomSheetController bottomSheetController, ShareParams shareParams, Callback<Tab> printTab, boolean isIncognito, ChromeOptionShareCallback chromeOptionShareCallback, Tracker featureEngagementTracker, String url, Profile profile, ChromeShareExtras chromeShareExtras, boolean isMultiWindow, - @Nullable LinkToTextCoordinator linkToTextCoordinator) { + @Nullable LinkToTextCoordinator linkToTextCoordinator, + DeviceLockActivityLauncher deviceLockActivityLauncher) { super(activity, windowAndroid, tabProvider, bottomSheetController, shareParams, printTab, - isIncognito, chromeOptionShareCallback, featureEngagementTracker, url, profile); + isIncognito, chromeOptionShareCallback, featureEngagementTracker, url, profile, + deviceLockActivityLauncher); mChromeShareExtras = chromeShareExtras; mLinkToTextCoordinator = linkToTextCoordinator; initCustomActions(shareParams, chromeShareExtras, isMultiWindow);
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetController.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetController.java index f7b71203..30609f9 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetController.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetController.java
@@ -34,6 +34,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.ui.favicon.FaviconHelper; import org.chromium.chrome.browser.ui.favicon.FaviconUtils; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.share.ShareImageFileUtils; import org.chromium.components.browser_ui.share.ShareParams; @@ -54,6 +55,7 @@ private final Callback<Tab> mPrintCallback; private @Nullable LinkToTextCoordinator mLinkToTextCoordinator; + private final DeviceLockActivityLauncher mDeviceLockActivityLauncher; /** * Construct the controller used to display Android share sheet, and show the share sheet. @@ -66,13 +68,15 @@ * whether incognito mode is selected or not. * @param profileSupplier Supplier of the current profile of the User. * @param printCallback The callback used to trigger print action. + * @param deviceLockActivityLauncher The launcher to start up the device lock page. */ public static void showShareSheet(ShareParams params, ChromeShareExtras chromeShareExtras, BottomSheetController controller, Supplier<Tab> tabProvider, Supplier<TabModelSelector> tabModelSelectorSupplier, Supplier<Profile> profileSupplier, - Callback<Tab> printCallback) { - var newController = new AndroidShareSheetController( - controller, tabProvider, tabModelSelectorSupplier, profileSupplier, printCallback); + Callback<Tab> printCallback, DeviceLockActivityLauncher deviceLockActivityLauncher) { + var newController = + new AndroidShareSheetController(controller, tabProvider, tabModelSelectorSupplier, + profileSupplier, printCallback, deviceLockActivityLauncher); // If the current share is delegated to, once the link generation is complete, the call will // routes back to #showShareSheet eventually. if (!newController.processShareWithLinkToText(params, chromeShareExtras)) { @@ -89,16 +93,18 @@ * whether incognito mode is selected or not. * @param profileSupplier Supplier of the current profile of the User. * @param printCallback The callback used to trigger print action. + * @param deviceLockActivityLauncher The launcher to start up the device lock page. */ @VisibleForTesting AndroidShareSheetController(BottomSheetController controller, Supplier<Tab> tabProvider, Supplier<TabModelSelector> tabModelSelectorSupplier, Supplier<Profile> profileSupplier, - Callback<Tab> printCallback) { + Callback<Tab> printCallback, DeviceLockActivityLauncher deviceLockActivityLauncher) { mController = controller; mTabProvider = tabProvider; mTabModelSelectorSupplier = tabModelSelectorSupplier; mProfileSupplier = profileSupplier; mPrintCallback = printCallback; + mDeviceLockActivityLauncher = deviceLockActivityLauncher; } @Override @@ -128,7 +134,7 @@ params.getWindow(), mTabProvider, mController, params, mPrintCallback, isIncognito, this, TrackerFactory.getTrackerForProfile(profile), getUrlToShare(params, chromeShareExtras), profile, chromeShareExtras, - isInMultiWindow, mLinkToTextCoordinator); + isInMultiWindow, mLinkToTextCoordinator, mDeviceLockActivityLauncher); if (actionProvider.getCustomActions().size() > 0 || actionProvider.getModifyShareAction() != null) { provider = actionProvider;
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java index 466220e3..43439cf 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; import org.chromium.chrome.browser.signin.services.SigninManager; import org.chromium.chrome.browser.sync.SyncService; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetCoordinator; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetCoordinator.EntryPoint; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetStrings; @@ -143,15 +144,18 @@ private final String mTitle; private final BottomSheetController mController; private final Profile mProfile; + private final DeviceLockActivityLauncher mDeviceLockActivityLauncher; public SendTabToSelfCoordinator(Context context, WindowAndroid windowAndroid, String url, - String title, BottomSheetController controller, Profile profile) { + String title, BottomSheetController controller, Profile profile, + DeviceLockActivityLauncher deviceLockActivityLauncher) { mContext = context; mWindowAndroid = windowAndroid; mUrl = url; mTitle = title; mController = controller; mProfile = profile; + mDeviceLockActivityLauncher = deviceLockActivityLauncher; } public void show() { @@ -187,7 +191,7 @@ MetricsRecorder.recordSendingEvent(SendingEvent.SHOW_SIGNIN_PROMO); new AccountPickerBottomSheetCoordinator(mWindowAndroid, mController, new SendTabToSelfAccountPickerDelegate(this::onSignInComplete, mProfile), - new BottomSheetStrings()); + new BottomSheetStrings(), mDeviceLockActivityLauncher); return; } }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java index 5b2fd2f..cef8c1f 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.share.screenshot.ScreenshotCoordinator; import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleMetricsHelper.LinkToggleMetricsDetails; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.modules.image_editor.ImageEditorModuleProvider; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.share.ShareParams; @@ -75,7 +76,8 @@ * generation, sharing text from successful link-to-text generation, or sharing link-to-text. * @param linkToggleMetricsDetails {@link LinkToggleMetricsDetails} for recording the final * toggle state. - * * @param profile The current profile of the User. + * @param profile The current profile of the User. + * @param deviceLockActivityLauncher The launcher to start up the device lock page. */ ChromeProvidedSharingOptionsProvider(Activity activity, WindowAndroid windowAndroid, Supplier<Tab> tabProvider, BottomSheetController bottomSheetController, @@ -84,9 +86,11 @@ ChromeOptionShareCallback chromeOptionShareCallback, ImageEditorModuleProvider imageEditorModuleProvider, Tracker featureEngagementTracker, String url, @LinkGeneration int linkGenerationStatusForMetrics, - LinkToggleMetricsDetails linkToggleMetricsDetails, Profile profile) { + LinkToggleMetricsDetails linkToggleMetricsDetails, Profile profile, + DeviceLockActivityLauncher deviceLockActivityLauncher) { super(activity, windowAndroid, tabProvider, bottomSheetController, shareParams, printTab, - isIncognito, chromeOptionShareCallback, featureEngagementTracker, url, profile); + isIncognito, chromeOptionShareCallback, featureEngagementTracker, url, profile, + deviceLockActivityLauncher); mBottomSheetContent = bottomSheetContent; mShareStartTime = shareStartTime; mImageEditorModuleProvider = imageEditorModuleProvider;
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java index 74bdc86..9c3d0e5 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
@@ -35,6 +35,7 @@ import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleCoordinator.LinkToggleState; import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleMetricsHelper.LinkToggleMetricsDetails; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.modules.image_editor.ImageEditorModuleProvider; import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -89,6 +90,7 @@ private @LinkGeneration int mLinkGenerationStatusForMetrics = LinkGeneration.MAX; private LinkToggleMetricsDetails mLinkToggleMetricsDetails = new LinkToggleMetricsDetails(LinkToggleState.COUNT, DetailedContentType.NOT_SPECIFIED); + private DeviceLockActivityLauncher mDeviceLockActivityLauncher; /** * Constructs a new ShareSheetCoordinator. @@ -101,13 +103,14 @@ * @param isIncognito Whether the share sheet was opened in incognito mode or not. * @param imageEditorModuleProvider Image Editor module entry point if present in the APK. * @param profile The current profile of the User. + * @param deviceLockActivityLauncher The launcher to start up the device lock page. */ // TODO(crbug/1022172): Should be package-protected once modularization is complete. public ShareSheetCoordinator(BottomSheetController controller, ActivityLifecycleDispatcher lifecycleDispatcher, Supplier<Tab> tabProvider, Callback<Tab> printTab, LargeIconBridge iconBridge, boolean isIncognito, ImageEditorModuleProvider imageEditorModuleProvider, Tracker featureEngagementTracker, - Profile profile) { + Profile profile, DeviceLockActivityLauncher deviceLockActivityLauncher) { mBottomSheetController = controller; mLifecycleDispatcher = lifecycleDispatcher; mLifecycleDispatcher.register(this); @@ -135,6 +138,7 @@ mIconBridge = iconBridge; mFeatureEngagementTracker = featureEngagementTracker; mProfile = profile; + mDeviceLockActivityLauncher = deviceLockActivityLauncher; mPropertyModelBuilder = new ShareSheetPropertyModelBuilder(mBottomSheetController, ContextUtils.getApplicationContext().getPackageManager(), mProfile); mShareSheetUsageRankingHelper = new ShareSheetUsageRankingHelper(mBottomSheetController, @@ -299,7 +303,8 @@ mWindowAndroid, mTabProvider, mBottomSheetController, mBottomSheet, shareParams, mPrintTabCallback, mIsIncognito, mShareStartTime, this, mImageEditorModuleProvider, mFeatureEngagementTracker, getUrlToShare(shareParams, chromeShareExtras), - mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails, mProfile); + mLinkGenerationStatusForMetrics, mLinkToggleMetricsDetails, mProfile, + mDeviceLockActivityLauncher); mIsMultiWindow = ApiCompatibilityUtils.isInMultiWindowMode(activity); return mChromeProvidedSharingOptionsProvider.getPropertyModels(
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java index d05c9a8e2..0a9f5d36 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/android_share_sheet/AndroidShareSheetControllerUnitTest.java
@@ -73,6 +73,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.ui.favicon.FaviconHelper; import org.chromium.chrome.browser.ui.favicon.FaviconHelperJni; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.share.ShareImageFileUtils; @@ -138,6 +139,8 @@ @Mock Tab mTab; @Mock + DeviceLockActivityLauncher mDeviceLockActivityLauncher; + @Mock Profile mProfile; @Mock Tracker mTracker; @@ -183,7 +186,9 @@ doReturn(mWindow).when(mTab).getWindowAndroid(); mController = new AndroidShareSheetController(mBottomSheetController, - () -> mTab, () -> mTabModelSelector, () -> mProfile, mPrintCallback::notifyCalled); + () + -> mTab, + () -> mTabModelSelector, () -> mProfile, mPrintCallback::notifyCalled, null); } @After @@ -252,7 +257,11 @@ new ChromeShareExtras.Builder().setIsUrlOfVisiblePage(true).build(); AndroidShareSheetController.showShareSheet(params, chromeShareExtras, mBottomSheetController, - () -> mTab, () -> mTabModelSelector, () -> mProfile, mPrintCallback::notifyCalled); + () + -> mTab, + () + -> mTabModelSelector, + () -> mProfile, mPrintCallback::notifyCalled, mDeviceLockActivityLauncher); Intent intent = Shadows.shadowOf((Activity) mActivity).peekNextStartedActivity(); chooseCustomAction(intent, R.string.print_share_activity_title); @@ -373,7 +382,11 @@ .build(); AndroidShareSheetController.showShareSheet(params, chromeShareExtras, mBottomSheetController, - () -> mTab, () -> mTabModelSelector, () -> mProfile, mPrintCallback::notifyCalled); + () + -> mTab, + () + -> mTabModelSelector, + () -> mProfile, mPrintCallback::notifyCalled, mDeviceLockActivityLauncher); Intent chooserIntent = Shadows.shadowOf((Activity) mActivity).peekNextStartedActivity(); Intent shareIntent = chooserIntent.getParcelableExtra(Intent.EXTRA_INTENT); @@ -421,7 +434,11 @@ .build(); AndroidShareSheetController.showShareSheet(params, chromeShareExtras, mBottomSheetController, - () -> mTab, () -> mTabModelSelector, () -> mProfile, mPrintCallback::notifyCalled); + () + -> mTab, + () + -> mTabModelSelector, + () -> mProfile, mPrintCallback::notifyCalled, mDeviceLockActivityLauncher); // Since link to share failed, the content being shared is a plain text. Intent chooserIntent = Shadows.shadowOf((Activity) mActivity).peekNextStartedActivity();
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java index 249c5ee3..d64df36 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java
@@ -130,7 +130,7 @@ SendTabToSelfCoordinator coordinator = new SendTabToSelfCoordinator(activity, windowAndroid, HTTP_URL, "Page", BottomSheetControllerProvider.from(windowAndroid), - Profile.getLastUsedRegularProfile()); + Profile.getLastUsedRegularProfile(), null); coordinator.show(); }); }
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java index 83b6a8e..fff0670a 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
@@ -48,6 +48,7 @@ import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleCoordinator.LinkToggleState; import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleMetricsHelper.LinkToggleMetricsDetails; import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.test.AutomotiveContextWrapperTestRule; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; @@ -114,6 +115,8 @@ private ShareParams.TargetChosenCallback mTargetChosenCallback; @Mock private WindowAndroid mWindowAndroid; + @Mock + private DeviceLockActivityLauncher mDeviceLockActivityLauncher; private TestActivity mActivity; private ChromeProvidedSharingOptionsProvider mChromeProvidedSharingOptionsProvider; @@ -422,7 +425,7 @@ /*imageEditorModuleProvider*/ null, mTracker, URL, linkGenerationStatus, new LinkToggleMetricsDetails( LinkToggleState.COUNT, DetailedContentType.NOT_SPECIFIED), - mProfile); + mProfile, mDeviceLockActivityLauncher); } private boolean propertyModelsContain(List<PropertyModel> propertyModels, int labelId) {
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java index fa31454..9e0b72c6 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java
@@ -137,7 +137,7 @@ .setCallback(mTargetChosenCallback) .build(); mShareSheetCoordinator = new ShareSheetCoordinator(mController, mLifecycleDispatcher, - mTabProvider, null, null, false, null, null, mProfile); + mTabProvider, null, null, false, null, null, mProfile, null); } @After
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc index 6ea2ad3..96b4d21 100644 --- a/chrome/browser/ssl/ssl_browsertest.cc +++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -5426,9 +5426,7 @@ // Simulate clicking on a bookmark. { - content::WindowedNotificationObserver observer( - content::NOTIFICATION_LOAD_STOP, - content::NotificationService::AllSources()); + content::LoadStopObserver observer(tab); NavigateParams navigate_params(browser(), start_url, ui::PAGE_TRANSITION_AUTO_BOOKMARK); Navigate(&navigate_params);
diff --git a/chrome/browser/touch_to_fill/password_generation/android/BUILD.gn b/chrome/browser/touch_to_fill/password_generation/android/BUILD.gn index 90e5966..c4cc0e61 100644 --- a/chrome/browser/touch_to_fill/password_generation/android/BUILD.gn +++ b/chrome/browser/touch_to_fill/password_generation/android/BUILD.gn
@@ -6,6 +6,8 @@ source_set("public") { deps = [ + ":android", + ":jni_headers", "//base", "//components/password_manager/content/browser:browser", ] @@ -16,11 +18,54 @@ ] } +source_set("android") { + sources = [ + "touch_to_fill_password_generation_bridge.h", + "touch_to_fill_password_generation_bridge_impl.cc", + "touch_to_fill_password_generation_bridge_impl.h", + ] + + deps = [ + ":jni_headers", + "//components/password_manager/core/common:features", + "//content/public/browser:browser", + "//ui/android:android", + "//ui/gfx:native_widget_types", + ] +} + +generate_jni("jni_headers") { + sources = [ "internal/java/src/org/chromium/chrome/browser/touch_to_fill/password_generation/TouchToFillPasswordGenerationBridge.java" ] + + visibility = [ + ":android", + ":public", + ] +} + +source_set("test_support") { + testonly = true + + deps = [ + ":android", + "//base", + "//content/public/browser:browser", + "//testing/gmock", + "//ui/gfx:native_widget_types", + ] + + sources = [ + "mock_touch_to_fill_password_generation_bridge.cc", + "mock_touch_to_fill_password_generation_bridge.h", + ] +} + source_set("unit_tests") { testonly = true deps = [ ":public", + ":test_support", "//base", "//chrome/test:test_support", "//components/password_manager/content/browser:browser",
diff --git a/chrome/browser/touch_to_fill/password_generation/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/password_generation/android/internal/BUILD.gn new file mode 100644 index 0000000..add0097 --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/internal/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +android_library("java") { + deps = [ + "//base:base_java", + "//base:jni_java", + "//components/browser_ui/bottomsheet/android:java", + "//third_party/androidx:androidx_annotation_annotation_java", + "//ui/android:ui_java", + ] + + sources = [ "java/src/org/chromium/chrome/browser/touch_to_fill/password_generation/TouchToFillPasswordGenerationBridge.java" ] + + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] + resources_package = + "org.chromium.chrome.browser.touch_to_fill.password_generation" +}
diff --git a/chrome/browser/touch_to_fill/password_generation/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/password_generation/TouchToFillPasswordGenerationBridge.java b/chrome/browser/touch_to_fill/password_generation/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/password_generation/TouchToFillPasswordGenerationBridge.java new file mode 100644 index 0000000..c1f882d --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/password_generation/TouchToFillPasswordGenerationBridge.java
@@ -0,0 +1,31 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.touch_to_fill.password_generation; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider; +import org.chromium.ui.base.WindowAndroid; + +/** + * JNI wrapper for C++ TouchToFillPasswordGenerationBridge. Delegates calls from native to Java. + */ +class TouchToFillPasswordGenerationBridge { + @CalledByNative + private static TouchToFillPasswordGenerationBridge create(WindowAndroid windowAndroid) { + BottomSheetController bottomSheetController = + BottomSheetControllerProvider.from(windowAndroid); + return new TouchToFillPasswordGenerationBridge(bottomSheetController); + } + + private TouchToFillPasswordGenerationBridge(BottomSheetController bottomSheetController) { + // TODO(crbug.com/1421753): create the coordinator. + } + + @CalledByNative + private void show() { + // TODO(crbug.com/1421753): implement showing the password generation bottom sheet. + } +}
diff --git a/chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.cc b/chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.cc new file mode 100644 index 0000000..c9114fa1 --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.cc
@@ -0,0 +1,13 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.h" +#include "testing/gmock/include/gmock/gmock.h" + +MockTouchToFillPasswordGenerationBridge:: + MockTouchToFillPasswordGenerationBridge() { + ON_CALL(*this, Show).WillByDefault(testing::Return(true)); +} +MockTouchToFillPasswordGenerationBridge:: + ~MockTouchToFillPasswordGenerationBridge() = default;
diff --git a/chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.h b/chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.h new file mode 100644 index 0000000..963c921 --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.h
@@ -0,0 +1,21 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_MOCK_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_H_ +#define CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_MOCK_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_H_ + +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h" +#include "content/public/browser/web_contents.h" +#include "testing/gmock/include/gmock/gmock.h" + +class MockTouchToFillPasswordGenerationBridge + : public TouchToFillPasswordGenerationBridge { + public: + MockTouchToFillPasswordGenerationBridge(); + ~MockTouchToFillPasswordGenerationBridge() override; + + MOCK_METHOD(bool, Show, (content::WebContents*), (override)); +}; + +#endif // CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_MOCK_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_H_
diff --git a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h new file mode 100644 index 0000000..3f3d8ff --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h
@@ -0,0 +1,17 @@ +// 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_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_H_ +#define CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_H_ + +#include "content/public/browser/web_contents.h" + +class TouchToFillPasswordGenerationBridge { + public: + virtual ~TouchToFillPasswordGenerationBridge() = default; + + virtual bool Show(content::WebContents* web_contents) = 0; +}; + +#endif // CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_H_
diff --git a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.cc b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.cc new file mode 100644 index 0000000..f498f0ea --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.cc
@@ -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. + +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.h" + +#include "base/check.h" +#include "chrome/browser/touch_to_fill/password_generation/android/jni_headers/TouchToFillPasswordGenerationBridge_jni.h" +#include "components/password_manager/core/common/password_manager_features.h" +#include "content/public/browser/web_contents.h" +#include "ui/android/view_android.h" +#include "ui/android/window_android.h" + +TouchToFillPasswordGenerationBridgeImpl:: + TouchToFillPasswordGenerationBridgeImpl() { + DCHECK(base::FeatureList::IsEnabled( + password_manager::features::kPasswordGenerationBottomSheet)); +} + +TouchToFillPasswordGenerationBridgeImpl:: + ~TouchToFillPasswordGenerationBridgeImpl() = default; + +bool TouchToFillPasswordGenerationBridgeImpl::Show( + content::WebContents* web_contents) { + if (!web_contents->GetNativeView() || + !web_contents->GetNativeView()->GetWindowAndroid()) { + return false; + } + + CHECK(!java_object_); + java_object_.Reset(Java_TouchToFillPasswordGenerationBridge_create( + base::android::AttachCurrentThread(), + web_contents->GetNativeView()->GetWindowAndroid()->GetJavaObject())); + + Java_TouchToFillPasswordGenerationBridge_show( + base::android::AttachCurrentThread(), java_object_); + return true; +}
diff --git a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.h b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.h new file mode 100644 index 0000000..24a8cec --- /dev/null +++ b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge_impl.h
@@ -0,0 +1,29 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_IMPL_H_ +#define CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_IMPL_H_ + +#include "base/android/scoped_java_ref.h" +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h" +#include "content/public/browser/web_contents.h" + +class TouchToFillPasswordGenerationBridgeImpl + : public TouchToFillPasswordGenerationBridge { + public: + TouchToFillPasswordGenerationBridgeImpl(); + TouchToFillPasswordGenerationBridgeImpl( + const TouchToFillPasswordGenerationBridgeImpl&) = delete; + TouchToFillPasswordGenerationBridgeImpl& operator=( + const TouchToFillPasswordGenerationBridgeImpl&) = delete; + ~TouchToFillPasswordGenerationBridgeImpl() override; + + bool Show(content::WebContents* web_contents) override; + + private: + // The corresponding Java TouchToFillCreditCardViewBridge. + base::android::ScopedJavaGlobalRef<jobject> java_object_; +}; + +#endif // CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_BRIDGE_IMPL_H_
diff --git a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.cc b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.cc index 11a7db80e..659217e9 100644 --- a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.cc +++ b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.cc
@@ -4,13 +4,16 @@ #include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h" +#include <memory> #include "base/check.h" #include "base/feature_list.h" #include "base/memory/ptr_util.h" +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h" #include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h" #include "components/password_manager/content/browser/content_password_manager_driver.h" #include "components/password_manager/core/common/password_manager_features.h" #include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" TouchToFillPasswordGenerationController:: @@ -21,8 +24,12 @@ TouchToFillPasswordGenerationController:: TouchToFillPasswordGenerationController( base::WeakPtr<password_manager::ContentPasswordManagerDriver> - frame_driver) - : frame_driver_(frame_driver) { + frame_driver, + content::WebContents* web_contents, + std::unique_ptr<TouchToFillPasswordGenerationBridge> bridge) + : frame_driver_(frame_driver), + web_contents_(web_contents), + bridge_(std::move(bridge)) { suppress_showing_ime_callback_ = base::BindRepeating([]() { // This controller exists only while the TTF is being shown, so // always suppress the keyboard. @@ -30,8 +37,13 @@ }); } -void TouchToFillPasswordGenerationController::ShowTouchToFill() { +bool TouchToFillPasswordGenerationController::ShowTouchToFill() { + if (!bridge_->Show(web_contents_)) { + return false; + } + AddSuppressShowingImeCallback(); + return true; } void TouchToFillPasswordGenerationController::AddSuppressShowingImeCallback() {
diff --git a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h index dc41e20..1dbadd5 100644 --- a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h +++ b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_CONTROLLER_H_ #define CHROME_BROWSER_TOUCH_TO_FILL_PASSWORD_GENERATION_ANDROID_TOUCH_TO_FILL_PASSWORD_GENERATION_CONTROLLER_H_ +#include "base/allocator/partition_allocator/pointers/raw_ptr.h" +#include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_bridge.h" #include "content/public/browser/render_widget_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" @@ -18,9 +20,11 @@ // after the bottom sheet is dismissed. class TouchToFillPasswordGenerationController { public: - explicit TouchToFillPasswordGenerationController( + TouchToFillPasswordGenerationController( base::WeakPtr<password_manager::ContentPasswordManagerDriver> - frame_driver); + frame_driver, + content::WebContents* web_contents, + std::unique_ptr<TouchToFillPasswordGenerationBridge> bridge); TouchToFillPasswordGenerationController( const TouchToFillPasswordGenerationController&) = delete; TouchToFillPasswordGenerationController& operator=( @@ -28,7 +32,7 @@ ~TouchToFillPasswordGenerationController(); // Shows the password generation bottom sheet. - void ShowTouchToFill(); + bool ShowTouchToFill(); private: // Suppressing IME input is necessary for Touch-To-Fill. @@ -36,9 +40,10 @@ void RemoveSuppressShowingImeCallback(); // Password manager driver for the frame on which the Touch-To-Fill was - // triggered. Ensure that the bottom sheet should be hidden when the frame is - // removed. + // triggered. base::WeakPtr<password_manager::ContentPasswordManagerDriver> frame_driver_; + base::raw_ptr<content::WebContents> web_contents_; + std::unique_ptr<TouchToFillPasswordGenerationBridge> bridge_; content::RenderWidgetHost::SuppressShowingImeCallback suppress_showing_ime_callback_;
diff --git a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller_unittest.cc b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller_unittest.cc index 260cbbb..8706eb5 100644 --- a/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller_unittest.cc +++ b/chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller_unittest.cc
@@ -5,6 +5,7 @@ #include <memory> #include "base/memory/weak_ptr.h" +#include "chrome/browser/touch_to_fill/password_generation/android/mock_touch_to_fill_password_generation_bridge.h" #include "chrome/browser/touch_to_fill/password_generation/android/touch_to_fill_password_generation_controller.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/autofill/core/browser/test_autofill_client.h" @@ -12,6 +13,7 @@ #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/common/password_manager_features.h" #include "content/public/test/text_input_test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" #include "ui/base/ime/mojom/text_input_state.mojom.h" #include "ui/base/ime/text_input_type.h" @@ -39,8 +41,11 @@ TEST_F(TouchToFillPasswordGenerationControllerTest, KeyboardIsSuppressedWhileTheBottomSheetIsShown) { + auto bridge = std::make_unique<MockTouchToFillPasswordGenerationBridge>(); + MockTouchToFillPasswordGenerationBridge* bridge_ptr = bridge.get(); auto controller = std::make_unique<TouchToFillPasswordGenerationController>( - password_mananger_driver()); + password_mananger_driver(), web_contents(), std::move(bridge)); + EXPECT_CALL(*bridge_ptr, Show); controller->ShowTouchToFill(); ui::mojom::TextInputStatePtr initial_state = ui::mojom::TextInputState::New();
diff --git a/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_answer_suggestion.xml b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_answer_suggestion.xml index 9b27a65..bbdc0645 100644 --- a/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_answer_suggestion.xml +++ b/chrome/browser/ui/android/omnibox/java/res/layout/omnibox_answer_suggestion.xml
@@ -9,6 +9,7 @@ android:id="@+id/omnibox_answer" android:layout_width="match_parent" android:layout_height="wrap_content" + android:gravity="center" android:orientation="vertical"> <TextView
diff --git a/chrome/browser/ui/android/signin/BUILD.gn b/chrome/browser/ui/android/signin/BUILD.gn index 7ec91f9..33bda2a 100644 --- a/chrome/browser/ui/android/signin/BUILD.gn +++ b/chrome/browser/ui/android/signin/BUILD.gn
@@ -49,6 +49,7 @@ "java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachine.java", "java/src/org/chromium/chrome/browser/ui/signin/ConfirmSyncDataStateMachineDelegate.java", "java/src/org/chromium/chrome/browser/ui/signin/ConsentTextTracker.java", + "java/src/org/chromium/chrome/browser/ui/signin/DeviceLockActivityLauncher.java", "java/src/org/chromium/chrome/browser/ui/signin/FullScreenSyncPromoUtil.java", "java/src/org/chromium/chrome/browser/ui/signin/GoogleActivityController.java", "java/src/org/chromium/chrome/browser/ui/signin/PersonalizedSigninPromoView.java", @@ -203,6 +204,7 @@ "//third_party/junit", "//third_party/mockito:mockito_java", "//ui/android:ui_java_test_support", + "//ui/android:ui_no_recycler_view_java", ] }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/DeviceLockActivityLauncher.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/DeviceLockActivityLauncher.java new file mode 100644 index 0000000..61aeaa5 --- /dev/null +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/DeviceLockActivityLauncher.java
@@ -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. + +package org.chromium.chrome.browser.ui.signin; + +import android.content.Context; + +import org.chromium.ui.base.WindowAndroid; + +/** Allows for launching {@link DeviceLockActivity} in modularized code. */ +public interface DeviceLockActivityLauncher { + /** + * Launches the {@link DeviceLockActivity} to set a device lock for data privacy. + * @param context The context to launch the {@link DeviceLockActivity} with. + * @param inSignInFlow Whether the current flow is related to account sign-in. + * @param selectedAccount The account that's currently signed into or selected for sign-in. + * @param windowAndroid The host activity's {@link WindowAndroid}. + * @param callback A callback to run after the {@link DeviceLockActivity} finishes. + */ + void launchDeviceLockActivity(Context context, boolean inSignInFlow, String selectedAccount, + WindowAndroid windowAndroid, WindowAndroid.IntentCallback callback); +}
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetCoordinator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetCoordinator.java index ec62907d..8c73eaf 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetCoordinator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetCoordinator.java
@@ -12,6 +12,7 @@ import org.chromium.chrome.browser.signin.services.SigninMetricsUtils; import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; @@ -79,12 +80,13 @@ public AccountPickerBottomSheetCoordinator(WindowAndroid windowAndroid, BottomSheetController bottomSheetController, AccountPickerDelegate accountPickerDelegate, - AccountPickerBottomSheetStrings accountPickerBottomSheetStrings) { + AccountPickerBottomSheetStrings accountPickerBottomSheetStrings, + DeviceLockActivityLauncher deviceLockActivityLauncher) { SigninMetricsUtils.logAccountConsistencyPromoAction(AccountConsistencyPromoAction.SHOWN); - mAccountPickerBottomSheetMediator = - new AccountPickerBottomSheetMediator(windowAndroid, accountPickerDelegate, - this::onDismissButtonClicked, accountPickerBottomSheetStrings); + mAccountPickerBottomSheetMediator = new AccountPickerBottomSheetMediator(windowAndroid, + accountPickerDelegate, this::onDismissButtonClicked, + accountPickerBottomSheetStrings, deviceLockActivityLauncher); mView = new AccountPickerBottomSheetView( windowAndroid.getActivity().get(), mAccountPickerBottomSheetMediator); mAccountPickerCoordinator = new AccountPickerCoordinator(
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java index 133dc1d..0f6568c6 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetMediator.java
@@ -12,11 +12,13 @@ import androidx.annotation.Nullable; +import org.chromium.base.BuildInfo; import org.chromium.base.Callback; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.chrome.browser.signin.services.ProfileDataCache; import org.chromium.chrome.browser.signin.services.SigninMetricsUtils; import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.browser.ui.signin.SigninUtils; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetCoordinator.EntryPoint; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetProperties.ViewState; @@ -47,6 +49,7 @@ private final ProfileDataCache mProfileDataCache; private final PropertyModel mModel; private final AccountManagerFacade mAccountManagerFacade; + private final DeviceLockActivityLauncher mDeviceLockActivityLauncher; private @Nullable String mSelectedAccountName; private @Nullable String mDefaultAccountName; @@ -58,11 +61,13 @@ AccountPickerBottomSheetMediator(WindowAndroid windowAndroid, AccountPickerDelegate accountPickerDelegate, Runnable onDismissButtonClicked, - AccountPickerBottomSheetStrings accountPickerBottomSheetStrings) { + AccountPickerBottomSheetStrings accountPickerBottomSheetStrings, + DeviceLockActivityLauncher deviceLockActivityLauncher) { mWindowAndroid = windowAndroid; mActivity = windowAndroid.getActivity().get(); mAccountPickerDelegate = accountPickerDelegate; mProfileDataCache = ProfileDataCache.createWithDefaultImageSizeAndNoBadge(mActivity); + mDeviceLockActivityLauncher = deviceLockActivityLauncher; mModel = AccountPickerBottomSheetProperties.createModel(this::onSelectedAccountClicked, this::onContinueAsClicked, @@ -248,7 +253,16 @@ int viewState = mModel.get(AccountPickerBottomSheetProperties.VIEW_STATE); if (viewState == ViewState.COLLAPSED_ACCOUNT_LIST || viewState == ViewState.SIGNIN_GENERAL_ERROR) { - signIn(); + if (BuildInfo.getInstance().isAutomotive) { + mDeviceLockActivityLauncher.launchDeviceLockActivity(mActivity, true, + mSelectedAccountName, mWindowAndroid, (resultCode, data) -> { + if (resultCode == Activity.RESULT_OK) { + signIn(); + } + }); + } else { + signIn(); + } } else if (viewState == ViewState.NO_ACCOUNTS) { addAccount(); } else if (viewState == ViewState.SIGNIN_AUTH_ERROR) {
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java index ba0c46e..bfee7cf 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetRenderTest.java
@@ -317,8 +317,7 @@ TestThreadUtils.runOnUiThreadBlocking(() -> { mCoordinator = new AccountPickerBottomSheetCoordinator( mActivityTestRule.getActivity().getWindowAndroid(), getBottomSheetController(), - mAccountPickerDelegate, accountPickerBottomSheetStrings); - + mAccountPickerDelegate, accountPickerBottomSheetStrings, null); }); ViewUtils.onViewWaiting(allOf(withId(R.id.account_picker_selected_account), isDisplayed())); }
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetTest.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetTest.java index 9316045..4dd464b 100644 --- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetTest.java +++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/AccountPickerBottomSheetTest.java
@@ -18,15 +18,18 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.core.AllOf.allOf; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.Activity; +import android.content.Context; import android.view.View; import androidx.test.espresso.ViewInteraction; @@ -57,8 +60,10 @@ import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfCoordinator; import org.chromium.chrome.browser.signin.services.SigninPreferencesManager; +import org.chromium.chrome.browser.ui.signin.DeviceLockActivityLauncher; import org.chromium.chrome.browser.ui.signin.R; import org.chromium.chrome.browser.ui.signin.account_picker.AccountPickerBottomSheetCoordinator.EntryPoint; +import org.chromium.chrome.test.AutomotiveContextWrapperTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; @@ -71,6 +76,7 @@ import org.chromium.components.signin.test.util.FakeAccountInfoService; import org.chromium.components.signin.test.util.FakeAccountManagerFacade; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.test.util.ViewUtils; /** @@ -113,6 +119,9 @@ new AccountManagerTestRule(mFakeAccountManagerFacade, mFakeAccountInfoService); @Rule + public AutomotiveContextWrapperTestRule mAutoTestRule = new AutomotiveContextWrapperTestRule(); + + @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS); @Mock @@ -122,6 +131,7 @@ private ArgumentCaptor<Callback<Boolean>> mUpdateCredentialsSuccessCallbackCaptor; private AccountPickerBottomSheetCoordinator mCoordinator; + private CustomDeviceLockActivityLauncher mDeviceLockActivityLauncher; @Before public void setUp() { @@ -174,7 +184,8 @@ TestThreadUtils.runOnUiThreadBlocking(() -> { mCoordinator = new AccountPickerBottomSheetCoordinator( sActivityTestRule.getActivity().getWindowAndroid(), getBottomSheetController(), - mAccountPickerDelegateMock, new AccountPickerBottomSheetStrings() {}); + mAccountPickerDelegateMock, new AccountPickerBottomSheetStrings() {}, + new CustomDeviceLockActivityLauncher()); }); checkZeroAccountBottomSheet(); @@ -344,7 +355,7 @@ TestThreadUtils.runOnUiThreadBlocking(() -> { mCoordinator = new AccountPickerBottomSheetCoordinator( sActivityTestRule.getActivity().getWindowAndroid(), getBottomSheetController(), - mAccountPickerDelegateMock, new AccountPickerBottomSheetStrings() {}); + mAccountPickerDelegateMock, new AccountPickerBottomSheetStrings() {}, null); }); checkZeroAccountBottomSheet(); @@ -413,6 +424,53 @@ @Test @MediumTest + public void testAutomotiveDevice_deviceLockReady_signInDefaultAccount() + throws InterruptedException { + mAutoTestRule.setIsAutomotive(true); + var accountConsistencyHistogram = + HistogramWatcher.newBuilder() + .expectIntRecords("Signin.AccountConsistencyPromoAction", + AccountConsistencyPromoAction.SHOWN, + AccountConsistencyPromoAction.SIGNED_IN_WITH_DEFAULT_ACCOUNT) + .build(); + SharedPreferencesManager.getInstance().writeInt( + ChromePreferenceKeys.WEB_SIGNIN_ACCOUNT_PICKER_ACTIVE_DISMISSAL_COUNT, 2); + buildAndShowCollapsedBottomSheet(); + + clickContinueButtonAndCheckSignInInProgressSheetOnAutomotive(true); + + accountConsistencyHistogram.assertExpected(); + Assert.assertEquals(0, + SigninPreferencesManager.getInstance() + .getWebSigninAccountPickerActiveDismissalCount()); + verify(mAccountPickerDelegateMock, times(1)).signIn(any(), any()); + } + + @Test + @MediumTest + public void testAutomotiveDevice_deviceLockRefused_dismissedSignIn() + throws InterruptedException { + mAutoTestRule.setIsAutomotive(true); + var accountConsistencyHistogram = + HistogramWatcher.newBuilder() + .expectIntRecords("Signin.AccountConsistencyPromoAction", + AccountConsistencyPromoAction.SHOWN) + .build(); + SharedPreferencesManager.getInstance().writeInt( + ChromePreferenceKeys.WEB_SIGNIN_ACCOUNT_PICKER_ACTIVE_DISMISSAL_COUNT, 2); + buildAndShowCollapsedBottomSheet(); + + clickContinueButtonAndCheckSignInInProgressSheetOnAutomotive(false); + + accountConsistencyHistogram.assertExpected(); + Assert.assertEquals(2, + SigninPreferencesManager.getInstance() + .getWebSigninAccountPickerActiveDismissalCount()); + verify(mAccountPickerDelegateMock, times(0)).signIn(any(), any()); + } + + @Test + @MediumTest public void testSignInDefaultAccountOnCollapsedSheetForSendTabToSelf() { when(mAccountPickerDelegateMock.getEntryPoint()).thenReturn(EntryPoint.SEND_TAB_TO_SELF); var accountConsistencyHistogram = @@ -743,6 +801,43 @@ onView(withId(R.id.account_picker_dismiss_button)).check(matches(not(isDisplayed()))); } + private void clickContinueButtonAndCheckSignInInProgressSheetOnAutomotive( + boolean deviceLockCreated) { + View bottomSheetView = mCoordinator.getBottomSheetViewForTesting(); + TestThreadUtils.runOnUiThreadBlocking(() -> { + bottomSheetView.findViewById(R.id.account_picker_continue_as_button).performClick(); + }); + assertTrue(mDeviceLockActivityLauncher.isLaunched()); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mDeviceLockActivityLauncher.runCallback( + deviceLockCreated ? Activity.RESULT_OK : Activity.RESULT_CANCELED); + }); + if (deviceLockCreated) { + // TODO(https://crbug.com/1116348): Check AccountPickerDelegate.signIn() is called + // after solving AsyncTask wait problem in espresso + // Currently the ProgressBar animation cannot be disabled on + // android-marshmallow-arm64-rel bot with DisableAnimationsTestRule, we hide the + // ProgressBar manually here to enable checks of other elements on the screen. + // TODO(https://crbug.com/1115067): Delete this line once DisableAnimationsTestRule is + // fixed. + TestThreadUtils.runOnUiThreadBlocking(() -> { + bottomSheetView.findViewById(R.id.account_picker_signin_spinner_view) + .setVisibility(View.GONE); + }); + onView(withText(R.string.signin_account_picker_bottom_sheet_signin_title)) + .check(matches(isDisplayed())); + onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed()))); + onView(withId(R.id.account_picker_selected_account)).check(matches(not(isDisplayed()))); + onView(withId(R.id.account_picker_dismiss_button)).check(matches(not(isDisplayed()))); + } else { + onView(withText(R.string.signin_account_picker_bottom_sheet_signin_title)) + .check(matches(not(isDisplayed()))); + onView(withId(R.id.account_picker_account_list)).check(matches(not(isDisplayed()))); + onView(withId(R.id.account_picker_selected_account)).check(matches(isDisplayed())); + onView(withId(R.id.account_picker_dismiss_button)).check(matches(isDisplayed())); + } + } + private static void checkZeroAccountBottomSheet() { onVisibleView(withText(TEST_EMAIL1)).check(doesNotExist()); onVisibleView(withText(TEST_EMAIL2)).check(doesNotExist()); @@ -777,10 +872,12 @@ mAccountPickerDelegateMock.getEntryPoint() == EntryPoint.SEND_TAB_TO_SELF ? new SendTabToSelfCoordinator.BottomSheetStrings() : new AccountPickerBottomSheetStrings() {}; + mDeviceLockActivityLauncher = new CustomDeviceLockActivityLauncher(); TestThreadUtils.runOnUiThreadBlocking(() -> { mCoordinator = new AccountPickerBottomSheetCoordinator( sActivityTestRule.getActivity().getWindowAndroid(), getBottomSheetController(), - mAccountPickerDelegateMock, accountPickerBottomSheetStrings); + mAccountPickerDelegateMock, accountPickerBottomSheetStrings, + mDeviceLockActivityLauncher); }); CriteriaHelper.pollUiThread(mCoordinator.getBottomSheetViewForTesting().findViewById( R.id.account_picker_selected_account)::isShown); @@ -803,4 +900,27 @@ // matcher. return onView(allOf(matcher, withEffectiveVisibility(VISIBLE))); } + + private class CustomDeviceLockActivityLauncher implements DeviceLockActivityLauncher { + private WindowAndroid.IntentCallback mCallback; + private boolean mLaunched; + + CustomDeviceLockActivityLauncher() {} + + @Override + public void launchDeviceLockActivity(Context context, boolean inSignInFlow, + String selectedAccount, WindowAndroid windowAndroid, + WindowAndroid.IntentCallback callback) { + mCallback = callback; + mLaunched = true; + } + + boolean isLaunched() { + return mLaunched; + } + + void runCallback(int activityResult) { + mCallback.onIntentCompleted(activityResult, null); + } + } }
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index a462353..71297e1 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -985,7 +985,7 @@ return DownloadCloseType::kOk; int total_download_count = - DownloadCoreService::NonMaliciousDownloadCountAllProfiles(); + DownloadCoreService::BlockingShutdownCountAllProfiles(); if (total_download_count == 0) return DownloadCloseType::kOk; // No downloads; can definitely close. @@ -1018,10 +1018,9 @@ DownloadCoreService* download_core_service = DownloadCoreServiceFactory::GetForBrowserContext(profile()); if ((profile_window_count == 0) && - (download_core_service->NonMaliciousDownloadCount() > 0) && + (download_core_service->BlockingShutdownCount() > 0) && (profile()->IsIncognitoProfile() || profile()->IsGuestSession())) { - *num_downloads_blocking = - download_core_service->NonMaliciousDownloadCount(); + *num_downloads_blocking = download_core_service->BlockingShutdownCount(); return profile()->IsGuestSession() ? DownloadCloseType::kLastWindowInGuestSession : DownloadCloseType::kLastWindowInIncognitoProfile;
diff --git a/chrome/browser/ui/browser_close_unittest.cc b/chrome/browser/ui/browser_close_unittest.cc index 06a060b..4a955ad36 100644 --- a/chrome/browser/ui/browser_close_unittest.cc +++ b/chrome/browser/ui/browser_close_unittest.cc
@@ -70,7 +70,7 @@ #endif bool HasCreatedDownloadManager() override { return true; } - int NonMaliciousDownloadCount() const override { return download_count_; } + int BlockingShutdownCount() const override { return download_count_; } void CancelDownloads() override {}
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc index 51e1aa0..3710d18 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
@@ -525,8 +525,14 @@ ShowAndVerifyUi(); } +// TODO(crbug.com/1445932): Flaky on Win10. +#if BUILDFLAG(IS_WIN) +#define MAYBE_InvokeUi_AllInfoTypes DISABLED_InvokeUi_AllInfoTypes +#else +#define MAYBE_InvokeUi_AllInfoTypes InvokeUi_AllInfoTypes +#endif IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest, - InvokeUi_AllInfoTypes) { + MAYBE_InvokeUi_AllInfoTypes) { AddPermission("Example permission"); AddPermissionWithDetails( "This permission has details",
diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.cc b/chrome/browser/ui/views/page_info/page_info_view_factory.cc index b9bcb9a2..2fe9a3a 100644 --- a/chrome/browser/ui/views/page_info/page_info_view_factory.cc +++ b/chrome/browser/ui/views/page_info/page_info_view_factory.cc
@@ -542,6 +542,11 @@ // static const ui::ImageModel PageInfoViewFactory::GetInvalidCertificateIcon() { + if (features::IsChromeRefresh2023()) { + return ui::ImageModel::FromVectorIcon( + vector_icons::kCertificateOffChromeRefreshIcon, ui::kColorIcon, + GetIconSize()); + } return ui::ImageModel::FromVectorIcon(vector_icons::kCertificateIcon, ui::kColorIcon, GetIconSize(), &vector_icons::kBlockedBadgeIcon); @@ -552,7 +557,7 @@ return ui::ImageModel::FromVectorIcon( features::IsChromeRefresh2023() ? vector_icons::kSettingsChromeRefreshIcon : vector_icons::kSettingsIcon, - ui::kColorIcon); + ui::kColorIcon, GetIconSize()); } // static @@ -570,15 +575,10 @@ } // static -const ui::ImageModel PageInfoViewFactory::GetSidePanelIcon() { - return ui::ImageModel::FromVectorIcon(kSidePanelIcon, ui::kColorIconSecondary, - GetIconSize()); -} - -// static const ui::ImageModel PageInfoViewFactory::GetConnectionNotSecureIcon() { return ui::ImageModel::FromVectorIcon(vector_icons::kNotSecureWarningIcon, - ui::kColorAlertHighSeverity); + ui::kColorAlertHighSeverity, + GetIconSize()); } // static
diff --git a/chrome/browser/ui/views/page_info/page_info_view_factory.h b/chrome/browser/ui/views/page_info/page_info_view_factory.h index 3ab4c33f..1195c8073 100644 --- a/chrome/browser/ui/views/page_info/page_info_view_factory.h +++ b/chrome/browser/ui/views/page_info/page_info_view_factory.h
@@ -99,9 +99,6 @@ // cookies dialog or site settings page). static const ui::ImageModel GetLaunchIcon(); - // Returns the icon for the side panel. - static const ui::ImageModel GetSidePanelIcon(); - // Returns the not secure state icon for the SecurityInformationView. static const ui::ImageModel GetConnectionNotSecureIcon();
diff --git a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc index 3c10c9d2..5b12b45 100644 --- a/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc +++ b/chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view_browsertest.cc
@@ -54,6 +54,13 @@ #include "ui/views/test/ax_event_counter.h" #include "ui/views/test/button_test_api.h" +// To run the pixel tests of this file run: browser_tests +// --gtest_filter=BrowserUiTest.Invoke --test-launcher-interactive +// --enable-pixel-output-in-tests --ui=<test name e.g. +// PermissionPromptBubbleBaseViewBrowserTest>.* +// +// Check go/brapp-desktop-pixel-tests for more info. + namespace { // Test implementation of PermissionUiSelector that always returns a canned // decision. @@ -88,11 +95,13 @@ public: PermissionPromptBubbleBaseViewBrowserTest() { if (GetParam()) { - feature_list_.InitWithFeatures({permissions::features::kPermissionChip}, - {}); + feature_list_.InitWithFeatures( + {permissions::features::kPermissionChip}, + {permissions::features::kPermissionStorageAccessAPI}); } else { - feature_list_.InitWithFeatures({}, - {permissions::features::kPermissionChip}); + feature_list_.InitWithFeatures( + {}, {permissions::features::kPermissionChip, + permissions::features::kPermissionStorageAccessAPI}); } } @@ -201,6 +210,17 @@ } permissions::PermissionRequestManager* manager = test_api_->manager(); content::RenderFrameHost* source_frame = GetActiveMainFrame(); + + // Pixel verification for storage_access test checks a permission + // request prompt that has an origin and port. Because these tests run + // on localhost, the port changes, and the test pixel verification + // fails. We need a fixed URL, so the Gold image used in the pixel test + // always matches with the output of the test. + if (it->type == ContentSettingsType::STORAGE_ACCESS) { + test_api_->manager()->set_embedding_origin_for_testing( + GURL("https://test.com")); + } + switch (it->type) { case ContentSettingsType::PROTOCOL_HANDLERS: manager->AddRequest(source_frame, MakeRegisterProtocolHandlerRequest()); @@ -392,14 +412,9 @@ ShowAndVerifyUi(); } -// TODO(crbug.com/1232028): Pixel verification for storage_access test checks -// permission request prompt that has origin and port. Because these tests run -// on localhost, the port constantly changes its value and hence test pixel -// verification fails. Host wants to access storage from the site in which it's -// embedded. // Host wants to access storage from the site in which it's embedded. IN_PROC_BROWSER_TEST_P(PermissionPromptBubbleBaseViewBrowserTest, - DISABLED_InvokeUi_storage_access) { + InvokeUi_storage_access) { ShowAndVerifyUi(); } @@ -421,6 +436,39 @@ ShowAndVerifyUi(); } +// Test fixture to test the Storage Access prompt with the new Google UI. +// +// We have created a new test fixture for the new Google UI so we can have a +// test for the new and old prompt UI and avoid adding unnecessary Gold images. +// If were to add a new parameter to |PermissionPromptBubbleBaseViewBrowserTest| +// to toggle the PermissionStorageAccessAPI, we would have to add extra Gold +// images for each of the other eleven tests, even though this flag only affects +// the SAA prompt. +class SAAEnabledPermissionPromptBubbleViewBrowserTest + : public PermissionPromptBubbleBaseViewBrowserTest { + public: + SAAEnabledPermissionPromptBubbleViewBrowserTest() { + if (GetParam()) { + feature_list_.InitWithFeatures( + {permissions::features::kPermissionStorageAccessAPI, + permissions::features::kPermissionChip}, + {}); + } else { + feature_list_.InitWithFeatures( + {permissions::features::kPermissionStorageAccessAPI}, + {permissions::features::kPermissionChip}); + } + } + base::test::ScopedFeatureList feature_list_; +}; + +// Host wants to access storage from the site in which it's embedded. Prompt +// with new Google UI. +IN_PROC_BROWSER_TEST_P(SAAEnabledPermissionPromptBubbleViewBrowserTest, + InvokeUi_storage_access) { + ShowAndVerifyUi(); +} + class QuietUIPromoBrowserTest : public PermissionPromptBubbleBaseViewBrowserTest { public: @@ -991,6 +1039,9 @@ PermissionPromptBubbleBaseViewBrowserTest, ::testing::Values(false, true)); INSTANTIATE_TEST_SUITE_P(All, + SAAEnabledPermissionPromptBubbleViewBrowserTest, + ::testing::Values(false, true)); +INSTANTIATE_TEST_SUITE_P(All, PermissionPromptBubbleBaseViewQuietUiBrowserTest, ::testing::Values(false, true)); INSTANTIATE_TEST_SUITE_P(All,
diff --git a/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc b/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc index ecf4f549..c08ccc1 100644 --- a/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc +++ b/chrome/browser/ui/views/profiles/profile_picker_interactive_uitest.cc
@@ -356,6 +356,6 @@ // Navigate back with the keyboard. SendBackKeyboardCommand(); - WaitForLoadStop(GURL("chrome://profile-picker")); + WaitForLoadStop(GURL("chrome://profile-picker"), web_contents()); EXPECT_EQ(0, web_contents()->GetController().GetLastCommittedEntryIndex()); }
diff --git a/chrome/browser/web_applications/DEPS b/chrome/browser/web_applications/DEPS index 242c13f..b15f1b0 100644 --- a/chrome/browser/web_applications/DEPS +++ b/chrome/browser/web_applications/DEPS
@@ -9,5 +9,6 @@ "+mojo/public/cpp/bindings", "+services/network/public/cpp", "+third_party/blink/public/common", + "+third_party/liburlpattern", "+url", }
diff --git a/chrome/browser/web_applications/proto/BUILD.gn b/chrome/browser/web_applications/proto/BUILD.gn index f3d25488..dcb3712 100644 --- a/chrome/browser/web_applications/proto/BUILD.gn +++ b/chrome/browser/web_applications/proto/BUILD.gn
@@ -13,6 +13,7 @@ "web_app_share_target.proto", "web_app_tab_strip.proto", "web_app_translations.proto", + "web_app_url_pattern.proto", ] link_deps = [ "//chrome/browser/ash/system_web_apps/types/proto",
diff --git a/chrome/browser/web_applications/proto/web_app_tab_strip.proto b/chrome/browser/web_applications/proto/web_app_tab_strip.proto index 55d20bf..ee7aef5a 100644 --- a/chrome/browser/web_applications/proto/web_app_tab_strip.proto +++ b/chrome/browser/web_applications/proto/web_app_tab_strip.proto
@@ -5,6 +5,7 @@ syntax = "proto2"; import "content/browser/background_fetch/background_fetch.proto"; +import "chrome/browser/web_applications/proto/web_app_url_pattern.proto"; option optimize_for = LITE_RUNTIME; @@ -12,6 +13,7 @@ message HomeTabParams { repeated content.proto.ImageResource icons = 1; + repeated UrlPattern scope_patterns = 2; } message NewTabButtonParams {
diff --git a/chrome/browser/web_applications/proto/web_app_url_pattern.proto b/chrome/browser/web_applications/proto/web_app_url_pattern.proto new file mode 100644 index 0000000..0c9c771 --- /dev/null +++ b/chrome/browser/web_applications/proto/web_app_url_pattern.proto
@@ -0,0 +1,39 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package web_app.proto; + +// Proto represtenting a UrlPattern. This should be kept up to date with +// third_party/blink/public/common/url_pattern.h +message UrlPattern { + repeated UrlPatternPart pathname = 1; +} + +message UrlPatternPart { + enum PartType { + UNKNOWN_PART_TYPE = 0; + FULL_WILDCARD = 1; + SEGMENT_WILDCARD = 2; + FIXED = 3; + } + optional PartType part_type = 1; + + optional string name = 2; + optional string prefix = 3; + optional string value = 4; + optional string suffix = 5; + + enum Modifier { + UNKNOWN_MODIFIER = 0; + ZERO_OR_MORE = 1; + OPTIONAL = 2; + ONE_OR_MORE = 3; + NONE = 4; + } + optional Modifier modifier = 6; +}
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc index 3cffcd9..8620373 100644 --- a/chrome/browser/web_applications/test/web_app_test_utils.cc +++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -71,7 +71,9 @@ #include "third_party/blink/public/common/permissions_policy/permissions_policy.h" #include "third_party/blink/public/common/permissions_policy/policy_helper_public.h" #include "third_party/blink/public/common/storage_key/storage_key.h" +#include "third_party/blink/public/common/url_pattern.h" #include "third_party/blink/public/mojom/manifest/capture_links.mojom-shared.h" +#include "third_party/liburlpattern/pattern.h" #include "third_party/skia/include/core/SkColor.h" #include "url/gurl.h" #include "url/origin.h" @@ -383,6 +385,42 @@ return icons; } +std::vector<blink::UrlPattern> CreateRandomScopePatterns(RandomHelper& random) { + std::vector<blink::UrlPattern> scope_patterns; + + for (int i = random.next_uint(4) + 1; i >= 0; --i) { + blink::UrlPattern url_pattern; + + for (int j = random.next_uint(4) + 1; j >= 0; --j) { + liburlpattern::Part part; + + std::vector<liburlpattern::PartType> part_types = { + liburlpattern::PartType::kFixed, + liburlpattern::PartType::kFullWildcard, + liburlpattern::PartType::kSegmentWildcard}; + std::vector<liburlpattern::Modifier> modifiers = { + liburlpattern::Modifier::kZeroOrMore, + liburlpattern::Modifier::kOptional, + liburlpattern::Modifier::kOneOrMore, liburlpattern::Modifier::kNone}; + part.type = part_types[random.next_uint(part_types.size())]; + part.value = "value" + base::NumberToString(j); + if (part.type == liburlpattern::PartType::kFullWildcard || + part.type == liburlpattern::PartType::kSegmentWildcard) { + part.prefix = "prefix" + base::NumberToString(j); + part.name = "name" + base::NumberToString(j); + part.suffix = "suffix" + base::NumberToString(j); + } + + part.modifier = modifiers[random.next_uint(modifiers.size())]; + + url_pattern.pathname.push_back(std::move(part)); + } + + scope_patterns.push_back(std::move(url_pattern)); + } + return scope_patterns; +} + proto::WebAppOsIntegrationState GenerateRandomWebAppOsIntegrationState( RandomHelper& random, WebApp& app) { @@ -828,6 +866,9 @@ if (random.next_bool()) { home_tab_params.icons = CreateRandomHomeTabIcons(random); } + if (random.next_bool()) { + home_tab_params.scope_patterns = CreateRandomScopePatterns(random); + } tab_strip.home_tab = std::move(home_tab_params); } else { tab_strip.home_tab =
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index d7a0a510..fbc1eab 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -566,6 +566,8 @@ // like is_placeholder and install URLs. ExternalConfigMap management_to_external_config_map_; + // TODO(crbug.com/1381374): Add to AsDebugValue() and + // GetManifestDataChanges(). absl::optional<blink::Manifest::TabStrip> tab_strip_; // Only used on Mac.
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc index 803630c..41a79c4 100644 --- a/chrome/browser/web_applications/web_app_database.cc +++ b/chrome/browser/web_applications/web_app_database.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" #include "chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h" #include "chrome/browser/web_applications/proto/web_app.pb.h" +#include "chrome/browser/web_applications/proto/web_app_url_pattern.pb.h" #include "chrome/browser/web_applications/user_display_mode.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_chromeos_data.h" @@ -44,8 +45,10 @@ #include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/blink/public/common/permissions_policy/origin_with_possible_wildcards.h" #include "third_party/blink/public/common/permissions_policy/policy_helper_public.h" +#include "third_party/blink/public/common/url_pattern.h" #include "third_party/blink/public/mojom/manifest/capture_links.mojom.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom.h" +#include "third_party/blink/public/mojom/url_pattern.mojom.h" #include "url/gurl.h" #include "url/origin.h" @@ -303,16 +306,6 @@ } } -TabStrip::Visibility ProtoToTabStripVisibility( - proto::TabStrip::Visibility visibility) { - switch (visibility) { - case proto::TabStrip_Visibility_AUTO: - return TabStrip::Visibility::kAuto; - case proto::TabStrip_Visibility_ABSENT: - return TabStrip::Visibility::kAbsent; - } -} - std::string FilePathToProto(const base::FilePath& path) { base::Pickle pickle; path.WriteToPickle(&pickle); @@ -772,12 +765,21 @@ } else { auto* mutable_home_tab_params = mutable_tab_strip->mutable_home_tab_params(); - absl::optional<std::vector<blink::Manifest::ImageResource>> icons = + + const absl::optional<std::vector<blink::Manifest::ImageResource>>& icons = absl::get<blink::Manifest::HomeTabParams>(tab_strip.home_tab).icons; for (const auto& image_resource : *icons) { *(mutable_home_tab_params->add_icons()) = AppImageResourceToProto(image_resource); } + + const std::vector<blink::UrlPattern>& scope_patterns = + absl::get<blink::Manifest::HomeTabParams>(tab_strip.home_tab) + .scope_patterns; + for (const auto& pattern : scope_patterns) { + *(mutable_home_tab_params->add_scope_patterns()) = + ToUrlPatternProto(pattern); + } } if (absl::holds_alternative<TabStrip::Visibility>( @@ -1478,33 +1480,7 @@ web_app->SetWebAppManagementExternalConfigMap(management_to_external_config); if (local_data.has_tab_strip()) { - TabStrip tab_strip; - if (local_data.tab_strip().has_home_tab_visibility()) { - tab_strip.home_tab = ProtoToTabStripVisibility( - local_data.tab_strip().home_tab_visibility()); - } else { - absl::optional<std::vector<blink::Manifest::ImageResource>> icons = - ParseAppImageResource( - "WebApp", local_data.tab_strip().home_tab_params().icons()); - blink::Manifest::HomeTabParams home_tab_params; - if (!icons->empty()) { - home_tab_params.icons = std::move(*icons); - } - tab_strip.home_tab = std::move(home_tab_params); - } - - if (local_data.tab_strip().has_new_tab_button_visibility()) { - tab_strip.new_tab_button = ProtoToTabStripVisibility( - local_data.tab_strip().new_tab_button_visibility()); - } else { - blink::Manifest::NewTabButtonParams new_tab_button_params; - if (local_data.tab_strip().new_tab_button_params().has_url()) { - new_tab_button_params.url = - GURL(local_data.tab_strip().new_tab_button_params().url()); - } - tab_strip.new_tab_button = new_tab_button_params; - } - web_app->SetTabStrip(std::move(tab_strip)); + web_app->SetTabStrip(ProtoToTabStrip(local_data.tab_strip())); } if (local_data.has_current_os_integration_states()) {
diff --git a/chrome/browser/web_applications/web_app_proto_utils.cc b/chrome/browser/web_applications/web_app_proto_utils.cc index 4cb6695..7cd03d57 100644 --- a/chrome/browser/web_applications/web_app_proto_utils.cc +++ b/chrome/browser/web_applications/web_app_proto_utils.cc
@@ -5,10 +5,12 @@ #include "chrome/browser/web_applications/web_app_proto_utils.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h" +#include "chrome/browser/web_applications/proto/web_app_url_pattern.pb.h" #include "chrome/browser/web_applications/user_display_mode.h" #include "components/services/app_service/public/cpp/icon_info.h" #include "third_party/blink/public/common/manifest/manifest.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom.h" +#include "third_party/liburlpattern/pattern.h" #include "ui/gfx/geometry/size.h" namespace web_app { @@ -56,6 +58,75 @@ } } +proto::UrlPatternPart::Modifier UrlPatternModifierToProto( + liburlpattern::Modifier modifier) { + switch (modifier) { + case liburlpattern::Modifier::kZeroOrMore: + return proto::UrlPatternPart_Modifier_ZERO_OR_MORE; + case liburlpattern::Modifier::kOptional: + return proto::UrlPatternPart_Modifier_OPTIONAL; + case liburlpattern::Modifier::kOneOrMore: + return proto::UrlPatternPart_Modifier_ONE_OR_MORE; + case liburlpattern::Modifier::kNone: + return proto::UrlPatternPart_Modifier_NONE; + } +} + +absl::optional<liburlpattern::Modifier> ProtoToUrlPatternModifier( + proto::UrlPatternPart::Modifier modifier) { + switch (modifier) { + case proto::UrlPatternPart_Modifier_UNKNOWN_MODIFIER: + return absl::nullopt; + case proto::UrlPatternPart_Modifier_ZERO_OR_MORE: + return liburlpattern::Modifier::kZeroOrMore; + case proto::UrlPatternPart_Modifier_OPTIONAL: + return liburlpattern::Modifier::kOptional; + case proto::UrlPatternPart_Modifier_ONE_OR_MORE: + return liburlpattern::Modifier::kOneOrMore; + case proto::UrlPatternPart_Modifier_NONE: + return liburlpattern::Modifier::kNone; + } +} + +proto::UrlPatternPart::PartType UrlPatternPartTypeToProto( + liburlpattern::PartType part_type) { + switch (part_type) { + case liburlpattern::PartType::kRegex: + NOTREACHED(); + [[fallthrough]]; + case liburlpattern::PartType::kFullWildcard: + return proto::UrlPatternPart_PartType_FULL_WILDCARD; + case liburlpattern::PartType::kSegmentWildcard: + return proto::UrlPatternPart_PartType_SEGMENT_WILDCARD; + case liburlpattern::PartType::kFixed: + return proto::UrlPatternPart_PartType_FIXED; + } +} + +absl::optional<liburlpattern::PartType> ProtoToUrlPatternPartType( + proto::UrlPatternPart::PartType part_type) { + switch (part_type) { + case proto::UrlPatternPart_PartType_UNKNOWN_PART_TYPE: + return absl::nullopt; + case proto::UrlPatternPart_PartType_FULL_WILDCARD: + return liburlpattern::PartType::kFullWildcard; + case proto::UrlPatternPart_PartType_SEGMENT_WILDCARD: + return liburlpattern::PartType::kSegmentWildcard; + case proto::UrlPatternPart_PartType_FIXED: + return liburlpattern::PartType::kFixed; + } +} + +TabStrip::Visibility ProtoToTabStripVisibility( + proto::TabStrip::Visibility visibility) { + switch (visibility) { + case proto::TabStrip_Visibility_AUTO: + return TabStrip::Visibility::kAuto; + case proto::TabStrip_Visibility_ABSENT: + return TabStrip::Visibility::kAbsent; + } +} + } // namespace absl::optional<std::vector<apps::IconInfo>> ParseAppIconInfos( @@ -297,4 +368,118 @@ } } +absl::optional<blink::UrlPattern> ToUrlPattern( + const proto::UrlPattern& proto_url_pattern) { + blink::UrlPattern url_pattern; + + for (const proto::UrlPatternPart& proto_part : proto_url_pattern.pathname()) { + liburlpattern::Part part; + + if (!proto_part.has_part_type()) { + DLOG(ERROR) << "WebApp UrlPattern Part has missing type"; + continue; + } + absl::optional<liburlpattern::PartType> opt_part_type = + ProtoToUrlPatternPartType(proto_part.part_type()); + if (!opt_part_type.has_value()) { + return absl::nullopt; + } + part.type = opt_part_type.value(); + + if (!proto_part.has_value()) { + DLOG(ERROR) << "WebApp UrlPattern Part has missing value"; + continue; + } + part.value = proto_part.value(); + + if (!proto_part.has_modifier()) { + DLOG(ERROR) << "WebApp UrlPattern Part has missing type"; + continue; + } + + absl::optional<liburlpattern::Modifier> opt_modifier = + ProtoToUrlPatternModifier(proto_part.modifier()); + if (!opt_modifier.has_value()) { + return absl::nullopt; + } + part.modifier = opt_modifier.value(); + + if (proto_part.has_name()) { + part.name = proto_part.name(); + } + + if (proto_part.has_prefix()) { + part.prefix = proto_part.prefix(); + } + + if (proto_part.has_suffix()) { + part.suffix = proto_part.suffix(); + } + + url_pattern.pathname.push_back(std::move(part)); + } + return url_pattern; +} + +proto::UrlPattern ToUrlPatternProto(const blink::UrlPattern& url_pattern) { + proto::UrlPattern url_pattern_proto; + for (const auto& part : url_pattern.pathname) { + proto::UrlPatternPart* url_pattern_part_proto = + url_pattern_proto.add_pathname(); + + url_pattern_part_proto->set_name(part.name); + url_pattern_part_proto->set_prefix(part.prefix); + url_pattern_part_proto->set_value(part.value); + url_pattern_part_proto->set_suffix(part.suffix); + + url_pattern_part_proto->set_part_type(UrlPatternPartTypeToProto(part.type)); + url_pattern_part_proto->set_modifier( + UrlPatternModifierToProto(part.modifier)); + } + return url_pattern_proto; +} + +absl::optional<TabStrip> ProtoToTabStrip(proto::TabStrip tab_strip_proto) { + TabStrip tab_strip; + if (tab_strip_proto.has_home_tab_visibility()) { + tab_strip.home_tab = + ProtoToTabStripVisibility(tab_strip_proto.home_tab_visibility()); + } else { + absl::optional<std::vector<blink::Manifest::ImageResource>> icons = + ParseAppImageResource("WebApp", + tab_strip_proto.home_tab_params().icons()); + blink::Manifest::HomeTabParams home_tab_params; + if (!icons->empty()) { + home_tab_params.icons = std::move(*icons); + } + + std::vector<blink::UrlPattern> scope_patterns; + for (const proto::UrlPattern& proto_url_pattern : + tab_strip_proto.home_tab_params().scope_patterns()) { + absl::optional<blink::UrlPattern> url_pattern = + ToUrlPattern(proto_url_pattern); + if (!url_pattern) { + return absl::nullopt; + } + scope_patterns.push_back(url_pattern.value()); + } + home_tab_params.scope_patterns = std::move(scope_patterns); + + tab_strip.home_tab = std::move(home_tab_params); + } + + if (tab_strip_proto.has_new_tab_button_visibility()) { + tab_strip.new_tab_button = + ProtoToTabStripVisibility(tab_strip_proto.new_tab_button_visibility()); + } else { + blink::Manifest::NewTabButtonParams new_tab_button_params; + if (tab_strip_proto.new_tab_button_params().has_url()) { + new_tab_button_params.url = + GURL(tab_strip_proto.new_tab_button_params().url()); + } + tab_strip.new_tab_button = new_tab_button_params; + } + return tab_strip; +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_proto_utils.h b/chrome/browser/web_applications/web_app_proto_utils.h index a07227e..70f01aa 100644 --- a/chrome/browser/web_applications/web_app_proto_utils.h +++ b/chrome/browser/web_applications/web_app_proto_utils.h
@@ -8,10 +8,13 @@ #include <vector> #include "chrome/browser/web_applications/proto/web_app.pb.h" +#include "chrome/browser/web_applications/proto/web_app_tab_strip.pb.h" +#include "chrome/browser/web_applications/proto/web_app_url_pattern.pb.h" #include "chrome/browser/web_applications/web_app.h" #include "components/sync/protocol/web_app_specifics.pb.h" #include "content/browser/background_fetch/background_fetch.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/blink/public/common/url_pattern.h" namespace apps { struct IconInfo; @@ -56,6 +59,13 @@ WebAppProto::RunOnOsLoginMode ToWebAppProtoRunOnOsLoginMode( RunOnOsLoginMode mode); +absl::optional<blink::UrlPattern> ToUrlPattern( + const proto::UrlPattern& proto_url_pattern); + +proto::UrlPattern ToUrlPatternProto(const blink::UrlPattern& url_pattern); + +absl::optional<TabStrip> ProtoToTabStrip(proto::TabStrip tab_strip_proto); + } // namespace web_app #endif // CHROME_BROWSER_WEB_APPLICATIONS_WEB_APP_PROTO_UTILS_H_
diff --git a/chrome/browser/webapps/chrome_webapps_client.cc b/chrome/browser/webapps/chrome_webapps_client.cc index 58ec9b4ce..daa2036 100644 --- a/chrome/browser/webapps/chrome_webapps_client.cc +++ b/chrome/browser/webapps/chrome_webapps_client.cc
@@ -124,14 +124,14 @@ const AddToHomescreenParams& params) { WebApkInstallService::Get(web_contents->GetBrowserContext()) ->InstallAsync(web_contents, *(params.shortcut_info), params.primary_icon, - params.install_source); + params.has_maskable_primary_icon, params.install_source); } void ChromeWebappsClient::InstallShortcut(content::WebContents* web_contents, const AddToHomescreenParams& params) { ShortcutHelper::AddToLauncherWithSkBitmap( web_contents, *(params.shortcut_info), params.primary_icon, - params.installable_status); + params.has_maskable_primary_icon, params.installable_status); } #endif
diff --git a/chrome/build/lacros64.pgo.txt b/chrome/build/lacros64.pgo.txt index bf92d0e..28635b0 100644 --- a/chrome/build/lacros64.pgo.txt +++ b/chrome/build/lacros64.pgo.txt
@@ -1 +1 @@ -chrome-chromeos-amd64-generic-main-1684222389-4cccd1a0238dc9ad21cc26fc40bb48c46ecc1676.profdata +chrome-chromeos-amd64-generic-main-1684238305-67e703eebc674e27cfd18eeee9a65bedd8b0c6ea.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index deab470..0fd716c 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1684195193-fbdc55d5154807568d02315c57541555acc532bd.profdata +chrome-linux-main-1684238305-c74cc53a26c07efc7f473ec1f137e865f8b79bdd.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 9bab22db..cadf1fab 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1684231006-5f5b1446b0ae08e07fd74df439b90db1c89e1b77.profdata +chrome-mac-arm-main-1684238305-015cc1100fc942408ee1e06edc1cb3541f37f19a.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index c473194..7c2afed 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1684195193-b4c187bf8e9121bbeb110d40859be58184de6774.profdata +chrome-mac-main-1684216780-5cca681fa1e6a02b822c4c1849c511ecbe2928e3.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 22079e8..f732d35b 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1684184393-526da9f3811b104011ec67450d3b02ef142772c3.profdata +chrome-win32-main-1684238305-2a63b520bb0d5d080c622cf0086ad58390bd4ce7.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 5d0b5328..99f5e89 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1684184393-13c8972f1e5c50e286e979c9beaadb5b256b00fb.profdata +chrome-win64-main-1684238305-a18062c95fa512af8d4658eb05585df102a38775.profdata
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index f299b70..2ced632 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -653,6 +653,16 @@ return "div"; } + // Some divs are marked with role=heading and aria-level=# to indicate + // the heading level, so use the <h#> tag directly. + if (ax_node->GetRole() == ax::mojom::Role::kHeading) { + std::string aria_level; + ax_node->GetHtmlAttribute("aria-level", &aria_level); + if (!aria_level.empty()) { + return "h" + aria_level; + } + } + // Replace mark element with bold element for readability std::string html_tag = ax_node->GetStringAttribute(ax::mojom::StringAttribute::kHtmlTag);
diff --git a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc index 8b426c6..171e3371 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller_browsertest.cc
@@ -414,6 +414,23 @@ EXPECT_EQ(div, GetHtmlTag(4)); } +TEST_F(ReadAnythingAppControllerTest, + GetHtmlTag_DivWithHeadingAndAriaLevelReturnsH) { + std::string h3 = "h3"; + std::string div = "div"; + ui::AXTreeUpdate update; + SetUpdateTreeID(&update); + update.nodes.resize(3); + update.nodes[0].id = 2; + update.nodes[1].id = 3; + update.nodes[2].id = 4; + update.nodes[1].role = ax::mojom::Role::kHeading; + update.nodes[1].html_attributes.emplace_back("aria-level", "3"); + AccessibilityEventReceived({update}); + OnAXTreeDistilled({}); + EXPECT_EQ(h3, GetHtmlTag(3)); +} + TEST_F(ReadAnythingAppControllerTest, GetTextContent_NoSelection) { std::string text_content = "Hello"; std::string missing_text_content = "";
diff --git a/chrome/test/base/browser_tests_main_chromeos.cc b/chrome/test/base/browser_tests_main_chromeos.cc index 3b0c6fb..35ebb3a 100644 --- a/chrome/test/base/browser_tests_main_chromeos.cc +++ b/chrome/test/base/browser_tests_main_chromeos.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/test/ui_controls_factory_ash.h" +#include "ash/test/ui_controls_ash.h" #include "base/command_line.h" #include "base/test/launcher/test_launcher.h" #include "chrome/test/base/chrome_test_launcher.h" @@ -12,7 +12,7 @@ // This class is introduced to provide ui_controls since some test cases use // it. Ideally such tests should be moved into interactive_ui_tests. -// TODO(mukai): remove this after moving such tests. +// TODO(1445328): remove this after moving such tests. class BrowserTestSuiteChromeOS : public ChromeTestSuite { public: BrowserTestSuiteChromeOS(int argc, char** argv) @@ -23,7 +23,7 @@ // ChromeTestSuite overrides: void Initialize() override { ChromeTestSuite::Initialize(); - ui_controls::InstallUIControlsAura(ash::test::CreateAshUIControls()); + ash::test::EnableUIControlsAsh(); } };
diff --git a/chrome/test/base/chrome_test_launcher.cc b/chrome/test/base/chrome_test_launcher.cc index 6c6a81f..117bd52 100644 --- a/chrome/test/base/chrome_test_launcher.cc +++ b/chrome/test/base/chrome_test_launcher.cc
@@ -42,18 +42,12 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/service_factory.h" #include "services/test/echo/echo_service.h" -#include "ui/base/test/ui_controls.h" #if BUILDFLAG(IS_MAC) #include "base/apple/bundle_locations.h" #include "chrome/browser/chrome_browser_application_mac.h" #endif // BUILDFLAG(IS_MAC) -#if defined(USE_AURA) -#include "ui/aura/test/ui_controls_factory_aura.h" -#include "ui/base/test/ui_controls_aura.h" -#endif - #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) #include "chrome/app/chrome_crash_reporter_client.h" #endif
diff --git a/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc b/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc index 042c896..b7b2e05e 100644 --- a/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc +++ b/chrome/test/base/chromeos/fake_ash_test_chrome_browser_main_extra_parts.cc
@@ -4,8 +4,8 @@ #include "fake_ash_test_chrome_browser_main_extra_parts.h" +#include "ash/test/ui_controls_ash.h" #include "ash/multi_device_setup/multi_device_notification_presenter.h" -#include "ash/test/ui_controls_factory_ash.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -16,7 +16,6 @@ #include "chrome/browser/ash/crosapi/test_controller_ash.h" #include "chrome/browser/ash/login/signin/signin_error_notifier.h" #include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h" -#include "ui/base/test/ui_controls.h" #include "ui/views/input_event_activation_protector.h" namespace test { @@ -58,7 +57,8 @@ void FakeAshTestChromeBrowserMainExtraParts::PreBrowserStart() { // These are used by exo's weston-test protocol for event injection. - ui_controls::InstallUIControlsAura(ash::test::CreateAshUIControls()); + // TODO(oshima): Move this to the test protocol side. + ash::test::EnableUIControlsAsh(); } void FakeAshTestChromeBrowserMainExtraParts::PostBrowserStart() {
diff --git a/chrome/test/base/interactive_ui_tests_main.cc b/chrome/test/base/interactive_ui_tests_main.cc index 58a6957..81f7c1c6 100644 --- a/chrome/test/base/interactive_ui_tests_main.cc +++ b/chrome/test/base/interactive_ui_tests_main.cc
@@ -16,18 +16,16 @@ #include "gpu/ipc/service/image_transport_surface.h" #include "ui/base/test/ui_controls.h" -#if defined(USE_AURA) -#include "ui/aura/test/ui_controls_factory_aura.h" -#include "ui/base/test/ui_controls_aura.h" -#if BUILDFLAG(IS_OZONE) +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/test/ui_controls_ash.h" +#elif BUILDFLAG(IS_WIN) +#include "ui/aura/test/ui_controls_aurawin.h" +#endif + +#if defined(USE_AURA) && BUILDFLAG(IS_OZONE) #include "ui/ozone/public/ozone_platform.h" #include "ui/platform_window/common/platform_window_defaults.h" -#endif // BUILDFLAG(IS_OZONE) -#endif // defined(USE_AURA) - -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/test/ui_controls_factory_ash.h" -#endif +#endif // defined(USE_AURA) && BUILDFLAG(IS_OZONE) #if BUILDFLAG(IS_WIN) #include "base/win/scoped_com_initializer.h" @@ -46,11 +44,10 @@ ChromeTestSuite::Initialize(); #if BUILDFLAG(IS_CHROMEOS_ASH) - ui_controls::InstallUIControlsAura(ash::test::CreateAshUIControls()); + ash::test::EnableUIControlsAsh(); #elif BUILDFLAG(IS_WIN) com_initializer_ = std::make_unique<base::win::ScopedCOMInitializer>(); - ui_controls::InstallUIControlsAura( - aura::test::CreateUIControlsAura(nullptr)); + aura::test::EnableUIControlsAuraWin(); #elif BUILDFLAG(IS_OZONE) // Notifies the platform that test config is needed. For Wayland, for // example, makes it possible to use emulated input.
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 7c74869..8854402 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -15460.0.0 \ No newline at end of file +15465.0.0 \ No newline at end of file
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt index 3251af0..33f2dcd 100644 --- a/chromeos/profiles/bigcore.afdo.newest.txt +++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-bigcore-115-5735.18-1684149627-benchmark-115.0.5772.0-r1-redacted.afdo.xz +chromeos-chrome-amd64-bigcore-115-5735.18-1684149627-benchmark-115.0.5773.0-r1-redacted.afdo.xz
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc index 763f4c3..ef8bc37 100644 --- a/components/autofill/content/renderer/autofill_agent.cc +++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -339,6 +339,7 @@ } void AutofillAgent::DidDispatchDOMContentLoadedEvent() { + is_dom_content_loaded_ = true; ProcessFormsUnthrottled(/*callback=*/{}); } @@ -1071,7 +1072,7 @@ void AutofillAgent::ProcessForms(base::OneShotTimer& timer, base::OnceCallback<void(bool)> callback) { static constexpr base::TimeDelta kThrottle = base::Milliseconds(100); - if (timer.IsRunning()) { + if (!is_dom_content_loaded_ || timer.IsRunning()) { if (!callback.is_null()) { std::move(callback).Run(/*success=*/false); }
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h index 97f6fb5..67ed89d 100644 --- a/components/autofill/content/renderer/autofill_agent.h +++ b/components/autofill/content/renderer/autofill_agent.h
@@ -458,6 +458,9 @@ base::OneShotTimer process_forms_reparse_timer_; base::OneShotTimer process_forms_reparse_with_response_timer_; + // True iff DidDispatchDOMContentLoadedEvent() fired. + bool is_dom_content_loaded_ = false; + // Will be set when accessibility mode changes, depending on what the new mode // is. bool is_screen_reader_enabled_ = false;
diff --git a/components/autofill/core/browser/field_types.cc b/components/autofill/core/browser/field_types.cc index 54e38844..dd1bc3d 100644 --- a/components/autofill/core/browser/field_types.cc +++ b/components/autofill/core/browser/field_types.cc
@@ -434,10 +434,8 @@ } ServerFieldType TypeNameToFieldType(base::StringPiece type_name) { - if (kTypeNameToFieldType.contains(type_name)) { - return kTypeNameToFieldType.at(type_name); - } - return UNKNOWN_TYPE; + auto* it = kTypeNameToFieldType.find(type_name); + return it != kTypeNameToFieldType.end() ? it->second : UNKNOWN_TYPE; } std::ostream& operator<<(std::ostream& o, ServerFieldTypeSet field_type_set) {
diff --git a/components/autofill/core/browser/form_data_importer_unittest.cc b/components/autofill/core/browser/form_data_importer_unittest.cc index 95024e9..033d2a0 100644 --- a/components/autofill/core/browser/form_data_importer_unittest.cc +++ b/components/autofill/core/browser/form_data_importer_unittest.cc
@@ -4091,17 +4091,15 @@ // Note that this function doesn't test the removal functionality itself. This // is done in the AutofillProfile unit tests. TEST_P(FormDataImporterTest, RemoveInaccessibleProfileValuesMetrics) { - // Minimal importable profile, but with a state, which is setting-inaccessible - // for Germany. - TypeValuePairs type_value_pairs = {{ADDRESS_HOME_COUNTRY, "DE"}, - {ADDRESS_HOME_LINE1, kDefaultAddressLine1}, - {ADDRESS_HOME_CITY, kDefaultCity}, - {ADDRESS_HOME_ZIP, kDefaultZip}, - {ADDRESS_HOME_STATE, kDefaultState}}; + // State is setting-inaccessible in Germany. Expect that when importing a + // German profile with a state, the state information is removed. + TypeValuePairs type_value_pairs = + GetDefaultProfileTypeValuePairsWithOverriddenCountry("DE"); + ASSERT_EQ(type_value_pairs[6].first, ADDRESS_HOME_STATE); std::unique_ptr<FormStructure> form_structure = ConstructFormStructureFromTypeValuePairs(type_value_pairs); - type_value_pairs.pop_back(); // Remove state manually for verification. + SetValueForType(type_value_pairs, ADDRESS_HOME_STATE, ""); base::HistogramTester histogram_tester; ExtractAddressProfilesAndVerifyExpectation( *form_structure, {ConstructProfileFromTypeValuePairs(type_value_pairs)});
diff --git a/components/autofill/core/browser/manual_testing_import.cc b/components/autofill/core/browser/manual_testing_import.cc index fed01dcd..26ed478 100644 --- a/components/autofill/core/browser/manual_testing_import.cc +++ b/components/autofill/core/browser/manual_testing_import.cc
@@ -49,25 +49,6 @@ {"localOrSyncable", AutofillProfile::Source::kLocalOrSyncable}}); constexpr base::StringPiece kKeyInitialCreatorId = "initial_creator_id"; -using FieldTypeLookupTable = base::flat_map<std::string, ServerFieldType>; - -// Builds a mapping from ServerFieldType's string representation to their -// enum type. E.g, "NAME_FULL" -> NAME_FULL. Only meaningful types are -// considered. -FieldTypeLookupTable MakeFieldTypeLookupTable() { - std::vector<std::pair<std::string, ServerFieldType>> mapping; - mapping.reserve(MAX_VALID_FIELD_TYPE - NAME_FIRST + 1); - // NAME_FIRST is the first meaningful type. - for (std::underlying_type_t<ServerFieldType> type_id = NAME_FIRST; - type_id <= MAX_VALID_FIELD_TYPE; type_id++) { - ServerFieldType type = ToSafeServerFieldType(type_id, UNKNOWN_TYPE); - if (type != UNKNOWN_TYPE) { - mapping.emplace_back(std::string(FieldTypeToStringPiece(type)), type); - } - } - return FieldTypeLookupTable(std::move(mapping)); -} - // Checks if the `profile` is changed by `FinalizeAfterImport()`. See // documentation of `AutofillProfilesFromJSON()` for a rationale. // The return value of `FinalizeAfterImport()` doesn't suffice to check that, @@ -101,15 +82,12 @@ // Given a `dict` of "field-type" : "value" mappings, constructs an // AutofillProfile where each "field-type" is set to the provided "value". -// "field-type"s are converted to ServerFieldTypes using the `lookup_table`. // All verification statuses are set to `kObserved`. Setting them to // `kUserVerified` is problematic, since the data model expects that only root // level (= setting-visible) nodes are user verified. // If a field type cannot be mapped, or if the resulting profile is not // `IsFullyStructuredProfile()`, absl::nullopt is returned. -absl::optional<AutofillProfile> MakeProfile( - const base::Value::Dict& dict, - const FieldTypeLookupTable& lookup_table) { +absl::optional<AutofillProfile> MakeProfile(const base::Value::Dict& dict) { absl::optional<AutofillProfile::Source> source = GetProfileSourceFromDict(dict); if (!source.has_value()) { @@ -130,19 +108,14 @@ return absl::nullopt; } } - if (!lookup_table.contains(key)) { - LOG(ERROR) << "Unknown type " << key << "."; + const ServerFieldType type = TypeNameToFieldType(key); + if (type == UNKNOWN_TYPE || !IsAddressType(AutofillType(type))) { + LOG(ERROR) << "Unknown or non-address type " << key << "."; return absl::nullopt; } - if (ServerFieldType type = lookup_table.at(key); - IsAddressType(AutofillType(type))) { - profile.SetRawInfoWithVerificationStatus( - type, base::UTF8ToUTF16(value.GetString()), - VerificationStatus::kObserved); - } else { - LOG(ERROR) << "Profile description contains non profile-related types."; - return absl::nullopt; - } + profile.SetRawInfoWithVerificationStatus( + type, base::UTF8ToUTF16(value.GetString()), + VerificationStatus::kObserved); } if (!IsFullyStructuredProfile(profile)) { LOG(ERROR) << "Some profile is not fully structured."; @@ -151,8 +124,7 @@ return profile; } -absl::optional<CreditCard> MakeCard(const base::Value::Dict& dict, - const FieldTypeLookupTable& lookup_table) { +absl::optional<CreditCard> MakeCard(const base::Value::Dict& dict) { CreditCard card; // `dict` is a dictionary of std::string -> base::Value. for (const auto [key, value] : dict) { @@ -160,17 +132,13 @@ card.SetNickname(base::UTF8ToUTF16(value.GetString())); continue; } - if (!lookup_table.contains(key)) { - LOG(ERROR) << "Unknown type " << key << "."; + const ServerFieldType type = TypeNameToFieldType(key); + if (type == UNKNOWN_TYPE || + GroupTypeOfServerFieldType(type) != FieldTypeGroup::kCreditCard) { + LOG(ERROR) << "Unknown or non-credit card type " << key << "."; return absl::nullopt; } - if (ServerFieldType type = lookup_table.at(key); - GroupTypeOfServerFieldType(type) == FieldTypeGroup::kCreditCard) { - card.SetRawInfo(type, base::UTF8ToUTF16(value.GetString())); - } else { - LOG(ERROR) << "Credit card description contains non CC-related types."; - return absl::nullopt; - } + card.SetRawInfo(type, base::UTF8ToUTF16(value.GetString())); } if (!card.IsValid()) { LOG(ERROR) << "Some credit card is not valid."; @@ -208,21 +176,18 @@ template <class T> absl::optional<std::vector<T>> DataModelsFromJSON( const base::Value::List* const json_array, - base::RepeatingCallback<absl::optional<T>(const base::Value::Dict&, - const FieldTypeLookupTable&)> + base::RepeatingCallback<absl::optional<T>(const base::Value::Dict&)> to_data_model) { if (!json_array) { return std::vector<T>{}; } - const auto lookup_table = MakeFieldTypeLookupTable(); std::vector<T> data_models; for (const base::Value& json : *json_array) { if (!json.is_dict()) { LOG(ERROR) << "Description is not a dictionary."; return absl::nullopt; } - absl::optional<T> data_model = - to_data_model.Run(json.GetDict(), lookup_table); + absl::optional<T> data_model = to_data_model.Run(json.GetDict()); if (!data_model.has_value()) { return absl::nullopt; }
diff --git a/components/autofill/core/browser/metrics/profile_import_metrics_unittest.cc b/components/autofill/core/browser/metrics/profile_import_metrics_unittest.cc index 500e085..f9feba8 100644 --- a/components/autofill/core/browser/metrics/profile_import_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/profile_import_metrics_unittest.cc
@@ -114,6 +114,8 @@ // 'perfect' profile import. TEST_F(AutofillProfileImportMetricsTest, ProfileImportRequirements_AllFulfilled) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillRequireNameForProfileImport); // Set up our form data. FormData form = GetAndAddSeenForm( {.description_for_logging = "ProfileImportRequirements_AllFulfilled", @@ -158,7 +160,7 @@ {AddressImportRequirements::kLine1RequirementViolated, false}, {AddressImportRequirements::kZipOrStateRequirementFulfilled, true}, {AddressImportRequirements::kZipOrStateRequirementViolated, false}, - {AddressImportRequirements::kNameRequirementFulfilled, false}, + {AddressImportRequirements::kNameRequirementFulfilled, true}, {AddressImportRequirements::kNameRequirementViolated, false}}; TestAddressProfileImportRequirements(&histogram_tester, expectations); @@ -240,6 +242,8 @@ // 'perfect' profile import. TEST_F(AutofillProfileImportMetricsTest, ProfileImportRequirements_AllFulfilledForNonStateCountry) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillRequireNameForProfileImport); // Set up our form data. FormData form = test::GetFormData( {.description_for_logging = @@ -292,7 +296,7 @@ {AddressImportRequirements::kLine1RequirementViolated, false}, {AddressImportRequirements::kZipOrStateRequirementFulfilled, true}, {AddressImportRequirements::kZipOrStateRequirementViolated, false}, - {AddressImportRequirements::kNameRequirementFulfilled, false}, + {AddressImportRequirements::kNameRequirementFulfilled, true}, {AddressImportRequirements::kNameRequirementViolated, false}}; TestAddressProfileImportRequirements(&histogram_tester, expectations); @@ -306,6 +310,8 @@ // completely filled profile but with invalid values. TEST_F(AutofillProfileImportMetricsTest, ProfileImportRequirements_FilledButInvalidZipEmailAndState) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillRequireNameForProfileImport); // Set up our form data. test::FormDescription form_description = { .description_for_logging = @@ -353,7 +359,7 @@ {AddressImportRequirements::kLine1RequirementViolated, false}, {AddressImportRequirements::kZipOrStateRequirementFulfilled, true}, {AddressImportRequirements::kZipOrStateRequirementViolated, false}, - {AddressImportRequirements::kNameRequirementFulfilled, false}, + {AddressImportRequirements::kNameRequirementFulfilled, true}, {AddressImportRequirements::kNameRequirementViolated, false}}; TestAddressProfileImportRequirements(&histogram_tester, expectations); @@ -368,6 +374,8 @@ // profile with multiple email addresses. TEST_F(AutofillProfileImportMetricsTest, ProfileImportRequirements_NonUniqueEmail) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeature(features::kAutofillRequireNameForProfileImport); // Set up our form data. FormData form = test::GetFormData( {.description_for_logging = "ProfileImportRequirements_NonUniqueEmail", @@ -424,7 +432,7 @@ {AddressImportRequirements::kLine1RequirementViolated, false}, {AddressImportRequirements::kZipOrStateRequirementFulfilled, true}, {AddressImportRequirements::kZipOrStateRequirementViolated, false}, - {AddressImportRequirements::kNameRequirementFulfilled, false}, + {AddressImportRequirements::kNameRequirementFulfilled, true}, {AddressImportRequirements::kNameRequirementViolated, false}}; TestAddressProfileImportRequirements(&histogram_tester, expectations);
diff --git a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc index 21bd626..d55ed9e 100644 --- a/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc +++ b/components/autofill/core/browser/payments/credit_card_save_manager_unittest.cc
@@ -1646,14 +1646,11 @@ // permanently if the test doesn't apply to iOS flow. #if !BUILDFLAG(IS_IOS) TEST_F(CreditCardSaveManagerTest, UploadCreditCard_NoNameAvailable) { - // Create, fill and submit an address form in order to establish a recent - // profile which can be selected for the upload request. - FormData address_form; - test::CreateTestAddressFormData(&address_form); - FormsSeen(std::vector<FormData>(1, address_form)); - // But omit the name: - ManuallyFillAddressForm("", "", "77401", "US", &address_form); - FormSubmitted(address_form); + // Add a profile without a name to the PersonalDataManager. + AutofillProfile profile; + profile.SetRawInfo(ADDRESS_HOME_ZIP, u"77401"); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US"); + personal_data().AddProfile(profile); // Set up our credit card form data. FormData credit_card_form; @@ -3851,14 +3848,11 @@ #if !BUILDFLAG(IS_IOS) TEST_F(CreditCardSaveManagerTest, UploadCreditCard_PaymentsDecidesOfferToSaveIfNoName) { - // Create, fill and submit an address form in order to establish a recent - // profile which can be selected for the upload request. - FormData address_form; - test::CreateTestAddressFormData(&address_form); - FormsSeen(std::vector<FormData>(1, address_form)); - // But omit the name: - ManuallyFillAddressForm("", "", "77401", "US", &address_form); - FormSubmitted(address_form); + // Add a profile without a name to the PersonalDataManager. + AutofillProfile profile; + profile.SetRawInfo(ADDRESS_HOME_ZIP, u"77401"); + profile.SetRawInfo(ADDRESS_HOME_COUNTRY, u"US"); + personal_data().AddProfile(profile); // Set up our credit card form data. FormData credit_card_form;
diff --git a/components/bookmarks/browser/BUILD.gn b/components/bookmarks/browser/BUILD.gn index b751de7..bd2ce0d 100644 --- a/components/bookmarks/browser/BUILD.gn +++ b/components/bookmarks/browser/BUILD.gn
@@ -17,7 +17,6 @@ "bookmark_node.h", "bookmark_node_data.h", "bookmark_storage.h", - "bookmark_undo_delegate.h", "bookmark_undo_provider.h", "bookmark_utils.h", "history_bookmark_model.h", @@ -91,6 +90,7 @@ "AppKit.framework", "Foundation.framework", ] + configs += [ "//build/config/compiler:enable_arc" ] } if (is_ios) {
diff --git a/components/bookmarks/browser/bookmark_client.h b/components/bookmarks/browser/bookmark_client.h index 5f7c915..3e6bfeba 100644 --- a/components/bookmarks/browser/bookmark_client.h +++ b/components/bookmarks/browser/bookmark_client.h
@@ -26,6 +26,7 @@ class BookmarkModel; class BookmarkPermanentNode; +class BookmarkUndoProvider; // A callback that generates a std::unique_ptr<BookmarkPermanentNode>, given a // max ID to use. The max ID argument will be updated after if a new node has @@ -101,6 +102,15 @@ virtual void DecodeBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) = 0; + + // Similar to BookmarkModelObserver::BookmarkNodeRemoved(), but transfers + // ownership of BookmarkNode, which allows undoing the operation. + virtual void OnBookmarkNodeRemovedUndoable( + BookmarkModel* model, + BookmarkUndoProvider* undo_provider, + const BookmarkNode* parent, + size_t index, + std::unique_ptr<BookmarkNode> node) = 0; }; } // namespace bookmarks
diff --git a/components/bookmarks/browser/bookmark_model.cc b/components/bookmarks/browser/bookmark_model.cc index f493013..24551a09 100644 --- a/components/bookmarks/browser/bookmark_model.cc +++ b/components/bookmarks/browser/bookmark_model.cc
@@ -25,7 +25,6 @@ #include "components/bookmarks/browser/bookmark_node.h" #include "components/bookmarks/browser/bookmark_node_data.h" #include "components/bookmarks/browser/bookmark_storage.h" -#include "components/bookmarks/browser/bookmark_undo_delegate.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "components/bookmarks/browser/model_loader.h" #include "components/bookmarks/browser/scoped_group_bookmark_actions.h" @@ -97,25 +96,6 @@ raw_ptr<icu::Collator> collator_; }; -// Delegate that does nothing. -class EmptyUndoDelegate : public BookmarkUndoDelegate { - public: - EmptyUndoDelegate() = default; - - EmptyUndoDelegate(const EmptyUndoDelegate&) = delete; - EmptyUndoDelegate& operator=(const EmptyUndoDelegate&) = delete; - - ~EmptyUndoDelegate() override = default; - - private: - // BookmarkUndoDelegate: - void OnBookmarkNodeRemoved(BookmarkModel* model, - BookmarkUndoProvider* undo_provider, - const BookmarkNode* parent, - size_t index, - std::unique_ptr<BookmarkNode> node) override {} -}; - // Builds the path of the bookmark file from the profile path. base::FilePath GetStorageFilePath(const base::FilePath& profile_path, StorageType storage_type) { @@ -138,8 +118,7 @@ base::Uuid::ParseLowercase(BookmarkNode::kRootNodeUuid), GURL())), root_(owned_root_.get()), - observers_(base::ObserverListPolicy::EXISTING_ONLY), - empty_undo_delegate_(std::make_unique<EmptyUndoDelegate>()) { + observers_(base::ObserverListPolicy::EXISTING_ONLY) { DCHECK(client_); client_->Init(this); } @@ -256,7 +235,7 @@ removed_urls); } - undo_delegate()->OnBookmarkNodeRemoved(this, this, parent, index.value(), + client_->OnBookmarkNodeRemovedUndoable(this, this, parent, index.value(), std::move(owned_node)); metrics::RecordBookmarkRemoved(source); @@ -324,7 +303,7 @@ removed_urls); } - undo_delegate()->OnBookmarkNodeRemoved(this, this, parent, index.value(), + client_->OnBookmarkNodeRemovedUndoable(this, this, parent, index.value(), std::move(owned_node)); // TODO(https://crbug.com/1416567): Record metrics. } @@ -395,7 +374,7 @@ BeginGroupedChanges(); for (auto& removed_node_data : removed_node_data_list) { - undo_delegate()->OnBookmarkNodeRemoved(this, this, removed_node_data.parent, + client_->OnBookmarkNodeRemovedUndoable(this, this, removed_node_data.parent, removed_node_data.index, std::move(removed_node_data.node)); } @@ -1244,14 +1223,4 @@ return next_node_id_++; } -void BookmarkModel::SetUndoDelegate(BookmarkUndoDelegate* undo_delegate) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - undo_delegate_ = undo_delegate; -} - -BookmarkUndoDelegate* BookmarkModel::undo_delegate() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - return undo_delegate_ ? undo_delegate_.get() : empty_undo_delegate_.get(); -} - } // namespace bookmarks
diff --git a/components/bookmarks/browser/bookmark_model.h b/components/bookmarks/browser/bookmark_model.h index 6c0c03d..101de9e 100644 --- a/components/bookmarks/browser/bookmark_model.h +++ b/components/bookmarks/browser/bookmark_model.h
@@ -52,7 +52,6 @@ class BookmarkLoadDetails; class BookmarkModelObserver; class BookmarkStorage; -class BookmarkUndoDelegate; class ModelLoader; class ScopedGroupBookmarkActions; class TestBookmarkClient; @@ -371,8 +370,6 @@ // Returns the client used by this BookmarkModel. BookmarkClient* client() const { return client_.get(); } - void SetUndoDelegate(BookmarkUndoDelegate* undo_delegate); - base::WeakPtr<BookmarkModel> AsWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -453,8 +450,6 @@ // decoding since during decoding codec assigns node IDs. void set_next_node_id(int64_t id) { next_node_id_ = id; } - BookmarkUndoDelegate* undo_delegate() const; - // Implementation of `UpdateLastUsedTime` which gives the option to skip // saving the change to `BookmarkStorage. Used to efficiently make changes // to multiple bookmarks. @@ -510,9 +505,6 @@ std::set<std::string> non_cloned_keys_; - raw_ptr<BookmarkUndoDelegate> undo_delegate_ = nullptr; - std::unique_ptr<BookmarkUndoDelegate> empty_undo_delegate_; - scoped_refptr<ModelLoader> model_loader_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/components/bookmarks/browser/bookmark_model_unittest.cc b/components/bookmarks/browser/bookmark_model_unittest.cc index 2b05c08f..a3c1229 100644 --- a/components/bookmarks/browser/bookmark_model_unittest.cc +++ b/components/bookmarks/browser/bookmark_model_unittest.cc
@@ -16,6 +16,7 @@ #include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/files/scoped_temp_dir.h" +#include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/scoped_observation.h" @@ -31,7 +32,6 @@ #include "build/build_config.h" #include "components/bookmarks/browser/bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_node.h" -#include "components/bookmarks/browser/bookmark_undo_delegate.h" #include "components/bookmarks/browser/bookmark_undo_provider.h" #include "components/bookmarks/browser/bookmark_utils.h" #include "components/bookmarks/browser/titled_url_match.h" @@ -52,15 +52,16 @@ #include "ui/gfx/image/image.h" #include "url/gurl.h" +namespace bookmarks { +namespace { + using base::ASCIIToUTF16; using base::Time; +using testing::ElementsAre; using testing::Invoke; using testing::Mock; using testing::WithArg; -namespace bookmarks { -namespace { - // Test cases used to test the removal of extra whitespace when adding // a new folder/bookmark or updating a title of a folder/bookmark. // Note that whitespace characters are all replaced with spaces, but spaces are @@ -121,13 +122,11 @@ {"\n foo\r\n\tbar\n \t", " foo bar "}, }; -class ScopedBookmarkUndoDelegate : public BookmarkUndoDelegate { +// TestBookmarkClient that also has basic support for undoing removals. +class TestBookmarkClientWithUndo : public TestBookmarkClient { public: - explicit ScopedBookmarkUndoDelegate(BookmarkModel* model) : model_(model) { - model_->SetUndoDelegate(this); - } - - ~ScopedBookmarkUndoDelegate() override { model_->SetUndoDelegate(nullptr); } + TestBookmarkClientWithUndo() = default; + ~TestBookmarkClientWithUndo() override = default; void RestoreLastRemovedBookmark() { DCHECK(undo_provider_); @@ -137,12 +136,13 @@ index_ = 0; } - // BookmarkUndoDelegate overrides. - void OnBookmarkNodeRemoved(BookmarkModel* model, - BookmarkUndoProvider* undo_provider, - const BookmarkNode* parent, - size_t index, - std::unique_ptr<BookmarkNode> node) override { + // BookmarkClient overrides. + void OnBookmarkNodeRemovedUndoable( + BookmarkModel* model, + BookmarkUndoProvider* undo_provider, + const BookmarkNode* parent, + size_t index, + std::unique_ptr<BookmarkNode> node) override { undo_provider_ = undo_provider; parent_ = parent; index_ = index; @@ -150,7 +150,6 @@ } private: - raw_ptr<BookmarkModel> model_ = nullptr; raw_ptr<BookmarkUndoProvider> undo_provider_ = nullptr; raw_ptr<const BookmarkNode> parent_ = nullptr; size_t index_ = 0; @@ -272,9 +271,7 @@ ASSERT_TRUE(ids.insert(it.Next()->id()).second); } -class BookmarkModelTest : public testing::Test, - public BookmarkModelObserver, - public BookmarkUndoDelegate { +class BookmarkModelTest : public testing::Test, public BookmarkModelObserver { public: struct ObserverDetails { ObserverDetails() { @@ -314,23 +311,20 @@ bool added_by_user_; }; - struct NodeRemovalDetail { - NodeRemovalDetail(const BookmarkNode* parent, - size_t index, - const BookmarkNode* node) - : parent_node_id(parent->id()), index(index), node_id(node->id()) {} + struct AllNodesRemovedDetail { + explicit AllNodesRemovedDetail(const std::set<GURL>& removed_urls) + : removed_urls(removed_urls) {} - bool operator==(const NodeRemovalDetail& other) const { - return parent_node_id == other.parent_node_id && index == other.index && - node_id == other.node_id; + bool operator==(const AllNodesRemovedDetail& other) const { + return removed_urls == other.removed_urls; } - int64_t parent_node_id; - size_t index; - int64_t node_id; + std::set<GURL> removed_urls; }; - BookmarkModelTest() : model_(TestBookmarkClient::CreateModel()) { + BookmarkModelTest() + : model_(TestBookmarkClient::CreateModelWithClient( + std::make_unique<TestBookmarkClientWithUndo>())) { model_->AddObserver(this); ClearCounts(); } @@ -418,6 +412,7 @@ BookmarkModel* model, const std::set<GURL>& removed_urls) override { ++all_bookmarks_removed_; + all_bookmarks_removed_details_.emplace_back(removed_urls); } void OnWillRemoveAllUserBookmarks(BookmarkModel* model) override { @@ -432,15 +427,6 @@ ++grouped_changes_ended_count_; } - void OnBookmarkNodeRemoved(BookmarkModel* model, - BookmarkUndoProvider* undo_provider, - const BookmarkNode* parent, - size_t index, - std::unique_ptr<BookmarkNode> node) override { - node_removal_details_.push_back( - NodeRemovalDetail(parent, index, node.get())); - } - void ClearCounts() { added_count_ = 0; moved_count_ = 0; @@ -517,7 +503,7 @@ protected: std::unique_ptr<BookmarkModel> model_; ObserverDetails observer_details_; - std::vector<NodeRemovalDetail> node_removal_details_; + std::vector<AllNodesRemovedDetail> all_bookmarks_removed_details_; base::HistogramTester histogram_tester_; base::UserActionTester user_action_tester_; @@ -831,8 +817,7 @@ // Add a url to bookmark bar. std::u16string title(u"foo"); GURL url("http://foo.com"); - const BookmarkNode* url_node = - model_->AddURL(bookmark_bar_node, 0, title, url); + model_->AddURL(bookmark_bar_node, 0, title, url); // Add a folder with child URL. const BookmarkNode* folder = model_->AddFolder(bookmark_bar_node, 0, title); @@ -843,12 +828,6 @@ size_t permanent_node_count = model_->root_node()->children().size(); - NodeRemovalDetail expected_node_removal_details[] = { - NodeRemovalDetail(bookmark_bar_node, 1, url_node), - NodeRemovalDetail(bookmark_bar_node, 0, folder), - }; - - model_->SetUndoDelegate(this); model_->RemoveAllUserBookmarks(); EXPECT_EQ(0u, bookmark_bar_node->children().size()); @@ -861,9 +840,8 @@ AssertGroupedChangesObserverCount(1, 1); EXPECT_EQ(1, AllNodesRemovedObserverCount()); EXPECT_EQ(1, AllNodesRemovedObserverCount()); - ASSERT_EQ(2u, node_removal_details_.size()); - EXPECT_EQ(expected_node_removal_details[0], node_removal_details_[0]); - EXPECT_EQ(expected_node_removal_details[1], node_removal_details_[1]); + EXPECT_THAT(all_bookmarks_removed_details_, + ElementsAre(AllNodesRemovedDetail(/*removed_urls=*/{url}))); } TEST_F(BookmarkModelTest, UpdateLastUsedTimeInRange) { @@ -1801,7 +1779,9 @@ class BookmarkModelFaviconTest : public testing::Test, public BookmarkModelObserver { public: - BookmarkModelFaviconTest() : model_(TestBookmarkClient::CreateModel()) { + BookmarkModelFaviconTest() + : model_(TestBookmarkClient::CreateModelWithClient( + std::make_unique<TestBookmarkClientWithUndo>())) { model_->AddObserver(this); } @@ -1950,10 +1930,11 @@ model_->GetFavicon(node); ASSERT_TRUE(node->is_favicon_loading()); - ScopedBookmarkUndoDelegate undo_delegate(model_.get()); model_->Remove(node, bookmarks::metrics::BookmarkEditSource::kOther); - undo_delegate.RestoreLastRemovedBookmark(); + static_cast<TestBookmarkClientWithUndo*>(model_->client()) + ->RestoreLastRemovedBookmark(); + EXPECT_FALSE(node->is_favicon_loading()); EXPECT_FALSE(node->is_favicon_loaded()); }
diff --git a/components/bookmarks/browser/bookmark_node_data_mac.mm b/components/bookmarks/browser/bookmark_node_data_mac.mm index 9b8350d1..e64a1e9 100644 --- a/components/bookmarks/browser/bookmark_node_data_mac.mm +++ b/components/bookmarks/browser/bookmark_node_data_mac.mm
@@ -11,6 +11,10 @@ #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/base/dragdrop/os_exchange_data_provider_mac.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace bookmarks { #if defined(TOOLKIT_VIEWS)
diff --git a/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm b/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm index 308de42..5c59d49 100644 --- a/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm +++ b/components/bookmarks/browser/bookmark_pasteboard_helper_mac.mm
@@ -19,6 +19,10 @@ #include "ui/base/clipboard/clipboard_constants.h" #include "ui/base/clipboard/clipboard_util_mac.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace bookmarks { NSString* const kUTTypeChromiumBookmarkDictionaryList = @@ -101,7 +105,7 @@ NSNumber* node_id = base::mac::ObjCCast<NSNumber>(bookmark_dict[kChromiumBookmarkIdKey]); if (node_id) - new_node->set_id([node_id longLongValue]); + new_node->set_id(node_id.longLongValue); NSDictionary* meta_info = base::mac::ObjCCast<NSDictionary>( bookmark_dict[kChromiumBookmarkMetaInfoKey]); @@ -143,16 +147,17 @@ bool ReadStandardBookmarks(NSPasteboard* pb, std::vector<BookmarkNodeData::Element>* elements) { - NSArray* urls = nil; - NSArray* titles = nil; - if (!ui::clipboard_util::URLsAndTitlesFromPasteboard( - pb, /*include_files=*/false, &urls, &titles)) { + NSArray<URLAndTitle*>* urls_and_titles = + ui::clipboard_util::URLsAndTitlesFromPasteboard(pb, + /*include_files=*/false); + + if (!urls_and_titles.count) { return false; } - for (NSUInteger i = 0; i < titles.count; ++i) { - std::u16string title = base::SysNSStringToUTF16(titles[i]); - std::string url = base::SysNSStringToUTF8(urls[i]); + for (URLAndTitle* url_and_title in urls_and_titles) { + std::string url = base::SysNSStringToUTF8(url_and_title.URL); + std::u16string title = base::SysNSStringToUTF16(url_and_title.title); if (!url.empty()) { BookmarkNodeData::Element element; element.is_url = true; @@ -249,7 +254,7 @@ // consist of bookmark folders. The data for those folders will be contained // in the Chromium-specific data, so make a single pasteboard item to hold // it. - items = @[ [[[NSPasteboardItem alloc] init] autorelease] ]; + items = @[ [[NSPasteboardItem alloc] init] ]; } [items.firstObject setPropertyList:GetNSArrayForBookmarkList(elements)
diff --git a/components/bookmarks/browser/bookmark_undo_delegate.h b/components/bookmarks/browser/bookmark_undo_delegate.h deleted file mode 100644 index 5ea728872..0000000 --- a/components/bookmarks/browser/bookmark_undo_delegate.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2015 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_UNDO_DELEGATE_H_ -#define COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_UNDO_DELEGATE_H_ - -#include <memory> - -namespace bookmarks { - -class BookmarkModel; -class BookmarkNode; -class BookmarkUndoProvider; - -// Delegate to handle bookmark change events in order to support undo when -// requested. -class BookmarkUndoDelegate { - public: - virtual ~BookmarkUndoDelegate() {} - - // Called when |node| was removed from |parent| at position |index|. - virtual void OnBookmarkNodeRemoved(BookmarkModel* model, - BookmarkUndoProvider* undo_provider, - const BookmarkNode* parent, - size_t index, - std::unique_ptr<BookmarkNode> node) = 0; -}; - - -} // namespace bookmarks - -#endif // COMPONENTS_BOOKMARKS_BROWSER_BOOKMARK_UNDO_DELEGATE_H_
diff --git a/components/bookmarks/test/test_bookmark_client.cc b/components/bookmarks/test/test_bookmark_client.cc index 8a13a47..e09a9e3 100644 --- a/components/bookmarks/test/test_bookmark_client.cc +++ b/components/bookmarks/test/test_bookmark_client.cc
@@ -153,6 +153,13 @@ return next_task_id_++; } +void TestBookmarkClient::OnBookmarkNodeRemovedUndoable( + BookmarkModel* model, + BookmarkUndoProvider* undo_provider, + const BookmarkNode* parent, + size_t index, + std::unique_ptr<BookmarkNode> node) {} + // static std::unique_ptr<BookmarkPermanentNode> TestBookmarkClient::LoadManagedNode( std::unique_ptr<BookmarkPermanentNode> managed_node,
diff --git a/components/bookmarks/test/test_bookmark_client.h b/components/bookmarks/test/test_bookmark_client.h index e69a360..700706cf 100644 --- a/components/bookmarks/test/test_bookmark_client.h +++ b/components/bookmarks/test/test_bookmark_client.h
@@ -81,6 +81,12 @@ const GURL& page_url, favicon_base::FaviconImageCallback callback, base::CancelableTaskTracker* tracker) override; + void OnBookmarkNodeRemovedUndoable( + BookmarkModel* model, + BookmarkUndoProvider* undo_provider, + const BookmarkNode* parent, + size_t index, + std::unique_ptr<BookmarkNode> node) override; private: // Helpers for GetLoadManagedNodeCallback().
diff --git a/components/browser_ui/site_settings/android/BUILD.gn b/components/browser_ui/site_settings/android/BUILD.gn index ea3c801b..489626f0 100644 --- a/components/browser_ui/site_settings/android/BUILD.gn +++ b/components/browser_ui/site_settings/android/BUILD.gn
@@ -73,6 +73,7 @@ "java/src/org/chromium/components/browser_ui/site_settings/FPSCookieSettings.java", "java/src/org/chromium/components/browser_ui/site_settings/ForwardingManagedPreferenceDelegate.java", "java/src/org/chromium/components/browser_ui/site_settings/FourStateCookieSettingsPreference.java", + "java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesActivityHolder.java", "java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java", "java/src/org/chromium/components/browser_ui/site_settings/LocalStorageInfo.java", "java/src/org/chromium/components/browser_ui/site_settings/LocationCategory.java",
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java index 8957d68..6f0bfa9a 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/AllSiteSettings.java
@@ -301,7 +301,7 @@ website.putSiteIntoExtras(SingleWebsiteSettings.EXTRA_SITE); website.getExtras().putInt(extraKey, getNavigationSource()); } else if (preference instanceof WebsiteRowPreference) { - ((WebsiteRowPreference) preference).handleClick(getArguments()); + ((WebsiteRowPreference) preference).handleClick(getArguments(), /*fromGrouped=*/false); } return super.onPreferenceTreeClick(preference);
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesActivityHolder.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesActivityHolder.java new file mode 100644 index 0000000..f4f7ef8 --- /dev/null +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesActivityHolder.java
@@ -0,0 +1,37 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.browser_ui.site_settings; + +import android.app.Activity; + +import androidx.annotation.Nullable; + +import org.chromium.base.ThreadUtils; + +import java.lang.ref.WeakReference; + +// A singleton class that holds a WeakReference to the Activity object of GroupedWebsiteSettings. +// Needed to be able to go to the 'All Sites' level when clearing data in SingleWebsiteSettings. +class GroupedWebsitesActivityHolder { + @Nullable + private WeakReference<Activity> mActivity; + + private static GroupedWebsitesActivityHolder sInstance; + private GroupedWebsitesActivityHolder(){}; + + public static GroupedWebsitesActivityHolder getInstance() { + ThreadUtils.assertOnUiThread(); + if (sInstance == null) sInstance = new GroupedWebsitesActivityHolder(); + return sInstance; + } + + public void setActivity(Activity activity) { + mActivity = new WeakReference<Activity>(activity); + } + + public Activity getActivity() { + return mActivity.get(); + } +}
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java index b755b9c..a2e4371e 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/GroupedWebsitesSettings.java
@@ -91,7 +91,9 @@ public boolean onPreferenceTreeClick(Preference preference) { if (preference instanceof WebsiteRowPreference) { // Handle a click on one of the sites in this group. - ((WebsiteRowPreference) preference).handleClick(getArguments()); + // Save the current activity, so it's accessible from the SingleWebsiteSettings. + GroupedWebsitesActivityHolder.getInstance().setActivity(getActivity()); + ((WebsiteRowPreference) preference).handleClick(getArguments(), /*fromGrouped=*/true); } return super.onPreferenceTreeClick(preference); }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java index 9a29e63..0066e99e 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -78,6 +78,9 @@ // A boolean to configure whether the sound setting should be shown. Defaults to true. public static final String EXTRA_SHOW_SOUND = "org.chromium.chrome.preferences.show_sound"; + // A boolean that indicates whether these settings were opened from GroupedWebsiteSettings. + public static final String EXTRA_FROM_GROUPED = "org.chromium.chrome.preferences.from_grouped"; + // Used to store mPreviousNotificationPermission when the activity is paused. private static final String PREVIOUS_NOTIFICATION_PERMISSION_KEY = "previous_notification_permission"; @@ -196,6 +199,9 @@ // The website this page is displaying details about. private Website mSite; + // Whether these settings were opened from GroupedWebsitesSettings. + private boolean mFromGrouped; + // The Preference key for chooser object permissions. private static final String CHOOSER_PERMISSION_PREFERENCE_KEY = "chooser_permission_list"; @@ -328,6 +334,8 @@ assert false : "Exactly one of EXTRA_SITE or EXTRA_SITE_ADDRESS must be provided."; } + mFromGrouped = getArguments().getBoolean(EXTRA_FROM_GROUPED, false); + // Disable animations of preference changes. getListView().setItemAnimator(null); } @@ -1131,6 +1139,10 @@ private void popBackIfNoSettings() { if (!hasPermissionsPreferences() && !hasUsagePreferences() && getActivity() != null) { getActivity().finish(); + if (mFromGrouped) { + Activity groupActivity = GroupedWebsitesActivityHolder.getInstance().getActivity(); + if (groupActivity != null) groupActivity.finish(); + } } } @@ -1213,6 +1225,10 @@ DeleteBrowsingDataAction.SITES_SETTINGS_PAGE, DeleteBrowsingDataAction.MAX_VALUE); if (finishActivityImmediately) { getActivity().finish(); + if (mFromGrouped) { + Activity groupActivity = GroupedWebsitesActivityHolder.getInstance().getActivity(); + if (groupActivity != null) groupActivity.finish(); + } } }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java index 87883962..c79ebd1 100644 --- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java +++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsiteRowPreference.java
@@ -63,12 +63,20 @@ updateSummary(); } + /** + * Handles the click on the row by opening the appropriate SettingsFragment. + * @param args the result of getArguments() + * @param fromGrouped whether this is invoked from GroupedWebsitesSettings + */ @SuppressWarnings("WrongConstant") - public void handleClick(Bundle args) { + public void handleClick(Bundle args, boolean fromGrouped) { getExtras().putSerializable(mSiteEntry instanceof Website ? SingleWebsiteSettings.EXTRA_SITE : GroupedWebsitesSettings.EXTRA_GROUP, mSiteEntry); + if (fromGrouped) { + getExtras().putBoolean(SingleWebsiteSettings.EXTRA_FROM_GROUPED, true); + } setFragment(mSiteEntry instanceof Website ? SingleWebsiteSettings.class.getName() : GroupedWebsitesSettings.class.getName()); getExtras().putInt(SettingsNavigationSource.EXTRA_KEY,
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java index 3d790e905..6028484 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequest.java
@@ -980,7 +980,12 @@ mRequestFinishedListener.getExecutor().execute(new Runnable() { @Override public void run() { - mRequestFinishedListener.onRequestFinished(requestInfo); + try { + mRequestFinishedListener.onRequestFinished(requestInfo); + } catch (Exception e) { + Log.e(CronetUrlRequestContext.LOG_TAG, + "Exception thrown from request finished listener", e); + } } }); } catch (RejectedExecutionException failException) {
diff --git a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java index c90480a..3f2ef31c 100644 --- a/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java +++ b/components/cronet/android/java/src/org/chromium/net/impl/CronetUrlRequestContext.java
@@ -806,7 +806,13 @@ private static void postObservationTaskToExecutor(Executor executor, Runnable task) { try { - executor.execute(task); + executor.execute(() -> { + try { + task.run(); + } catch (Exception e) { + Log.e(LOG_TAG, "Exception thrown from observation task", e); + } + }); } catch (RejectedExecutionException failException) { Log.e(CronetUrlRequestContext.LOG_TAG, "Exception posting task to executor", failException);
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java b/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java index 6ebf894..867c57fa 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/RequestFinishedInfoTest.java
@@ -281,6 +281,38 @@ @Test @SmallTest @OnlyRunNativeCronet + public void testRequestFinishedListenerThrowInListener() throws Exception { + TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); + requestFinishedListener.makeListenerThrow(); + TestUrlRequestCallback callback = new TestUrlRequestCallback(); + mTestFramework.mCronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getExecutor()) + .setRequestFinishedListener(requestFinishedListener) + .build() + .start(); + callback.blockForDone(); + // We expect that the exception from the listener will not crash the test. + requestFinishedListener.blockUntilDone(); + } + + @Test + @SmallTest + @OnlyRunNativeCronet + public void testRequestFinishedListenerThrowInEngineListener() throws Exception { + TestRequestFinishedListener requestFinishedListener = new TestRequestFinishedListener(); + requestFinishedListener.makeListenerThrow(); + mTestFramework.mCronetEngine.addRequestFinishedListener(requestFinishedListener); + TestUrlRequestCallback callback = new TestUrlRequestCallback(); + mTestFramework.mCronetEngine.newUrlRequestBuilder(mUrl, callback, callback.getExecutor()) + .build() + .start(); + callback.blockForDone(); + // We expect that the exception from the listener will not crash the test. + requestFinishedListener.blockUntilDone(); + } + + @Test + @SmallTest + @OnlyRunNativeCronet @SuppressWarnings("deprecation") public void testRequestFinishedListenerRemoved() throws Exception { TestExecutor testExecutor = new TestExecutor();
diff --git a/components/cronet/android/test/javatests/src/org/chromium/net/TestRequestFinishedListener.java b/components/cronet/android/test/javatests/src/org/chromium/net/TestRequestFinishedListener.java index b717c5c..4dd50fd 100644 --- a/components/cronet/android/test/javatests/src/org/chromium/net/TestRequestFinishedListener.java +++ b/components/cronet/android/test/javatests/src/org/chromium/net/TestRequestFinishedListener.java
@@ -18,6 +18,7 @@ public class TestRequestFinishedListener extends RequestFinishedInfo.Listener { private final ConditionVariable mBlock; private RequestFinishedInfo mRequestInfo; + private boolean mMakeListenerThrow; // TODO(mgersh): it's weird that you can use either this constructor or blockUntilDone() but // not both. Either clean it up or document why it has to work this way. @@ -31,6 +32,10 @@ mBlock = new ConditionVariable(); } + public void makeListenerThrow() { + mMakeListenerThrow = true; + } + public RequestFinishedInfo getRequestInfo() { return mRequestInfo; } @@ -41,6 +46,10 @@ assertNotNull(requestInfo); mRequestInfo = requestInfo; mBlock.open(); + if (mMakeListenerThrow) { + throw new IllegalStateException( + "TestRequestFinishedListener throwing exception as requested"); + } } public void blockUntilDone() {
diff --git a/components/download/public/common/mock_download_item_impl.h b/components/download/public/common/mock_download_item_impl.h index d37ed92..280500a 100644 --- a/components/download/public/common/mock_download_item_impl.h +++ b/components/download/public/common/mock_download_item_impl.h
@@ -121,6 +121,7 @@ MOCK_CONST_METHOD0(GetLastReason, DownloadInterruptReason()); MOCK_CONST_METHOD0(GetFileNameToReportUser, base::FilePath()); MOCK_METHOD1(SetDisplayName, void(const base::FilePath&)); + MOCK_CONST_METHOD0(IsTransient, bool()); // May be called when vlog is on. std::string DebugString(bool verbose) const override { return std::string(); } };
diff --git a/components/exo/surface.cc b/components/exo/surface.cc index 9b5925a..5a87ef6 100644 --- a/components/exo/surface.cc +++ b/components/exo/surface.cc
@@ -610,6 +610,11 @@ pending_state_.basic_state.background_color = background_color; } +void Surface::SetTrustedDamage(bool trusted_damage) { + TRACE_EVENT0("exo", "Surface::SetTrustedDamage"); + trusted_damage_ = trusted_damage; +} + void Surface::SetViewport(const gfx::SizeF& viewport) { TRACE_EVENT1("exo", "Surface::SetViewport", "viewport", viewport.ToString()); @@ -915,25 +920,30 @@ // TODO(penghuang): Make the damage more precise for sub surface changes. // https://crbug.com/779704 - bool needs_full_damage = - sub_surfaces_changed_ || - cached_state_.basic_state.opaque_region != - state_.basic_state.opaque_region || - cached_state_.basic_state.buffer_scale != - state_.basic_state.buffer_scale || - cached_state_.basic_state.buffer_transform != - state_.basic_state.buffer_transform || - cached_state_.basic_state.viewport != state_.basic_state.viewport || - cached_state_.rounded_corners_bounds != state_.rounded_corners_bounds || - cached_state_.basic_state.crop != state_.basic_state.crop || - cached_state_.basic_state.only_visible_on_secure_output != - state_.basic_state.only_visible_on_secure_output || - cached_state_.basic_state.blend_mode != state_.basic_state.blend_mode || - cached_state_.basic_state.alpha != state_.basic_state.alpha || - cached_state_.basic_state.color_space != - state_.basic_state.color_space || - cached_state_.basic_state.is_tracking_occlusion != - state_.basic_state.is_tracking_occlusion; + bool needs_full_damage = false; + if (!trusted_damage_) { + needs_full_damage = + sub_surfaces_changed_ || + cached_state_.basic_state.opaque_region != + state_.basic_state.opaque_region || + cached_state_.basic_state.buffer_scale != + state_.basic_state.buffer_scale || + cached_state_.basic_state.buffer_transform != + state_.basic_state.buffer_transform || + cached_state_.basic_state.viewport != state_.basic_state.viewport || + cached_state_.rounded_corners_bounds != + state_.rounded_corners_bounds || + cached_state_.basic_state.crop != state_.basic_state.crop || + cached_state_.basic_state.only_visible_on_secure_output != + state_.basic_state.only_visible_on_secure_output || + cached_state_.basic_state.blend_mode != + state_.basic_state.blend_mode || + cached_state_.basic_state.alpha != state_.basic_state.alpha || + cached_state_.basic_state.color_space != + state_.basic_state.color_space || + cached_state_.basic_state.is_tracking_occlusion != + state_.basic_state.is_tracking_occlusion; + } bool needs_update_buffer_transform = cached_state_.basic_state.buffer_scale != @@ -1047,6 +1057,9 @@ aura::Window* stacking_target = nullptr; for (const auto& sub_surface_entry : pending_sub_surfaces_) { Surface* sub_surface = sub_surface_entry.first; + // If the parent has trusted damage set, then consider it trusted for + // all subsurfaces. + sub_surface->SetTrustedDamage(trusted_damage_); sub_surfaces_.push_back(sub_surface_entry); // Move sub-surface to its new position in the stack. if (stacking_target)
diff --git a/components/exo/surface.h b/components/exo/surface.h index 87b534a..0e84453 100644 --- a/components/exo/surface.h +++ b/components/exo/surface.h
@@ -197,6 +197,9 @@ // commit. void SetBackgroundColor(absl::optional<SkColor4f> background_color); + // Sets that this surface uses trusted damage. + void SetTrustedDamage(bool trusted_damage); + // This sets the surface viewport for scaling. void SetViewport(const gfx::SizeF& viewport); @@ -614,6 +617,9 @@ // This true, if sub_surfaces_ has changes (order, position, etc). bool sub_surfaces_changed_ = false; + // This is true if damage reported by the client should be trusted. + bool trusted_damage_ = false; + // This is the size of the last committed contents. gfx::SizeF content_size_;
diff --git a/components/exo/wayland/protocol/surface-augmenter.xml b/components/exo/wayland/protocol/surface-augmenter.xml index bdf2bd9..f505c78 100644 --- a/components/exo/wayland/protocol/surface-augmenter.xml +++ b/components/exo/wayland/protocol/surface-augmenter.xml
@@ -24,7 +24,7 @@ DEALINGS IN THE SOFTWARE. </copyright> - <interface name="surface_augmenter" version="5"> + <interface name="surface_augmenter" version="6"> <description summary="surface composition delegation"> The global interface exposing surface delegated composition capabilities is used to instantiate an interface extension for a @@ -89,7 +89,7 @@ </request> </interface> - <interface name="augmented_surface" version="3"> + <interface name="augmented_surface" version="6"> <description summary="delegate composition of a wl_surface"> An additional interface to a wl_surface object, which allows the client to specify the delegated composition of the surface @@ -170,6 +170,20 @@ <arg name="color" type="array" summary="overlay color represented by a SkColor4f"/> </request> + + <!-- Version 6 additions --> + + <request name="set_trusted_damage" since="6"> + <description summary="sets the trusted damage state of this surface"> + When set, this surface trusts all damage reported to this surface and + descendant sub-surfaces is accurate, and will not try to recompute it. + If not set, various changes like adding or removing a sub-surface, + changing its position or stacking order, can cause full damage on this + surface. + The initial state is disabled. + </description> + <arg name="enabled" type="int"/> + </request> </interface> <interface name="augmented_sub_surface" version="5">
diff --git a/components/exo/wayland/surface_augmenter.cc b/components/exo/wayland/surface_augmenter.cc index 7dee365..9364a61 100644 --- a/components/exo/wayland/surface_augmenter.cc +++ b/components/exo/wayland/surface_augmenter.cc
@@ -72,6 +72,10 @@ surface_->SetBackgroundColor(background_color); } + void SetTrustedDamage(bool trusted_damage) { + surface_->SetTrustedDamage(trusted_damage); + } + // SurfaceObserver: void OnSurfaceDestroying(Surface* surface) override { surface->RemoveSurfaceObserver(this); @@ -149,11 +153,19 @@ GetUserDataAs<AugmentedSurface>(resource)->SetBackgroundColor(sk_color); } +void augmented_surface_set_trusted_damage(wl_client* client, + wl_resource* resource, + int enabled) { + GetUserDataAs<AugmentedSurface>(resource)->SetTrustedDamage(enabled); +} + const struct augmented_surface_interface augmented_implementation = { - augmented_surface_destroy, augmented_surface_set_corners_DEPRECATED, + augmented_surface_destroy, + augmented_surface_set_corners_DEPRECATED, augmented_surface_set_destination_size, augmented_surface_set_rounded_corners_bounds, - augmented_surface_set_background_color}; + augmented_surface_set_background_color, + augmented_surface_set_trusted_damage}; //////////////////////////////////////////////////////////////////////////////// // augmented_sub_surface_interface:
diff --git a/components/exo/wayland/surface_augmenter.h b/components/exo/wayland/surface_augmenter.h index 49734e8..25f630a6 100644 --- a/components/exo/wayland/surface_augmenter.h +++ b/components/exo/wayland/surface_augmenter.h
@@ -12,7 +12,7 @@ namespace exo { namespace wayland { -constexpr uint32_t kSurfaceAugmenterVersion = 5; +constexpr uint32_t kSurfaceAugmenterVersion = 6; void bind_surface_augmenter(wl_client* client, void* data,
diff --git a/components/invalidation/impl/fcm_invalidation_service_unittest.cc b/components/invalidation/impl/fcm_invalidation_service_unittest.cc index fd8f2cd..9cc394f 100644 --- a/components/invalidation/impl/fcm_invalidation_service_unittest.cc +++ b/components/invalidation/impl/fcm_invalidation_service_unittest.cc
@@ -161,17 +161,16 @@ } void InitializeInvalidationService() { - fake_listener_ = new FakeFCMInvalidationListener( + auto fake_listener = std::make_unique<FakeFCMInvalidationListener>( std::make_unique<TestFCMSyncNetworkChannel>()); - invalidation_service_->InitForTest(base::WrapUnique(fake_listener_.get())); + fake_listener_ = fake_listener.get(); + invalidation_service_->InitForTest(std::move(fake_listener)); } FCMInvalidationService* GetInvalidationService() { return invalidation_service_.get(); } - void DestroyInvalidationService() { invalidation_service_.reset(); } - void TriggerOnInvalidatorStateChange(InvalidatorState state) { fake_listener_->EmitStateChangeForTest(state); } @@ -188,13 +187,13 @@ std::unique_ptr<MockInstanceID> mock_instance_id_; signin::IdentityTestEnvironment identity_test_env_; std::unique_ptr<IdentityProvider> identity_provider_; - raw_ptr<FCMInvalidationListener> fake_listener_; // Owned by the service. network::TestURLLoaderFactory url_loader_factory_; TestingPrefServiceSimple pref_service_; // The service has to be below the provider since the service keeps // a non-owned pointer to the provider. std::unique_ptr<FCMInvalidationService> invalidation_service_; + raw_ptr<FCMInvalidationListener> fake_listener_; // Owned by the service. }; INSTANTIATE_TYPED_TEST_SUITE_P(FCMInvalidationServiceTest,
diff --git a/components/invalidation/impl/invalidation_service_test_template.h b/components/invalidation/impl/invalidation_service_test_template.h index 7cd831d..63bcb7f 100644 --- a/components/invalidation/impl/invalidation_service_test_template.h +++ b/components/invalidation/impl/invalidation_service_test_template.h
@@ -30,11 +30,6 @@ // ... // } // -// // Destroy the InvalidationService implementation. -// void DestroyInvalidationService() { -// ... -// } -// // // The Trigger* functions below should block until the effects of // // the call are visible on the current thread. //
diff --git a/components/metrics/BUILD.gn b/components/metrics/BUILD.gn index f28aa3c0e..2e0e10f9 100644 --- a/components/metrics/BUILD.gn +++ b/components/metrics/BUILD.gn
@@ -228,6 +228,10 @@ deps += [ ":jni_headers" ] } + if (is_apple) { + configs += [ "//build/config/compiler:enable_arc" ] + } + if (is_ios) { sources += [ "clean_exit_beacon_ios.mm",
diff --git a/components/metrics/clean_exit_beacon_ios.mm b/components/metrics/clean_exit_beacon_ios.mm index c8d36ba..e6cbabc 100644 --- a/components/metrics/clean_exit_beacon_ios.mm +++ b/components/metrics/clean_exit_beacon_ios.mm
@@ -8,6 +8,10 @@ #include "base/feature_list.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace metrics { namespace { @@ -25,20 +29,20 @@ // static void CleanExitBeacon::SetUserDefaultsBeacon(bool exited_cleanly) { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; [defaults setBool:exited_cleanly forKey:kLastSessionExitedCleanly]; [defaults synchronize]; } // static bool CleanExitBeacon::ShouldUseUserDefaultsBeacon() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; return [defaults boolForKey:kUserDefaultsFeatureFlagForExitedCleanlyBeacon]; } // static void CleanExitBeacon::SyncUseUserDefaultsBeacon() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; [defaults setBool:base::FeatureList::IsEnabled( kUseUserDefaultsForExitedCleanlyBeacon) forKey:kUserDefaultsFeatureFlagForExitedCleanlyBeacon]; @@ -47,19 +51,19 @@ // static bool CleanExitBeacon::HasUserDefaultsBeacon() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; return [defaults objectForKey:kLastSessionExitedCleanly] != nil; } // static bool CleanExitBeacon::GetUserDefaultsBeacon() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; return [defaults boolForKey:kLastSessionExitedCleanly]; } // static void CleanExitBeacon::ResetUserDefaultsBeacon() { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + NSUserDefaults* defaults = NSUserDefaults.standardUserDefaults; [defaults removeObjectForKey:kLastSessionExitedCleanly]; [defaults synchronize]; }
diff --git a/components/metrics/drive_metrics_provider_ios.mm b/components/metrics/drive_metrics_provider_ios.mm index f8123067..70887f4 100644 --- a/components/metrics/drive_metrics_provider_ios.mm +++ b/components/metrics/drive_metrics_provider_ios.mm
@@ -4,6 +4,10 @@ #include "components/metrics/drive_metrics_provider.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace metrics { // static
diff --git a/components/metrics/drive_metrics_provider_mac.mm b/components/metrics/drive_metrics_provider_mac.mm index 9c8a095..33e12015 100644 --- a/components/metrics/drive_metrics_provider_mac.mm +++ b/components/metrics/drive_metrics_provider_mac.mm
@@ -12,12 +12,17 @@ #include <stdlib.h> #include <sys/stat.h> +#include "base/apple/bridging.h" #include "base/files/file_path.h" #include "base/mac/foundation_util.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/mac/scoped_ioobject.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace metrics { // static @@ -58,7 +63,7 @@ if (!type_ref) return false; - NSString* type = base::mac::CFToNSCast(type_ref); + NSString* type = base::apple::CFToNSPtrCast(type_ref); if ([type isEqualToString:@kIOPropertyMediumTypeRotationalKey]) { *has_seek_penalty = true; return true;
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 2f7b970..fc9f1301 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -635,6 +635,7 @@ "login_database_unittest.cc", "old_google_credentials_cleaner_unittest.cc", "origin_credential_store_unittest.cc", + "passkey_credential_unittest.cc", "password_access_authenticator_unittest.cc", "password_account_storage_settings_watcher_unittest.cc", "password_autofill_manager_unittest.cc",
diff --git a/components/password_manager/core/browser/fake_password_store_backend.cc b/components/password_manager/core/browser/fake_password_store_backend.cc index afc563b..f7e7d65 100644 --- a/components/password_manager/core/browser/fake_password_store_backend.cc +++ b/components/password_manager/core/browser/fake_password_store_backend.cc
@@ -274,11 +274,12 @@ std::vector<PasswordForm>& forms = stored_passwords_[form.signon_realm]; for (auto& stored_form : forms) { if (ArePasswordFormUniqueKeysEqual(form, stored_form)) { + bool password_changed = form.password_value != stored_form.password_value; stored_form = form; stored_form.in_store = is_account_store() ? PasswordForm::Store::kAccountStore : PasswordForm::Store::kProfileStore; - changes.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form)); + changes.emplace_back(PasswordStoreChange::UPDATE, form, password_changed); } } if (changes.empty() && update_always_succeeds_) {
diff --git a/components/password_manager/core/browser/passkey_credential.cc b/components/password_manager/core/browser/passkey_credential.cc index a775f115..f0e46598 100644 --- a/components/password_manager/core/browser/passkey_credential.cc +++ b/components/password_manager/core/browser/passkey_credential.cc
@@ -7,10 +7,45 @@ #include <string> #include <vector> +#include "base/containers/flat_set.h" +#include "base/containers/span.h" #include "components/strings/grit/components_strings.h" +#include "components/sync/protocol/webauthn_credential_specifics.pb.h" namespace password_manager { +namespace { + +std::vector<uint8_t> ProtobufBytesToVector(const std::string& bytes) { + return std::vector<uint8_t>(bytes.begin(), bytes.end()); +} + +} // namespace + +// static +std::vector<PasskeyCredential> PasskeyCredential::FromCredentialSpecifics( + base::span<const sync_pb::WebauthnCredentialSpecifics> passkeys) { + base::flat_set<std::string> shadowed_credential_ids; + for (const sync_pb::WebauthnCredentialSpecifics& passkey : passkeys) { + for (const std::string& id : passkey.newly_shadowed_credential_ids()) { + shadowed_credential_ids.emplace(id); + } + } + std::vector<password_manager::PasskeyCredential> credentials; + for (const sync_pb::WebauthnCredentialSpecifics& passkey : passkeys) { + if (shadowed_credential_ids.contains(passkey.credential_id())) { + continue; + } + credentials.emplace_back( + password_manager::PasskeyCredential::Source::kAndroidPhone, + passkey.rp_id(), ProtobufBytesToVector(passkey.credential_id()), + ProtobufBytesToVector(passkey.user_id()), + passkey.has_user_name() ? passkey.user_name() : "", + passkey.has_user_display_name() ? passkey.user_display_name() : ""); + } + return credentials; +} + PasskeyCredential::PasskeyCredential(Source source, std::string rp_id, std::vector<uint8_t> credential_id,
diff --git a/components/password_manager/core/browser/passkey_credential.h b/components/password_manager/core/browser/passkey_credential.h index 7bf384bd..71005a94 100644 --- a/components/password_manager/core/browser/passkey_credential.h +++ b/components/password_manager/core/browser/passkey_credential.h
@@ -9,6 +9,12 @@ #include <string> #include <vector> +#include "base/containers/span.h" + +namespace sync_pb { +class WebauthnCredentialSpecifics; +} + namespace password_manager { // Represents a Web Authentication passkey credential to be displayed in @@ -22,6 +28,9 @@ kOther, }; + static std::vector<PasskeyCredential> FromCredentialSpecifics( + base::span<const sync_pb::WebauthnCredentialSpecifics> passkeys); + PasskeyCredential(Source source, std::string rp_id, std::vector<uint8_t> credential_id,
diff --git a/components/password_manager/core/browser/passkey_credential_unittest.cc b/components/password_manager/core/browser/passkey_credential_unittest.cc new file mode 100644 index 0000000..3c0e52b --- /dev/null +++ b/components/password_manager/core/browser/passkey_credential_unittest.cc
@@ -0,0 +1,103 @@ +// 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/password_manager/core/browser/passkey_credential.h" + +#include "base/containers/span.h" +#include "base/rand_util.h" +#include "components/sync/protocol/webauthn_credential_specifics.pb.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace password_manager { + +namespace { + +constexpr char kRpId[] = "gensokyo.com"; + +constexpr std::array<const uint8_t, 4> kCredentialId1 = {'a', 'b', 'c', 'd'}; +constexpr std::array<const uint8_t, 4> kUserId1 = {'1', '2', '3', '4'}; +constexpr char kUserName1[] = "reimu"; +constexpr char kUserDisplayName1[] = "Reimu Hakurei"; + +constexpr std::array<const uint8_t, 4> kCredentialId2 = {'e', 'f', 'g', 'h'}; +constexpr std::array<const uint8_t, 4> kUserId2 = {'5', '6', '7', '8'}; +constexpr char kUserName2[] = "marisa"; +constexpr char kUserDisplayName2[] = "Marisa Kirisame"; + +constexpr std::array<const uint8_t, 4> kCredentialIdShadow = {'i', 'j', 'k', + 'l'}; + +std::vector<uint8_t> ToUint8Vector( + const std::array<const uint8_t, 4>& byte_array) { + return std::vector<uint8_t>(byte_array.begin(), byte_array.end()); +} + +} // namespace + +class PasskeyCredentialTest : public testing::Test {}; + +TEST_F(PasskeyCredentialTest, FromCredentialSpecifics) { + sync_pb::WebauthnCredentialSpecifics credential1; + credential1.set_sync_id(base::RandBytesAsString(16)); + credential1.set_credential_id(kCredentialId1.data(), kCredentialId1.size()); + credential1.set_rp_id(kRpId); + credential1.set_user_id(kUserId1.data(), kUserId1.size()); + credential1.set_user_name(kUserName1); + credential1.set_user_display_name(kUserDisplayName1); + + sync_pb::WebauthnCredentialSpecifics credential2; + credential2.set_sync_id(base::RandBytesAsString(16)); + credential2.set_credential_id(kCredentialId2.data(), kCredentialId2.size()); + credential2.set_rp_id(kRpId); + credential2.set_user_id(kUserId2.data(), kUserId2.size()); + credential2.set_user_name(kUserName2); + credential2.set_user_display_name(kUserDisplayName2); + + // Shadow the first credential. + sync_pb::WebauthnCredentialSpecifics credential1_shadow; + credential1_shadow.set_sync_id(base::RandBytesAsString(16)); + credential1_shadow.set_credential_id(kCredentialIdShadow.data(), + kCredentialIdShadow.size()); + credential1_shadow.set_rp_id(kRpId); + credential1_shadow.set_user_id(kUserId1.data(), kUserId1.size()); + credential1_shadow.set_user_name(kUserName1); + credential1_shadow.set_user_display_name(kUserDisplayName1); + credential1_shadow.add_newly_shadowed_credential_ids( + credential1.credential_id()); + + std::vector<PasskeyCredential> credentials = + PasskeyCredential::FromCredentialSpecifics(std::vector{ + credential1, + credential2, + credential1_shadow, + }); + + ASSERT_THAT(credentials, + testing::UnorderedElementsAre( + PasskeyCredential(PasskeyCredential::Source::kAndroidPhone, + kRpId, ToUint8Vector(kCredentialIdShadow), + ToUint8Vector(kUserId1), kUserName1, + kUserDisplayName1), + PasskeyCredential(PasskeyCredential::Source::kAndroidPhone, + kRpId, ToUint8Vector(kCredentialId2), + ToUint8Vector(kUserId2), kUserName2, + kUserDisplayName2))); +} + +TEST_F(PasskeyCredentialTest, FromCredentialSpecifics_EmptyOptionalFields) { + sync_pb::WebauthnCredentialSpecifics credential; + credential.set_sync_id(base::RandBytesAsString(16)); + credential.set_credential_id(kCredentialId1.data(), kCredentialId1.size()); + credential.set_rp_id(kRpId); + credential.set_user_id(kUserId1.data(), kUserId1.size()); + + ASSERT_THAT( + PasskeyCredential::FromCredentialSpecifics(std::vector{credential}), + testing::UnorderedElementsAre(PasskeyCredential( + PasskeyCredential::Source::kAndroidPhone, kRpId, + ToUint8Vector(kCredentialId1), ToUint8Vector(kUserId1), "", ""))); +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc index 33e39101..5569e49 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.cc
@@ -71,6 +71,15 @@ #endif } +bool ChangesRequireRerunningCheck(const PasswordStoreChangeList& changes) { + return base::ranges::any_of(changes, [](const auto& change) { + return change.type() == PasswordStoreChange::ADD || + change.type() == PasswordStoreChange::REMOVE || + (change.type() == PasswordStoreChange::UPDATE && + change.password_changed()); + }); +} + #endif // !BUILDFLAG(IS_ANDROID) } // namespace @@ -219,34 +228,37 @@ NotifyInsecureCredentialsChanged(); } -void InsecureCredentialsManager::OnEdited(const CredentialUIEntry& credential) { - // The WeakCheck feature is not available on Android yet. Disable on Android - // to avoid pulling in a big dependency on zxcvbn. -#if !BUILDFLAG(IS_ANDROID) - if (IsCheckForReusedPasswordsEnabled()) { - // Re-run reused check since user might have changed reused password. - StartReuseCheck(); - } - - if (IsCheckForWeakPasswordsEnabled()) { - const std::u16string& password = credential.password; - if (weak_passwords_.contains(password) || !IsWeak(password)) { - // Either the password is already known to be weak, or it is not weak at - // all. In both cases there is nothing to do. - return; - } - - weak_passwords_.insert(password); - NotifyInsecureCredentialsChanged(); - } -#endif -} - // Re-computes the list of insecure credentials with passwords after obtaining a // new list of saved passwords. void InsecureCredentialsManager::OnSavedPasswordsChanged( const PasswordStoreChangeList& changes) { + // Disable on Android to avoid pulling in a big dependency on zxcvbn. +#if !BUILDFLAG(IS_ANDROID) + if (IsCheckForWeakPasswordsEnabled()) { + for (const auto& change : changes) { + if (change.type() == PasswordStoreChange::ADD || + (change.type() == PasswordStoreChange::UPDATE && + change.password_changed())) { + const std::u16string& password = change.form().password_value; + if (!weak_passwords_.contains(password) && IsWeak(password)) { + weak_passwords_.insert(password); + } + } + } + } + if (IsCheckForReusedPasswordsEnabled() && + ChangesRequireRerunningCheck(changes)) { + // Re-run reused check since user might have changed reused password. Don't + // notify observers yet, as they'll be notified on OnReuseCheckDone() + // anyway. + StartReuseCheck(); + } else { + // Notify about changes immediately. + NotifyInsecureCredentialsChanged(); + } +#else NotifyInsecureCredentialsChanged(); +#endif } void InsecureCredentialsManager::NotifyInsecureCredentialsChanged() {
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager.h b/components/password_manager/core/browser/ui/insecure_credentials_manager.h index 9ee6e58..78678ff 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager.h +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager.h
@@ -96,7 +96,6 @@ base::flat_set<std::u16string> reused_passwords); // SavedPasswordsPresenter::Observer: - void OnEdited(const CredentialUIEntry& credential) override; void OnSavedPasswordsChanged(const PasswordStoreChangeList& changes) override; // Notifies observers when insecure credentials have changed.
diff --git a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc index 0843e8a..8e6027ec 100644 --- a/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc +++ b/components/password_manager/core/browser/ui/insecure_credentials_manager_unittest.cc
@@ -121,8 +121,6 @@ return std::u16string(); } - base::HistogramTester& histogram_tester() { return histogram_tester_; } - void AdvanceClock(base::TimeDelta time) { task_env_.AdvanceClock(time); } bool IsGroupingEnabled() { return GetParam(); } @@ -131,7 +129,6 @@ base::test::ScopedFeatureList feature_list_; base::test::TaskEnvironment task_env_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; - base::HistogramTester histogram_tester_; scoped_refptr<TestPasswordStore> store_ = base::MakeRefCounted<TestPasswordStore>(); FakeAffiliationService affiliation_service_; @@ -339,8 +336,9 @@ } TEST_P(InsecureCredentialsManagerTest, StartWeakCheckOnEmptyPasswordsList) { + base::HistogramTester histogram_tester; EXPECT_THAT( - histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"), + histogram_tester.GetTotalCountsForPrefix("PasswordManager.WeakCheck"), IsEmpty()); RunUntilIdle(); @@ -350,12 +348,12 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), IsEmpty()); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 0, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 0, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", kDelay, + 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 0, 1); } TEST_P(InsecureCredentialsManagerTest, WeakCredentialsNotFound) { @@ -365,25 +363,27 @@ store().AddLogin(passwords[0]); store().AddLogin(passwords[1]); + RunUntilIdle(); + + base::HistogramTester histogram_tester; EXPECT_THAT( - histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"), + histogram_tester.GetTotalCountsForPrefix("PasswordManager.WeakCheck"), IsEmpty()); - RunUntilIdle(); provider().StartWeakCheck(); AdvanceClock(base::Milliseconds(2 * kDelay)); RunUntilIdle(); EXPECT_THAT(provider().GetInsecureCredentialEntries(), IsEmpty()); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 2, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - 2 * kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 0, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.PasswordScore", 4, 2); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", + 2 * kDelay, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 0, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.PasswordScore", + 4, 2); } TEST_P(InsecureCredentialsManagerTest, DetectedWeakCredential) { @@ -393,11 +393,13 @@ store().AddLogin(passwords[0]); store().AddLogin(passwords[1]); + RunUntilIdle(); + + base::HistogramTester histogram_tester; EXPECT_THAT( - histogram_tester().GetTotalCountsForPrefix("PasswordManager.WeakCheck"), + histogram_tester.GetTotalCountsForPrefix("PasswordManager.WeakCheck"), IsEmpty()); - RunUntilIdle(); provider().StartWeakCheck(); AdvanceClock(base::Milliseconds(kDelay)); RunUntilIdle(); @@ -405,14 +407,14 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), ElementsAre(CredentialUIEntry(passwords[0]))); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 2, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 1, 1); - histogram_tester().ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore", - 2); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", kDelay, + 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 1, 1); + histogram_tester.ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore", + 2); } // Tests that credentials with the same signon_realm and username, but different @@ -426,8 +428,9 @@ store().AddLogin(passwords[0]); store().AddLogin(passwords[1]); - RunUntilIdle(); + + base::HistogramTester histogram_tester; provider().StartWeakCheck(); AdvanceClock(base::Milliseconds(kDelay)); RunUntilIdle(); @@ -436,14 +439,14 @@ ElementsAre(CredentialUIEntry(passwords[0]), CredentialUIEntry(passwords[1]))); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 2, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 2, 1); - histogram_tester().ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore", - 2); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", kDelay, + 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 2, 1); + histogram_tester.ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore", + 2); } // Tests that credentials with the same signon_realm, username and passwords @@ -456,8 +459,9 @@ store().AddLogin(passwords[0]); store().AddLogin(passwords[1]); - RunUntilIdle(); + + base::HistogramTester histogram_tester; provider().StartWeakCheck(); AdvanceClock(base::Milliseconds(kDelay)); RunUntilIdle(); @@ -465,14 +469,14 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), ElementsAre(CredentialUIEntry(passwords[0]))); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 1, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 1, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.PasswordScore", 0, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", kDelay, + 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 1, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.PasswordScore", + 0, 1); } TEST_P(InsecureCredentialsManagerTest, BothWeakAndCompromisedCredentialsExist) { @@ -486,8 +490,9 @@ store().AddLogin(passwords[0]); store().AddLogin(passwords[1]); - RunUntilIdle(); + + base::HistogramTester histogram_tester; provider().StartWeakCheck(); AdvanceClock(base::Milliseconds(kDelay)); RunUntilIdle(); @@ -505,14 +510,14 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), ElementsAreArray(credentials)); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 2, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 1, 1); - histogram_tester().ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore", - 2); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", kDelay, + 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 1, 1); + histogram_tester.ExpectTotalCount("PasswordManager.WeakCheck.PasswordScore", + 2); } // Checks that for a credential that is both weak and compromised, @@ -526,8 +531,9 @@ {InsecureType::kLeaked, InsecurityMetadata()}); store().AddLogin(passwords[0]); - RunUntilIdle(); + + base::HistogramTester histogram_tester; provider().StartWeakCheck(); AdvanceClock(base::Milliseconds(kDelay)); RunUntilIdle(); @@ -537,14 +543,14 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), ElementsAre(CredentialUIEntry(passwords[0]))); - histogram_tester().ExpectUniqueSample( + histogram_tester.ExpectUniqueSample( "PasswordManager.WeakCheck.CheckedPasswords", 1, 1); - histogram_tester().ExpectUniqueSample("PasswordManager.WeakCheck.Time", - kDelay, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.WeakPasswords", 1, 1); - histogram_tester().ExpectUniqueSample( - "PasswordManager.WeakCheck.PasswordScore", 0, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.Time", kDelay, + 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.WeakPasswords", + 1, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.WeakCheck.PasswordScore", + 0, 1); } #endif // !BUILDFLAG(IS_ANDROID) @@ -1186,6 +1192,8 @@ store().AddLogin(form1); store().AddLogin(form2); RunUntilIdle(); + + base::HistogramTester histogram_tester; provider().StartReuseCheck(); AdvanceClock(base::Milliseconds(kDelay)); RunUntilIdle(); @@ -1193,8 +1201,8 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), ElementsAre(CredentialUIEntry(form1), CredentialUIEntry(form2))); - histogram_tester().ExpectUniqueSample("PasswordManager.ReuseCheck.Time", - kDelay, 1); + histogram_tester.ExpectUniqueSample("PasswordManager.ReuseCheck.Time", kDelay, + 1); } TEST_P(InsecureCredentialsManagerTest, UpdatingReusedPasswordFixesTheIssue) { @@ -1228,6 +1236,45 @@ EXPECT_THAT(provider().GetInsecureCredentialEntries(), IsEmpty()); } +TEST_P(InsecureCredentialsManagerTest, IrrelevantUpdatesDontCauseReuseCheck) { +#if BUILDFLAG(IS_IOS) + base::test::ScopedFeatureList scoped_feature_list( + password_manager::features::kIOSPasswordCheckup); +#else + base::test::ScopedFeatureList scoped_feature_list( + password_manager::features::kPasswordManagerRedesign); +#endif + + PasswordForm form1 = MakeSavedPassword(kExampleCom, kUsername1, kPassword1); + PasswordForm form2 = MakeSavedPassword(kExampleCom, kUsername2, kPassword216); + + store().AddLogin(form1); + store().AddLogin(form2); + RunUntilIdle(); + + base::HistogramTester histogram_tester; + + provider().StartReuseCheck(); + RunUntilIdle(); + + histogram_tester.ExpectTotalCount("PasswordManager.ReuseCheck.Time", 1); + + // Updating leak information doesn't cause a recheck. + CredentialUIEntry updated_credential(form1); + updated_credential.password_issues.insert( + {InsecureType::kLeaked, InsecurityMetadata()}); + presenter().EditSavedCredentials(CredentialUIEntry(form1), + updated_credential); + RunUntilIdle(); + histogram_tester.ExpectTotalCount("PasswordManager.ReuseCheck.Time", 1); + + // Adding a new password on the other hand will cause a recheck. + store().AddLogin(MakeSavedPassword(kExampleCom, kUsername2, kPassword1)); + RunUntilIdle(); + + histogram_tester.ExpectTotalCount("PasswordManager.ReuseCheck.Time", 2); +} + TEST_P(InsecureCredentialsManagerTest, ReuseCheckUsesAffiliationInfo) { if (!IsGroupingEnabled()) { return;
diff --git a/components/permissions/permission_request_manager.cc b/components/permissions/permission_request_manager.cc index 7db2994a..9726659 100644 --- a/components/permissions/permission_request_manager.cc +++ b/components/permissions/permission_request_manager.cc
@@ -544,6 +544,10 @@ } GURL PermissionRequestManager::GetEmbeddingOrigin() const { + if (embedding_origin_for_testing_.has_value()) { + return embedding_origin_for_testing_.value(); + } + return PermissionUtil::GetLastCommittedOriginAsURL( web_contents()->GetPrimaryMainFrame()); }
diff --git a/components/permissions/permission_request_manager.h b/components/permissions/permission_request_manager.h index 4d7ff6e6..066a4f7 100644 --- a/components/permissions/permission_request_manager.h +++ b/components/permissions/permission_request_manager.h
@@ -238,6 +238,10 @@ enabled_app_level_notification_permission_for_testing_ = enabled; } + void set_embedding_origin_for_testing(const GURL& embedding_origin) { + embedding_origin_for_testing_ = embedding_origin; + } + base::ObserverList<Observer>* get_observer_list_for_testing() { CHECK_IS_TEST(); return &observer_list_; @@ -495,6 +499,8 @@ absl::optional<bool> enabled_app_level_notification_permission_for_testing_; + absl::optional<GURL> embedding_origin_for_testing_; + // A timer is used to pre-ignore the permission request if it's been displayed // as a quiet chip. base::OneShotTimer preignore_timer_;
diff --git a/components/remote_cocoa/app_shim/bridged_content_view.mm b/components/remote_cocoa/app_shim/bridged_content_view.mm index fc9c7b30..a7dd841 100644 --- a/components/remote_cocoa/app_shim/bridged_content_view.mm +++ b/components/remote_cocoa/app_shim/bridged_content_view.mm
@@ -18,6 +18,7 @@ #include "components/remote_cocoa/common/native_widget_ns_window_host.mojom.h" #import "ui/base/cocoa/appkit_utils.h" #include "ui/base/cocoa/find_pasteboard.h" +#include "ui/base/cocoa/tracking_area.h" #include "ui/base/dragdrop/drag_drop_types.h" #include "ui/base/dragdrop/os_exchange_data_provider_mac.h" #include "ui/base/ime/input_method.h" @@ -389,10 +390,12 @@ options |= NSTrackingActiveInActiveApp | NSTrackingCursorUpdate; } - _cursorTrackingArea.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect - options:options - owner:self - userInfo:nil]); + base::scoped_nsobject<CrTrackingArea> trackingArea([[CrTrackingArea alloc] + initWithRect:NSZeroRect + options:options + owner:self + userInfo:nil]); + _cursorTrackingArea.reset(trackingArea.get()); [self addTrackingArea:_cursorTrackingArea.get()]; }
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc b/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc index 8b4cb42a..1920a01 100644 --- a/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc +++ b/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
@@ -67,6 +67,29 @@ return gfx::Image::CreateFrom1xBitmap(bitmap); } +// TestBookmarkClient that supports undoing removals. +class TestBookmarkClientWithUndo : public bookmarks::TestBookmarkClient { + public: + explicit TestBookmarkClientWithUndo(BookmarkUndoService* undo_service) + : undo_service_(undo_service) {} + + ~TestBookmarkClientWithUndo() override = default; + + // BookmarkClient overrides. + void OnBookmarkNodeRemovedUndoable( + bookmarks::BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const bookmarks::BookmarkNode* parent, + size_t index, + std::unique_ptr<bookmarks::BookmarkNode> node) override { + undo_service_->AddUndoEntryForRemovedNode(model, undo_provider, parent, + index, std::move(node)); + } + + private: + const raw_ptr<BookmarkUndoService> undo_service_; +}; + class BookmarkModelObserverImplTest : public testing::Test { public: BookmarkModelObserverImplTest() @@ -75,7 +98,9 @@ observer_(nudge_for_commit_closure_.Get(), /*on_bookmark_model_being_deleted_closure=*/base::DoNothing(), bookmark_tracker_.get()), - bookmark_model_(bookmarks::TestBookmarkClient::CreateModel()) { + bookmark_model_(bookmarks::TestBookmarkClient::CreateModelWithClient( + std::make_unique<TestBookmarkClientWithUndo>(&undo_service_))) { + undo_service_.StartObservingBookmarkModel(bookmark_model_.get()); bookmark_model_->AddObserver(&observer_); sync_pb::EntitySpecifics specifics; specifics.mutable_bookmark()->set_legacy_canonicalized_title( @@ -100,6 +125,8 @@ ~BookmarkModelObserverImplTest() override { bookmark_model_->RemoveObserver(&observer_); + bookmark_model_->Shutdown(); + undo_service_.Shutdown(); } void SimulateCommitResponseForAllLocalChanges() { @@ -158,12 +185,14 @@ return static_cast<bookmarks::TestBookmarkClient*>( bookmark_model_->client()); } + UndoManager* undo_manager() { return undo_service_.undo_manager(); } private: NiceMock<base::MockCallback<base::RepeatingClosure>> nudge_for_commit_closure_; std::unique_ptr<SyncedBookmarkTracker> bookmark_tracker_; BookmarkModelObserverImpl observer_; + BookmarkUndoService undo_service_; std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_; }; @@ -917,13 +946,11 @@ ASSERT_FALSE(folder_entity->IsUnsynced()); // Now delete the entity and restore it with the same bookmark node. - BookmarkUndoService undo_service; - undo_service.StartObservingBookmarkModel(bookmark_model()); bookmark_model()->Remove(folder, bookmarks::metrics::BookmarkEditSource::kOther); // The removed bookmark must be saved in the undo service. - ASSERT_EQ(undo_service.undo_manager()->undo_count(), 1u); + ASSERT_GE(undo_manager()->undo_count(), 1u); ASSERT_THAT(bookmark_tracker()->GetEntityForBookmarkNode(folder), IsNull()); // Check that the entity is a tombstone now. @@ -936,8 +963,7 @@ folder_entity); // Restore the removed bookmark. - undo_service.undo_manager()->Undo(); - undo_service.Shutdown(); + undo_manager()->Undo(); EXPECT_EQ(folder_entity, bookmark_tracker()->GetEntityForBookmarkNode(folder));
diff --git a/components/undo/bookmark_undo_service.cc b/components/undo/bookmark_undo_service.cc index 3e16773..db4aca5 100644 --- a/components/undo/bookmark_undo_service.cc +++ b/components/undo/bookmark_undo_service.cc
@@ -348,7 +348,6 @@ DCHECK(!scoped_observations_.IsObservingSource(model)); scoped_observations_.AddObservation(model); observed_models_.insert(model); - model->SetUndoDelegate(this); } void BookmarkUndoService::Shutdown() { @@ -358,9 +357,6 @@ undo_manager_.RemoveAllOperations(); scoped_observations_.RemoveAllObservations(); - for (BookmarkModel* model : observed_models_) { - model->SetUndoDelegate(nullptr); - } observed_models_.clear(); } @@ -415,7 +411,7 @@ undo_manager()->EndGroupingActions(); } -void BookmarkUndoService::OnBookmarkNodeRemoved( +void BookmarkUndoService::AddUndoEntryForRemovedNode( BookmarkModel* model, BookmarkUndoProvider* undo_provider, const BookmarkNode* parent,
diff --git a/components/undo/bookmark_undo_service.h b/components/undo/bookmark_undo_service.h index 6c9148aa..187cbc1 100644 --- a/components/undo/bookmark_undo_service.h +++ b/components/undo/bookmark_undo_service.h
@@ -14,7 +14,6 @@ #include "components/bookmarks/browser/base_bookmark_model_observer.h" #include "components/bookmarks/browser/bookmark_model.h" #include "components/bookmarks/browser/bookmark_node_data.h" -#include "components/bookmarks/browser/bookmark_undo_delegate.h" #include "components/keyed_service/core/keyed_service.h" #include "components/undo/undo_manager.h" @@ -23,7 +22,6 @@ // BookmarkUndoService is owned by the profile, and is responsible for observing // BookmarkModel changes in order to provide an undo for those changes. class BookmarkUndoService : public bookmarks::BaseBookmarkModelObserver, - public bookmarks::BookmarkUndoDelegate, public KeyedService { public: BookmarkUndoService(); @@ -43,6 +41,17 @@ // KeyedService: void Shutdown() override; + // Pushes an undo operation to the stack that allows restoring a deleted + // bookmark. As opposed to other operations, which reach this service via + // BookmarkModelObserver, removals are special-cased to be able to transfer + // ownership of the removed node. + void AddUndoEntryForRemovedNode( + bookmarks::BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const bookmarks::BookmarkNode* parent, + size_t index, + std::unique_ptr<bookmarks::BookmarkNode> node); + private: // bookmarks::BaseBookmarkModelObserver: void BookmarkModelChanged() override {} @@ -64,14 +73,6 @@ bookmarks::BookmarkModel* model) override; void GroupedBookmarkChangesEnded(bookmarks::BookmarkModel* model) override; - // bookmarks::BookmarkUndoDelegate: - void OnBookmarkNodeRemoved( - bookmarks::BookmarkModel* model, - bookmarks::BookmarkUndoProvider* undo_provider, - const bookmarks::BookmarkNode* parent, - size_t index, - std::unique_ptr<bookmarks::BookmarkNode> node) override; - UndoManager undo_manager_; base::flat_set<raw_ptr<bookmarks::BookmarkModel>> observed_models_; base::ScopedMultiSourceObservation<bookmarks::BookmarkModel,
diff --git a/components/undo/bookmark_undo_service_test.cc b/components/undo/bookmark_undo_service_test.cc index c92d0b1..e55e265 100644 --- a/components/undo/bookmark_undo_service_test.cc +++ b/components/undo/bookmark_undo_service_test.cc
@@ -21,6 +21,29 @@ namespace { +// TestBookmarkClient that supports undoing removals. +class TestBookmarkClientWithUndo : public bookmarks::TestBookmarkClient { + public: + explicit TestBookmarkClientWithUndo(BookmarkUndoService* undo_service) + : undo_service_(undo_service) {} + + ~TestBookmarkClientWithUndo() override = default; + + // BookmarkClient overrides. + void OnBookmarkNodeRemovedUndoable( + BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const BookmarkNode* parent, + size_t index, + std::unique_ptr<BookmarkNode> node) override { + undo_service_->AddUndoEntryForRemovedNode(model, undo_provider, parent, + index, std::move(node)); + } + + private: + const raw_ptr<BookmarkUndoService> undo_service_; +}; + class BookmarkUndoServiceTest : public testing::Test { public: BookmarkUndoServiceTest(); @@ -35,8 +58,8 @@ BookmarkUndoService* GetUndoService(); private: - std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_; std::unique_ptr<BookmarkUndoService> bookmark_undo_service_; + std::unique_ptr<bookmarks::BookmarkModel> bookmark_model_; }; BookmarkUndoServiceTest::BookmarkUndoServiceTest() {} @@ -44,8 +67,10 @@ void BookmarkUndoServiceTest::SetUp() { DCHECK(!bookmark_model_); DCHECK(!bookmark_undo_service_); - bookmark_model_ = bookmarks::TestBookmarkClient::CreateModel(); bookmark_undo_service_ = std::make_unique<BookmarkUndoService>(); + bookmark_model_ = bookmarks::TestBookmarkClient::CreateModelWithClient( + std::make_unique<TestBookmarkClientWithUndo>( + bookmark_undo_service_.get())); bookmark_undo_service_->StartObservingBookmarkModel(bookmark_model_.get()); bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model_.get()); }
diff --git a/components/viz/common/gpu/dawn_context_provider.cc b/components/viz/common/gpu/dawn_context_provider.cc index 458cf310..ecba60ad 100644 --- a/components/viz/common/gpu/dawn_context_provider.cc +++ b/components/viz/common/gpu/dawn_context_provider.cc
@@ -83,6 +83,7 @@ features.push_back(wgpu::FeatureName::DawnInternalUsages); features.push_back(wgpu::FeatureName::DepthClipControl); features.push_back(wgpu::FeatureName::Depth32FloatStencil8); + features.push_back(wgpu::FeatureName::ImplicitDeviceSynchronization); descriptor.requiredFeatures = features.data(); descriptor.requiredFeaturesCount = features.size();
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 2375081..707498d 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -1738,11 +1738,17 @@ } if (is_using_vulkan()) { - if (!InitializeForVulkan()) + if (!InitializeForVulkan()) { return false; + } + } else if (is_using_graphite_dawn()) { + if (!InitializeForDawn()) { + return false; + } } else { - if (!InitializeForGL()) + if (!InitializeForGL()) { return false; + } } max_resource_cache_bytes_ = @@ -1957,18 +1963,26 @@ GetDidSwapBuffersCompleteCallback()); } #elif BUILDFLAG(IS_WIN) - std::unique_ptr<SkiaOutputDeviceDawn> output_device = - std::make_unique<SkiaOutputDeviceDawn>( - dawn_context_provider_, gfx::SurfaceOrigin::kTopLeft, - shared_gpu_deps_->memory_tracker(), - GetDidSwapBuffersCompleteCallback()); - const gpu::SurfaceHandle child_window_handle = - output_device->GetChildSurfaceHandle(); - AddChildWindowToBrowser(child_window_handle); - output_device_ = std::move(output_device); + output_device_ = std::make_unique<SkiaOutputDeviceDawn>( + dawn_context_provider_, gfx::SurfaceOrigin::kTopLeft, + shared_gpu_deps_->memory_tracker(), + GetDidSwapBuffersCompleteCallback()); + AddChildWindowToBrowser(output_device_->GetChildSurfaceHandle()); +#elif BUILDFLAG(IS_MAC) + presenter_ = dependency_->CreatePresenter(weak_ptr_factory_.GetWeakPtr(), + gl::GLSurfaceFormat()); + if (features::UseGpuVsync()) { + presenter_->SetVSyncDisplayID(renderer_settings_.display_id); + } + output_device_ = std::make_unique<SkiaOutputDeviceBufferQueue>( + std::make_unique<OutputPresenterGL>( + presenter_, dependency_, shared_image_factory_.get(), + shared_image_representation_factory_.get()), + dependency_, shared_image_representation_factory_.get(), + shared_gpu_deps_->memory_tracker(), + GetDidSwapBuffersCompleteCallback()); #else - NOTREACHED(); - return false; + NOTREACHED_NORETURN(); #endif } #endif
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index f382afa..0f0b23f 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -336,6 +336,11 @@ return gpu_preferences_.gr_context_type == gpu::GrContextType::kGL; } + bool is_using_graphite_dawn() const { + return !!dawn_context_provider_ && gpu_preferences_.gr_context_type == + gpu::GrContextType::kGraphiteDawn; + } + // Helper for `CopyOutput()` method, handles the RGBA format. void CopyOutputRGBA(SkSurface* surface, copy_output::RenderPassGeometry geometry,
diff --git a/components/webapps/browser/android/add_to_homescreen_mediator.cc b/components/webapps/browser/android/add_to_homescreen_mediator.cc index 360dba7..43fc01e 100644 --- a/components/webapps/browser/android/add_to_homescreen_mediator.cc +++ b/components/webapps/browser/android/add_to_homescreen_mediator.cc
@@ -80,7 +80,8 @@ } // In this code path (show A2HS dialog from app banner), a maskable primary // icon isn't padded yet. We'll need to pad it here. - SetIcon(params_->primary_icon, params_->HasMaskablePrimaryIcon()); + SetIcon(params_->primary_icon, + params_->has_maskable_primary_icon /*need_to_add_padding*/); } void AddToHomescreenMediator::StartForAppMenu( @@ -146,7 +147,7 @@ base::android::ScopedJavaLocalRef<jobject> java_bitmap = gfx::ConvertToJavaBitmap(display_icon); Java_AddToHomescreenMediator_setIcon(env, java_ref_, java_bitmap, - params_->HasMaskablePrimaryIcon(), + params_->has_maskable_primary_icon, need_to_add_padding); } @@ -182,6 +183,8 @@ : AddToHomescreenParams::AppType::SHORTCUT; params_->shortcut_info = std::make_unique<ShortcutInfo>(info); params_->primary_icon = data_fetcher_->primary_icon(); + params_->has_maskable_primary_icon = + data_fetcher_->has_maskable_primary_icon(); params_->install_source = InstallableMetrics::GetInstallSource( data_fetcher_->web_contents(), InstallTrigger::MENU); params_->installable_status = status_code;
diff --git a/components/webapps/browser/android/add_to_homescreen_params.cc b/components/webapps/browser/android/add_to_homescreen_params.cc index b5f6252..9a21377 100644 --- a/components/webapps/browser/android/add_to_homescreen_params.cc +++ b/components/webapps/browser/android/add_to_homescreen_params.cc
@@ -16,9 +16,4 @@ : native_app_package_name; } -bool AddToHomescreenParams::HasMaskablePrimaryIcon() { - return app_type != AddToHomescreenParams::AppType::NATIVE && - shortcut_info->is_primary_icon_maskable; -} - } // namespace webapps
diff --git a/components/webapps/browser/android/add_to_homescreen_params.h b/components/webapps/browser/android/add_to_homescreen_params.h index e446ec1..0ed66567 100644 --- a/components/webapps/browser/android/add_to_homescreen_params.h +++ b/components/webapps/browser/android/add_to_homescreen_params.h
@@ -31,6 +31,7 @@ AppType app_type; SkBitmap primary_icon; + bool has_maskable_primary_icon = false; std::unique_ptr<ShortcutInfo> shortcut_info; WebappInstallSource install_source; InstallableStatusCode installable_status; @@ -41,7 +42,6 @@ ~AddToHomescreenParams(); std::string GetAppIdentifier(); - bool HasMaskablePrimaryIcon(); }; } // namespace webapps
diff --git a/components/webapps/browser/android/ambient_badge_manager.cc b/components/webapps/browser/android/ambient_badge_manager.cc index 3b63848..8b16219 100644 --- a/components/webapps/browser/android/ambient_badge_manager.cc +++ b/components/webapps/browser/android/ambient_badge_manager.cc
@@ -228,7 +228,7 @@ base::MakeRefCounted<segmentation_platform::InputContext>(); input_context->metadata_args.emplace("url", validated_url_); input_context->metadata_args.emplace("maskable_icon", - a2hs_params_->HasMaskablePrimaryIcon()); + a2hs_params_->has_maskable_primary_icon); segmentation_platform_service_->GetClassificationResult( segmentation_platform::kWebAppInstallationPromoKey, prediction_options, input_context, @@ -312,11 +312,11 @@ messages::kMessagesForAndroidInfrastructure)) { message_controller_.EnqueueMessage( web_contents_.get(), app_name_, a2hs_params_->primary_icon, - a2hs_params_->HasMaskablePrimaryIcon(), url); + a2hs_params_->has_maskable_primary_icon, url); } else { InstallableAmbientBadgeInfoBarDelegate::Create( web_contents_.get(), weak_factory_.GetWeakPtr(), app_name_, - a2hs_params_->primary_icon, a2hs_params_->HasMaskablePrimaryIcon(), + a2hs_params_->primary_icon, a2hs_params_->has_maskable_primary_icon, url); } }
diff --git a/components/webapps/browser/android/app_banner_manager_android.cc b/components/webapps/browser/android/app_banner_manager_android.cc index d45262d..2ed893dc 100644 --- a/components/webapps/browser/android/app_banner_manager_android.cc +++ b/components/webapps/browser/android/app_banner_manager_android.cc
@@ -190,9 +190,9 @@ if (native_app_data_.is_null()) { a2hs_params->app_type = AddToHomescreenParams::AppType::WEBAPK; a2hs_params->shortcut_info = ShortcutInfo::CreateShortcutInfo( - manifest_url_, manifest(), primary_icon_url_, - has_maskable_primary_icon_); + manifest_url_, manifest(), primary_icon_url_); a2hs_params->install_source = install_source; + a2hs_params->has_maskable_primary_icon = has_maskable_primary_icon_; } else { a2hs_params->app_type = AddToHomescreenParams::AppType::NATIVE; a2hs_params->native_app_data = native_app_data_;
diff --git a/components/webapps/browser/android/shortcut_info.cc b/components/webapps/browser/android/shortcut_info.cc index bf144cf..34c420f6 100644 --- a/components/webapps/browser/android/shortcut_info.cc +++ b/components/webapps/browser/android/shortcut_info.cc
@@ -54,8 +54,7 @@ std::unique_ptr<ShortcutInfo> ShortcutInfo::CreateShortcutInfo( const GURL& manifest_url, const blink::mojom::Manifest& manifest, - const GURL& primary_icon_url, - bool primary_icon_maskable) { + const GURL& primary_icon_url) { if (blink::IsEmptyManifest(manifest)) { return nullptr; } @@ -64,7 +63,6 @@ shortcut_info->UpdateFromManifest(manifest); shortcut_info->manifest_url = manifest_url; shortcut_info->best_primary_icon_url = primary_icon_url; - shortcut_info->is_primary_icon_maskable = primary_icon_maskable; shortcut_info->UpdateBestSplashIcon(manifest); return shortcut_info; }
diff --git a/components/webapps/browser/android/shortcut_info.h b/components/webapps/browser/android/shortcut_info.h index 72235948..f7d82c8 100644 --- a/components/webapps/browser/android/shortcut_info.h +++ b/components/webapps/browser/android/shortcut_info.h
@@ -56,8 +56,7 @@ static std::unique_ptr<ShortcutInfo> CreateShortcutInfo( const GURL& manifest_url, const blink::mojom::Manifest& manifest, - const GURL& primary_icon_url, - bool primary_icon_maskable); + const GURL& primary_icon_url); // This enum is used to back a UMA histogram, and must be treated as // append-only. @@ -155,10 +154,9 @@ absl::optional<SkColor> background_color; int ideal_splash_image_size_in_px = 0; int minimum_splash_image_size_in_px = 0; - GURL best_primary_icon_url; - bool is_primary_icon_maskable = false; GURL splash_image_url; bool is_splash_image_maskable = false; + GURL best_primary_icon_url; std::vector<std::string> icon_urls; std::vector<GURL> screenshot_urls; absl::optional<ShareTarget> share_target;
diff --git a/components/webapps/browser/android/webapk/webapk_proto_builder.cc b/components/webapps/browser/android/webapk/webapk_proto_builder.cc index 1e2501c7..ad15b31 100644 --- a/components/webapps/browser/android/webapk/webapk_proto_builder.cc +++ b/components/webapps/browser/android/webapk/webapk_proto_builder.cc
@@ -95,6 +95,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -175,7 +176,7 @@ webapk::Image* best_primary_icon_image = web_app_manifest->add_icons(); best_primary_icon_image->set_image_data(primary_icon_data); best_primary_icon_image->add_usages(webapk::Image::PRIMARY_ICON); - if (shortcut_info.is_primary_icon_maskable) { + if (is_primary_icon_maskable) { best_primary_icon_image->add_purposes(webapk::Image::MASKABLE); } else { best_primary_icon_image->add_purposes(webapk::Image::ANY); @@ -210,7 +211,7 @@ image->set_image_data(it->second.unsafe_data); } image->add_usages(webapk::Image::PRIMARY_ICON); - if (shortcut_info.is_primary_icon_maskable) { + if (is_primary_icon_maskable) { image->add_purposes(webapk::Image::MASKABLE); } else { image->add_purposes(webapk::Image::ANY); @@ -279,6 +280,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -290,7 +292,8 @@ GetBackgroundTaskRunner()->PostTaskAndReplyWithResult( FROM_HERE, base::BindOnce(&webapps::BuildProtoInBackground, shortcut_info, app_key, - primary_icon_data, splash_icon_data, package_name, version, + primary_icon_data, is_primary_icon_maskable, + splash_icon_data, package_name, version, std::move(icon_url_to_murmur2_hash), is_manifest_stale, is_app_identity_update_supported, std::vector<webapps::WebApkUpdateReason>()), @@ -305,6 +308,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -316,8 +320,9 @@ base::BlockingType::MAY_BLOCK); std::unique_ptr<std::string> proto = BuildProtoInBackground( - shortcut_info, app_key, primary_icon_data, splash_icon_data, package_name, - version, std::move(icon_url_to_murmur2_hash), is_manifest_stale, + shortcut_info, app_key, primary_icon_data, is_primary_icon_maskable, + splash_icon_data, package_name, version, + std::move(icon_url_to_murmur2_hash), is_manifest_stale, is_app_identity_update_supported, std::move(update_reasons)); // Create directory if it does not exist.
diff --git a/components/webapps/browser/android/webapk/webapk_proto_builder.h b/components/webapps/browser/android/webapk/webapk_proto_builder.h index ce0b9d2a..94994a4 100644 --- a/components/webapps/browser/android/webapk/webapk_proto_builder.h +++ b/components/webapps/browser/android/webapk/webapk_proto_builder.h
@@ -31,6 +31,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -45,6 +46,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version, @@ -62,6 +64,7 @@ const webapps::ShortcutInfo& shortcut_info, const GURL& app_key, const std::string& primary_icon_data, + bool is_primary_icon_maskable, const std::string& splash_icon_data, const std::string& package_name, const std::string& version,
diff --git a/components/webapps/browser/android/webapk/webapk_proto_builder_unittest.cc b/components/webapps/browser/android/webapk/webapk_proto_builder_unittest.cc index 5b14f15..91bf13c 100644 --- a/components/webapps/browser/android/webapk/webapk_proto_builder_unittest.cc +++ b/components/webapps/browser/android/webapk/webapk_proto_builder_unittest.cc
@@ -68,7 +68,8 @@ info.shortcut_items.back().icons.back().src = shortcut_url; } - webapps::BuildProto(info, app_key, primary_icon_data, splash_icon_data, + webapps::BuildProto(info, app_key, primary_icon_data, + false /* is_primary_icon_maskable */, splash_icon_data, "" /* package_name */, "" /* version */, std::move(icon_url_to_murmur2_hash), is_manifest_stale, is_app_identity_update_supported,
diff --git a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm index e6ae7d2..a211fd0 100644 --- a/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/web_contents_view_cocoa.mm
@@ -161,11 +161,12 @@ gfx::PointF(screenPoint.x, screenFrame.size.height - screenPoint.y); NSPasteboard* pboard = [nsInfo draggingPasteboard]; - NSArray<NSString*>* urls; - NSArray<NSString*>* titles; - if (ui::clipboard_util::URLsAndTitlesFromPasteboard( - pboard, /*include_files=*/true, &urls, &titles)) { - info->url = GURL(base::SysNSStringToUTF8(urls.firstObject)); + NSArray<URLAndTitle*>* urls_and_titles = + ui::clipboard_util::URLsAndTitlesFromPasteboard(pboard, + /*include_files=*/true); + + if (urls_and_titles.count) { + info->url = GURL(base::SysNSStringToUTF8(urls_and_titles.firstObject.URL)); } info->operation_mask = ui::DragDropTypes::NSDragOperationToDragOperation( [nsInfo draggingSourceOperationMask]);
diff --git a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc index 6f45234..7005fc4 100644 --- a/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc +++ b/content/browser/accessibility/ax_platform_node_textrangeprovider_win_browsertest.cc
@@ -1602,8 +1602,8 @@ std::vector<std::wstring> paragraphs = { L"start", - L"text with [:before] and [:after]content, then a\n\xFFFC", - L"bold element with a [block]before content then a italic\n\xFFFC", + L"text with [:before] and [:after]content, then a", + L"bold element with a [block]before content then a italic", L"element with a [block] after content", L"end", }; @@ -1964,7 +1964,7 @@ std::vector<std::wstring> paragraphs = { L"start", - L"text with [:before] and [:after]content, then a\n\xFFFC", + L"text with [:before] and [:after]content, then a", L"bold element", };
diff --git a/content/browser/accessibility/ax_platform_node_win_browsertest.cc b/content/browser/accessibility/ax_platform_node_win_browsertest.cc index 9db86f2..cab493b 100644 --- a/content/browser/accessibility/ax_platform_node_win_browsertest.cc +++ b/content/browser/accessibility/ax_platform_node_win_browsertest.cc
@@ -271,7 +271,7 @@ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML( <!DOCTYPE html> <html> - <body role="none"> + <body> <dialog open>Example Text</dialog> </body> </html> @@ -287,7 +287,7 @@ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML( <!DOCTYPE html> <html> - <body role="none"> + <body> <dialog open aria-modal="false">Example Text</dialog> </body> </html> @@ -303,7 +303,7 @@ LoadInitialAccessibilityTreeFromHtml(std::string(R"HTML( <!DOCTYPE html> <html> - <body role="none"> + <body> <dialog open aria-modal="true">Example Text</dialog> </body> </html>
diff --git a/content/browser/download/download_manager_impl.cc b/content/browser/download/download_manager_impl.cc index d25b1e3..e941131 100644 --- a/content/browser/download/download_manager_impl.cc +++ b/content/browser/download/download_manager_impl.cc
@@ -1222,7 +1222,7 @@ return count; } -int DownloadManagerImpl::NonMaliciousInProgressCount() { +int DownloadManagerImpl::BlockingShutdownCount() { int count = 0; for (const auto& it : downloads_by_guid_) { download::DownloadItemImpl* download = it.second; @@ -1241,7 +1241,11 @@ download->GetDangerType() != download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS && it.second->GetDangerType() != - download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE) { + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE && + it.second->GetDangerType() != + download::DOWNLOAD_DANGER_TYPE_UNCOMMON_CONTENT && + it.second->GetDangerType() != + download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING) { ++count; } }
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h index fdc6d7f..a57d350e 100644 --- a/content/browser/download/download_manager_impl.h +++ b/content/browser/download/download_manager_impl.h
@@ -142,7 +142,7 @@ void PostInitialization(DownloadInitializationDependency dependency) override; bool IsManagerInitialized() override; int InProgressCount() override; - int NonMaliciousInProgressCount() override; + int BlockingShutdownCount() override; BrowserContext* GetBrowserContext() override; void CheckForHistoryFilesRemoval() override; void OnHistoryQueryComplete(
diff --git a/content/browser/download/download_manager_impl_unittest.cc b/content/browser/download/download_manager_impl_unittest.cc index 6c3505d3..d8c6b4a 100644 --- a/content/browser/download/download_manager_impl_unittest.cc +++ b/content/browser/download/download_manager_impl_unittest.cc
@@ -248,6 +248,7 @@ EXPECT_CALL(*result, GetId()) .WillRepeatedly(Return(download_id)); EXPECT_CALL(*result, GetGuid()).WillRepeatedly(ReturnRefOfCopy(guid)); + EXPECT_CALL(*result, IsTransient()).WillRepeatedly(Return(transient)); items_[download_id] = result; return result; } @@ -302,6 +303,7 @@ .WillRepeatedly(Return(download::DOWNLOAD_INTERRUPT_REASON_NONE)); EXPECT_CALL(*result, IsPaused()).WillRepeatedly(Return(false)); EXPECT_CALL(*result, IsTemporary()).WillRepeatedly(Return(false)); + EXPECT_CALL(*result, IsTransient()).WillRepeatedly(Return(info.transient)); if (is_download_persistent_) { EXPECT_CALL(*result, RemoveObserver(_)); @@ -897,6 +899,35 @@ } } +TEST_F(DownloadManagerTest, BlockingShutdownCount) { + download::MockDownloadItemImpl& item(AddItemToManager()); + + EXPECT_CALL(item, GetState()) + .WillRepeatedly(Return(download::DownloadItem::COMPLETE)); + EXPECT_EQ(download_manager_->BlockingShutdownCount(), 0); + + EXPECT_CALL(item, GetState()) + .WillRepeatedly(Return(download::DownloadItem::IN_PROGRESS)); + EXPECT_EQ(download_manager_->BlockingShutdownCount(), 1); + + const download::DownloadDangerType kDangerTypes[] = { + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL, + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT, + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST, + download::DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED, + download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS, + download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE, + download::DOWNLOAD_DANGER_TYPE_PROMPT_FOR_SCANNING}; + for (download::DownloadDangerType danger_type : kDangerTypes) { + SCOPED_TRACE(testing::Message() + << "Failed for danger type " + << download::GetDownloadDangerTypeString(danger_type) + << std::endl); + EXPECT_CALL(item, GetDangerType()).WillRepeatedly(Return(danger_type)); + EXPECT_EQ(download_manager_->BlockingShutdownCount(), 0); + } +} + class DownloadManagerWithExpirationTest : public DownloadManagerTest { public: DownloadManagerWithExpirationTest() {
diff --git a/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm b/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm index ad16a476..f398f1b6 100644 --- a/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm +++ b/content/browser/media/capture/mouse_cursor_overlay_controller_mac.mm
@@ -41,10 +41,12 @@ NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect | NSTrackingEnabledDuringMouseDrag; - _trackingArea.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect - options:kTrackingOptions - owner:self - userInfo:nil]); + base::scoped_nsobject<CrTrackingArea> trackingArea([[CrTrackingArea alloc] + initWithRect:NSZeroRect + options:kTrackingOptions + owner:self + userInfo:nil]); + _trackingArea.reset(trackingArea.get()); [nsView addTrackingArea:_trackingArea.get()]; } return self;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc index a340151..5e93e714 100644 --- a/content/browser/web_contents/web_contents_impl_browsertest.cc +++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -460,14 +460,12 @@ NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"))); // Navigate to an invalid URL and make sure it doesn't leave a pending entry. - LoadStopNotificationObserver load_observer1( - &shell()->web_contents()->GetController()); + LoadStopObserver load_observer1(shell()->web_contents()); ASSERT_TRUE(ExecJs(shell(), "window.location.href=\"nonexistent:12121\";")); load_observer1.Wait(); EXPECT_FALSE(shell()->web_contents()->GetController().GetPendingEntry()); - LoadStopNotificationObserver load_observer2( - &shell()->web_contents()->GetController()); + LoadStopObserver load_observer2(shell()->web_contents()); ASSERT_TRUE(ExecJs(shell(), "window.location.href=\"#foo\";")); load_observer2.Wait(); EXPECT_EQ(embedded_test_server()->GetURL("/title1.html#foo"), @@ -691,8 +689,7 @@ new LoadingStateChangedDelegate()); shell()->web_contents()->SetDelegate(delegate.get()); - LoadStopNotificationObserver load_observer( - &shell()->web_contents()->GetController()); + LoadStopObserver load_observer(shell()->web_contents()); TitleWatcher title_watcher(shell()->web_contents(), u"pushState"); EXPECT_TRUE(NavigateToURL( shell(), embedded_test_server()->GetURL("/push_state.html")));
diff --git a/content/browser/web_contents/web_drag_dest_mac.mm b/content/browser/web_contents/web_drag_dest_mac.mm index 4a7153d..786f17d 100644 --- a/content/browser/web_contents/web_drag_dest_mac.mm +++ b/content/browser/web_contents/web_drag_dest_mac.mm
@@ -409,12 +409,14 @@ // Get URL if possible. To avoid exposing file system paths to web content, // filenames in the drag are not converted to file URLs. - NSArray<NSString*>* urls; - NSArray<NSString*>* titles; - if (ui::clipboard_util::URLsAndTitlesFromPasteboard( - pboard, /*include_files=*/false, &urls, &titles)) { - drop_data.url = GURL(base::SysNSStringToUTF8(urls.firstObject)); - drop_data.url_title = base::SysNSStringToUTF16(titles.firstObject); + NSArray<URLAndTitle*>* urls_and_titles = + ui::clipboard_util::URLsAndTitlesFromPasteboard(pboard, + /*include_files=*/false); + if (urls_and_titles.count) { + drop_data.url = + GURL(base::SysNSStringToUTF8(urls_and_titles.firstObject.URL)); + drop_data.url_title = + base::SysNSStringToUTF16(urls_and_titles.firstObject.title); } // Get plain text.
diff --git a/content/public/browser/download_manager.h b/content/public/browser/download_manager.h index af60df6..9da8131 100644 --- a/content/public/browser/download_manager.h +++ b/content/public/browser/download_manager.h
@@ -186,11 +186,11 @@ // is too slow, use an AllDownloadItemNotifier to count in-progress items. virtual int InProgressCount() = 0; - // The number of in progress (including paused) downloads. + // The number of in progress (including paused) downloads that should block + // shutdown. This excludes downloads that are marked as malicious. // Performance note: this loops over all items. If profiling finds that this // is too slow, use an AllDownloadItemNotifier to count in-progress items. - // This excludes downloads that are marked as malicious. - virtual int NonMaliciousInProgressCount() = 0; + virtual int BlockingShutdownCount() = 0; virtual BrowserContext* GetBrowserContext() = 0;
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 07fc5d2..cdb7ad4 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -780,9 +780,7 @@ // In many cases, the load may have finished before we get here. Only wait if // the tab still has a pending navigation. if (web_contents->IsLoading()) { - WindowedNotificationObserver load_stop_observer( - NOTIFICATION_LOAD_STOP, - Source<NavigationController>(&web_contents->GetController())); + LoadStopObserver load_stop_observer(web_contents); load_stop_observer.Wait(); } }
diff --git a/content/public/test/mock_download_manager.h b/content/public/test/mock_download_manager.h index 0634ce39..1dee08df 100644 --- a/content/public/test/mock_download_manager.h +++ b/content/public/test/mock_download_manager.h
@@ -159,7 +159,7 @@ void(DownloadInitializationDependency dependency)); MOCK_METHOD0(IsManagerInitialized, bool()); MOCK_METHOD0(InProgressCount, int()); - MOCK_METHOD0(NonMaliciousInProgressCount, int()); + MOCK_METHOD0(BlockingShutdownCount, int()); MOCK_METHOD0(GetBrowserContext, BrowserContext*()); MOCK_METHOD0(CheckForHistoryFilesRemoval, void()); MOCK_METHOD1(GetDownload, download::DownloadItem*(uint32_t id));
diff --git a/content/test/data/accessibility/css/before-after-block-expected-blink.txt b/content/test/data/accessibility/css/before-after-block-expected-blink.txt index 97be2e6..8cb1b0a2 100644 --- a/content/test/data/accessibility/css/before-after-block-expected-blink.txt +++ b/content/test/data/accessibility/css/before-after-block-expected-blink.txt
@@ -5,7 +5,7 @@ ++++++++staticText name='A' ++++++++++inlineTextBox name='A' ++++++++genericContainer ignored htmlTag='b' -++++++++++genericContainer htmlTag='::before' +++++++++++genericContainer ignored htmlTag='::before' ++++++++++staticText name='bold' ++++++++++++inlineTextBox name='bold' ++++++++staticText name=' element'
diff --git a/content/test/data/accessibility/css/before-after-code-expected-android-external.txt b/content/test/data/accessibility/css/before-after-code-expected-android-external.txt index f174c0f..f1ca5d2f 100644 --- a/content/test/data/accessibility/css/before-after-code-expected-android-external.txt +++ b/content/test/data/accessibility/css/before-after-code-expected-android-external.txt
@@ -1,27 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"start" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++TextView text:"text with " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"[" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:":before" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"]" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:" and " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"[" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:":after" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"]" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:" content, then a" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++TextView text:"bold" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:" element with a " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"[" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"block" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"]" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:" before content then a " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"italic" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++TextView text:"element with a " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"[" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"block" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:"]" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++TextView text:" after content" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++TextView text:"end" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++TextView text:"text with [:before] and [:after] content, then abold element with a [block] before content then a italicelement with a [block] after content" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] +++TextView text:"end" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/css/transform-expected-blink.txt b/content/test/data/accessibility/css/transform-expected-blink.txt index 1f3a20e39..6a0ad03 100644 --- a/content/test/data/accessibility/css/transform-expected-blink.txt +++ b/content/test/data/accessibility/css/transform-expected-blink.txt
@@ -1,7 +1,7 @@ rootWebArea pageLocation=(0, 0) ++genericContainer ignored -++++genericContainer pageLocation=(0, 50) +++++genericContainer ignored ++++++genericContainer pageLocation=(0, 50) ++++++++paragraph pageLocation=(0, 50) ++++++++++staticText pageLocation=(0, 50) name='content' -++++++++++++inlineTextBox pageLocation=(0, 50) name='content' \ No newline at end of file +++++++++++++inlineTextBox pageLocation=(0, 50) name='content'
diff --git a/content/test/data/accessibility/css/transform-expected-mac.txt b/content/test/data/accessibility/css/transform-expected-mac.txt index 7f9e696..27d0ef6 100644 --- a/content/test/data/accessibility/css/transform-expected-mac.txt +++ b/content/test/data/accessibility/css/transform-expected-mac.txt
@@ -1,5 +1,4 @@ AXWebArea LocalPosition={x: 0, y: 0} ++AXGroup LocalPosition={x: 0, y: 50} ++++AXGroup LocalPosition={x: 0, y: 50} -++++++AXGroup LocalPosition={x: 0, y: 50} -++++++++AXStaticText AXValue='content' LocalPosition={x: 0, y: 50} \ No newline at end of file +++++++AXStaticText AXValue='content' LocalPosition={x: 0, y: 50}
diff --git a/content/test/data/accessibility/css/transform-expected-uia-win.txt b/content/test/data/accessibility/css/transform-expected-uia-win.txt index 195fb43..1b1d409 100644 --- a/content/test/data/accessibility/css/transform-expected-uia-win.txt +++ b/content/test/data/accessibility/css/transform-expected-uia-win.txt
@@ -1,5 +1,4 @@ Document ++Group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false ++++Group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false -++++++Group BoundingRectangle=(0, 50, 48, 18) IsControlElement=false -++++++++Text BoundingRectangle=(0, 50, 48, 17) Name='content' \ No newline at end of file +++++++Text BoundingRectangle=(0, 50, 48, 17) Name='content'
diff --git a/content/test/data/accessibility/css/transform-expected-win.txt b/content/test/data/accessibility/css/transform-expected-win.txt index 29e014fe..b270fecb 100644 --- a/content/test/data/accessibility/css/transform-expected-win.txt +++ b/content/test/data/accessibility/css/transform-expected-win.txt
@@ -1,5 +1,4 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE location=(0, 0) ++IA2_ROLE_SECTION location=(0, 50) -++++IA2_ROLE_SECTION location=(0, 50) -++++++IA2_ROLE_PARAGRAPH location=(0, 50) -++++++++ROLE_SYSTEM_STATICTEXT name='content' location=(0, 50) \ No newline at end of file +++++IA2_ROLE_PARAGRAPH location=(0, 50) +++++++ROLE_SYSTEM_STATICTEXT name='content' location=(0, 50)
diff --git a/content/test/data/accessibility/html/bounds-fixed-expected-blink.txt b/content/test/data/accessibility/html/bounds-fixed-expected-blink.txt index 199c949..a110ddf4 100644 --- a/content/test/data/accessibility/html/bounds-fixed-expected-blink.txt +++ b/content/test/data/accessibility/html/bounds-fixed-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea clipsChildren=true ++genericContainer ignored -++++genericContainer +++++genericContainer ignored ++++++genericContainer size=(200, 200) pageSize=(200, 200) unclippedSize=(200, 200) clipsChildren=true ++++++++dialog size=(200, 200) pageLocation=(150, 50) pageSize=(200, 200) unclippedLocation=(150, 50) unclippedSize=(200, 200) ++++++++++button size=(160, 50) pageSize=(160, 50) name='Button 1' @@ -8,4 +8,4 @@ ++++++++++++++inlineTextBox name='Button 1' ++++++++++button size=(160, 50) pageSize=(160, 50) name='Button 2' ++++++++++++staticText name='Button 2' -++++++++++++++inlineTextBox name='Button 2' \ No newline at end of file +++++++++++++++inlineTextBox name='Button 2'
diff --git a/content/test/data/accessibility/html/dialog-expected-android-external.txt b/content/test/data/accessibility/html/dialog-expected-android-external.txt index 3fdbff1..0faee2b 100644 --- a/content/test/data/accessibility/html/dialog-expected-android-external.txt +++ b/content/test/data/accessibility/html/dialog-expected-android-external.txt
@@ -1,3 +1,2 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++Dialog text:"Text in dialog" paneTitle:"dialog opened." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] +++Dialog text:"Text in dialog" paneTitle:"dialog opened." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-android.txt b/content/test/data/accessibility/html/dialog-expected-android.txt index 61f6832..a00521f8 100644 --- a/content/test/data/accessibility/html/dialog-expected-android.txt +++ b/content/test/data/accessibility/html/dialog-expected-android.txt
@@ -1,3 +1,2 @@ android.webkit.WebView focusable focused scrollable -++android.view.View -++++android.app.Dialog role_description='dialog' name='Text in dialog' +++android.app.Dialog role_description='dialog' name='Text in dialog' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-auralinux.txt b/content/test/data/accessibility/html/dialog-expected-auralinux.txt index 9e646d0..1678791c 100644 --- a/content/test/data/accessibility/html/dialog-expected-auralinux.txt +++ b/content/test/data/accessibility/html/dialog-expected-auralinux.txt
@@ -1,4 +1,3 @@ [document web] -++[section] -++++[dialog] -++++++[static] name='Text in dialog' \ No newline at end of file +++[dialog] +++++[static] name='Text in dialog'
diff --git a/content/test/data/accessibility/html/dialog-expected-blink.txt b/content/test/data/accessibility/html/dialog-expected-blink.txt index c457d0b..2031cd98 100644 --- a/content/test/data/accessibility/html/dialog-expected-blink.txt +++ b/content/test/data/accessibility/html/dialog-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea ++genericContainer ignored -++++genericContainer +++++genericContainer ignored ++++++dialog ++++++++staticText name='Text in dialog' -++++++++++inlineTextBox name='Text in dialog' \ No newline at end of file +++++++++++inlineTextBox name='Text in dialog'
diff --git a/content/test/data/accessibility/html/dialog-expected-fuchsia.txt b/content/test/data/accessibility/html/dialog-expected-fuchsia.txt index 3313a1b..0f7f56d 100644 --- a/content/test/data/accessibility/html/dialog-expected-fuchsia.txt +++ b/content/test/data/accessibility/html/dialog-expected-fuchsia.txt
@@ -1,6 +1,6 @@ UNKNOWN focusable has_input_focus ++UNKNOWN hidden -++++UNKNOWN +++++UNKNOWN hidden ++++++UNKNOWN ++++++++STATIC_TEXT label='Text in dialog' -++++++++++UNKNOWN label='Text in dialog' +++++++++++UNKNOWN label='Text in dialog' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-mac.txt b/content/test/data/accessibility/html/dialog-expected-mac.txt index 65bb711..d5017e9 100644 --- a/content/test/data/accessibility/html/dialog-expected-mac.txt +++ b/content/test/data/accessibility/html/dialog-expected-mac.txt
@@ -1,4 +1,3 @@ AXWebArea -++AXGroup -++++AXGroup AXSubrole=AXApplicationDialog -++++++AXStaticText AXValue='Text in dialog' \ No newline at end of file +++AXGroup AXSubrole=AXApplicationDialog +++++AXStaticText AXValue='Text in dialog'
diff --git a/content/test/data/accessibility/html/dialog-expected-uia-win.txt b/content/test/data/accessibility/html/dialog-expected-uia-win.txt index db74f7a..002cbb2 100644 --- a/content/test/data/accessibility/html/dialog-expected-uia-win.txt +++ b/content/test/data/accessibility/html/dialog-expected-uia-win.txt
@@ -1,4 +1,3 @@ Document -++Group IsControlElement=false -++++Window IsControlElement=false Window.IsModal=false -++++++Text Name='Text in dialog' \ No newline at end of file +++Window IsControlElement=false Window.IsModal=false +++++Text Name='Text in dialog'
diff --git a/content/test/data/accessibility/html/dialog-expected-win.txt b/content/test/data/accessibility/html/dialog-expected-win.txt index e91b184..5cecfd7d 100644 --- a/content/test/data/accessibility/html/dialog-expected-win.txt +++ b/content/test/data/accessibility/html/dialog-expected-win.txt
@@ -1,4 +1,3 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE -++IA2_ROLE_SECTION -++++ROLE_SYSTEM_DIALOG -++++++ROLE_SYSTEM_STATICTEXT name='Text in dialog' \ No newline at end of file +++ROLE_SYSTEM_DIALOG +++++ROLE_SYSTEM_STATICTEXT name='Text in dialog'
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt index 5384852..4465176 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-android.txt
@@ -1,6 +1,5 @@ android.webkit.WebView focusable focused scrollable ++android.view.View -++++android.view.View -++++++android.view.View scrollable -++++android.view.View -++++++android.view.View scrollable +++++android.view.View scrollable +++android.view.View +++++android.view.View scrollable
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt index cdc46a31..1c48268 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-auralinux.txt
@@ -1,6 +1,5 @@ [document web] -++[section] -++++[internal frame] -++++++[document web] -++++[internal frame] -++++++[document web] \ No newline at end of file +++[internal frame] +++++[document web] +++[internal frame] +++++[document web] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt index 9e7554c..3e04afa 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea ++genericContainer ignored -++++genericContainer +++++genericContainer ignored ++++++iframe ++++++++rootWebArea ++++++++++genericContainer ignored @@ -8,4 +8,4 @@ ++++++iframe ++++++++rootWebArea ++++++++++genericContainer ignored -++++++++++++genericContainer ignored \ No newline at end of file +++++++++++++genericContainer ignored
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-fuchsia.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-fuchsia.txt index 9afeef1..14e283aa1 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-fuchsia.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-fuchsia.txt
@@ -1,6 +1,6 @@ UNKNOWN focusable has_input_focus ++UNKNOWN hidden -++++UNKNOWN +++++UNKNOWN hidden ++++++UNKNOWN ++++++++UNKNOWN focusable ++++++++++UNKNOWN hidden
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt index 47128acc..ac1b05b 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-mac.txt
@@ -1,6 +1,5 @@ AXWebArea ++AXGroup -++++AXGroup -++++++AXWebArea -++++AXGroup -++++++AXWebArea \ No newline at end of file +++++AXWebArea +++AXGroup +++++AXWebArea
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt index b74a4a6..fe49b5b2 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-uia-win.txt
@@ -1,6 +1,5 @@ Document -++Group IsControlElement=false -++++Document IsControlElement=false -++++++Document -++++Document IsControlElement=false -++++++Document \ No newline at end of file +++Document IsControlElement=false +++++Document +++Document IsControlElement=false +++++Document \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt b/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt index 4f3fc65..870cb45 100644 --- a/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt +++ b/content/test/data/accessibility/html/iframe-empty-positioned-expected-win.txt
@@ -1,6 +1,5 @@ -ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0>' -++IA2_ROLE_SECTION ia2_hypertext='<obj0><obj1>' -++++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' -++++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE -++++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' -++++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE \ No newline at end of file +ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE ia2_hypertext='<obj0><obj1>' +++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE +++IA2_ROLE_INTERNAL_FRAME ia2_hypertext='<obj0>' +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-padding-expected-blink.txt b/content/test/data/accessibility/html/iframe-padding-expected-blink.txt index 797d2997..fd3b047 100644 --- a/content/test/data/accessibility/html/iframe-padding-expected-blink.txt +++ b/content/test/data/accessibility/html/iframe-padding-expected-blink.txt
@@ -1,7 +1,7 @@ rootWebArea pageLocation=(0, 0) ++genericContainer ignored ++++genericContainer ignored -++++++genericContainer pageLocation=(0, 0) pageSize=(300, 100) +++++++genericContainer ignored ++++++++iframe pageLocation=(0, 0) pageSize=(300, 100) ++++++++++rootWebArea pageLocation=(0, 0) pageSize=(300, 100) ++++++++++++genericContainer ignored @@ -10,7 +10,7 @@ ++++++++++++++++++button pageLocation=(25, 25) pageSize=(250, 50) name='Ordinary Button' ++++++++++++++++++++staticText name='Ordinary Button' ++++++++++++++++++++++inlineTextBox name='Ordinary Button' -++++++genericContainer pageLocation=(30, 230) pageSize=(300, 100) +++++++genericContainer ignored ++++++++iframe pageLocation=(30, 230) pageSize=(300, 100) ++++++++++rootWebArea pageLocation=(30, 230) pageSize=(300, 100) ++++++++++++genericContainer ignored @@ -18,4 +18,4 @@ ++++++++++++++++genericContainer pageLocation=(30, 230) pageSize=(300, 100) ++++++++++++++++++button pageLocation=(55, 255) pageSize=(250, 50) name='Second Button' ++++++++++++++++++++staticText name='Second Button' -++++++++++++++++++++++inlineTextBox name='Second Button' \ No newline at end of file +++++++++++++++++++++++inlineTextBox name='Second Button'
diff --git a/content/test/data/accessibility/html/iframe-transform-cross-process-expected-blink.txt b/content/test/data/accessibility/html/iframe-transform-cross-process-expected-blink.txt index 6c143d4c..fa5a868 100644 --- a/content/test/data/accessibility/html/iframe-transform-cross-process-expected-blink.txt +++ b/content/test/data/accessibility/html/iframe-transform-cross-process-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea pageLocation=(0, 0) ++genericContainer ignored -++++genericContainer pageLocation=(0, 0) +++++genericContainer ignored ++++++iframe pageLocation=(0, 0) ++++++++rootWebArea pageLocation=(0, 0) ++++++++++genericContainer ignored @@ -10,4 +10,4 @@ ++++++++rootWebArea pageLocation=(0, 250) ++++++++++genericContainer ignored ++++++++++++genericContainer ignored -++++++++++++++image pageLocation=(15, 265) pageSize=(150, 75) \ No newline at end of file +++++++++++++++image pageLocation=(15, 265) pageSize=(150, 75)
diff --git a/content/test/data/accessibility/html/iframe-transform-expected-blink.txt b/content/test/data/accessibility/html/iframe-transform-expected-blink.txt index 6c143d4c..fa5a868 100644 --- a/content/test/data/accessibility/html/iframe-transform-expected-blink.txt +++ b/content/test/data/accessibility/html/iframe-transform-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea pageLocation=(0, 0) ++genericContainer ignored -++++genericContainer pageLocation=(0, 0) +++++genericContainer ignored ++++++iframe pageLocation=(0, 0) ++++++++rootWebArea pageLocation=(0, 0) ++++++++++genericContainer ignored @@ -10,4 +10,4 @@ ++++++++rootWebArea pageLocation=(0, 250) ++++++++++genericContainer ignored ++++++++++++genericContainer ignored -++++++++++++++image pageLocation=(15, 265) pageSize=(150, 75) \ No newline at end of file +++++++++++++++image pageLocation=(15, 265) pageSize=(150, 75)
diff --git a/content/test/data/accessibility/html/iframe-transform-expected-fuchsia.txt b/content/test/data/accessibility/html/iframe-transform-expected-fuchsia.txt index 2b49322..db0a107 100644 --- a/content/test/data/accessibility/html/iframe-transform-expected-fuchsia.txt +++ b/content/test/data/accessibility/html/iframe-transform-expected-fuchsia.txt
@@ -1,6 +1,6 @@ UNKNOWN focusable has_input_focus ++UNKNOWN hidden -++++UNKNOWN +++++UNKNOWN hidden ++++++UNKNOWN ++++++++UNKNOWN focusable ++++++++++UNKNOWN hidden
diff --git a/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt b/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt index d74d125d..f1ced26c9 100644 --- a/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt +++ b/content/test/data/accessibility/html/iframe-transform-expected-uia-win.txt
@@ -1,8 +1,7 @@ Document -++Group IsControlElement=false -++++Document IsControlElement=false -++++++Document -++++++++Image -++++Document IsControlElement=false -++++++Document -++++++++Image \ No newline at end of file +++Document IsControlElement=false +++++Document +++++++Image +++Document IsControlElement=false +++++Document +++++++Image \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-transform-expected-win.txt b/content/test/data/accessibility/html/iframe-transform-expected-win.txt index e3590d4a..1b5b2f2 100644 --- a/content/test/data/accessibility/html/iframe-transform-expected-win.txt +++ b/content/test/data/accessibility/html/iframe-transform-expected-win.txt
@@ -1,8 +1,7 @@ ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE location=(0, 0) -++IA2_ROLE_SECTION location=(0, 0) -++++IA2_ROLE_INTERNAL_FRAME location=(0, 0) -++++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE location=(0, 0) -++++++++ROLE_SYSTEM_GRAPHIC READONLY location=(10, 10) size=(100, 50) -++++IA2_ROLE_INTERNAL_FRAME location=(0, 250) -++++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE location=(0, 250) -++++++++ROLE_SYSTEM_GRAPHIC READONLY location=(15, 265) size=(150, 75) \ No newline at end of file +++IA2_ROLE_INTERNAL_FRAME location=(0, 0) +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE location=(0, 0) +++++++ROLE_SYSTEM_GRAPHIC READONLY location=(10, 10) size=(100, 50) +++IA2_ROLE_INTERNAL_FRAME location=(0, 250) +++++ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE location=(0, 250) +++++++ROLE_SYSTEM_GRAPHIC READONLY location=(15, 265) size=(150, 75) \ No newline at end of file
diff --git a/content/test/data/accessibility/html/iframe-transform-nested-cross-process-expected-blink.txt b/content/test/data/accessibility/html/iframe-transform-nested-cross-process-expected-blink.txt index b9747d6..5178aca 100644 --- a/content/test/data/accessibility/html/iframe-transform-nested-cross-process-expected-blink.txt +++ b/content/test/data/accessibility/html/iframe-transform-nested-cross-process-expected-blink.txt
@@ -1,12 +1,12 @@ rootWebArea pageLocation=(0, 0) ++genericContainer ignored -++++genericContainer pageLocation=(0, 100) +++++genericContainer ignored ++++++iframe pageLocation=(0, 100) transform ++++++++rootWebArea pageLocation=(0, 100) ++++++++++genericContainer ignored -++++++++++++genericContainer pageLocation=(200, 100) +++++++++++++genericContainer ignored ++++++++++++++iframe pageLocation=(200, 100) transform ++++++++++++++++rootWebArea pageLocation=(200, 100) ++++++++++++++++++genericContainer ignored ++++++++++++++++++++genericContainer ignored -++++++++++++++++++++++image pageLocation=(240, 140) pageSize=(400, 200) \ No newline at end of file +++++++++++++++++++++++image pageLocation=(240, 140) pageSize=(400, 200)
diff --git a/content/test/data/accessibility/html/iframe-transform-nested-expected-blink.txt b/content/test/data/accessibility/html/iframe-transform-nested-expected-blink.txt index b9747d6..5178aca 100644 --- a/content/test/data/accessibility/html/iframe-transform-nested-expected-blink.txt +++ b/content/test/data/accessibility/html/iframe-transform-nested-expected-blink.txt
@@ -1,12 +1,12 @@ rootWebArea pageLocation=(0, 0) ++genericContainer ignored -++++genericContainer pageLocation=(0, 100) +++++genericContainer ignored ++++++iframe pageLocation=(0, 100) transform ++++++++rootWebArea pageLocation=(0, 100) ++++++++++genericContainer ignored -++++++++++++genericContainer pageLocation=(200, 100) +++++++++++++genericContainer ignored ++++++++++++++iframe pageLocation=(200, 100) transform ++++++++++++++++rootWebArea pageLocation=(200, 100) ++++++++++++++++++genericContainer ignored ++++++++++++++++++++genericContainer ignored -++++++++++++++++++++++image pageLocation=(240, 140) pageSize=(400, 200) \ No newline at end of file +++++++++++++++++++++++image pageLocation=(240, 140) pageSize=(400, 200)
diff --git a/content/test/data/accessibility/html/window-crops-items-expected-blink.txt b/content/test/data/accessibility/html/window-crops-items-expected-blink.txt index 37bd6e08..c91fa97 100644 --- a/content/test/data/accessibility/html/window-crops-items-expected-blink.txt +++ b/content/test/data/accessibility/html/window-crops-items-expected-blink.txt
@@ -1,6 +1,6 @@ rootWebArea ++genericContainer ignored -++++genericContainer +++++genericContainer ignored ++++++button size=(300, 150) name='Button fits' ++++++++staticText name='Button fits' ++++++++++inlineTextBox name='Button fits' @@ -21,4 +21,4 @@ ++++++++++inlineTextBox offscreen pageSize=(1, 1) name='Button offscreen top' ++++++button size=(300, 150) pageSize=(208, 58) name='Button partially on screen' ++++++++staticText offscreen name='Button partially on screen' -++++++++++inlineTextBox offscreen name='Button partially on screen' \ No newline at end of file +++++++++++inlineTextBox offscreen name='Button partially on screen'
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt index 6a67eeb0..511cb3ce 100644 --- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -177,6 +177,7 @@ crbug.com/1419583 [ linux amd-0x7340 angle-vulkan ] ContextLost_WebGLContextRestoredInHiddenTab [ Failure ] +crbug.com/1419558 [ fuchsia ] ContextLost_WebGLContextLostFromQuantity [ Failure ] ####################################################################### # Automated Entries After This Point - Do Not Manually Add Below Here #
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index 2373331..4bc6e8d 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -301,14 +301,8 @@ # Times out on Pixel 4s in webview. crbug.com/1176918 [ android android-pixel-4 android-webview-instrumentation renderer-skia-gl ] Pixel_Video_Context_Loss_VP9 [ Failure ] -# WebGL drawingBufferStorage does not work on Google Pixel devices, Samsung -# devices or kevin yet. -crbug.com/1230619 [ android android-nexus-5x passthrough ] Pixel_WebGLFloat [ Failure ] -crbug.com/1230619 [ android android-pixel-2 ] Pixel_WebGLFloat [ Failure ] -crbug.com/1230619 [ android android-pixel-4 angle-disabled no-passthrough ] Pixel_WebGLFloat [ Failure ] -crbug.com/1230619 [ android android-pixel-6 angle-disabled no-passthrough ] Pixel_WebGLFloat [ Failure ] -crbug.com/1230619 [ android android-SM-A135M ] Pixel_WebGLFloat [ Failure ] -crbug.com/1230619 [ android android-SM-A235M ] Pixel_WebGLFloat [ Failure ] +# WebGL drawingBufferStorage does not work on Android devices or on kevin yet. +crbug.com/1230619 [ android ] Pixel_WebGLFloat [ Failure ] crbug.com/1230619 [ chromeos chromeos-board-kevin ] Pixel_WebGLFloat [ Failure ] @@ -413,6 +407,9 @@ # Samsung flaky incorrect colors crbug.com/1445552 [ android android-sm-a135m ] Pixel_OffscreenCanvasWebGLDefault [ Failure ] +# ChromeOS consistent Canvas failure +crbug.com/1445502 [ chromeos chromeos-board-amd64-generic angle-disabled no-passthrough ] Pixel_VideoStreamFrom2DAlphaCanvas_DisableReadbackFromTexture [ Failure ] + ####################################################################### # Automated Entries After This Point - Do Not Manually Add Below Here # #######################################################################
diff --git a/docs/security/faq.md b/docs/security/faq.md index ce8f9c7..b7bf570 100644 --- a/docs/security/faq.md +++ b/docs/security/faq.md
@@ -47,7 +47,7 @@ there is no need to further assess the risk of Chromium vulnerabilities: we strive to fix vulnerabilities quickly and release often. -<a name="TOC-How-can-I-know-which-fixes-to-include-in-my-downstream-project-"> +<a name="TOC-How-can-I-know-which-fixes-to-include-in-my-downstream-project-"></a> ### How can I know which fixes to include in my downstream project? Chrome is built with mitigations and hardening which aim to prevent or reduce
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc index 4278888..d1502d9 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.cc
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/check_deref.h" #include "base/functional/bind.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -285,18 +286,22 @@ EXTENSION_FUNCTION_PRERUN_VALIDATE(args().size() >= 1); const auto& instance_id_value = args()[0]; EXTENSION_FUNCTION_PRERUN_VALIDATE(instance_id_value.is_int()); - int instance_id = instance_id_value.GetInt(); + instance_id_ = instance_id_value.GetInt(); // TODO(780728): Remove crash key once the cause of the kill is known. static crash_reporter::CrashKeyString<128> name_key("webview-function"); crash_reporter::ScopedCrashKeyString name_key_scope(&name_key, name()); - guest_ = WebViewGuest::FromInstanceID(source_process_id(), instance_id); - if (!guest_) { + if (!WebViewGuest::FromInstanceID(source_process_id(), instance_id_)) { *error = "Could not find guest"; return false; } return true; } +WebViewGuest& WebViewInternalExtensionFunction::GetGuest() { + return CHECK_DEREF( + WebViewGuest::FromInstanceID(source_process_id(), instance_id_)); +} + WebViewInternalCaptureVisibleRegionFunction:: WebViewInternalCaptureVisibleRegionFunction() : is_guest_transparent_(false) {} @@ -314,9 +319,10 @@ image_details = ImageDetails::FromValueDeprecated(args()[1]); } - is_guest_transparent_ = guest_->allow_transparency(); + WebViewGuest& guest = GetGuest(); + is_guest_transparent_ = guest.allow_transparency(); const CaptureResult capture_result = CaptureAsync( - guest_->web_contents(), image_details.get(), + guest.web_contents(), image_details.get(), base::BindOnce( &WebViewInternalCaptureVisibleRegionFunction::CopyFromSurfaceComplete, this)); @@ -420,7 +426,7 @@ web_view_internal::Navigate::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); std::string src = params->src; - guest_->NavigateGuest(src, true /* force_navigation */); + GetGuest().NavigateGuest(src, true /* force_navigation */); return RespondNow(NoArguments()); } @@ -651,7 +657,7 @@ absl::optional<web_view_internal::SetName::Params> params = web_view_internal::SetName::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->SetName(params->frame_name); + GetGuest().SetName(params->frame_name); return RespondNow(NoArguments()); } @@ -668,7 +674,7 @@ absl::optional<web_view_internal::SetAllowTransparency::Params> params = web_view_internal::SetAllowTransparency::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->SetAllowTransparency(params->allow); + GetGuest().SetAllowTransparency(params->allow); return RespondNow(NoArguments()); } @@ -685,7 +691,7 @@ absl::optional<web_view_internal::SetAllowScaling::Params> params = web_view_internal::SetAllowScaling::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->SetAllowScaling(params->allow); + GetGuest().SetAllowScaling(params->allow); return RespondNow(NoArguments()); } @@ -699,7 +705,7 @@ absl::optional<web_view_internal::SetZoom::Params> params = web_view_internal::SetZoom::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->SetZoom(params->zoom_factor); + GetGuest().SetZoom(params->zoom_factor); return RespondNow(NoArguments()); } @@ -714,7 +720,7 @@ web_view_internal::GetZoom::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - double zoom_factor = guest_->GetZoom(); + double zoom_factor = GetGuest().GetZoom(); return RespondNow(WithArguments(zoom_factor)); } @@ -744,7 +750,7 @@ NOTREACHED(); } - guest_->SetZoomMode(zoom_mode); + GetGuest().SetZoomMode(zoom_mode); return RespondNow(NoArguments()); } @@ -760,7 +766,7 @@ EXTENSION_FUNCTION_VALIDATE(params); web_view_internal::ZoomMode zoom_mode = web_view_internal::ZoomMode::kNone; - switch (guest_->GetZoomMode()) { + switch (GetGuest().GetZoomMode()) { case ZoomController::ZOOM_MODE_DEFAULT: zoom_mode = web_view_internal::ZoomMode::kPerOrigin; break; @@ -806,7 +812,7 @@ params->options->match_case ? *params->options->match_case : false; } - guest_->StartFind(search_text, std::move(options), this); + GetGuest().StartFind(search_text, std::move(options), this); // It is possible that StartFind has already responded. return did_respond() ? AlreadyResponded() : RespondLater(); } @@ -838,7 +844,7 @@ action = content::STOP_FIND_ACTION_KEEP_SELECTION; } - guest_->StopFinding(action); + GetGuest().StopFinding(action); return RespondNow(NoArguments()); } @@ -862,9 +868,9 @@ params->virtual_url ? *params->virtual_url : params->data_url; std::string error; - bool successful = guest_->LoadDataWithBaseURL(GURL(params->data_url), - GURL(params->base_url), - GURL(virtual_url), &error); + bool successful = GetGuest().LoadDataWithBaseURL(GURL(params->data_url), + GURL(params->base_url), + GURL(virtual_url), &error); if (successful) return RespondNow(NoArguments()); return RespondNow(Error(std::move(error))); @@ -881,7 +887,7 @@ web_view_internal::Go::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - bool successful = guest_->Go(params->relative_index); + bool successful = GetGuest().Go(params->relative_index); return RespondNow(WithArguments(successful)); } @@ -892,7 +898,7 @@ } ExtensionFunction::ResponseAction WebViewInternalReloadFunction::Run() { - guest_->Reload(); + GetGuest().Reload(); return RespondNow(NoArguments()); } @@ -927,7 +933,7 @@ user_input = *params->user_input; WebViewPermissionHelper* web_view_permission_helper = - guest_->web_view_permission_helper(); + GetGuest().web_view_permission_helper(); WebViewPermissionHelper::SetPermissionResult result = web_view_permission_helper->SetPermission( @@ -954,7 +960,7 @@ web_view_internal::OverrideUserAgent::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->SetUserAgentOverride(params->user_agent_override); + GetGuest().SetUserAgentOverride(params->user_agent_override); return RespondNow(NoArguments()); } @@ -965,7 +971,7 @@ } ExtensionFunction::ResponseAction WebViewInternalStopFunction::Run() { - guest_->Stop(); + GetGuest().Stop(); return RespondNow(NoArguments()); } @@ -980,7 +986,7 @@ web_view_internal::SetAudioMuted::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->web_contents()->SetAudioMuted(params->mute); + GetGuest().web_contents()->SetAudioMuted(params->mute); return RespondNow(NoArguments()); } @@ -995,7 +1001,7 @@ web_view_internal::IsAudioMuted::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - content::WebContents* web_contents = guest_->web_contents(); + content::WebContents* web_contents = GetGuest().web_contents(); return RespondNow(WithArguments(web_contents->IsAudioMuted())); } @@ -1010,7 +1016,7 @@ web_view_internal::GetAudioState::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - content::WebContents* web_contents = guest_->web_contents(); + content::WebContents* web_contents = GetGuest().web_contents(); return RespondNow(WithArguments(web_contents->IsCurrentlyAudible())); } @@ -1021,7 +1027,7 @@ } ExtensionFunction::ResponseAction WebViewInternalTerminateFunction::Run() { - guest_->Terminate(); + GetGuest().Terminate(); return RespondNow(NoArguments()); } @@ -1045,7 +1051,7 @@ args()); EXTENSION_FUNCTION_VALIDATE(params); - guest_->SetSpatialNavigationEnabled(params->spatial_nav_enabled); + GetGuest().SetSpatialNavigationEnabled(params->spatial_nav_enabled); return RespondNow(NoArguments()); } @@ -1061,7 +1067,7 @@ web_view_internal::IsSpatialNavigationEnabled::Params::Create(args()); EXTENSION_FUNCTION_VALIDATE(params); - return RespondNow(WithArguments(guest_->IsSpatialNavigationEnabled())); + return RespondNow(WithArguments(GetGuest().IsSpatialNavigationEnabled())); } // Parses the |dataToRemove| argument to generate the remove mask. Sets @@ -1113,7 +1119,7 @@ bool scheduled = false; if (remove_mask_) { - scheduled = guest_->ClearData( + scheduled = GetGuest().ClearData( remove_since_, remove_mask_, base::BindOnce(&WebViewInternalClearDataFunction::ClearDataDone, this)); }
diff --git a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h index a856fb70..ee936bfc 100644 --- a/extensions/browser/api/guest_view/web_view/web_view_internal_api.h +++ b/extensions/browser/api/guest_view/web_view/web_view_internal_api.h
@@ -7,7 +7,6 @@ #include <stdint.h> -#include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/time/time.h" #include "base/values.h" @@ -29,13 +28,16 @@ class WebViewInternalExtensionFunction : public ExtensionFunction { public: - WebViewInternalExtensionFunction() {} + WebViewInternalExtensionFunction() = default; protected: - ~WebViewInternalExtensionFunction() override {} + ~WebViewInternalExtensionFunction() override = default; bool PreRunValidation(std::string* error) override; - raw_ptr<WebViewGuest, FlakyDanglingUntriaged> guest_ = nullptr; + WebViewGuest& GetGuest(); + + private: + int instance_id_ = 0; }; class WebViewInternalCaptureVisibleRegionFunction
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index af9ef54..5d0fdb65 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -46,6 +46,7 @@ #include "extensions/common/permissions/permissions_data.h" #include "ipc/ipc_channel_proxy.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "url/origin.h" using content::BrowserContext; using content::BrowserThread; @@ -1059,10 +1060,19 @@ process_map->GetMostLikelyContextType(extension, process->GetID(), url); // We shouldn't be dispatching an event to a webpage, since all such events - // (e.g. messaging) don't go through EventRouter. - DCHECK_NE(Feature::WEB_PAGE_CONTEXT, target_context) - << "Trying to dispatch event " << event.event_name << " to a webpage," - << " but this shouldn't be possible"; + // (e.g. messaging) don't go through EventRouter. The one exception to this + // is the new chrome webstore domain, which has permission to receive + // extension events. + if (target_context == Feature::WEB_PAGE_CONTEXT) { + // |url| can only be null for service workers, so should never be null here. + CHECK(url); + bool is_new_webstore_origin = + url::Origin::Create(extension_urls::GetNewWebstoreLaunchURL()) + .IsSameOriginWith(*url); + CHECK(is_new_webstore_origin) + << "Trying to dispatch event " << event.event_name << " to a webpage," + << " but this shouldn't be possible"; + } Feature::Availability availability = ExtensionAPI::GetSharedInstance()->IsAvailable(
diff --git a/extensions/common/api/API_OWNERS b/extensions/common/api/API_OWNERS index 83b6052..1c8f264 100644 --- a/extensions/common/api/API_OWNERS +++ b/extensions/common/api/API_OWNERS
@@ -11,7 +11,8 @@ # Please see //extensions/docs/new_api_proposal.md for details. # For Extensions and Apps APIs. -rdevlin.cronin@chromium.org +rdevlin.cronin@chromium.org # Primary for extensions APIs +tjudkins@chromium.org # Secondary for extensions APIs # For Chrome OS apps APIs. tbarzic@chromium.org
diff --git a/gin/v8_platform_thread_isolated_allocator.cc b/gin/v8_platform_thread_isolated_allocator.cc index 4228dfc..caf169e0 100644 --- a/gin/v8_platform_thread_isolated_allocator.cc +++ b/gin/v8_platform_thread_isolated_allocator.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "gin/v8_platform_thread_isolated_allocator.h" +#include "base/allocator/partition_allocator/partition_root.h" #if BUILDFLAG(ENABLE_THREAD_ISOLATION) @@ -24,15 +25,11 @@ void ThreadIsolatedAllocator::Initialize(int pkey) { pkey_ = pkey; - allocator_.init({ - partition_alloc::PartitionOptions::AlignedAlloc::kAllowed, - partition_alloc::PartitionOptions::ThreadCache::kDisabled, - partition_alloc::PartitionOptions::Quarantine::kDisallowed, - partition_alloc::PartitionOptions::Cookie::kAllowed, - partition_alloc::PartitionOptions::BackupRefPtr::kDisabled, - partition_alloc::PartitionOptions::BackupRefPtrZapping::kDisabled, - partition_alloc::PartitionOptions::UseConfigurablePool::kNo, - partition_alloc::ThreadIsolationOption(pkey_), + allocator_.init(partition_alloc::PartitionOptions{ + .aligned_alloc = + partition_alloc::PartitionOptions::AlignedAlloc::kAllowed, + .cookie = partition_alloc::PartitionOptions::Cookie::kAllowed, + .thread_isolation = partition_alloc::ThreadIsolationOption(pkey_), }); }
diff --git a/gpu/command_buffer/service/shared_image/wrapped_graphite_texture_backing.cc b/gpu/command_buffer/service/shared_image/wrapped_graphite_texture_backing.cc index ab75d9b..43218b8 100644 --- a/gpu/command_buffer/service/shared_image/wrapped_graphite_texture_backing.cc +++ b/gpu/command_buffer/service/shared_image/wrapped_graphite_texture_backing.cc
@@ -140,7 +140,7 @@ graphite_textures_.clear(); return false; } - graphite_textures_.push_back(std::move(texture)); + graphite_textures_[plane] = std::move(texture); } return true;
diff --git a/infra/config/generated/builders/ci/linux-arm64-rel-cft/properties.json b/infra/config/generated/builders/ci/linux-arm64-rel-cft/properties.json new file mode 100644 index 0000000..e1c2406e --- /dev/null +++ b/infra/config/generated/builders/ci/linux-arm64-rel-cft/properties.json
@@ -0,0 +1,57 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "linux-arm64-rel-cft", + "project": "chromium" + }, + "builder_spec": { + "builder_group": "chromium.cft", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_bits": 64, + "target_platform": "linux" + }, + "legacy_gclient_config": { + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "linux-arm64-rel-cft", + "project": "chromium" + } + ] + } + }, + "$build/reclient": { + "instance": "rbe-chromium-trusted", + "jobs": 500, + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.cft", + "recipe": "chromium", + "sheriff_rotations": [ + "cft" + ] +} \ No newline at end of file
diff --git a/infra/config/generated/builders/try/mac-rel/properties.json b/infra/config/generated/builders/try/mac-rel/properties.json index 29baca5..e5662a28 100644 --- a/infra/config/generated/builders/try/mac-rel/properties.json +++ b/infra/config/generated/builders/try/mac-rel/properties.json
@@ -201,6 +201,5 @@ ] }, "builder_group": "tryserver.chromium.mac", - "cq": "required", "recipe": "chromium/orchestrator" } \ No newline at end of file
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md index 26554e8..c679dc79 100644 --- a/infra/config/generated/cq-builders.md +++ b/infra/config/generated/cq-builders.md
@@ -45,6 +45,8 @@ * [fuchsia-binary-size](https://ci.chromium.org/p/chromium/builders/try/fuchsia-binary-size) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""fuchsia-binary-size"")) +* [fuchsia-x64-cast-receiver-rel](https://ci.chromium.org/p/chromium/builders/try/fuchsia-x64-cast-receiver-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""fuchsia-x64-cast-receiver-rel"")) + * [ios-simulator](https://ci.chromium.org/p/chromium/builders/try/ios-simulator) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""ios-simulator"")) * [lacros-amd64-generic-rel](https://ci.chromium.org/p/chromium/builders/try/lacros-amd64-generic-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""lacros-amd64-generic-rel"")) @@ -71,8 +73,6 @@ * [linux_chromium_tsan_rel_ng](https://ci.chromium.org/p/chromium/builders/try/linux_chromium_tsan_rel_ng) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""linux_chromium_tsan_rel_ng"")) -* [mac-rel](https://ci.chromium.org/p/chromium/builders/try/mac-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""mac-rel"")) - * [mac_chromium_compile_dbg_ng](https://ci.chromium.org/p/chromium/builders/try/mac_chromium_compile_dbg_ng) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""mac_chromium_compile_dbg_ng"")) * [win-libfuzzer-asan-rel](https://ci.chromium.org/p/chromium/builders/try/win-libfuzzer-asan-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""win-libfuzzer-asan-rel"")) @@ -549,9 +549,6 @@ * [`//third_party/nearby/README.chromium`](https://cs.chromium.org/search?q=+file:third_party/nearby/README.chromium) ### chromium -* [fuchsia-x64-cast-receiver-rel](https://ci.chromium.org/p/chromium/builders/try/fuchsia-x64-cast-receiver-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""fuchsia-x64-cast-receiver-rel"")) - * Experiment percentage: 100.0 - * [linux-1mbu-compile-fyi-rel](https://ci.chromium.org/p/chromium/builders/try/linux-1mbu-compile-fyi-rel) ([definition](https://cs.chromium.org/search?q=+file:/try/.*\.star$+""linux-1mbu-compile-fyi-rel"")) * Experiment percentage: 5.0
diff --git a/infra/config/generated/cq-usage/default.cfg b/infra/config/generated/cq-usage/default.cfg index a2fdb8c..9d244c7 100644 --- a/infra/config/generated/cq-usage/default.cfg +++ b/infra/config/generated/cq-usage/default.cfg
@@ -56,6 +56,9 @@ name: "chromium/try/fuchsia-binary-size" } builders { + name: "chromium/try/fuchsia-x64-cast-receiver-rel" + } + builders { name: "chromium/try/ios-simulator" } builders { @@ -95,9 +98,6 @@ name: "chromium/try/linux_chromium_tsan_rel_ng" } builders { - name: "chromium/try/mac-rel" - } - builders { name: "chromium/try/mac_chromium_compile_dbg_ng" } builders {
diff --git a/infra/config/generated/cq-usage/full.cfg b/infra/config/generated/cq-usage/full.cfg index 21ee5dc..68016a6 100644 --- a/infra/config/generated/cq-usage/full.cfg +++ b/infra/config/generated/cq-usage/full.cfg
@@ -1268,6 +1268,26 @@ } } builders { + name: "chromium/try/fuchsia-x64-cast-receiver-rel" + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "docs/.+" + exclude: true + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "infra/config/.+" + exclude: true + } + location_filters { + gerrit_host_regexp: ".*" + gerrit_project_regexp: ".*" + path_regexp: "infra/config/generated/builders/try/fuchsia-x64-cast-receiver-rel/.+" + } + } + builders { name: "chromium/try/gpu-fyi-cq-android-arm64" location_filters { gerrit_host_regexp: ".*" @@ -2254,26 +2274,6 @@ } } builders { - name: "chromium/try/mac-rel" - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "docs/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/generated/builders/try/mac-rel/.+" - } - } - builders { name: "chromium/try/mac-updater-try-builder-dbg" location_filters { gerrit_host_regexp: ".*"
diff --git a/infra/config/generated/health-specs/health-specs.json b/infra/config/generated/health-specs/health-specs.json index 8baf858..bd33b00 100644 --- a/infra/config/generated/health-specs/health-specs.json +++ b/infra/config/generated/health-specs/health-specs.json
@@ -22,103 +22,105 @@ "p99_mins": 30 } }, - "ci": { - "Linux ChromiumOS Full": { - "_default": "_default" - }, - "chromeos-amd64-generic-asan-rel": { - "_default": "_default" - }, - "chromeos-amd64-generic-cfi-thin-lto-rel": { - "_default": "_default" - }, - "chromeos-amd64-generic-dbg": { - "_default": "_default" - }, - "chromeos-amd64-generic-lacros-dbg": { - "_default": "_default" - }, - "chromeos-amd64-generic-rel": { - "_default": "_default" - }, - "chromeos-arm-generic-dbg": { - "_default": "_default" - }, - "chromeos-arm-generic-rel": { - "_default": "_default" - }, - "chromeos-arm64-generic-rel": { - "_default": "_default" - }, - "chromeos-jacuzzi-rel": { - "_default": "_default" - }, - "chromeos-octopus-rel": { - "_default": "_default" - }, - "lacros-amd64-generic-binary-size-rel": { - "_default": "_default" - }, - "lacros-amd64-generic-rel": { - "_default": "_default" - }, - "lacros-amd64-generic-rel-skylab": { - "_default": "_default" - }, - "lacros-arm-generic-rel": { - "_default": "_default" - }, - "lacros-arm-generic-rel-skylab": { - "_default": "_default" - }, - "lacros-arm64-generic-rel": { - "_default": "_default" - }, - "lacros-arm64-generic-rel-skylab": { - "_default": "_default" - }, - "linux-ash-chromium-generator-rel": { - "_default": "_default" - }, - "linux-cfm-rel": { - "_default": "_default" - }, - "linux-chromeos-dbg": { - "_default": "_default" - }, - "linux-chromeos-rel": { - "_default": "_default" - }, - "linux-lacros-builder-rel": { - "_default": "_default" - }, - "linux-lacros-dbg": { - "_default": "_default" - }, - "linux-lacros-tester-rel": { - "_default": "_default" - }, - "linux-official": { - "build_time": { - "p50_mins": 240, - "p95_mins": 300, - "p99_mins": 360 + "thresholds": { + "ci": { + "Linux ChromiumOS Full": { + "_default": "_default" }, - "fail_rate": { - "average": 0.2 + "chromeos-amd64-generic-asan-rel": { + "_default": "_default" }, - "infra_fail_rate": { - "average": 0.05 + "chromeos-amd64-generic-cfi-thin-lto-rel": { + "_default": "_default" }, - "pending_time": { - "p50_mins": 10, - "p95_mins": 20, - "p99_mins": 30 + "chromeos-amd64-generic-dbg": { + "_default": "_default" }, - "test_pending_time": { - "p50_mins": 10, - "p95_mins": 20, - "p99_mins": 30 + "chromeos-amd64-generic-lacros-dbg": { + "_default": "_default" + }, + "chromeos-amd64-generic-rel": { + "_default": "_default" + }, + "chromeos-arm-generic-dbg": { + "_default": "_default" + }, + "chromeos-arm-generic-rel": { + "_default": "_default" + }, + "chromeos-arm64-generic-rel": { + "_default": "_default" + }, + "chromeos-jacuzzi-rel": { + "_default": "_default" + }, + "chromeos-octopus-rel": { + "_default": "_default" + }, + "lacros-amd64-generic-binary-size-rel": { + "_default": "_default" + }, + "lacros-amd64-generic-rel": { + "_default": "_default" + }, + "lacros-amd64-generic-rel-skylab": { + "_default": "_default" + }, + "lacros-arm-generic-rel": { + "_default": "_default" + }, + "lacros-arm-generic-rel-skylab": { + "_default": "_default" + }, + "lacros-arm64-generic-rel": { + "_default": "_default" + }, + "lacros-arm64-generic-rel-skylab": { + "_default": "_default" + }, + "linux-ash-chromium-generator-rel": { + "_default": "_default" + }, + "linux-cfm-rel": { + "_default": "_default" + }, + "linux-chromeos-dbg": { + "_default": "_default" + }, + "linux-chromeos-rel": { + "_default": "_default" + }, + "linux-lacros-builder-rel": { + "_default": "_default" + }, + "linux-lacros-dbg": { + "_default": "_default" + }, + "linux-lacros-tester-rel": { + "_default": "_default" + }, + "linux-official": { + "build_time": { + "p50_mins": 240, + "p95_mins": 300, + "p99_mins": 360 + }, + "fail_rate": { + "average": 0.2 + }, + "infra_fail_rate": { + "average": 0.05 + }, + "pending_time": { + "p50_mins": 10, + "p95_mins": 20, + "p99_mins": 30 + }, + "test_pending_time": { + "p50_mins": 10, + "p95_mins": 20, + "p99_mins": 30 + } } } }
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg index cf9e8f7..f6cf6dc0 100644 --- a/infra/config/generated/luci/commit-queue.cfg +++ b/infra/config/generated/luci/commit-queue.cfg
@@ -1853,7 +1853,6 @@ } builders { name: "chromium/try/fuchsia-x64-cast-receiver-rel" - experiment_percentage: 100 location_filters { gerrit_host_regexp: ".*" gerrit_project_regexp: ".*" @@ -3490,23 +3489,7 @@ } builders { name: "chromium/try/mac-rel" - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "docs/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/.+" - exclude: true - } - location_filters { - gerrit_host_regexp: ".*" - gerrit_project_regexp: ".*" - path_regexp: "infra/config/generated/builders/try/mac-rel/.+" - } + includable_only: true } builders { name: "chromium/try/mac-rel-cft"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 6a078d68..736b5e8f 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -36003,6 +36003,93 @@ } } builders { + name: "linux-arm64-rel-cft" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "free_space:standard" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.ci" + dimensions: "ssd:0" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/linux-arm64-rel-cft/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.cft",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium",' + ' "sheriff_rotations": [' + ' "cft"' + ' ]' + '}' + execution_timeout_secs: 10800 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "linux-ash-chromium-generator-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -80396,7 +80483,6 @@ ' }' ' },' ' "builder_group": "tryserver.chromium.mac",' - ' "cq": "required",' ' "led_builder_is_bootstrapped": true,' ' "recipe": "chromium/orchestrator"' '}' @@ -83604,7 +83690,7 @@ ' "builder_group": "tryserver.chromium.mac",' ' "recipe": "chromium_toolchain/package_clang"' '}' - execution_timeout_secs: 28800 + execution_timeout_secs: 21600 expiration_secs: 7200 grace_period { seconds: 120 @@ -83847,7 +83933,7 @@ ' "builder_group": "tryserver.chromium.mac",' ' "recipe": "chromium_toolchain/package_rust"' '}' - execution_timeout_secs: 28800 + execution_timeout_secs: 21600 expiration_secs: 7200 grace_period { seconds: 120
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 24455e17..1fdd545 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -6015,6 +6015,10 @@ refs: "regexp:refs/heads/main" manifest_name: "REVISION" builders { + name: "buildbucket/luci.chromium.ci/linux-arm64-rel-cft" + short_name: "linux-arm64-rel-cft" + } + builders { name: "buildbucket/luci.chromium.ci/linux-rel-cft" short_name: "linux-rel-cft" }
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index 83727c2..7968290c 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -4568,6 +4568,15 @@ } } job { + id: "linux-arm64-rel-cft" + realm: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "linux-arm64-rel-cft" + } +} +job { id: "linux-ash-chromium-generator-rel" realm: "ci" schedule: "triggered" @@ -6343,6 +6352,7 @@ triggers: "linux-annotator-rel" triggers: "linux-archive-dbg" triggers: "linux-archive-rel" + triggers: "linux-arm64-rel-cft" triggers: "linux-bfcache-rel" triggers: "linux-blink-animation-use-time-delta" triggers: "linux-blink-heap-verification"
diff --git a/infra/config/generated/sheriff-rotations/OWNERS b/infra/config/generated/sheriff-rotations/OWNERS index f612dd6..c9ffde11 100644 --- a/infra/config/generated/sheriff-rotations/OWNERS +++ b/infra/config/generated/sheriff-rotations/OWNERS
@@ -3,6 +3,7 @@ per-file android.txt=file://infra/config/groups/sheriff-rotations/ANDROID_OWNERS per-file angle.txt=file://infra/config/groups/sheriff-rotations/ANGLE_OWNERS +per-file cft.txt=file://infra/config/groups/sheriff-rotations/CFT_OWNERS per-file chromium.clang.txt=file://infra/config/groups/sheriff-rotations/CHROMIUM_CLANG_OWNERS per-file chromium.gpu.txt=file://infra/config/groups/sheriff-rotations/CHROMIUM_GPU_OWNERS per-file chromium.txt=file://infra/config/groups/sheriff-rotations/CHROMIUM_OWNERS
diff --git a/infra/config/generated/sheriff-rotations/cft.txt b/infra/config/generated/sheriff-rotations/cft.txt index 19b7311..b2b2714a 100644 --- a/infra/config/generated/sheriff-rotations/cft.txt +++ b/infra/config/generated/sheriff-rotations/cft.txt
@@ -1,3 +1,4 @@ +ci/linux-arm64-rel-cft ci/linux-rel-cft ci/mac-rel-cft ci/win-rel-cft
diff --git a/infra/config/groups/sheriff-rotations/CFT_OWNERS b/infra/config/groups/sheriff-rotations/CFT_OWNERS new file mode 100644 index 0000000..6862957 --- /dev/null +++ b/infra/config/groups/sheriff-rotations/CFT_OWNERS
@@ -0,0 +1,7 @@ +# @chromium.org email addresses: +mathias@chromium.org +tperrotta@chromium.org + +# @google.com email addresses: +mths@google.com +tperrotta@google.com
diff --git a/infra/config/lib/builder_health_indicators.star b/infra/config/lib/builder_health_indicators.star index 21491de7..76a95186 100644 --- a/infra/config/lib/builder_health_indicators.star +++ b/infra/config/lib/builder_health_indicators.star
@@ -60,7 +60,11 @@ builder = node.key.id specs.setdefault(bucket, {})[builder] = node.props - specs["_default"] = _default_thresholds - ctx.output["health-specs/health-specs.json"] = json.indent(json.encode(specs), indent = " ") + result = { + "_default": _default_thresholds, + "thresholds": specs, + } + + ctx.output["health-specs/health-specs.json"] = json.indent(json.encode(result), indent = " ") lucicfg.generator(_generate_health_specs)
diff --git a/infra/config/subprojects/chromium/ci/chromium.cft.star b/infra/config/subprojects/chromium/ci/chromium.cft.star index 42aa502e..e38914d 100644 --- a/infra/config/subprojects/chromium/ci/chromium.cft.star +++ b/infra/config/subprojects/chromium/ci/chromium.cft.star
@@ -54,6 +54,18 @@ ) ci.builder( + name = "linux-arm64-rel-cft", + builder_spec = builder_spec( + build_config = builder_config.build_config.RELEASE, + target_platform = builder_config.target_platform.LINUX, + ), + os = os.LINUX_DEFAULT, + console_view_entry = consoles.console_view_entry( + short_name = "linux-arm64-rel-cft", + ), +) + +ci.builder( name = "linux-rel-cft", builder_spec = builder_spec( build_config = builder_config.build_config.RELEASE,
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star index be984a27..d8c37103 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.fuchsia.star
@@ -140,10 +140,7 @@ "weetbix.enable_weetbix_exonerations": 100, }, main_list_view = "try", - # TODO(crbug.com/1445005): Restore when runhooks is fixed. - tryjob = try_.job( - experiment_percentage = 100, - ), + tryjob = try_.job(), use_clang_coverage = True, )
diff --git a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star index dc5a261..2f90c49 100644 --- a/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star +++ b/infra/config/subprojects/chromium/try/tryserver.chromium.mac.star
@@ -134,7 +134,8 @@ "chromium.add_one_test_shard": 10, }, main_list_view = "try", - tryjob = try_.job(), + # TODO(guterman): Re-enable when https://crbug.com/1445991 is fixed + # tryjob = try_.job(), use_clang_coverage = True, # TODO (crbug.com/1372179): Use orchestrator pool once overloaded test pools # are addressed @@ -329,7 +330,7 @@ name = "mac_upload_clang", executable = "recipe:chromium_toolchain/package_clang", builderless = False, - execution_timeout = 8 * time.hour, + execution_timeout = 6 * time.hour, ) try_.builder( @@ -350,7 +351,7 @@ name = "mac_upload_rust_arm", executable = "recipe:chromium_toolchain/package_rust", builderless = False, - execution_timeout = 8 * time.hour, + execution_timeout = 6 * time.hour, ) try_.builder(
diff --git a/ios/build/bots/scripts/iossim_util.py b/ios/build/bots/scripts/iossim_util.py index b2325e6..e875e165 100644 --- a/ios/build/bots/scripts/iossim_util.py +++ b/ios/build/bots/scripts/iossim_util.py
@@ -7,9 +7,11 @@ import os import subprocess import time +import typing import test_runner import test_runner_errors +import mac_util LOGGER = logging.getLogger(__name__) @@ -350,3 +352,51 @@ if (time_waited > MAX_WAIT_TIME_TO_DELETE_RUNTIME): raise test_runner_errors.SimRuntimeDeleteTimeoutError(ios_version) LOGGER.debug('Runtime successfully deleted!') + + +def disable_hardware_keyboard(udid: str) -> None: + """Disables hardware keyboard input for the given simulator. + + Exceptions are caught and logged but do not interrupt program flow. The result + is that if the util is unable to change the HW keyboard pref for any reason + the test will still run without changing the preference. + + Args: + udid: (str) UDID of the simulator to disable hw keyboard for. + """ + + path = os.path.expanduser( + '~/Library/Preferences/com.apple.iphonesimulator.plist') + + try: + if not os.path.exists(path): + subprocess.check_call(['plutil', '-create', 'binary1', path]) + + plist, error = mac_util.plist_as_dict(path) + if error: + raise error + + if 'DevicePreferences' not in plist: + subprocess.check_call( + ['plutil', '-insert', 'DevicePreferences', '-dictionary', path]) + plist['DevicePreferences'] = {} + + if 'DevicePreferences' in plist and udid not in plist['DevicePreferences']: + subprocess.check_call([ + 'plutil', '-insert', 'DevicePreferences.{}'.format(udid), + '-dictionary', path + ]) + plist['DevicePreferences'][udid] = {} + + subprocess.check_call([ + 'plutil', '-replace', + 'DevicePreferences.{}.ConnectHardwareKeyboard'.format(udid), '-bool', + 'NO', path + ]) + + except subprocess.CalledProcessError as e: + message = 'Unable to disable hardware keyboard. Error: %s' % e.stderr + LOGGER.error(message) + except json.JSONDecodeError as e: + message = 'Unable to disable hardware keyboard. Error: %s' % e.msg + LOGGER.error(message)
diff --git a/ios/build/bots/scripts/iossim_util_test.py b/ios/build/bots/scripts/iossim_util_test.py index d3a649f3..11597b2d 100755 --- a/ios/build/bots/scripts/iossim_util_test.py +++ b/ios/build/bots/scripts/iossim_util_test.py
@@ -8,6 +8,7 @@ import unittest import iossim_util +import mac_util import os import subprocess import test_runner @@ -327,6 +328,55 @@ mock_get_runtime_info.assert_called_with('13.1') mock_delete_runtime.assert_called_once_with('111111') + def test_disable_hardware_keyboard(self, _, _2): + """Ensures right commands are issued to disable hardware keyboard""" + + self.mock(os.path, 'exists', lambda *args: False) + self.mock(os.path, 'expanduser', lambda *args: 'PATH') + + check_call_mock = mock.Mock() + self.mock(subprocess, 'check_call', check_call_mock) + check_calls = [ + mock.call(['plutil', '-create', 'binary1', 'PATH']), + mock.call( + ['plutil', '-insert', 'DevicePreferences', '-dictionary', 'PATH']), + mock.call([ + 'plutil', '-insert', 'DevicePreferences.UDID', '-dictionary', 'PATH' + ]), + mock.call([ + 'plutil', '-replace', + 'DevicePreferences.UDID.ConnectHardwareKeyboard', '-bool', 'NO', + 'PATH' + ]) + ] + + dict_mock = mock.Mock() + self.mock(mac_util, 'plist_as_dict', dict_mock) + + # file does not exist + dict_mock.return_value = ({}, None) + iossim_util.disable_hardware_keyboard('UDID') + check_call_mock.assert_has_calls(check_calls) + + # file exists but is empty + self.mock(os.path, 'exists', lambda *args: True) + check_call_mock.reset_mock() + dict_mock.return_value = ({}, None) + iossim_util.disable_hardware_keyboard('UDID') + check_call_mock.assert_has_calls(check_calls[1:]) + + #Device Prefs Dictionary Exists but not Prefs for UDID + check_call_mock.reset_mock() + dict_mock.return_value = ({'DevicePreferences': {}}, None) + iossim_util.disable_hardware_keyboard('UDID') + check_call_mock.assert_has_calls(check_calls[2:]) + + # Prefs for UDID exists + check_call_mock.reset_mock() + dict_mock.return_value = ({'DevicePreferences': {'UDID': {}}}, None) + iossim_util.disable_hardware_keyboard('UDID') + check_call_mock.assert_has_calls(check_calls[3:]) + if __name__ == '__main__': unittest.main()
diff --git a/ios/build/bots/scripts/mac_util.py b/ios/build/bots/scripts/mac_util.py index c0f967dd..895b9cb 100644 --- a/ios/build/bots/scripts/mac_util.py +++ b/ios/build/bots/scripts/mac_util.py
@@ -3,8 +3,10 @@ # found in the LICENSE file. import distutils.version +import json import logging import subprocess +from typing import Union, Tuple LOGGER = logging.getLogger(__name__) @@ -57,3 +59,26 @@ return False, e return True, None + + +error_type = Union[subprocess.CalledProcessError, json.JSONDecodeError] +plist_as_dict_return_type = Union[Tuple[dict, None], Tuple[None, error_type]] + + +def plist_as_dict(abs_path: str) -> plist_as_dict_return_type: + """Converts plist to python dictionary. + + Args: + abs_path (str) absolute path of the string to convert. + + Returns: + Plist (dictionary), + error (subprocess.CalledProcessError, json.JSONDecodeError) + """ + try: + plist = json.loads( + subprocess.check_output( + ['plutil', '-convert', 'json', '-o', '-', abs_path])) + return plist, None + except (subprocess.CalledProcessError, json.JSONDecodeError) as e: + return None, e
diff --git a/ios/build/bots/scripts/mac_util_test.py b/ios/build/bots/scripts/mac_util_test.py index c8ab833..622a9b8f9 100755 --- a/ios/build/bots/scripts/mac_util_test.py +++ b/ios/build/bots/scripts/mac_util_test.py
@@ -4,6 +4,7 @@ # found in the LICENSE file. """Unittests for mac_util_test.py.""" +import json import subprocess import unittest from unittest.mock import patch, MagicMock @@ -49,5 +50,51 @@ self.assertEqual(return_error, error) +class TestPlistAsDict(test_runner_test.TestCase): + + @patch('subprocess.check_output') + def test_complex_dict(self, mock_check_output: MagicMock): + + mock_return = '{"key1":"val1","key2":{"key3":[1,2,3],"key4":false}}'.encode( + 'utf-8') + mock_check_output.return_value = mock_return + + plist, error = mac_util.plist_as_dict('PATH') + + expected_plist = { + 'key1': 'val1', + 'key2': { + 'key3': [1, 2, 3], + 'key4': False + } + } + self.assertIsNone(error) + self.assertDictEqual(plist, expected_plist) + + @patch('subprocess.check_output') + def test_subprocess_call(self, mock_check_output: MagicMock): + mock_check_output.return_value = '{}'.encode('utf-8') + mac_util.plist_as_dict('PATH') + mock_check_output.assert_called_once_with( + ['plutil', '-convert', 'json', '-o', '-', 'PATH']) + + @patch('subprocess.check_output') + def test_subprocess_raises_error(self, mock_check_output: MagicMock): + mock_check_output.side_effect = subprocess.CalledProcessError( + cmd='cmd', returncode=1) + plist, error = mac_util.plist_as_dict('PATH') + self.assertIsNone(plist) + self.assertIsInstance(error, subprocess.CalledProcessError) + + @patch('subprocess.check_output') + def test_json_decode_raises_error(self, mock_check_output: MagicMock): + mock_json_loads = MagicMock() + mock_json_loads.side_effect = json.JSONDecodeError('message', 'doc', 0) + self.mock(json, 'loads', mock_json_loads) + plist, error = mac_util.plist_as_dict('PATH') + self.assertIsNone(plist) + self.assertIsInstance(error, json.JSONDecodeError) + + if __name__ == '__main__': unittest.main()
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index 0cda93e4..e660c080 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py
@@ -796,6 +796,10 @@ """Wipes the simulator.""" iossim_util.wipe_simulator_by_udid(self.udid) + def disable_hw_keyboard(self): + """Disables hardware keyboard input.""" + iossim_util.disable_hardware_keyboard(self.udid) + def get_home_directory(self): """Returns the simulator's home directory.""" return iossim_util.get_home_directory(self.platform, self.version) @@ -806,6 +810,7 @@ self.kill_simulators() self.wipe_simulator() self.wipe_derived_data() + self.disable_hw_keyboard() self.homedir = self.get_home_directory() # Crash reports have a timestamp in their file name, formatted as # YYYY-MM-DD-HHMMSS. Save the current time in the same format so
diff --git a/ios/chrome/browser/bookmarks/account_bookmark_model_factory.cc b/ios/chrome/browser/bookmarks/account_bookmark_model_factory.cc index 31a737ac8..9a55a22f 100644 --- a/ios/chrome/browser/bookmarks/account_bookmark_model_factory.cc +++ b/ios/chrome/browser/bookmarks/account_bookmark_model_factory.cc
@@ -41,7 +41,8 @@ new bookmarks::BookmarkModel(std::make_unique<BookmarkClientImpl>( browser_state, /*managed_bookmark_service=*/nullptr, ios::AccountBookmarkSyncServiceFactory::GetForBrowserState( - browser_state)))); + browser_state), + ios::BookmarkUndoServiceFactory::GetForBrowserState(browser_state)))); bookmark_model->Load(browser_state->GetStatePath(), bookmarks::StorageType::kAccount); ios::BookmarkUndoServiceFactory::GetForBrowserState(browser_state)
diff --git a/ios/chrome/browser/bookmarks/bookmark_client_impl.cc b/ios/chrome/browser/bookmarks/bookmark_client_impl.cc index f579d92a..d7bf99c 100644 --- a/ios/chrome/browser/bookmarks/bookmark_client_impl.cc +++ b/ios/chrome/browser/bookmarks/bookmark_client_impl.cc
@@ -17,16 +17,19 @@ #include "components/history/core/browser/url_database.h" #include "components/keyed_service/core/service_access_type.h" #include "components/sync_bookmarks/bookmark_sync_service.h" +#include "components/undo/bookmark_undo_service.h" #include "ios/chrome/browser/favicon/favicon_service_factory.h" #include "ios/chrome/browser/history/history_service_factory.h" BookmarkClientImpl::BookmarkClientImpl( ChromeBrowserState* browser_state, bookmarks::ManagedBookmarkService* managed_bookmark_service, - sync_bookmarks::BookmarkSyncService* bookmark_sync_service) + sync_bookmarks::BookmarkSyncService* bookmark_sync_service, + BookmarkUndoService* bookmark_undo_service) : browser_state_(browser_state), managed_bookmark_service_(managed_bookmark_service), - bookmark_sync_service_(bookmark_sync_service) {} + bookmark_sync_service_(bookmark_sync_service), + bookmark_undo_service_(bookmark_undo_service) {} BookmarkClientImpl::~BookmarkClientImpl() {} @@ -118,3 +121,13 @@ bookmark_sync_service_->DecodeBookmarkSyncMetadata( metadata_str, schedule_save_closure, model_); } + +void BookmarkClientImpl::OnBookmarkNodeRemovedUndoable( + bookmarks::BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const bookmarks::BookmarkNode* parent, + size_t index, + std::unique_ptr<bookmarks::BookmarkNode> node) { + bookmark_undo_service_->AddUndoEntryForRemovedNode( + model, undo_provider, parent, index, std::move(node)); +}
diff --git a/ios/chrome/browser/bookmarks/bookmark_client_impl.h b/ios/chrome/browser/bookmarks/bookmark_client_impl.h index 1c71726..1d1afc6 100644 --- a/ios/chrome/browser/bookmarks/bookmark_client_impl.h +++ b/ios/chrome/browser/bookmarks/bookmark_client_impl.h
@@ -9,27 +9,30 @@ #include <string> #include <vector> +#include "base/memory/raw_ptr.h" #include "base/task/deferred_sequenced_task_runner.h" #include "components/bookmarks/browser/bookmark_client.h" +class BookmarkUndoService; class ChromeBrowserState; class GURL; namespace bookmarks { class BookmarkModel; class ManagedBookmarkService; -} +} // namespace bookmarks namespace sync_bookmarks { class BookmarkSyncService; -} +} // namespace sync_bookmarks class BookmarkClientImpl : public bookmarks::BookmarkClient { public: BookmarkClientImpl( ChromeBrowserState* browser_state, bookmarks::ManagedBookmarkService* managed_bookmark_service, - sync_bookmarks::BookmarkSyncService* bookmark_sync_service); + sync_bookmarks::BookmarkSyncService* bookmark_sync_service, + BookmarkUndoService* bookmark_undo_service); BookmarkClientImpl(const BookmarkClientImpl&) = delete; BookmarkClientImpl& operator=(const BookmarkClientImpl&) = delete; @@ -56,21 +59,30 @@ void DecodeBookmarkSyncMetadata( const std::string& metadata_str, const base::RepeatingClosure& schedule_save_closure) override; + void OnBookmarkNodeRemovedUndoable( + bookmarks::BookmarkModel* model, + bookmarks::BookmarkUndoProvider* undo_provider, + const bookmarks::BookmarkNode* parent, + size_t index, + std::unique_ptr<bookmarks::BookmarkNode> node) override; private: // Pointer to the associated ChromeBrowserState. Must outlive // BookmarkClientImpl. - ChromeBrowserState* browser_state_ = nullptr; + const raw_ptr<ChromeBrowserState> browser_state_; // Pointer to the ManagedBookmarkService responsible for bookmark policy. May // be null during testing. - bookmarks::ManagedBookmarkService* managed_bookmark_service_ = nullptr; - - bookmarks::BookmarkModel* model_ = nullptr; + const raw_ptr<bookmarks::ManagedBookmarkService> managed_bookmark_service_; // Pointer to the BookmarkSyncService responsible for encoding and decoding // sync metadata persisted together with the bookmarks model. - sync_bookmarks::BookmarkSyncService* bookmark_sync_service_ = nullptr; + const raw_ptr<sync_bookmarks::BookmarkSyncService> bookmark_sync_service_; + + // Pointer to BookmarkUndoService, responsible for making operations undoable. + const raw_ptr<BookmarkUndoService> bookmark_undo_service_; + + raw_ptr<bookmarks::BookmarkModel> model_ = nullptr; }; #endif // IOS_CHROME_BROWSER_BOOKMARKS_BOOKMARK_CLIENT_IMPL_H_
diff --git a/ios/chrome/browser/bookmarks/local_or_syncable_bookmark_model_factory.cc b/ios/chrome/browser/bookmarks/local_or_syncable_bookmark_model_factory.cc index be86183..8557b786 100644 --- a/ios/chrome/browser/bookmarks/local_or_syncable_bookmark_model_factory.cc +++ b/ios/chrome/browser/bookmarks/local_or_syncable_bookmark_model_factory.cc
@@ -36,7 +36,8 @@ browser_state, ManagedBookmarkServiceFactory::GetForBrowserState(browser_state), ios::LocalOrSyncableBookmarkSyncServiceFactory::GetForBrowserState( - browser_state))); + browser_state), + ios::BookmarkUndoServiceFactory::GetForBrowserState(browser_state))); bookmark_model->Load(browser_state->GetStatePath(), bookmarks::StorageType::kLocalOrSyncable); ios::BookmarkUndoServiceFactory::GetForBrowserState(browser_state)
diff --git a/ios/chrome/browser/flags/BUILD.gn b/ios/chrome/browser/flags/BUILD.gn index 7cacf8f..51acd98 100644 --- a/ios/chrome/browser/flags/BUILD.gn +++ b/ios/chrome/browser/flags/BUILD.gn
@@ -82,7 +82,6 @@ "//ios/chrome/browser/ui/ntp:feature_flags", "//ios/chrome/browser/ui/ntp:field_trial", "//ios/chrome/browser/ui/omnibox:features", - "//ios/chrome/browser/ui/open_in:features", "//ios/chrome/browser/ui/popup_menu/overflow_menu:feature_flags", "//ios/chrome/browser/ui/post_restore_signin:features", "//ios/chrome/browser/ui/start_surface:feature_flags",
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 5c483b9..f07a206 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -95,7 +95,6 @@ #import "ios/chrome/browser/ui/ntp/new_tab_page_feature.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_retention_field_trial_constants.h" #import "ios/chrome/browser/ui/omnibox/omnibox_ui_features.h" -#import "ios/chrome/browser/ui/open_in/features.h" #import "ios/chrome/browser/ui/popup_menu/overflow_menu/feature_flags.h" #import "ios/chrome/browser/ui/post_restore_signin/features.h" #import "ios/chrome/browser/ui/start_surface/start_surface_features.h" @@ -464,22 +463,6 @@ std::size(kFeedAppCloseBackgroundRefresh), nullptr}, }; -const FeatureEntry::FeatureParam kOpenInDownloadInShareButton[] = { - {kOpenInDownloadParameterName, kOpenInDownloadInShareButtonParam}}; -const FeatureEntry::FeatureParam kOpenInDownloadWithWKDownload[] = { - {kOpenInDownloadParameterName, kOpenInDownloadWithWKDownloadParam}}; -const FeatureEntry::FeatureParam kOpenInDownloadWithV2[] = { - {kOpenInDownloadParameterName, kOpenInDownloadWithV2Param}}; - -const FeatureEntry::FeatureVariation kOpenInDownloadVariations[] = { - {"With legacy download", kOpenInDownloadInShareButton, - std::size(kOpenInDownloadInShareButton), nullptr}, - {"With WKDownload", kOpenInDownloadWithWKDownload, - std::size(kOpenInDownloadWithWKDownload), nullptr}, - {"With V2", kOpenInDownloadWithV2, std::size(kOpenInDownloadWithV2), - nullptr}, -}; - const FeatureEntry::FeatureParam kEnablePinnedTabsOverflow[] = { {kEnablePinnedTabsOverflowParam, "true"}}; @@ -1196,11 +1179,6 @@ flag_descriptions::kOmniboxKeyboardPasteButtonDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kOmniboxKeyboardPasteButton)}, - {"enable-open-in-download", flag_descriptions::kEnableOpenInDownloadName, - flag_descriptions::kEnableOpenInDownloadDescription, flags_ui::kOsIos, - FEATURE_WITH_PARAMS_VALUE_TYPE(kEnableOpenInDownload, - kOpenInDownloadVariations, - "EnableOpenInDownload")}, {"whats-new-ios", flag_descriptions::kWhatsNewIOSName, flag_descriptions::kWhatsNewIOSDescription, flags_ui::kOsIos, FEATURE_WITH_PARAMS_VALUE_TYPE(kWhatsNewIOS,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 261bcc3..3803a3c 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -364,10 +364,6 @@ "Group passwords into the same affiliated group in the Password Manager " "for the Saved Passwords section"; -const char kEnableOpenInDownloadName[] = "Enable Open In download"; -const char kEnableOpenInDownloadDescription[] = - "Enable new download for Open In menu (iOS 14.5+)."; - const char kEnablePasswordsAccountStorageName[] = "Enable the account data storage for passwords"; const char kEnablePasswordsAccountStorageDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index b7ca7c9..c5c8ffa8 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -320,10 +320,6 @@ extern const char kPasswordsGroupingName[]; extern const char kPasswordsGroupingDescription[]; -// Title and description for the flag to enable open in download. -extern const char kEnableOpenInDownloadName[]; -extern const char kEnableOpenInDownloadDescription[]; - // Title and description for the flag to enable the passwords account storage. extern const char kEnablePasswordsAccountStorageName[]; extern const char kEnablePasswordsAccountStorageDescription[];
diff --git a/ios/chrome/browser/open_in/BUILD.gn b/ios/chrome/browser/open_in/BUILD.gn deleted file mode 100644 index 9000979..0000000 --- a/ios/chrome/browser/open_in/BUILD.gn +++ /dev/null
@@ -1,41 +0,0 @@ -# Copyright 2019 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//build/config/ios/rules.gni") - -source_set("open_in") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "open_in_tab_helper.h", - "open_in_tab_helper.mm", - "open_in_tab_helper_delegate.h", - ] - deps = [ - "//base", - "//ios/chrome/app/strings", - "//ios/chrome/browser/shared/model/browser_state", - "//ios/chrome/browser/shared/public/features", - "//ios/web/public", - "//ui/base:base", - "//url", - ] -} - -source_set("unit_tests") { - configs += [ "//build/config/compiler:enable_arc" ] - testonly = true - sources = [ "open_in_tab_helper_unittest.mm" ] - deps = [ - ":open_in", - "//base", - "//base/test:test_support", - "//ios/chrome/app/strings", - "//ios/chrome/browser/shared/model/browser_state:test_support", - "//ios/chrome/browser/ui/open_in", - "//ios/web/public/test/fakes", - "//testing/gtest", - "//ui/base:base", - "//url", - ] -}
diff --git a/ios/chrome/browser/open_in/DEPS b/ios/chrome/browser/open_in/DEPS deleted file mode 100644 index 70949eff7..0000000 --- a/ios/chrome/browser/open_in/DEPS +++ /dev/null
@@ -1,7 +0,0 @@ -specific_include_rules = { - # TODO(crbug.com/1294160): Remove this dependency. - "^open_in_tab_helper.mm": [ - "+ios/chrome/browser/ui/ui_feature_flags.h", - ], -} -
diff --git a/ios/chrome/browser/open_in/OWNERS b/ios/chrome/browser/open_in/OWNERS deleted file mode 100644 index 10e4970..0000000 --- a/ios/chrome/browser/open_in/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -ewannpv@chromium.org -alionadangla@chromium.org -gambard@chromium.org
diff --git a/ios/chrome/browser/open_in/open_in_tab_helper_delegate.h b/ios/chrome/browser/open_in/open_in_tab_helper_delegate.h deleted file mode 100644 index e9a33e0..0000000 --- a/ios/chrome/browser/open_in/open_in_tab_helper_delegate.h +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_OPEN_IN_OPEN_IN_TAB_HELPER_DELEGATE_H_ -#define IOS_CHROME_BROWSER_OPEN_IN_OPEN_IN_TAB_HELPER_DELEGATE_H_ - -class GURL; - -namespace web { -class WebState; -} - -@class NSString; - -// Protocol for handling openIn and presenting related UI. -@protocol OpenInTabHelperDelegate - -// Enables the openIn view for the webState with the `documentURL` and sets -// the file name for the currently loaded document. -- (void)enableOpenInForWebState:(web::WebState*)webState - withDocumentURL:(const GURL&)documentURL - suggestedFileName:(NSString*)suggestedFileName; - -// Disables the openIn view for `webState`. -- (void)disableOpenInForWebState:(web::WebState*)webState; - -// Destroys the openIn view and detach it from the `webState`. -- (void)destroyOpenInForWebState:(web::WebState*)webState; - -@end - -#endif // IOS_CHROME_BROWSER_OPEN_IN_OPEN_IN_TAB_HELPER_DELEGATE_H_
diff --git a/ios/chrome/browser/open_in/open_in_tab_helper_unittest.mm b/ios/chrome/browser/open_in/open_in_tab_helper_unittest.mm deleted file mode 100644 index 0cced2c3..0000000 --- a/ios/chrome/browser/open_in/open_in_tab_helper_unittest.mm +++ /dev/null
@@ -1,302 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/open_in/open_in_tab_helper.h" - -#import <memory> - -#import "base/memory/ref_counted.h" -#import "base/strings/sys_string_conversions.h" -#import "base/test/scoped_feature_list.h" -#import "ios/chrome/browser/open_in/open_in_tab_helper_delegate.h" -#import "ios/chrome/grit/ios_strings.h" -#import "ios/web/public/navigation/navigation_item.h" -#import "ios/web/public/navigation/navigation_manager.h" -#import "ios/web/public/test/fakes/fake_navigation_context.h" -#import "ios/web/public/test/fakes/fake_navigation_manager.h" -#import "ios/web/public/test/fakes/fake_web_state.h" -#import "net/http/http_response_headers.h" -#import "testing/gtest/include/gtest/gtest.h" -#import "testing/gtest_mac.h" -#import "testing/platform_test.h" -#import "ui/base/l10n/l10n_util.h" -#import "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// An object that conforms to OpenInTabHelperDelegate for testing. -@interface FakeOpenInTabHelperDelegate : NSObject <OpenInTabHelperDelegate> -// URL of the last opened document. -@property(nonatomic, assign) GURL lastOpenedDocumentURL; -// The last suggested file name used for openIn. -@property(nonatomic, copy) NSString* lastSuggestedFileName; -// True if disableOpenInForWebState was called. -@property(nonatomic, assign) BOOL openInDisabled; -// True if destroyOpenInForWebState was called. -@property(nonatomic, assign) BOOL openInDestroyed; -@end - -@implementation FakeOpenInTabHelperDelegate -- (void)enableOpenInForWebState:(web::WebState*)webState - withDocumentURL:(const GURL&)documentURL - suggestedFileName:(NSString*)suggestedFileName { - self.lastOpenedDocumentURL = documentURL; - self.lastSuggestedFileName = suggestedFileName; - self.openInDisabled = NO; -} -- (void)disableOpenInForWebState:(web::WebState*)webState { - self.openInDisabled = YES; -} -- (void)destroyOpenInForWebState:(web::WebState*)webState { - self.openInDestroyed = YES; -} -@end - -namespace { - -const char kInvalidFileNameUrl[] = "https://test.test/"; -const char kContentDispositionWithoutFileName[] = - "attachment; parameter=parameter_value"; -const char kHtmlContentType[] = "text/html"; -const char kValidFileNamePDF[] = "https://test.test/file_name.pdf"; -const char kValidFileNameMicrosoftPowerPointOpenXML[] = - "https://test.test/file_name.pptx"; - -// Returns the content type according to the current testing value. -std::string ContentTypeForMimeType(OpenInMimeType parameter) { - switch (parameter) { - case OpenInMimeType::kMimeTypeMicrosoftPowerPointOpenXML: - return content_type::kMimeTypeMicrosoftPowerPointOpenXML; - case OpenInMimeType::kMimeTypeMicrosoftWordOpenXML: - return content_type::kMimeTypeMicrosoftWordOpenXML; - case OpenInMimeType::kMimeTypeMicrosoftExcelOpenXML: - return content_type::kMimeTypeMicrosoftExcelOpenXML; - case OpenInMimeType::kMimeTypePDF: - return content_type::kMimeTypePDF; - case OpenInMimeType::kMimeTypeMicrosoftWord: - return content_type::kMimeTypeMicrosoftWord; - case OpenInMimeType::kMimeTypeJPEG: - return content_type::kMimeTypeJPEG; - case OpenInMimeType::kMimeTypePNG: - return content_type::kMimeTypePNG; - case OpenInMimeType::kMimeTypeMicrosoftPowerPoint: - return content_type::kMimeTypeMicrosoftPowerPoint; - case OpenInMimeType::kMimeTypeRTF: - return content_type::kMimeTypeRTF; - case OpenInMimeType::kMimeTypeSVG: - return content_type::kMimeTypeSVG; - case OpenInMimeType::kMimeTypeMicrosoftExcel: - return content_type::kMimeTypeMicrosoftExcel; - // Should not be reached. - case OpenInMimeType::kMimeTypeNotHandled: - return ""; - } -} - -// Returns the file extension according to the current testing value. -std::string ExtensionForMimeType(OpenInMimeType parameter) { - switch (parameter) { - case OpenInMimeType::kMimeTypeMicrosoftPowerPointOpenXML: - return ".pptx"; - case OpenInMimeType::kMimeTypeMicrosoftWordOpenXML: - return ".docx"; - case OpenInMimeType::kMimeTypeMicrosoftExcelOpenXML: - return ".xlsx"; - case OpenInMimeType::kMimeTypePDF: - return ".pdf"; - case OpenInMimeType::kMimeTypeMicrosoftWord: - return ".doc"; - case OpenInMimeType::kMimeTypeJPEG: - return ".jpeg"; - case OpenInMimeType::kMimeTypePNG: - return ".png"; - case OpenInMimeType::kMimeTypeMicrosoftPowerPoint: - return ".ppt"; - case OpenInMimeType::kMimeTypeRTF: - return ".rtf"; - case OpenInMimeType::kMimeTypeSVG: - return ".svg"; - case OpenInMimeType::kMimeTypeMicrosoftExcel: - return ".xls"; - // Should not be reached. - case OpenInMimeType::kMimeTypeNotHandled: - return ""; - } -} - -// Returns the file name according to the current testing value. -std::string FileNameForMimeType(OpenInMimeType parameter) { - return "filename" + ExtensionForMimeType(parameter); -} -} // namespace - -// Test fixture for OpenInTabHelper class. -class OpenInTabHelperTest - : public PlatformTest, - public ::testing::WithParamInterface<OpenInMimeType> { - protected: - OpenInTabHelperTest() - : delegate_([[FakeOpenInTabHelperDelegate alloc] init]) { - OpenInTabHelper::CreateForWebState(&web_state_); - tab_helper()->SetDelegate(delegate_); - - // Setup navigation manager. - auto navigation_manager = std::make_unique<web::FakeNavigationManager>(); - navigation_manager_ = navigation_manager.get(); - web_state_.SetNavigationManager(std::move(navigation_manager)); - } - - OpenInTabHelper* tab_helper() { - return OpenInTabHelper::FromWebState(&web_state_); - } - - // Simulates a navigation to `url` and set the proper response headers based - // on `content_type` and `content_disposition` - void NavigateTo(const GURL& url, - const char* content_type, - const char* content_disposition) { - item_ = web::NavigationItem::Create(); - item_->SetURL(url); - scoped_refptr<net::HttpResponseHeaders> headers = - new net::HttpResponseHeaders("HTTP 1.1 200 OK"); - headers->SetHeader("Content-Type", content_type); - headers->SetHeader("Content-Disposition", content_disposition); - - web::FakeNavigationContext navigation_context; - navigation_context.SetResponseHeaders(headers); - web_state_.OnNavigationStarted(&navigation_context); - navigation_manager_->SetLastCommittedItem(item_.get()); - // PageLoaded will always be called after DidFinishNavigation. - web_state_.OnNavigationFinished(&navigation_context); - web_state_.LoadData(nil, base::SysUTF8ToNSString(content_type), url); - } - - FakeOpenInTabHelperDelegate* delegate_ = nil; - web::FakeWebState web_state_; - web::FakeNavigationManager* navigation_manager_; - std::unique_ptr<web::NavigationItem> item_; -}; - -// Tests that on starting new navigation openIn will be disabled. -TEST_F(OpenInTabHelperTest, WebStateObservationStartNavigation) { - ASSERT_FALSE(delegate_.openInDisabled); - web_state_.OnNavigationStarted(nullptr); - EXPECT_TRUE(delegate_.openInDisabled); -} - -// Tests that on web state destruction openIn will be destroyed. -TEST_F(OpenInTabHelperTest, WebStateObservationDestruction) { - auto web_state = std::make_unique<web::FakeWebState>(); - OpenInTabHelper::CreateForWebState(web_state.get()); - OpenInTabHelper::FromWebState(web_state.get())->SetDelegate(delegate_); - EXPECT_FALSE(delegate_.openInDestroyed); - web_state = nullptr; - EXPECT_TRUE(delegate_.openInDestroyed); -} - -// Tests that openIn is enabled for exportable files and that it uses the file -// name from the content desposition key in the response headers. -TEST_P(OpenInTabHelperTest, - OpenInForExportableFilesWithFileNameFromContentDesposition) { - base::test::ScopedFeatureList feature_list; - ASSERT_FALSE(delegate_.openInDisabled); - - const std::string file_name = - FileNameForMimeType(OpenInTabHelperTest::GetParam()); - GURL url("https://test.test/" + file_name); - - NavigateTo(url, - ContentTypeForMimeType(OpenInTabHelperTest::GetParam()).c_str(), - ("attachment; filename=\"suggested_" + file_name + "\"").c_str()); - - EXPECT_FALSE(delegate_.openInDisabled); - EXPECT_EQ(url, delegate_.lastOpenedDocumentURL); - - std::string suggested_file_name = "suggested_" + file_name; - EXPECT_NSEQ(base::SysUTF8ToNSString(suggested_file_name), - delegate_.lastSuggestedFileName); -} - -// Tests that openIn is enabled for exportable files and that it uses the file -// name from the URL if the content desposition key in the response headers -// doesn't have file name. -TEST_P(OpenInTabHelperTest, OpenInForExportableFilesWithFileNameFromURL) { - base::test::ScopedFeatureList feature_list; - ASSERT_FALSE(delegate_.openInDisabled); - - const std::string file_name = - FileNameForMimeType(OpenInTabHelperTest::GetParam()); - GURL url("https://test.test/" + file_name); - NavigateTo(url, - ContentTypeForMimeType(OpenInTabHelperTest::GetParam()).c_str(), - kContentDispositionWithoutFileName); - - EXPECT_FALSE(delegate_.openInDisabled); - EXPECT_EQ(url, delegate_.lastOpenedDocumentURL); - - EXPECT_NSEQ(base::SysUTF8ToNSString(file_name), - delegate_.lastSuggestedFileName); -} - -// Tests that openIn is enabled for exportable files and that it uses the -// default file name if neither the URL nor the content desposition key in the -// response headers has a file name. -TEST_P(OpenInTabHelperTest, OpenInForExportableFilesWithDefaultFileName) { - base::test::ScopedFeatureList feature_list; - ASSERT_FALSE(delegate_.openInDisabled); - - GURL url(kInvalidFileNameUrl); - NavigateTo(url, - ContentTypeForMimeType(OpenInTabHelperTest::GetParam()).c_str(), - kContentDispositionWithoutFileName); - - EXPECT_FALSE(delegate_.openInDisabled); - EXPECT_EQ(url, delegate_.lastOpenedDocumentURL); - - std::string default_file_name = - l10n_util::GetStringUTF8(IDS_IOS_OPEN_IN_FILE_DEFAULT_TITLE) + - ExtensionForMimeType(OpenInTabHelperTest::GetParam()); - - EXPECT_NSEQ(base::SysUTF8ToNSString(default_file_name), - delegate_.lastSuggestedFileName); -} - -// Tests that openIn is disabled for non exportable files. -TEST_F(OpenInTabHelperTest, OpenInDisabledForNonExportableFiles) { - base::test::ScopedFeatureList feature_list; - ASSERT_FALSE(delegate_.openInDisabled); - - // Testing PDF. - GURL url_pdf(kValidFileNamePDF); - NavigateTo(url_pdf, kHtmlContentType, kContentDispositionWithoutFileName); - - EXPECT_EQ(GURL::EmptyGURL(), delegate_.lastOpenedDocumentURL); - EXPECT_FALSE(delegate_.lastSuggestedFileName); - EXPECT_TRUE(delegate_.openInDisabled); - - // Testing Microsoft PowerPoint OpenXML. - GURL url_pptx(kValidFileNameMicrosoftPowerPointOpenXML); - NavigateTo(url_pptx, kHtmlContentType, kContentDispositionWithoutFileName); - - EXPECT_EQ(GURL::EmptyGURL(), delegate_.lastOpenedDocumentURL); - EXPECT_FALSE(delegate_.lastSuggestedFileName); - EXPECT_TRUE(delegate_.openInDisabled); -} - -INSTANTIATE_TEST_SUITE_P( - , - OpenInTabHelperTest, - ::testing::Values(OpenInMimeType::kMimeTypePDF, - OpenInMimeType::kMimeTypeMicrosoftWord, - OpenInMimeType::kMimeTypeMicrosoftWordOpenXML, - OpenInMimeType::kMimeTypeJPEG, - OpenInMimeType::kMimeTypePNG, - OpenInMimeType::kMimeTypeMicrosoftPowerPoint, - OpenInMimeType::kMimeTypeMicrosoftPowerPointOpenXML, - OpenInMimeType::kMimeTypeRTF, - OpenInMimeType::kMimeTypeSVG, - OpenInMimeType::kMimeTypeMicrosoftExcel, - OpenInMimeType::kMimeTypeMicrosoftExcelOpenXML));
diff --git a/ios/chrome/browser/passwords/password_checkup_utils_unittest.mm b/ios/chrome/browser/passwords/password_checkup_utils_unittest.mm index dfb8530..e19c3340 100644 --- a/ios/chrome/browser/passwords/password_checkup_utils_unittest.mm +++ b/ios/chrome/browser/passwords/password_checkup_utils_unittest.mm
@@ -137,8 +137,7 @@ base::test::ScopedFeatureList feature_list( password_manager::features::kIOSPasswordCheckup); - std::vector<CredentialUIEntry> insecure_credentials = - manager().GetInsecureCredentials(); + std::vector<CredentialUIEntry> insecure_credentials; // The "no insecure passwords" warning is the highest priority warning. EXPECT_THAT(GetWarningOfHighestPriority(insecure_credentials), WarningType::kNoInsecurePasswordsWarning); @@ -147,9 +146,8 @@ PasswordForm form1 = MakeSavedPassword(kExampleCom1, kUsername116); AddIssueToForm(&form1, InsecureType::kLeaked, base::Minutes(1), /*is_muted=*/true); - store().AddLogin(form1); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form1); + // The "dismissed warnings" warning becomes the highest priority warning. EXPECT_THAT(GetWarningOfHighestPriority(insecure_credentials), WarningType::kDismissedWarningsWarning); @@ -159,9 +157,7 @@ AddIssueToForm(&form2, InsecureType::kLeaked, base::Minutes(1), /*is_muted=*/true); AddIssueToForm(&form2, InsecureType::kWeak, base::Minutes(1)); - store().AddLogin(form2); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form2); // The "weak passwords" warning becomes the highest priority warning. EXPECT_THAT(GetWarningOfHighestPriority(insecure_credentials), WarningType::kWeakPasswordsWarning); @@ -169,9 +165,7 @@ // Add a weak password. PasswordForm form3 = MakeSavedPassword(kExampleCom3, kUsername116); AddIssueToForm(&form3, InsecureType::kWeak, base::Minutes(1)); - store().AddLogin(form3); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form3); // The "weak passwords" warning stays the highest priority warning. EXPECT_THAT(GetWarningOfHighestPriority(insecure_credentials), WarningType::kWeakPasswordsWarning); @@ -179,12 +173,10 @@ // Add 2 reused passwords. PasswordForm form4 = MakeSavedPassword(kExampleCom4, kUsername116); AddIssueToForm(&form4, InsecureType::kReused, base::Minutes(1)); - store().AddLogin(form4); PasswordForm form5 = MakeSavedPassword(kExampleCom5, kUsername116); AddIssueToForm(&form5, InsecureType::kReused, base::Minutes(1)); - store().AddLogin(form5); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form4); + insecure_credentials.emplace_back(form5); // The "reused passwords" warning becomes the highest priority warning. EXPECT_THAT(GetWarningOfHighestPriority(insecure_credentials), WarningType::kReusedPasswordsWarning); @@ -192,9 +184,7 @@ // Add an unmuted compromised password. PasswordForm form6 = MakeSavedPassword(kExampleCom6, kUsername116); AddIssueToForm(&form6, InsecureType::kLeaked, base::Minutes(1)); - store().AddLogin(form6); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form6); // The "compromised passwords" warning becomes the highest priority warning. EXPECT_THAT(GetWarningOfHighestPriority(insecure_credentials), WarningType::kCompromisedPasswordsWarning); @@ -207,8 +197,7 @@ base::test::ScopedFeatureList feature_list( password_manager::features::kIOSPasswordCheckup); - std::vector<CredentialUIEntry> insecure_credentials = - manager().GetInsecureCredentials(); + std::vector<CredentialUIEntry> insecure_credentials; WarningType warning_type = GetWarningOfHighestPriority(insecure_credentials); EXPECT_EQ(GetPasswordCountForWarningType(warning_type, insecure_credentials), 0); @@ -217,9 +206,7 @@ PasswordForm form1 = MakeSavedPassword(kExampleCom1, kUsername116); AddIssueToForm(&form1, InsecureType::kLeaked, base::Minutes(1), /*is_muted=*/true); - store().AddLogin(form1); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form1); warning_type = GetWarningOfHighestPriority(insecure_credentials); // The number of passwords for which the compromised warning was dismissed // should be returned. @@ -231,10 +218,8 @@ PasswordForm form3 = MakeSavedPassword(kExampleCom3, kUsername116); AddIssueToForm(&form2, InsecureType::kWeak, base::Minutes(1)); AddIssueToForm(&form3, InsecureType::kWeak, base::Minutes(1)); - store().AddLogin(form2); - store().AddLogin(form3); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form2); + insecure_credentials.emplace_back(form3); warning_type = GetWarningOfHighestPriority(insecure_credentials); // The number of weak passwords should be returned. EXPECT_EQ(GetPasswordCountForWarningType(warning_type, insecure_credentials), @@ -247,11 +232,9 @@ AddIssueToForm(&form4, InsecureType::kReused, base::Minutes(1)); AddIssueToForm(&form5, InsecureType::kReused, base::Minutes(1)); AddIssueToForm(&form6, InsecureType::kReused, base::Minutes(1)); - store().AddLogin(form4); - store().AddLogin(form5); - store().AddLogin(form6); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form4); + insecure_credentials.emplace_back(form5); + insecure_credentials.emplace_back(form6); warning_type = GetWarningOfHighestPriority(insecure_credentials); // The number of reused passwords should be returned. EXPECT_EQ(GetPasswordCountForWarningType(warning_type, insecure_credentials), @@ -266,12 +249,10 @@ AddIssueToForm(&form8, InsecureType::kLeaked, base::Minutes(1)); AddIssueToForm(&form9, InsecureType::kLeaked, base::Minutes(1)); AddIssueToForm(&form10, InsecureType::kLeaked, base::Minutes(1)); - store().AddLogin(form7); - store().AddLogin(form8); - store().AddLogin(form9); - store().AddLogin(form10); - RunUntilIdle(); - insecure_credentials = manager().GetInsecureCredentials(); + insecure_credentials.emplace_back(form7); + insecure_credentials.emplace_back(form8); + insecure_credentials.emplace_back(form9); + insecure_credentials.emplace_back(form10); warning_type = GetWarningOfHighestPriority(insecure_credentials); // The number of compromised passwords should be returned. EXPECT_EQ(GetPasswordCountForWarningType(warning_type, insecure_credentials),
diff --git a/ios/chrome/browser/sharing/BUILD.gn b/ios/chrome/browser/sharing/BUILD.gn new file mode 100644 index 0000000..56ac091 --- /dev/null +++ b/ios/chrome/browser/sharing/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2019 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ios/rules.gni") + +source_set("sharing") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "share_file_download_tab_helper.h", + "share_file_download_tab_helper.mm", + ] + deps = [ + "//base", + "//ios/chrome/app/strings", + "//ios/chrome/browser/shared/model/browser_state", + "//ios/chrome/browser/shared/public/features", + "//ios/web/public", + "//ui/base:base", + "//url", + ] +}
diff --git a/ios/chrome/browser/open_in/open_in_tab_helper.h b/ios/chrome/browser/sharing/share_file_download_tab_helper.h similarity index 70% rename from ios/chrome/browser/open_in/open_in_tab_helper.h rename to ios/chrome/browser/sharing/share_file_download_tab_helper.h index 0a800a8c..03b56fb2 100644 --- a/ios/chrome/browser/open_in/open_in_tab_helper.h +++ b/ios/chrome/browser/sharing/share_file_download_tab_helper.h
@@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_OPEN_IN_OPEN_IN_TAB_HELPER_H_ -#define IOS_CHROME_BROWSER_OPEN_IN_OPEN_IN_TAB_HELPER_H_ +#ifndef IOS_CHROME_BROWSER_SHARING_SHARE_FILE_DOWNLOAD_TAB_HELPER_H_ +#define IOS_CHROME_BROWSER_SHARING_SHARE_FILE_DOWNLOAD_TAB_HELPER_H_ #include <string> -#import "ios/chrome/browser/open_in/open_in_tab_helper_delegate.h" #include "ios/web/public/web_state_observer.h" #import "ios/web/public/web_state_user_data.h" @@ -54,7 +53,7 @@ // Enum used to determine the MIME type of a previewed file. Entries should // always keep synced with the IOS.OpenIn.MimeType UMA histogram. -enum class OpenInMimeType { +enum class ShareFileDownloadMimeType { kMimeTypeNotHandled = 0, kMimeTypePDF = 1, kMimeTypeMicrosoftWord = 2, @@ -70,21 +69,17 @@ kMaxValue = kMimeTypeMicrosoftExcelOpenXML, }; -@class OpenInController; - // A tab helper that observes WebState and shows open in button for PDF // documents. -class OpenInTabHelper : public web::WebStateObserver, - public web::WebStateUserData<OpenInTabHelper> { +class ShareFileDownloadTabHelper + : public web::WebStateObserver, + public web::WebStateUserData<ShareFileDownloadTabHelper> { public: - OpenInTabHelper(const OpenInTabHelper&) = delete; - OpenInTabHelper& operator=(const OpenInTabHelper&) = delete; + ShareFileDownloadTabHelper(const ShareFileDownloadTabHelper&) = delete; + ShareFileDownloadTabHelper& operator=(const ShareFileDownloadTabHelper&) = + delete; - ~OpenInTabHelper() override; - - // Sets the OpenInTabHelper delegate. `delegate` will be in charge of enabling - // the openIn view. `delegate` is not retained by TabHelper. - void SetDelegate(id<OpenInTabHelperDelegate> delegate); + ~ShareFileDownloadTabHelper() override; // Returns true if the displayed content should be downloaded. static bool ShouldDownload(web::WebState* web_state); @@ -93,24 +88,22 @@ std::u16string GetFileNameSuggestion(); private: - friend class web::WebStateUserData<OpenInTabHelper>; + friend class web::WebStateUserData<ShareFileDownloadTabHelper>; - explicit OpenInTabHelper(web::WebState* web_state); + explicit ShareFileDownloadTabHelper(web::WebState* web_state); // Handles exportable files and shows open in button if content mime type is // PDF. void HandleExportableFile(); // Tests that files are exportable and returns their MIME type. - OpenInMimeType GetUmaResult(const std::string& mime_type) const; + ShareFileDownloadMimeType GetUmaResult(const std::string& mime_type) const; // WebStateObserver implementation. void PageLoaded( web::WebState* web_state, web::PageLoadCompletionStatus load_completion_status) override; void WebStateDestroyed(web::WebState* web_state) override; - void DidStartNavigation(web::WebState* web_state, - web::NavigationContext* navigation_context) override; void DidFinishNavigation(web::WebState* web_state, web::NavigationContext* navigation_context) override; @@ -121,10 +114,7 @@ // Headers of the last response received for the current navigation. scoped_refptr<net::HttpResponseHeaders> response_headers_; - // Used to enable/disable openIn UI. - __weak id<OpenInTabHelperDelegate> delegate_ = nil; - WEB_STATE_USER_DATA_KEY_DECL(); }; -#endif // IOS_CHROME_BROWSER_OPEN_IN_OPEN_IN_TAB_HELPER_H_ +#endif // IOS_CHROME_BROWSER_SHARING_SHARE_FILE_DOWNLOAD_TAB_HELPER_H_
diff --git a/ios/chrome/browser/open_in/open_in_tab_helper.mm b/ios/chrome/browser/sharing/share_file_download_tab_helper.mm similarity index 64% rename from ios/chrome/browser/open_in/open_in_tab_helper.mm rename to ios/chrome/browser/sharing/share_file_download_tab_helper.mm index dae7784..830ae93 100644 --- a/ios/chrome/browser/open_in/open_in_tab_helper.mm +++ b/ios/chrome/browser/sharing/share_file_download_tab_helper.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/open_in/open_in_tab_helper.h" +#import "ios/chrome/browser/sharing/share_file_download_tab_helper.h" #import "base/memory/ptr_util.h" #import "base/metrics/histogram_functions.h" @@ -53,72 +53,65 @@ } // namespace content_type -void OpenInTabHelper::SetDelegate(id<OpenInTabHelperDelegate> delegate) { - delegate_ = delegate; -} - -OpenInTabHelper::~OpenInTabHelper() { +ShareFileDownloadTabHelper::~ShareFileDownloadTabHelper() { // In case that the destructor is called before WebStateDestroyed. stop // observing the WebState. if (web_state_) { - [delegate_ destroyOpenInForWebState:web_state_]; web_state_->RemoveObserver(this); web_state_ = nullptr; } } -OpenInMimeType OpenInTabHelper::GetUmaResult( +ShareFileDownloadMimeType ShareFileDownloadTabHelper::GetUmaResult( const std::string& mime_type) const { - if (mime_type == content_type::kMimeTypePDF) - return OpenInMimeType::kMimeTypePDF; - if (mime_type == content_type::kMimeTypeMicrosoftWord) - return OpenInMimeType::kMimeTypeMicrosoftWord; - if (mime_type == content_type::kMimeTypeMicrosoftWordOpenXML) - return OpenInMimeType::kMimeTypeMicrosoftWordOpenXML; - if (mime_type == content_type::kMimeTypeJPEG) - return OpenInMimeType::kMimeTypeJPEG; - if (mime_type == content_type::kMimeTypePNG) - return OpenInMimeType::kMimeTypePNG; - if (mime_type == content_type::kMimeTypeMicrosoftPowerPoint) - return OpenInMimeType::kMimeTypeMicrosoftPowerPoint; - if (mime_type == content_type::kMimeTypeMicrosoftPowerPointOpenXML) - return OpenInMimeType::kMimeTypeMicrosoftPowerPointOpenXML; - if (mime_type == content_type::kMimeTypeRTF) - return OpenInMimeType::kMimeTypeRTF; - if (mime_type == content_type::kMimeTypeSVG) - return OpenInMimeType::kMimeTypeSVG; - if (mime_type == content_type::kMimeTypeMicrosoftExcel) - return OpenInMimeType::kMimeTypeMicrosoftExcel; - if (mime_type == content_type::kMimeTypeMicrosoftExcelOpenXML) - return OpenInMimeType::kMimeTypeMicrosoftExcelOpenXML; - return OpenInMimeType::kMimeTypeNotHandled; + if (mime_type == content_type::kMimeTypePDF) { + return ShareFileDownloadMimeType::kMimeTypePDF; + } + if (mime_type == content_type::kMimeTypeMicrosoftWord) { + return ShareFileDownloadMimeType::kMimeTypeMicrosoftWord; + } + if (mime_type == content_type::kMimeTypeMicrosoftWordOpenXML) { + return ShareFileDownloadMimeType::kMimeTypeMicrosoftWordOpenXML; + } + if (mime_type == content_type::kMimeTypeJPEG) { + return ShareFileDownloadMimeType::kMimeTypeJPEG; + } + if (mime_type == content_type::kMimeTypePNG) { + return ShareFileDownloadMimeType::kMimeTypePNG; + } + if (mime_type == content_type::kMimeTypeMicrosoftPowerPoint) { + return ShareFileDownloadMimeType::kMimeTypeMicrosoftPowerPoint; + } + if (mime_type == content_type::kMimeTypeMicrosoftPowerPointOpenXML) { + return ShareFileDownloadMimeType::kMimeTypeMicrosoftPowerPointOpenXML; + } + if (mime_type == content_type::kMimeTypeRTF) { + return ShareFileDownloadMimeType::kMimeTypeRTF; + } + if (mime_type == content_type::kMimeTypeSVG) { + return ShareFileDownloadMimeType::kMimeTypeSVG; + } + if (mime_type == content_type::kMimeTypeMicrosoftExcel) { + return ShareFileDownloadMimeType::kMimeTypeMicrosoftExcel; + } + if (mime_type == content_type::kMimeTypeMicrosoftExcelOpenXML) { + return ShareFileDownloadMimeType::kMimeTypeMicrosoftExcelOpenXML; + } + return ShareFileDownloadMimeType::kMimeTypeNotHandled; } -void OpenInTabHelper::HandleExportableFile() { - OpenInMimeType mime_type = GetUmaResult(web_state_->GetContentsMimeType()); - if (mime_type == OpenInMimeType::kMimeTypeNotHandled) +void ShareFileDownloadTabHelper::HandleExportableFile() { + ShareFileDownloadMimeType mime_type = + GetUmaResult(web_state_->GetContentsMimeType()); + if (mime_type == ShareFileDownloadMimeType::kMimeTypeNotHandled) { return; + } - DCHECK_NE(mime_type, OpenInMimeType::kMimeTypeNotHandled); + CHECK_NE(mime_type, ShareFileDownloadMimeType::kMimeTypeNotHandled); base::UmaHistogramEnumeration("IOS.OpenIn.MimeType", mime_type); - base::RecordAction(base::UserMetricsAction("IOS.OpenIn.Presented")); - - web::NavigationItem* item = - web_state_->GetNavigationManager()->GetLastCommittedItem(); - const GURL& last_committed_url = item ? item->GetURL() : GURL::EmptyGURL(); - std::u16string file_name = GetFileNameSuggestion(); - [delegate_ enableOpenInForWebState:web_state_ - withDocumentURL:last_committed_url - suggestedFileName:base::SysUTF16ToNSString(file_name)]; } -void OpenInTabHelper::DidStartNavigation( - web::WebState* web_state, - web::NavigationContext* navigation_context) { - [delegate_ disableOpenInForWebState:web_state]; -} - -void OpenInTabHelper::DidFinishNavigation( +void ShareFileDownloadTabHelper::DidFinishNavigation( web::WebState* web_state, web::NavigationContext* navigation_context) { // Retrieve the response headers to be used in case the Page loaded @@ -128,36 +121,36 @@ navigation_context->GetResponseHeaders()); } -OpenInTabHelper::OpenInTabHelper(web::WebState* web_state) +ShareFileDownloadTabHelper::ShareFileDownloadTabHelper(web::WebState* web_state) : web_state_(web_state) { web_state_->AddObserver(this); } -void OpenInTabHelper::PageLoaded( +void ShareFileDownloadTabHelper::PageLoaded( web::WebState* web_state, web::PageLoadCompletionStatus load_completion_status) { - if (load_completion_status == web::PageLoadCompletionStatus::SUCCESS) + if (load_completion_status == web::PageLoadCompletionStatus::SUCCESS) { HandleExportableFile(); + } } -void OpenInTabHelper::WebStateDestroyed(web::WebState* web_state) { +void ShareFileDownloadTabHelper::WebStateDestroyed(web::WebState* web_state) { DCHECK_EQ(web_state_, web_state); - [delegate_ destroyOpenInForWebState:web_state]; - delegate_ = nil; // The call to RemoveUserData cause the destruction of the current instance, // so nothing should be done after that point (this is like "delete this;"). // Unregistration as an observer happens in the destructor. web_state_->RemoveUserData(UserDataKey()); } -std::u16string OpenInTabHelper::GetFileNameSuggestion() { +std::u16string ShareFileDownloadTabHelper::GetFileNameSuggestion() { // Try to generate a filename by first looking at `content_disposition`, then // at the last component of WebState's last committed URL and if both of these // fail use the default filename "document". std::string content_disposition; - if (response_headers_) + if (response_headers_) { response_headers_->GetNormalizedHeader("content-disposition", &content_disposition); + } std::string default_file_name = l10n_util::GetStringUTF8(IDS_IOS_OPEN_IN_FILE_DEFAULT_TITLE); web::NavigationItem* item = @@ -173,7 +166,7 @@ } // static -bool OpenInTabHelper::ShouldDownload(web::WebState* web_state) { +bool ShareFileDownloadTabHelper::ShouldDownload(web::WebState* web_state) { if (!web_state) { return false; } @@ -192,4 +185,4 @@ mime_type == content_type::kMimeTypeMicrosoftExcelOpenXML); } -WEB_STATE_USER_DATA_KEY_IMPL(OpenInTabHelper) +WEB_STATE_USER_DATA_KEY_IMPL(ShareFileDownloadTabHelper)
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index a5decd4..4b1ec05 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -83,7 +83,6 @@ "//ios/chrome/browser/metrics", "//ios/chrome/browser/ntp", "//ios/chrome/browser/ntp:features", - "//ios/chrome/browser/open_in", "//ios/chrome/browser/optimization_guide", "//ios/chrome/browser/overscroll_actions", "//ios/chrome/browser/passwords", @@ -101,6 +100,7 @@ "//ios/chrome/browser/shared/model/url:constants", "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/public/features", + "//ios/chrome/browser/sharing", "//ios/chrome/browser/snapshots", "//ios/chrome/browser/ssl", "//ios/chrome/browser/store_kit", @@ -164,7 +164,6 @@ "//ios/chrome/browser/shared/model/browser/test:test_support", "//ios/chrome/browser/shared/model/browser_state:test_support", "//ios/chrome/browser/shared/model/web_state_list", - "//ios/chrome/browser/ui/open_in", "//ios/chrome/browser/web", "//ios/chrome/browser/web_state_list:agents", "//ios/chrome/browser/web_state_list/web_usage_enabler",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index d10c3b23..a7eb6e74 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -61,7 +61,6 @@ #import "ios/chrome/browser/metrics/pageload_foreground_duration_tab_helper.h" #import "ios/chrome/browser/ntp/features.h" #import "ios/chrome/browser/ntp/new_tab_page_tab_helper.h" -#import "ios/chrome/browser/open_in/open_in_tab_helper.h" #import "ios/chrome/browser/optimization_guide/optimization_guide_tab_helper.h" #import "ios/chrome/browser/optimization_guide/optimization_guide_validation_tab_helper.h" #import "ios/chrome/browser/overscroll_actions/overscroll_actions_tab_helper.h" @@ -81,6 +80,7 @@ #import "ios/chrome/browser/sessions/ios_chrome_session_tab_helper.h" #import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/public/features/features.h" +#import "ios/chrome/browser/sharing/share_file_download_tab_helper.h" #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" #import "ios/chrome/browser/ssl/captive_portal_tab_helper.h" #import "ios/chrome/browser/supervised_user/supervised_user_url_filter_tab_helper.h" @@ -196,7 +196,7 @@ ImageFetchTabHelper::CreateForWebState(web_state); NewTabPageTabHelper::CreateForWebState(web_state); - OpenInTabHelper::CreateForWebState(web_state); + ShareFileDownloadTabHelper::CreateForWebState(web_state); OptimizationGuideTabHelper::CreateForWebState(web_state); OptimizationGuideValidationTabHelper::CreateForWebState(web_state); ChromeBrowserState* original_browser_state =
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index b6ad40bc..e913bc5f 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -75,7 +75,6 @@ "//ios/chrome/browser/ntp", "//ios/chrome/browser/ntp:features", "//ios/chrome/browser/ntp:util", - "//ios/chrome/browser/open_in", "//ios/chrome/browser/overlays", "//ios/chrome/browser/overlays/public/web_content_area", "//ios/chrome/browser/overscroll_actions", @@ -158,8 +157,6 @@ "//ios/chrome/browser/ui/omnibox", "//ios/chrome/browser/ui/omnibox:omnibox_internal", "//ios/chrome/browser/ui/omnibox/popup", - "//ios/chrome/browser/ui/open_in", - "//ios/chrome/browser/ui/open_in:features", "//ios/chrome/browser/ui/overlays", "//ios/chrome/browser/ui/overscroll_actions", "//ios/chrome/browser/ui/page_info:coordinator",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index f3d5ede..b6446c8 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -130,8 +130,6 @@ #import "ios/chrome/browser/ui/location_bar/location_bar_coordinator.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_component_factory.h" #import "ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h" -#import "ios/chrome/browser/ui/open_in/features.h" -#import "ios/chrome/browser/ui/open_in/open_in_coordinator.h" #import "ios/chrome/browser/ui/overlays/overlay_container_coordinator.h" #import "ios/chrome/browser/ui/page_info/page_info_coordinator.h" #import "ios/chrome/browser/ui/page_info/requirements/page_info_presentation.h" @@ -266,9 +264,6 @@ @property(nonatomic, strong) BrowserContainerCoordinator* browserContainerCoordinator; -// Coordinator between OpenIn TabHelper and OpenIn UI. -@property(nonatomic, strong) OpenInCoordinator* openInCoordinator; - // Mediator for incognito reauth. @property(nonatomic, strong) IncognitoReauthMediator* incognitoAuthMediator; @@ -583,8 +578,6 @@ dismissOmnibox:(BOOL)dismissOmnibox { [self.passKitCoordinator stop]; - [self.openInCoordinator dismissAll]; - [self.printController dismissAnimated:YES]; [self.readingListCoordinator stop]; @@ -1151,12 +1144,6 @@ _promosManagerCoordinator; [_credentialProviderPromoCoordinator start]; } - if (!IsOpenInActivitiesInShareButtonEnabled()) { - self.openInCoordinator = [[OpenInCoordinator alloc] - initWithBaseViewController:self.viewController - browser:self.browser]; - [self.openInCoordinator start]; - } } // Stops child coordinators. @@ -1278,11 +1265,6 @@ [_credentialProviderPromoCoordinator stop]; _credentialProviderPromoCoordinator = nil; - if (!IsOpenInActivitiesInShareButtonEnabled()) { - [self.openInCoordinator stop]; - self.openInCoordinator = nil; - } - [self.defaultBrowserPromoManager stop]; self.defaultBrowserPromoManager = nil; }
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/action_list_module.mm b/ios/chrome/browser/ui/content_suggestions/cells/action_list_module.mm index 1cf4c25c..aad9b36 100644 --- a/ios/chrome/browser/ui/content_suggestions/cells/action_list_module.mm +++ b/ios/chrome/browser/ui/content_suggestions/cells/action_list_module.mm
@@ -36,11 +36,12 @@ self = [super initWithType:type]; if (self) { UILabel* title = [[UILabel alloc] init]; - title.text = [self titleString]; + title.text = [MagicStackModuleContainer titleStringForModule:type]; title.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; title.textColor = [UIColor colorNamed:kTextPrimaryColor]; title.accessibilityTraits |= UIAccessibilityTraitHeader; - title.accessibilityIdentifier = [self titleString]; + title.accessibilityIdentifier = + [MagicStackModuleContainer titleStringForModule:type]; UIStackView* stackView = [[UIStackView alloc] init]; stackView.translatesAutoresizingMaskIntoConstraints = NO;
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 98a145e4..d5bf64c3 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
@@ -21,8 +21,8 @@ + (CGFloat)moduleWidthForHorizontalTraitCollection: (UITraitCollection*)traitCollection; -// Returns the title string for the module. -- (NSString*)titleString; +// Returns the title string for the module `type`. ++ (NSString*)titleStringForModule:(ContentSuggestionsModuleType)type; @end
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 3cc518a..357d6763 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
@@ -52,8 +52,8 @@ : kModuleWidthCompact; } -- (NSString*)titleString { - switch (self.type) { ++ (NSString*)titleStringForModule:(ContentSuggestionsModuleType)type { + switch (type) { case ContentSuggestionsModuleType::kShortcuts: return l10n_util::GetNSString( IDS_IOS_CONTENT_SUGGESTIONS_SHORTCUTS_MODULE_TITLE);
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 a257a1f..12905db 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
@@ -56,13 +56,17 @@ // Stack. const float kMagicStackMinimumPaginationScrollVelocity = 0.2f; +// The spacing between modules in the Magic Stack. +const float kMagicStackSpacing = 10.0f; + } // namespace @interface ContentSuggestionsViewController () < UIGestureRecognizerDelegate, ContentSuggestionsSelectionActions, URLDropDelegate, - UIScrollViewDelegate> + UIScrollViewDelegate, + UIScrollViewAccessibilityDelegate> @property(nonatomic, strong) URLDragDropHandler* dragDropHandler; @@ -133,9 +137,6 @@ // height/width configurations for each row. self.verticalStackView.distribution = UIStackViewDistributionFill; [self.view addSubview:self.verticalStackView]; - // Add bottom spacing to last module by applying it after - // `_verticalStackView`. If ShouldMinimizeSpacingForModuleRefresh() is YES, - // then no space is added after the last module. // Add bottom spacing to the last module by applying it after // `_verticalStackView`. If `IsContentSuggestionsUIModuleRefreshEnabled()` is @@ -489,6 +490,22 @@ velocity:velocity.x]; } +#pragma mark - UIScrollViewAccessibilityDelegate + +// This reads out the new page whenever the user scrolls in VoiceOver. +- (NSString*)accessibilityScrollStatusForScrollView:(UIScrollView*)scrollView { + CGFloat moduleWidth = [MagicStackModuleContainer + moduleWidthForHorizontalTraitCollection:self.traitCollection]; + NSUInteger moduleCount = [_magicStackModuleOrder count]; + + NSUInteger closestPage = roundf(scrollView.contentOffset.x / moduleWidth); + closestPage = fminf(closestPage, moduleCount); + + ContentSuggestionsModuleType type = (ContentSuggestionsModuleType) + [_magicStackModuleOrder[closestPage] intValue]; + return [MagicStackModuleContainer titleStringForModule:type]; +} + #pragma mark - Private - (void)addUIElement:(UIView*)view withCustomBottomSpacing:(CGFloat)spacing { @@ -602,7 +619,7 @@ _magicStack.translatesAutoresizingMaskIntoConstraints = NO; _magicStack.axis = UILayoutConstraintAxisHorizontal; _magicStack.distribution = UIStackViewDistributionEqualSpacing; - _magicStack.spacing = 10; + _magicStack.spacing = kMagicStackSpacing; _magicStack.alignment = UIStackViewAlignmentCenter; [_magicStackScrollView addSubview:_magicStack]; @@ -673,12 +690,14 @@ closestPage = fminf(closestPage, moduleCount); if (fabs(velocity) < kMagicStackMinimumPaginationScrollVelocity) { - return closestPage * moduleWidth; + return closestPage * moduleWidth + (closestPage * 10); } if (velocity < 0) { - return (closestPage - 1) * moduleWidth; + return (closestPage - 1) * moduleWidth + + ((closestPage - 1) * kMagicStackSpacing); } - return (closestPage + 1) * moduleWidth; + return (closestPage + 1) * moduleWidth + + ((closestPage + 1) * kMagicStackSpacing); } @end
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm index 4cc25020..79f85393 100644 --- a/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm +++ b/ios/chrome/browser/ui/omnibox/omnibox_egtest.mm
@@ -350,7 +350,8 @@ // Tests that the keyboard accessory's paste to search button is shown with a // text in the clipboard and is starting a search. -- (void)testOmniboxKeyboardAccessoryPasteTextToSearch { +// TODO(crbug.com/1445718): Re-enable when fixed. +- (void)DISABLED_testOmniboxKeyboardAccessoryPasteTextToSearch { if (@available(iOS 16, *)) { [[AppLaunchManager sharedManager] ensureAppLaunchedWithFeaturesEnabled:{kOmniboxKeyboardPasteButton} @@ -389,7 +390,8 @@ // Tests that the keyboard accessory's paste to search button is shown with an // image in the clipboard and is starting an image search. -- (void)testOmniboxKeyboardAccessoryPasteImageToSearch { +// TODO(crbug.com/1445718): Re-enable when fixed. +- (void)DISABLED_testOmniboxKeyboardAccessoryPasteImageToSearch { if (@available(iOS 16, *)) { [[AppLaunchManager sharedManager] ensureAppLaunchedWithFeaturesEnabled:{kOmniboxKeyboardPasteButton}
diff --git a/ios/chrome/browser/ui/open_in/BUILD.gn b/ios/chrome/browser/ui/open_in/BUILD.gn deleted file mode 100644 index 1a39120..0000000 --- a/ios/chrome/browser/ui/open_in/BUILD.gn +++ /dev/null
@@ -1,122 +0,0 @@ -# Copyright 2019 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -source_set("open_in_ui") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "open_in_activity_delegate.h", - "open_in_activity_view_controller.h", - "open_in_activity_view_controller.mm", - "open_in_controller.h", - "open_in_controller.mm", - "open_in_controller_testing.h", - "open_in_toolbar.h", - "open_in_toolbar.mm", - ] - deps = [ - ":features", - ":open_in_histograms", - "//base", - "//components/strings", - "//ios/chrome/app/strings", - "//ios/chrome/browser/open_in", - "//ios/chrome/browser/shared/coordinator/alert", - "//ios/chrome/browser/shared/coordinator/layout_guide", - "//ios/chrome/browser/shared/model/browser", - "//ios/chrome/browser/shared/ui/util", - "//ios/chrome/browser/ui/sharing/activity_services", - "//ios/chrome/common/ui/colors", - "//ios/chrome/common/ui/util", - "//ios/web/public", - "//ios/web/public/download", - "//ui/base", - "//url", - ] -} - -source_set("open_in") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "open_in_coordinator.h", - "open_in_coordinator.mm", - "open_in_mediator.h", - "open_in_mediator.mm", - ] - deps = [ - ":open_in_ui", - "//base", - "//ios/chrome/browser/open_in", - "//ios/chrome/browser/shared/coordinator/chrome_coordinator", - "//ios/chrome/browser/shared/model/browser", - "//ios/chrome/browser/shared/model/web_state_list", - "//ios/web/public", - "//net", - "//services/network/public/cpp", - "//ui/base", - "//ui/gfx", - "//url", - ] -} - -source_set("open_in_histograms") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "open_in_histograms.h", - "open_in_histograms.mm", - ] -} - -source_set("unit_tests") { - configs += [ "//build/config/compiler:enable_arc" ] - testonly = true - sources = [ - "open_in_mediator_unittest.mm", - "open_in_toolbar_unittest.mm", - ] - deps = [ - ":open_in", - ":open_in_histograms", - ":open_in_ui", - "//ios/chrome/browser/shared/coordinator/layout_guide", - "//ios/chrome/browser/shared/model/browser/test:test_support", - "//ios/chrome/browser/shared/model/browser_state:test_support", - "//ios/chrome/browser/shared/model/web_state_list", - "//ios/chrome/browser/shared/model/web_state_list/test:test_support", - "//ios/web/public/test", - "//ios/web/public/test/fakes", - "//net", - "//net:test_support", - "//services/network:test_support", - "//services/network/public/cpp", - "//testing/gtest", - "//third_party/ocmock", - ] -} - -source_set("eg2_tests") { - configs += [ - "//build/config/compiler:enable_arc", - "//build/config/ios:xctest_config", - ] - testonly = true - - sources = [ "open_in_controller_egtest.mm" ] - deps = [ - "//base/test:test_support", - "//ios/chrome/test/earl_grey:eg_test_support+eg2", - "//ios/testing/earl_grey:eg_test_support+eg2", - "//net:test_support", - ] - - frameworks = [ "UIKit.framework" ] -} - -source_set("features") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "features.h", - "features.mm", - ] - public_deps = [ "//base" ] -}
diff --git a/ios/chrome/browser/ui/open_in/DEPS b/ios/chrome/browser/ui/open_in/DEPS deleted file mode 100644 index 6cf13939..0000000 --- a/ios/chrome/browser/ui/open_in/DEPS +++ /dev/null
@@ -1,3 +0,0 @@ -include_rules = [ - "+ios/chrome/browser/ui/sharing", -]
diff --git a/ios/chrome/browser/ui/open_in/OWNERS b/ios/chrome/browser/ui/open_in/OWNERS deleted file mode 100644 index 10e4970..0000000 --- a/ios/chrome/browser/ui/open_in/OWNERS +++ /dev/null
@@ -1,3 +0,0 @@ -ewannpv@chromium.org -alionadangla@chromium.org -gambard@chromium.org
diff --git a/ios/chrome/browser/ui/open_in/features.h b/ios/chrome/browser/ui/open_in/features.h deleted file mode 100644 index fde7f30..0000000 --- a/ios/chrome/browser/ui/open_in/features.h +++ /dev/null
@@ -1,42 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_FEATURES_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_FEATURES_H_ - -#import "base/feature_list.h" - -// Feature flag that enables Open In download. -BASE_DECLARE_FEATURE(kEnableOpenInDownload); - -// Feature parameters for Open In download. If no parameter is set, the default -// download and toolbar will be used. -extern const char kOpenInDownloadParameterName[]; - -// Indicates which Open In download variant to use. -extern const char kOpenInDownloadInShareButtonParam[]; -extern const char kOpenInDownloadWithWKDownloadParam[]; -extern const char kOpenInDownloadWithV2Param[]; - -// Convenience method for determining when Open In with legacy download in share -// button is enabled. -bool IsOpenInDownloadInShareButton(); - -// Convenience method for determining when Open In download with WKDownload in -// share button is enabled. -bool IsOpenInDownloadWithWKDownload(); - -// Convenience method for determining when Open In download with V2 in share -// button is enabled. -bool IsOpenInDownloadWithV2(); - -// Convenience method for determining when new download experiment is -// enabled. -bool IsOpenInNewDownloadEnabled(); - -// Convenience method for determining if Open In activities are moved in the -// share button. -bool IsOpenInActivitiesInShareButtonEnabled(); - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_FEATURES_H_
diff --git a/ios/chrome/browser/ui/open_in/features.mm b/ios/chrome/browser/ui/open_in/features.mm deleted file mode 100644 index fdcbcb9..0000000 --- a/ios/chrome/browser/ui/open_in/features.mm +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/features.h" - -#import <Foundation/Foundation.h> - -#import "base/metrics/field_trial_params.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -BASE_FEATURE(kEnableOpenInDownload, - "EnableOpenInDownload", - base::FEATURE_ENABLED_BY_DEFAULT); - -const char kOpenInDownloadParameterName[] = "default"; - -const char kOpenInDownloadInShareButtonParam[] = "variant_with_openin_download"; -const char kOpenInDownloadWithWKDownloadParam[] = "variant_with_wkdownload"; -const char kOpenInDownloadWithV2Param[] = "variant_with_v2"; - -std::string GetFeatureParameter() { - return kOpenInDownloadWithWKDownloadParam; -} - -bool IsOpenInDownloadInShareButton() { - if (@available(iOS 14.5, *)) { - if (base::FeatureList::IsEnabled(kEnableOpenInDownload)) { - return GetFeatureParameter() == kOpenInDownloadInShareButtonParam; - } - } - return false; -} - -bool IsOpenInDownloadWithWKDownload() { - if (@available(iOS 14.5, *)) { - if (base::FeatureList::IsEnabled(kEnableOpenInDownload)) { - return GetFeatureParameter() == kOpenInDownloadWithWKDownloadParam; - } - } - return false; -} - -bool IsOpenInDownloadWithV2() { - if (@available(iOS 14.5, *)) { - if (base::FeatureList::IsEnabled(kEnableOpenInDownload)) { - return GetFeatureParameter() == kOpenInDownloadWithV2Param; - } - } - return false; -} - -bool IsOpenInNewDownloadEnabled() { - return IsOpenInDownloadWithV2() || IsOpenInDownloadWithWKDownload(); -} - -bool IsOpenInActivitiesInShareButtonEnabled() { - return IsOpenInDownloadWithV2() || IsOpenInDownloadWithWKDownload() || - IsOpenInDownloadInShareButton(); -}
diff --git a/ios/chrome/browser/ui/open_in/open_in_activity_delegate.h b/ios/chrome/browser/ui/open_in/open_in_activity_delegate.h deleted file mode 100644 index 25005cf..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_activity_delegate.h +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_ACTIVITY_DELEGATE_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_ACTIVITY_DELEGATE_H_ - -// Delegate for the OpenInActivityViewController class. -@protocol OpenInActivityDelegate - -// Method invoked when the OpenInActivityViewController is about to be removed. -- (void)openInActivityWillDisappearForFileAtURL:(NSURL*)fileURL; - -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_ACTIVITY_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_activity_view_controller.h b/ios/chrome/browser/ui/open_in/open_in_activity_view_controller.h deleted file mode 100644 index 4d27d58..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_activity_view_controller.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_ACTIVITY_VIEW_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_ACTIVITY_VIEW_CONTROLLER_H_ - -#import <UIKit/UIKit.h> - -@protocol OpenInActivityDelegate; - -// View controller that provides an interface to perform actions on a file. -@interface OpenInActivityViewController : UIActivityViewController - -// Initializes an UIActivityViewController with the given `fileURL`. -- (instancetype)initWithURL:(NSURL*)fileURL NS_DESIGNATED_INITIALIZER; -- (instancetype)initWithActivityItems:(NSArray*)activityItems - applicationActivities: - (NSArray<__kindof UIActivity*>*)applicationActivities - NS_UNAVAILABLE; - -// Delegate used to handle presentation actions. -@property(nonatomic, weak) id<OpenInActivityDelegate> delegate; - -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_ACTIVITY_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_activity_view_controller.mm b/ios/chrome/browser/ui/open_in/open_in_activity_view_controller.mm deleted file mode 100644 index f5ba301..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_activity_view_controller.mm +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2022 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_activity_view_controller.h" - -#import "base/metrics/user_metrics.h" -#import "base/metrics/user_metrics_action.h" -#import "ios/chrome/browser/ui/open_in/open_in_activity_delegate.h" -#import "ios/chrome/browser/ui/sharing/activity_services/activity_service_histograms.h" -#import "ios/chrome/browser/ui/sharing/activity_services/activity_type_util.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface OpenInActivityViewController () - -// NSURL of the presented file. -@property(nonatomic, strong) NSURL* fileURL; - -// BOOL that indicates if the view is still presented. -@property(nonatomic, assign) BOOL isPresented; - -@end - -@implementation OpenInActivityViewController - -- (instancetype)initWithURL:(NSURL*)fileURL { - NSArray* customActions = @[ fileURL ]; - NSArray* activities = nil; - if (self = [super initWithActivityItems:customActions - applicationActivities:activities]) { - self.fileURL = fileURL; - __weak __typeof__(self) weakSelf = self; - self.completionWithItemsHandler = ^(NSString* activityType, BOOL completed, - NSArray* returnedItems, - NSError* activityError) { - [weakSelf activityViewCompletionHandler]; - - if (activityType && completed) { - activity_type_util::ActivityType type = - activity_type_util::TypeFromString(activityType); - activity_type_util::RecordMetricForActivity(type); - RecordActivityForScenario(type, SharingScenario::TabShareButton); - } else { - // Share action was cancelled. - base::RecordAction(base::UserMetricsAction("MobileShareMenuCancel")); - RecordCancelledScenario(SharingScenario::TabShareButton); - } - }; - } - return self; -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - self.isPresented = NO; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - self.isPresented = YES; -} - -#pragma mark - Private Methods - -// Invokes `openInActivityWillDisappearForFileAtURL:` when the view is about to -// be removed. -- (void)activityViewCompletionHandler { - if (!self.isPresented) { - [self.delegate openInActivityWillDisappearForFileAtURL:self.fileURL]; - } -} - -@end
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller.h b/ios/chrome/browser/ui/open_in/open_in_controller.h deleted file mode 100644 index 164014e..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_controller.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright 2012 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_OPEN_IN_OPEN_IN_CONTROLLER_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_CONTROLLER_H_ - -#import <UIKit/UIKit.h> - - -#include "base/memory/ref_counted.h" -#import "ios/chrome/browser/ui/open_in/open_in_toolbar.h" -#include "url/gurl.h" - -namespace network { -class SharedURLLoaderFactory; -} - -namespace web { -class WebState; -} - -class Browser; - -// Class used to handle opening files in other applications. -@interface OpenInController : NSObject <UIGestureRecognizerDelegate> - -- (instancetype)initWithBaseViewController:(UIViewController*)baseViewController - URLLoaderFactory: - (scoped_refptr<network::SharedURLLoaderFactory>) - urlLoaderFactory - webState:(web::WebState*)webState - browser:(Browser*)browser - NS_DESIGNATED_INITIALIZER; -- (instancetype)init NS_UNAVAILABLE; - -// Base view on which the Open In toolbar will be presented. -@property(nonatomic, weak) UIView* baseView; - -// Removes the `openInToolbar_` from the `webController_`'s view and resets the -// variables specific to the loaded document. -- (void)disable; - -// Dismisses any modal presented by the controller -- (void)dismissModalView; - -// Disconnects the controller from its WebState. Should be called when the -// WebState is being torn down. -- (void)detachFromWebState; - -// Adds the `openInToolbar_` to the `webController_`'s view and sets the url and -// the filename for the currently loaded document. -- (void)enableWithDocumentURL:(const GURL&)documentURL - suggestedFilename:(NSString*)suggestedFilename; -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller.mm b/ios/chrome/browser/ui/open_in/open_in_controller.mm deleted file mode 100644 index 47828a32..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_controller.mm +++ /dev/null
@@ -1,748 +0,0 @@ -// Copyright 2012 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_controller.h" - -#import <QuickLook/QuickLook.h> - -#import "base/files/file_path.h" -#import "base/functional/bind.h" -#import "base/location.h" -#import "base/logging.h" -#import "base/mac/scoped_cftyperef.h" -#import "base/metrics/histogram_macros.h" -#import "base/metrics/user_metrics.h" -#import "base/metrics/user_metrics_action.h" -#import "base/sequence_checker.h" -#import "base/strings/sys_string_conversions.h" -#import "base/task/sequenced_task_runner.h" -#import "base/task/thread_pool.h" -#import "base/threading/scoped_blocking_call.h" -#import "components/strings/grit/components_strings.h" -#import "ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h" -#import "ios/chrome/browser/shared/coordinator/layout_guide/layout_guide_util.h" -#import "ios/chrome/browser/shared/ui/util/layout_guide_names.h" -#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" -#import "ios/chrome/browser/shared/ui/util/util_swift.h" -#import "ios/chrome/browser/ui/open_in/features.h" -#import "ios/chrome/browser/ui/open_in/open_in_activity_delegate.h" -#import "ios/chrome/browser/ui/open_in/open_in_activity_view_controller.h" -#import "ios/chrome/browser/ui/open_in/open_in_controller_testing.h" -#import "ios/chrome/browser/ui/open_in/open_in_histograms.h" -#import "ios/chrome/grit/ios_strings.h" -#import "ios/web/public/download/crw_web_view_download.h" -#import "ios/web/public/ui/crw_web_view_proxy.h" -#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h" -#import "ios/web/public/web_state.h" -#import "net/base/load_flags.h" -#import "services/network/public/cpp/resource_request.h" -#import "services/network/public/cpp/shared_url_loader_factory.h" -#import "services/network/public/cpp/simple_url_loader.h" -#import "ui/base/device_form_factor.h" -#import "ui/base/l10n/l10n_util_mac.h" -#import "ui/gfx/ios/NSString+CrStringDrawing.h" -#import "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { -// The path in the temp directory containing documents that are to be opened in -// other applications. -static NSString* const kDocumentsTemporaryPath = @"OpenIn"; - -// Duration of the show/hide animation for the `openInToolbar_`. -const NSTimeInterval kOpenInToolbarAnimationDuration = 0.2; - -// Duration to show or hide the `overlayedView_`. -const NSTimeInterval kOverlayViewAnimationDuration = 0.3; - -// Time interval after which the `openInToolbar_` is automatically hidden. -const NSTimeInterval kOpenInToolbarDisplayDuration = 2.0; - -// Alpha value for the background view of `overlayedView_`. -const CGFloat kOverlayedViewBackgroundAlpha = 0.6; - -// Width of the label displayed on the `overlayedView_` as a percentage of the -// `overlayedView_`'s width. -const CGFloat kOverlayedViewLabelWidthPercentage = 0.7; - -// Bottom margin for the label displayed on the `overlayedView_`. -const CGFloat kOverlayedViewLabelBottomMargin = 60; - -// Logs the result of the download process after the user taps "open in" button. -void LogOpenInDownloadResult(const OpenInDownloadResult result) { - UMA_HISTOGRAM_ENUMERATION(kOpenInDownloadHistogram, result); -} - -// Returns true if the file located at `url` can be previewed. -bool HasValidFileAtUrl(NSURL* url) { - if (!url) - return false; - - if (![[NSFileManager defaultManager] isReadableFileAtPath:url.path]) - return false; - - NSString* extension = [url.path pathExtension]; - if ([extension isEqualToString:@"pdf"]) { - base::ScopedCFTypeRef<CGPDFDocumentRef> document( - CGPDFDocumentCreateWithURL((__bridge CFURLRef)url)); - return document; - } - - return [QLPreviewController canPreviewItem:url]; -} - -// Returns the temporary path where documents are stored. -NSString* GetTemporaryDocumentDirectory() { - return [NSTemporaryDirectory() - stringByAppendingPathComponent:kDocumentsTemporaryPath]; -} - -// Removes the file at `file_url`. -void RemoveDocumentAtPath(NSURL* file_url) { - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::WILL_BLOCK); - - if (!file_url.path) - return; - - NSError* error = nil; - if (![[NSFileManager defaultManager] removeItemAtPath:file_url.path - error:&error]) { - DLOG(ERROR) << "Failed to remove file: " - << base::SysNSStringToUTF8([error description]); - } -} - -// Removes all the stored files at `path`. -void RemoveAllStoredDocumentsAtPath(NSString* path) { - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::WILL_BLOCK); - - NSFileManager* file_manager = [NSFileManager defaultManager]; - - NSError* error = nil; - NSArray<NSString*>* document_files = - [file_manager contentsOfDirectoryAtPath:path error:&error]; - if (!document_files) { - DLOG(ERROR) << "Failed to get content of directory at path: " - << base::SysNSStringToUTF8([error description]); - return; - } - - for (NSString* filename in document_files) { - NSString* file_path = [path stringByAppendingPathComponent:filename]; - if (![file_manager removeItemAtPath:file_path error:&error]) { - DLOG(ERROR) << "Failed to remove file: " - << base::SysNSStringToUTF8([error description]); - } - } -} - -// Ensures the destination directory is created and any contained obsolete files -// are deleted. Returns YES if the directory is created successfully. -BOOL CreateDestinationDirectoryAndRemoveObsoleteFiles() { - base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, - base::BlockingType::WILL_BLOCK); - - NSString* temporary_directory_path = GetTemporaryDocumentDirectory(); - NSFileManager* file_manager = [NSFileManager defaultManager]; - - NSError* error = nil; - BOOL is_directory = NO; - if (![file_manager fileExistsAtPath:temporary_directory_path - isDirectory:&is_directory]) { - BOOL created = [file_manager createDirectoryAtPath:temporary_directory_path - withIntermediateDirectories:YES - attributes:nil - error:&error]; - DCHECK(created); - if (!created) { - DLOG(ERROR) << "Error creating destination dir: " - << base::SysNSStringToUTF8([error description]); - return NO; - } - } else { - if (!is_directory) { - DLOG(ERROR) << "Destination Directory already exists and is a file."; - return NO; - } - // Remove all documents that might be still on temporary storage. - RemoveAllStoredDocumentsAtPath(temporary_directory_path); - } - return YES; -} - -} // anonymous namespace - -@interface OpenInController () <CRWWebViewScrollViewProxyObserver, - CRWWebViewDownloadDelegate, - OpenInActivityDelegate> { - // AlertCoordinator for showing an alert if no applications were found to open - // the current document. - AlertCoordinator* _alertCoordinator; -} - -// Property storing the Y content offset the scroll view the last time it was -// updated. Used to know in which direction the scroll view is scrolling. -@property(nonatomic, assign) CGFloat previousScrollViewOffset; - -// The base view controller from which to present UI. -@property(nonatomic, weak) UIViewController* baseViewController; - -// Task runner on which file operations should happen. -@property(nonatomic, assign) scoped_refptr<base::SequencedTaskRunner> - sequencedTaskRunner; - -// Path where the downloaded file is saved. -@property(nonatomic, strong) NSString* filePath; - -// CRWWebViewDownload instance that handle download interactions. -@property(nonatomic, strong) id<CRWWebViewDownload> download; - -// SimpleURLLoader completion callback, when `urlLoader_` completes a request. -- (void)urlLoadDidComplete:(const base::FilePath&)file_path; -// Starts downloading the file at path `kDocumentsTemporaryPath` with the name -// `suggestedFilename_`. -- (void)startDownload; -// Shows the overlayed toolbar `openInToolbar_`. If `withTimer` is YES, it would -// be hidden after a certain amount of time. -- (void)showOpenInToolbarWithTimer:(BOOL)withTimer; -// Hides the overlayed toolbar `openInToolbar_`. -- (void)hideOpenInToolbar; -// Called when there is a tap on the `webState_`'s view to display the -// overlayed toolbar `openInToolbar_` if necessary and (re)schedule the -// `openInTimer_`. -- (void)handleTapFrom:(UIGestureRecognizer*)gestureRecognizer; -// Downloads the file at `documentURL_` and presents the OpenIn menu for opening -// it in other applications. -- (void)exportFileWithOpenInMenuAnchoredAt:(id)sender; -// Called when there is a tap on the `overlayedView_` to cancel the file -// download. -- (void)handleTapOnOverlayedView:(UIGestureRecognizer*)gestureRecognizer; -// Removes `overlayedView_` from the top view of the application. -- (void)removeOverlayedView; -// Shows an alert with the given error message. -- (void)showErrorWithMessage:(NSString*)message; -// Presents the OpenIn menu for the file at `fileURL`. -- (void)presentOpenInMenuForFileAtURL:(NSURL*)fileURL; -// Shows an overlayed spinner on the top view to indicate that a file download -// is in progress. -- (void)showDownloadOverlayView; -// Returns a toolbar with an "Open in..." button to be overlayed on a document -// on tap. -- (OpenInToolbar*)openInToolbar; -@end - -@implementation OpenInController { - // To check that callbacks are executed on the correct sequence. - SEQUENCE_CHECKER(_sequenceChecker); - - // URL of the document. - GURL _documentURL; - - // Controller for opening documents in other applications. - OpenInActivityViewController* _activityViewController; - - // Toolbar overlay to be displayed on tap. - OpenInToolbar* _openInToolbar; - - // Timer used to automatically hide the `openInToolbar_` after a period. - NSTimer* _openInTimer; - - // Gesture recognizer to catch taps on the document. - UITapGestureRecognizer* _tapRecognizer; - - // Layout guide to position the toolbar. - UILayoutGuide* _layoutGuide; - - // Suggested filename for the document. - NSString* _suggestedFilename; - - // Loader used to redownload the document and save it in the sandbox. - std::unique_ptr<network::SimpleURLLoader> _urlLoader; - - // WebState used to check if the tap is not on a link and the - // `openInToolbar_` should be displayed. - web::WebState* _webState; - - // Browser used to display errors. - Browser* _browser; - - // URLLoaderFactory instance needed for URLLoader. - scoped_refptr<network::SharedURLLoaderFactory> _urlLoaderFactory; - - // Spinner view displayed while the file is downloading. - UIView* _overlayedView; - - // The location where the "Open in..." menu is anchored. - CGRect _anchorLocation; - - // YES if the file download was canceled. - BOOL _downloadCanceled; - - // YES if the toolbar is displayed. - BOOL _isOpenInToolbarDisplayed; - - // YES if the workflow has been canceled. - BOOL _disabled; -} - -@synthesize baseView = _baseView; -@synthesize previousScrollViewOffset = _previousScrollViewOffset; - -- (instancetype)initWithBaseViewController:(UIViewController*)baseViewController - URLLoaderFactory: - (scoped_refptr<network::SharedURLLoaderFactory>) - urlLoaderFactory - webState:(web::WebState*)webState - browser:(Browser*)browser { - self = [super init]; - if (self) { - _baseViewController = baseViewController; - _urlLoaderFactory = std::move(urlLoaderFactory); - _webState = webState; - _tapRecognizer = [[UITapGestureRecognizer alloc] - initWithTarget:self - action:@selector(handleTapFrom:)]; - [_tapRecognizer setDelegate:self]; - LayoutGuideCenter* layoutGuideCenter = LayoutGuideCenterForBrowser(browser); - _layoutGuide = - [layoutGuideCenter makeLayoutGuideNamed:kSecondaryToolbarGuide]; - - _sequencedTaskRunner = base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); - _previousScrollViewOffset = 0; - _browser = browser; - } - return self; -} - -- (void)enableWithDocumentURL:(const GURL&)documentURL - suggestedFilename:(NSString*)suggestedFilename { - _disabled = NO; - _documentURL = GURL(documentURL); - _suggestedFilename = suggestedFilename; - - if (self.baseView) { - [self.baseView addGestureRecognizer:_tapRecognizer]; - self.openInToolbar.alpha = 0.0f; - self.openInToolbar.translatesAutoresizingMaskIntoConstraints = NO; - [self.baseView addSubview:self.openInToolbar]; - [self.baseView addLayoutGuide:_layoutGuide]; - [NSLayoutConstraint activateConstraints:@[ - [self.openInToolbar.leadingAnchor - constraintEqualToAnchor:self.baseView.leadingAnchor], - [self.openInToolbar.trailingAnchor - constraintEqualToAnchor:self.baseView.trailingAnchor], - [self.openInToolbar.bottomAnchor - constraintEqualToAnchor:_layoutGuide.topAnchor], - ]]; - } - - if (_webState) - [[_webState->GetWebViewProxy() scrollViewProxy] addObserver:self]; - - [self showOpenInToolbarWithTimer:NO]; -} - -- (void)disable { - _disabled = YES; - [self removeOverlayedView]; - self.openInToolbar.alpha = 0.0f; - [_openInTimer invalidate]; - [self.baseView removeGestureRecognizer:_tapRecognizer]; - [self.baseView removeLayoutGuide:_layoutGuide]; - if (_webState) - [[_webState->GetWebViewProxy() scrollViewProxy] removeObserver:self]; - self.previousScrollViewOffset = 0; - [self.openInToolbar removeFromSuperview]; - _documentURL = GURL(); - _suggestedFilename = nil; - _urlLoader.reset(); -} - -- (void)dismissModalView { - [_activityViewController dismissViewControllerAnimated:NO completion:nil]; -} - -- (void)detachFromWebState { - [self disable]; - // Animation blocks may be keeping this object alive; don't keep a - // potentially dangling pointer to WebState and Browser. - _webState = nullptr; - _browser = nullptr; -} - -- (void)dealloc { - [self disable]; -} - -- (void)handleTapFrom:(UIGestureRecognizer*)gestureRecognizer { - if ([gestureRecognizer state] == UIGestureRecognizerStateEnded) { - if (_isOpenInToolbarDisplayed) { - [self hideOpenInToolbar]; - } else { - [self showOpenInToolbarWithTimer:YES]; - } - } -} - -- (void)showOpenInToolbarWithTimer:(BOOL)withTimer { - if (withTimer) { - if ([_openInTimer isValid]) { - [_openInTimer setFireDate:([NSDate dateWithTimeIntervalSinceNow: - kOpenInToolbarDisplayDuration])]; - } else { - _openInTimer = - [NSTimer scheduledTimerWithTimeInterval:kOpenInToolbarDisplayDuration - target:self - selector:@selector(hideOpenInToolbar) - userInfo:nil - repeats:NO]; - } - } else { - [_openInTimer invalidate]; - } - - OpenInToolbar* openInToolbar = self.openInToolbar; - if (!_isOpenInToolbarDisplayed) { - [UIView animateWithDuration:kOpenInToolbarAnimationDuration - animations:^{ - [openInToolbar setAlpha:1.0]; - }]; - } - _isOpenInToolbarDisplayed = YES; -} - -- (void)hideOpenInToolbar { - if (!_openInToolbar) - return; - [_openInTimer invalidate]; - UIView* openInToolbar = self.openInToolbar; - [UIView animateWithDuration:kOpenInToolbarAnimationDuration - animations:^{ - [openInToolbar setAlpha:0.0]; - }]; - _isOpenInToolbarDisplayed = NO; -} - -- (void)exportFileWithOpenInMenuAnchoredAt:(UIView*)view { - DCHECK_CALLED_ON_VALID_SEQUENCE(_sequenceChecker); - DCHECK([view isKindOfClass:[UIView class]]); - - base::RecordAction(base::UserMetricsAction("IOS.OpenIn.Tapped")); - - if (!_webState) - return; - - _anchorLocation = [self.openInToolbar convertRect:view.frame - toView:self.baseView]; - [_openInTimer invalidate]; - - // Creating the directory can block the main thread, so perform it on a - // background sequence, then on current sequence complete the workflow. - __weak OpenInController* weakSelf = self; - _sequencedTaskRunner->PostTaskAndReplyWithResult( - FROM_HERE, - base::BindOnce(&CreateDestinationDirectoryAndRemoveObsoleteFiles), - base::BindOnce(^(BOOL directoryCreated) { - [weakSelf onDestinationDirectoryCreated:directoryCreated]; - })); -} - -- (void)onDestinationDirectoryCreated:(BOOL)directoryCreated { - DCHECK_CALLED_ON_VALID_SEQUENCE(_sequenceChecker); - if (_disabled) - return; - - if (!directoryCreated) { - [self hideOpenInToolbar]; - } else { - [self startDownload]; - } -} - -- (void)startDownload { - NSString* tempDirPath = GetTemporaryDocumentDirectory(); - self.filePath = - [tempDirPath stringByAppendingPathComponent:_suggestedFilename]; - - // In iPad the toolbar has to be displayed to anchor the "Open in" menu. - if (ui::GetDeviceFormFactor() != ui::DEVICE_FORM_FACTOR_TABLET) - [self hideOpenInToolbar]; - - // Show an overlayed view to indicate a download is in progress. On tap this - // view can be dismissed and the download canceled. - [self showDownloadOverlayView]; - _downloadCanceled = NO; - - if (@available(iOS 14.5, *)) { - if (IsOpenInNewDownloadEnabled()) { - __weak OpenInController* weakSelf = self; - _webState->DownloadCurrentPage(self.filePath, self, - ^(id<CRWWebViewDownload> download) { - weakSelf.download = download; - }); - return; - } - } - - // Download the document and save it at `self.filePath`. - // TODO(crbug.com/1357553): Remove when Open In download experiment is - // finished. - auto resourceRequest = std::make_unique<network::ResourceRequest>(); - resourceRequest->url = _documentURL; - resourceRequest->load_flags = net::LOAD_SKIP_CACHE_VALIDATION; - - _urlLoader = network::SimpleURLLoader::Create(std::move(resourceRequest), - NO_TRAFFIC_ANNOTATION_YET); - _urlLoader->DownloadToFile( - _urlLoaderFactory.get(), base::BindOnce(^(base::FilePath filePath) { - [self urlLoadDidComplete:filePath]; - }), - base::FilePath(base::SysNSStringToUTF8(self.filePath))); -} - -- (void)handleTapOnOverlayedView:(UIGestureRecognizer*)gestureRecognizer { - if ([gestureRecognizer state] != UIGestureRecognizerStateEnded) - return; - - if (@available(iOS 14.5, *)) { - if (IsOpenInDownloadWithWKDownload()) { - __weak __typeof(self) weakSelf = self; - [self.download cancelDownload:^() { - [weakSelf removeOverlayedView]; - if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) { - [weakSelf hideOpenInToolbar]; - } - }]; - _downloadCanceled = YES; - } - } -} - -- (void)removeOverlayedView { - if (!_overlayedView) - return; - - UIView* overlayedView = _overlayedView; - [UIView animateWithDuration:kOverlayViewAnimationDuration - animations:^{ - [overlayedView setAlpha:0.0]; - } - completion:^(BOOL finished) { - [overlayedView removeFromSuperview]; - }]; - _overlayedView = nil; -} - -- (void)showErrorWithMessage:(NSString*)message { - UIViewController* topViewController = [GetAnyKeyWindow() rootViewController]; - - _alertCoordinator = - [[AlertCoordinator alloc] initWithBaseViewController:topViewController - browser:_browser - title:nil - message:message]; - - [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_OK) - action:nil - style:UIAlertActionStyleDefault]; - - [_alertCoordinator start]; -} - -- (void)presentOpenInMenuForFileAtURL:(NSURL*)fileURL { - if (!_webState) - return; - - _activityViewController = - [[OpenInActivityViewController alloc] initWithURL:fileURL]; - _activityViewController.delegate = self; - - // UIActivityViewController is presented in a popover on iPad. - _activityViewController.popoverPresentationController.sourceView = - self.baseView; - _activityViewController.popoverPresentationController.sourceRect = - _anchorLocation; - - [self removeOverlayedView]; - [self.baseViewController presentViewController:_activityViewController - animated:YES - completion:nil]; -} - -- (void)completedPresentOpenInMenuForFileAtURL:(NSURL*)fileURL { - _sequencedTaskRunner->PostTask(FROM_HERE, base::BindOnce(^{ - RemoveDocumentAtPath(fileURL); - })); - - if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) { - _openInTimer = - [NSTimer scheduledTimerWithTimeInterval:kOpenInToolbarDisplayDuration - target:self - selector:@selector(hideOpenInToolbar) - userInfo:nil - repeats:NO]; - } -} - -- (void)showDownloadOverlayView { - _overlayedView = [[UIView alloc] initWithFrame:[self.baseView bounds]]; - [_overlayedView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight)]; - UIView* grayBackgroundView = - [[UIView alloc] initWithFrame:[_overlayedView frame]]; - [grayBackgroundView setBackgroundColor:[UIColor darkGrayColor]]; - [grayBackgroundView setAlpha:kOverlayedViewBackgroundAlpha]; - [grayBackgroundView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight)]; - [_overlayedView addSubview:grayBackgroundView]; - - UIActivityIndicatorView* spinner = GetLargeUIActivityIndicatorView(); - [spinner setFrame:[_overlayedView frame]]; - [spinner setHidesWhenStopped:YES]; - [spinner setUserInteractionEnabled:NO]; - [spinner startAnimating]; - [spinner setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | - UIViewAutoresizingFlexibleHeight)]; - [_overlayedView addSubview:spinner]; - - UILabel* label = [[UILabel alloc] init]; - [label setTextColor:[UIColor whiteColor]]; - [label setFont:[UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]]; - [label setNumberOfLines:0]; - [label setShadowColor:[UIColor blackColor]]; - [label setShadowOffset:CGSizeMake(0.0, 1.0)]; - [label setBackgroundColor:[UIColor clearColor]]; - [label setText:l10n_util::GetNSString(IDS_IOS_OPEN_IN_FILE_DOWNLOAD_CANCEL)]; - [label setLineBreakMode:NSLineBreakByWordWrapping]; - [label setTextAlignment:NSTextAlignmentCenter]; - CGFloat labelWidth = - [_overlayedView frame].size.width * kOverlayedViewLabelWidthPercentage; - CGFloat originX = ([_overlayedView frame].size.width - labelWidth) / 2; - - CGFloat labelHeight = - [[label text] cr_boundingSizeWithSize:CGSizeMake(labelWidth, CGFLOAT_MAX) - font:[label font]] - .height; - CGFloat originY = - [_overlayedView center].y - labelHeight - kOverlayedViewLabelBottomMargin; - [label setFrame:CGRectMake(originX, originY, labelWidth, labelHeight)]; - [_overlayedView addSubview:label]; - - UITapGestureRecognizer* tapRecognizer = [[UITapGestureRecognizer alloc] - initWithTarget:self - action:@selector(handleTapOnOverlayedView:)]; - [tapRecognizer setDelegate:self]; - [_overlayedView addGestureRecognizer:tapRecognizer]; - [_overlayedView setAlpha:0.0]; - [self.baseView addSubview:_overlayedView]; - UIView* overlayedView = _overlayedView; - [UIView animateWithDuration:kOverlayViewAnimationDuration - animations:^{ - [overlayedView setAlpha:1.0]; - }]; -} - -- (OpenInToolbar*)openInToolbar { - if (!_openInToolbar) { - _openInToolbar = [[OpenInToolbar alloc] - initWithTarget:self - action:@selector(exportFileWithOpenInMenuAnchoredAt:)]; - } - return _openInToolbar; -} - -#pragma mark - OpenInActivityDelegate - -- (void)openInActivityWillDisappearForFileAtURL:(NSURL*)fileURL { - [self completedPresentOpenInMenuForFileAtURL:fileURL]; -} - -#pragma mark File management - -- (void)urlLoadDidComplete:(const base::FilePath&)filePath { - NSURL* fileURL = nil; - if (!filePath.empty()) - fileURL = [NSURL fileURLWithPath:base::SysUTF8ToNSString(filePath.value())]; - if (!_downloadCanceled && HasValidFileAtUrl(fileURL)) { - LogOpenInDownloadResult(OpenInDownloadResult::kSucceeded); - [self presentOpenInMenuForFileAtURL:fileURL]; - return; - } - _sequencedTaskRunner->PostTask(FROM_HERE, base::BindOnce(^{ - RemoveDocumentAtPath(fileURL); - })); - OpenInDownloadResult download_result = OpenInDownloadResult::kCanceled; - if (!_downloadCanceled) { - download_result = OpenInDownloadResult::kFailed; - if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) - [self hideOpenInToolbar]; - [self removeOverlayedView]; - [self showErrorWithMessage:l10n_util::GetNSStringWithFixup( - IDS_IOS_OPEN_IN_FILE_DOWNLOAD_FAILED)]; - } - LogOpenInDownloadResult(download_result); -} - -#pragma mark - UIGestureRecognizerDelegate Methods - -- (BOOL)gestureRecognizer:(UIGestureRecognizer*)gestureRecognizer - shouldRecognizeSimultaneouslyWithGestureRecognizer: - (UIGestureRecognizer*)otherGestureRecognizer { - return YES; -} - -- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer { - if ([gestureRecognizer.view isEqual:_overlayedView]) - return YES; - - CGPoint location = [gestureRecognizer locationInView:self.openInToolbar]; - return ![self.openInToolbar pointInside:location withEvent:nil]; -} - -#pragma mark - CRWWebViewScrollViewProxyObserver - -- (void)webViewScrollViewDidScroll: - (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { - // Store the values. - CGFloat previousScrollOffset = self.previousScrollViewOffset; - CGFloat currentScrollOffset = webViewScrollViewProxy.contentOffset.y; - self.previousScrollViewOffset = currentScrollOffset; - - if (previousScrollOffset - currentScrollOffset > 0) { - if (!_isOpenInToolbarDisplayed || - (_isOpenInToolbarDisplayed && [_openInTimer isValid])) { - // Shows the OpenInToolbar only if it isn't displayed, or if it is - // displayed with a timer to have the timer reset. - [self showOpenInToolbarWithTimer:YES]; - } - } else if (webViewScrollViewProxy.dragging) { - [self hideOpenInToolbar]; - } -} - -#pragma mark - TestingAditions - -- (NSString*)suggestedFilename { - return _suggestedFilename; -} - -#pragma mark - CRWWebViewDownloadDelegate - -- (void)downloadDidFinish { - [self urlLoadDidComplete:base::FilePath( - base::SysNSStringToUTF8(self.filePath))]; -} - -- (void)downloadDidFailWithError:(NSError*)error { - [self urlLoadDidComplete:base::FilePath( - base::SysNSStringToUTF8(self.filePath))]; -} - -@end
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller_testing.h b/ios/chrome/browser/ui/open_in/open_in_controller_testing.h deleted file mode 100644 index 70e0d52f..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_controller_testing.h +++ /dev/null
@@ -1,13 +0,0 @@ -// Copyright 2012 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_OPEN_IN_OPEN_IN_CONTROLLER_TESTING_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_CONTROLLER_TESTING_H_ - -@interface OpenInController (TestingAditions) -- (NSString*)suggestedFilename; -- (void)startDownload; -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_CONTROLLER_TESTING_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_coordinator.h b/ios/chrome/browser/ui/open_in/open_in_coordinator.h deleted file mode 100644 index b03d6f93..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_coordinator.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_COORDINATOR_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_COORDINATOR_H_ - -#import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h" - -// Coordinator for OpenIn. -@interface OpenInCoordinator : ChromeCoordinator - -// Disables all registered openInControllers. -- (void)disableAll; - -// Dismisses all the activity controller window -- (void)dismissAll; - -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_coordinator.mm b/ios/chrome/browser/ui/open_in/open_in_coordinator.mm deleted file mode 100644 index dbab591..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_coordinator.mm +++ /dev/null
@@ -1,43 +0,0 @@ -// Copyright 2021 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_coordinator.h" - -#import "ios/chrome/browser/ui/open_in/open_in_mediator.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface OpenInCoordinator () - -// The mediator used to configure and display the OpenInController. -@property(nonatomic, strong) OpenInMediator* openInMediator; - -@end - -@implementation OpenInCoordinator - -- (void)start { - self.openInMediator = - [[OpenInMediator alloc] initWithBaseViewController:self.baseViewController - browser:self.browser]; -} - -- (void)stop { - [self.openInMediator disableAll]; - self.openInMediator = nil; -} - -#pragma mark - Public - -- (void)disableAll { - [self.openInMediator disableAll]; -} - -- (void)dismissAll { - [self.openInMediator dismissAll]; -} - -@end
diff --git a/ios/chrome/browser/ui/open_in/open_in_mediator.h b/ios/chrome/browser/ui/open_in/open_in_mediator.h deleted file mode 100644 index 03a9932..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_mediator.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_MEDIATOR_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_MEDIATOR_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/open_in/open_in_tab_helper_delegate.h" - -class Browser; - -// Mediator which mediates between openIn views and openIn tab helpers. -@interface OpenInMediator : NSObject <OpenInTabHelperDelegate> - -// Creates a mediator that uses a `viewController` and a `browser`. -- (instancetype)initWithBaseViewController:(UIViewController*)baseViewController - browser:(Browser*)browser - NS_DESIGNATED_INITIALIZER; - -- (instancetype)init NS_UNAVAILABLE; - -// Disables all registered openInControllers. -- (void)disableAll; - -// Dismisses all the activity controller window. -- (void)dismissAll; - -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_mediator.mm b/ios/chrome/browser/ui/open_in/open_in_mediator.mm deleted file mode 100644 index d0b752b..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_mediator.mm +++ /dev/null
@@ -1,128 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_mediator.h" - -#import "ios/chrome/browser/open_in/open_in_tab_helper.h" -#import "ios/chrome/browser/shared/model/browser/browser.h" -#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" -#import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer_bridge.h" -#import "ios/chrome/browser/ui/open_in/open_in_controller.h" -#import "ios/web/public/browser_state.h" -#import "ios/web/public/web_state.h" -#import "services/network/public/cpp/shared_url_loader_factory.h" -#import "url/gurl.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface OpenInMediator () <WebStateListObserving> { - std::unique_ptr<WebStateListObserverBridge> _webStateListObserver; - // A map associating webStates with their OpenInControllers. - std::map<web::WebState*, OpenInController*> _openInControllersForWebStates; -} - -// The Browser that accesses the WebStateList. -@property(nonatomic, assign) Browser* browser; - -// The WebStateList that this mediator listens for newly added Webstates. -@property(nonatomic, assign) WebStateList* webStateList; - -// The base view controller from which to present UI. -@property(nonatomic, weak) UIViewController* baseViewController; - -@end - -@implementation OpenInMediator - -- (instancetype)initWithBaseViewController:(UIViewController*)baseViewController - browser:(Browser*)browser { - self = [super init]; - if (self) { - _baseViewController = baseViewController; - _browser = browser; - _webStateList = browser->GetWebStateList(); - // Set the delegates for all existing webstates in the `_webStateList`. - for (int i = 0; i < _webStateList->count(); i++) { - web::WebState* webState = _webStateList->GetWebStateAt(i); - OpenInTabHelper::FromWebState(webState)->SetDelegate(self); - } - _webStateListObserver = std::make_unique<WebStateListObserverBridge>(self); - _webStateList->AddObserver(_webStateListObserver.get()); - } - return self; -} - -- (void)dealloc { - [self disconnect]; -} - -- (void)disableAll { - for (const auto& element : _openInControllersForWebStates) - [element.second detachFromWebState]; - _openInControllersForWebStates.clear(); -} - -- (void)dismissAll { - for (const auto& element : _openInControllersForWebStates) - [element.second dismissModalView]; -} - -- (void)disconnect { - if (_webStateList) { - _webStateList->RemoveObserver(_webStateListObserver.get()); - _webStateListObserver.reset(); - _webStateList = nullptr; - } - [self disableAll]; -} - -#pragma mark - WebStateListObserver - -- (void)webStateList:(WebStateList*)webStateList - didInsertWebState:(web::WebState*)webState - atIndex:(int)index - activating:(BOOL)activating { - DCHECK_EQ(_webStateList, webStateList); - OpenInTabHelper::FromWebState(webState)->SetDelegate(self); -} - -#pragma mark - OpenInTabHelperDelegate - -// Creates OpenInController and set its base view to the `webState` view. Then -// enables the OpenIn view for the `webState`. -- (void)enableOpenInForWebState:(web::WebState*)webState - withDocumentURL:(const GURL&)documentURL - suggestedFileName:(NSString*)suggestedFileName { - if (!_openInControllersForWebStates[webState]) { - OpenInController* openInController = [[OpenInController alloc] - initWithBaseViewController:_baseViewController - URLLoaderFactory:webState->GetBrowserState() - ->GetSharedURLLoaderFactory() - webState:webState - browser:_browser]; - _openInControllersForWebStates[webState] = openInController; - } - OpenInController* controller = _openInControllersForWebStates[webState]; - controller.baseView = webState->GetView(); - [controller enableWithDocumentURL:documentURL - suggestedFilename:suggestedFileName]; -} - -// Disables the openIn view for the `webState`. -- (void)disableOpenInForWebState:(web::WebState*)webState { - if (_openInControllersForWebStates[webState]) - [_openInControllersForWebStates[webState] disable]; -} - -// Detaches the webState from its' OpenInController. -- (void)destroyOpenInForWebState:(web::WebState*)webState { - if (!_openInControllersForWebStates[webState]) - return; - [_openInControllersForWebStates[webState] detachFromWebState]; - _openInControllersForWebStates.erase(webState); -} - -@end
diff --git a/ios/chrome/browser/ui/open_in/open_in_mediator_unittest.mm b/ios/chrome/browser/ui/open_in/open_in_mediator_unittest.mm deleted file mode 100644 index 5df5e0ab..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_mediator_unittest.mm +++ /dev/null
@@ -1,120 +0,0 @@ -// Copyright 2019 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_mediator.h" - -#import "base/mac/foundation_util.h" -#import "ios/chrome/browser/shared/model/browser/test/test_browser.h" -#import "ios/chrome/browser/shared/model/browser_state/test_chrome_browser_state.h" -#import "ios/chrome/browser/ui/open_in/open_in_toolbar.h" -#import "ios/web/public/test/fakes/fake_web_state.h" -#import "ios/web/public/test/web_task_environment.h" -#import "ios/web/public/ui/crw_web_view_proxy.h" -#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h" -#import "testing/gtest_mac.h" -#import "testing/platform_test.h" -#import "third_party/ocmock/OCMock/OCMock.h" -#import "third_party/ocmock/gtest_support.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// Test fixture for testing OpenInMediator class. -class OpenInMediatorTest : public PlatformTest { - protected: - OpenInMediatorTest() - : browser_state_(TestChromeBrowserState::Builder().Build()), - browser_(std::make_unique<TestBrowser>(browser_state_.get())), - mediator_([[OpenInMediator alloc] - initWithBaseViewController:nil - browser:browser_.get()]) {} - - std::unique_ptr<web::FakeWebState> CreateWebStateWithView() { - auto web_state = std::make_unique<web::FakeWebState>(); - CGRect web_view_frame = CGRectMake(0, 0, 100, 100); - UIView* web_state_view = [[UIView alloc] initWithFrame:web_view_frame]; - web_view_proxy_mock = OCMProtocolMock(@protocol(CRWWebViewProxy)); - [[[web_view_proxy_mock stub] andReturn:scroll_view_proxy_] scrollViewProxy]; - web_state->SetWebViewProxy(web_view_proxy_mock); - - web_state->SetView(web_state_view); - web_state->SetBrowserState(browser_state_.get()); - return web_state; - } - - // Returns the potential OpenInToolbar subview of the given view. - OpenInToolbar* ToolbarInView(UIView* view) { - for (UIView* subview in view.subviews) { - if ([subview isKindOfClass:[OpenInToolbar class]]) { - return base::mac::ObjCCastStrict<OpenInToolbar>(subview); - } - } - return nil; - } - - // Whether the given view has an OpenInToolbar as subview. - bool ViewContainsToolbar(UIView* view) { return ToolbarInView(view) != nil; } - - web::WebTaskEnvironment task_environment_; - std::unique_ptr<TestChromeBrowserState> browser_state_; - std::unique_ptr<Browser> browser_; - id web_view_proxy_mock; - CRWWebViewScrollViewProxy* scroll_view_proxy_; - OpenInMediator* mediator_; -}; - -// Tests that enabling openIn adds openInToolBar to the WebState view. -TEST_F(OpenInMediatorTest, EnableForWebState) { - auto web_state = CreateWebStateWithView(); - [mediator_ enableOpenInForWebState:web_state.get() - withDocumentURL:GURL::EmptyGURL() - suggestedFileName:@""]; - - EXPECT_TRUE(ViewContainsToolbar(web_state->GetView())); - [mediator_ disableAll]; -} - -// Tests that disabling openIn removes openInToolBar from the WebState view. -TEST_F(OpenInMediatorTest, DisableForWebState) { - auto web_state = CreateWebStateWithView(); - - [mediator_ enableOpenInForWebState:web_state.get() - withDocumentURL:GURL::EmptyGURL() - suggestedFileName:@""]; - ASSERT_TRUE(ViewContainsToolbar(web_state->GetView())); - [mediator_ disableOpenInForWebState:web_state.get()]; - EXPECT_FALSE(ViewContainsToolbar(web_state->GetView())); - [mediator_ disableAll]; -} - -// Tests that OpenInMediator can handle multiple WebStates correctly. -TEST_F(OpenInMediatorTest, MultipleWebStates) { - auto web_state_1 = CreateWebStateWithView(); - [mediator_ enableOpenInForWebState:web_state_1.get() - withDocumentURL:GURL::EmptyGURL() - suggestedFileName:@""]; - EXPECT_TRUE(ViewContainsToolbar(web_state_1->GetView())); - - auto web_state_2 = CreateWebStateWithView(); - [mediator_ enableOpenInForWebState:web_state_2.get() - withDocumentURL:GURL::EmptyGURL() - suggestedFileName:@""]; - EXPECT_TRUE(ViewContainsToolbar(web_state_2->GetView())); - - EXPECT_NSNE(ToolbarInView(web_state_1->GetView()), - ToolbarInView(web_state_2->GetView())); - - // Verify that destroy will detach the OpenIn view from the WebState. - [mediator_ destroyOpenInForWebState:web_state_1.get()]; - EXPECT_FALSE(ViewContainsToolbar(web_state_1->GetView())); - - // Verify that destroying OpenIn for `web_state_1` doesn't affect - // `web_state_2`. - EXPECT_TRUE(ViewContainsToolbar(web_state_2->GetView())); - - // Verify that calling disableAll remove any remaining views. - [mediator_ disableAll]; - EXPECT_FALSE(ViewContainsToolbar(web_state_2->GetView())); -}
diff --git a/ios/chrome/browser/ui/open_in/open_in_toolbar.h b/ios/chrome/browser/ui/open_in/open_in_toolbar.h deleted file mode 100644 index 15c0e955..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_toolbar.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_TOOLBAR_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_TOOLBAR_H_ - -#import <UIKit/UIKit.h> - -@interface OpenInToolbar : UIView - -// Init with the given local target and action. -- (instancetype)initWithTarget:(id)target - action:(SEL)action NS_DESIGNATED_INITIALIZER; - -- (instancetype)initWithFrame:(CGRect)aRect NS_UNAVAILABLE; - -- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE; - -@end - -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_TOOLBAR_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_toolbar.mm b/ios/chrome/browser/ui/open_in/open_in_toolbar.mm deleted file mode 100644 index f8ef0aa..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_toolbar.mm +++ /dev/null
@@ -1,109 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_toolbar.h" - -#import <cmath> - -#import "base/check.h" -#import "base/notreached.h" -#import "ios/chrome/browser/shared/ui/util/named_guide.h" -#import "ios/chrome/browser/shared/ui/util/rtl_geometry.h" -#import "ios/chrome/browser/shared/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#import "ios/chrome/common/ui/util/constraints_ui_util.h" -#import "ios/chrome/grit/ios_strings.h" -#import "ui/base/l10n/l10n_util.h" -#import "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -// The toolbar's constants. -const CGFloat kToolbarHeight = 49.0f; -// The toolbar's open button constants. -const CGFloat kOpenButtonTrailingPadding = 16.0f; -// The toolbar's border related constants. -const CGFloat kTopBorderHeight = 0.5f; - -} // anonymous namespace - -@interface OpenInToolbar () - -// The "Open in..." button that's hooked up with the target and action passed -// on initialization. -@property(nonatomic, strong, readonly) UIButton* openButton; - -// The line used as the border at the top of the toolbar. -@property(nonatomic, strong, readonly) UIView* topBorder; - -@end - -@implementation OpenInToolbar - -- (instancetype)initWithTarget:(id)target action:(SEL)action { - self = [super initWithFrame:CGRectZero]; - if (self) { - DCHECK([target respondsToSelector:action]); - self.backgroundColor = [UIColor colorNamed:kBackgroundColor]; - - _openButton = [self openButtonWithTarget:target action:action]; - _topBorder = [self topBorderView]; - - [self addSubview:_openButton]; - [self addSubview:_topBorder]; - - [NSLayoutConstraint activateConstraints:@[ - [self.heightAnchor constraintEqualToConstant:kToolbarHeight], - [_openButton.topAnchor constraintEqualToAnchor:self.topAnchor], - [_openButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor], - [_openButton.leadingAnchor - constraintGreaterThanOrEqualToAnchor:self.safeAreaLayoutGuide - .leadingAnchor - constant:kOpenButtonTrailingPadding], - [_openButton.trailingAnchor - constraintEqualToAnchor:self.safeAreaLayoutGuide.trailingAnchor - constant:-kOpenButtonTrailingPadding], - [_topBorder.heightAnchor constraintEqualToConstant:kTopBorderHeight], - ]]; - - AddSameConstraintsToSides( - _topBorder, self, - LayoutSides::kTop | LayoutSides::kLeading | LayoutSides::kTrailing); - } - return self; -} - -#pragma mark Helper - -// Helper to create the OpenIn button. -- (UIButton*)openButtonWithTarget:(id)target action:(SEL)action { - UIButton* openButton = [[UIButton alloc] init]; - [openButton setTitleColor:[UIColor colorNamed:kBlueColor] - forState:UIControlStateNormal]; - [openButton setTitle:l10n_util::GetNSString(IDS_IOS_OPEN_IN) - forState:UIControlStateNormal]; - [openButton sizeToFit]; - openButton.translatesAutoresizingMaskIntoConstraints = NO; - - [openButton addTarget:target - action:action - forControlEvents:UIControlEventTouchUpInside]; - - return openButton; -} - -// Helper to create the topBorder view. -- (UIView*)topBorderView { - UIView* topBorder = [[UIView alloc] initWithFrame:CGRectZero]; - topBorder.backgroundColor = [UIColor colorNamed:kToolbarShadowColor]; - topBorder.translatesAutoresizingMaskIntoConstraints = NO; - - return topBorder; -} - -@end
diff --git a/ios/chrome/browser/ui/open_in/open_in_toolbar_unittest.mm b/ios/chrome/browser/ui/open_in/open_in_toolbar_unittest.mm deleted file mode 100644 index e9a24c1..0000000 --- a/ios/chrome/browser/ui/open_in/open_in_toolbar_unittest.mm +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2014 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/browser/ui/open_in/open_in_toolbar.h" -#import "testing/platform_test.h" -#import "third_party/ocmock/OCMock/OCMock.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -// A class that counts the number of times the `dummyMethod:` method is called. -@interface DummyObserver : NSObject - -// The number of times `dummyMethod:` is invoked. -@property(nonatomic, readonly) int dummyMethodCallCount; - -// The method whose invocation increases `dummyMethodCallCount` by one. -- (void)dummyMethod:(id)parameter; - -@end - -@implementation DummyObserver - -@synthesize dummyMethodCallCount = _dummyMethodCallCount; - -- (void)dummyMethod:(id)parameter { - _dummyMethodCallCount++; -} - -@end - -namespace { - -class OpenInToolbarTest : public PlatformTest { - protected: - UIButton* GetOpenInButtonInToolBar(OpenInToolbar* toolbar) { - NSArray* subviews = [toolbar subviews]; - // Assumes there is only one UIButton in the toolbar. - for (UIView* subview in subviews) { - if ([subview isKindOfClass:[UIButton class]]) { - return (UIButton*)subview; - } - } - return nil; - } -}; - -TEST_F(OpenInToolbarTest, TestButtonActionAndSelector) { - DummyObserver* dummyObserver = [[DummyObserver alloc] init]; - OpenInToolbar* openInToolbar = - [[OpenInToolbar alloc] initWithTarget:dummyObserver - action:@selector(dummyMethod:)]; - UIButton* button = GetOpenInButtonInToolBar(openInToolbar); - ASSERT_TRUE(button); - EXPECT_EQ([dummyObserver dummyMethodCallCount], 0); - [button sendActionsForControlEvents:UIControlEventTouchUpInside]; - EXPECT_EQ([dummyObserver dummyMethodCallCount], 1); -} - -} // namespace
diff --git a/ios/chrome/browser/ui/settings/password/password_issues/password_issues_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/password_issues/password_issues_mediator_unittest.mm index 7d08537f..2138cb9 100644 --- a/ios/chrome/browser/ui/settings/password/password_issues/password_issues_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/password/password_issues/password_issues_mediator_unittest.mm
@@ -64,6 +64,9 @@ constexpr char kPassword[] = "s3cre3t"; constexpr char kPassword2[] = "s3cre3t2"; +constexpr char kStrongPassword[] = "pmsFlsnoab4nsl#losb@skpfnsbkjb^klsnbs!cns"; +constexpr char kStrongPassword2[] = "sfdf#losb@sdf^klsnbs!cns"; +constexpr char kStrongPassword3[] = "sdfsdfwer@313QaDSdsd!cns"; NSString* GetUsername() { return base::SysUTF8ToNSString(kUsername); @@ -293,15 +296,15 @@ // Weak. MakeTestPasswordIssue(kExampleCom, kUsername, kPassword, InsecureType::kWeak); // Reused. - MakeTestPasswordIssue(kExampleCom2, kUsername, kPassword, + MakeTestPasswordIssue(kExampleCom2, kUsername, kStrongPassword, InsecureType::kReused); - MakeTestPasswordIssue(kExampleCom3, kUsername2, kPassword, + MakeTestPasswordIssue(kExampleCom3, kUsername2, kStrongPassword, InsecureType::kReused); // Dismissed Compromised - MakeTestPasswordIssue(kExampleCom3, kUsername, kPassword, + MakeTestPasswordIssue(kExampleCom3, kUsername, kStrongPassword2, InsecureType::kLeaked, /*muted=*/true); // Compromised. - MakeTestPasswordIssue(kExampleCom, kUsername2, kPassword, + MakeTestPasswordIssue(kExampleCom, kUsername2, kStrongPassword3, InsecureType::kPhished); RunUntilIdle();
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm index a1208f7..69da8e6 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator_unittest.mm
@@ -203,7 +203,7 @@ form->username_element = u"Email"; form->username_value = u"test@egmail.com"; form->password_element = u"Passwd"; - form->password_value = u"test"; + form->password_value = u"fnlsr4@cm^mdls@fkspnsg3d"; form->submit_element = u"signIn"; form->signon_realm = signon_realm; form->scheme = password_manager::PasswordForm::Scheme::kHtml;
diff --git a/ios/chrome/browser/ui/sharing/BUILD.gn b/ios/chrome/browser/ui/sharing/BUILD.gn index a7f4ae8..49e4cf4 100644 --- a/ios/chrome/browser/ui/sharing/BUILD.gn +++ b/ios/chrome/browser/ui/sharing/BUILD.gn
@@ -29,27 +29,30 @@ ] deps = [ ":sharing", + ":sharing_metrics", "//base", - "//components/bookmarks/browser", "//ios/chrome/app/strings", "//ios/chrome/browser/bookmarks", - "//ios/chrome/browser/open_in", "//ios/chrome/browser/shared/coordinator/chrome_coordinator", "//ios/chrome/browser/shared/model/browser", "//ios/chrome/browser/shared/model/web_state_list", "//ios/chrome/browser/shared/public/commands", "//ios/chrome/browser/shared/ui/util", - "//ios/chrome/browser/shared/ui/util:url_with_title", - "//ios/chrome/browser/ui/bookmarks:core", - "//ios/chrome/browser/ui/open_in:features", - "//ios/chrome/browser/ui/open_in:open_in_histograms", + "//ios/chrome/browser/sharing", "//ios/chrome/browser/ui/sharing/activity_services", "//ios/chrome/browser/ui/sharing/qr_generator", "//ios/third_party/material_components_ios", "//ios/web/public", "//ios/web/public/download", "//ui/base", - "//url", + ] +} + +source_set("sharing_metrics") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "share_file_download_metrics.h", + "share_file_download_metrics.mm", ] } @@ -84,3 +87,19 @@ "//url", ] } + +source_set("eg2_tests") { + configs += [ + "//build/config/compiler:enable_arc", + "//build/config/ios:xctest_config", + ] + testonly = true + sources = [ "share_file_download_egtest.mm" ] + deps = [ + "//base/test:test_support", + "//ios/chrome/test/earl_grey:eg_test_support+eg2", + "//ios/testing/earl_grey:eg_test_support+eg2", + "//net:test_support", + ] + frameworks = [ "UIKit.framework" ] +}
diff --git a/ios/chrome/browser/ui/sharing/DEPS b/ios/chrome/browser/ui/sharing/DEPS deleted file mode 100644 index c8fce14..0000000 --- a/ios/chrome/browser/ui/sharing/DEPS +++ /dev/null
@@ -1,4 +0,0 @@ -include_rules = [ - "+ios/chrome/browser/ui/open_in/features.h", - "+ios/chrome/browser/ui/open_in/open_in_histograms.h", -]
diff --git a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm b/ios/chrome/browser/ui/sharing/share_file_download_egtest.mm similarity index 82% rename from ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm rename to ios/chrome/browser/ui/sharing/share_file_download_egtest.mm index 4608f736..6407cb3 100644 --- a/ios/chrome/browser/ui/open_in/open_in_controller_egtest.mm +++ b/ios/chrome/browser/ui/sharing/share_file_download_egtest.mm
@@ -42,10 +42,10 @@ using base::test::ios::WaitUntilConditionOrTimeout; // Tests Open in Feature. -@interface OpenInManagerTestCase : ChromeTestCase +@interface ShareFileDownloadTestCase : ChromeTestCase @end -@implementation OpenInManagerTestCase +@implementation ShareFileDownloadTestCase - (void)setUp { [super setUp]; @@ -95,21 +95,11 @@ @"Waiting for the open in dialog to disappear"); } -- (BOOL)shouldRunTests { - if (@available(iOS 14.5, *)) { - return YES; - } - return NO; -} - #pragma mark - Tests // Tests that open in button appears when opening a PDF, and that tapping on it // will open the activity view. - (void)testOpenInPDF { - if (![self shouldRunTests]) { - EARL_GREY_TEST_SKIPPED(@"Do not run the test."); - } // Open the activity menu. [ChromeEarlGrey loadURL:self.testServer->GetURL(kPDFPath)]; [self openActivityMenu]; @@ -120,19 +110,11 @@ // the open in toolbar. [self closeActivityMenu]; [self assertActivityMenuDismissed]; - // TODO(crbug.com/1357553): Remove when Open In download experiment is - // finished. - [[EarlGrey selectElementWithMatcher:chrome_test_util::OpenInButton()] - assertWithMatcher:grey_notVisible()]; } // Tests that open in button appears when opening a PNG, and that tapping on it // will open the activity view. - (void)testOpenInPNG { - if (![self shouldRunTests]) { - EARL_GREY_TEST_SKIPPED(@"Do not run the test."); - } - // Open the activity menu. [ChromeEarlGrey loadURL:self.testServer->GetURL(kPNGPath)]; [self openActivityMenu]; @@ -142,17 +124,10 @@ // the open in toolbar. [self closeActivityMenu]; [self assertActivityMenuDismissed]; - // TODO(crbug.com/1357553): Remove when Open In download experiment is - // finished. - [[EarlGrey selectElementWithMatcher:chrome_test_util::OpenInButton()] - assertWithMatcher:grey_notVisible()]; } // Tests that open in button do not appears when opening a MOV file. - (void)testOpenInMOV { - if (![self shouldRunTests]) { - EARL_GREY_TEST_SKIPPED(@"Do not run the test."); - } [ChromeEarlGrey loadURL:self.testServer->GetURL(kMOVPath)]; [[EarlGrey selectElementWithMatcher:chrome_test_util::OpenInButton()] assertWithMatcher:grey_nil()]; @@ -161,9 +136,6 @@ // Tests that open in button appears when opening a PNG and when shutting down // the test server, the appropriate error message is displayed. - (void)testOpenInOfflineServer { - if (![self shouldRunTests]) { - EARL_GREY_TEST_SKIPPED(@"Do not run the test."); - } [ChromeEarlGrey loadURL:self.testServer->GetURL(kPNGPath)]; // Shutdown the test server. GREYAssertTrue(self.testServer->ShutdownAndWaitUntilComplete(),
diff --git a/ios/chrome/browser/ui/open_in/open_in_histograms.h b/ios/chrome/browser/ui/sharing/share_file_download_metrics.h similarity index 73% rename from ios/chrome/browser/ui/open_in/open_in_histograms.h rename to ios/chrome/browser/ui/sharing/share_file_download_metrics.h index 28801d2..5ec312a 100644 --- a/ios/chrome/browser/ui/open_in/open_in_histograms.h +++ b/ios/chrome/browser/ui/sharing/share_file_download_metrics.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_HISTOGRAMS_H_ -#define IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_HISTOGRAMS_H_ +#ifndef IOS_CHROME_BROWSER_UI_SHARING_SHARE_FILE_DOWNLOAD_METRICS_H_ +#define IOS_CHROME_BROWSER_UI_SHARING_SHARE_FILE_DOWNLOAD_METRICS_H_ // UMA histogram names. extern const char kOpenInDownloadHistogram[]; @@ -19,4 +19,4 @@ kMaxValue = kFailed, }; -#endif // IOS_CHROME_BROWSER_UI_OPEN_IN_OPEN_IN_HISTOGRAMS_H_ +#endif // IOS_CHROME_BROWSER_UI_SHARING_SHARE_FILE_DOWNLOAD_METRICS_H_
diff --git a/ios/chrome/browser/ui/open_in/open_in_histograms.mm b/ios/chrome/browser/ui/sharing/share_file_download_metrics.mm similarity index 81% rename from ios/chrome/browser/ui/open_in/open_in_histograms.mm rename to ios/chrome/browser/ui/sharing/share_file_download_metrics.mm index dec51922..0e70febd 100644 --- a/ios/chrome/browser/ui/open_in/open_in_histograms.mm +++ b/ios/chrome/browser/ui/sharing/share_file_download_metrics.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/open_in/open_in_histograms.h" +#import "ios/chrome/browser/ui/sharing/share_file_download_metrics.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator.mm index 9d940d5..071b684 100644 --- a/ios/chrome/browser/ui/sharing/sharing_coordinator.mm +++ b/ios/chrome/browser/ui/sharing/sharing_coordinator.mm
@@ -4,8 +4,6 @@ #import "ios/chrome/browser/ui/sharing/sharing_coordinator.h" -#import <MaterialComponents/MaterialSnackbar.h> - #import "base/files/file_util.h" #import "base/ios/block_types.h" #import "base/mac/foundation_util.h" @@ -13,7 +11,6 @@ #import "base/strings/sys_string_conversions.h" #import "base/task/thread_pool.h" #import "base/threading/scoped_blocking_call.h" -#import "ios/chrome/browser/open_in/open_in_tab_helper.h" #import "ios/chrome/browser/shared/model/browser/browser.h" #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h" #import "ios/chrome/browser/shared/public/commands/activity_service_commands.h" @@ -21,23 +18,15 @@ #import "ios/chrome/browser/shared/public/commands/qr_generation_commands.h" #import "ios/chrome/browser/shared/public/commands/share_download_overlay_commands.h" #import "ios/chrome/browser/shared/public/commands/snackbar_commands.h" -#import "ios/chrome/browser/ui/open_in/features.h" -#import "ios/chrome/browser/ui/open_in/open_in_histograms.h" +#import "ios/chrome/browser/sharing/share_file_download_tab_helper.h" #import "ios/chrome/browser/ui/sharing/activity_services/activity_service_coordinator.h" #import "ios/chrome/browser/ui/sharing/activity_services/activity_service_presentation.h" #import "ios/chrome/browser/ui/sharing/qr_generator/qr_generator_coordinator.h" #import "ios/chrome/browser/ui/sharing/share_download_overlay_coordinator.h" +#import "ios/chrome/browser/ui/sharing/share_file_download_metrics.h" #import "ios/chrome/browser/ui/sharing/sharing_params.h" #import "ios/chrome/browser/ui/sharing/sharing_positioner.h" -#import "ios/web/public/browser_state.h" #import "ios/web/public/download/crw_web_view_download.h" -#import "ios/web/public/navigation/navigation_item.h" -#import "ios/web/public/navigation/navigation_manager.h" -#import "net/base/load_flags.h" -#import "net/base/mac/url_conversions.h" -#import "services/network/public/cpp/resource_request.h" -#import "services/network/public/cpp/shared_url_loader_factory.h" -#import "services/network/public/cpp/simple_url_loader.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -140,17 +129,7 @@ @end -@implementation SharingCoordinator { - // Loader used to redownload the document and save it in the sandbox. - // TODO(crbug.com/1357553): Remove when Open In download experiment is - // finished. - std::unique_ptr<network::SimpleURLLoader> _urlLoader; - - // URLLoaderFactory instance needed for URLLoader. - // TODO(crbug.com/1357553): Remove when Open In download experiment is - // finished. - scoped_refptr<network::SharedURLLoaderFactory> _urlLoaderFactory; -} +@implementation SharingCoordinator - (instancetype)initWithBaseViewController:(UIViewController*)viewController browser:(Browser*)browser @@ -222,8 +201,8 @@ - (void)start { web::WebState* currentWebState = self.browser->GetWebStateList()->GetActiveWebState(); - if (currentWebState && OpenInTabHelper::ShouldDownload(currentWebState) && - IsOpenInActivitiesInShareButtonEnabled()) { + if (currentWebState && + ShareFileDownloadTabHelper::ShouldDownload(currentWebState)) { // Creating the directory can block the main thread, so perform it on a // background sequence, then on current sequence complete the workflow. __weak SharingCoordinator* weakSelf = self; @@ -265,8 +244,6 @@ [self.activityServiceCoordinator stop]; self.activityServiceCoordinator = nil; - _urlLoader.reset(); - // If a new download with a file with the same name exist it will throw an // error in downloadDidFailWithError method. [self removeFile]; @@ -329,52 +306,18 @@ - (void)startDownloadFromWebState:(web::WebState*)webState { self.isDownloadCanceled = NO; NSString* tempDirPath = GetTemporaryDocumentDirectory(); - OpenInTabHelper* helper = OpenInTabHelper::FromWebState(webState); + ShareFileDownloadTabHelper* helper = + ShareFileDownloadTabHelper::FromWebState(webState); self.filePath = [tempDirPath stringByAppendingPathComponent:base::SysUTF16ToNSString( helper->GetFileNameSuggestion())]; self.fileNSURL = [NSURL fileURLWithPath:self.filePath]; - if (@available(iOS 14.5, *)) { - if (IsOpenInNewDownloadEnabled()) { __weak SharingCoordinator* weakSelf = self; webState->DownloadCurrentPage(self.filePath, self, ^(id<CRWWebViewDownload> download) { weakSelf.download = download; }); - return; - } - } - - // Download the document and save it at `self.filePath`. - // TODO(crbug.com/1357553): Remove when Open In download experiment is - // finished. - web::NavigationItem* item = - webState->GetNavigationManager()->GetLastCommittedItem(); - const GURL& last_committed_url = item ? item->GetURL() : GURL::EmptyGURL(); - - auto resourceRequest = std::make_unique<network::ResourceRequest>(); - resourceRequest->url = last_committed_url; - resourceRequest->load_flags = net::LOAD_SKIP_CACHE_VALIDATION; - - _urlLoader = network::SimpleURLLoader::Create(std::move(resourceRequest), - NO_TRAFFIC_ANNOTATION_YET); - - _urlLoaderFactory = webState->GetBrowserState()->GetSharedURLLoaderFactory(); - - __weak SharingCoordinator* weakSelf = self; - _urlLoader->DownloadToFile( - std::move(_urlLoaderFactory).get(), - base::BindOnce(^(base::FilePath filePath) { - if (!weakSelf.isDownloadCanceled) { - if ([weakSelf hasValidFileAtURL:weakSelf.fileNSURL]) { - [weakSelf downloadDidFinish]; - } else { - [weakSelf downloadDidFailWithError:nil]; - } - } - }), - base::FilePath(base::SysNSStringToUTF8(self.filePath))); } // Shows an overlayed spinner on the top view to indicate that a file download @@ -442,19 +385,17 @@ - (void)cancelDownload { [self stopDisplayDownloadOverlay]; - if (@available(iOS 14.5, *)) { - self.isCancelling = YES; - __weak SharingCoordinator* weakSelf = self; - [self.download cancelDownload:^() { - weakSelf.isDownloadCanceled = YES; - weakSelf.isCancelling = NO; - if (weakSelf.shouldRestartCoordinator) { - // Self will be destroyed after this call so it should not be used - // anymore. - [weakSelf stopAndStartNewCoordinator]; - } - }]; - } + self.isCancelling = YES; + __weak SharingCoordinator* weakSelf = self; + [self.download cancelDownload:^() { + weakSelf.isDownloadCanceled = YES; + weakSelf.isCancelling = NO; + if (weakSelf.shouldRestartCoordinator) { + // Self will be destroyed after this call so it should not be used + // anymore. + [weakSelf stopAndStartNewCoordinator]; + } + }]; UMA_HISTOGRAM_ENUMERATION(kOpenInDownloadHistogram, OpenInDownloadResult::kCanceled); }
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 96400b9..9f83ac2 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -243,7 +243,6 @@ "//ios/chrome/browser/net:unit_tests", "//ios/chrome/browser/ntp:unit_tests", "//ios/chrome/browser/omaha:unit_tests", - "//ios/chrome/browser/open_in:unit_tests", "//ios/chrome/browser/optimization_guide:unit_tests", "//ios/chrome/browser/overlays:unit_tests", "//ios/chrome/browser/overlays/public/common/confirmation:unit_tests", @@ -348,7 +347,6 @@ "//ios/chrome/browser/ui/ntp/metrics:unit_tests", "//ios/chrome/browser/ui/omnibox:unit_tests", "//ios/chrome/browser/ui/omnibox/popup:unit_tests", - "//ios/chrome/browser/ui/open_in:unit_tests", "//ios/chrome/browser/ui/overlays:unit_tests", "//ios/chrome/browser/ui/overlays/infobar_banner:unit_tests", "//ios/chrome/browser/ui/overlays/infobar_banner/autofill_address_profile:unit_tests",
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn index e2e01148..53e043a 100644 --- a/ios/chrome/test/earl_grey2/BUILD.gn +++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -184,7 +184,6 @@ "//ios/chrome/browser/ui/ntp/feed_management:eg2_tests", "//ios/chrome/browser/ui/omnibox:eg2_tests", "//ios/chrome/browser/ui/omnibox/popup:eg2_tests", - "//ios/chrome/browser/ui/open_in:eg2_tests", "//ios/chrome/browser/ui/page_info:eg2_tests", "//ios/chrome/browser/ui/passwords:eg2_tests", "//ios/chrome/browser/ui/permissions:eg2_tests", @@ -200,6 +199,7 @@ "//ios/chrome/browser/ui/search_with:eg2_tests", "//ios/chrome/browser/ui/send_tab_to_self:eg2_tests", "//ios/chrome/browser/ui/settings/sync/utils:eg2_tests", + "//ios/chrome/browser/ui/sharing:eg2_tests", "//ios/chrome/browser/ui/sharing/activity_services:eg2_tests", "//ios/chrome/browser/ui/side_swipe:eg2_tests", "//ios/chrome/browser/ui/start_surface:eg2_tests",
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index fd832db..c0e12b3 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -550,7 +550,12 @@ // hardware video decoders. BASE_FEATURE(kUseMultiPlaneFormatForHardwareVideo, "UseMultiPlaneFormatForHardwareVideo", - base::FEATURE_DISABLED_BY_DEFAULT); +#if BUILDFLAG(IS_ANDROID) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT +#endif +); // Enables creating single shared image and mailbox for multi-planar formats for // software video decoders.
diff --git a/media/mojo/clients/mojo_video_decoder.cc b/media/mojo/clients/mojo_video_decoder.cc index b1d0f2c..cf531da 100644 --- a/media/mojo/clients/mojo_video_decoder.cc +++ b/media/mojo/clients/mojo_video_decoder.cc
@@ -328,6 +328,7 @@ void MojoVideoDecoder::OnResetDone() { DVLOG(2) << __func__; DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(pending_decodes_.empty()); can_read_without_stalling_ = true; std::move(reset_cb_).Run(); }
diff --git a/media/mojo/clients/mojo_video_decoder.h b/media/mojo/clients/mojo_video_decoder.h index ec4ebd3..87fdd87 100644 --- a/media/mojo/clients/mojo_video_decoder.h +++ b/media/mojo/clients/mojo_video_decoder.h
@@ -130,7 +130,7 @@ OutputCB output_cb_; WaitingCB waiting_cb_; uint64_t decode_counter_ = 0; - std::map<uint64_t, DecodeCB> pending_decodes_; + base::flat_map<uint64_t, DecodeCB> pending_decodes_; base::OnceClosure reset_cb_; // DecodeBuffer/VideoFrame timestamps for histogram/tracing purposes. Must be
diff --git a/media/mojo/services/mojo_video_decoder_service.cc b/media/mojo/services/mojo_video_decoder_service.cc index 3aba153..8e05eed 100644 --- a/media/mojo/services/mojo_video_decoder_service.cc +++ b/media/mojo/services/mojo_video_decoder_service.cc
@@ -117,7 +117,8 @@ private: // TODO(sandersd): Also track age, so that an overall limit can be enforced. - std::map<base::UnguessableToken, scoped_refptr<VideoFrame>> video_frames_; + base::flat_map<base::UnguessableToken, scoped_refptr<VideoFrame>> + video_frames_; }; MojoVideoDecoderService::MojoVideoDecoderService(
diff --git a/net/socket/udp_client_socket.cc b/net/socket/udp_client_socket.cc index 8645f1f..ca4a277 100644 --- a/net/socket/udp_client_socket.cc +++ b/net/socket/udp_client_socket.cc
@@ -18,6 +18,11 @@ handles::NetworkHandle network) : socket_(bind_type, net_log, source), connect_using_network_(network) {} +UDPClientSocket::UDPClientSocket(DatagramSocket::BindType bind_type, + NetLogWithSource source_net_log, + handles::NetworkHandle network) + : socket_(bind_type, source_net_log), connect_using_network_(network) {} + UDPClientSocket::~UDPClientSocket() = default; int UDPClientSocket::Connect(const IPEndPoint& address) { @@ -26,7 +31,10 @@ return ConnectUsingNetwork(connect_using_network_, address); connect_called_ = true; - int rv = socket_.Open(address.GetFamily()); + int rv = OK; + if (!adopted_opened_socket_) { + rv = socket_.Open(address.GetFamily()); + } if (rv != OK) return rv; return socket_.Connect(address); @@ -38,9 +46,13 @@ connect_called_ = true; if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) return ERR_NOT_IMPLEMENTED; - int rv = socket_.Open(address.GetFamily()); - if (rv != OK) + int rv = OK; + if (!adopted_opened_socket_) { + rv = socket_.Open(address.GetFamily()); + } + if (rv != OK) { return rv; + } rv = socket_.BindToNetwork(network); if (rv != OK) return rv; @@ -53,8 +65,10 @@ connect_called_ = true; if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) return ERR_NOT_IMPLEMENTED; - int rv; - rv = socket_.Open(address.GetFamily()); + int rv = OK; + if (!adopted_opened_socket_) { + rv = socket_.Open(address.GetFamily()); + } if (rv != OK) return rv; // Calling connect() will bind a socket to the default network, however there @@ -126,6 +140,7 @@ void UDPClientSocket::Close() { socket_.Close(); + adopted_opened_socket_ = false; } int UDPClientSocket::GetPeerAddress(IPEndPoint* address) const { @@ -178,9 +193,13 @@ #endif } -void UDPClientSocket::AdoptOpenedSocket(AddressFamily address_family, - SocketDescriptor socket) { - socket_.AdoptOpenedSocket(address_family, socket); +int UDPClientSocket::AdoptOpenedSocket(AddressFamily address_family, + SocketDescriptor socket) { + int rv = socket_.AdoptOpenedSocket(address_family, socket); + if (rv == OK) { + adopted_opened_socket_ = true; + } + return rv; } } // namespace net
diff --git a/net/socket/udp_client_socket.h b/net/socket/udp_client_socket.h index fc695b7..6e3875b 100644 --- a/net/socket/udp_client_socket.h +++ b/net/socket/udp_client_socket.h
@@ -30,6 +30,11 @@ const net::NetLogSource& source, handles::NetworkHandle network = handles::kInvalidNetworkHandle); + UDPClientSocket( + DatagramSocket::BindType bind_type, + NetLogWithSource source_net_log, + handles::NetworkHandle network = handles::kInvalidNetworkHandle); + UDPClientSocket(const UDPClientSocket&) = delete; UDPClientSocket& operator=(const UDPClientSocket&) = delete; @@ -74,14 +79,34 @@ int SetMulticastInterface(uint32_t interface_index) override; void SetIOSNetworkServiceType(int ios_network_service_type) override; - // Takes ownership of an opened but unconnected and unbound `socket`. - void AdoptOpenedSocket(AddressFamily address_family, SocketDescriptor socket); + // Takes ownership of an opened but unconnected and unbound `socket`. This + // method must be called after UseNonBlockingIO, otherwise the adopted socket + // will not have the non-blocking IO flag set. + int AdoptOpenedSocket(AddressFamily address_family, SocketDescriptor socket); + + uint32_t get_multicast_interface_for_testing() { + return socket_.get_multicast_interface_for_testing(); + } +#if !BUILDFLAG(IS_WIN) + bool get_msg_confirm_for_testing() { + return socket_.get_msg_confirm_for_testing(); + } + bool get_recv_optimization_for_testing() { + return socket_.get_experimental_recv_optimization_enabled_for_testing(); + } +#endif +#if BUILDFLAG(IS_WIN) + bool get_use_non_blocking_io_for_testing() { + return socket_.get_use_non_blocking_io_for_testing(); + } +#endif private: UDPSocket socket_; + bool adopted_opened_socket_ = false; bool connect_called_ = false; // The network the socket is currently bound to. - handles::NetworkHandle network_; + handles::NetworkHandle network_ = handles::kInvalidNetworkHandle; handles::NetworkHandle connect_using_network_; };
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc index d7fe60c..120ce58 100644 --- a/net/socket/udp_socket_posix.cc +++ b/net/socket/udp_socket_posix.cc
@@ -139,6 +139,22 @@ net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source); } +UDPSocketPosix::UDPSocketPosix(DatagramSocket::BindType bind_type, + NetLogWithSource source_net_log) + : socket_(kInvalidSocket), + bind_type_(bind_type), + read_socket_watcher_(FROM_HERE), + write_socket_watcher_(FROM_HERE), + read_watcher_(this), + write_watcher_(this), + net_log_(source_net_log), + bound_network_(handles::kInvalidNetworkHandle), + always_update_bytes_received_(base::FeatureList::IsEnabled( + features::kUdpSocketPosixAlwaysUpdateBytesReceived)) { + net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, + net_log_.source()); +} + UDPSocketPosix::~UDPSocketPosix() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); Close();
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h index ed9c754..a0cb1e2 100644 --- a/net/socket/udp_socket_posix.h +++ b/net/socket/udp_socket_posix.h
@@ -72,6 +72,9 @@ net::NetLog* net_log, const net::NetLogSource& source); + UDPSocketPosix(DatagramSocket::BindType bind_type, + NetLogWithSource source_net_log); + UDPSocketPosix(const UDPSocketPosix&) = delete; UDPSocketPosix& operator=(const UDPSocketPosix&) = delete; @@ -280,6 +283,14 @@ // not bound or connected to an address. int AdoptOpenedSocket(AddressFamily address_family, int socket); + uint32_t get_multicast_interface_for_testing() { + return multicast_interface_; + } + bool get_msg_confirm_for_testing() { return sendto_flags_; } + bool get_experimental_recv_optimization_enabled_for_testing() { + return experimental_recv_optimization_enabled_; + } + private: enum SocketOptions { SOCKET_OPTION_MULTICAST_LOOP = 1 << 0
diff --git a/net/socket/udp_socket_win.cc b/net/socket/udp_socket_win.cc index dfc234f5..32926a0 100644 --- a/net/socket/udp_socket_win.cc +++ b/net/socket/udp_socket_win.cc
@@ -249,6 +249,16 @@ net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source); } +UDPSocketWin::UDPSocketWin(DatagramSocket::BindType bind_type, + NetLogWithSource source_net_log) + : socket_(INVALID_SOCKET), + socket_options_(SOCKET_OPTION_MULTICAST_LOOP), + net_log_(source_net_log) { + EnsureWinsockInit(); + net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, + net_log_.source()); +} + UDPSocketWin::~UDPSocketWin() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); Close();
diff --git a/net/socket/udp_socket_win.h b/net/socket/udp_socket_win.h index 8576135..dd27752 100644 --- a/net/socket/udp_socket_win.h +++ b/net/socket/udp_socket_win.h
@@ -165,6 +165,9 @@ net::NetLog* net_log, const net::NetLogSource& source); + UDPSocketWin(DatagramSocket::BindType bind_type, + NetLogWithSource source_net_log); + UDPSocketWin(const UDPSocketWin&) = delete; UDPSocketWin& operator=(const UDPSocketWin&) = delete; @@ -346,8 +349,8 @@ // Resets the thread to be used for thread-safety checks. void DetachFromThread(); - // This class by default uses overlapped IO. Call this method before Open() - // to switch to non-blocking IO. + // This class by default uses overlapped IO. Call this method before Open() or + // AdoptOpenedSocket() to switch to non-blocking IO. void UseNonBlockingIO(); // Apply |tag| to this socket. @@ -355,9 +358,16 @@ // Takes ownership of `socket`, which should be a socket descriptor opened // with the specified address family. The socket should only be created but - // not bound or connected to an address. + // not bound or connected to an address. This method must be called after + // UseNonBlockingIO, otherwise the adopted socket will not have the + // non-blocking IO flag set. int AdoptOpenedSocket(AddressFamily address_family, SOCKET socket); + uint32_t get_multicast_interface_for_testing() { + return multicast_interface_; + } + bool get_use_non_blocking_io_for_testing() { return use_non_blocking_io_; } + private: enum SocketOptions { SOCKET_OPTION_MULTICAST_LOOP = 1 << 0
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index c1421d8..048cf32 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -13,6 +13,8 @@ sources = [ "brokered_client_socket_factory.cc", "brokered_client_socket_factory.h", + "brokered_udp_client_socket.cc", + "brokered_udp_client_socket.h", "cache_transparency_settings.cc", "cache_transparency_settings.h", "chunked_data_pipe_upload_data_stream.cc", @@ -382,6 +384,7 @@ testonly = true sources = [ + "brokered_udp_client_socket_unittest.cc", "chunked_data_pipe_upload_data_stream_unittest.cc", "cookie_access_delegate_impl_unittest.cc", "cookie_manager_unittest.cc",
diff --git a/services/network/brokered_client_socket_factory.cc b/services/network/brokered_client_socket_factory.cc index 7023ad5..822ad43 100644 --- a/services/network/brokered_client_socket_factory.cc +++ b/services/network/brokered_client_socket_factory.cc
@@ -8,6 +8,7 @@ #include "net/socket/datagram_client_socket.h" #include "net/socket/tcp_client_socket.h" #include "net/socket/udp_client_socket.h" +#include "services/network/brokered_udp_client_socket.h" #include "services/network/tcp_client_socket_brokered.h" #if BUILDFLAG(IS_WIN) @@ -39,8 +40,8 @@ net::DatagramSocket::BindType bind_type, net::NetLog* net_log, const net::NetLogSource& source) { - // TODO(liza): Call into the broker rather than directly to net. - return std::make_unique<net::UDPClientSocket>(bind_type, net_log, source); + return std::make_unique<BrokeredUdpClientSocket>(bind_type, net_log, source, + this); } std::unique_ptr<net::TransportClientSocket>
diff --git a/services/network/brokered_client_socket_factory.h b/services/network/brokered_client_socket_factory.h index 1575db22..a669281 100644 --- a/services/network/brokered_client_socket_factory.h +++ b/services/network/brokered_client_socket_factory.h
@@ -74,10 +74,11 @@ net::AddressFamily address_family, mojom::SocketBroker::CreateUdpSocketCallback callback); - private: - // Whether or not a socket for `addresses` should be brokered or not. - bool ShouldBroker(const net::AddressList& addresses) const; + // Whether or not a socket for `addresses` should be brokered or not. Virtual + // for testing. + virtual bool ShouldBroker(const net::AddressList& addresses) const; + private: mojo::Remote<mojom::SocketBroker> socket_broker_; #if BUILDFLAG(IS_WIN) BrokerHelperWin broker_helper_;
diff --git a/services/network/brokered_udp_client_socket.cc b/services/network/brokered_udp_client_socket.cc new file mode 100644 index 0000000..c9e8f9a --- /dev/null +++ b/services/network/brokered_udp_client_socket.cc
@@ -0,0 +1,310 @@ +// 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 "services/network/brokered_udp_client_socket.h" + +#include "base/component_export.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "base/task/single_thread_task_runner.h" +#include "build/build_config.h" +#include "mojo/public/cpp/platform/platform_handle.h" +#include "net/base/address_list.h" +#include "net/base/completion_once_callback.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" +#include "net/base/network_change_notifier.h" +#include "net/base/network_handle.h" +#include "net/log/net_log_source.h" +#include "net/nqe/network_quality_estimator.h" +#include "net/socket/datagram_client_socket.h" +#include "net/socket/datagram_socket.h" +#include "net/socket/socket_tag.h" +#include "net/socket/stream_socket.h" +#include "net/socket/udp_client_socket.h" +#include "net/socket/udp_socket.h" +#include "net/socket/udp_socket_global_limits.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "services/network/brokered_client_socket_factory.h" +#include "services/network/public/cpp/transferable_socket.h" + +namespace network { + +BrokeredUdpClientSocket::BrokeredUdpClientSocket( + net::DatagramSocket::BindType bind_type, + net::NetLog* net_log, + const net::NetLogSource& source, + BrokeredClientSocketFactory* client_socket_factory, + net::handles::NetworkHandle network) + : bind_type_(bind_type), + network_(network), + net_log_source_( + net::NetLogWithSource::Make(net_log, net::NetLogSourceType::SOCKET)), + client_socket_factory_(client_socket_factory) { + net_log_source_.BeginEventReferencingSource( + net::NetLogEventType::BROKERED_SOCKET_ALIVE, source); +} + +BrokeredUdpClientSocket::~BrokeredUdpClientSocket() { + net_log_source_.EndEvent(net::NetLogEventType::BROKERED_SOCKET_ALIVE); +} + +int BrokeredUdpClientSocket::Connect(const net::IPEndPoint& address) { + NOTREACHED(); + return net::OK; +} + +int BrokeredUdpClientSocket::ConnectUsingNetwork( + net::handles::NetworkHandle network, + const net::IPEndPoint& address) { + NOTREACHED(); + return net::OK; +} + +int BrokeredUdpClientSocket::ConnectUsingDefaultNetwork( + const net::IPEndPoint& address) { + NOTREACHED(); + return net::OK; +} + +int BrokeredUdpClientSocket::ConnectAsync( + const net::IPEndPoint& address, + net::CompletionOnceCallback callback) { + return ConnectAsyncInternal(address, CONNECT, + net::handles::kInvalidNetworkHandle, + std::move(callback)); +} + +int BrokeredUdpClientSocket::ConnectUsingNetworkAsync( + net::handles::NetworkHandle network, + const net::IPEndPoint& address, + net::CompletionOnceCallback callback) { + return ConnectAsyncInternal(address, CONNECT_USING_NETWORK, network, + std::move(callback)); +} + +int BrokeredUdpClientSocket::ConnectUsingDefaultNetworkAsync( + const net::IPEndPoint& address, + net::CompletionOnceCallback callback) { + return ConnectAsyncInternal(address, CONNECT_USING_DEFAULT_NETWORK, + net::handles::kInvalidNetworkHandle, + std::move(callback)); +} + +int BrokeredUdpClientSocket::ConnectAsyncInternal( + const net::IPEndPoint& address, + WhichConnect which_connect, + net::handles::NetworkHandle network, + net::CompletionOnceCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(callback); + DCHECK(!socket_); + CHECK(!connect_called_); + connect_called_ = true; + if ((which_connect == CONNECT_USING_NETWORK || + which_connect == CONNECT_USING_DEFAULT_NETWORK) && + !net::NetworkChangeNotifier::AreNetworkHandlesSupported()) { + return net::ERR_NOT_IMPLEMENTED; + } +#if BUILDFLAG(IS_WIN) + if (!broker_helper_.ShouldBroker(address.address())) { + return DidCompleteCreate(/*should_broker=*/false, address, which_connect, + network, std::move(callback), + network::TransferableSocket(), net::OK); + } +#endif + net_log_source_.BeginEvent(net::NetLogEventType::BROKERED_CREATE_SOCKET); + client_socket_factory_->BrokerCreateUdpSocket( + address.GetFamily(), + base::BindOnce( + base::IgnoreResult(&BrokeredUdpClientSocket::DidCompleteCreate), + brokered_weak_ptr_factory_.GetWeakPtr(), /*should_broker=*/true, + address, which_connect, network, std::move(callback))); + return net::ERR_IO_PENDING; +} + +int BrokeredUdpClientSocket::DidCompleteCreate( + bool should_broker, + const net::IPEndPoint& address, + WhichConnect which_connect, + net::handles::NetworkHandle network, + net::CompletionOnceCallback callback, + network::TransferableSocket socket, + int result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (should_broker) { + net_log_source_.EndEventWithNetErrorCode( + net::NetLogEventType::BROKERED_CREATE_SOCKET, result); + if (result != net::OK) { + std::move(callback).Run(result); + return result; + } + } + socket_ = std::make_unique<net::UDPClientSocket>(bind_type_, net_log_source_, + network_); + // These options must be set before opening a socket or adopting an opened + // socket. + if (use_non_blocking_io_) { + socket_->UseNonBlockingIO(); + } + if (recv_optimization_) { + socket_->EnableRecvOptimization(); + } + + if (should_broker) { + int adopt_socket_rv = + socket_->AdoptOpenedSocket(address.GetFamily(), socket.TakeSocket()); + if (adopt_socket_rv != net::OK) { + Close(); + std::move(callback).Run(adopt_socket_rv); + return adopt_socket_rv; + } + } + + int set_multicast_rv = socket_->SetMulticastInterface(interface_index_); + if (set_multicast_rv != net::OK) { + if (should_broker) { + std::move(callback).Run(set_multicast_rv); + } + return set_multicast_rv; + } + socket_->ApplySocketTag(tag_); + socket_->SetMsgConfirm(set_msg_confirm_); + + int connect_rv = net::OK; + auto split_callback = base::SplitOnceCallback(std::move(callback)); + switch (which_connect) { + case CONNECT: + connect_rv = + socket_->ConnectAsync(address, std::move(split_callback.first)); + break; + case CONNECT_USING_NETWORK: + connect_rv = socket_->ConnectUsingNetworkAsync( + network, address, std::move(split_callback.first)); + break; + case CONNECT_USING_DEFAULT_NETWORK: + connect_rv = socket_->ConnectUsingDefaultNetworkAsync( + address, std::move(split_callback.first)); + break; + } + if (should_broker && connect_rv != net::ERR_IO_PENDING) { + std::move(split_callback.second).Run(connect_rv); + } + return connect_rv; +} + +net::handles::NetworkHandle BrokeredUdpClientSocket::GetBoundNetwork() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!socket_) { + return net::handles::kInvalidNetworkHandle; + } + return socket_->GetBoundNetwork(); +} + +void BrokeredUdpClientSocket::ApplySocketTag(const net::SocketTag& tag) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (socket_) { + socket_->ApplySocketTag(tag); + } + tag_ = tag; +} + +int BrokeredUdpClientSocket::Read(net::IOBuffer* buf, + int buf_len, + net::CompletionOnceCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!socket_) { + return net::ERR_SOCKET_NOT_CONNECTED; + } + return socket_->Read(buf, buf_len, std::move(callback)); +} + +int BrokeredUdpClientSocket::Write( + net::IOBuffer* buf, + int buf_len, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& traffic_annotation) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!socket_) { + return net::ERR_SOCKET_NOT_CONNECTED; + } + return socket_->Write(buf, buf_len, std::move(callback), traffic_annotation); +} + +void BrokeredUdpClientSocket::Close() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + socket_.reset(); + brokered_weak_ptr_factory_.InvalidateWeakPtrs(); +} + +int BrokeredUdpClientSocket::GetPeerAddress(net::IPEndPoint* address) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!socket_) { + return net::ERR_SOCKET_NOT_CONNECTED; + } + return socket_->GetPeerAddress(address); +} + +int BrokeredUdpClientSocket::GetLocalAddress(net::IPEndPoint* address) const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!socket_) { + return net::ERR_SOCKET_NOT_CONNECTED; + } + return socket_->GetLocalAddress(address); +} + +int BrokeredUdpClientSocket::SetReceiveBufferSize(int32_t size) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(socket_); + return socket_->SetReceiveBufferSize(size); +} + +int BrokeredUdpClientSocket::SetSendBufferSize(int32_t size) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(socket_); + return socket_->SetSendBufferSize(size); +} + +int BrokeredUdpClientSocket::SetDoNotFragment() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(socket_); + return socket_->SetDoNotFragment(); +} + +void BrokeredUdpClientSocket::SetMsgConfirm(bool confirm) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + set_msg_confirm_ = confirm; +} + +const net::NetLogWithSource& BrokeredUdpClientSocket::NetLog() const { + return net_log_source_; +} + +void BrokeredUdpClientSocket::UseNonBlockingIO() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + use_non_blocking_io_ = true; +} + +int BrokeredUdpClientSocket::SetMulticastInterface(uint32_t interface_index) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!socket_) { + interface_index_ = interface_index; + return net::OK; + } + return socket_->SetMulticastInterface(interface_index); +} + +void BrokeredUdpClientSocket::EnableRecvOptimization() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + recv_optimization_ = true; +} + +void BrokeredUdpClientSocket::SetIOSNetworkServiceType( + int ios_network_service_type) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + socket_->SetIOSNetworkServiceType(ios_network_service_type); +} + +} // namespace network
diff --git a/services/network/brokered_udp_client_socket.h b/services/network/brokered_udp_client_socket.h new file mode 100644 index 0000000..9fc0769f --- /dev/null +++ b/services/network/brokered_udp_client_socket.h
@@ -0,0 +1,180 @@ +// 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 SERVICES_NETWORK_BROKERED_UDP_CLIENT_SOCKET_H_ +#define SERVICES_NETWORK_BROKERED_UDP_CLIENT_SOCKET_H_ + +#include <stdint.h> + +#include "base/component_export.h" +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "build/build_config.h" +#include "mojo/public/cpp/platform/platform_handle.h" +#include "net/base/completion_once_callback.h" +#include "net/base/network_handle.h" +#include "net/log/net_log_source.h" +#include "net/nqe/network_quality_estimator.h" +#include "net/socket/datagram_client_socket.h" +#include "net/socket/datagram_socket.h" +#include "net/socket/socket_tag.h" +#include "net/socket/stream_socket.h" +#include "net/socket/udp_client_socket.h" +#include "net/socket/udp_socket.h" +#include "net/socket/udp_socket_global_limits.h" + +#if BUILDFLAG(IS_WIN) +#include "services/network/broker_helper_win.h" +#endif + +namespace net { +class IOBuffer; +class IPEndPoint; +class NetLog; +} // namespace net + +namespace network { + +class BrokeredClientSocketFactory; +class TransferableSocket; + +enum WhichConnect { + CONNECT, + CONNECT_USING_NETWORK, + CONNECT_USING_DEFAULT_NETWORK, +}; + +// A client socket used exclusively with a socket broker. Currently intended for +// Windows and Android only. Not intended to be used by non-brokered +// connections. Generally, all calls pass through to an underlying +// TCPClientSocket API, but Bind and Connect are the sent to a privileged +// process using the net:SocketBroker interface. This is because socket creation +// needs to be brokered, and TCPClientSocket only creates and opens a socket +// within Bind and Connect. +class COMPONENT_EXPORT(NETWORK_SERVICE) BrokeredUdpClientSocket + : public net::DatagramClientSocket { + public: + BrokeredUdpClientSocket(net::DatagramSocket::BindType bind_type, + net::NetLog* net_log, + const net::NetLogSource& source, + BrokeredClientSocketFactory* client_socket_factory, + net::handles::NetworkHandle network = + net::handles::kInvalidNetworkHandle); + + ~BrokeredUdpClientSocket() override; + + BrokeredUdpClientSocket(const BrokeredUdpClientSocket&) = delete; + BrokeredUdpClientSocket& operator=(const BrokeredUdpClientSocket&) = delete; + + // DatagramClientSocket implementation. + int Connect(const net::IPEndPoint& address) override; + int ConnectUsingNetwork(net::handles::NetworkHandle network, + const net::IPEndPoint& address) override; + int ConnectUsingDefaultNetwork(const net::IPEndPoint& address) override; + int ConnectAsync(const net::IPEndPoint& address, + net::CompletionOnceCallback callback) override; + int ConnectUsingNetworkAsync(net::handles::NetworkHandle network, + const net::IPEndPoint& address, + net::CompletionOnceCallback callback) override; + int ConnectUsingDefaultNetworkAsync( + const net::IPEndPoint& address, + net::CompletionOnceCallback callback) override; + net::handles::NetworkHandle GetBoundNetwork() const override; + void ApplySocketTag(const net::SocketTag& tag) override; + void EnableRecvOptimization() override; + int SetMulticastInterface(uint32_t interface_index) override; + void SetIOSNetworkServiceType(int ios_network_service_type) override; + + // DatagramSocket implementation. + void Close() override; + int GetPeerAddress(net::IPEndPoint* address) const override; + int GetLocalAddress(net::IPEndPoint* address) const override; + // Switch to use non-blocking IO. Must be called right after construction and + // before other calls. + void UseNonBlockingIO() override; + int SetReceiveBufferSize(int32_t size) override; + int SetSendBufferSize(int32_t size) override; + int SetDoNotFragment() override; + void SetMsgConfirm(bool confirm) override; + const net::NetLogWithSource& NetLog() const override; + + // Socket implementation. + int Read(net::IOBuffer* buf, + int buf_len, + net::CompletionOnceCallback callback) override; + int Write( + net::IOBuffer* buf, + int buf_len, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& traffic_annotation) override; + + uint32_t get_multicast_interface_for_testing() { + return socket_->get_multicast_interface_for_testing(); + } +#if !BUILDFLAG(IS_WIN) + bool get_msg_confirm_for_testing() { + return socket_->get_msg_confirm_for_testing(); + } + bool get_recv_optimization_for_testing() { + return socket_->get_recv_optimization_for_testing(); + } +#endif +#if BUILDFLAG(IS_WIN) + bool get_use_non_blocking_io_for_testing() { + return socket_->get_use_non_blocking_io_for_testing(); + } +#endif + + private: + // On Windows, this method determines if a Connection needs to be brokered. + // Directly creates a new `socket_` if brokering is not required, calls + // `BrokerCreateUdpSocket` if it is. + int ConnectAsyncInternal(const net::IPEndPoint& address, + WhichConnect which_connect, + net::handles::NetworkHandle network, + net::CompletionOnceCallback callback); + // Returns a net error result upon opening and connecting `socket_`. If a + // connection needs to be brokered, the return value is ignored as callback is + // run with the return value instead. + int DidCompleteCreate(bool should_broker, + const net::IPEndPoint& address, + WhichConnect which_connect, + net::handles::NetworkHandle network, + net::CompletionOnceCallback callback, + network::TransferableSocket socket, + int result); + + net::DatagramSocket::BindType bind_type_; + net::handles::NetworkHandle network_; + net::NetLogWithSource net_log_source_; + // Need to store the tag in case ApplySocketTag() is called before Connect(). + net::SocketTag tag_; + uint32_t interface_index_ = 0; + bool use_non_blocking_io_ = false; + bool set_msg_confirm_ = false; + bool connect_called_ = false; + bool recv_optimization_ = false; + + // The underlying brokered socket. Created when the socket is created for + // Connect(). + std::unique_ptr<net::UDPClientSocket> socket_; + + // The ClientSocketFactory that created this socket. Used to send IPCs to the + // remote SocketBroker. + const raw_ptr<BrokeredClientSocketFactory> client_socket_factory_; + +#if BUILDFLAG(IS_WIN) + BrokerHelperWin broker_helper_; +#endif + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<BrokeredUdpClientSocket> brokered_weak_ptr_factory_{ + this}; +}; + +} // namespace network + +#endif // SERVICES_NETWORK_BROKERED_UDP_CLIENT_SOCKET_H_
diff --git a/services/network/brokered_udp_client_socket_unittest.cc b/services/network/brokered_udp_client_socket_unittest.cc new file mode 100644 index 0000000..847137d --- /dev/null +++ b/services/network/brokered_udp_client_socket_unittest.cc
@@ -0,0 +1,365 @@ +// 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 "services/network/brokered_udp_client_socket.h" + +#include "base/test/bind.h" +#include "base/test/scoped_run_loop_timeout.h" +#include "base/test/task_environment.h" +#include "build/build_config.h" +#include "net/base/completion_repeating_callback.h" +#include "net/base/io_buffer.h" +#include "net/base/ip_address.h" +#include "net/base/ip_endpoint.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/log/net_log_source.h" +#include "net/nqe/network_quality_estimator_test_util.h" +#include "net/socket/socket_tag.h" +#include "net/socket/socket_test_util.h" +#include "net/socket/udp_server_socket.h" +#include "net/test/gtest_util.h" +#include "net/test/test_with_task_environment.h" +#include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "services/network/brokered_client_socket_factory.h" +#include "services/network/test/test_socket_broker_impl.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if BUILDFLAG(IS_ANDROID) +#include "net/android/network_change_notifier_factory_android.h" +#include "net/base/network_change_notifier.h" +#endif + +using net::test::IsError; +using net::test::IsOk; +using testing::Not; + +namespace network { + +// This class's only purpose is to return a BrokeredUdpClientSocket instead of a +// DatagramClientSocket. This is necessary as BrokeredUdpClientSocket has +// specific helper methods for unit tests that DatagramclientSocket does not +// need. +class TestBrokeredClientSocketFactory : public BrokeredClientSocketFactory { + public: + explicit TestBrokeredClientSocketFactory( + mojo::PendingRemote<mojom::SocketBroker> pending_remote) + : BrokeredClientSocketFactory(std::move(pending_remote)) {} + + std::unique_ptr<BrokeredUdpClientSocket> CreateBrokeredUdpClientSocket( + net::DatagramSocket::BindType bind_type, + net::NetLog* net_log, + const net::NetLogSource& source) { + return std::make_unique<BrokeredUdpClientSocket>(bind_type, net_log, source, + this); + } +}; + +class BrokeredUdpClientSocketTest : public testing::Test, + public net::WithTaskEnvironment { + public: + BrokeredUdpClientSocketTest() + : receiver_(&socket_broker_impl_), + client_socket_factory_(TestBrokeredClientSocketFactory( + receiver_.BindNewPipeAndPassRemote())), + buffer_(base::MakeRefCounted<net::IOBufferWithSize>(kMaxRead)) {} + + ~BrokeredUdpClientSocketTest() override = default; + + void SetUp() override { + // Set up the socket_ + socket_ = client_socket_factory_.CreateBrokeredUdpClientSocket( + net::DatagramSocket::DEFAULT_BIND, net::NetLog::Get(), + net::NetLogSource()); + + // Confirm that we fail gracefully when making certain calls before + // connecting. + net::IPEndPoint test_address; + EXPECT_EQ(socket_->GetPeerAddress(&test_address), + net::ERR_SOCKET_NOT_CONNECTED); + EXPECT_EQ(socket_->GetLocalAddress(&test_address), + net::ERR_SOCKET_NOT_CONNECTED); + } + + // Writes specified message to the socket. + int WriteToClientSocket(const std::string& msg) { + scoped_refptr<net::StringIOBuffer> io_buffer = + base::MakeRefCounted<net::StringIOBuffer>(msg); + net::TestCompletionCallback callback; + int rv = socket_->Write(io_buffer.get(), io_buffer->size(), + callback.callback(), TRAFFIC_ANNOTATION_FOR_TESTS); + return callback.GetResult(rv); + } + + std::string ReadFromClientSocket() { + net::TestCompletionCallback callback; + + int rv = socket_->Read(buffer_.get(), kMaxRead, callback.callback()); + rv = callback.GetResult(rv); + if (rv < 0) { + return std::string(); + } + return std::string(buffer_->data(), rv); + } + + int SendToSocket(net::UDPServerSocket* socket, + std::string msg, + const net::IPEndPoint& address) { + auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(msg); + net::TestCompletionCallback callback; + int rv = socket->SendTo(io_buffer.get(), io_buffer->size(), address, + callback.callback()); + return callback.GetResult(rv); + } + + // Blocks until data is read from the socket. + std::string RecvFromSocket(net::UDPServerSocket* socket, + net::IPEndPoint& address) { + net::TestCompletionCallback callback; + int rv = socket->RecvFrom(buffer_.get(), kMaxRead, &address, + callback.callback()); + rv = callback.GetResult(rv); + if (rv < 0) { + return std::string(); + } + return std::string(buffer_->data(), rv); + } + + void SimpleReadAndWrite(net::UDPServerSocket* server) { + std::string simple_message("hello world!"); + int rv = WriteToClientSocket(simple_message); + net::IPEndPoint address; + EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); + // Server waits for message. + std::string str = RecvFromSocket(server, address); + EXPECT_EQ(simple_message, str); + // Server echoes reply. + rv = SendToSocket(server, simple_message, address); + EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); + // Client waits for response. + str = ReadFromClientSocket(); + EXPECT_EQ(simple_message, str); + } + + protected: + std::unique_ptr<BrokeredUdpClientSocket> socket_; + mojo::Receiver<mojom::SocketBroker> receiver_; + TestBrokeredClientSocketFactory client_socket_factory_; + scoped_refptr<net::IOBufferWithSize> buffer_; + static const int kMaxRead = 1024; + + TestSocketBrokerImpl socket_broker_impl_; +}; + +const int BrokeredUdpClientSocketTest::kMaxRead; + +TEST_F(BrokeredUdpClientSocketTest, FailedConnect) { + net::TestCompletionCallback callback; + base::test::ScopedDisableRunLoopTimeout disable_timeout; + net::IPEndPoint server_address(net::IPAddress::IPv4Localhost(), + 8080 /* port */); + + socket_broker_impl_.SetConnectionFailure(true); + + int rv = socket_->ConnectAsync(server_address, callback.callback()); + + ASSERT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(rv, net::ERR_CONNECTION_FAILED); +} + +TEST_F(BrokeredUdpClientSocketTest, Connect) { + ASSERT_EQ(0, net::GetGlobalUDPSocketCountForTesting()); + net::TestCompletionCallback callback; + net::IPEndPoint server_address(net::IPAddress::IPv4Localhost(), + 8080 /* port */); + + int rv = socket_->ConnectAsync(server_address, callback.callback()); + + ASSERT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(rv, net::OK); + EXPECT_EQ(net::handles::kInvalidNetworkHandle, socket_->GetBoundNetwork()); + ASSERT_EQ(1, net::GetGlobalUDPSocketCountForTesting()); + socket_->Close(); + ASSERT_EQ(0, net::GetGlobalUDPSocketCountForTesting()); +} + +TEST_F(BrokeredUdpClientSocketTest, SetOptions) { + net::TestCompletionCallback callback; + net::IPEndPoint server_address(net::IPAddress::IPv4Localhost(), + 8080 /* port */); + EXPECT_THAT(socket_->SetMulticastInterface(1), IsOk()); + socket_->SetMsgConfirm(true); + socket_->EnableRecvOptimization(); + socket_->UseNonBlockingIO(); + int rv = socket_->ConnectAsync(server_address, callback.callback()); + + ASSERT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(rv, net::OK); + + EXPECT_EQ(socket_->get_multicast_interface_for_testing(), uint32_t(1)); +#if (!BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_WIN)) + EXPECT_TRUE(socket_->get_msg_confirm_for_testing()); +#endif +#if BUILDFLAG(IS_POSIX) + EXPECT_TRUE(socket_->get_recv_optimization_for_testing()); +#endif +#if BUILDFLAG(IS_WIN) + EXPECT_TRUE(socket_->get_use_non_blocking_io_for_testing()); + + // Set up a new socket to check that options are set correctly when sockets + // don't need to be brokered on win. + auto new_socket = client_socket_factory_.CreateBrokeredUdpClientSocket( + net::DatagramSocket::DEFAULT_BIND, net::NetLog::Get(), + net::NetLogSource()); + + net::TestCompletionCallback callback2; + net::IPEndPoint server_address2(net::IPAddress::IPv4AllZeros(), + 8080 /* port */); + EXPECT_THAT(new_socket->SetMulticastInterface(1), IsOk()); + new_socket->UseNonBlockingIO(); + rv = new_socket->ConnectAsync(server_address2, callback2.callback()); + + // `new_socket` shouldn't successfully connect since the address is invalid, + // but the options should still be set. + EXPECT_EQ(rv, net::ERR_ADDRESS_INVALID); + EXPECT_EQ(new_socket->get_multicast_interface_for_testing(), uint32_t(1)); + EXPECT_TRUE(new_socket->get_use_non_blocking_io_for_testing()); +#endif +} + +TEST_F(BrokeredUdpClientSocketTest, SimpleReadWrite) { + net::TestCompletionCallback callback; + net::UDPServerSocket server(nullptr, net::NetLogSource()); + ASSERT_THAT( + server.Listen(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0)), + IsOk()); + net::IPEndPoint server_address; + ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk()); + + int rv = socket_->ConnectAsync(server_address, callback.callback()); + + ASSERT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(rv, net::OK); + + SimpleReadAndWrite(&server); +} + +TEST_F(BrokeredUdpClientSocketTest, ConnectUsingNetwork) { + // The specific value of this address doesn't really matter, and no + // server needs to be running here. The test only needs to call + // ConnectUsingNetworkAsync() and won't send any datagrams. + net::IPEndPoint server_address(net::IPAddress::IPv4Localhost(), + 8080 /* port */); + const net::handles::NetworkHandle wrong_network_handle = 65536; + net::TestCompletionCallback callback; +#if BUILDFLAG(IS_ANDROID) + net::NetworkChangeNotifierFactoryAndroid ncn_factory; + net::NetworkChangeNotifierDelegateAndroid:: + EnableNetworkChangeNotifierAutoDetectForTest(); + std::unique_ptr<net::NetworkChangeNotifier> ncn(ncn_factory.CreateInstance()); + if (!net::NetworkChangeNotifier::AreNetworkHandlesSupported()) { + GTEST_SKIP() << "Network handles are required to test BindToNetwork."; + } + + { + // Connecting using a not existing network should fail but not report + // ERR_NOT_IMPLEMENTED when network handles are supported. + auto socket = client_socket_factory_.CreateDatagramClientSocket( + net::DatagramSocket::DEFAULT_BIND, net::NetLog::Get(), + net::NetLogSource()); + int rv = socket->ConnectUsingNetworkAsync( + wrong_network_handle, server_address, callback.callback()); + EXPECT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_NE(net::ERR_NOT_IMPLEMENTED, rv); + EXPECT_NE(net::OK, rv); + } + + { + // Connecting using an existing network should succeed when + // NetworkChangeNotifier returns a valid default network. + const net::handles::NetworkHandle network_handle = + net::NetworkChangeNotifier::GetDefaultNetwork(); + if (network_handle != net::handles::kInvalidNetworkHandle) { + auto socket2 = client_socket_factory_.CreateDatagramClientSocket( + net::DatagramSocket::DEFAULT_BIND, net::NetLog::Get(), + net::NetLogSource()); + int rv = socket2->ConnectUsingNetworkAsync(network_handle, server_address, + callback.callback()); + EXPECT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + EXPECT_EQ(network_handle, socket2->GetBoundNetwork()); + // Also check that connecting using the default network succeeds with a + // valid default network. + auto socket3 = client_socket_factory_.CreateDatagramClientSocket( + net::DatagramSocket::DEFAULT_BIND, net::NetLog::Get(), + net::NetLogSource()); + rv = socket3->ConnectUsingDefaultNetworkAsync(server_address, + callback.callback()); + EXPECT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(net::OK, rv); + EXPECT_EQ(network_handle, socket3->GetBoundNetwork()); + } + } +#else + EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, + socket_->ConnectUsingNetworkAsync( + wrong_network_handle, server_address, callback.callback())); + auto socket2 = client_socket_factory_.CreateDatagramClientSocket( + net::DatagramSocket::DEFAULT_BIND, net::NetLog::Get(), + net::NetLogSource()); + EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, socket2->ConnectUsingDefaultNetworkAsync( + server_address, callback.callback())); +#endif // BUILDFLAG(IS_ANDROID) +} + +// On Android, where socket tagging is supported, verify that the +// BrokeredUdpClientSocket sets tags correctly. +#if BUILDFLAG(IS_ANDROID) +TEST_F(BrokeredUdpClientSocketTest, Tag) { + if (!net::CanGetTaggedBytes()) { + DVLOG(0) << "Skipping test - GetTaggedBytes unsupported."; + return; + } + + net::TestCompletionCallback callback; + net::UDPServerSocket server(nullptr, net::NetLogSource()); + ASSERT_THAT( + server.Listen(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0)), + IsOk()); + net::IPEndPoint server_address; + ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk()); + + // Verify tag is properly set when ApplySocketTag is called before connecting. + int32_t tag_val1 = 0x12345678; + uint64_t old_traffic = net::GetTaggedBytes(tag_val1); + net::SocketTag tag1(net::SocketTag::UNSET_UID, tag_val1); + socket_->ApplySocketTag(tag1); + int rv = socket_->ConnectAsync(server_address, callback.callback()); + + ASSERT_EQ(rv, net::ERR_IO_PENDING); + rv = callback.WaitForResult(); + EXPECT_EQ(rv, net::OK); + SimpleReadAndWrite(&server); + EXPECT_GT(net::GetTaggedBytes(tag_val1), old_traffic); + + // Verify socket can be retagged with a new value and the current process's + // UID. + int32_t tag_val2 = 0x87654321; + old_traffic = net::GetTaggedBytes(tag_val2); + net::SocketTag tag2(getuid(), tag_val2); + socket_->ApplySocketTag(tag2); + SimpleReadAndWrite(&server); + EXPECT_GT(net::GetTaggedBytes(tag_val2), old_traffic); +} +#endif + +} // namespace network
diff --git a/services/network/tcp_client_socket_brokered_unittest.cc b/services/network/tcp_client_socket_brokered_unittest.cc index 5d69ff4..eccf574 100644 --- a/services/network/tcp_client_socket_brokered_unittest.cc +++ b/services/network/tcp_client_socket_brokered_unittest.cc
@@ -114,7 +114,7 @@ net::TestCompletionCallback callback; base::test::ScopedDisableRunLoopTimeout disable_timeout; - socket_broker_impl_.SetMockSocketTest(true); + socket_broker_impl_.SetConnectionFailure(true); int result = socket_->Connect(callback.callback());
diff --git a/services/network/test/test_socket_broker_impl.cc b/services/network/test/test_socket_broker_impl.cc index 406cd05..d1769f5a 100644 --- a/services/network/test/test_socket_broker_impl.cc +++ b/services/network/test/test_socket_broker_impl.cc
@@ -60,7 +60,7 @@ void TestSocketBrokerImpl::CreateTcpSocket(net::AddressFamily address_family, CreateTcpSocketCallback callback) { - if (is_mock_socket_test_) { + if (connection_failure_) { std::move(callback).Run(network::TransferableSocket(), net::ERR_CONNECTION_FAILED); return; @@ -87,7 +87,7 @@ void TestSocketBrokerImpl::CreateUdpSocket(net::AddressFamily address_family, CreateUdpSocketCallback callback) { - if (is_mock_socket_test_) { + if (connection_failure_) { std::move(callback).Run(network::TransferableSocket(), net::ERR_CONNECTION_FAILED); return;
diff --git a/services/network/test/test_socket_broker_impl.h b/services/network/test/test_socket_broker_impl.h index 5db6d06e..314758c6 100644 --- a/services/network/test/test_socket_broker_impl.h +++ b/services/network/test/test_socket_broker_impl.h
@@ -28,8 +28,9 @@ void CreateUdpSocket(net::AddressFamily address_family, CreateUdpSocketCallback callback) override; - void SetMockSocketTest(bool is_mock_socket_test) { - is_mock_socket_test_ = is_mock_socket_test; + // Used to set whether a test connection should fail. + void SetConnectionFailure(bool connection_failure) { + connection_failure_ = connection_failure; } private: @@ -37,7 +38,7 @@ // When true, CreateTcpSocket returns ERR_CONNECTION_FAILED to test a failed // connection. - bool is_mock_socket_test_ = false; + bool connection_failure_ = false; }; } // namespace network
diff --git a/testing/buildbot/chromium.cft.json b/testing/buildbot/chromium.cft.json index 71bdf41b..a264ac1f 100644 --- a/testing/buildbot/chromium.cft.json +++ b/testing/buildbot/chromium.cft.json
@@ -1,6 +1,2247 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, + "linux-arm64-rel-cft": { + "additional_compile_targets": [ + "all" + ], + "gtest_tests": [ + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "absl_hardening_tests", + "test_id_prefix": "ninja://third_party/abseil-cpp:absl_hardening_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "accessibility_unittests", + "test_id_prefix": "ninja://ui/accessibility:accessibility_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "angle_unittests", + "test_id_prefix": "ninja://third_party/angle/src/tests:angle_unittests/", + "use_isolated_scripts_api": true + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "app_shell_unittests", + "test_id_prefix": "ninja://extensions/shell:app_shell_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "aura_unittests", + "test_id_prefix": "ninja://ui/aura:aura_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "base_unittests", + "test_id_prefix": "ninja://base:base_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_common_unittests", + "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_fuzzer_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_fuzzer_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_heap_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform/heap:blink_heap_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_platform_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform:blink_platform_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "webkit_unit_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/controller:blink_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "boringssl_crypto_tests", + "test_id_prefix": "ninja://third_party/boringssl:boringssl_crypto_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "boringssl_ssl_tests", + "test_id_prefix": "ninja://third_party/boringssl:boringssl_ssl_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.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*" + ], + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "capture_unittests", + "test_id_prefix": "ninja://media/capture:capture_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "cast_unittests", + "test_id_prefix": "ninja://media/cast:cast_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "cc_unittests", + "test_id_prefix": "ninja://cc:cc_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "chrome_app_unittests", + "test_id_prefix": "ninja://chrome/test:chrome_app_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "chromedriver_unittests", + "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "color_unittests", + "test_id_prefix": "ninja://ui/color:color_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "components_browsertests", + "test_id_prefix": "ninja://components:components_browsertests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "components_unittests", + "test_id_prefix": "ninja://components:components_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "compositor_unittests", + "test_id_prefix": "ninja://ui/compositor:compositor_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test": "content_browsertests", + "test_id_prefix": "ninja://content/test:content_browsertests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "content_unittests", + "test_id_prefix": "ninja://content/test:content_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "crashpad_tests", + "test_id_prefix": "ninja://third_party/crashpad/crashpad:crashpad_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "cronet_tests", + "test_id_prefix": "ninja://components/cronet:cronet_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "cronet_unittests", + "test_id_prefix": "ninja://components/cronet:cronet_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "crypto_unittests", + "test_id_prefix": "ninja://crypto:crypto_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "dbus_unittests", + "test_id_prefix": "ninja://dbus:dbus_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "device_unittests", + "test_id_prefix": "ninja://device:device_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "display_unittests", + "test_id_prefix": "ninja://ui/display:display_unittests/" + }, + { + "ci_only": true, + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "env_chromium_unittests", + "test_id_prefix": "ninja://third_party/leveldatabase:env_chromium_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "events_unittests", + "test_id_prefix": "ninja://ui/events:events_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "extensions_browsertests", + "test_id_prefix": "ninja://extensions:extensions_browsertests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "extensions_unittests", + "test_id_prefix": "ninja://extensions:extensions_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "filesystem_service_unittests", + "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gcm_unit_tests", + "test_id_prefix": "ninja://google_apis/gcm:gcm_unit_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gfx_unittests", + "test_id_prefix": "ninja://ui/gfx:gfx_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gin_unittests", + "test_id_prefix": "ninja://gin:gin_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "google_apis_unittests", + "test_id_prefix": "ninja://google_apis:google_apis_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gpu_unittests", + "test_id_prefix": "ninja://gpu:gpu_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "gwp_asan_unittests", + "test_id_prefix": "ninja://components/gwp_asan:gwp_asan_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "headless_browsertests", + "test_id_prefix": "ninja://headless:headless_browsertests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "headless_unittests", + "test_id_prefix": "ninja://headless:headless_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "interactive_ui_tests", + "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ipc_tests", + "test_id_prefix": "ninja://ipc:ipc_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "latency_unittests", + "test_id_prefix": "ninja://ui/latency:latency_unittests/" + }, + { + "ci_only": true, + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "leveldb_unittests", + "test_id_prefix": "ninja://third_party/leveldatabase:leveldb_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "libjingle_xmpp_unittests", + "test_id_prefix": "ninja://third_party/libjingle_xmpp:libjingle_xmpp_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "liburlpattern_unittests", + "test_id_prefix": "ninja://third_party/liburlpattern:liburlpattern_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "media_unittests", + "test_id_prefix": "ninja://media:media_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "message_center_unittests", + "test_id_prefix": "ninja://ui/message_center:message_center_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "midi_unittests", + "test_id_prefix": "ninja://media/midi:midi_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "mojo_unittests", + "test_id_prefix": "ninja://mojo:mojo_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "nacl_loader_unittests", + "test_id_prefix": "ninja://components/nacl/loader:nacl_loader_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "native_theme_unittests", + "test_id_prefix": "ninja://ui/native_theme:native_theme_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "net_unittests", + "test_id_prefix": "ninja://net:net_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "openscreen_unittests", + "test_id_prefix": "ninja://chrome/browser/media/router:openscreen_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ozone_unittests", + "test_id_prefix": "ninja://ui/ozone:ozone_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ozone_x11_unittests", + "test_id_prefix": "ninja://ui/ozone:ozone_x11_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "pdf_unittests", + "test_id_prefix": "ninja://pdf:pdf_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "perfetto_unittests", + "test_id_prefix": "ninja://third_party/perfetto:perfetto_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ppapi_unittests", + "test_id_prefix": "ninja://ppapi:ppapi_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "printing_unittests", + "test_id_prefix": "ninja://printing:printing_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "remoting_unittests", + "test_id_prefix": "ninja://remoting:remoting_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "sandbox_linux_unittests", + "test_id_prefix": "ninja://sandbox/linux:sandbox_linux_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "service_manager_unittests", + "test_id_prefix": "ninja://services/service_manager/tests:service_manager_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "services_unittests", + "test_id_prefix": "ninja://services:services_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "shell_dialogs_unittests", + "test_id_prefix": "ninja://ui/shell_dialogs:shell_dialogs_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "skia_unittests", + "test_id_prefix": "ninja://skia:skia_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "snapshot_unittests", + "test_id_prefix": "ninja://ui/snapshot:snapshot_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "sql_unittests", + "test_id_prefix": "ninja://sql:sql_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "storage_unittests", + "test_id_prefix": "ninja://storage:storage_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test": "sync_integration_tests", + "test_id_prefix": "ninja://chrome/test:sync_integration_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ui_base_unittests", + "test_id_prefix": "ninja://ui/base:ui_base_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "ui_touch_selection_unittests", + "test_id_prefix": "ninja://ui/touch_selection:ui_touch_selection_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "unit_tests", + "test_id_prefix": "ninja://chrome/test:unit_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "url_unittests", + "test_id_prefix": "ninja://url:url_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "views_unittests", + "test_id_prefix": "ninja://ui/views:views_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "viz_unittests", + "test_id_prefix": "ninja://components/viz:viz_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "vr_common_unittests", + "test_id_prefix": "ninja://chrome/browser/vr:vr_common_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "wm_unittests", + "test_id_prefix": "ninja://ui/wm:wm_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "wtf_unittests", + "test_id_prefix": "ninja://third_party/blink/renderer/platform/wtf:wtf_unittests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "xr_browser_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "xr_browser_tests", + "test_id_prefix": "ninja://chrome/test:xr_browser_tests/" + }, + { + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "zlib_unittests", + "test_id_prefix": "ninja://third_party/zlib:zlib_unittests/" + } + ], + "isolated_scripts": [ + { + "isolate_name": "blink_python_tests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "blink_python_tests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://:blink_python_tests/" + }, + { + "isolate_name": "blink_pytype", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "blink_pytype", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/blink/tools:blink_pytype/" + }, + { + "args": [ + "--num-retries=3", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_web_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "blink_web_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 5 + }, + "test_id_prefix": "ninja://:blink_web_tests/" + }, + { + "args": [ + "--num-retries=3", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_wpt_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "blink_wpt_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 7 + }, + "test_id_prefix": "ninja://:blink_wpt_tests/" + }, + { + "args": [ + "--test-type=integration" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "chromedriver_py_tests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "chromedriver_py_tests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_py_tests/" + }, + { + "isolate_name": "chromedriver_replay_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "chromedriver_replay_unittests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test/chromedriver:chromedriver_replay_unittests/" + }, + { + "isolate_name": "content_shell_crash_test", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "content_shell_crash_test", + "resultdb": { + "enable": true, + "result_format": "single" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://content/shell:content_shell_crash_test/" + }, + { + "isolate_name": "flatbuffers_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "flatbuffers_unittests", + "resultdb": { + "enable": true, + "result_format": "single" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://third_party/flatbuffers:flatbuffers_unittests/" + }, + { + "isolate_name": "fuchsia_pytype", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "fuchsia_pytype", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://testing:fuchsia_pytype/" + }, + { + "isolate_name": "gold_common_pytype", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gold_common_pytype", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://build:gold_common_pytype/" + }, + { + "isolate_name": "gpu_pytype", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "gpu_pytype", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://content/test:gpu_pytype/" + }, + { + "isolate_name": "grit_python_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "grit_python_unittests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://tools/grit:grit_python_unittests/" + }, + { + "args": [ + "--flag-specific=highdpi", + "--skipped=always", + "--num-retries=3", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_web_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "high_dpi_blink_web_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://:blink_web_tests/" + }, + { + "args": [ + "--flag-specific=highdpi", + "--skipped=always", + "--num-retries=3", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_wpt_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "high_dpi_blink_wpt_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 3 + }, + "test_id_prefix": "ninja://:blink_wpt_tests/" + }, + { + "isolate_name": "mojo_python_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "mojo_python_unittests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://mojo/public/tools:mojo_python_unittests/" + }, + { + "args": [ + "--flag-specific=disable-site-isolation-trials", + "--num-retries=3", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_web_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "not_site_per_process_blink_web_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://:blink_web_tests/" + }, + { + "args": [ + "--flag-specific=disable-site-isolation-trials", + "--num-retries=3", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_wpt_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "not_site_per_process_blink_wpt_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 10 + }, + "test_id_prefix": "ninja://:blink_wpt_tests/" + }, + { + "isolate_name": "telemetry_gpu_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "telemetry_gpu_unittests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://chrome/test:telemetry_gpu_unittests/" + }, + { + "args": [ + "--extra-browser-args=--enable-crashpad" + ], + "isolate_name": "telemetry_perf_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "telemetry_perf_unittests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_perf_unittests/" + }, + { + "args": [ + "--jobs=1", + "--extra-browser-args=--disable-gpu" + ], + "isolate_name": "telemetry_unittests", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "telemetry_unittests", + "resultdb": { + "enable": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "idempotent": false, + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://chrome/test:telemetry_unittests/" + }, + { + "isolate_name": "testing_pytype", + "isolate_profile_data": true, + "merge": { + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "testing_pytype", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://testing:testing_pytype/" + }, + { + "args": [ + "--gtest-benchmark-name=views_perftests" + ], + "isolate_name": "views_perftests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--smoke-test-mode" + ], + "script": "//tools/perf/process_perf_results.py" + }, + "name": "views_perftests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://ui/views:views_perftests/" + }, + { + "args": [ + "--num-retries=3", + "--skipped=always", + "--flag-specific=skia-vulkan-swiftshader", + "--write-run-histories-to=${ISOLATED_OUTDIR}/run_histories.json" + ], + "check_flakiness_for_new_tests": false, + "isolate_name": "blink_web_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "vulkan_swiftshader_blink_web_tests", + "resultdb": { + "enable": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test_id_prefix": "ninja://:blink_web_tests/" + }, + { + "isolate_name": "webdriver_wpt_tests", + "isolate_profile_data": true, + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "webdriver_tests_suite", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 4 + }, + "test_id_prefix": "ninja://:webdriver_wpt_tests/" + } + ], + "scripts": [ + { + "isolate_profile_data": true, + "name": "check_network_annotations", + "script": "check_network_annotations.py", + "swarming": {} + }, + { + "isolate_profile_data": true, + "name": "check_static_initializers", + "script": "check_static_initializers.py", + "swarming": {} + }, + { + "isolate_profile_data": true, + "name": "checkdeps", + "script": "checkdeps.py", + "swarming": {} + }, + { + "isolate_profile_data": true, + "name": "checkperms", + "script": "checkperms.py", + "swarming": {} + }, + { + "isolate_profile_data": true, + "name": "headless_python_unittests", + "script": "headless_python_unittests.py", + "swarming": {} + }, + { + "isolate_profile_data": true, + "name": "metrics_python_tests", + "script": "metrics_python_tests.py", + "swarming": {} + }, + { + "isolate_profile_data": true, + "name": "webkit_lint", + "script": "blink_lint_expectations.py", + "swarming": {} + } + ] + }, "linux-rel-cft": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter index b16c86f..89f8bf9 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter
@@ -97,7 +97,9 @@ -TabDragging/DetachToBrowserTabDragControllerTest.DetachFromFullsizeWindow/0 -TabDragging/DetachToBrowserTabDragControllerTest.DetachFromFullsizeWindow/2 -TabDragging/DetachToBrowserTabDragControllerTest.DetachFromFullsizeWindow/3 +-TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/0 -TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/1 +-TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/2 -TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/3 -TabDragging/DetachToBrowserTabDragControllerTest.DragCollapsedGroupHeaderExpandsGroup/0 -TabDragging/DetachToBrowserTabDragControllerTest.DragCollapsedGroupHeaderExpandsGroup/2
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter index 4211c67..0c25ea7 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.beta.filter
@@ -3,10 +3,7 @@ # If you want to disable a test only for version skew testing, # you should add the test here, not in the source code. -# Can be enabled once this version skew variant uses Ash >= 114. --BookmarkBarViewTest10.KeyEvents --BookmarkBarViewTest20.ContextMenuExitTest --BookmarkBarViewTest27.MiddleClickOnFolderOpensAllBookmarks +# Can be enabled once this version skew variant uses Ash >= 114.0.5735.19. -MenuItemViewTestRemoveWithSubmenu0.RemoveItemWithSubmenu0 -TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/0 -TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/2
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.dev.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.dev.filter index 2c09970..0c25ea7 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.dev.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.dev.filter
@@ -3,7 +3,7 @@ # If you want to disable a test only for version skew testing, # you should add the test here, not in the source code. -# Can be enabled once this version skew variant uses Ash >= 114.0.5735.18. +# Can be enabled once this version skew variant uses Ash >= 114.0.5735.19. -MenuItemViewTestRemoveWithSubmenu0.RemoveItemWithSubmenu0 -TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/0 -TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/2
diff --git a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.stable.filter b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.stable.filter index 63f54f30..7b29850 100644 --- a/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.stable.filter +++ b/testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.stable.filter
@@ -3,127 +3,28 @@ # If you want to disable a test only for version skew testing, # you should add the test here, not in the source code. -# Can be enabled once this version skew variant uses Ash >= 114. +# Can be enabled once this version skew variant uses Ash >= 114.0.5735.19. -BookmarkBarViewTest10.KeyEvents -BookmarkBarViewTest20.ContextMenuExitTest -BookmarkBarViewTest27.MiddleClickOnFolderOpensAllBookmarks -MenuItemViewTestRemoveWithSubmenu0.RemoveItemWithSubmenu0 -TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/0 +-TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/2 -TabDragging/DetachToBrowserTabDragControllerTest.CaptureLostDuringDrag/0 -TabDragging/DetachToBrowserTabDragControllerTest.CaptureLostDuringDrag/2 -TabDragging/DetachToBrowserTabDragControllerTest.DeleteBeforeStartedDragging/0 -TabDragging/DetachToBrowserTabDragControllerTest.DeleteBeforeStartedDragging/2 -TabDragging/DetachToBrowserTabDragControllerTest.DeleteTabsWhileDetached/0 -TabDragging/DetachToBrowserTabDragControllerTest.DeleteTabsWhileDetached/2 +-TabDragging/DetachToBrowserTabDragControllerTest.DeleteTabWhileAttached/0 +-TabDragging/DetachToBrowserTabDragControllerTest.DeleteTabWhileAttached/2 +-TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindow/0 -TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindow/2 +-TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/0 -TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/2 -TabDragging/DetachToBrowserTabDragControllerTest.DragAll/0 -TabDragging/DetachToBrowserTabDragControllerTest.DragAll/2 --TabDragging/DetachToBrowserTabDragControllerTest.DragMultipleTabsLeftIntoGroup/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragPinnedTabDoesNotGroup/2 --TabDragging/DetachToBrowserTabDragControllerTest.DragSingleTabRightOfRightmostGroup/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragUngroupedTabGroupedTabOutsideGroup/0 -TabDragging/DetachToBrowserTabDragControllerTest.KeyPressShouldEndDragTest/0 -TabDragging/DetachToBrowserTabDragControllerTest.KeyPressShouldEndDragTest/2 - -### The following filters are the ones needed when using the weston-test -### protocol. They can be removed once this version skew variant uses the -### ui-controls protocol, i.e. uses Ash >= 113. - -# Drag and drop based interactive_ui_tests mostly don't work. This will be fixed -# by making a new ui control test protocol. -# https://crbug.com/1366264 -# https://crbug.com/1353089 --BookmarkBarViewTest22.CloseSourceBrowserDuringDrag --BookmarkBarViewTest5.DND --BookmarkBarViewTest7.DNDToDifferentMenu --BookmarkBarViewTest8.DNDBackToOriginatingMenu - -# Mouse clicks with modifier keys currently don't work. This will be fixed by -# making a new ui control test protocol. -# https://crbug.com/1352618 -# https://crbug.com/1353089 --BookmarkBarViewTest28.ClickWithModifierOnFolderOpensAllBookmarks - -# TODO(crbug.com/1111979) Enable all tests on lacros. --ChromeVisibilityObserverInteractiveTest.VisibilityTest --CrossSiteSubframe/DragAndDropBrowserTest.CrossSiteDrag/* --CrossSiteSubframe/DragAndDropBrowserTest.CrossTabDrag/* --CrossSiteSubframe/DragAndDropBrowserTest.DragCorsSameOriginImageBetweenFrames/* --CrossSiteSubframe/DragAndDropBrowserTest.DragCrossOriginImageBetweenFrames/* --CrossSiteSubframe/DragAndDropBrowserTest.DragSameOriginImageBetweenFrames/* --DesktopWidgetTestInteractive.DesktopNativeWidgetWithModalTransientChild --DesktopWindowTreeHostPlatformImplTest.CaptureEventForwarding --DesktopWindowTreeHostPlatformImplTest.InputMethodFocus --MenuViewDragAndDropTestNestedDrag.MenuViewDragAndDropNestedDrag --MenuViewDragAndDropTestTestInMenuDrag.TestInMenuDrag --OmniboxViewViewsTest.SelectionClipboard --SameSiteSubframe/DragAndDropBrowserTest.CrossSiteDrag/* --SameSiteSubframe/DragAndDropBrowserTest.CrossTabDrag/* --SameSiteSubframe/DragAndDropBrowserTest.DragCorsSameOriginImageBetweenFrames/* --SameSiteSubframe/DragAndDropBrowserTest.DragCrossOriginImageBetweenFrames/* --SameSiteSubframe/DragAndDropBrowserTest.DragSameOriginImageBetweenFrames/* - -# TODO(crbug.com/1195712): Implement the feature for Wayland. --GlobalCommandsApiTest.GlobalCommand -# TODO(crbug.com/1208111): Flaky test. --MenuControllerUITest.TestMouseOverShownMenu - -# TODO(b/181803566): Fix modifier key interactions --All/ActionCommandsApiTest.TriggeringCommandTriggersListener* --All/ActionCommandsApiTest.TriggeringCommandTriggersPopup* --CommandsApiTest.ChromeOSConversions --CommandsApiTest.DontOverwriteSystemShortcuts --CommandsApiTest.PageActionKeyUpdated --CommandsApiTest.UnpinnedPageActionTriggers --PrivacySandboxDialogViewInteractiveUiTest.EscapeClosesNotice - -# TODO(crbug.com/1336691) Most tab dragging tests are failing, or flaky, but a -# few consistently pass when run using touch interactions. --TabDragging/DetachToBrowserTabDragControllerTest.CancelOnNewTabWhenDragging/* --TabDragging/DetachToBrowserTabDragControllerTest.CaptureLostDuringDrag/* --TabDragging/DetachToBrowserTabDragControllerTest.DeleteBeforeStartedDragging/* --TabDragging/DetachToBrowserTabDragControllerTest.DeleteTabsWhileDetached/* --TabDragging/DetachToBrowserTabDragControllerTest.DeleteTabWhileAttached/* --TabDragging/DetachToBrowserTabDragControllerTest.DetachFromFullsizeWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DetachToOwnWindowFromMaximizedWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragAll/* --TabDragging/DetachToBrowserTabDragControllerTest.DragAllToSeparateWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragCollapsedGroupHeaderExpandsGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragDirectlyToSecondWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragDoesntStartFromClick/* --TabDragging/DetachToBrowserTabDragControllerTest.DragGroupHeaderDragsGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragGroupHeaderLeftAvoidsOtherGroups/* --TabDragging/DetachToBrowserTabDragControllerTest.DragGroupHeaderRightAvoidsOtherGroups/* --TabDragging/DetachToBrowserTabDragControllerTest.DragGroupHeaderToSeparateWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragInSameWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragLeftToUngroupTab/* --TabDragging/DetachToBrowserTabDragControllerTest.DragMultipleTabsLeftIntoGroup/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragMultipleTabsRightIntoGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragOnlyTabInGroupRemovesGroup/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragOnlyTabInGroupRemovesGroup/2 --TabDragging/DetachToBrowserTabDragControllerTest.DragPinnedTabDoesNotGroup/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragRightToUngroupTab/* --TabDragging/DetachToBrowserTabDragControllerTest.DragSingleTabLeftIntoGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragSingleTabRightIntoGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragSingleTabRightOfRightmostGroup/0 --TabDragging/DetachToBrowserTabDragControllerTest.DragSingleTabToSeparateWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragTabLeftPastCollapsedGroupHeader/* --TabDragging/DetachToBrowserTabDragControllerTest.DragTabRightPastCollapsedGroupHeader/* --TabDragging/DetachToBrowserTabDragControllerTest.DragTabWithinGroupDoesNotModifyGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragToSeparateWindow/* --TabDragging/DetachToBrowserTabDragControllerTest.DragWindowIntoGroup/* --TabDragging/DetachToBrowserTabDragControllerTest.DragWithMaskedWindows/* --TabDragging/DetachToBrowserTabDragControllerTest.OffsetForDraggingTab/* --TabDragging/DetachToBrowserTabDragControllerTest.Revert* --TabDragging/DetachToBrowserTabDragControllerTest.SelectTabDuringDrag/* - -# TODO(crbug.com/1342797): Flaking on linux-lacros-rel --TabDragging/DetachToBrowserTabDragControllerTest.DragPinnedTabDoesNotGroup/1 - -# TODO(b/256212431): Re-enable when linux-lacros-rel support -# signin::MakePrimaryAccountAvailable(). --AccessCodeCastDialogBrowserTest.* --AccessCodeCastHandlerBrowserTest.ExpectProfileSynErrorWhenNoSync --AccessCodeCastSinkServiceBrowserTest.* +-TabDragging/DetachToBrowserTabDragControllerTest.RevertDragWhileDetached/0 +-TabDragging/DetachToBrowserTabDragControllerTest.RevertDragWhileDetached/2
diff --git a/testing/buildbot/filters/pixel_tests.filter b/testing/buildbot/filters/pixel_tests.filter index fb63e9b..cfb7364f 100644 --- a/testing/buildbot/filters/pixel_tests.filter +++ b/testing/buildbot/filters/pixel_tests.filter
@@ -70,6 +70,7 @@ RelaunchRecommendedBubbleViewDialogTest.* RelaunchRequiredDialogViewDialogTest.* ReopenTabPromoControllerDialogBrowserTest.* +SAAEnabledPermissionPromptBubbleViewBrowserTest.* SafetyTipPageInfoBubbleViewDialogTest.* ScreenCaptureNotificationUiBrowserTest.* SecurePaymentConfirmationDialogViewTest.InvokeUi_*
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 8d491a1..61dc829 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1323,6 +1323,23 @@ 'mixins': ['chromium-tester-service-account'], 'machines': { # Mirrors "Linux Builder" and "Linux Tests". + 'linux-arm64-rel-cft': { + 'mixins': [ + 'isolate_profile_data', + 'linux-bionic', + 'arm64', + ], + 'additional_compile_targets': [ + 'all' + ], + 'test_suites': { + 'gtest_tests': 'chromium_linux_gtests', + 'isolated_scripts': 'chromium_linux_rel_isolated_scripts', + 'scripts': 'chromium_linux_scripts', + } + }, + + # Mirrors "Linux Builder" and "Linux Tests". 'linux-rel-cft': { 'mixins': [ 'isolate_profile_data',
diff --git a/third_party/androidx/local_modifications/.clang-format b/third_party/androidx/local_modifications/.clang-format new file mode 100644 index 0000000..e384528 --- /dev/null +++ b/third_party/androidx/local_modifications/.clang-format
@@ -0,0 +1 @@ +DisableFormat: true
diff --git a/third_party/androidx/local_modifications/buildcompat/java/androidx/core/os/BuildCompat.java b/third_party/androidx/local_modifications/buildcompat/java/androidx/core/os/BuildCompat.java index 3138f6f..4f183521 100644 --- a/third_party/androidx/local_modifications/buildcompat/java/androidx/core/os/BuildCompat.java +++ b/third_party/androidx/local_modifications/buildcompat/java/androidx/core/os/BuildCompat.java
@@ -51,8 +51,9 @@ * @hide */ @VisibleForTesting - protected static boolean isAtLeastPreReleaseCodename( - @NonNull String codename, @NonNull String buildCodename) { + protected static boolean isAtLeastPreReleaseCodename(@NonNull String codename, + @NonNull String buildCodename) { + // Special case "REL", which means the build is not a pre-release build. if ("REL".equals(buildCodename)) { return false; @@ -194,7 +195,8 @@ @Deprecated public static boolean isAtLeastSv2() { return VERSION.SDK_INT >= 32 - || (VERSION.SDK_INT >= 31 && isAtLeastPreReleaseCodename("Sv2", VERSION.CODENAME)); + || (VERSION.SDK_INT >= 31 + && isAtLeastPreReleaseCodename("Sv2", VERSION.CODENAME)); } /** @@ -232,7 +234,7 @@ public static boolean isAtLeastU() { return VERSION.SDK_INT >= 34 || (VERSION.SDK_INT >= 33 - && isAtLeastPreReleaseCodename("UpsideDownCake", VERSION.CODENAME)); + && isAtLeastPreReleaseCodename("UpsideDownCake", VERSION.CODENAME)); } /** @@ -260,7 +262,7 @@ * removed</strong> after their respective SDKs are finalized for release. */ @RequiresOptIn - public @interface PrereleaseSdkCheck {} + public @interface PrereleaseSdkCheck { } /** * The value of {@code SdkExtensions.getExtensionVersion(R)}. This is a convenience constant
diff --git a/third_party/blink/renderer/core/animation/animation_timeline.h b/third_party/blink/renderer/core/animation/animation_timeline.h index 17a61539..8543a1d8 100644 --- a/third_party/blink/renderer/core/animation/animation_timeline.h +++ b/third_party/blink/renderer/core/animation/animation_timeline.h
@@ -74,17 +74,25 @@ // consideration here: https://github.com/w3c/csswg-drafts/issues/2075. virtual absl::optional<base::TimeDelta> InitialStartTimeForAnimations() = 0; - virtual AnimationTimeDelta CalculateIntrinsicIterationDuration( - const absl::optional<TimelineOffset>& rangeStart, - const absl::optional<TimelineOffset>& rangeEnd, - const Timing&) { - return AnimationTimeDelta(); + AnimationTimeDelta CalculateIntrinsicIterationDuration( + const Animation* animation, + const Timing& timing) { + return CalculateIntrinsicIterationDuration( + animation->GetRangeStartInternal(), animation->GetRangeEndInternal(), + timing); } - virtual AnimationTimeDelta CalculateIntrinsicIterationDuration( - const Animation*, - const Timing&) { - return AnimationTimeDelta(); + AnimationTimeDelta CalculateIntrinsicIterationDuration( + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end, + const Timing& timing) { + // TODO(crbug.com/1441013): Support range start and end for scroll-timelines + // that are not view timelines. + return CalculateIntrinsicIterationDuration( + GetTimelineRange(), + IsViewTimeline() ? range_start : absl::optional<TimelineOffset>(), + IsViewTimeline() ? range_end : absl::optional<TimelineOffset>(), + timing); } // See class TimelineRange. @@ -144,6 +152,14 @@ protected: virtual PhaseAndTime CurrentPhaseAndTime() = 0; + virtual AnimationTimeDelta CalculateIntrinsicIterationDuration( + const TimelineRange&, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end, + const Timing&) { + return AnimationTimeDelta(); + } + Member<Document> document_; unsigned outdated_animation_count_; // Animations which will be updated on the next frame
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc index 10a5fbb..b7c8128 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.cc +++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -1302,12 +1302,12 @@ return matching_timeline; } -// Find a ScrollTimeline in the inclusive sibling-ancestors. +// Find a ScrollTimeline in inclusive ancestors. // // The reason `update` is provided from the outside rather than just fetching // it from ElementAnimations, is that for the current node we're resolving style // for, the update hasn't actually been stored on ElementAnimations yet. -ScrollTimeline* CSSAnimations::FindPreviousSiblingAncestorTimeline( +ScrollTimeline* CSSAnimations::FindAncestorTimeline( const ScopedCSSName& name, Node* node, const CSSAnimationUpdate* update) { @@ -1316,17 +1316,6 @@ if (ScrollTimeline* timeline = FindTimelineForNode(name, node, update)) return timeline; - // We use LayoutTreeBuilderTraversal to skip siblings which are not in the - // flat tree, because they don't have a ComputedStyle (and therefore can't - // provide any timelines). - for (Node* prev = LayoutTreeBuilderTraversal::PreviousSibling(*node); prev; - prev = LayoutTreeBuilderTraversal::PreviousSibling(*prev)) { - if (ScrollTimeline* timeline = - FindTimelineForNode(name, prev, GetPendingAnimationUpdate(*prev))) { - return timeline; - } - } - Element* parent_element = RuntimeEnabledFeatures::CSSTreeScopedTimelinesEnabled() ? node->ParentOrShadowHostElement() @@ -1334,8 +1323,8 @@ if (!parent_element) { return nullptr; } - return FindPreviousSiblingAncestorTimeline( - name, parent_element, GetPendingAnimationUpdate(*parent_element)); + return FindAncestorTimeline(name, parent_element, + GetPendingAnimationUpdate(*parent_element)); } namespace { @@ -1393,8 +1382,7 @@ return nullptr; } if (style_timeline.IsName()) { - return FindPreviousSiblingAncestorTimeline(style_timeline.GetName(), - element, &update); + return FindAncestorTimeline(style_timeline.GetName(), element, &update); } if (style_timeline.IsView()) { return ComputeViewFunctionTimeline(element, style_timeline.GetView(),
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.h b/third_party/blink/renderer/core/animation/css/css_animations.h index dc18d68..58fb178 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.h +++ b/third_party/blink/renderer/core/animation/css/css_animations.h
@@ -347,10 +347,9 @@ const TimelineData*, const CSSAnimationUpdate*); - static ScrollTimeline* FindPreviousSiblingAncestorTimeline( - const ScopedCSSName& name, - Node*, - const CSSAnimationUpdate*); + static ScrollTimeline* FindAncestorTimeline(const ScopedCSSName& name, + Node*, + const CSSAnimationUpdate*); static AnimationTimeline* ComputeTimeline( Element*,
diff --git a/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc b/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc index 9de50494..2c4aa741 100644 --- a/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc +++ b/third_party/blink/renderer/core/animation/css/css_scroll_timeline_test.cc
@@ -41,12 +41,17 @@ TEST_F(CSSScrollTimelineTest, SharedTimelines) { SetBodyInnerHTML(R"HTML( <style> + body { + scroll-timeline-attachment: defer; + scroll-timeline-name: timeline1, timeline2; + } @keyframes anim1 { to { top: 200px; } } @keyframes anim2 { to { left: 200px; } } @keyframes anim3 { to { right: 200px; } } .scroller { height: 100px; overflow: scroll; + scroll-timeline-attachment: ancestor; } .scroller > div { height: 200px;
diff --git a/third_party/blink/renderer/core/animation/scroll_timeline.cc b/third_party/blink/renderer/core/animation/scroll_timeline.cc index 37f8b69..153eba3 100644 --- a/third_party/blink/renderer/core/animation/scroll_timeline.cc +++ b/third_party/blink/renderer/core/animation/scroll_timeline.cc
@@ -12,8 +12,6 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_union_cssnumericvalue_double.h" #include "third_party/blink/renderer/core/animation/keyframe_effect.h" #include "third_party/blink/renderer/core/animation/scroll_timeline_util.h" -#include "third_party/blink/renderer/core/animation/worklet_animation_base.h" -#include "third_party/blink/renderer/core/animation/worklet_animation_controller.h" #include "third_party/blink/renderer/core/css/css_to_length_conversion_data.h" #include "third_party/blink/renderer/core/css/cssom/css_unit_values.h" #include "third_party/blink/renderer/core/css/parser/css_parser_context.h" @@ -266,24 +264,37 @@ } AnimationTimeDelta ScrollTimeline::CalculateIntrinsicIterationDuration( - const Animation* animation, + const TimelineRange& timeline_range, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end, const Timing& timing) { absl::optional<AnimationTimeDelta> duration = GetDuration(); // Only run calculation for progress based scroll timelines - if (duration) { - if (timing.iteration_count > 0) { - // duration represents 100% so we subtract percentage delays and divide it - // by iteration count to calculate the iteration duration. - double start_delay = timing.start_delay.relative_delay.value_or(0); - double end_delay = timing.end_delay.relative_delay.value_or(0); - double scale = (1 - start_delay - end_delay); - if (scale <= 0) { - return AnimationTimeDelta(); - } + if (duration && timing.iteration_count > 0) { + double active_interval = 1; - return scale * duration.value() / timing.iteration_count; + double start = range_start + ? timeline_range.ToFractionalOffset(range_start.value()) + : 0; + double end = + range_end ? timeline_range.ToFractionalOffset(range_end.value()) : 1; + + active_interval -= start; + active_interval -= (1 - end); + active_interval = std::max(0., active_interval); + + // Start and end delays are proportional to the active interval. + double start_delay = timing.start_delay.relative_delay.value_or(0); + double end_delay = timing.end_delay.relative_delay.value_or(0); + double delay = start_delay + end_delay; + + if (delay >= 1) { + return AnimationTimeDelta(); } + + active_interval *= (1 - delay); + return duration.value() * active_interval / timing.iteration_count; } return AnimationTimeDelta(); } @@ -353,13 +364,6 @@ } } -void ScrollTimeline::WorkletAnimationAttached(WorkletAnimationBase* worklet) { - if (!ResolvedSource()) { - return; - } - attached_worklet_animations_.insert(worklet); -} - Node* ScrollTimeline::ComputeResolvedSource() const { if (!CurrentAttachment()) { return nullptr; @@ -375,7 +379,6 @@ void ScrollTimeline::Trace(Visitor* visitor) const { visitor->Trace(timeline_state_snapshotted_); - visitor->Trace(attached_worklet_animations_); visitor->Trace(attachments_); AnimationTimeline::Trace(visitor); ScrollSnapshotClient::Trace(visitor);
diff --git a/third_party/blink/renderer/core/animation/scroll_timeline.h b/third_party/blink/renderer/core/animation/scroll_timeline.h index 244702b..cac3e7f 100644 --- a/third_party/blink/renderer/core/animation/scroll_timeline.h +++ b/third_party/blink/renderer/core/animation/scroll_timeline.h
@@ -27,7 +27,6 @@ class PaintLayerScrollableArea; class ScrollTimelineOptions; class ScrollTimelineAttachment; -class WorkletAnimationBase; // Implements the ScrollTimeline concept from the Scroll-linked Animations spec. // @@ -77,18 +76,6 @@ bool IsActive() const override; absl::optional<base::TimeDelta> InitialStartTimeForAnimations() override; - AnimationTimeDelta CalculateIntrinsicIterationDuration( - const Animation*, - const Timing&) override; - - // TODO(kevers): Support range start and end for scroll-timelines that are not - // view timelines. - AnimationTimeDelta CalculateIntrinsicIterationDuration( - const absl::optional<TimelineOffset>& rangeStart, - const absl::optional<TimelineOffset>& rangeEnd, - const Timing& timing) override { - return CalculateIntrinsicIterationDuration(nullptr, timing); - } TimelineRange GetTimelineRange() const override; @@ -134,13 +121,6 @@ cc::AnimationTimeline* EnsureCompositorTimeline() override; void UpdateCompositorTimeline() override; - // TODO(crbug.com/896249): This method is temporary and currently required - // to support worklet animations. Once worklet animations become animations - // these methods will not be longer needed. They are used to keep track of - // the of worklet animations attached to the scroll timeline for updating - // compositing state. - void WorkletAnimationAttached(WorkletAnimationBase*); - void AnimationAttached(Animation*) override; void AnimationDetached(Animation*) override; @@ -173,6 +153,12 @@ PhaseAndTime CurrentPhaseAndTime() override; + AnimationTimeDelta CalculateIntrinsicIterationDuration( + const TimelineRange&, + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end, + const Timing&) override; + Node* ComputeResolvedSource() const; static bool ComputeIsResolved(Node* resolved_source); @@ -242,7 +228,6 @@ // Snapshotted value produced by the last SnapshotState call. TimelineState timeline_state_snapshotted_; - HeapHashSet<WeakMember<WorkletAnimationBase>> attached_worklet_animations_; HeapVector<Member<ScrollTimelineAttachment>, 1> attachments_; };
diff --git a/third_party/blink/renderer/core/animation/scroll_timeline_test.cc b/third_party/blink/renderer/core/animation/scroll_timeline_test.cc index f30ba7e6..f812230c 100644 --- a/third_party/blink/renderer/core/animation/scroll_timeline_test.cc +++ b/third_party/blink/renderer/core/animation/scroll_timeline_test.cc
@@ -11,6 +11,7 @@ #include "third_party/blink/renderer/core/animation/document_animations.h" #include "third_party/blink/renderer/core/animation/keyframe_effect.h" #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h" +#include "third_party/blink/renderer/core/animation/timing_calculations.h" #include "third_party/blink/renderer/core/animation/view_timeline.h" #include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/dom/dom_token_list.h" @@ -97,6 +98,16 @@ // UpdateSnapshot has 'protected' visibility. void UpdateSnapshotForTesting() { UpdateSnapshot(); } + + AnimationTimeDelta CalculateIntrinsicIterationDurationForTest( + const absl::optional<TimelineOffset>& range_start, + const absl::optional<TimelineOffset>& range_end) { + Timing timing; + timing.iteration_count = 1; + TimelineRange timeline_range = GetTimelineRange(); + return CalculateIntrinsicIterationDuration(timeline_range, range_start, + range_end, timing); + } }; class TestViewTimeline : public ViewTimeline { @@ -999,4 +1010,71 @@ timeline->GetTimelineRange()); } +TEST_F(ScrollTimelineTest, ScrollTimelineCalculateIntrinsicIterationDuration) { + SetBodyInnerHTML(R"HTML( + <style> + #scroller { + overflow-y: auto; + width: 100px; + height: 100px; + } + .spacer { + height: 400px; + } + } + </style> + <div id='scroller'> + <div class='spacer'></div> + </div> + )HTML"); + + auto* timeline = MakeGarbageCollected<TestScrollTimeline>( + &GetDocument(), GetElementById("scroller")); + + AnimationTimeDelta duration = timeline->GetDuration().value(); + + using NamedRange = TimelineOffset::NamedRange; + + // [0, 300] + EXPECT_TRUE(IsWithinAnimationTimeTolerance( + duration, timeline->CalculateIntrinsicIterationDurationForTest( + /* range_start */ absl::optional<TimelineOffset>(), + /* range_end */ absl::optional<TimelineOffset>()))); + + // [0, 300] (explicit) + EXPECT_TRUE(IsWithinAnimationTimeTolerance( + duration, + timeline->CalculateIntrinsicIterationDurationForTest( + /* range_start */ TimelineOffset(NamedRange::kNone, Length::Fixed(0)), + /* range_end */ TimelineOffset(NamedRange::kNone, + Length::Fixed(300))))); + + // [50, 200] + EXPECT_TRUE(IsWithinAnimationTimeTolerance( + duration / 2.0, timeline->CalculateIntrinsicIterationDurationForTest( + /* range_start */ + TimelineOffset(NamedRange::kNone, Length::Fixed(50)), + /* range_end */ TimelineOffset(NamedRange::kNone, + Length::Fixed(200))))); + + // [50, 200] (kEntry) + // The name part of the TimelineOffset is ignored. + EXPECT_TRUE(IsWithinAnimationTimeTolerance( + duration / 2.0, + timeline->CalculateIntrinsicIterationDurationForTest( + /* range_start */ + TimelineOffset(NamedRange::kEntry, Length::Fixed(50)), + /* range_end */ + TimelineOffset(NamedRange::kEntry, Length::Fixed(200))))); + + // [50, 50] + EXPECT_TRUE(IsWithinAnimationTimeTolerance( + AnimationTimeDelta(), + timeline->CalculateIntrinsicIterationDurationForTest( + /* range_start */ + TimelineOffset(NamedRange::kNone, Length::Fixed(50)), + /* range_end */ TimelineOffset(NamedRange::kNone, + Length::Fixed(50))))); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/animation/view_timeline.cc b/third_party/blink/renderer/core/animation/view_timeline.cc index a1a6484d..c5769d5e 100644 --- a/third_party/blink/renderer/core/animation/view_timeline.cc +++ b/third_party/blink/renderer/core/animation/view_timeline.cc
@@ -237,46 +237,6 @@ axis, inset)) {} -AnimationTimeDelta ViewTimeline::CalculateIntrinsicIterationDuration( - const Animation* animation, - const Timing& timing) { - return CalculateIntrinsicIterationDuration(animation->GetRangeStartInternal(), - animation->GetRangeEndInternal(), - timing); -} - -AnimationTimeDelta ViewTimeline::CalculateIntrinsicIterationDuration( - const absl::optional<TimelineOffset>& rangeStart, - const absl::optional<TimelineOffset>& rangeEnd, - const Timing& timing) { - absl::optional<AnimationTimeDelta> duration = GetDuration(); - - // Only run calculation for progress based scroll timelines - if (duration && timing.iteration_count > 0) { - double active_interval = 1; - - double start = rangeStart ? ToFractionalOffset(rangeStart.value()) : 0; - double end = rangeEnd ? ToFractionalOffset(rangeEnd.value()) : 1; - - active_interval -= start; - active_interval -= (1 - end); - active_interval = std::max(0., active_interval); - - // Start and end delays are proportional to the active interval. - double start_delay = timing.start_delay.relative_delay.value_or(0); - double end_delay = timing.end_delay.relative_delay.value_or(0); - double delay = start_delay + end_delay; - - if (delay >= 1) { - return AnimationTimeDelta(); - } - - active_interval *= (1 - delay); - return duration.value() * active_interval / timing.iteration_count; - } - return AnimationTimeDelta(); -} - TimelineRange ViewTimeline::GetTimelineRange() const { absl::optional<ScrollOffsets> scroll_offsets = GetResolvedScrollOffsets(); absl::optional<ScrollOffsets> view_offsets = GetResolvedViewOffsets();
diff --git a/third_party/blink/renderer/core/animation/view_timeline.h b/third_party/blink/renderer/core/animation/view_timeline.h index 61b378f..1c8ec5d 100644 --- a/third_party/blink/renderer/core/animation/view_timeline.h +++ b/third_party/blink/renderer/core/animation/view_timeline.h
@@ -42,15 +42,6 @@ CSSNumericValue* getCurrentTime(const String& rangeName) override; - AnimationTimeDelta CalculateIntrinsicIterationDuration( - const Animation*, - const Timing&) override; - - AnimationTimeDelta CalculateIntrinsicIterationDuration( - const absl::optional<TimelineOffset>& rangeStart, - const absl::optional<TimelineOffset>& rangeEnd, - const Timing&) override; - TimelineRange GetTimelineRange() const override; // IDL API implementation.
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_mappings.h b/third_party/blink/renderer/core/css/css_primitive_value_mappings.h index cdb1425..72bf800f 100644 --- a/third_party/blink/renderer/core/css/css_primitive_value_mappings.h +++ b/third_party/blink/renderer/core/css/css_primitive_value_mappings.h
@@ -1632,6 +1632,8 @@ return kContainerTypeInlineSize; case CSSValueID::kSize: return kContainerTypeSize; + case CSSValueID::kSticky: + return kContainerTypeSticky; default: break; }
diff --git a/third_party/blink/renderer/core/css/css_properties.json5 b/third_party/blink/renderer/core/css/css_properties.json5 index 28919b9..8bfd4ea 100644 --- a/third_party/blink/renderer/core/css/css_properties.json5 +++ b/third_party/blink/renderer/core/css/css_properties.json5
@@ -2572,9 +2572,9 @@ { name: "container-type", property_methods: ["ParseSingleValue", "CSSValueFromComputedStyleInternal"], - keywords: ["normal", "inline-size", "size"], + keywords: ["normal", "inline-size", "size", "sticky"], field_group: "*", - field_size: 2, + field_size: 3, field_template: "primitive", default_value: "kContainerTypeNormal", type_name: "unsigned",
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 8069929..066b2c4 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -7274,22 +7274,40 @@ } CSSValue* ConsumeContainerType(CSSParserTokenRange& range) { + // container-type: normal | [ [ size | inline-size ] || sticky ] if (CSSValue* value = ConsumeIdent<CSSValueID::kNormal>(range)) { return value; } - if (CSSValue* value = - ConsumeIdent<CSSValueID::kSize, CSSValueID::kInlineSize>(range)) { - // Note that StyleBuilderConverter::ConvertFlags requires that values - // other than the ZeroValue appear in a CSSValueList, hence we return a list - // with one item here. Also note that the full grammar will require multiple - // list items in the future, if we add support for non-size container types. - CSSValueList* list = CSSValueList::CreateSpaceSeparated(); - list->Append(*value); - return list; - } + CSSValue* size_value = nullptr; + CSSValue* sticky_value = nullptr; - return nullptr; + do { + if (!size_value) { + size_value = + ConsumeIdent<CSSValueID::kSize, CSSValueID::kInlineSize>(range); + if (size_value) { + continue; + } + } + if (!sticky_value && + RuntimeEnabledFeatures::CSSStickyContainerQueriesEnabled()) { + sticky_value = ConsumeIdent<CSSValueID::kSticky>(range); + if (sticky_value) { + continue; + } + } + return nullptr; + } while (!range.AtEnd()); + + CSSValueList* list = CSSValueList::CreateSpaceSeparated(); + if (size_value) { + list->Append(*size_value); + } + if (sticky_value) { + list->Append(*sticky_value); + } + return list; } CSSValue* ConsumeSVGPaint(CSSParserTokenRange& range,
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc index fa551c1..14317c85 100644 --- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc +++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2264,17 +2264,21 @@ bool allow_visited_style) const { DCHECK_NE(style.ContainerType() & kContainerTypeSize, kContainerTypeBlockSize); + if (style.ContainerType() == kContainerTypeNormal) { return CSSIdentifierValue::Create(CSSValueID::kNormal); } - if (style.ContainerType() == kContainerTypeSize) { - return CSSIdentifierValue::Create(CSSValueID::kSize); + CSSValueList* values = CSSValueList::CreateSpaceSeparated(); + if ((style.ContainerType() & kContainerTypeBlockSize) == + kContainerTypeBlockSize) { + values->Append(*CSSIdentifierValue::Create(CSSValueID::kSize)); + } else if (style.ContainerType() & kContainerTypeInlineSize) { + values->Append(*CSSIdentifierValue::Create(CSSValueID::kInlineSize)); } - if (style.ContainerType() == kContainerTypeInlineSize) { - return CSSIdentifierValue::Create(CSSValueID::kInlineSize); + if (style.ContainerType() & kContainerTypeSticky) { + values->Append(*CSSIdentifierValue::Create(CSSValueID::kSticky)); } - NOTREACHED(); - return nullptr; + return values; } namespace {
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 579b070..2830c9ee 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -5930,44 +5930,6 @@ checkBorderWidth(1.0f); } -TEST_F(StyleEngineTest, SubsequentSiblingRecalcFlatTree) { - GetDocument() - .documentElement() - ->setInnerHTMLWithDeclarativeShadowDOMForTesting(R"HTML( - <div id="host"> - <template shadowroot=open> - <slot name=a></slot> - </template> - <div slot=a id=target></div> - <div></div> - <div></div> - <div></div> - <div></div> - <div slot=a></div> - <div></div> - <div></div> - <div></div> - <div></div> - <div slot=a></div> - </div> - )HTML"); - - UpdateAllLifecyclePhasesForTest(); - - unsigned before_count = GetStyleEngine().StyleForElementCount(); - - Element* target = GetElementById("target"); - ASSERT_TRUE(target); - - target->SetInlineStyleProperty(CSSPropertyID::kScrollTimelineName, "foo"); - UpdateAllLifecyclePhasesForTest(); - - unsigned after_count = GetStyleEngine().StyleForElementCount(); - - // Only the slotted elements should get style recalc. - EXPECT_EQ(3u, after_count - before_count); -} - TEST_F(StyleEngineTest, AnimationDelayShorthandFlags) { String css = "animation-delay:1s"; {
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index cc76dfc..c9710b4a 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3444,9 +3444,6 @@ diff < ComputedStyle::Difference::kPseudoElementStyle) { return change; } - if (diff == ComputedStyle::Difference::kSiblingDescendantAffecting) { - return change.EnsureAtLeast(StyleRecalcChange::kRecalcSiblingDescendants); - } if (diff == ComputedStyle::Difference::kDescendantAffecting) { return change.EnsureAtLeast(StyleRecalcChange::kRecalcDescendants); }
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index 5fdff6f4..17b6fbfd 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -396,7 +396,7 @@ } if (!old_style || !new_style) { if (AffectsScrollAnimations(old_style, new_style)) { - return Difference::kSiblingDescendantAffecting; + return Difference::kDescendantAffecting; } return Difference::kInherited; } @@ -428,7 +428,7 @@ const ComputedStyle& new_style) { DCHECK_NE(&old_style, &new_style); if (DiffAffectsScrollAnimations(old_style, new_style)) { - return Difference::kSiblingDescendantAffecting; + return Difference::kDescendantAffecting; } if (old_style.Display() != new_style.Display() && old_style.BlockifiesChildren() != new_style.BlockifiesChildren()) {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index c9a5aa86..15d1cc2 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -400,11 +400,6 @@ // The container-name property affects which container is queried by // rules matching descedant elements. kDescendantAffecting, - // Properties which can affect the follow elements changed: - // descendants, subsequent siblings, and descendants of subsequent siblings. - // - // For example, scroll-timeline-* properties. - kSiblingDescendantAffecting, }; CORE_EXPORT static Difference ComputeDifference( const ComputedStyle* old_style,
diff --git a/third_party/blink/renderer/core/style/computed_style_constants.h b/third_party/blink/renderer/core/style/computed_style_constants.h index a82bdcb..8765511 100644 --- a/third_party/blink/renderer/core/style/computed_style_constants.h +++ b/third_party/blink/renderer/core/style/computed_style_constants.h
@@ -250,11 +250,12 @@ return a = a | b; } -static const size_t kContainerTypeBits = 2; +static const size_t kContainerTypeBits = 3; enum EContainerType { kContainerTypeNormal = 0x0, kContainerTypeInlineSize = 0x1, kContainerTypeBlockSize = 0x2, + kContainerTypeSticky = 0x4, kContainerTypeSize = kContainerTypeInlineSize | kContainerTypeBlockSize, }; inline EContainerType operator|(EContainerType a, EContainerType b) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index 199752cd5..b054bb0 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -546,11 +546,17 @@ } // Ignore a block flow (display:block, display:inline-block), unless it - // directly parents inline children. + // directly parents inline children and can have a caret inside of it. // This effectively trims a lot of uninteresting divs out of the tree. auto* block_flow = DynamicTo<LayoutBlockFlow>(*layout_object_); if (block_flow && block_flow->ChildrenInline() && block_flow->FirstChild()) { - return false; + // Require the ability to contain a caret -- this requirement is not + // strictly necessary, and could be removed, but caused about 20 test + // changes on each platform. + NGInlineCursor cursor(*block_flow); + if (cursor.HasRoot()) { + return false; + } } // By default, objects should be ignored so that the AX hierarchy is not
diff --git a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc index f06cd47..f058f14 100644 --- a/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc +++ b/third_party/blink/renderer/modules/animationworklet/worklet_animation.cc
@@ -13,7 +13,6 @@ #include "third_party/blink/renderer/core/animation/document_timeline.h" #include "third_party/blink/renderer/core/animation/element_animations.h" #include "third_party/blink/renderer/core/animation/keyframe_effect_model.h" -#include "third_party/blink/renderer/core/animation/scroll_timeline.h" #include "third_party/blink/renderer/core/animation/scroll_timeline_util.h" #include "third_party/blink/renderer/core/animation/timing.h" #include "third_party/blink/renderer/core/animation/worklet_animation_controller.h" @@ -304,9 +303,6 @@ } effect_timings_ = std::make_unique<WorkletAnimationEffectTimings>( timings, normalized_timings); - - if (timeline_->IsScrollTimeline()) - To<ScrollTimeline>(*timeline_).WorkletAnimationAttached(this); } String WorkletAnimation::playState() {
diff --git a/third_party/blink/renderer/modules/smart_card/smart_card_resource_manager.cc b/third_party/blink/renderer/modules/smart_card/smart_card_resource_manager.cc index 1c1c988..1d78cf1 100644 --- a/third_party/blink/renderer/modules/smart_card/smart_card_resource_manager.cc +++ b/third_party/blink/renderer/modules/smart_card/smart_card_resource_manager.cc
@@ -18,11 +18,13 @@ namespace blink { namespace { -const char kWatchForReadersNotSupported[] = +constexpr char kWatchForReadersNotSupported[] = "Watching for reader addition/removal is not supported in this platform."; -const char kContextGone[] = "Script context has shut down."; -const char kFeaturePolicyBlocked[] = +constexpr char kContextGone[] = "Script context has shut down."; +constexpr char kFeaturePolicyBlocked[] = "Access to the feature \"smart-card\" is disallowed by permissions policy."; +constexpr char kServiceDisconnected[] = + "Disconnected from the smart card service."; bool ShouldBlockSmartCardServiceCall(ExecutionContext* context, ExceptionState& exception_state) { @@ -301,8 +303,28 @@ void SmartCardResourceManager::CloseServiceConnection() { service_.reset(); - // TODO(crbug.com/1386175): Deal with promises in - // get_readers_promises_ and watch_for_readers_promises_ + + // This loop is resolving promises with a value and so it is possible for + // script to be executed in the process of determining if the value is a + // thenable. Move the set to a local variable to prevent such execution from + // invalidating the iterator used by the loop. + HeapHashSet<Member<ScriptPromiseResolver>> get_readers_promises; + get_readers_promises.swap(get_readers_promises_); + for (auto& resolver : get_readers_promises) { + resolver->Resolve(HeapVector<Member<SmartCardReader>>()); + } + + // Similar protection is unnecessary when rejecting a promise. + for (auto& resolver : watch_for_readers_promises_) { + ScriptState* script_state = resolver->GetScriptState(); + if (!IsInParallelAlgorithmRunnable(resolver->GetExecutionContext(), + script_state)) { + continue; + } + ScriptState::Scope script_state_scope(script_state); + resolver->RejectWithDOMException(DOMExceptionCode::kInvalidStateError, + kServiceDisconnected); + } } } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 76d4361..3050e89a 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1108,6 +1108,10 @@ status: "experimental", }, { + name: "CSSStickyContainerQueries", + status: "experimental", + }, + { // https://drafts.csswg.org/css-contain-3/#style-container // This flag is for querying custom properties only. name: "CSSStyleQueries",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index a4f5406..9a69b98 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2909,6 +2909,8 @@ 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 [ Linux ] external/wpt/svg/pservers/reftests/pattern-opacity-01.svg [ Failure ] +crbug.com/626703 [ Win ] external/wpt/svg/pservers/reftests/pattern-opacity-01.svg [ Failure ] crbug.com/626703 external/wpt/clipboard-apis/async-navigator-clipboard-write-multiple.tentative.https.sub.html [ Timeout ] crbug.com/626703 external/wpt/preload/modulepreload-as.html [ Failure Timeout ] crbug.com/626703 [ Win ] external/wpt/preload/modulepreload.html [ Failure Timeout ]
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 81d9ff3..7363632 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
@@ -1884,6 +1884,13 @@ {} ] ], + "font-features-two-stylesheets-crash.html": [ + "0e6490974c27afe7aff29a22418107890eef45e2", + [ + null, + {} + ] + ], "infinite-size-crash.html": [ "d44cf4a37e26a772a4742a825a7422b795dfc9ee", [ @@ -122364,6 +122371,19 @@ {} ] ], + "percentage-padding-004.html": [ + "ca96e546cc86e6a0c0db1a9884653cdecfab7409", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "percentage-size-subitems-001.html": [ "70f3953052a3a770c6cd15ee169607a00fc452b0", [ @@ -267306,6 +267326,19 @@ {} ] ], + "pattern-opacity-01.svg": [ + "eb2d2d7e9a9a7776e5ffeeaf51ba992204a70fc4", + [ + null, + [ + [ + "/svg/pservers/reftests/reference/pattern-opacity-01-ref.svg", + "==" + ] + ], + {} + ] + ], "pattern-viewbox-01.svg": [ "618b8fc29e69d2624d5556d6bbcdba600ce21a4a", [ @@ -272136,11 +272169,11 @@ "support": { ".cache": { "gitignore2.json": [ - "33994b8c7d47d7fe5dad78f845cda057ecdbe35c", + "1005ed4e173635321c8d3b87230ae8ce960f2167", [] ], "mtime.json": [ - "712c0eb75ab94f25f4850f933ea44fd9adf14dd8", + "c4f5ab75c07eaaf599235b4daf047995dbf658e4", [] ] }, @@ -297847,12 +297880,12 @@ [] ], "animations": { - "font-size-adjust-interpolation-expected.txt": [ - "58fe3c7440937f2f5584afa4b80880c99605ed62", + "font-size-adjust-composition-expected.txt": [ + "21f150cd5dfb168718debbd23d07d61ec0c747f6", [] ], - "font-size-adjust-interpolation.html.ini": [ - "c97359074bba5596073557191e3719dbaedfb744", + "font-size-adjust-composition.html.ini": [ + "389f920d0c0301452ca886b9861249745c782015", [] ], "font-variation-settings-interpolation.html.ini": [ @@ -317058,10 +317091,6 @@ "9f505dd7f1d121c0bd0af0131b51f536225326b1", [] ], - "textarea-scrollbar-width-none.html.ini": [ - "16a645b45c87eaed88a375d62f59ccf2e2768e8a", - [] - ], "transparent-on-root-ref.html": [ "a5b2de4f00f3abd19c74b08b80a027d09a7abcca", [] @@ -331957,7 +331986,7 @@ [] ], "round-mod-rem-computed-expected.txt": [ - "6c536edc1f0c8406a73f4ae599e23f49586272a4", + "3b5dcb2bb88ac76f7c13b3addf3288697622c5cb", [] ], "round-mod-rem-computed.html.ini": [ @@ -379582,7 +379611,7 @@ [] ], "modulepreload-as.html.ini": [ - "0835ead581d41e170115e74e1a41764197e7191b", + "7431c2a2b9e4e22dd024039d8766107f16b1e0b4", [] ], "modulepreload-expected.txt": [ @@ -389858,6 +389887,10 @@ "120941444a4898197d6b6001f9908a6cd48b62ba", [] ], + "pattern-opacity-01-ref.svg": [ + "1c9c68bd9d5becec895d4cacac93082bc2defcec", + [] + ], "pattern-viewbox-01-ref.svg": [ "c9f6931deadd57bad20ae1dbbd529d595b14adfb", [] @@ -397624,6 +397657,10 @@ "4347d4aae3e1c6475b21a8f246fb768d91a43afc", [] ], + "echo_datagram_length.py": [ + "f0610b085fe30b4d5fda6473bf17fc498eb47650", + [] + ], "query.py": [ "75d458255ad7af10508dce9905bf2ddb259f3699", [] @@ -446601,6 +446638,13 @@ }, "css-fonts": { "animations": { + "font-size-adjust-composition.html": [ + "d98b0ffd10e5550ab7ccc7a96d02ebb93385ddcb", + [ + null, + {} + ] + ], "font-size-adjust-interpolation.html": [ "a138d7fee5a39bc925a7a4cc5224dcc3db5cc387", [ @@ -611583,10 +611627,43 @@ }, "storage": { "buckets": { - "buckets_storage_policy.tentative.https.any.js": [ - "a66fd81cd4394209d1c534322b2b150cac35adf6", + "bucket-quota-indexeddb.tentative.https.any.js": [ + "ba82edb72ec6fc1656be169a14c3a025e1ab6a23", [ - "storage/buckets/buckets_storage_policy.tentative.https.any.html", + "storage/buckets/bucket-quota-indexeddb.tentative.https.any.html", + { + "script_metadata": [ + [ + "title", + "Bucket quota enforcement for indexeddb" + ], + [ + "script", + "/storage/buckets/resources/util.js" + ] + ] + } + ], + [ + "storage/buckets/bucket-quota-indexeddb.tentative.https.any.worker.html", + { + "script_metadata": [ + [ + "title", + "Bucket quota enforcement for indexeddb" + ], + [ + "script", + "/storage/buckets/resources/util.js" + ] + ] + } + ] + ], + "bucket-storage-policy.tentative.https.any.js": [ + "d6dce3675d0bca18a379518c6ecf2c7ec1310930", + [ + "storage/buckets/bucket-storage-policy.tentative.https.any.html", { "script_metadata": [ [ @@ -611605,7 +611682,7 @@ } ], [ - "storage/buckets/buckets_storage_policy.tentative.https.any.serviceworker.html", + "storage/buckets/bucket-storage-policy.tentative.https.any.serviceworker.html", { "script_metadata": [ [ @@ -611624,7 +611701,7 @@ } ], [ - "storage/buckets/buckets_storage_policy.tentative.https.any.sharedworker.html", + "storage/buckets/bucket-storage-policy.tentative.https.any.sharedworker.html", { "script_metadata": [ [ @@ -611643,7 +611720,7 @@ } ], [ - "storage/buckets/buckets_storage_policy.tentative.https.any.worker.html", + "storage/buckets/bucket-storage-policy.tentative.https.any.worker.html", { "script_metadata": [ [ @@ -654155,7 +654232,7 @@ ] ], "datagrams.https.any.js": [ - "dc7133bb867e203ee651d887b64e48782dc3c58b", + "d5b8e3bbda158707bb5273628ec1abea7206d1ac", [ "webtransport/datagrams.https.any.html", {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-composition.html.ini b/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-composition.html.ini new file mode 100644 index 0000000..389f920 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/animations/font-size-adjust-composition.html.ini
@@ -0,0 +1,260 @@ +[font-size-adjust-composition.html] + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0.0\] to add [ex-height 2.0\] at (-0.5) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0.0\] to add [ex-height 2.0\] at (0) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0.0\] to add [ex-height 2.0\] at (0.5) should be [ex-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0.0\] to add [ex-height 2.0\] at (1) should be [ex-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0.0\] to add [ex-height 2.0\] at (1.5) should be [ex-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0\] to replace [ex-height 2.0\] at (-0.5) should be [ic-height 0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0\] to replace [ex-height 2.0\] at (0) should be [ic-height 0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0\] to replace [ex-height 2.0\] at (0.5) should be [ex-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0\] to replace [ex-height 2.0\] at (1) should be [ex-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-height 0\] to replace [ex-height 2.0\] at (1.5) should be [ex-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0.0\] to add [ic-height 2.0\] at (-0.5) should be [ic-width 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0.0\] to add [ic-height 2.0\] at (0) should be [ic-width 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0.0\] to add [ic-height 2.0\] at (0.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0.0\] to add [ic-height 2.0\] at (1) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0.0\] to add [ic-height 2.0\] at (1.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0\] to replace [ic-height 2.0\] at (-0.5) should be [ic-width 0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0\] to replace [ic-height 2.0\] at (0) should be [ic-width 0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0\] to replace [ic-height 2.0\] at (0.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0\] to replace [ic-height 2.0\] at (1) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from add [ic-width 0\] to replace [ic-height 2.0\] at (1.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0.0\] to replace [ex-height 2.0\] at (-0.5) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0.0\] to replace [ex-height 2.0\] at (0) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0.0\] to replace [ex-height 2.0\] at (0.5) should be [ex-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0.0\] to replace [ex-height 2.0\] at (1) should be [ex-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0.0\] to replace [ex-height 2.0\] at (1.5) should be [ex-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0\] to add [ex-height 2.0\] at (-0.5) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0\] to add [ex-height 2.0\] at (0) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0\] to add [ex-height 2.0\] at (0.5) should be [ex-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0\] to add [ex-height 2.0\] at (1) should be [ex-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-height 0\] to add [ex-height 2.0\] at (1.5) should be [ex-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0.0\] to replace [ic-height 2.0\] at (-0.5) should be [ic-width 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0.0\] to replace [ic-height 2.0\] at (0) should be [ic-width 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0.0\] to replace [ic-height 2.0\] at (0.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0.0\] to replace [ic-height 2.0\] at (1) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0.0\] to replace [ic-height 2.0\] at (1.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0\] to add [ic-height 2.0\] at (-0.5) should be [ic-width 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0\] to add [ic-height 2.0\] at (0) should be [ic-width 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0\] to add [ic-height 2.0\] at (0.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0\] to add [ic-height 2.0\] at (1) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [0.5\] from replace [ic-width 0\] to add [ic-height 2.0\] at (1.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to add [ic-height 2.0\] at (-0.5) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to add [ic-height 2.0\] at (0) should be [ic-height 0.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to add [ic-height 2.0\] at (0.5) should be [ic-height 1.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to add [ic-height 2.0\] at (1) should be [ic-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to add [ic-height 2.0\] at (1.5) should be [ic-height 3.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to replace [ic-height 2.0\] at (-0.5) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to replace [ic-height 2.0\] at (0) should be [ic-height 0.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to replace [ic-height 2.0\] at (0.5) should be [ic-height 1.25\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to replace [ic-height 2.0\] at (1) should be [ic-height 2\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from add [ic-height 0\] to replace [ic-height 2.0\] at (1.5) should be [ic-height 2.75\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 0\] to add [ic-height 2.0\] at (-0.5) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 0\] to add [ic-height 2.0\] at (0) should be [ic-height 0.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 0\] to add [ic-height 2.0\] at (0.5) should be [ic-height 1.25\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 0\] to add [ic-height 2.0\] at (1) should be [ic-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 0\] to add [ic-height 2.0\] at (1.5) should be [ic-height 3.75\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 2.0\] to add [none\] at (-0.5) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 2.0\] to add [none\] at (0) should be [ic-height 2.0\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 2.0\] to add [none\] at (0.5) should be [none\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 2.0\] to add [none\] at (1) should be [none\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [ic-height 2.0\] to add [none\] at (1.5) should be [none\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [none\] to add [ic-height 2.0\] at (-0.5) should be [none\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [none\] to add [ic-height 2.0\] at (0) should be [none\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [none\] to add [ic-height 2.0\] at (0.5) should be [ic-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [none\] to add [ic-height 2.0\] at (1) should be [ic-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL + + [Compositing: property <font-size-adjust> underlying [ic-height 0.5\] from replace [none\] to add [ic-height 2.0\] at (1.5) should be [ic-height 2.5\]] + expected: + if (product == "content_shell") and (os == "linux"): FAIL
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 0835ead..7431c2a 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,9 +1,11 @@ [modulepreload-as.html] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK if (product == "content_shell") and (os == "mac") and (port == "mac10.15"): OK - if (product == "content_shell") and (os == "mac") and (port == "mac12"): [OK, ERROR, TIMEOUT] + if (product == "content_shell") and (os == "mac") and (port == "mac12"): OK + if (product == "content_shell") and (os == "mac") and (port == "mac11"): OK if (product == "content_shell") and (os == "win") and (port == "win11"): TIMEOUT + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [ERROR, TIMEOUT] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [ERROR, TIMEOUT] ERROR [Modulepreload with as="audio"] expected: FAIL @@ -15,79 +17,85 @@ expected: FAIL [Modulepreload with as="embed"] - expected: FAIL + expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [FAIL, PASS] + FAIL [Modulepreload with as="fetch"] expected: if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS - if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] if (product == "content_shell") and (os == "linux"): PASS if product == "chrome": PASS FAIL [Modulepreload with as="font"] expected: - 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 == ""): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] if (product == "content_shell") and (os == "win"): PASS if product == "chrome": PASS FAIL [Modulepreload with as="frame"] expected: - 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 == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] if (product == "content_shell") and (os == "win"): PASS if product == "chrome": PASS FAIL [Modulepreload with as="iMaGe"] expected: + if (product == "content_shell") and (os == "mac") and (port == "mac12"): 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 - if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] [Modulepreload with as="iframe"] expected: - 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 == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] if (product == "content_shell") and (os == "win"): PASS if product == "chrome": PASS FAIL [Modulepreload with as="image"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): FAIL - 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 == "mac10.15"): 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 == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "win"): PASS + if product == "chrome": PASS + FAIL [Modulepreload with as="invalid-dest"] expected: FAIL [Modulepreload with as="manifest"] expected: - 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 == "mac12-arm64"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS + if (product == "content_shell") and (os == "win"): PASS + if product == "chrome": PASS + FAIL [Modulepreload with as="object"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] - 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 == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] [Modulepreload with as="paintworklet"] expected: 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 == "mac10.15"): FAIL - if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] + if (product == "content_shell") and (os == "mac") and (port == "mac11"): FAIL + if (product == "content_shell") and (os == "mac") and (port == "mac12"): FAIL [Modulepreload with as="serviceworker"] expected: FAIL @@ -97,32 +105,35 @@ [Modulepreload with as="style"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [FAIL, PASS] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS if product == "chrome": PASS FAIL [Modulepreload with as="track"] expected: - if (product == "content_shell") and (os == "linux") and (flag_specific == ""): PASS + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS if product == "chrome": PASS FAIL [Modulepreload with as="video"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): PASS - if (product == "content_shell") and (os == "linux"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS + if (product == "content_shell") and (os == "linux") and (flag_specific == "disable-site-isolation-trials"): [PASS, FAIL] + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] if product == "chrome": PASS FAIL [Modulepreload with as="webidentity"] expected: + if (product == "content_shell") and (os == "linux") and (flag_specific == ""): [PASS, FAIL] 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 == "content_shell") and (os == "mac") and (port == "mac12-arm64"): PASS if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS + if (product == "content_shell") and (os == "mac") and (port == "mac12-arm64"): PASS if product == "chrome": PASS FAIL @@ -131,7 +142,6 @@ [Modulepreload with as="xslt"] expected: - if (product == "content_shell") and (os == "mac") and (port == "mac12"): [FAIL, PASS] if (product == "content_shell") and (os == "mac") and (port == "mac13-arm64"): PASS if (product == "content_shell") and (os == "linux"): PASS if product == "chrome": PASS
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative-expected.txt b/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative-expected.txt deleted file mode 100644 index 2068867a..0000000 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/animation-timeline-named-scroll-progress-timeline.tentative-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -This is a testharness.js-based test. -PASS scroll-timeline-name is referenceable in animation-timeline on the declaring element itself -PASS scroll-timeline-name is referenceable in animation-timeline on that element's descendants -FAIL scroll-timeline-name is not referenceable in animation-timeline on that element's siblings assert_equals: Animation with unknown timeline name holds current time at zero expected "50px" but got "100px" -PASS scroll-timeline-name on an element which is not a scroll-container -PASS Change in scroll-timeline-name to match animation timeline updates animation. -PASS Change in scroll-timeline-name to no longer match animation timeline updates animation. -PASS Timeline lookup updates candidate when closer match available. -PASS Timeline lookup updates candidate when match becomes available. -PASS scroll-timeline-axis is block -PASS scroll-timeline-axis is inline -PASS scroll-timeline-axis is horizontal -PASS scroll-timeline-axis is vertical -PASS scroll-timeline-axis is mutated -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-attachment.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-attachment.html index 9603385..7996e48 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-attachment.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-attachment.html
@@ -96,6 +96,25 @@ }, 'Deferred timeline with no attachments'); </script> +<template id=scroll_timeline_defer_no_attach_to_prev_sibling> + <div class="timeline defer"> + <div class="scroller timeline"> + <div class=content></div> + </div> + <div class=target>Test</div> + </div> +</template> +<script> + promise_test(async (t) => { + inflate(t, scroll_timeline_defer_no_attach_to_prev_sibling); + let scroller = main.querySelector('.scroller'); + let target = main.querySelector('.target'); + await scrollTop(scroller, 350); // 50% + assert_equals(getComputedStyle(target).width, '0px'); + assert_equals(getComputedStyle(target).getPropertyValue('--applied'), ''); + }, 'Deferred timeline with no attachments to previous sibling'); +</script> + <template id=scroll_timeline_local_ancestor> <div class="scroller timeline local"> <div class=content>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-sibling-gcs.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-sibling-gcs.html deleted file mode 100644 index 6062e795..0000000 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/scroll-timeline-sibling-gcs.html +++ /dev/null
@@ -1,52 +0,0 @@ -<!DOCTYPE html> -<title>scroll-timeline and container queries</title> -<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand"> -<link rel="help" src="https://drafts.csswg.org/css-contain-3/#container-queries"> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> -<script src="/web-animations/testcommon.js"></script> -<script src="support/testcommon.js"></script> -<style> - #scroller { - overflow: auto; - width: auto; - height: 100px; - } - #scroller > div { - height: 200px; - } - - @keyframes anim { - from { background-color: rgb(100, 100, 100); } - to { background-color: rgb(200, 200, 200); } - } - #element { - height: 10px; - width: 10px; - animation: anim 10s linear; - animation-timeline: timeline; - background-color: rgb(0, 0, 0); - } -</style> -<div> - <div id=scroller> - <div></div> - </div> - <div> - <div id=element></div> - </div> -</div> -<script> - setup(assert_implements_animation_timeline); - - promise_test(async (t) => { - element.offsetTop; - scroller.scrollTop = 50; - await waitForNextFrame(); - // Unknown timeline, time held at zero. - assert_equals(getComputedStyle(element).backgroundColor, 'rgb(100, 100, 100)'); - scroller.style.scrollTimeline = 'timeline'; - await waitForCSSScrollTimelineStyle(); - assert_equals(getComputedStyle(element).backgroundColor, 'rgb(150, 150, 150)'); - }, 'Timelines appearing on preceding siblings are visible to getComputedStyle'); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject-expected.txt b/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject-expected.txt new file mode 100644 index 0000000..69118b6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Keyframes with timeline-offsets ignored when timeline is inactive assert_equals: properties on ComputedKeyframe #0: Keyframes with invalid view timeline should match expected "composite,computedOffset,easing,offset,opacity" but got "composite,computedOffset,easing,marginRight,offset,opacity" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject.html index 93ef7ffa..bea072aa 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/timeline-offset-keyframes-hidden-subject.html
@@ -13,10 +13,10 @@ <style type="text/css"> @keyframes anim { cover 0% { - margin-left: 0px; + margin-left: 0px; } 50% { - opacity: 0.5; + opacity: 0.5; } cover 100% { margin-right: 0px; @@ -24,35 +24,34 @@ } #scroller { - scroll-timeline-attachment: defer t1; - border: 10px solid lightgray; + border: 10px solid lightgray; overflow-y: scroll; overflow-x: hidden; width: 300px; height: 200px; + view-timeline: t1 defer; } #block { - scroll-timeline-attachment: ancestor; - margin-top: 800px; - margin-left: 10px; - margin-right: 10px; - width: 100px; - height: 50px; - background-color: blue; - view-timeline: t1 block; + margin-top: 800px; + margin-left: 10px; + margin-right: 10px; + width: 100px; + height: 50px; + background-color: blue; + view-timeline: t1 ancestor; } #target { margin-bottom: 800px; - margin-left: 10px; - margin-right: 10px; + margin-left: 10px; + margin-right: 10px; width: 100px; height: 100px; z-index: -1; background-color: green; - animation: anim auto both linear; - animation-range-start: contain 0%; - animation-range-end: contain 100%; - animation-timeline: t1; + animation: anim auto both linear; + animation-range-start: contain 0%; + animation-range-end: contain 100%; + animation-timeline: t1; } </style> <body> @@ -74,16 +73,16 @@ let frames = anim.effect.getKeyframes(); let expected_resolved_offsets = [ - { offset: 0, computedOffset: 0, easing: "linear", composite: "replace", + { offset: 0, computedOffset: 0, easing: "linear", composite: "replace", marginRight: "10px", opacity: "1" }, { offset: 1/2, computedOffset: 1/2, easing: "linear", composite: "auto", opacity: "0.5" }, { offset: 1, computedOffset: 1, easing: "linear", composite: "replace", marginLeft: "10px", opacity: "1" }, - { offset: { rangeName: 'cover', offset: CSS.percent(0) }, + { offset: { rangeName: "cover", offset: CSS.percent(0) }, computedOffset: -1/3, easing: "linear", composite: "auto", marginLeft: "0px" }, - { offset: { rangeName: 'cover', offset: CSS.percent(100) }, + { offset: { rangeName: "cover", offset: CSS.percent(100) }, computedOffset: 4/3, easing: "linear", composite: "auto", marginRight: "0px" }, ];
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/pattern-opacity-01.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/pattern-opacity-01.svg new file mode 100644 index 0000000..eb2d2d7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/pattern-opacity-01.svg
@@ -0,0 +1,14 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:html="http://www.w3.org/1999/xhtml"> + <g id="testmeta"> + <title>Pattern: fill-opacity</title> + <html:link rel="help" + href="https://www.w3.org/TR/SVG2/pservers.html#Patterns"/> + <html:link rel="match" href="reference/pattern-opacity-01-ref.svg"/> + </g> + <defs> + <pattern id="pattern" width='1' height='1' patternContentUnits="objectBoundingBox">> + <rect fill="lime" width="1" height="1"/> + </pattern> + </defs> + <rect width="100%" height="100%" fill-opacity="0.5" fill="url(#pattern)"/> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/pattern-opacity-01-ref.svg b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/pattern-opacity-01-ref.svg new file mode 100644 index 0000000..1c9c68b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/pservers/reftests/reference/pattern-opacity-01-ref.svg
@@ -0,0 +1,3 @@ +<svg xmlns="http://www.w3.org/2000/svg"> + <rect width="100%" height="100%" fill-opacity="0.5" fill="lime"/> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/webtransport/datagrams.https.any.js b/third_party/blink/web_tests/external/wpt/webtransport/datagrams.https.any.js index dc7133bb..d5b8e3b 100644 --- a/third_party/blink/web_tests/external/wpt/webtransport/datagrams.https.any.js +++ b/third_party/blink/web_tests/external/wpt/webtransport/datagrams.https.any.js
@@ -171,17 +171,24 @@ promise_test(async t => { // Establish a WebTransport session. - const wt = new WebTransport(webtransport_url('echo.py')); + const wt = new WebTransport(webtransport_url('echo_datagram_length.py')); await wt.ready; const writer = wt.datagrams.writable.getWriter(); const reader = wt.datagrams.readable.getReader(); // Write and read max-size datagram. - await writer.write(new Uint8Array(wt.datagrams.maxDatagramSize)); + const maxDatagramSize = wt.datagrams.maxDatagramSize; + await writer.write(new Uint8Array(maxDatagramSize)); + + // the server should echo the datagram length encoded in JSON const { value: token, done } = await reader.read(); assert_false(done); - assert_equals(token.length, wt.datagrams.maxDatagramSize); + + const decoder = new TextDecoder(); + const datagramStr = decoder.decode(token); + const jsonObject = JSON.parse(datagramStr); + assert_equals(jsonObject['length'], maxDatagramSize); }, 'Transfer max-size datagram'); promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/webtransport/handlers/echo_datagram_length.py b/third_party/blink/web_tests/external/wpt/webtransport/handlers/echo_datagram_length.py new file mode 100644 index 0000000..f0610b0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webtransport/handlers/echo_datagram_length.py
@@ -0,0 +1,8 @@ +import json + +def datagram_received(session, data: bytes): + # encode the received length into a JSON string and send back + data_len = len(data) + out_datagram_json = json.dumps({'length': data_len}) + out_data = out_datagram_json.encode() + session.send_datagram(out_data)
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-contain/container-queries/container-type-sticky-computed.html b/third_party/blink/web_tests/wpt_internal/css/css-contain/container-queries/container-type-sticky-computed.html new file mode 100644 index 0000000..e535178 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-contain/container-queries/container-type-sticky-computed.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Computed values of container-type with sticky</title> +<link rel="help" href="https://drafts.csswg.org/css-contain-3/#container-type"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/computed-testcommon.js"></script> +<script src="/css/css-contain/container-queries/support/cq-testcommon.js"></script> +<div id="target"></div> +<script> + setup(() => assert_implements_container_queries()); + + test_computed_value('container-type', 'sticky'); + test_computed_value('container-type', 'sticky size', 'size sticky'); + test_computed_value('container-type', 'inline-size sticky'); +</script>
diff --git a/third_party/blink/web_tests/wpt_internal/css/css-contain/container-queries/container-type-sticky-parsing.html b/third_party/blink/web_tests/wpt_internal/css/css-contain/container-queries/container-type-sticky-parsing.html new file mode 100644 index 0000000..9c4ffded --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/css/css-contain/container-queries/container-type-sticky-parsing.html
@@ -0,0 +1,20 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Containment Test: Parsing of container-type with sticky/title> +<link rel="help" href="https://drafts.csswg.org/css-contain-3/#container-type"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/parsing-testcommon.js"></script> +<script src="/css/css-contain/container-queries/support/cq-testcommon.js"></script> +<div id="target"></div> +<script> + setup(() => assert_implements_container_queries()); + + test_valid_value('container-type', 'sticky'); + test_valid_value('container-type', 'size sticky'); + test_valid_value('container-type', 'sticky inline-size', 'inline-size sticky'); + + test_invalid_value('container-type', 'sticky sticky'); + test_invalid_value('container-type', 'normal sticky'); + test_invalid_value('container-type', 'inline-size block-size sticky'); +</script>
diff --git a/third_party/flatbuffers/OWNERS b/third_party/flatbuffers/OWNERS index 94966f0..8aa51358 100644 --- a/third_party/flatbuffers/OWNERS +++ b/third_party/flatbuffers/OWNERS
@@ -1,3 +1,6 @@ battre@chromium.org csharrison@chromium.org engedy@chromium.org + +# Flatbuffers' versioning is tightly coupled with TFLite. +file://third_party/tflite/OWNERS \ No newline at end of file
diff --git a/tools/clang/scripts/upload_revision.py b/tools/clang/scripts/upload_revision.py index fee94442..9790cc7 100755 --- a/tools/clang/scripts/upload_revision.py +++ b/tools/clang/scripts/upload_revision.py
@@ -87,12 +87,12 @@ Cq-Include-Trybots: chromium/try:android-rust-arm64-dbg Cq-Include-Trybots: chromium/try:android-rust-arm64-rel Cq-Include-Trybots: chromium/try:linux-rust-x64-dbg -Cq-Include-Trybots: chromium/try:linux-rust-x64-rel''' +Cq-Include-Trybots: chromium/try:linux-rust-x64-rel +Cq-Include-Trybots: chromium/try:win-rust-x64-dbg +Cq-Include-Trybots: chromium/try:win-rust-x64-rel''' # These do not pass yet: #Cq-Include-Trybots: chromium/try:mac-rust-x64-rel -#Cq-Include-Trybots: chromium/try:win-rust-x64-dbg -#Cq-Include-Trybots: chromium/try:win-rust-x64-rel is_win = sys.platform.startswith('win32')
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index b264cdc..03c021f 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -156,6 +156,7 @@ }, 'chromium.cft': { + 'linux-arm64-rel-cft': 'gpu_tests_release_bot_minimal_symbols_chrome_for_testing_reclient_arm64', 'linux-rel-cft': 'gpu_tests_release_bot_minimal_symbols_chrome_for_testing_reclient', 'mac-rel-cft': 'gpu_tests_release_bot_minimal_symbols_chrome_for_testing_reclient', 'win-rel-cft': 'gpu_tests_release_bot_minimal_symbols_chrome_for_testing_reclient', @@ -2731,6 +2732,11 @@ 'chrome_for_testing', ], + 'gpu_tests_release_bot_minimal_symbols_chrome_for_testing_reclient_arm64': [ + 'gpu_tests', 'release_bot_reclient', 'minimal_symbols', + 'chrome_for_testing', 'arm64', + ], + 'gpu_tests_release_bot_minimal_symbols_code_coverage': [ 'gpu_tests', 'release_bot', 'minimal_symbols', 'use_clang_coverage', 'partial_code_coverage_instrumentation',
diff --git a/tools/mb/mb_config_expectations/chromium.cft.json b/tools/mb/mb_config_expectations/chromium.cft.json index 09b69f4..207af0ab 100644 --- a/tools/mb/mb_config_expectations/chromium.cft.json +++ b/tools/mb/mb_config_expectations/chromium.cft.json
@@ -1,4 +1,17 @@ { + "linux-arm64-rel-cft": { + "gn_args": { + "dcheck_always_on": false, + "ffmpeg_branding": "Chrome", + "is_chrome_for_testing": true, + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "symbol_level": 1, + "target_cpu": "arm64", + "use_remoteexec": true + } + }, "linux-rel-cft": { "gn_args": { "dcheck_always_on": false,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index 05c15e6a..3f4b983 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -11855,6 +11855,9 @@ </action> <action name="IOS.OpenIn.Presented" not_user_triggered="true"> + <obsolete> + This flag no longer exists. OpenIn toolbar been removed in M113. + </obsolete> <owner>mrefaat@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <description> @@ -11864,6 +11867,9 @@ </action> <action name="IOS.OpenIn.Tapped"> + <obsolete> + This flag no longer exists. OpenIn toolbar been removed in M113. + </obsolete> <owner>mrefaat@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index a0c809a..d939914 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1327,7 +1327,7 @@ </histogram> <histogram name="Tabs.PersistedTabData.Deserialize.Critical" - enum="BooleanSuccess" expires_after="2023-06-19"> + enum="BooleanSuccess" expires_after="2024-05-14"> <!-- P2 project which hasn't launched yet --> <owner>yusufo@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 6847a0a..e170d75f 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -21,8 +21,8 @@ "full_remote_path": "perfetto-luci-artifacts/v34.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "dba28497d132b963956df1501b7732b08313ddfe", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/f18d5dceede0c5bc68675a4fbf964b467c919511/trace_processor_shell" + "hash": "cdf225e1faad44eda1e7046e0908026e678c746e", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/cb3dce3b1e0615372e8fbe669622c03456467a96/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/page_sets/rendering/tough_scrollbar_scrolling_cases.py b/tools/perf/page_sets/rendering/tough_scrollbar_scrolling_cases.py index acc437a..f13f821 100644 --- a/tools/perf/page_sets/rendering/tough_scrollbar_scrolling_cases.py +++ b/tools/perf/page_sets/rendering/tough_scrollbar_scrolling_cases.py
@@ -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 time +import os from telemetry.internal.actions import page_action from telemetry.page import shared_page_state @@ -32,8 +33,8 @@ extra_browser_args=extra_browser_args) def RunPageInteractions(self, action_runner): - scrollbar_x, scrollbar_top, scrollbar_bottom = self._ScrollBarRatios( - action_runner) + scrollbar_x, scrollbar_top, scrollbar_bottom, top_button, bottom_button = \ + self._ScrollBarRatios(action_runner) start = time.time() with action_runner.CreateGestureInteraction('DragAction'): direction = 'down' @@ -43,14 +44,14 @@ left_start_ratio=scrollbar_x, top_start_ratio=scrollbar_top, left_end_ratio=scrollbar_x, - top_end_ratio=scrollbar_bottom, + top_end_ratio=bottom_button, speed_in_pixels_per_second=self.SPEED_IN_PIXELS_PER_SECOND) else: action_runner.DragPage( left_start_ratio=scrollbar_x, top_start_ratio=scrollbar_bottom, left_end_ratio=scrollbar_x, - top_end_ratio=scrollbar_top, + top_end_ratio=top_button, speed_in_pixels_per_second=self.SPEED_IN_PIXELS_PER_SECOND) direction = 'up' if direction == 'down' else 'down' @@ -88,17 +89,45 @@ window_width = float(action_runner.EvaluateJavaScript('window.innerWidth')) window_height = float( action_runner.EvaluateJavaScript('window.innerHeight')) + # Add logic to account for Fluent scrollbars on Windows. + # TODO(crbug.com/1445774): Investigate why this logic causes performance + # regressions on Linux and reunify code paths. + if os.name == 'nt': + # Works only when there is no horizontally overflowing content. + left_margin = float( + action_runner.EvaluateJavaScript( + 'document.body.getBoundingClientRect().x')) + body_width = float( + action_runner.EvaluateJavaScript( + 'document.body.getBoundingClientRect().width')) + top_margin = float( + action_runner.EvaluateJavaScript( + 'document.body.getBoundingClientRect().y')) + window_height = window_height - top_margin - # For regular scrollbars the minimal thumb length is one and two times the - # track's width in W10 and W11 respectively. For Fluent scrollbars the - # minimal thumb length is 17px. The constant was chosen such that: - # (Button Length) <= (Track width * |track_to_arrow_button_ratio|) <= - # (Button Length + Minimum thumb length) for all scrollbars. - track_to_arrow_button_ratio = 1.8 - top = (scrollbar_thickness * track_to_arrow_button_ratio) / window_height - bottom = 1 - top + # For regular scrollbars the minimal thumb length is one and two times the + # track's width in W10 and W11 respectively. For Fluent scrollbars the + # minimal thumb length is 17px. The constant was chosen such that: + # (Button Length) <= (Track width * |track_to_arrow_button_ratio|) <= + # (Button Length + Minimum thumb length) for all scrollbars. + track_to_arrow_button_ratio = 1.8 + top = (scrollbar_thickness * track_to_arrow_button_ratio - + top_margin) / (window_height) + bottom = 1 - (scrollbar_thickness * + track_to_arrow_button_ratio) / window_height + scrollbar_mid_x = (window_width - left_margin - + (scrollbar_thickness / 2)) / body_width + # Ensure the thumb goes through the full range of motion. These + # variables make the the mouse drag until the middle of the scrollbar + # buttons. + top_button = ((scrollbar_thickness / 2) - top_margin) / window_height + bottom_button = 1 - (scrollbar_thickness / 2) / window_height + return scrollbar_mid_x, top, bottom, top_button, bottom_button + top = 0 + bottom = 1 - (scrollbar_thickness * 1.5) / (window_height + + scrollbar_thickness) scrollbar_mid_x = (window_width + (scrollbar_thickness / 2)) / window_width - return scrollbar_mid_x, top, bottom + return scrollbar_mid_x, top, bottom, top, bottom def WillStartTracing(self, chrome_trace_config): chrome_trace_config.EnableUMAHistograms(*TOUGH_SCROLLBAR_UMA)
diff --git a/tools/perf/page_sets/tough_scrolling_cases/text.html b/tools/perf/page_sets/tough_scrolling_cases/text.html index 10ae1448..01cd6565 100644 --- a/tools/perf/page_sets/tough_scrolling_cases/text.html +++ b/tools/perf/page_sets/tough_scrolling_cases/text.html
@@ -1,9 +1,4 @@ <!DOCTYPE html> -<style> -body, h1 { - margin: 0px; -} -</style> <body> <h1>Lorem ipsum dolor</h1><h2>Sit amet vitae</h2><p>Magna sed dolores. Phasellus aliquam suscipit. Molestie rutrum quia. Feugiat laborum sapien. Vehicula dapibus placerat velit et lacus ullamcorper.</p><ol><li>Sapien ultrices phasellus feugiat nec aut.</li><li>Nam risus tellus.</li><li>Et aliquam diam.</li><li>Libero urna eget.</li><li>Lobortis erat pellentesque.</li><li>Deleniti a vestibulum.</li><li>Congue lectus erat nullam.</li></ol><h2>Nec porta feugiat egestas sapien cras</h2><p>Pellentesque suscipit mattis. Cras magna non. Vestibulum lectus rhoncus. At in arcu. Quam bibendum ac. Nullam sed id sed.</p><p>Metus vehicula feugiat. Ante mauris nunc. Nam mauris erat. Metus pellentesque metus. Et est sodales. In in malesuada. Nulla auctor cras adipiscing leo erat id.</p><h2>Dolor vulputate cras</h2><p>Maecenas aliquet arcu. Et lorem fusce. Quis est id pulvinar feugiat auctor. Risus nam ornare. Vestibulum praesent lorem. Fringilla morbi a phasellus.</p><p>Laoreet proin vestibulum. Mi scelerisque semper. Id magna nec non vestibulum condimentum. Omnis suscipit eu. Ut dictum wisi. Ullamco ac eu. Posuere eleifend risus non.</p><h2>Vivamus amet rutrum</h2><p>Ligula dolor ut. Lacus donec porta tellus velit ut. In eu eget. Diam quis magna. In wisi phasellus. Sed arcu lectus leo.</p><p>Donec wisi eget. Venenatis et interdum. Posuere libero quis. Primis lectus proin neque blandit quisque. Eu nibh mi. Felis urna facilisi. Rutrum scelerisque mauris nunc.</p><h2>Dui vivamus urna blandit at quam</h2><p>Eget ut quam. Semper ullamcorper risus. Lorem pretium nunc. Enim dis velit. Litora dolor mollis. Pellentesque fusce ipsum morbi.</p><p>Id velit mauris. Magna ac non. Sapien sociosqu mauris habitant ante dolor. Amet nullam sit. Viverra at aliquet. In magna odio. Urna eros velit neque.</p><h2>Nibh tellus elementum</h2><p>Libero egestas semper. Sed sit voluptates. Phasellus viverra sit. Nec dolor sit. Blandit mi morbi. Mauris nulla tortor pretium eget aptent ipsum.</p><p>Mauris porttitor dui. Diam vehicula tincidunt. Tellus rhoncus molestie. Qui id tincidunt. Integer augue congue. A in enim. Fringilla accumsan pulvinar gravida pede sit sociis.</p><h2>Facilisis laoreet blandit</h2><p>Elit amet massa. Placerat urna nulla. Mollis magna penatibus. Scelerisque non porta. Eu neque quam. Urna nec placerat felis non diam purus.</p><p>Lectus integer dictum. Ut faucibus in. Condimentum commodo sit. Eget justo nec. Eu vestibulum risus. Proin morbi ac. Ultrices et lorem vehicula tortor placerat cursus.</p><h2>Nec risus mollis</h2><p>Velit orci justo. Mollis eleifend aenean. Enim maecenas ante. Lorem sollicitudin sit. Vestibulum sem lorem. Dolor pretium nulla tortor diam placerat ligula.</p><p>Proin rhoncus velit. Nisl pede magna magna venenatis fusce. Nihil nec sollicitudin. Gravida sed est. Urna dictum eros. Tincidunt montes vestibulum. Et nulla tristique quam.</p><h2>Velit ut mi</h2><p>Elit amet sapien. Aliquam ligula nec. Accumsan nulla leo vel eu ac. Sed et blandit. Curabitur conubia eros. Vivamus gravida ridiculus commodo.</p><p>Purus vulputate aptent. Augue vestibulum urna. Viverra ullamcorper turpis. In sodales facilisis. Id urna quam. Donec non bibendum. Volutpat et mattis wisi quis ipsum est.</p><h2>Et quam et</h2><p>Ipsum malesuada quam. Metus eget aliquet sit massa leo. Aliquam veniam venenatis. Nec sagittis euismod. Nunc vitae mollis. Iaculis ut nec enim.</p><p>In wisi pede. Dapibus urna tellus. Ut pede quis. Sit blandit phasellus. Metus interdum nam. Nec convallis ante. Faucibus maecenas enim nulla nunc lorem suscipit.</p><h2>Hac euismod lacinia</h2><p>Luctus nibh pellentesque. Etiam scelerisque phasellus. Sodales ultrices vitae massa mollis sem. Ultrices etiam neque. Integer mauris suscipit. Non nullam dui faucibus.</p><p>Ligula mauris non. Quisque vestibulum eleifend. Nulla massa eros tellus ipsum lorem. Sed vestibulum ac. Malesuada cras nisl. Est molestie dui. Luctus urna hendrerit arcu.</p><h2>Eu libero non</h2><p>Ligula dolor et. Justo nunc faucibus. Purus velit nulla facilisi sollicitudin phasellus. Erat platea sodales. Bibendum libero wisi. Quisque ipsum qui per.</p><p>Amet sit ut. Nascetur vestibulum turpis facilisis culpa congue. Nonummy tempor suspendisse. Convallis purus mollis. A commodi con. Nulla curabitur vitae. Metus pretium auctor adipiscing.</p><h2>Sed in nisl fames integer wisi</h2><p>Justo purus donec. Laoreet ultrices proin. Maecenas officia donec. In elit amet. Id platea et. Donec ante orci vitae.</p><p>Cras mattis commodo. Vitae ipsum id. Enim at nec. Luctus magna lorem. Scelerisque quis est. Enim sociis nulla. Facilisis vitae con vestibulum malesuada sit posuere.</p><h2>Eius tristique suspendisse</h2><p>Malesuada praesent nibh. Pharetra adipiscing id. Diam mattis integer ipsum at risus. Commodo non orci. Ullamcorper et mi. Ac et mollis vel.</p><ul><li>Lacus platea in.</li><li>Dignissim quam lacus.</li><li>Et leo cursus in donec hymenaeos.</li><li>Nunc pretium tellus.</li><li>Tellus vestibulum lacus.</li><li>Eu bibendum vitae.</li><li>Lobortis congue risus diam.</li></ul><h2>Nulla ut vel</h2><p>Justo pretium purus. In pellentesque urna. Consequatur reprehenderit praesentium posuere ante eu. Pellentesque quisque vel. Ipsum a metus. Quam lorem eu tellus.</p><p>Est etiam ut. Faucibus quis magna. Integer integer cubilia hymenaeos aliquam risus. Fusce amet fermentum. Quis lorem nunc. Pede eros mollis. Illo arcu sit at.</p><h2>Ullamcorper odio nec</h2><p>Lacus duis orci. Enim velit neque. Aliquam leo torquent. Placerat elit sit nec lectus posuere. Fusce eleifend bibendum. Commodo odio quis dui.</p><ol><li>Ornare eget odio.</li><li>Vivamus porttitor totam.</li><li>Donec imperdiet donec tincidunt sed risus.</li><li>Urna facilisis mattis.</li><li>Nulla eros in.</li><li>Lectus volutpat erat.</li><li>Mollis semper duis augue.</li></ol><h2>Sapien ante dapibus</h2><p>Urna consequat ac. Laoreet odio varius cursus sed mauris. Dolor sed orci. Aut lectus ligula. Amet ut tellus. Non ac a quam.</p><p>Nonummy dui magna. At egestas odio. Sed a perferendis. Sed varius et. Donec nascetur lorem. Lectus non phasellus. Sed elementum convallis aliquet vehicula pellentesque lacinia.</p><h2>Quis semper nibh mauris mauris justo</h2><p>Augue hac nunc. Aliquam imperdiet a. Nisl blandit curabitur. Curae pede dolor. Lacinia tempor nulla. Bibendum curabitur wisi eget.</p><ul><li>In fermentum fames aliquam non purus.</li><li>Consequat parturient eget.</li><li>Repellat suspendisse vitae.</li><li>Ad natoque arcu.</li><li>Velit elit vitae.</li><li>Suscipit eu molestie.</li><li>Vel diam rem ut.</li></ul><h2>Eget quis sollicitudin</h2><p>Mattis sapien quam. Id phasellus nunc. Vivamus wisi arcu. Suscipit nibh tristique. Venenatis lobortis et. Curabitur ut eu dolor eros sociosqu congue.</p><p>Mattis risus enim potenti arcu dui. Vitae nec sed. Tempus wisi duis. Ut mi aliquam. Ante ultrices ante. Pharetra sodales vivamus. Quis quis arcu in.</p><h2>Iaculis lectus aliquam</h2><p>Rhoncus sodales tortor. Vitae voluptatem sed nostra blandit ligula. Turpis est et. Vestibulum pede vestibulum. Facere laoreet suspendisse. Dapibus nec viverra sit.</p><p>Montes elementum vestibulum. Duis neque platea. In eros a. Condimentum id id hymenaeos pellentesque iaculis. Magna at blandit. Tenetur et venenatis. Lectus lobortis feugiat urna.</p><h2>Justo nunc curae</h2><p>Sociosqu sodales neque. Vitae habitasse quam. Etiam congue praesent. Libero leo sit potenti maecenas pellentesque. Ipsa cras pellentesque. Rhoncus non leo cras.</p><p>Metus elit massa. Aenean quisque sed. Mauris erat imperdiet. Vel quis donec. Sed erat lacus. Et neque convallis erat et sit. Non eu bibendum integer.</p><h2>Dolor bibendum etiam</h2><p>At molestie nisl. Mi eleifend vivamus. Etiam pede ultricies in sit eget. Consectetuer etiam consectetuer. Neque orci ut. Amet vestibulum luctus odio.</p><ol><li>Ante augue aptent.</li><li>Bibendum id mi.</li><li>Mollit ut nullam congue potenti feugiat.</li><li>Ipsum vehicula pulvinar.</li><li>Nec elit consequatur.</li><li>Massa velit arcu.</li><li>Magna vehicula orci rhoncus.</li></ol><h2>Amet donec parturient</h2><p>Curabitur ut parturient. Phasellus odio eleifend. Et penatibus magna suscipit vestibulum neque. Facilisis a donec. Lectus vitae orci. Ultrices magna luctus a.</p><p>Vestibulum iaculis metus. Est vel curabitur. Nec cras vel. Tellus nunc quis. A nunc vestibulum. Id dolor donec. Egestas leo vulputate lorem duis lectus ullamcorper.</p><h2>A tincidunt et</h2><p>Arcu tincidunt vestibulum. Ultrices egestas enim. Nam et amet. Neque sed quam. Ultricies tellus vestibulum. Eleifend vivamus mauris eget dictumst turpis nec.</p><p>Placerat arcu fames. Wisi non tristique. Porttitor fusce per. Ipsum rhoncus maecenas. A ornare donec. Conubia tellus eleifend ipsum praesent in. Facilisis venenatis montes suscipit.</p><h2>Vel condimentum commodo</h2><p>Et pede ante. Leo aliquam praesent. Mollis aliquet tincidunt fusce sit dui. Mi pede mollis. Porta curabitur debitis. Mauris sed rhoncus rhoncus.</p><ol><li>Ipsum non ut.</li><li>Voluptas elit elementum pede ante pellentesque.</li><li>Nisl neque scelerisque.</li><li>Mauris nibh in.</li><li>In eros sit.</li><li>Et tellus maecenas.</li><li>Orci erat dui metus.</li></ol><h2>Nunc velit wisi</h2><p>Velit a rhoncus. Diam at class nibh in sed. Sollicitudin libero a. Nunc dictum orci. Tenetur sed fermentum. Sapien ac mauris per.</p><p>Nam accumsan ipsam. Venenatis sed consectetuer. Sem praesent pharetra. Vitae sed diam. Ornare erat vel at maecenas suspendisse. Leo ligula ligula. Nonummy dolor sapien tristique.</p><h2>Magnis odio sed</h2><p>Elit imperdiet fermentum. Nunc morbi id. Massa venenatis gravida. Amet suscipit ullam nullam suspendisse est. Eget elit mollis. Volutpat dapibus ut nascetur.</p><p>Urna pede suspendisse. Donec dui libero. Et fermentum vivamus. Eu magnis fames. Id maecenas hendrerit. Fringilla sapien turpis ultricies hac nascetur. Fermentum magna adipiscing consequat.</p><h2>Eros metus justo ante vivamus vitae</h2><p>Magnis risus nec. Ad suspendisse pellentesque. Dui phasellus neque. Justo sapien mi. Aliquet ac gravida. Eu sollicitudin suscipit integer.</p><ol><li>Est luctus quis.</li><li>Felis vivamus malesuada.</li><li>Penatibus tellus nulla per mattis magna.</li><li>Justo mauris ac.</li><li>Eu ut sit.</li><li>Id non consectetuer.</li><li>Cursus torquent pellentesque felis.</li></ol><h2>Sapien lacus mollis</h2><p>Tempor vitae tempor. Dolor odio ultrices. Sed amet at. Elit a porta. Amet nam aliquet. Vivamus cras sit amet vestibulum proin praesent.</p><p>Duis orci egestas. Aliquam morbi pellentesque tristique aliquam phasellus. In eu nunc. Pede placeat nulla. Auctor id massa. Urna odio augue. Wisi ut pellentesque dignissim.</p><h2>Gravida libero eros con diam ut</h2><p>Neque nec in. Rhoncus nec pede. Ac ipsum eu. Reiciendis vitae viverra. Quis iaculis phasellus. Semper nunc neque in.</p><p>Dolorum pharetra massa. Mi platea velit quis aut eget. Tellus aut dui. Id nec commodo. Sed ipsum lorem. Dolorum aliquam mi. Non fusce scelerisque bibendum.</p><h2>Duis eget adipiscing</h2><p>Nibh diam magna. Metus dapibus at. Mauris eros sodales. Fringilla facilisis fusce. Cras id laoreet. Id ut ad est maecenas sodales sagittis.</p><p>Porta sed suscipit. Vehicula libero sit. Purus varius massa. Erat sem sit. Faucibus ut euismod. Quam lorem bibendum. Euismod elit turpis eget ipsum eleifend nec.</p><h2>Magnis neque bibendum</h2><p>Morbi suscipit nunc est felis laoreet. Condimentum vitae placerat. Mi iaculis mauris. At enim eu. A sem fermentum. Pellentesque tempor condimentum elit.</p><p>Pede urna ullamcorper massa molestiae nibh. Donec sodales hac. Vulputate metus feugiat. Egestas parturient pellentesque. Corporis vel imperdiet. Id velit erat. Tincidunt eget id fusce.</p><h2>Amet pellentesque temporibus</h2><p>Mauris perferendis vitae. Rutrum cras aliquet. Tempor penatibus turpis. Magnis pellentesque in. Massa maecenas ipsum. Suspendisse dolor mauris dui lacinia pharetra feugiat.</p><p>Quis duis pulvinar. Id lacus duis. In nulla varius. Sit vivamus sed. Vel pellentesque praesent. Non accumsan non. Lectus libero vestibulum ultrices et sollicitudin wisi.</p><h2>Non fusce non</h2><p>Orci pellentesque nobis. Nullam wisi modi. A gravida pharetra maecenas eget nec. Odio nonummy eget. Vestibulum quis mus. Accumsan eros sem nam.</p><p>Id tellus alias. Ipsum a id. Vitae quia est elit nec eleifend. Id porta sapien. Integer scelerisque in. Augue elementum debitis. Mauris vivamus aliquet cras.</p><h2>Sed eget hendrerit wisi venenatis amet</h2><p>Bibendum conubia leo. Est vivamus nullam. Amet maecenas libero. Aliquam proin aut. Donec diam amet. Tincidunt blandit vel mauris.</p><ul><li>Vestibulum mauris ac.</li><li>At ligula libero.</li><li>Tortor massa neque.</li><li>Ut metus nam.</li><li>Cras eu tincidunt.</li><li>Dictumst in nam.</li><li>Sed vitae orci vitae suscipit ipsum dictum.</li></ul><h2>Morbi lacinia sit</h2><p>Fringilla risus sed. Tempor lectus phasellus. Fringilla recusandae justo feugiat purus vel. Urna consequat pretium. Semper dui mauris. Ut tortor consectetuer quisque.</p><p>Nunc aliquam eget habitant morbi odio. Wisi ligula sit. Amet suspendisse purus. Nulla condimentum in. Mi dapibus pellentesque. Quam soluta suspendisse. Placerat tristique fermentum venenatis.</p><h2>Eget nisl tempus</h2><p>Donec litora quis. Donec a ante. Sit sed quis massa augue dui. At tellus ipsum. Felis parturient sit. Fringilla mauris egestas praesent.</p><p>Tempor nam cras. Vel congue proin. Sit eget sollicitudin aliquam id nostra. Dolor elit ut. Massa eu rutrum. Facilisis in ipsum. Quis ornare etiam vel.</p><h2>Praesent ac lorem</h2><p>Lorem vivamus eu. Sapien et ac. Duis nisl elementum. At magna a. Malesuada interdum ante quam felis accumsan. Mattis eu purus aliquam.</p><p>Ut erat elit. Pellentesque rhoncus risus. Ante hendrerit vulputate. Ligula amet dignissim. Bibendum pellentesque per. Varius non egestas. Vitae in metus sed vestibulum vestibulum ut.</p><h2>Tempus nunc vestibulum lacus eget elit</h2><p>Wisi nullam sem. Eleifend adipiscing purus. Nullam quisque non. Mi ultricies urna. Lacus voluptatem placerat. Rutrum ac enim bibendum.</p><p>Vitae gravida quis. Convallis suspendisse phasellus. Pariatur neque id. Auctor fringilla vitae. Nec modi eu at neque magna. Elit fames sed. Habitant neque est taciti.</p><h2>At lacus fusce</h2><p>Amet etiam vestibulum. Donec massa et nec potenti natoque. Convallis cras quis. Aliquam arcu risus. Nec scelerisque adipiscing. Commodo justo in ut.</p><p>Sodales luctus justo. Amet nam quam. In tellus dui. Potenti non vestibulum. Bibendum pretium pellentesque ut vivamus non. Varius sit pretium. Ut vivamus aliquam leo.</p><h2>Sed amet ac ut in et</h2><p>Placerat ut sit. Felis vulputate magna. Nisl tincidunt aliquet. Auctor nunc metus. A lobortis volutpat. Sociis donec ut nisl.</p><p>Ac posuere aenean. Dis quis ultricies. Inceptos nunc dolorum. Velit vitae mollis. Quis etiam cras. Curabitur ut metus. Magna pellentesque ipsum convallis curabitur rutrum tellus.</p><h2>Mollis leo fusce</h2><p>Pellentesque tincidunt pede. Vel eius inceptos. At ullamcorper purus nibh cras in. Mauris in ullamcorper. Rhoncus mi pharetra. Nulla malesuada sed etiam.</p><p>Bibendum blandit deserunt ligula sed nibh. Neque sit urna. Dignissim suspendisse ante. Vestibulum mauris nec. Lacus non consectetuer. Donec in enim. Phasellus fermentum arcu montes.</p><h2>Nec nostra sociis</h2><p>Quisque adipiscing ultrices. Dictum amet imperdiet. Sem non aut. Luctus ultricies sapien. Consectetuer id eleifend. Semper viverra nisl lectus blandit eros pellentesque.</p><p>Dolor rhoncus fringilla mi aliquam neque. Dapibus donec ullamcorper. Ut senectus sapien. Sit id porta. Quis sit eleifend. Ut sed sagittis. Pretium egestas donec odio.</p><h2>Nulla ornare cursus</h2><p>Magna porta ultrices. Arcu felis etiam. Urna rhoncus volutpat massa urna eros. Arcu arcu risus. Urna blandit aliquam. Quisque velit lorem gravida.</p><ul><li>Rhoncus ultrices eget.</li><li>Aliquam et sed.</li><li>Nulla nec purus.</li><li>Per lacus vestibulum.</li><li>Porttitor ipsum con felis penatibus sodales.</li><li>Vitae rhoncus sed.</li><li>In nullam sed in.</li></ul><h2>Sem eu ante</h2><p>Libero vestibulum euismod. Et odio fringilla. Ut nec semper. Aspernatur mi duis. Fermentum porta ut. Eu in in aliquam rhoncus purus eget.</p><p>Dui adipiscing vestibulum. Tincidunt dis sollicitudin sed fringilla eget. Donec sed augue. Molestie wisi tempor. Mollis massa leo. Ipsum dui tempor. Eu duis morbi felis.</p><h2>Enim nulla faucibus</h2><p>Fusce sed elit et convallis amet. Sollicitudin in dapibus. Pede et arcu. Sollicitudin sagittis netus. Eu quisque bibendum. At vitae orci tortor.</p><p>Odio hac mi. Et ut quam inceptos ridiculus facilisi. Sed lobortis pede. In nonummy eget. Varius turpis urna. Risus vehicula sapien. Ridiculus libero dui egestas.</p><h2>Tincidunt curabitur volutpat vestibulum dictum aenean</h2><p>Porttitor class convallis. Tristique eu varius. Sociosqu urna turpis. Nibh rhoncus felis. Eros dapibus malesuada. Dui ut ac velit.</p><ul><li>Urna libero curabitur.</li><li>Nunc odio at.</li><li>Dictum amet consectetuer.</li><li>Con in neque.</li><li>In vitae amet.</li><li>Aliquam venenatis consequat.</li><li>Ante nullam posuere justo scelerisque lectus ut.</li></ul><h2>Metus quam et</h2><p>Purus egestas nunc. Hendrerit vestibulum metus. Ultrices ridiculus cillum. Adipiscing blandit dolor fermentum pretium ullamcorper. In et nulla. Morbi vitae suspendisse maecenas.</p><p>Scelerisque ut velit. Quis tellus laoreet. Aenean nullam mi turpis in vestibulum. Etiam id eget. Diam porta adipiscing. At ante sem. Mauris a velit ultrices.</p><h2>Elit maecenas vestibulum</h2><p>Ac arcu nulla. Vitae vestibulum a. In senectus a. Ipsum metus libero. Adipiscing morbi risus. Vulputate tortor sem velit mi bibendum hendrerit.</p><p>Ut donec venenatis. Aliquam nisl commodo. Vel vitae platea. Sit lacus quis. Conubia dapibus sapien. Arcu in magna justo sed odio. Donec nec justo dolor.</p><h2>Vitae tellus risus</h2><p>Amet ante non. Purus quis ut. Per eget nostra. Mattis laoreet laoreet. Diam tincidunt eu. Eget dui sollicitudin penatibus et justo vulputate.</p><ol><li>Mattis vel at.</li><li>Euismod quam eget.</li><li>Sollicitudin amet erat.</li><li>Iaculis fermentum imperdiet.</li><li>Urna suspendisse venenatis lorem nunc egestas.</li><li>Ac praesent sit.</li><li>Elit proin ridiculus mi.</li></ol><h2>Nam etiam nibh</h2><p>Tellus varius amet in wisi nisl. Officia vestibulum adipiscing. Suspendisse augue pede. Venenatis in ligula. Nibh nec dolor. Imperdiet sapien nonummy quam.</p><p>Lectus donec nec. Tellus at enim. At nibh ut ante penatibus erat. Odio nam gravida. Eget justo nunc. Nisl ornare laoreet. Porta felis ut risus.</p><h2>Quam fringilla pellentesque</h2><p>Sodales maecenas elit. Molestie rhoncus sit. Distinctio in quam elit ullamcorper pulvinar. Et leo consectetuer. Amet est aliquet. Quis etiam at risus.</p><p>Viverra magna risus. Proin orci vehicula. Arcu volutpat mattis. Eu pellentesque libero. Suspendisse ultricies porttitor ac rhoncus explicabo. Sem non consequat. Pretium vel sollicitudin morbi.</p><h2>Dictum dictum autem</h2><p>Praesent aliquam sem. Ac lacinia nemo. Per eu praesent. Quis voluptates vivamus auctor nec malesuada. Magni irure laoreet. Amet ullamcorper ac aliquet.</p><ol><li>Torquent orci donec.</li><li>Integer tristique nonummy.</li><li>Hendrerit fringilla massa.</li><li>Pede ridiculus in.</li><li>Scelerisque nec tincidunt.</li><li>Nulla elit cras convallis odio in.</li><li>Quisque molestie semper donec.</li></ol><h2>Non dolorem magna aliquam facilisis pharetra</h2><p>Eget porta justo. Et habitasse habitasse. Nulla lacus orci. Dui adipiscing neque. Scelerisque in neque. Suspendisse vitae leo arcu.</p><p>Ultricies lorem id. Tincidunt sit ligula amet condimentum blandit. At eros hac. Nullam sagittis velit. Commodo praesent vestibulum. Sit ipsum sed. Accumsan donec augue mollis.</p><h2>In pellentesque wisi</h2><p>Massa dui ipsum. Tempus lectus sed. Aliquet augue sed ac integer condimentum. Rhoncus vitae massa. Rutrum diam eu. Sollicitudin nec ante ac.</p><p>Enim a mollis eleifend rutrum scelerisque. Lacus luctus bibendum. Erat convallis semper. Lectus sit consectetuer. Eget ac sed. Lorem blandit cras. Curabitur proin diam cras.</p><h2>Iaculis erat velit</h2><p>Mauris adipisci neque. Neque vestibulum vestibulum donec in mauris. Nibh maecenas et. Dui suscipit molestie. Proin amet aenean. Fermentum magnis nullam porttitor.</p><ul><li>Mauris libero maecenas.</li><li>Sem nulla magna.</li><li>Molestie congue sit.</li><li>Eu turpis curabitur metus vivamus laoreet.</li><li>Tristique id sit.</li><li>Veritatis wisi suspendisse.</li><li>Quisque vehicula quam non.</li></ul><h2>Et tortor dolor</h2><p>Feugiat aenean wisi. Ac pellentesque per. Eleifend nisl nullam. Pulvinar quisque dignissim. Sapien vitae arcu justo pellentesque mollis. Eu nulla eget sed.</p><p>Aliquam ut porttitor. Quis pede odio. Et et cras. Phasellus nec non. Odio tortor quam. Phasellus mus sollicitudin non suspendisse blandit. Dictum praesent ipsum viverra.</p><h2>Conubia placerat malesuada</h2><p>Lectus suspendisse amet. Sit elit commodo. Ipsum aliquam rhoncus magna sed lacus. Elit luctus phasellus. Est ultrices amet. Elit pellentesque purus elit.</p><p>Felis quam imperdiet. Congue adipiscing quis velit mauris fugiat. Eu amet libero. Ut feugiat hac. Arcu massa elit. Luctus id dis. Ipsum et quis sit.</p><h2>Duis est pulvinar</h2><p>Arcu dictum malesuada. Morbi sociosqu nec. Dolor quam dui. Pellentesque nostra congue ut magna leo. Nullam fusce cras. In recusandae imperdiet hendrerit.</p><ul><li>Natoque arcu amet.</li><li>Risus morbi odio.</li><li>Fringilla nulla curabitur.</li><li>Bibendum ac nullam.</li><li>Nam dictumst aliquam.</li><li>Ipsum pede fusce suscipit ultricies in.</li><li>In velit lacinia et.</li></ul><h2>Ornare justo magna tortor quis metus</h2><p>Felis vehicula curabitur. Ut curabitur mollis. Pellentesque enim tellus. Risus tempus sed. Velit dui ut. Mattis ultricies nonummy vel.</p><p>Aliquam sed suspendisse. Nullam tristique ac hac ante parturient. Etiam curabitur ac. Quisque lorem donec. Senectus torquent a. Proin urna adipisicing. Duis facilisis gravida sed.</p><h2>Facilisis phasellus non</h2><p>Id fringilla dolor. Vel lobortis elementum. Curabitur mollis mauris. Dolorem ut dolor. Diam amet eros metus urna ut. Sed praesent enim sed.</p><ul><li>Lectus quam aenean.</li><li>Sed bibendum cras.</li><li>Risus aperiam tempus.</li><li>Ac id ac.</li><li>At hendrerit gravida metus leo accusamus.</li><li>Elit dapibus urna.</li><li>Donec vestibulum velit proin.</li></ul><h2>Aliqua id quam elit nec nostra</h2><p>Eros iaculis erat. Nulla integer rutrum. A accumsan tempor. Vestibulum dolor vestibulum. Varius nulla convallis. Elit aliquam elit nisl.</p><p>Neque nulla maecenas. Metus mi vivamus. Sapien tempor imperdiet. Pellentesque sit et lobortis vel nibh. Neque mauris eu. Risus nullam lobortis. Quis consectetuer tincidunt est.</p><h2>Ultricies risus sociosqu</h2><p>Ut nulla dolor nulla integer donec. Taciti ornare arcu. Sed cubilia aliquam. Sociis diam nulla. Mattis varius nisl. Malesuada nulla integer wisi.</p><ul><li>Sapien ullamcorper et dignissim proin velit.</li><li>Arcu ut at.</li><li>Eros tristique elementum.</li><li>Et elit duis.</li><li>Pariatur et ut.</li><li>Hac dui sed.</li><li>Lorem tellus metus ligula.</li></ul><h2>Quis lacus aenean</h2><p>Tristique facilisi non. Feugiat pretium volutpat. Metus pharetra ut. Vel vel ac. Nisl porta cras libero fames accumsan. Ante turpis integer magna.</p><p>Nulla at lacus. Vestibulum sollicitudin dolor. Magna turpis elit. Sollicitudin lacus est. At ut erat. Turpis risus sit. Sed taciti felis interdum et suspendisse eu.</p><h2>Duis turpis sed sed amet justo</h2><p>Rhoncus id convallis. Consequat iaculis malesuada. Integer ac at. Integer massa convallis. Integer consequat tempus. Ut egestas nulla praesent.</p><ol><li>Ipsum sit enim.</li><li>Sem et a.</li><li>Vitae a justo.</li><li>Donec in malesuada.</li><li>Netus et mauris.</li><li>Donec habitasse metus justo dignissim vel.</li><li>Cras sed orci vel.</li></ol><h2>Elit dictum lorem</h2><p>Sit ut vel. Tortor risus in. Amet sit sit. Congue ultricies ac. Dignissim duis quam. Erat amet id purus nulla ipsum venenatis.</p><p>Turpis metus lectus. Nunc egestas dui. Integer sit massa. Ac quis vel. Turpis sed gravida. Mauris scelerisque pharetra. Condimentum porttitor elit wisi leo hymenaeos placerat.</p><h2>Dolor phasellus sed</h2><p>Morbi ipsum at. A consequuntur lacinia. Id sed ut risus nunc sodales. Aperiam per neque. Nonummy elementum elit. Justo ante eget suscipit.</p><p>Sed lacinia lobortis. Tortor risus vitae. Nec mauris hac vitae ex a. Lorem aliquam pharetra. Semper dolor dignissim. Maecenas eget lorem. Convallis amet tristique consequat.</p><h2>Tincidunt duis dictum</h2><p>Sit sapien pellentesque. Integer conubia dui porta rutrum cursus. Nibh est elit. Sit vel ut. Elit lectus lobortis. Sollicitudin aliquam sed mattis.</p><p>Pellentesque ac pharetra. Penatibus placerat nunc. Quis tristique curabitur. Diam scelerisque mi laoreet turpis ante. Hymenaeos in augue. Id cursus donec. Dapibus ipsum augue pharetra.</p><h2>Aliquam curabitur magna</h2><p>Aliquam est in. Vestibulum nunc mauris vitae tempus non. Nec pretium quam. Arcu leo a. Sollicitudin tellus sit. Fusce mi maiores primis.</p><ul><li>Sociis nascetur dolor.</li><li>Aenean vestibulum nonummy.</li><li>Vel duis nonummy mattis vestibulum mollis.</li><li>Facilisis bibendum accumsan.</li><li>Pulvinar elit mauris.</li><li>Ante mauris non.</li><li>Amet diam tellus wisi.</li></ul><h2>Pharetra vitae imperdiet</h2><p>Ipsum con est. Fusce ac luctus. Vitae interdum eu dolor hic phasellus. Elementum tristique erat. Pretium sed class. Sollicitudin ligula sed tempor.</p><p>Eget aliquam orci. Suspendisse mauris ut sapien sed suspendisse. Eros ut egestas. Tortor vestibulum litora. Urna pellentesque curae. Luctus condimentum leo. Justo erat eu odio.</p><h2>Posuere ullamcorper condimentum</h2><p>Ligula porta aliquet. Sodales gravida phasellus. Wisi dolor quam. Mattis aliquet id. Volutpat leo velit lacus ullamcorper vestibulum. Suspendisse dolores nam commodo.</p><p>Vel augue vel. Et mauris arcu. Rutrum ac eleifend. Laoreet amet ornare. Morbi quis eu. Sunt erat erat. Dui suspendisse tortor neque eleifend a mi.</p><h2>Pede platea mauris</h2><p>Accumsan sem ac. Sapien tellus libero. Quis tempor amet. Odio dictum tristique. Rutrum congue aliquet. A fames suscipit in porta tincidunt libero.</p><p>Urna odio purus. Aliquet lobortis duis. Sed risus erat. Fermentum turpis pulvinar. Lobortis habitant wisi. Id porttitor etiam eget feugiat porttitor. Per sit tellus vitae.</p><h2>Sit aliquam duis</h2><p>Mauris tortor in. Malesuada cras maecenas. Volutpat arcu dolor. Duis velit feugiat. Etiam neque eleifend ut at vehicula. Amet non cras suspendisse.</p><ul><li>Hendrerit eget eget.</li><li>Et wisi sem.</li><li>A amet lorem lacus sed lacus.</li><li>Risus parturient dolores.</li><li>Sed elit libero.</li><li>Nec nulla suscipit.</li><li>Nec ut vel nulla.</li></ul><h2>Urna tortor in</h2><p>Sed varius ultrices. Sed suspendisse dolor. Commodo velit lobortis. Amet aptent non. In sit wisi. Lorem ut ridiculus nunc eu libero pellentesque.</p><p>Sit earum posuere. Pellentesque neque sed. Tristique tortor nunc tortor at ut. Gravida fames aliquam. Pellentesque molestie massa. Nibh vivamus ipsum. Turpis natoque metus montes.</p><h2>Mollis elit a ut lectus eget</h2><p>Netus dictum eu. Nec nunc wisi. Vel nulla pede. Augue maecenas culpa. Con ut class. Eu aliquam quis viverra.</p><p>Leo vestibulum lacus. Mauris hendrerit venenatis phasellus vitae quis. Morbi proin sed. Non faucibus id. Tincidunt tortor viverra. Metus eu odio. Nibh mollis aliquet nulla.</p><h2>Vestibulum habitasse posuere mollis vestibulum justo</h2><p>Pellentesque magna leo. Est orci amet. Mauris mauris nunc. Maecenas non diam. Nunc etiam nec. Ut condimentum aptent nisl.</p><p>Quam ac magna. Quam leo morbi. Erat augue sit. Ultricies viverra et. Nulla pellentesque earum. Ridiculus arcu enim. Facilisi pretium libero sit metus rhoncus hendrerit.</p><h2>Lorem mauris tellus</h2><p>Eget elit tempus. Nunc iaculis pellentesque. Phasellus etiam lorem. Quis nec sed. Amet ut quis eget odio eleifend. Nullam eros quam in.</p><p>Facilisi nulla amet. Nunc eget tempor quam wisi sed. Morbi nisl excepteur. Eget tristique neque. Ut massa pariatur. Nec feugiat maecenas. Id morbi luctus maecenas.</p><h2>Maecenas phasellus id</h2><p>Imperdiet officia sit. Et et sit sodales at nunc. Vestibulum eget sequi. Ac ligula nulla. In odio lectus. Aliquam vel eu amet.</p><p>Per in nec. Erat urna luctus. Elit bibendum ipsum. Libero augue sagittis. Integer turpis urna. Euismod diamlorem nec. Magna neque vestibulum cras ultricies massa leo.</p><h2>Dolor mauris duis nulla nec dignissim</h2><p>Sed pede lectus. Eu quam vel. Eu neque tortor. Vitae cras phasellus. Bibendum commodo diam. In mauris at magnis.</p><p>Mauris nulla dolor. Pretium nostra donec. Sed mi pede. Cras amet parturient massa wisi vehicula. Rutrum placerat enim. Ut nec dolor. Commodo turpis duis justo.</p><h2>Tincidunt morbi iaculis etiam dapibus sapien</h2><p>In nunc nullam. Vitae ac duis. Pede accumsan quis. Neque placerat sit. Augue id placerat. Nunc gravida ante massa.</p><ul><li>Urna est diam quis turpis augue.</li><li>Convallis volutpat hac.</li><li>Qui ut lectus.</li><li>Ullamcorper amet curabitur.</li><li>Diam odio aliquam.</li><li>Posuere nisl class.</li><li>Wisi a vehicula diam.</li></ul><h2>Pede faucibus purus</h2><p>Sodales et sociis. Pulvinar massa in. Duis lectus quam porta in justo. Tristique a per. Nonummy mauris nunc. Tellus a consectetuer nonummy.</p><ol><li>Ullamcorper a at donec enim eros.</li><li>Leo corrupti cras.</li><li>Eros ut pharetra.</li><li>Sollicitudin posuere cras.</li><li>Facilisis ut sed.</li><li>Mollis non lorem.</li><li>Suspendisse ut urna egestas.</li></ol><h2>Nunc mauris imperdiet</h2><p>Pulvinar libero fermentum. Lectus ullamco etiam. Eget metus vitae. In neque cursus. Urna nibh diam. In interdum dictum justo justo justo id.</p><p>Turpis interdum lorem. In pellentesque vel. Id vitae enim. Sed vestibulum vel. Velit pulvinar gravida. Morbi auctor praesent. Id pellentesque risus aliquip volutpat nibh aenean.</p><h2>Corrupti ut vestibulum</h2><p>Faucibus libero dictumst. Magna magna semper. Id cras lorem risus mauris dictum. Montes etiam quis. Nunc eleifend mauris. Nec odio a nec.</p><p>Ipsum aliquam ut donec nec penatibus. Elit bibendum per. Sodales tempor vel. Maecenas hendrerit justo. Praesent vivamus eu. Tempor erat morbi. Quis nunc integer inceptos.</p><h2>Id nulla diam</h2><p>Ut pellentesque vitae. Sed metus arcu. Eu mattis adipiscing. Sed nulla amet. Massa pellentesque velit. Ac augue lorem rhoncus mauris tristique cupiditate.</p><ol><li>Donec urna dolor amet non sed.</li><li>Tristique libero iaculis.</li><li>Non gravida platea.</li><li>Ante lectus nulla.</li><li>Posuere ligula mauris.</li><li>Curae wisi euismod.</li><li>Donec sagittis turpis tortor.</li></ol><h2>Integer tellus volutpat</h2><p>Nullam eget a. Erat accusamus ad urna nullam feugiat. Et eleifend donec. In velit maecenas. Adipiscing gravida class. Sapien augue integer iaculis.</p><p>Quisque sed mus. Curae amet diam. Est turpis vestibulum ipsum sollicitudin lacinia. Posuere in eu. Mauris culpa tempor. In sapien sociosqu. Nec qui quis eu.</p><h2>Arcu amet neque</h2><p>Id pede maecenas. Enim volutpat condimentum. Nullam quisque sollicitudin. Volutpat auctor sollicitudin. At mi diam. Dui nisl velit porttitor ut in lectus.</p><p>Mollis eget ut. Eu scelerisque imperdiet. Felis dolor fringilla. Dui odio vel. Posuere nec nunc. Feugiat et sed metus ante nibh. Commodo est id sed.</p><h2>Consectetuer nec dolor</h2><p>Risus ut quam. Torquent enim id. Varius vulputate dis. Arcu vestibulum eu. In fusce vitae. Con id mauris fringilla non justo nullam.</p><p>Quis quam ut. Pede sed aliquam. Quisquam fermentum augue. Morbi aliquam fermentum volutpat vestibulum dolor. Urna eu nulla. Cras donec wisi. Pretium dui faucibus sed.</p><h2>Augue aliquet purus</h2><p>Quis venenatis integer. Amet in proin. Ligula fringilla viverra. Bibendum nec molestie dolor eros quis. Egestas ultrices in. Egestas mauris aliquip nascetur.</p><p>Eget diam nunc. Diam felis eros. Aliquam convallis tincidunt. Vestibulum ante proin tenetur tellus interdum. Ac odio neque. Sem blandit morbi. Arcu dapibus tempor molestie.</p><h2>Lorem nec dui</h2><p>Laoreet pede cras. Nonummy nam ullamcorper. At nibh leo. Euismod vestibulum arcu. Quam at amet. Nam felis in et pellentesque lectus in.</p><p>Massa et ullamcorper. Vel etiam tempus montes at bibendum. Leo metus tortor. Nec eleifend eu. Augue non tellus. A est et. Semper suscipit reprehenderit ultrices.</p><h2>Feugiat nulla minus</h2><p>Cursus sit cursus. Tristique pretium iaculis. Urna sed placerat. Eu diam nonummy velit est veniam. Eros sociis felis. Feugiat leo sem enim.</p><p>Libero eleifend felis. Etiam vulputate et. Lobortis debitis eros. Leo pretium accumsan. Vehicula torquent natus. Convallis et viverra sit nam vestibulum. Ut egestas conubia pellentesque.</p><h2>Justo elit nec</h2><p>Sed quis eu. Justo nunc vestibulum. Magna pharetra massa. Neque suspendisse mi orci pharetra ultricies. Consequat velit eget. Nam praesent non id.</p><p>Primis sollicitudin in. Nostra euismod sed. Turpis aliquam lectus. Id nunc elit. Amet mauris amet. Sollicitudin risus fusce. Scelerisque aptent placerat eos neque pretium sed.</p><h2>Magna lectus con</h2><p>In dignissim mi. Aliquam augue morbi. Odit donec in. Turpis tincidunt in morbi dolor tellus. Urna posuere non. Quam sollicitudin laoreet volutpat.</p><ol><li>Risus dolor eiusmod.</li><li>Vel montes placerat.</li><li>Urna nibh aliquet.</li><li>Ultricies libero enim.</li><li>Donec non sit ornare leo nec.</li><li>Nullam quam tincidunt.</li><li>Tincidunt faucibus facilisis elit.</li></ol><h2>Ultrices nulla leo</h2><p>Nec quis ipsum. Nisl rutrum exercitation aliquam felis leo. In quisque blandit. Vestibulum quis ac. Sapien tempus duis. Metus vel sed pellentesque.</p><ul><li>Lectus et dignissim.</li><li>Vel suspendisse dictum.</li><li>Lacus at veniam.</li><li>Lectus tincidunt neque.</li><li>Arcu vestibulum fringilla.</li><li>Quisque velit quam.</li><li>Lectus feugiat class metus donec ipsum non.</li></ul><h2>Ut vitae cursus</h2><p>Mi sit tempor. Fusce sollicitudin eget pellentesque wisi sollicitudin. Ut aliquam amet. Non sit tincidunt. Dapibus maecenas turpis. Erat torquent lobortis a.</p><p>In tempor purus. Mi tincidunt elementum pede faucibus nunc. Ipsum aenean viverra. Elit leo adipiscing. Curabitur a donec. Ante ultricies et. Tincidunt commodo wisi vulputate.</p><h2>Luctus in suspendisse</h2><p>Suspendisse tortor arcu duis felis eros. Laoreet in ante. Ut massa nibh. Ipsum odio magna. Ut consectetuer suspendisse. Odio libero in non.</p><p>Id justo rhoncus maecenas a iaculis. Nec justo vitae. Odio ultricies rutrum. Eget arcu turpis. Eget arcu amet. Aenean quis et. Sollicitudin pellentesque morbi per.</p><h2>Eros platea conubia duis ornare nec</h2><p>Magna ut at. Consectetuer mauris mauris. Non quis semper. Vel sed lacus. At mauris nec. Amet non in quis.</p><ul><li>Placerat libero aliquip.</li><li>Nostrum ac orci.</li><li>Ante vulputate rutrum esse habitant amet.</li><li>Tortor risus arcu.</li><li>Eros eu dolor.</li><li>Ut urna vel.</li><li>Ac dapibus vivamus sed.</li></ul><h2>Etiam nunc posuere</h2><p>Volutpat eros illo. Natoque a a. Eget nibh dolor. Ac pede aliquam. Nullam et blandit. Aliquam a massa bibendum nullam dignissimos sem.</p><ul><li>Vitae sed venenatis.</li><li>Magna a sed tempor vel et.</li><li>Mauris adipiscing eget.</li><li>Scelerisque donec duis.</li><li>Sagittis facilisis sed.</li><li>Lorem accumsan dui.</li><li>Phasellus ullamcorper quis metus.</li></ul><h2>Varius vel praesent</h2><p>Sed sed fusce eget eget ipsum. Nullam odio ac. Per commodo massa. In quisque quis. Ipsum amet at. Vel nisl non vel.</p><p>Augue tortor lacus facilisi urna ante. Augue nec lacinia. Eleifend ligula ac. Vivamus magna scelerisque. Mauris tellus condimentum. Amet montes venenatis. Neque at orci non.</p><h2>Ac nam sed</h2><p>Aut quis etiam metus eaque consectetuer. Praesent consequat pulvinar. Ultricies metus quis. Integer et nonummy. Sed eu gravida. Sodales cras praesent duis.</p><p>Mollis et dictum. Ut nibh dapibus. Proin vivamus ipsum. Netus integer non. Vitae mauris etiam non metus aliquam. Commodo est sit. Mauris ut amet lorem.</p><h2>Dignissim fringilla tellus</h2><p>Mauris adipiscing aptent. Nibh sed rutrum. Duis condimentum ac. Nisl malesuada sit imperdiet ultricies lectus. Condimentum lectus nam. Turpis amet id wisi.</p><p>Blanditiis tellus ullamcorper congue eu vestibulum. Maecenas id wisi. Pellentesque ut a. Libero in massa. Vehicula id eget. Commodo sapien faucibus. Sociis primis molestie nunc.</p><h2>Cras dolor ac</h2><p>Nunc nulla vehicula eu commodo purus. Cursus lorem nec. Sapien augue in. Bibendum fusce vitae. Eros in sed. Lacinia et ligula ridiculus.</p><p>Aliquam ut nunc. Lacus praesent pede ante adipiscing amet. Lobortis eros enim. Neque massa molestie. Ornare bibendum omnis. Orci lacus justo. Tempus ac non in.</p><h2>Non lacinia diam</h2><p>Mauris enim molestie. Mauris quam ligula. Aliquam augue mauris. Consequat nulla nam vestibulum hendrerit mollis. Mattis arcu sit. Nibh vehicula nec vel.</p><p>Ut fusce viverra. Arcu tempus nec. Suspendisse vitae non. Amet quisque consequat. Purus nunc luctus. Dui quis ridiculus. Enim cras sociis vitae mattis risus nibh.</p><h2>Vel risus etiam</h2><p>Nulla velit rutrum tempus ornare nulla. Sit et rhoncus. Nec aliquam a. Habitant mauris vestibulum. Nec nunc nibh. Non ligula vestibulum vivamus.</p><p>Mi elit duis aliquet neque tortor. Dignissim duis libero. Aenean justo amet. Ac fusce vel. Eros aenean fusce. Leo dictum mollis. Est mauris tellus sed.</p><h2>Sed turpis at</h2><p>A vitae dui. Eros dapibus proin. Hac mauris eu. Phasellus vitae consequat vestibulum nec lectus. A eros sed. Fugiat enim sapien sollicitudin.</p><ol><li>Eget non nunc.</li><li>Reprehenderit condimentum nullam.</li><li>Sed ante ultricies.</li><li>Phasellus molestie quisque.</li><li>Mattis vitae wisi.</li><li>Amet turpis faucibus.</li><li>Sem aenean hendrerit leo qui vivamus nec.</li></ol><h2>Sed in velit</h2><p>Faucibus velit dolor. Libero eget eleifend. Imperdiet velit ad. Ut consequat laoreet dictumst aut quis. Ligula sodales suspendisse. Nec sed tortor ipsum.</p><p>Quam cras aliquam. Erat dignissim libero. Elit nunc velit. Cursus dolore mauris. Enim a pede. Nec blandit facilisi. Donec mauris pellentesque feugiat imperdiet metus velit.</p><h2>Parturient donec pede</h2><p>Mus ducimus potenti. Mi lorem sagittis. Odio vel et amet ante tortor. Habitasse aenean nec. Semper volutpat proin. Feugiat netus in lorem.</p><p>Sit quam fermentum nec eu tincidunt. Nec at eros. Lacus ut et. Felis mauris nec. At fusce integer. Nam elit nibh. Mattis neque vestibulum fusce.</p><h2>Quam suspendisse nulla</h2><p>Vel quia ac. Eleifend vel sit. Parturient dolor odio. Quaerat sit id sem auctor sit. Tempus ut lorem. Diam vehicula commodo libero.</p><p>Quis nunc suscipit. In aenean duis. Massa quam doloribus. Bibendum mattis massa etiam tristique mauris. Adipiscing neque arcu. Nec voluptas ligula. Sequi vivamus tellus adipiscing.</p><h2>Donec curabitur turpis</h2><p>Per congue tellus. Donec et diam. Amet lectus con. Placerat amet leo. Tortor pharetra molestie mauris felis etiam. Aliquam rutrum faucibus netus.</p><p>Praesent neque amet. Id ac nunc. Etiam vestibulum at. Laoreet in sed orci voluptatem nullam. Pellentesque nulla morbi. Commodo eleifend suspendisse. Etiam odio ligula ut.</p><h2>Euismod ullamcorper sapien</h2><p>Cras maecenas elit. A erat massa. Nulla pede mauris. Est suscipit dolorum accumsan nunc faucibus. Id sagittis quis. Vehicula sit id cras.</p><p>Orci laudantium pretium. Aliquet eget rutrum donec vestibulum sint. Viverra consectetuer in. Vel nec mi. Ultricies dignissim ut. Velit lobortis quo. Eget a ac in.</p><h2>Est quisque mauris</h2><p>Diam consectetuer interdum. Viverra erat urna. Ut feugiat sit. Nec nonummy enim. Nulla phasellus erat luctus non pede. Hymenaeos blandit imperdiet ante.</p><p>Massa erat vel. Lectus sit cubilia. Purus sodales ac. Mauris enim hendrerit. Vitae auctor tortor gravida at pretium. Egestas mattis accumsan. Nunc sapien facilisis fermentum.</p><h2>Phasellus at sed</h2><p>Eget sollicitudin elit. Sed ligula mauris. Pede non eros. Vestibulum gravida ut. Mi nullam aenean eget quia wisi. Proin eu per orci.</p><p>Phasellus mus sed. Tempus fringilla ornare sodales at nullam. Habitant id molestie. Ut lacinia dui. Nibh sit tincidunt. Placerat molestie et. Ornare nam laoreet commodo.</p><h2>Etiam potenti mauris</h2><p>In sollicitudin eleifend. Purus mi felis elit ut ullamcorper. Vivamus orci elit. Posuere nulla nulla. Elit eget at. Pellentesque bibendum tincidunt placerat.</p><p>Ullamcorper libero potenti. Nunc ultricies pharetra. Ultrices volutpat nulla. Suspendisse commodo fermentum nam mi ultricies. Odio tincidunt quis. Turpis at interdum. Maecenas dolor praesent hendrerit.</p><h2>Dui quis lectus</h2><p>Eget consequat odio. Vel at in. Varius nisl massa. Consequatur nulla wisi. Quis nulla purus. Nam ultrices tempus vitae non sed sed.</p><p>Sit et egestas. Nunc quis eget. Nulla inceptos porttitor. Molestie tristique maecenas. Tortor massa duis. Facilisi justo lectus tristique vel vel. Felis interdum venenatis elit.</p><h2>Ultricies amet nec et lectus mus</h2><p>Quo dictum tempus. Nam vestibulum quis. Etiam nulla quam. Viverra adipiscing ipsum. Netus risus wisi. A ac non neque.</p><ol><li>Tellus nec ut.</li><li>Donec at consectetuer.</li><li>Tempor in diam consectetuer magna inceptos.</li><li>Ligula cursus sed.</li><li>Sollicitudin augue amet.</li><li>Ante vel orci.</li><li>Nulla lacinia erat nulla.</li></ol><h2>Atque ultrices vitae pellentesque nullam cursus</h2><p>Luctus velit donec. Ullamcorper ligula eros. Eget suscipit hendrerit. Curabitur quam felis. Curabitur vero tempus. Volutpat malesuada nulla pulvinar.</p><p>Eu et ut. Non diam aliquam. Id turpis volutpat. Mi venenatis volutpat. Nulla risus libero. Ac vivamus in. Est et tristique ultrices nec nunc ut.</p><h2>Orci ac pede</h2><p>Nulla porta feugiat. Nec wisi eros. Lacus ac erat. Mus sed eu a tincidunt a. Pede possimus ut. Massa ullamcorper purus turpis.</p><ul><li>Sit fames mi.</li><li>Quis risus wisi.</li><li>Nulla enim rhoncus.</li><li>Vitae ante eros.</li><li>Donec mi condimentum.</li><li>Donec malesuada et amet sed sint.</li><li>Urna nulla vel pede.</li></ul><h2>Non vel placerat</h2><p>In vel inceptos. Fringilla euismod in. Dui rhoncus magna. Auctor cursus scelerisque. Facilisi sapien pharetra. Semper duis sapien amet tellus imperdiet enim.</p><p>Etiam cras integer. Lobortis metus condimentum. Risus in dis. Condimentum eu vitae lobortis semper volutpat. Semper ut fuga. Primis nonummy sem. Gravida vivamus ornare integer.</p><h2>Non felis nunc</h2><p>Amet justo a. Arcu rhoncus quisque. Ut eros odio pretium justo tincidunt. Sit vitae in. Ipsum nec lectus. Vivamus nunc egestas nam.</p><ol><li>Non eu hic.</li><li>Volutpat sit luctus.</li><li>Feugiat posuere dis.</li><li>Felis mauris lectus eget diam sit.</li><li>Ad impedit a.</li><li>Sem sapien nulla.</li><li>Quis aliquam lectus turpis.</li></ol><h2>Erat curabitur eu</h2><p>Libero mollis congue. Felis iaculis posuere. Massa ac varius in elit nonummy. Neque in ornare. Enim ligula nullam. Tortor sit neque vestibulum.</p><ul><li>Dapibus quis in.</li><li>Lorem lorem dolor.</li><li>Odio feugiat sed.</li><li>Duis libero magna.</li><li>Faucibus varius mauris.</li><li>Et suspendisse malesuada sagittis wisi rutrum.</li><li>Egestas dapibus blandit sem.</li></ul><h2>Interdum vitae pretium</h2><p>Vestibulum velit id. Dictum dis in. Magna dui erat. Vel euismod neque nec facilisi sed. In et dolorem. Eu auctor magna tellus.</p><p>Nulla risus maiores ridiculus nunc orci. Semper sed erat. Velit lacus in. Purus faucibus magnis. Et risus blandit. Sem hac ut. Dictum nonummy ante vel.</p><h2>Velit leo mauris sit molestie dictum</h2><p>Litora risus neque. Sed duis ante. Nunc interdum mattis. A cras con. Sem lorem eleifend. Quam dui in donec.</p><p>Ipsum dolor ipsum. Nulla quis class. Libero sed vestibulum. Aenean massa tempor. Integer nec praesent. Diam mus conubia. Commodi duis vitae tempor massa libero fringilla.</p><h2>Et nec mi</h2><p>Ante id nec. At vehicula in. Dolor non nonummy vehicula in vulputate. Non mi lacus. Viverra tempus et. Aliquet erat pellentesque eu.</p><p>Curabitur vehicula non. Per nulla congue. Dis facilisis ridiculus. Porta bibendum amet nonummy mauris purus. Cursus quaerat taciti. Lobortis volutpat nisl. Sunt pede dapibus in.</p><h2>Dui sed etiam imperdiet sed mi</h2><p>Pellentesque magna neque. Blandit donec sed. Pellentesque mauris porttitor. Sit a nunc. Condimentum nec lorem. Auctor suspendisse eleifend con.</p><p>Vel augue suscipit. Integer elit vestibulum mauris ante vitae. Molestie ac tincidunt. Aliquet wisi a. Lobortis leo molestie. Pellentesque nonummy facilisis. Ut quis nec suspendisse.</p><h2>Eget libero sed</h2><p>Lectus vel sed. Arcu massa sodales pellentesque nascetur vel. Eu est gravida. Adipiscing sapien wisi. Lorem donec vel. Quis curabitur tempor amet.</p><p>Ante a parturient. Pede morbi massa. Sollicitudin integer amet. A suscipit in. Vel egestas primis. Laoreet wisi purus lorem ultricies phasellus. Ac urna turpis sit.</p><h2>In massa maecenas</h2><p>Habitasse pellentesque pellentesque. In et quis quam non phasellus. Vestibulum rutrum egestas. Ante nam amet. Et aliquet vitae. Blandit neque quam leo.</p><p>Augue sit lorem. Cras nunc dolor. In fringilla hac posuere urna lectus. Purus suspendisse aliquip. Risus risus orci. Vivamus arcu at. Non facilisis justo erat.</p><h2>Aliqua sed at</h2><p>Curabitur fusce massa. Pellentesque auctor amet volutpat eu urna. Nec porttitor urna. Aptent vitae posuere. Praesent aliquet magna. Fames dui condimentum amet.</p><p>Omnis at dolor. Felis ligula fringilla. In nisl elit. Tincidunt hendrerit vestibulum. Et nulla nunc. Neque eget tellus. Est nibh ac et do sed quis.</p><h2>Faucibus scelerisque faucibus</h2><p>Adipiscing elit donec. Luctus vel venenatis consequat malesuada dis. Et feugiat anim. Gravida purus tortor. Gravida ut fringilla. Nam aliquam tristique auctor.</p><p>Quis nec lorem. Aenean libero faucibus rutrum fames ac. Metus congue nec. Turpis fermentum massa. Malesuada ultrices libero. Congue leo vestibulum. Cras hymenaeos felis turpis.</p><h2>Non dapibus sed</h2><p>Iaculis in laoreet. Vitae nec ut. Odio eget urna aptent arcu aliquet. Nisl quam porttitor. Vel ac aliquam. Aenean non donec interdum.</p><p>Nam condimentum placerat ligula cras blandit. Odio vestibulum augue. Suspendisse dolor adipiscing. Leo nec est. Magna wisi urna. Sed duis egestas. Feugiat lectus sollicitudin etiam.</p><h2>Tortor risus sagittis</h2><p>Sit duis scelerisque. Metus duis leo. Sodales ut enim. Leo nunc et. Et nulla orci. In pellentesque feugiat leo phasellus suscipit nulla.</p><p>Cras hic condimentum. Erat porttitor ultricies. Magna commodo nullam. Congue maecenas dignissim. Et leo ante at sit venenatis. Et orci lacus. Magna ipsum eu ut.</p><h2>Nulla nonummy scelerisque</h2><p>Est cras assumenda. Cras vel justo. Fermentum morbi ipsum. Eros ad nec at erat convallis. In faucibus sapien. Ornare arcu neque eros.</p><p>Tempus ab nunc. Suspendisse facilisis dui. Sed potenti rutrum. Ac fringilla vulputate. Eros elit eu. Praesent risus ut. Enim lacus pretium eros id penatibus velit.</p><h2>Accumsan vehicula a</h2><p>Lobortis dui quis. Lacus nec tortor. Non a wisi. Ultricies vitae dicta. Felis porta fusce. Erat vel pulvinar et rhoncus eleifend libero.</p><p>Quis dolor purus. Montes veritatis aenean. Ut mauris rutrum netus lobortis sed. Suspendisse tortor congue. Eu vitae fugit. Nonummy ut elit. Elit mi pellentesque curabitur.</p><h2>Ut adipiscing tellus</h2><p>Consectetuer vestibulum quis. Dictum habitant libero nisl etiam rutrum. Magna euismod nullam. Porttitor at pede. Rhoncus tortor arcu. Eget sed proin tempor.</p><p>Duis quis viverra. Mauris vulputate tristique. Interdum officia nec. Tellus odio bibendum. Cras id blandit tincidunt aliquam mauris. Nulla pellentesque elementum. Non tincidunt morbi fermentum.</p><h2>Vel proin massa</h2><p>Accumsan lacus nullam. Mi ut mi. Imperdiet proin fringilla. Quis phasellus aenean. Sed ultricies orci. Nec quis donec dolore ultricies vestibulum placerat.</p><p>Ut amet amet. In eu dolor. Tristique similique curabitur vestibulum morbi tincidunt. Eros sit sed. Ipsum tellus netus. Sodales cras ipsum. Dui sit dolor esse.</p><h2>In et habitasse ante suscipit arcu</h2><p>Hendrerit fringilla nec. Metus erat malesuada. Quisque nulla curabitur. Leo augue pellentesque. Quia ac nunc. Ac eleifend consequat sed.</p><p>Magna nulla risus. Nec quam sit. Adipiscing sodales ante. Praesent sit risus. Vestibulum ut purus. Cras lectus sit. Occaecati metus in libero feugiat aenean parturient.</p><h2>Eleifend tellus in</h2><p>Arcu aliquam rutrum. Sem dictumst id. Lobortis euismod dui. Vel amet leo. Velit fringilla felis suspendisse lacus massa. Velit magna est fermentum.</p><p>Elit felis nibh. Eget vitae accumsan. Sem elit sed. Id fames ipsum. Commodo mauris metus non dolor odio. Quia gravida in. Integer elit rutrum ultrices.</p><h2>Quam in turpis vivamus viverra phasellus</h2><p>Ridiculus pharetra volutpat. Eget nulla lacinia. Neque nullam metus. Purus vel at. Eget tristique ac. Faucibus diam odio nulla.</p><p>Mauris nulla elementum. Orci urna ridiculus. Amet consequat suspendisse. Dictum elementum ac. Habitasse amet vitae. Donec vestibulum amet. Habitant pellentesque sed sit ut ut in.</p><h2>Lorem posuere augue mauris mollis neque</h2><p>Mi turpis non. Donec deserunt adipiscing. Imperdiet donec ante. Pretium egestas augue. Phasellus vitae donec. Placerat eget lectus elementum.</p><p>Ut dapibus eros. Felis nullam duis. Lacus posuere eu mauris nibh duis. Proident rutrum ipsum. Vel in pellentesque. Proin egestas sed. Ultrices odio lacus vestibulum.</p><h2>Nulla sed nunc</h2><p>Tellus sit aute vehicula scelerisque amet. Sagittis ligula mi. Nulla pellentesque eu. Sem suspendisse ornare. Elit ante condimentum. Magna quam sunt sit.</p><p>Id eu elit. Mauris scelerisque ea. At ligula rhoncus. Eros nascetur sed. Turpis pellentesque velit et sociis suscipit. Blandit tellus aliquam. Non id mauris in.</p><h2>In ut eget</h2><p>Hendrerit at sit. Ut nec vestibulum sem dignissim viverra. Nullam metus condimentum. Gravida vulputate vitae. Purus sit mi. Arcu gravida magnis ac.</p><ol><li>Fermentum viverra arcu.</li><li>Phasellus nec a.</li><li>Quis ut sit.</li><li>Pretium erat quam.</li><li>Ipsa ultricies sem lectus consectetuer et.</li><li>Ut ut aenean.</li><li>Nunc eu et phasellus.</li></ol><h2>Nonummy tristique ornare</h2><p>Netus tristique non. Sed duis pellentesque convallis tempus rutrum. Adipiscing convallis integer. Dolor mauris consectetuer. Id facilisis sodales. Vulputate est commodo in.</p><p>Vehicula sit elementum. Egestas dui sapien. Est sed non dolor imperdiet nunc. Faucibus ultricies arcu. Ut vitae in. At et proin. In mi gravida turpis.</p><h2>Etiam metus risus</h2><p>Est rhoncus viverra. Arcu suspendisse phasellus. Neque in nascetur at maecenas eu. Nisl ac quisque. Montes ac nam. Non nunc odio felis.</p><ol><li>Nulla porta pretium.</li><li>Dui tortor donec.</li><li>Convallis aliquam fringilla consectetuer mauris nullam.</li><li>Quis pulvinar velit.</li><li>Commodo eget pede.</li><li>Nisl lobortis nisl.</li><li>Quis nec erat convallis.</li></ol><h2>Dictum nibh pulvinar</h2><p>Tellus scelerisque ipsum. Ligula pharetra dictumst. Adipiscing at praesent eget est platea. Quisque nulla ligula. Fusce platea fusce. Arcu ac nunc vel.</p><p>Etiam vitae magna sit nec vel. Et nunc ut. Quis placerat euismod. Volutpat at torquent. Tristique non enim. Nulla interdum nibh. Nonummy vitae pede urna.</p><h2>Id nonummy id</h2><p>Etiam totam vestibulum. Non fusce hac ultrices sit ipsum. Vitae eget vel. Vestibulum rutrum sit. Nulla nec pellentesque. Posuere turpis et et.</p><ul><li>Elit id tempor wisi sed cursus.</li><li>Tempor lectus purus.</li><li>Molestias mauris sed.</li><li>Maecenas in et.</li><li>Etiam porttitor ac.</li><li>Sit non lectus.</li><li>Vel aenean morbi in.</li></ul><h2>A rutrum felis</h2><p>Duis sapien elit. Neque iaculis mattis. Molestie porttitor cursus. Felis lectus at. Montes leo metus. Ullamcorper urna justo elit rutrum enim accumsan.</p><p>Vel sit velit. Et aliquam sed. Nullam id adipiscing. Hendrerit dictum pulvinar volutpat mi sociis. Pellentesque fringilla suspendisse. Ut vestibulum luctus. Amet in quis risus.</p><h2>Rutrum volutpat ligula</h2><p>Tincidunt praesent wisi. Sed augue urna. Cubilia ridiculus eget. Lorem at in quam sed tincidunt. Nec donec malesuada. Praesent molestiae sollicitudin id.</p><p>Faucibus etiam etiam. Egestas nullam ratione. Ut donec id. Turpis platea nascetur. Velit ligula enim. Orci ornare metus. Mattis sem rhoncus eros feugiat ultricies etiam.</p><h2>Fringilla commodo laoreet</h2><p>Aptent ac vulputate. Parturient mollis massa. Purus duis vehicula. Pede aliquam posuere leo venenatis morbi. Et arcu non. Sed tortor sodales duis.</p><ol><li>Nesciunt leo fringilla.</li><li>Phasellus ut duis.</li><li>In morbi ac.</li><li>Felis ligula wisi.</li><li>Sociis consequat fermentum.</li><li>Fringilla pede sit tristique odio leo.</li><li>Consequat vestibulum egestas enim.</li></ol><h2>Magnis enim tortor</h2><p>Velit quam wisi. Arcu vivamus dictum habitant mauris sodales. Enim sollicitudin maecenas. Pede velit fames. Quisque ante a. Ut ac habitant est.</p><p>A mauris vitae. Erat eros bibendum. Non a dapibus porttitor quis sed. Purus libero luctus. Dignissim fringilla amet. Consectetuer wisi et. Nullam in amet suscipit.</p><h2>Lacinia in tellus</h2><p>Venenatis pharetra purus. Fringilla sodales sed. Condimentum et purus. Quis libero pede. Ligula porta ornare. Eget nascetur urna et laoreet suscipit arcu.</p><p>Sollicitudin non ac. Ornare mi pellentesque. Magna at metus. Orci purus molestie. Vel erat quis consectetuer egestas ut. Quaerat dolor risus. Odio maecenas in volutpat.</p><h2>Luctus a aliquam vestibulum ligula vel</h2><p>Massa sapien nam. Et curabitur elementum. Nonummy egestas porta. Sagittis magna tincidunt. Lacinia odio suspendisse. Tellus ac purus enim.</p><ul><li>Aliquam duis non.</li><li>In pretium in.</li><li>Elit massa etiam.</li><li>Rutrum lorem hendrerit lacinia magna nec.</li><li>Sapien nunc vitae.</li><li>Itaque sed pellentesque.</li><li>Sed id sed pede.</li></ul><h2>Etiam arcu magna</h2><p>Orci suscipit auctor. Maecenas dui id. Sem integer orci. Et duis gravida enim venenatis a. Venenatis etiam etiam. Aptent condimentum luctus fusce.</p><p>Auctor leo erat. Vehicula adipiscing adipiscing erat lobortis metus. Duis bibendum nisl. Leo egestas venenatis. Curabitur eu at. Ut hendrerit vel. Curabitur mi velit cras.</p><h2>Iaculis felis a</h2><p>Quam a congue. Phasellus condimentum phasellus. Accumsan tellus quam. Dapibus bibendum tortor. Duis in venenatis eros sollicitudin a. Velit odio lorem ultrices.</p><p>Integer nulla praesent. Facilisi justo vestibulum. Mauris non mauris. Integer praesent pellentesque erat a elementum. Aliquam odio quam. Donec nonummy interdum. Cras non leo purus.</p><h2>A aptent ut</h2><p>Quisque fringilla scelerisque nec nunc nunc. Et vitae hymenaeos. Aliquet a turpis. Dolor nisl blandit. Etiam magna placerat. Hendrerit hymenaeos ut a.</p><p>Libero quam mauris. Lorem at et. Lorem eu maecenas vitae pellentesque ullamcorper. Metus vitae porttitor. Nec et montes. Augue purus augue. Urna est dui hendrerit.</p><h2>Faucibus eu nisl neque molestie eget</h2><p>Porta mauris pharetra. Id urna dui. Massa erat sed. Ut diam velit. Volutpat diam sed. Duis in lobortis rhoncus.</p><p>Justo dictum suspendisse. Nullam molestie eu. Nam duis con. Dolorem non quis. Integer magna hendrerit. Duis mauris phasellus laoreet et non. Orci magna amet rutrum.</p><h2>Sunt pellentesque ullamcorper</h2><p>Donec pharetra integer eu adipiscing nisl. Morbi rutrum etiam. Lobortis in ullamcorper. Velit elit dui. Ut sit nunc. Platea vitae in lectus.</p><p>Tristique adipiscing ipsum. Leo suspendisse auctor. Eget erat turpis. Vitae varius in tempor lacinia eu. Aliquam proin donec. Dapibus nunc ipsum. Ridiculus est aliquam lectus.</p><h2>Vestibulum quam nostra</h2><p>Non metus non. Dis ligula odio mauris libero eget. Augue donec quisque. Fugiat dictum dolor. Lobortis porta nulla. Molestie consequat elit elit.</p><p>Donec amet nullam. Suscipit fames turpis sit donec tellus. Torquent dignissim maecenas. Arcu viverra arcu. Risus arcu vivamus. Morbi id elit. Consectetuer varius etiam ipsum.</p><h2>Aenean id in</h2><p>Suspendisse sit volutpat. Sit eget scelerisque. Fringilla quam varius. Nec maecenas sollicitudin. Urna eget a ultrices viverra mauris. Mauris donec suscipit sagittis.</p><p>Diam aliquam posuere. Curabitur blandit qui. Quam mauris leo arcu lacus sit. Consectetuer arcu dui. Id lectus dictum. Eget at mi. Integer libero elit integer.</p><h2>Urna eget amet sed gravida tempus</h2><p>Magnis ipsam viverra. Dictum erat purus. Lectus sapien nisl. Arcu a wisi. Vel mauris cursus. Vitae malesuada sem quisque.</p><p>Nulla ut volutpat. Sit consequat a. Quis at ac nullam dolor mi. Blandit elit tellus. Mi eu nulla. In vestibulum nec. Class pellentesque sollicitudin ad.</p><h2>Nulla diam pede</h2><p>Magna in consectetuer. Sit quis arcu. Ac bibendum nec. Nec est potenti. Amet sodales quis nisl tincidunt vel. Felis quam condimentum phasellus.</p><ol><li>Aliquam ornare magna.</li><li>Sodales lacus ipsum.</li><li>Velit ac sagittis.</li><li>Etiam ligula semper.</li><li>Quam quis pellentesque.</li><li>Bibendum pellentesque nec.</li><li>Cras purus morbi tortor leo eget volutpat.</li></ol><h2>Ultrices enim eros</h2><p>Nec massa consequat. Litora gravida id. Natoque lectus neque. Ac elementum parturient. Pharetra consectetuer pellentesque nec lectus sit. Ipsum quisque sollicitudin urna.</p><p>Etiam vestibulum ligula. Sed in enim. Sapien ut velit. Eros gravida felis. Nisl sed nibh wisi diam ut. Ex tristique eget. Augue aliquam adipiscing nulla.</p><h2>Orci felis et</h2><p>Non phasellus fames fermentum sit feugiat. Eleifend pharetra et. Libero vel augue. Posuere aliquam nisl. Lorem sed fermentum. Curabitur vestibulum sit id.</p><p>Rhoncus vehicula dui sapien etiam quis. Eu et praesent. Odio mauris turpis. Congue tortor a. Nibh at sed. Sit sed adipiscing. Nullam mattis lacus sociis.</p><h2>Leo duis sagittis</h2><p>Pretium sagittis nunc. Mauris leo a. Lectus curabitur ipsum. Et consequat in. Est laoreet sint orci justo ante. Ipsum in volutpat nulla.</p><p>At morbi nam. In arcu magna. Nunc donec congue. In nulla blandit. Justo sollicitudin occaecat. Suspendisse massa ligula. In vivamus montes scelerisque ut nisl quis.</p><h2>Vestibulum scelerisque nulla</h2><p>Elit maecenas mi. Tellus justo netus sed habitasse etiam. Non dolor libero. Morbi morbi congue. Viverra corporis justo. Ipsum amet urna ligula.</p><p>Litora elementum nisl placerat quisque dui. Blandit urna sit. Metus sodales enim. Odio arcu amet. Non eget nisl. Arcu neque nunc. Dapibus ut arcu vestibulum.</p><h2>Facilisis hendrerit convallis</h2><p>Sit pede aliquam. Morbi vitae diam. Sed commodo elit. Dapibus a sociis. Sit nullam vitae eros lectus nulla. Enim hymenaeos quis massa.</p><p>Dictum ipsum tortor. Eros neque dolor. Cras at et. Gravida aenean a. Integer sagittis sit mattis etiam quam. Tristique aliquam arcu. Vestibulum pede sapien lorem.</p><h2>Tincidunt consequat tellus</h2><p>Arcu egestas veritatis. Elit sem ante nisl risus augue. Sed natoque a. Lacus metus in. Porta quis ante. Justo augue pede labore.</p><p>Accumsan id leo. Mi at pellentesque. Adipiscing mauris libero. Id sem sit. Sociis sed et. Suspendisse mauris dictumst mi amet et. Ac mattis voluptas pharetra.</p><h2>Duis donec turpis</h2><p>Id sed adipiscing. Rutrum eleifend vel. Nulla pede iaculis. Mauris vitae in. Et nam in dolor leo neque. Wisi enim quam ornare.</p><p>Nulla non tempus. Dolor nunc tempus. Dolor sagittis justo. Nam quis sed. Senectus pellentesque urna mauris quis arcu. Nec risus tempus. Aliquet luctus dui nec.</p><h2>Tellus tempus convallis</h2><p>Id libero lorem. Fringilla facilisis metus. Sit dictum varius. Urna ornare felis. Eros tristique amet. Duis est lorem mauris at in sem.</p><ol><li>Vitae ante amet sodales tortor enim.</li><li>Mi nulla augue.</li><li>Scelerisque interdum orci.</li><li>Vitae sed lacus.</li><li>Ut cursus praesent.</li><li>Dictum et cillum.</li><li>Euismod tortor lacus corporis.</li></ol><h2>Vitae praesent ante at sit eleifend</h2><p>Nec wisi nulla. Inceptos et nam. Orci autem fusce. Nunc consectetur dolor. Urna libero erat. Et lobortis cras tempor.</p><ol><li>Pede erat at nulla curabitur id.</li><li>Quis pulvinar dui.</li><li>Ligula nisl duis.</li><li>Pretium tincidunt eu.</li><li>Urna sit varius.</li><li>Massa et amet.</li><li>Libero vitae vel duis.</li></ol><h2>Lorem mauris quis</h2><p>Aliquet aenean tincidunt est eu ut. Quisque quam non. Scelerisque ut ligula. Tortor in vel. Magna in euismod. Aenean sit est elit.</p><p>Adipiscing dolor risus. Accumsan feugiat ridiculus. Metus iaculis conubia. Fringilla ut cras aliquam id donec. Elementum vivamus fusce. Vestibulum ridiculus blandit. Etiam rutrum neque lacinia.</p><h2>Mauris velit convallis</h2><p>Vulputate tortor id odio aliquet magna. Quis sed suscipit. Est est vestibulum. Velit et vestibulum. A eleifend augue. Rutrum laoreet ut risus.</p><p>Turpis condimentum nulla. Tortor diam ut. Amet pede mattis. Pellentesque imperdiet sodales. Lectus autem venenatis. Dictumst luctus nunc. Mauris donec nam felis dolor at sit.</p><h2>Aliquam eu natoque</h2><p>Integer at arcu. Metus et ligula. Malesuada integer augue. Ultrices mauris ut. Nulla sit eu justo lacinia fringilla. Urna quisque ligula tincidunt.</p><ul><li>A eu wisi.</li><li>Odio aliquet interdum.</li><li>Dignissim eu dolor.</li><li>Est aliquet quis.</li><li>Class ut id placerat at leo.</li><li>Vel tempor morbi.</li><li>Venenatis eleifend enim in.</li></ul><h2>Porttitor beatae ac</h2><p>Wisi ornare nullam. In eget fusce. Quis ligula parturient. Ut mollis aenean. In sapien amet velit nisl euismod. Nulla est fringilla commodo.</p><p>Libero morbi vehicula. Diam luctus tincidunt. Cras metus sed iaculis tincidunt at. Aenean molestie iaculis. Arcu malesuada lobortis. Ultrices venenatis turpis. Ut curabitur morbi amet.</p><h2>Egestas etiam mauris</h2><p>Integer vel consequat. Mauris bibendum lectus. Ac velit faucibus. Egestas cras mollis. Integer pulvinar lectus odio purus nunc. Sit porttitor elementum proin.</p><p>Cursus ut elit. Molestie mollis magnis. Est dui dui. Varius pellentesque sit nec etiam magna. Amet incidunt phasellus. Cras eu erat. Libero et volutpat quibusdam.</p><h2>Tempus et con</h2><p>Nisl aliquam sem. Eu leo et in morbi vulputate. Suspendisse accumsan suspendisse. A sit non. Donec justo diam. Velit amet eget leo.</p><p>Erat consectetuer rutrum. Pulvinar lectus turpis vehicula voluptate dolor. Suspendisse fermentum scelerisque. Nunc porttitor viverra. Eget pellentesque quis. Massa neque penatibus. Ultricies a amet vivamus.</p><h2>Dapibus vivamus et</h2><p>Nec sapien massa. Id mauris lorem. Magna suspendisse felis. Id commodo condimentum. Molestie potenti sociis. Sodales id sem nibh a ipsum sapien.</p><p>Enim aliquet ac. Libero vitae et. Facilisis non sem tellus tristique molestie. Praesent nulla non. Massa orci eget. Diam quidem augue. Qui dui nec eu.</p><h2>Malesuada nunc ante</h2><p>Laoreet eget tristique. Vel wisi faucibus. Sapien arcu euismod. Morbi nulla tortor erat nascetur mauris. Cursus enim phasellus. Pellentesque netus sequi etiam.</p><p>Nibh curabitur sit blandit morbi molestie. Nullam est a. Condimentum soluta at. Aut dolor orci. Dolor eget interdum. Proin urna sit. Taciti a magnis ante.</p><h2>Sit fermentum imperdiet</h2><p>Duis porttitor sit. Dolor arcu vitae. Elementum faucibus praesent magna gravida nulla. Congue aliquam condimentum. Vitae amet vitae. Cras interdum scelerisque gravida.</p><p>Aliquam libero sodales nibh eu donec. Litora odio ut. Nulla vitae eget. Luctus metus nulla. Arcu wisi mauris. Arcu maecenas lacus. Cras class consectetuer cras.</p><h2>Ut suspendisse quisque</h2><p>Nullam ante consequat. Amet id eget arcu bibendum vel. Massa eros gravida. Elit magnis mollis. Lacinia nonummy magna. Ligula sollicitudin eros delectus.</p><p>Nonummy sollicitudin enim. Pharetra elementum ac. Amet vivamus posuere. Adipiscing commodo felis. Maecenas quam integer. Eu arcu justo tellus nam wisi. Ultricies vel quis tellus.</p><h2>Sagittis ac ut</h2><p>Cubilia semper arcu pede in sed. Ut ultricies erat. Eget massa at. Dolor enim porta. Id elit metus. Mi ligula ullamcorper quisque.</p><p>Nibh eleifend sit tincidunt eget tempus. Sit nunc mattis. Morbi rhoncus volutpat. Adipiscing augue vitae. Sodales velit tellus. Magna dignissim vitae. Morbi quam mauris urna.</p><h2>Quisque interdum sapien</h2><p>In sit quis. Nulla tellus magna malesuada ipsum sit. Amet proin elit. Eget et venenatis. Mattis sit risus. Sagittis dignissim enim mauris.</p><p>Dictum quis quis. Sociis sagittis lacus. Ultricies laboris et. Suscipit metus eget sed congue eget. Aptent habitant felis. In sed fames. Mauris dolor at nullam.</p><h2>Libero id elit</h2><p>Libero mauris eget. Quis nec suscipit. Velit a et. Arcu mollis facilisis urna vivamus integer. Tempus iaculis ligula. Dolor nullam lectus rutrum.</p><p>Aliquam risus enim. Mi congue dictum. Et tellus lorem. Vehicula nibh etiam. Ultrices aliquam non. Ac at eros libero odio convallis. Vivamus nunc nonummy at.</p><h2>Porta mi lectus</h2><p>Ut turpis sed. Quis aptent ipsum. Leo in vel nulla nisl elit. Est sociosqu nunc. Egestas ante sagittis. Etiam sed ante neque.</p><p>Eu at feugiat. Mi malesuada luctus. In vestibulum justo pellentesque suspendisse metus. In nullam nullam. Ipsum vestibulum elementum. Lacinia faucibus imperdiet. Augue vestibulum nam ac.</p><h2>Volutpat velit leo</h2><p>In duis nam. Mauris pede tincidunt vitae dis semper. Tempus natoque risus. Enim lacinia duis. Diam turpis enim. Sed et nulla maecenas.</p><p>Sem ut duis. Rhoncus posuere ipsum. Massa dolor metus non scelerisque nec. Eu vestibulum volutpat. Enim sem urna. At risus wisi. Urna pulvinar varius a.</p><h2>Lacus quis velit eget consequat dolor</h2><p>Metus diam ipsum. Wisi pede facilisi. Sed quis volutpat. Sodales sodales aliquet. Ut fusce venenatis. Aliquam varius pulvinar pede.</p><p>Bibendum nec nunc. Vestibulum diam luctus magna feugiat porttitor. Non feugiat nonummy. Fringilla mauris ut. Mattis nunc curabitur. Placerat sed imperdiet. Eros sapien sit gravida.</p><h2>Fames donec est</h2><p>Sit eget vitae. Ut suscipit in. Montes sed faucibus. Morbi vestibulum penatibus consequat et morbi. Penatibus eu sollicitudin. Dui sed quis nunc.</p><p>Eget urna ac. Porta non mi. A scelerisque vel. Phasellus consequat gravida quis volutpat platea. Imperdiet at hac. Vel placerat ullamcorper. Hac rutrum ante vitae.</p><h2>Nam amet et</h2><p>A lectus facilisis. Varius ut eu. Hac dui vel. Cursus nunc nullam. Pellentesque dolor ut. Sapien quam viverra velit ut lacus aliquam.</p><p>Nunc lorem ligula. Vel lectus sem. Donec interdum ut. Phasellus luctus integer blandit sit sit. Duis mauris nullam. Luctus ante massa. In fringilla senectus nulla.</p><h2>Urna ullamcorper fusce</h2><p>Ac inceptos quis. Vestibulum ultrices urna. Sed cras nibh. Sem erat dis. Et tellus aliquam amet nulla vehicula. Orci risus sit sapien.</p><p>Dapibus praesent nulla. Arcu vivamus turpis fusce morbi proin. A quam nulla. Duis curabitur leo. Nascetur malesuada luctus. Faucibus eu integer. Erat sit in vivamus.</p><h2>Commodo sociis etiam</h2><p>Ridiculus potenti a. At ligula ut luctus iaculis vitae. Sem nulla ut. Et gravida sed. Curabitur incididunt elit. Architecto sodales tortor adipiscing.</p><p>Augue praesent tellus. Nullam neque porttitor. Cras bibendum neque. At dui neque. Adipiscing integer in. Posuere etiam gravida turpis laoreet dui. Parturient ultricies nulla lectus.</p><h2>Risus aliquam montes</h2><p>Vestibulum morbi imperdiet. Fusce libero lacinia. Ultrices amet condimentum. In dapibus nec mauris vel ullamcorper. Non velit nunc. Massa nonummy neque iaculis.</p><p>Egestas vel tellus. Sed urna in wisi eget a. Mi ac felis. In morbi potenti. Erat ut in. Id elit nulla. Et nibh quisque mattis.</p><h2>Gravida pharetra amet</h2><p>Nunc phasellus con. Morbi enim molestie. Tempus magnis neque. Tincidunt nullam dolor. Est blandit dictum. Nisl orci tortor lacus nunc donec at.</p><p>Vel senectus nulla. Sit nam ad. Suspendisse massa elementum. Luctus sodales proin rhoncus donec eros. Leo vulputate sapien. Orci blandit congue. Justo amet sapien ut.</p><h2>Tempor amet a</h2><p>Sagittis in sapien. Habitant ac fringilla. Tempora lectus mi. Lectus consequat donec non amet mauris. Aliquam congue vitae. Pulvinar porttitor eros elit.</p><p>Id tempor eu. Libero sed nunc. Rutrum gravida risus. Neque elementum dolor. Arcu integer quis. Faucibus ut a. Rutrum massa vehicula integer leo purus suspendisse.</p><h2>Ligula neque porttitor</h2><p>Neque tortor perspiciatis velit ad proin. Mollis nulla bibendum. Ut per nulla. Sodales nibh sapien. Quis faucibus ante. Wisi purus eros lectus.</p><p>In dictum at. Vehicula nulla vivamus. Sodales sem dictum. In morbi neque sodales sed non. Duis integer tincidunt. Sed sed non. Dui nulla orci eget.</p><h2>Tempor at luctus</h2><p>Ut dolorum vitae. Vulputate a mi et et id. Mattis dolor ultrices. Commodo a arcu. Tristique nunc felis. Fringilla justo pharetra fuga.</p><p>Commodo vivamus tellus. Per sodales nonummy. Ac aliquet porta. Enim cras id. Accumsan quam dolor. Aliquet convallis ut cursus non illo. Orci amet eget amet.</p><h2>Quisque tortor et</h2><p>In suspendisse suspendisse. Aenean in quis. Odio nullam tellus. Ligula wisi aliquam. Sed libero montes. Vestibulum et mauris fermentum lectus aliquet interdum.</p><p>Iaculis semper quam. Faucibus amet mauris. Lectus dictum elementum. Natoque quis hac. Dolor ut pellentesque curae viverra luctus. Pulvinar ipsum enim. Sapien commodi sit elementum.</p><h2>Ridiculus non mattis</h2><p>Convallis ultrices fringilla. Venenatis ullamcorper id. Arcu libero dignissim. Tortor wisi libero at ullamcorper faucibus. Suspendisse fringilla aptent. Viverra odio erat dolor.</p><p>Nascetur sem nibh. Justo aliquam diam. Diam tincidunt risus. Fringilla integer et. Turpis platea laoreet. Congue sapien et. Nulla non mi tempus egestas a et.</p><h2>Convallis in adipiscing</h2><p>Vel vitae vulputate. Dolor convallis odio sit in nunc. Sed vitae ultrices. Id nibh libero. Urna scelerisque suspendisse. Etiam tortor eros lectus.</p><p>Deserunt rutrum fusce. Pharetra et curae. Nibh varius sem. Vel pede nec magna a leo. Velit dignissim eget. Magnis pulvinar viverra. Suscipit facilisis nullam leo.</p><h2>Viverra mauris vel</h2><p>Mauris phasellus congue. Suspendisse donec nam. Massa iaculis dapibus. Amet nam malesuada dolor pede aliquam. Ultricies fusce porttitor. Eu accumsan ut neque.</p><p>A ultrices vitae. In ac nunc. Magnis vitae convallis cras scelerisque semper. Suspendisse nullam praesent. Sed lacus congue. Eget suspendisse sodales. Leo eget duis elementum.</p><h2>Vitae suscipit sapien dictum rutrum aliquip</h2><p>Purus vitae lacus. Vestibulum eget in. Ipsum cras nisl. Proin orci odio. Morbi dui velit. Neque nostra hendrerit aliquet.</p><p>Cursus integer nam. Arcu in sequi. Faucibus tortor etiam. Scelerisque lacus est. Per pretium sem. In diam dapibus rutrum lacus erat. Diam accumsan nec sollicitudin.</p><h2>In mauris et</h2><p>Urna ut sed. Egestas eu pellentesque. Ut amet vestibulum. Eget elit leo aptent massa pulvinar. Lorem est mauris. Condimentum sit lorem sodales.</p><p>Maecenas sed viverra. Imperdiet dolore nullam. Elit eu duis consectetuer nec in. Vel ac odio. Auctor fusce consectetuer. Proin felis quos. Risus per enim porta.</p><h2>Curabitur wisi lorem</h2><p>Elit mattis diam. Consequat nisl bibendum. Fermentum sapien elementum donec et curabitur. Sed nascetur imperdiet. Vivamus sagittis nullam. Morbi nunc sit ipsum.</p><p>Tellus magnis luctus. Vel a ligula. Nec bibendum proin. Ipsum pulvinar et. Lorem ut tincidunt sed magna curabitur. Vestibulum eu nam. Vivamus varius bibendum a.</p><p>At wisi etiam. Placerat taciti ante. Phasellus ac wisi. Libero purus condimentum. In accumsan in. Nec ante tempus suscipit magna nulla. Aenean tempor lorem. Elit et dapibus. Posuere at vehicula. Lectus lectus nibh. Vivamus suscipit ullamcorper massa wisi sagittis et aut velit. Imperdiet posuere velit. Sagittis imperdiet sed faucibus.</p>
diff --git a/tools/rust/build_rust.py b/tools/rust/build_rust.py index 72db46c..25257b5 100755 --- a/tools/rust/build_rust.py +++ b/tools/rust/build_rust.py
@@ -74,9 +74,6 @@ os.path.join('tests', 'codegen', 'sanitizer-cfi-emit-type-checks.rs'), os.path.join('tests', 'codegen', 'sanitizer-cfi-emit-type-metadata-itanium-cxx-abi.rs'), - # https://github.com/rust-lang/rust/issues/96464 used to be Windows only but - # now fails everywhere. - os.path.join('tests', 'codegen', 'vec-shrink-panik.rs'), # https://github.com/rust-lang/rust/issues/109671 the test is being # optimized in newer LLVM which breaks its expectations. os.path.join('tests', 'ui', 'abi', 'stack-protector.rs'), @@ -88,6 +85,8 @@ os.path.join('tests', 'ui', 'numeric', 'numeric-cast.rs'), ] EXCLUDED_TESTS_WINDOWS = [ + # https://github.com/rust-lang/rust/issues/96464 + os.path.join('tests', 'codegen', 'vec-shrink-panik.rs'), ] CLANG_SCRIPTS_DIR = os.path.join(THIS_DIR, '..', 'clang', 'scripts')
diff --git a/ui/aura/BUILD.gn b/ui/aura/BUILD.gn index c357f73..fdd7c76 100644 --- a/ui/aura/BUILD.gn +++ b/ui/aura/BUILD.gn
@@ -206,6 +206,7 @@ "test/test_window_targeter.h", "test/test_windows.cc", "test/test_windows.h", + "test/ui_controls_aurawin.h", "test/ui_controls_factory_aura.h", "test/window_event_dispatcher_test_api.cc", "test/window_event_dispatcher_test_api.h", @@ -245,7 +246,7 @@ ] if (is_win) { - sources += [ "test/ui_controls_factory_aurawin.cc" ] + sources += [ "test/ui_controls_aurawin.cc" ] } if (use_ozone && (is_chromeos_ash || is_castos)) {
diff --git a/ui/aura/test/ui_controls_factory_aurawin.cc b/ui/aura/test/ui_controls_aurawin.cc similarity index 94% rename from ui/aura/test/ui_controls_factory_aurawin.cc rename to ui/aura/test/ui_controls_aurawin.cc index de006727..17efa7b 100644 --- a/ui/aura/test/ui_controls_factory_aurawin.cc +++ b/ui/aura/test/ui_controls_aurawin.cc
@@ -5,15 +5,11 @@ #include "base/check.h" #include "base/functional/callback.h" #include "base/task/single_thread_task_runner.h" -#include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/base/test/ui_controls_aura.h" #include "ui/base/test/ui_controls_internal_win.h" -namespace aura { -namespace test { - namespace { using ui_controls::DOWN; @@ -99,9 +95,10 @@ } // namespace -UIControlsAura* CreateUIControlsAura(WindowTreeHost* host) { - return new UIControlsWin(); +namespace aura::test { + +void EnableUIControlsAuraWin() { + InstallUIControlsAura(new UIControlsWin()); } -} // namespace test -} // namespace aura +} // namespace aura::test
diff --git a/ui/aura/test/ui_controls_aurawin.h b/ui/aura/test/ui_controls_aurawin.h new file mode 100644 index 0000000..bc096b5a --- /dev/null +++ b/ui/aura/test/ui_controls_aurawin.h
@@ -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. + +#ifndef UI_AURA_TEST_UI_CONTROLS_AURAWIN_H_ +#define UI_AURA_TEST_UI_CONTROLS_AURAWIN_H_ + +namespace aura::test { + +void EnableUIControlsAuraWin(); + +} // namespace aura::test + +#endif // UI_AURA_TEST_UI_CONTROLS_AURAWIN_H_
diff --git a/ui/aura/test/ui_controls_factory_aura.h b/ui/aura/test/ui_controls_factory_aura.h index 6a4dfc8..477cd9e3 100644 --- a/ui/aura/test/ui_controls_factory_aura.h +++ b/ui/aura/test/ui_controls_factory_aura.h
@@ -6,20 +6,18 @@ #define UI_AURA_TEST_UI_CONTROLS_FACTORY_AURA_H_ #include "build/build_config.h" -#include "ui/base/test/ui_controls_aura.h" + +namespace ui_controls { +class UIControlsAura; +} namespace aura { class WindowTreeHost; namespace test { +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) ui_controls::UIControlsAura* CreateUIControlsAura(WindowTreeHost* host); - -#if BUILDFLAG(IS_OZONE) -// Callback from Window Service with the result of posting an event. |result| -// is true if event successfully processed and |closure| is an optional closure -// to run when done (used in client code to wait for ack). -void OnWindowServiceProcessedEvent(base::OnceClosure closure, bool result); #endif } // namespace test
diff --git a/ui/aura/test/ui_controls_ozone.h b/ui/aura/test/ui_controls_ozone.h index bfd45990..662824e 100644 --- a/ui/aura/test/ui_controls_ozone.h +++ b/ui/aura/test/ui_controls_ozone.h
@@ -13,7 +13,6 @@ #include "ui/aura/env.h" #include "ui/aura/test/aura_test_utils.h" #include "ui/aura/test/env_test_helper.h" -#include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window_tree_host.h" #include "ui/base/test/ui_controls_aura.h" #include "ui/display/display.h"
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 1e2047cc..28c038d9 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -1027,28 +1027,6 @@ "test/run_all_unittests.cc", "webui/i18n_source_stream_unittest.cc", ] - if (is_mac) { - sources += [ - "cocoa/defaults_utils_unittest.mm", - "cocoa/nsmenu_additions_unittest.mm", - "cocoa/nsmenuitem_additions_unittest.mm", - "interaction/element_tracker_mac_unittest.mm", - "l10n/l10n_util_mac_unittest.mm", - ] - } - if (is_chromeos_lacros) { - sources += [ "resource/data_pack_with_resource_sharing_lacros_unittest.cc" ] - } - if (!is_ios) { - sources += [ - "themed_vector_icon_unittest.cc", - "user_activity/user_activity_detector_unittest.cc", - ] - - if (is_mac) { - sources += [ "test/view_tree_validator_unittest.mm" ] - } - } data = [] data_deps = [ "//testing/buildbot/filters:ui_base_unittests_filters" ] @@ -1089,8 +1067,31 @@ "//url", ] - if (is_android) { - sources -= [ "user_activity/user_activity_detector_unittest.cc" ] + if (!is_android && !is_ios) { + sources += [ "user_activity/user_activity_detector_unittest.cc" ] + } + + if (is_mac) { + sources += [ + "accelerators/platform_accelerator_cocoa_unittest.mm", + "cocoa/base_view_unittest.mm", + "cocoa/bubble_closer_unittest.mm", + "cocoa/cocoa_base_utils_unittest.mm", + "cocoa/constrained_window/constrained_window_animation_unittest.mm", + "cocoa/defaults_utils_unittest.mm", + "cocoa/menu_controller_unittest.mm", + "cocoa/nsmenu_additions_unittest.mm", + "cocoa/nsmenuitem_additions_unittest.mm", + "cocoa/touch_bar_util_unittest.mm", + "cocoa/tracking_area_unittest.mm", + "interaction/element_tracker_mac_unittest.mm", + "l10n/l10n_util_mac_unittest.mm", + "test/view_tree_validator_unittest.mm", + ] + } + + if (is_chromeos_lacros) { + sources += [ "resource/data_pack_with_resource_sharing_lacros_unittest.cc" ] } if (is_ios) { @@ -1118,26 +1119,13 @@ "models/list_selection_model_unittest.cc", "models/tree_node_model_unittest.cc", "text/bytes_formatting_unittest.cc", + "themed_vector_icon_unittest.cc", "webui/web_ui_util_unittest.cc", ] + } - if (is_linux || is_chromeos) { - sources += - [ "accelerators/menu_label_accelerator_util_linux_unittest.cc" ] - } - - if (is_mac) { - sources += [ - "accelerators/platform_accelerator_cocoa_unittest.mm", - "cocoa/base_view_unittest.mm", - "cocoa/bubble_closer_unittest.mm", - "cocoa/cocoa_base_utils_unittest.mm", - "cocoa/constrained_window/constrained_window_animation_unittest.mm", - "cocoa/menu_controller_unittest.mm", - "cocoa/touch_bar_util_unittest.mm", - "cocoa/tracking_area_unittest.mm", - ] - } + if (is_linux || is_chromeos) { + sources += [ "accelerators/menu_label_accelerator_util_linux_unittest.cc" ] } # TODO(crbug.com/1091985): Support CrOS. @@ -1157,6 +1145,10 @@ "ime/mojom/ime_mojom_traits_unittest.cc", "ime/surrounding_text_tracker_unittest.cc", ] + deps += [ + "//ui/base/ime", + "//ui/base/ime/mojom:test_interfaces", + ] if (is_win) { sources += [ "ime/win/imm32_manager_unittest.cc", @@ -1213,13 +1205,6 @@ data_deps += [ ":ui_base_test_resources_pak" ] } - if (build_ime) { - deps += [ - "//ui/base/ime", - "//ui/base/ime/mojom:test_interfaces", - ] - } - if (is_ios) { deps += [ "//ui/resources:ui_test_pak_bundle_data" ] } else {
diff --git a/ui/base/clipboard/BUILD.gn b/ui/base/clipboard/BUILD.gn index 7be3061..e437041c 100644 --- a/ui/base/clipboard/BUILD.gn +++ b/ui/base/clipboard/BUILD.gn
@@ -34,6 +34,7 @@ if (is_apple) { sources += [ "clipboard_constants_mac.mm" ] + configs += [ "//build/config/compiler:enable_arc" ] } if (is_win) { @@ -120,6 +121,10 @@ ] } + if (is_apple) { + configs += [ "//build/config/compiler:enable_arc" ] + } + if (is_mac) { sources += [ "clipboard_mac.h", @@ -134,8 +139,8 @@ "clipboard_ios.h", "clipboard_ios.mm", ] - configs += [ "//build/config/compiler:enable_arc" ] } + if (is_win) { sources += [ "clipboard_util_win.cc", @@ -235,6 +240,10 @@ sources = [] output_name = "ui_base_clipboard_test" + if (is_apple) { + configs += [ "//build/config/compiler:enable_arc" ] + } + if (is_ios) { if (use_blink) { # On other OSs, clipboard platform unit tests are run as part of
diff --git a/ui/base/clipboard/clipboard_constants_mac.mm b/ui/base/clipboard/clipboard_constants_mac.mm index a4e18bd..1809dc68 100644 --- a/ui/base/clipboard/clipboard_constants_mac.mm +++ b/ui/base/clipboard/clipboard_constants_mac.mm
@@ -6,6 +6,10 @@ #import <Foundation/Foundation.h> +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ui { NSString* const kUTTypeChromiumImageAndHTML = @"org.chromium.image-html";
diff --git a/ui/base/clipboard/clipboard_format_type.h b/ui/base/clipboard/clipboard_format_type.h index e0485e7d1..0e2114a 100644 --- a/ui/base/clipboard/clipboard_format_type.h +++ b/ui/base/clipboard/clipboard_format_type.h
@@ -20,8 +20,6 @@ #if BUILDFLAG(IS_APPLE) #ifdef __OBJC__ @class NSString; -#else -class NSString; #endif #endif // BUILDFLAG(IS_APPLE) @@ -120,7 +118,9 @@ #if BUILDFLAG(IS_WIN) const FORMATETC& ToFormatEtc() const { return *ChromeToWindowsType(&data_); } #elif BUILDFLAG(IS_APPLE) - NSString* ToNSString() const { return uttype_; } +#if __OBJC__ + NSString* ToNSString() const; +#endif // __OBJC__ // Custom copy and assignment constructor to handle NSString. ClipboardFormatType(const ClipboardFormatType& other); ClipboardFormatType& operator=(const ClipboardFormatType& other); @@ -159,10 +159,11 @@ explicit ClipboardFormatType(const std::string& native_format); std::string data_; #elif BUILDFLAG(IS_APPLE) +#if __OBJC__ explicit ClipboardFormatType(NSString* uttype); - // A Uniform Type identifier string. TODO(macOS 11): Change to a UTType - // object. - NSString* uttype_; +#endif // __OBJC__ + struct ObjCStorage; + std::unique_ptr<ObjCStorage> objc_storage_; #else #error No ClipboardFormatType definition. #endif
diff --git a/ui/base/clipboard/clipboard_format_type_ios.mm b/ui/base/clipboard/clipboard_format_type_ios.mm index 2be7cab9..ca84dc4 100644 --- a/ui/base/clipboard/clipboard_format_type_ios.mm +++ b/ui/base/clipboard/clipboard_format_type_ios.mm
@@ -14,36 +14,51 @@ #include "base/strings/sys_string_conversions.h" #include "ui/base/clipboard/clipboard_constants.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ui { +struct ClipboardFormatType::ObjCStorage { + // A Uniform Type identifier string. + NSString* uttype; +}; + // ClipboardFormatType implementation. -ClipboardFormatType::ClipboardFormatType() : uttype_(nil) {} +ClipboardFormatType::ClipboardFormatType() + : objc_storage_(std::make_unique<ObjCStorage>()) {} ClipboardFormatType::ClipboardFormatType(NSString* native_format) - : uttype_([native_format retain]) {} + : ClipboardFormatType() { + objc_storage_->uttype = native_format; +} ClipboardFormatType::ClipboardFormatType(const ClipboardFormatType& other) - : uttype_([other.uttype_ retain]) {} + : ClipboardFormatType() { + objc_storage_->uttype = other.objc_storage_->uttype; +} ClipboardFormatType& ClipboardFormatType::operator=( const ClipboardFormatType& other) { if (this != &other) { - [uttype_ release]; - uttype_ = [other.uttype_ retain]; + objc_storage_->uttype = other.objc_storage_->uttype; } return *this; } bool ClipboardFormatType::operator==(const ClipboardFormatType& other) const { - return [uttype_ isEqualToString:other.uttype_]; + return [objc_storage_->uttype isEqualToString:other.objc_storage_->uttype]; } -ClipboardFormatType::~ClipboardFormatType() { - [uttype_ release]; -} +ClipboardFormatType::~ClipboardFormatType() = default; std::string ClipboardFormatType::Serialize() const { - return base::SysNSStringToUTF8(uttype_); + return base::SysNSStringToUTF8(objc_storage_->uttype); +} + +NSString* ClipboardFormatType::ToNSString() const { + return objc_storage_->uttype; } // static @@ -57,7 +72,8 @@ } bool ClipboardFormatType::operator<(const ClipboardFormatType& other) const { - return [uttype_ compare:other.uttype_] == NSOrderedAscending; + return [objc_storage_->uttype compare:other.objc_storage_->uttype] == + NSOrderedAscending; } std::string ClipboardFormatType::WebCustomFormatName(int index) {
diff --git a/ui/base/clipboard/clipboard_format_type_mac.mm b/ui/base/clipboard/clipboard_format_type_mac.mm index 5bcacc4..a2653f97 100644 --- a/ui/base/clipboard/clipboard_format_type_mac.mm +++ b/ui/base/clipboard/clipboard_format_type_mac.mm
@@ -8,6 +8,7 @@ #import <CoreServices/CoreServices.h> // pre-macOS 11 #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h> // macOS 11 +#include "base/apple/bridging.h" #include "base/mac/foundation_util.h" #include "base/no_destructor.h" #include "base/strings/strcat.h" @@ -16,35 +17,51 @@ #include "base/strings/sys_string_conversions.h" #include "ui/base/clipboard/clipboard_constants.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ui { -ClipboardFormatType::ClipboardFormatType() : uttype_(nil) {} +struct ClipboardFormatType::ObjCStorage { + // A Uniform Type identifier string. + NSString* uttype; +}; -ClipboardFormatType::ClipboardFormatType(NSString* uttype) - : uttype_([uttype copy]) {} +// ClipboardFormatType implementation. +ClipboardFormatType::ClipboardFormatType() + : objc_storage_(std::make_unique<ObjCStorage>()) {} + +ClipboardFormatType::ClipboardFormatType(NSString* native_format) + : ClipboardFormatType() { + objc_storage_->uttype = native_format; +} ClipboardFormatType::ClipboardFormatType(const ClipboardFormatType& other) - : uttype_([other.uttype_ copy]) {} + : ClipboardFormatType() { + objc_storage_->uttype = other.objc_storage_->uttype; +} ClipboardFormatType& ClipboardFormatType::operator=( const ClipboardFormatType& other) { if (this != &other) { - [uttype_ release]; - uttype_ = [other.uttype_ copy]; + objc_storage_->uttype = other.objc_storage_->uttype; } return *this; } bool ClipboardFormatType::operator==(const ClipboardFormatType& other) const { - return [uttype_ isEqualToString:other.uttype_]; + return [objc_storage_->uttype isEqualToString:other.objc_storage_->uttype]; } -ClipboardFormatType::~ClipboardFormatType() { - [uttype_ release]; -} +ClipboardFormatType::~ClipboardFormatType() = default; std::string ClipboardFormatType::Serialize() const { - return base::SysNSStringToUTF8(uttype_); + return base::SysNSStringToUTF8(objc_storage_->uttype); +} + +NSString* ClipboardFormatType::ToNSString() const { + return objc_storage_->uttype; } // static @@ -58,7 +75,8 @@ } bool ClipboardFormatType::operator<(const ClipboardFormatType& other) const { - return [uttype_ compare:other.uttype_] == NSOrderedAscending; + return [objc_storage_->uttype compare:other.objc_storage_->uttype] == + NSOrderedAscending; } // static @@ -123,7 +141,7 @@ return *type; } else { static base::NoDestructor<ClipboardFormatType> type( - base::mac::CFToNSCast(kUTTypeScalableVectorGraphics)); + base::apple::CFToNSPtrCast(kUTTypeScalableVectorGraphics)); return *type; } }
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm index d5d0ddce..0b0a2e0 100644 --- a/ui/base/clipboard/clipboard_mac.mm +++ b/ui/base/clipboard/clipboard_mac.mm
@@ -15,7 +15,6 @@ #include "base/mac/foundation_util.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_nsobject.h" #include "base/memory/ref_counted_memory.h" #include "base/notreached.h" #include "base/ranges/algorithm.h" @@ -44,6 +43,10 @@ #include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ui { namespace { @@ -51,24 +54,27 @@ NSPasteboard* GetPasteboard() { // The pasteboard can always be nil, since there is a finite amount of storage // that must be shared between all pasteboards. - NSPasteboard* pasteboard = [NSPasteboard generalPasteboard]; + NSPasteboard* pasteboard = NSPasteboard.generalPasteboard; return pasteboard; } -base::scoped_nsobject<NSImage> GetNSImage(NSPasteboard* pasteboard) { +NSImage* GetNSImage(NSPasteboard* pasteboard) { // If the pasteboard's image data is not to its liking, the guts of NSImage // may throw, and that exception will leak. Prevent a crash in that case; // a blank image is better. - base::scoped_nsobject<NSImage> image; + NSImage* image; @try { - if (pasteboard) - image.reset([[NSImage alloc] initWithPasteboard:pasteboard]); + if (pasteboard) { + image = [[NSImage alloc] initWithPasteboard:pasteboard]; + } } @catch (id exception) { } - if (!image) - return base::scoped_nsobject<NSImage>(); - if ([[image representations] count] == 0u) - return base::scoped_nsobject<NSImage>(); + if (!image) { + return nil; + } + if (image.representations.count == 0u) { + return nil; + } return image; } @@ -148,8 +154,9 @@ DCHECK(CalledOnValidThread()); DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste); - // https://crbug.com/1016740#c21 - base::scoped_nsobject<NSArray> types([[GetPasteboard() types] retain]); + // https://crbug.com/1016740#c21: The pasteboard types array may end up going + // away; make a copy. + NSArray* types = [GetPasteboard().types copy]; // Safari only places RTF on the pasteboard, never HTML. We can convert RTF // to HTML, so the presence of either indicates success when looking for HTML. @@ -230,7 +237,7 @@ types->clear(); *types = GetStandardFormats(buffer, data_dst); - if ([[pb types] containsObject:kUTTypeChromiumWebCustomData]) { + if ([pb.types containsObject:kUTTypeChromiumWebCustomData]) { NSData* data = [pb dataForType:kUTTypeChromiumWebCustomData]; if ([data length]) ReadCustomDataTypes([data bytes], [data length], types); @@ -498,7 +505,7 @@ // If we can’t read a PNG, try reading for an NSImage, and if successful, // transcode it to PNG. - base::scoped_nsobject<NSImage> image = GetNSImage(pasteboard); + NSImage* image = GetNSImage(pasteboard); if (!image) { std::move(callback).Run({}); return; @@ -545,8 +552,7 @@ NSData* data = [image_rep representationUsingType:NSBitmapImageFileTypePNG properties:@{}]; if (data) { - base::scoped_nsobject<NSPasteboardItem> pasteboard_item( - [[NSPasteboardItem alloc] init]); + NSPasteboardItem* pasteboard_item = [[NSPasteboardItem alloc] init]; [pasteboard_item setData:data forType:NSPasteboardTypePNG]; if ([pasteboard writeObjects:@[ pasteboard_item ]]) { return; @@ -555,7 +561,7 @@ // Otherwise, fall back to writing the NSImage directly to the clipboard, // which will write only a TIFF. - base::scoped_nsobject<NSImage> image([[NSImage alloc] init]); + NSImage* image = [[NSImage alloc] init]; [image addRepresentation:image_rep]; [image setSize:NSMakeSize(bitmap.width(), bitmap.height())]; [pasteboard writeObjects:@[ image ]];
diff --git a/ui/base/clipboard/clipboard_mac_unittest.mm b/ui/base/clipboard/clipboard_mac_unittest.mm index 9b6a7e04..0e21816 100644 --- a/ui/base/clipboard/clipboard_mac_unittest.mm +++ b/ui/base/clipboard/clipboard_mac_unittest.mm
@@ -12,7 +12,6 @@ #include "base/feature_list.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" -#include "base/mac/scoped_nsobject.h" #include "base/memory/free_deleter.h" #include "base/memory/ref_counted.h" #include "base/test/scoped_feature_list.h" @@ -26,11 +25,15 @@ #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/skia_util.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + @interface RedView : NSView @end @implementation RedView - (void)drawRect:(NSRect)dirtyRect { - [[NSColor redColor] setFill]; + [NSColor.redColor setFill]; NSRectFill(dirtyRect); [super drawRect:dirtyRect]; } @@ -61,9 +64,7 @@ PlatformTest::SetUp(); } - base::scoped_nsobject<NSImage> CreateImage(int32_t width, - int32_t height, - bool retina) { + NSImage* CreateImage(int32_t width, int32_t height, bool retina) { int32_t pixel_width = retina ? width * 2 : width; int32_t pixel_height = retina ? height * 2 : height; @@ -83,9 +84,8 @@ CGImageCreate(pixel_width, pixel_height, 8, 32, 4 * pixel_width, color_space.get(), kCGBitmapByteOrderDefault, provider.get(), nullptr, NO, kCGRenderingIntentDefault)); - return base::scoped_nsobject<NSImage>([[NSImage alloc] - initWithCGImage:image_ref.get() - size:NSMakeSize(width, height)]); + return [[NSImage alloc] initWithCGImage:image_ref.get() + size:NSMakeSize(width, height)]; } bool ShouldWriteImageWithPng() const { return GetParam(); } @@ -114,8 +114,7 @@ int32_t width = 99; int32_t height = 101; scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; - base::scoped_nsobject<NSImage> image = CreateImage(width, height, true); - [pasteboard->get() writeObjects:@[ image.get() ]]; + [pasteboard->get() writeObjects:@[ CreateImage(width, height, true) ]]; Clipboard* clipboard = Clipboard::GetForCurrentThread(); ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard); @@ -131,8 +130,7 @@ int32_t width = 99; int32_t height = 101; scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; - base::scoped_nsobject<NSImage> image = CreateImage(width, height, false); - [pasteboard->get() writeObjects:@[ image.get() ]]; + [pasteboard->get() writeObjects:@[ CreateImage(width, height, false) ]]; Clipboard* clipboard = Clipboard::GetForCurrentThread(); ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard); @@ -145,9 +143,9 @@ } TEST_P(ClipboardMacTest, EmptyImage) { - base::scoped_nsobject<NSImage> image([[NSImage alloc] init]); + NSImage* image = [[NSImage alloc] init]; scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; - [pasteboard->get() writeObjects:@[ image.get() ]]; + [pasteboard->get() writeObjects:@[ image ]]; Clipboard* clipboard = Clipboard::GetForCurrentThread(); ClipboardMac* clipboard_mac = static_cast<ClipboardMac*>(clipboard); @@ -167,7 +165,7 @@ // This seems like a round-about way of getting a NSPDFImageRep to shove into // an NSPasteboard. However, I haven't found any other way of generating a // "PDF" image that makes NSPasteboard happy. - base::scoped_nsobject<NSView> v([[RedView alloc] initWithFrame:frame]); + NSView* v = [[RedView alloc] initWithFrame:frame]; NSData* data = [v dataWithPDFInsideRect:frame]; scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard;
diff --git a/ui/base/clipboard/clipboard_util_mac.h b/ui/base/clipboard/clipboard_util_mac.h index 4c87064d5..d2701c8 100644 --- a/ui/base/clipboard/clipboard_util_mac.h +++ b/ui/base/clipboard/clipboard_util_mac.h
@@ -15,6 +15,13 @@ #include "ui/base/clipboard/clipboard_buffer.h" #include "ui/base/clipboard/file_info.h" +@interface URLAndTitle : NSObject + +@property(readonly) NSString* URL; +@property(readonly) NSString* title; + +@end + namespace ui { class COMPONENT_EXPORT(UI_BASE_CLIPBOARD) UniquePasteboard @@ -45,14 +52,12 @@ // For a given pasteboard, reads and extracts the URLs to be found on it. If // `include_files` is set, then any file references on the pasteboard will be -// returned as file URLs. The two out-parameter arrays are guaranteed to be the -// same length when this function completes. Returns true if at least one URL -// was successfully read, and false otherwise. +// returned as file URLs. Returns an array of URLAndTitle objects each holding +// a URL and title pair read from the pasteboard. If no URLs were successfully +// read, the array will be empty. COMPONENT_EXPORT(UI_BASE_CLIPBOARD) -bool URLsAndTitlesFromPasteboard(NSPasteboard* pboard, - bool include_files, - NSArray<NSString*>** urls, - NSArray<NSString*>** titles); +NSArray<URLAndTitle*>* URLsAndTitlesFromPasteboard(NSPasteboard* pboard, + bool include_files); // For a given pasteboard, extracts the files found on it. COMPONENT_EXPORT(UI_BASE_CLIPBOARD)
diff --git a/ui/base/clipboard/clipboard_util_mac.mm b/ui/base/clipboard/clipboard_util_mac.mm index 116f63e..0cb9b30c 100644 --- a/ui/base/clipboard/clipboard_util_mac.mm +++ b/ui/base/clipboard/clipboard_util_mac.mm
@@ -10,6 +10,7 @@ #include <string> +#include "base/apple/bridging.h" #include "base/files/file_path.h" #include "base/mac/foundation_util.h" #include "base/notreached.h" @@ -19,23 +20,47 @@ #include "ui/base/clipboard/url_file_parser.h" #include "url/gurl.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface URLAndTitle () + +@property(copy) NSString* URL; +@property(copy) NSString* title; + ++ (instancetype)URLAndTitleWithURL:(NSString*)url title:(NSString*)title; + +@end + +@implementation URLAndTitle + +@synthesize URL = _url; +@synthesize title = _title; + ++ (instancetype)URLAndTitleWithURL:(NSString*)url title:(NSString*)title { + URLAndTitle* result = [[URLAndTitle alloc] init]; + result.URL = url; + result.title = title; + return result; +} + +@end + namespace ui { namespace { // Reads the "WebKitWebURLsWithTitles" type put onto the pasteboard by Safari -// and returns the URLs/titles found within. Returns true if this was -// successful, or false if it was not. -bool ReadWebURLsWithTitlesPboardType(NSPasteboard* pboard, - NSArray<NSString*>** urls, - NSArray<NSString*>** titles) { +// and returns the URLs/titles found within. +NSArray<URLAndTitle*>* ReadWebURLsWithTitlesPboardType(NSPasteboard* pboard) { NSArray* bookmark_pairs = base::mac::ObjCCast<NSArray>( [pboard propertyListForType:kUTTypeWebKitWebURLsWithTitles]); if (!bookmark_pairs) { - return false; + return [NSArray array]; } if (bookmark_pairs.count != 2) { - return false; + return [NSArray array]; } NSArray<NSString*>* urls_array = @@ -44,29 +69,33 @@ base::mac::ObjCCast<NSArray>(bookmark_pairs[1]); if (!urls_array || !titles_array) { - return false; + return [NSArray array]; } if (urls_array.count < 1) { - return false; + return [NSArray array]; } if (urls_array.count != titles_array.count) { - return false; + return [NSArray array]; } for (id obj in urls_array) { if (![obj isKindOfClass:[NSString class]]) { - return false; + return [NSArray array]; } } for (id obj in titles_array) { if (![obj isKindOfClass:[NSString class]]) { - return false; + return [NSArray array]; } } - *urls = urls_array; - *titles = titles_array; - return true; + NSMutableArray<URLAndTitle*>* result = [NSMutableArray array]; + for (NSUInteger i = 0; i < urls_array.count; ++i) { + [result addObject:[URLAndTitle URLAndTitleWithURL:urls_array[i] + title:titles_array[i]]]; + } + + return result; } // Returns the user-visible name of the file, optionally without any extension. @@ -106,20 +135,14 @@ return [localized_name stringByDeletingPathExtension]; } -// A simple pair of URL with title. Valid if the `url` field is not null. -struct URLAndTitle { - NSString* url = nil; - NSString* title = nil; -}; - // Returns a URL and title if standard URL and URL title types are present on // the pasteboard item. Because the Finder and/or the core macOS drag code // automatically turn .webloc file drags into standard URL types, .webloc file // drags are also handled by this function. -URLAndTitle ExtractStandardURLAndTitle(NSPasteboardItem* item) { +URLAndTitle* ExtractStandardURLAndTitle(NSPasteboardItem* item) { NSString* url = [item stringForType:NSPasteboardTypeURL]; if (!url) { - return {}; + return nil; } NSString* title = [item stringForType:kUTTypeURLName]; @@ -141,22 +164,22 @@ if (![file_url getResourceValue:&type forKey:NSURLContentTypeKey error:nil]) { - return {}; + return nil; } if (![type conformsToType:UTTypeInternetLocation]) { - return {}; + return nil; } } else { NSString* type; if (![file_url getResourceValue:&type forKey:NSURLTypeIdentifierKey error:nil]) { - return {}; + return nil; } if (![NSWorkspace.sharedWorkspace type:type - conformsToType:base::mac::CFToNSCast( + conformsToType:base::apple::CFToNSPtrCast( kUTTypeInternetLocation)]) { - return {}; + return nil; } } @@ -169,15 +192,15 @@ title = [NSURL URLWithString:url].host; } - return {.url = url, .title = title}; + return [URLAndTitle URLAndTitleWithURL:url title:title]; } // Returns a URL and title if the pasteboard item is of a standard Microsoft // Windows IShellLink-style .url file. -URLAndTitle ExtractURLFromURLFile(NSPasteboardItem* item) { +URLAndTitle* ExtractURLFromURLFile(NSPasteboardItem* item) { NSString* file = [item stringForType:NSPasteboardTypeFileURL]; if (!file) { - return {}; + return nil; } NSURL* file_url = [NSURL URLWithString:file].filePathURL; @@ -187,18 +210,18 @@ resourceValuesForKeys:@[ NSURLFileSizeKey, NSURLContentTypeKey ] error:nil]; if (!resource_values) { - return {}; + return nil; } NSNumber* file_size = resource_values[NSURLFileSizeKey]; if (file_size.unsignedLongValue > clipboard_util::internal::kMaximumParsableFileSize) { - return {}; + return nil; } UTType* type = resource_values[NSURLContentTypeKey]; if (![type conformsToType:UTTypeInternetShortcut]) { - return {}; + return nil; } } else { NSDictionary* resource_values; @@ -206,13 +229,13 @@ resourceValuesForKeys:@[ NSURLFileSizeKey, NSURLTypeIdentifierKey ] error:nil]; if (!resource_values) { - return {}; + return nil; } NSNumber* file_size = resource_values[NSURLFileSizeKey]; if (file_size.unsignedLongValue > clipboard_util::internal::kMaximumParsableFileSize) { - return {}; + return nil; } NSString* type = resource_values[NSURLTypeIdentifierKey]; @@ -220,7 +243,7 @@ @"com.microsoft.internet-shortcut"; if (![NSWorkspace.sharedWorkspace type:type conformsToType:kUTTypeInternetShortcut]) { - return {}; + return nil; } } @@ -230,27 +253,28 @@ encoding:NSWindowsCP1252StringEncoding error:nil]; if (!contents) { - return {}; + return nil; } std::string found_url = clipboard_util::internal::ExtractURLFromURLFileContents( base::SysNSStringToUTF8(contents)); if (found_url.empty()) { - return {}; + return nil; } NSString* title = DeriveTitleFromFilename(file_url, /*strip_extension=*/true); - return {.url = base::SysUTF8ToNSString(found_url), .title = title}; + return [URLAndTitle URLAndTitleWithURL:base::SysUTF8ToNSString(found_url) + title:title]; } // Returns a URL and title if a string on the pasteboard item is formatted as a // URL but doesn't actually have the URL type. -URLAndTitle ExtractURLFromStringValue(NSPasteboardItem* item) { +URLAndTitle* ExtractURLFromStringValue(NSPasteboardItem* item) { NSString* string = [item stringForType:NSPasteboardTypeString]; if (!string) { - return {}; + return nil; } string = [string @@ -265,77 +289,69 @@ // needed? If significant time goes by and no one complains, remove this TODO // and don't put that back in. GURL url(base::SysNSStringToUTF8(string)); - if (url.is_valid()) { - // The hostname is the best that can be done for the title. - return {.url = string, .title = base::SysUTF8ToNSString(url.host())}; + if (!url.is_valid()) { + return nil; } - return {}; + // The hostname is the best that can be done for the title. + return [URLAndTitle URLAndTitleWithURL:string + title:base::SysUTF8ToNSString(url.host())]; } // If there is a file URL on the pasteboard, returns that file as the URL and // returns the file's name as the title. -URLAndTitle ExtractFileURL(NSPasteboardItem* item) { +URLAndTitle* ExtractFileURL(NSPasteboardItem* item) { NSString* file = [item stringForType:NSPasteboardTypeFileURL]; if (!file) { - return {}; + return nil; } NSURL* file_url = [NSURL URLWithString:file].filePathURL; NSString* filename = DeriveTitleFromFilename(file_url, /*strip_extension=*/false); - return {.url = file_url.absoluteString, .title = filename}; + return [URLAndTitle URLAndTitleWithURL:file_url.absoluteString + title:filename]; } // Reads the given pasteboard, and returns URLs/titles found on it. If // `include_files` is set, then any file references on the pasteboard will be // returned as file URLs. Returns true if at least one URL was found on the // pasteboard, and false if none were. -bool ReadURLItemsWithTitles(NSPasteboard* pboard, - bool include_files, - NSArray<NSString*>** urls, - NSArray<NSString*>** titles) { - NSMutableArray<NSString*>* urls_array = [NSMutableArray array]; - NSMutableArray<NSString*>* titles_array = [NSMutableArray array]; +NSArray<URLAndTitle*>* ReadURLItemsWithTitles(NSPasteboard* pboard, + bool include_files) { + NSMutableArray<URLAndTitle*>* result = [NSMutableArray array]; for (NSPasteboardItem* item in pboard.pasteboardItems) { // Try each of several ways of getting URLs from the pasteboard item and // stop with the first one that works. - URLAndTitle url_and_title = ExtractStandardURLAndTitle(item); + URLAndTitle* url_and_title = ExtractStandardURLAndTitle(item); - if (!url_and_title.url) { + if (!url_and_title) { url_and_title = ExtractURLFromURLFile(item); } - if (!url_and_title.url) { + if (!url_and_title) { url_and_title = ExtractURLFromStringValue(item); } - if (!url_and_title.url && include_files) { + if (!url_and_title && include_files) { url_and_title = ExtractFileURL(item); } - if (url_and_title.url) { - [urls_array addObject:url_and_title.url]; - [titles_array addObject:url_and_title.title]; + if (url_and_title) { + [result addObject:url_and_title]; } } - if (urls_array.count) { - *urls = urls_array; - *titles = titles_array; - return true; - } else { - return false; - } + return result; } } // namespace UniquePasteboard::UniquePasteboard() - : pasteboard_([[NSPasteboard pasteboardWithUniqueName] retain]) {} + : pasteboard_([NSPasteboard pasteboardWithUniqueName]) {} UniquePasteboard::~UniquePasteboard() { [pasteboard_ releaseGlobally]; @@ -351,7 +367,7 @@ NSMutableArray<NSPasteboardItem*>* items = [NSMutableArray array]; for (NSUInteger i = 0; i < urls.count; ++i) { - NSPasteboardItem* item = [[[NSPasteboardItem alloc] init] autorelease]; + NSPasteboardItem* item = [[NSPasteboardItem alloc] init]; NSString* url_string = urls[i]; NSString* title = titles[i]; @@ -394,12 +410,14 @@ } } -bool URLsAndTitlesFromPasteboard(NSPasteboard* pboard, - bool include_files, - NSArray<NSString*>** urls, - NSArray<NSString*>** titles) { - return ReadWebURLsWithTitlesPboardType(pboard, urls, titles) || - ReadURLItemsWithTitles(pboard, include_files, urls, titles); +NSArray<URLAndTitle*>* URLsAndTitlesFromPasteboard(NSPasteboard* pboard, + bool include_files) { + NSArray<URLAndTitle*>* result = ReadWebURLsWithTitlesPboardType(pboard); + if (result.count) { + return result; + } + + return ReadURLItemsWithTitles(pboard, include_files); } std::vector<FileInfo> FilesFromPasteboard(NSPasteboard* pboard) { @@ -432,7 +450,7 @@ [NSMutableArray arrayWithCapacity:files.size()]; for (const auto& file : files) { NSURL* url = base::mac::FilePathToNSURL(file.path); - NSPasteboardItem* item = [[[NSPasteboardItem alloc] init] autorelease]; + NSPasteboardItem* item = [[NSPasteboardItem alloc] init]; [item setString:url.absoluteString forType:NSPasteboardTypeFileURL]; [items addObject:item]; } @@ -463,8 +481,7 @@ return nil; NSAttributedString* attributed = - [[[NSAttributedString alloc] initWithRTF:rtf_data - documentAttributes:nil] autorelease]; + [[NSAttributedString alloc] initWithRTF:rtf_data documentAttributes:nil]; NSData* html_data = [attributed dataFromRange:NSMakeRange(0, attributed.length) documentAttributes:@{ @@ -473,8 +490,8 @@ error:nil]; // According to the docs, NSHTMLTextDocumentType is UTF-8. - return [[[NSString alloc] initWithData:html_data - encoding:NSUTF8StringEncoding] autorelease]; + return [[NSString alloc] initWithData:html_data + encoding:NSUTF8StringEncoding]; } } // namespace clipboard_util
diff --git a/ui/base/clipboard/clipboard_util_mac_unittest.mm b/ui/base/clipboard/clipboard_util_mac_unittest.mm index c842995..9182fc8 100644 --- a/ui/base/clipboard/clipboard_util_mac_unittest.mm +++ b/ui/base/clipboard/clipboard_util_mac_unittest.mm
@@ -5,7 +5,6 @@ #import "ui/base/clipboard/clipboard_util_mac.h" #include "base/mac/mac_util.h" -#include "base/mac/scoped_nsobject.h" #include "base/memory/ref_counted.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -13,6 +12,10 @@ #include "testing/platform_test.h" #include "ui/base/clipboard/clipboard_constants.h" +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + namespace ui { namespace { @@ -33,17 +36,15 @@ scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; [pasteboard->get() writeObjects:items]; - NSArray* urls = nil; - NSArray* titles = nil; - clipboard_util::URLsAndTitlesFromPasteboard( - pasteboard->get(), /*include_files=*/false, &urls, &titles); + NSArray<URLAndTitle*>* urls_and_titles = + clipboard_util::URLsAndTitlesFromPasteboard(pasteboard->get(), + /*include_files=*/false); - ASSERT_EQ(2u, urls.count); - EXPECT_NSEQ(url_string_1, urls[0]); - EXPECT_NSEQ(url_string_2, urls[1]); - ASSERT_EQ(2u, titles.count); - EXPECT_NSEQ(@"", titles[0]); - EXPECT_NSEQ(title_2, titles[1]); + ASSERT_EQ(2u, urls_and_titles.count); + EXPECT_NSEQ(url_string_1, urls_and_titles[0].URL); + EXPECT_NSEQ(url_string_2, urls_and_titles[1].URL); + EXPECT_NSEQ(@"", urls_and_titles[0].title); + EXPECT_NSEQ(title_2, urls_and_titles[1].title); NSURL* url = [NSURL URLFromPasteboard:pasteboard->get()]; EXPECT_NSEQ(url.absoluteString, url_string_1); @@ -59,15 +60,13 @@ scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; [pasteboard->get() writeObjects:@[ url_string ]]; - NSArray* urls = nil; - NSArray* titles = nil; - clipboard_util::URLsAndTitlesFromPasteboard( - pasteboard->get(), /*include_files=*/false, &urls, &titles); + NSArray<URLAndTitle*>* urls_and_titles = + clipboard_util::URLsAndTitlesFromPasteboard(pasteboard->get(), + /*include_files=*/false); - ASSERT_EQ(1u, urls.count); - EXPECT_NSEQ(@"https://www.google.com/", urls[0]); - ASSERT_EQ(1u, titles.count); - EXPECT_NSEQ(@"www.google.com", titles[0]); + ASSERT_EQ(1u, urls_and_titles.count); + EXPECT_NSEQ(@"https://www.google.com/", urls_and_titles[0].URL); + EXPECT_NSEQ(@"www.google.com", urls_and_titles[0].title); } TEST_F(ClipboardUtilMacTest, PasteboardItemWithFilePath) { @@ -75,7 +74,7 @@ ASSERT_TRUE(url); NSString* url_string = url.absoluteString; - NSPasteboardItem* item = [[[NSPasteboardItem alloc] init] autorelease]; + NSPasteboardItem* item = [[NSPasteboardItem alloc] init]; [item setString:url_string forType:NSPasteboardTypeFileURL]; scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; @@ -83,22 +82,20 @@ // Read without translating file URLs, expect to not find it. - NSArray* urls = nil; - NSArray* titles = nil; - clipboard_util::URLsAndTitlesFromPasteboard( - pasteboard->get(), /*include_files=*/false, &urls, &titles); + NSArray<URLAndTitle*>* urls_and_titles = + clipboard_util::URLsAndTitlesFromPasteboard(pasteboard->get(), + /*include_files=*/false); - ASSERT_EQ(0u, urls.count); - ASSERT_EQ(0u, titles.count); + ASSERT_EQ(0u, urls_and_titles.count); // Read with translating file URLs, expect to find it. - clipboard_util::URLsAndTitlesFromPasteboard( - pasteboard->get(), /*include_files=*/true, &urls, &titles); + urls_and_titles = + clipboard_util::URLsAndTitlesFromPasteboard(pasteboard->get(), + /*include_files=*/true); - ASSERT_EQ(1u, urls.count); - EXPECT_NSEQ(url_string, urls[0]); - ASSERT_EQ(1u, titles.count); + ASSERT_EQ(1u, urls_and_titles.count); + EXPECT_NSEQ(url_string, urls_and_titles[0].URL); } TEST_F(ClipboardUtilMacTest, PasteboardItemDisplayName) { @@ -110,21 +107,19 @@ ASSERT_TRUE(tempdir_url); NSString* url_string = file_url.absoluteString; - NSPasteboardItem* item = [[[NSPasteboardItem alloc] init] autorelease]; + NSPasteboardItem* item = [[NSPasteboardItem alloc] init]; [item setString:url_string forType:NSPasteboardTypeFileURL]; scoped_refptr<UniquePasteboard> pasteboard = new UniquePasteboard; [pasteboard->get() writeObjects:@[ item ]]; - NSArray* urls = nil; - NSArray* titles = nil; - clipboard_util::URLsAndTitlesFromPasteboard( - pasteboard->get(), /*include_files=*/true, &urls, &titles); + NSArray<URLAndTitle*>* urls_and_titles = + clipboard_util::URLsAndTitlesFromPasteboard(pasteboard->get(), + /*include_files=*/true); - ASSERT_EQ(1u, urls.count); - EXPECT_NSEQ(url_string, urls[0]); - ASSERT_EQ(1u, titles.count); - EXPECT_NSEQ(@"a/b.txt", titles[0]); + ASSERT_EQ(1u, urls_and_titles.count); + EXPECT_NSEQ(url_string, urls_and_titles[0].URL); + EXPECT_NSEQ(@"a/b.txt", urls_and_titles[0].title); } TEST_F(ClipboardUtilMacTest, CheckForLeak) {
diff --git a/ui/base/cocoa/base_view.mm b/ui/base/cocoa/base_view.mm index c7f2aea..20a2595 100644 --- a/ui/base/cocoa/base_view.mm +++ b/ui/base/cocoa/base_view.mm
@@ -6,6 +6,8 @@ #include "base/check_op.h" #include "base/mac/mac_util.h" +#include "base/mac/scoped_nsobject.h" +#include "ui/base/cocoa/tracking_area.h" NSString* kViewDidBecomeFirstResponder = @"Chromium.kViewDidBecomeFirstResponder"; @@ -40,10 +42,12 @@ NSTrackingMouseMoved | NSTrackingActiveAlways | NSTrackingInVisibleRect; - _trackingArea.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect - options:trackingOptions - owner:self - userInfo:nil]); + base::scoped_nsobject<CrTrackingArea> trackingArea([[CrTrackingArea alloc] + initWithRect:NSZeroRect + options:trackingOptions + owner:self + userInfo:nil]); + _trackingArea.reset(trackingArea.get()); [self addTrackingArea:_trackingArea.get()]; }
diff --git a/ui/base/cocoa/tracking_area.h b/ui/base/cocoa/tracking_area.h index a58674d..c83af031 100644 --- a/ui/base/cocoa/tracking_area.h +++ b/ui/base/cocoa/tracking_area.h
@@ -40,7 +40,7 @@ // when this goes out of scope. class COMPONENT_EXPORT(UI_BASE) ScopedCrTrackingArea { public: - // Takes ownership of |tracking_area| without retaining it. + // Takes ownership of |tracking_area|. explicit ScopedCrTrackingArea(CrTrackingArea* tracking_area = nil); ScopedCrTrackingArea(const ScopedCrTrackingArea&) = delete;
diff --git a/ui/base/cocoa/tracking_area.mm b/ui/base/cocoa/tracking_area.mm index 26507da..e58325e0 100644 --- a/ui/base/cocoa/tracking_area.mm +++ b/ui/base/cocoa/tracking_area.mm
@@ -99,15 +99,14 @@ namespace ui { ScopedCrTrackingArea::ScopedCrTrackingArea(CrTrackingArea* tracking_area) - : tracking_area_(tracking_area) { -} + : tracking_area_([tracking_area retain]) {} ScopedCrTrackingArea::~ScopedCrTrackingArea() { [tracking_area_ clearOwner]; } void ScopedCrTrackingArea::reset(CrTrackingArea* tracking_area) { - tracking_area_.reset(tracking_area); + tracking_area_.reset([tracking_area retain]); } CrTrackingArea* ScopedCrTrackingArea::get() const {
diff --git a/ui/base/cocoa/tracking_area_unittest.mm b/ui/base/cocoa/tracking_area_unittest.mm index 92105396..f8b814d31 100644 --- a/ui/base/cocoa/tracking_area_unittest.mm +++ b/ui/base/cocoa/tracking_area_unittest.mm
@@ -59,7 +59,7 @@ TEST_F(CrTrackingAreaTest, ScoperInit) { { - ScopedCrTrackingArea scoper([trackingArea_ retain]); + ScopedCrTrackingArea scoper(trackingArea_); [[scoper.get() owner] performMessage]; EXPECT_EQ(1U, [owner_ messageCount]); } @@ -73,7 +73,7 @@ ScopedCrTrackingArea scoper; EXPECT_FALSE(scoper.get()); - scoper.reset([trackingArea_ retain]); + scoper.reset(trackingArea_); [[scoper.get() owner] performMessage]; EXPECT_EQ(1U, [owner_ messageCount]);
diff --git a/ui/base/dragdrop/os_exchange_data_provider_mac.mm b/ui/base/dragdrop/os_exchange_data_provider_mac.mm index 4c4bbfa..3de0d5d4 100644 --- a/ui/base/dragdrop/os_exchange_data_provider_mac.mm +++ b/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -210,12 +210,12 @@ DCHECK(url); DCHECK(title); - NSArray<NSString*>* urls; - NSArray<NSString*>* titles; - if (clipboard_util::URLsAndTitlesFromPasteboard( - GetPasteboard(), /*include_files=*/false, &urls, &titles)) { - *url = GURL(base::SysNSStringToUTF8(urls.firstObject)); - *title = base::SysNSStringToUTF16(titles.firstObject); + NSArray<URLAndTitle*>* urls_and_titles = + clipboard_util::URLsAndTitlesFromPasteboard(GetPasteboard(), + /*include_files=*/false); + if (urls_and_titles.count) { + *url = GURL(base::SysNSStringToUTF8(urls_and_titles.firstObject.URL)); + *title = base::SysNSStringToUTF16(urls_and_titles.firstObject.title); return true; }
diff --git a/ui/base/test/ui_controls.h b/ui/base/test/ui_controls.h index f96a5c5..b2151c8b 100644 --- a/ui/base/test/ui_controls.h +++ b/ui/base/test/ui_controls.h
@@ -181,7 +181,7 @@ base::OnceClosure task); #endif -#if defined(USE_AURA) +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) class UIControlsAura; void InstallUIControlsAura(UIControlsAura* instance); #endif
diff --git a/ui/base/test/ui_controls_aura.cc b/ui/base/test/ui_controls_aura.cc index 9bb078d..53f0ae2 100644 --- a/ui/base/test/ui_controls_aura.cc +++ b/ui/base/test/ui_controls_aura.cc
@@ -16,9 +16,11 @@ bool g_ui_controls_enabled = false; } // namespace +#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_WIN) void EnableUIControls() { g_ui_controls_enabled = true; } +#endif void ResetUIControlsIfEnabled() {} @@ -163,11 +165,13 @@ UIControlsAura::~UIControlsAura() { } +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_WIN) // static. declared in ui_controls.h void InstallUIControlsAura(UIControlsAura* instance) { - EnableUIControls(); + g_ui_controls_enabled = true; delete instance_; instance_ = instance; } +#endif //! BUILDFLAG(IS_CHROMEOS_ASH) } // namespace ui_controls
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc index 0284eaa..b98320a8 100644 --- a/ui/color/ui_color_mixer.cc +++ b/ui/color/ui_color_mixer.cc
@@ -74,23 +74,11 @@ mixer[kColorDropdownForegroundSelected] = {kColorPrimaryForeground}; mixer[kColorFocusableBorderFocused] = {kColorItemHighlight}; mixer[kColorFocusableBorderUnfocused] = {kColorMidground}; -#if BUILDFLAG(IS_CHROMEOS) - // TODO(b/267817808): Replace cros_tokens::kCrosRefSecondary20 with - // cros_tokens::kCrosRefSecondary15 once it's added. - mixer[kColorFrameActive] = {dark_mode ? kColorRefSecondary20 - : kColorSysHeader}; -#else mixer[kColorFrameActive] = {kColorFrameActiveUnthemed}; -#endif // BUILDFLAG(IS_CHROMEOS) mixer[kColorFrameActiveUnthemed] = { dark_mode ? gfx::kGoogleGrey900 : SkColorSetRGB(0xDE, 0xE1, 0xE6)}; -#if BUILDFLAG(IS_CHROMEOS) - mixer[kColorFrameInactive] = {dark_mode ? kColorSysSurface1 - : kColorSysSurface3}; -#else mixer[kColorFrameInactive] = {dark_mode ? gfx::kGoogleGrey800 : gfx::kGoogleGrey200}; -#endif // BUILDFLAG(IS_CHROMEOS) mixer[kColorHelpIconActive] = {kColorPrimaryForeground}; mixer[kColorHelpIconInactive] = {kColorSecondaryForeground}; mixer[kColorIcon] = {kColorSecondaryForeground};
diff --git a/ui/views/test/ui_controls_factory_desktop_aura_ozone.cc b/ui/views/test/ui_controls_factory_desktop_aura_ozone.cc index 86bda060..187e55a 100644 --- a/ui/views/test/ui_controls_factory_desktop_aura_ozone.cc +++ b/ui/views/test/ui_controls_factory_desktop_aura_ozone.cc
@@ -18,7 +18,6 @@ #include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" #include "ui/aura/test/aura_test_utils.h" -#include "ui/aura/test/ui_controls_factory_aura.h" #include "ui/aura/window_event_dispatcher.h" #include "ui/base/test/ui_controls.h" #include "ui/gfx/native_widget_types.h" @@ -36,7 +35,6 @@ using ui_controls::MIDDLE; using ui_controls::MouseButton; using ui_controls::RIGHT; -using ui_controls::UIControlsAura; using ui_controls::UP; aura::Window* RootWindowForPoint(const gfx::Point& point,
diff --git a/ui/views/widget/desktop_aura/README.chromium b/ui/views/widget/desktop_aura/README.chromium index 0cf7dc9..49ba0706 100644 --- a/ui/views/widget/desktop_aura/README.chromium +++ b/ui/views/widget/desktop_aura/README.chromium
@@ -30,7 +30,7 @@ Moving onto aura-specific concepts: * aura::Window: A cross-platform abstraction that replaces the NativeWindow. Forms a tree hierarchy. An aura::Window is effectively an abstraction over a - ui:::Layer that handles events as an EventTarget. + ui::Layer that handles events as an EventTarget. * WindowTreeHost: Provides the root aura::Window. WindowTreeHost owns a compositor that ultimately enables rendering the contents of an aura::Window tree on to an AcceleratedWidget.
diff --git a/ui/webui/resources/cr_elements/chromeos/cros_color_overrides.css b/ui/webui/resources/cr_elements/chromeos/cros_color_overrides.css index 8e5696de..fd3267c7 100644 --- a/ui/webui/resources/cr_elements/chromeos/cros_color_overrides.css +++ b/ui/webui/resources/cr_elements/chromeos/cros_color_overrides.css
@@ -106,7 +106,7 @@ --cr-form-field-label-color: var(--cros-sys-on_surface); --cr-link-color: var(--cros-sys-primary); --cr-primary-text-color: var(--cros-sys-on_surface); - --cr-secondary-text-color: var(--cros-sys-secondary); + --cr-secondary-text-color: var(--cros-sys-on_surface_variant); } /* Button */
diff --git a/weblayer/browser/webapps/webapk_install_scheduler.cc b/weblayer/browser/webapps/webapk_install_scheduler.cc index e97003be..038d242 100644 --- a/weblayer/browser/webapps/webapk_install_scheduler.cc +++ b/weblayer/browser/webapps/webapk_install_scheduler.cc
@@ -27,9 +27,11 @@ WebApkInstallScheduler::WebApkInstallScheduler( const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, WebApkInstallFinishedCallback callback) : webapps_client_callback_(std::move(callback)), - primary_icon_(primary_icon) { + primary_icon_(primary_icon), + is_primary_icon_maskable_(is_primary_icon_maskable) { shortcut_info_ = std::make_unique<webapps::ShortcutInfo>(shortcut_info); } @@ -40,12 +42,14 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, WebApkInstallFinishedCallback callback) { // Self owned WebApkInstallScheduler that destroys itself as soon as its // OnResult function is called when the scheduled installation failed or // finished. - WebApkInstallScheduler* scheduler = new WebApkInstallScheduler( - shortcut_info, primary_icon, std::move(callback)); + WebApkInstallScheduler* scheduler = + new WebApkInstallScheduler(shortcut_info, primary_icon, + is_primary_icon_maskable, std::move(callback)); scheduler->FetchMurmur2Hashes(web_contents); } @@ -87,7 +91,7 @@ webapps::BuildProto( *shortcut_info_.get(), shortcut_info_->manifest_id, - std::string() /* primary_icon_data */, + std::string() /* primary_icon_data */, is_primary_icon_maskable_, std::string() /* splash_icon_data */, "" /* package_name */, "" /* version */, std::move(*hashes), false /* is_manifest_stale */, false /* is_app_identity_update_supported */, @@ -98,8 +102,7 @@ void WebApkInstallScheduler::ScheduleWithChrome( std::unique_ptr<std::string> serialized_proto) { WebApkInstallSchedulerBridge::ScheduleWebApkInstallWithChrome( - std::move(serialized_proto), primary_icon_, - shortcut_info_->is_primary_icon_maskable, + std::move(serialized_proto), primary_icon_, is_primary_icon_maskable_, base::BindOnce(&WebApkInstallScheduler::OnResult, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/weblayer/browser/webapps/webapk_install_scheduler.h b/weblayer/browser/webapps/webapk_install_scheduler.h index e6ad388..54159007 100644 --- a/weblayer/browser/webapps/webapk_install_scheduler.h +++ b/weblayer/browser/webapps/webapk_install_scheduler.h
@@ -47,6 +47,7 @@ content::WebContents* web_contents, const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, WebApkInstallFinishedCallback callback); void FetchProtoAndScheduleInstallForTesting( @@ -57,6 +58,7 @@ private: WebApkInstallScheduler(const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, WebApkInstallFinishedCallback callback); friend class TestWebApkInstallScheduler; @@ -75,6 +77,7 @@ WebApkInstallFinishedCallback webapps_client_callback_; std::unique_ptr<webapps::ShortcutInfo> shortcut_info_; const SkBitmap primary_icon_; + bool is_primary_icon_maskable_; // Used to get |weak_ptr_|. base::WeakPtrFactory<WebApkInstallScheduler> weak_ptr_factory_{this};
diff --git a/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc b/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc index 9970784..c0d2b9f 100644 --- a/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc +++ b/weblayer/browser/webapps/webapk_install_scheduler_browsertest.cc
@@ -45,9 +45,11 @@ public: TestWebApkInstallScheduler(const webapps::ShortcutInfo& shortcut_info, const SkBitmap& primary_icon, + bool is_primary_icon_maskable, WebApkInstallFinishedCallback callback) : WebApkInstallScheduler(shortcut_info, primary_icon, + is_primary_icon_maskable, std::move(callback)) {} TestWebApkInstallScheduler(const TestWebApkInstallScheduler&) = delete; @@ -157,7 +159,7 @@ webapps::ShortcutInfo info) { std::unique_ptr<TestWebApkInstallScheduler> scheduler_bridge( new TestWebApkInstallScheduler( - info, SkBitmap(), + info, SkBitmap(), false, base::BindOnce(&WebApkInstallSchedulerTest::OnInstallFinished, base::Unretained(this)))); return scheduler_bridge;
diff --git a/weblayer/browser/webapps/weblayer_webapps_client.cc b/weblayer/browser/webapps/weblayer_webapps_client.cc index f3a5d34..ed9c9c2 100644 --- a/weblayer/browser/webapps/weblayer_webapps_client.cc +++ b/weblayer/browser/webapps/weblayer_webapps_client.cc
@@ -100,6 +100,7 @@ current_install_ids_.insert(params.shortcut_info->manifest_id); WebApkInstallScheduler::FetchProtoAndScheduleInstall( web_contents, *(params.shortcut_info), params.primary_icon, + params.has_maskable_primary_icon, base::BindOnce(&WebLayerWebappsClient::OnInstallFinished, weak_ptr_factory_.GetWeakPtr())); } @@ -111,7 +112,7 @@ webapps::addShortcutToHomescreen( base::Uuid::GenerateRandomV4().AsLowercaseString(), info.url, - info.user_title, params.primary_icon, info.is_primary_icon_maskable); + info.user_title, params.primary_icon, params.has_maskable_primary_icon); } void WebLayerWebappsClient::OnInstallFinished(GURL manifest_id) {