diff --git a/DEPS b/DEPS index 61060ee..af0bf08 100644 --- a/DEPS +++ b/DEPS
@@ -304,7 +304,7 @@ # 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': '0e0aa7e82d3a476d6e983b1fc383186082e948ad', + 'skia_revision': '5fa5d5958628088f44a784fa5f69a27ec60488d9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -312,7 +312,7 @@ # 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': '34a06e25df2a1625bad36ab565319dace7cc5c54', + 'angle_revision': '997c4c7b3d6bf1d0bc1e92267ae50d372f76a502', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -331,7 +331,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. - 'fuchsia_version': 'version:12.20230323.1.1', + 'fuchsia_version': 'version:12.20230323.3.1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling google-toolbox-for-mac # and whatever else without interference from each other. @@ -455,7 +455,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '39df20d821ba6988fa3e2aa0ae42eadf4298c617', + 'nearby_revision': '3f1b0c81e3c441f89b94843a60461677972f163e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -495,7 +495,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': 'e44019bfac2b2d3ebe1618628884f85c8600e322', + 'libcxx_revision': '5622befaf8a9d539bc94c9f1341b8e76065334db', # GN CIPD package version. 'gn_version': 'git_revision:41fef642de70ecdcaaa26be96d56a0398f95abd4', @@ -790,7 +790,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '52e08fba3410cf3b5d3d18734052bc45bc42f28c', + 'e4e0d6c5312163f362c568a5b7dd89e23a612bf7', 'condition': 'checkout_android and checkout_src_internal', }, @@ -819,7 +819,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c9eba0ffc740ea68f455e39c19e0c0230282c7cb', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'ba1e10d39bb1fa6086410c0a86d6b06604d082f5', 'condition': 'checkout_ios', }, @@ -979,7 +979,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'Bd5GuYdu-KY7DAsP-QU0XofyaFYU7ySZX8QQpca7j3sC', + 'version': 'NiTVtksLm4vhVv9RrW0oOiw5xdUpMuEuyGmD1_YR5kkC', }, ], 'condition': 'checkout_android', @@ -1230,7 +1230,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '479e1e9055020c8d1351bf2194d0a606aeca93d5', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c799f76f30dec736e37da32da2395cb29ed4ede4', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1702,7 +1702,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '134b1104235eedbaa47555f5c27fa8d0b6c0c7c3', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'bfdb3fc5cc0fc2ea9324caef920ceb30c1e3d9f5', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1884,10 +1884,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'b9f099aa09dfb96e4f9851c05cf900cc9e13a4f5', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '07ce6fa80556ad9ea530f68bd82ffcafede40728', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '31a10d321a6cf300da27610bd30469982b8e51fd', + Var('webrtc_git') + '/src.git' + '@' + 'd3e765e4eb4af8eba0c63b6bfe2e17a12dc670dc', # Wuffs' canonical repository is at github.com/google/wuffs, but we use # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file. @@ -1964,7 +1964,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': Var('chrome_git') + '/chrome/src-internal.git@c6737ebfc10f0a0896b17cfd173c7df2c6c3f66f', + 'url': Var('chrome_git') + '/chrome/src-internal.git@9f5a9e63630393ca7e0e10fcca591a9874348387', 'condition': 'checkout_src_internal', },
diff --git a/ash/accelerators/ash_accelerator_configuration.cc b/ash/accelerators/ash_accelerator_configuration.cc index 5df2199..e0d975c2 100644 --- a/ash/accelerators/ash_accelerator_configuration.cc +++ b/ash/accelerators/ash_accelerator_configuration.cc
@@ -11,6 +11,7 @@ #include "ash/constants/ash_features.h" #include "ash/public/cpp/accelerators.h" #include "ash/public/cpp/accelerators_util.h" +#include "ash/public/mojom/accelerator_configuration.mojom-shared.h" #include "ash/public/mojom/accelerator_configuration.mojom.h" #include "ash/public/mojom/accelerator_info.mojom.h" #include "base/containers/contains.h" @@ -163,7 +164,19 @@ AcceleratorConfigResult AshAcceleratorConfiguration::AddUserAccelerator( AcceleratorActionId action_id, const ui::Accelerator& accelerator) { - return AcceleratorConfigResult::kActionLocked; + CHECK(::features::IsShortcutCustomizationEnabled()); + const AcceleratorConfigResult result = + DoAddAccelerator(action_id, accelerator); + + if (result == AcceleratorConfigResult::kSuccess) { + UpdateAndNotifyAccelerators(); + } + + VLOG(1) << "AddAccelerator called for ActionID: " << action_id + << ", Accelerator: " << accelerator.GetShortcutText() + << " returned: " << static_cast<int>(result); + + return result; } AcceleratorConfigResult AshAcceleratorConfiguration::RemoveAccelerator( @@ -358,6 +371,37 @@ return AcceleratorConfigResult::kSuccess; } +AcceleratorConfigResult AshAcceleratorConfiguration::DoAddAccelerator( + AcceleratorActionId action_id, + const ui::Accelerator& accelerator) { + CHECK(::features::IsShortcutCustomizationEnabled()); + + const auto& accelerators_iter = id_to_accelerators_.find(action_id); + if (accelerators_iter == id_to_accelerators_.end()) { + return AcceleratorConfigResult::kNotFound; + } + + // Check if `accelerator` is already used, in-use or deprecated. If so + // remove/disable it. + const auto* conflict_action_id = FindAcceleratorAction(accelerator); + if (conflict_action_id) { + const AcceleratorConfigResult remove_result = + DoRemoveAccelerator(*conflict_action_id, accelerator); + if (remove_result != AcceleratorConfigResult::kSuccess) { + return remove_result; + } + } + + // Add the accelerator. + auto& accelerators = accelerators_iter->second; + accelerators.push_back(accelerator); + accelerator_to_id_.InsertNew( + {accelerator, static_cast<AcceleratorAction>(action_id)}); + + // TODO(jimmyxgong): Update prefs to match updated state. + return AcceleratorConfigResult::kSuccess; +} + const DeprecatedAcceleratorData* AshAcceleratorConfiguration::GetDeprecatedAcceleratorData( AcceleratorActionId action) {
diff --git a/ash/accelerators/ash_accelerator_configuration.h b/ash/accelerators/ash_accelerator_configuration.h index d431a6a..b0bbdd2 100644 --- a/ash/accelerators/ash_accelerator_configuration.h +++ b/ash/accelerators/ash_accelerator_configuration.h
@@ -12,6 +12,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/accelerator_configuration.h" #include "ash/public/cpp/accelerators.h" +#include "ash/public/mojom/accelerator_configuration.mojom-shared.h" #include "ash/public/mojom/accelerator_configuration.mojom.h" #include "ash/public/mojom/accelerator_info.mojom.h" #include "base/containers/flat_set.h" @@ -118,6 +119,11 @@ AcceleratorActionId action_id, const ui::Accelerator& accelerator); + // Adds the accelerator, does not notify observers. + mojom::AcceleratorConfigResult DoAddAccelerator( + AcceleratorActionId action_id, + const ui::Accelerator& accelerator); + void NotifyAcceleratorsUpdated(); void UpdateAndNotifyAccelerators();
diff --git a/ash/accelerators/ash_accelerator_configuration_unittest.cc b/ash/accelerators/ash_accelerator_configuration_unittest.cc index 22c18dc..f475413a 100644 --- a/ash/accelerators/ash_accelerator_configuration_unittest.cc +++ b/ash/accelerators/ash_accelerator_configuration_unittest.cc
@@ -741,4 +741,351 @@ EXPECT_EQ(1, observer_.num_times_accelerator_updated_called()); } +// Add accelerator with no conflict. +TEST_F(AshAcceleratorConfigurationTest, AddAccelerator) { + EXPECT_EQ(0, observer_.num_times_accelerator_updated_called()); + const AcceleratorData test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + config_->Initialize(test_data); + + ExpectAllAcceleratorsEqual(test_data, config_->GetAllAccelerators()); + EXPECT_EQ(1, observer_.num_times_accelerator_updated_called()); + + // Add CTRL + SPACE to SWITCH_TO_LAST_USED_IME. + const AcceleratorData updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, + SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + const ui::Accelerator new_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN); + AcceleratorConfigResult result = + config_->AddUserAccelerator(SWITCH_TO_LAST_USED_IME, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + + // Compare expected accelerators and that the observer was fired after + // adding an accelerator. + EXPECT_EQ(2, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(updated_test_data, config_->GetAllAccelerators()); + const AcceleratorAction* found_action = + config_->FindAcceleratorAction(new_accelerator); + EXPECT_TRUE(found_action); + EXPECT_EQ(SWITCH_TO_LAST_USED_IME, *found_action); +} + +// Add accelerator that conflict with default accelerator. +TEST_F(AshAcceleratorConfigurationTest, AddAcceleratorDefaultConflict) { + EXPECT_EQ(0, observer_.num_times_accelerator_updated_called()); + const AcceleratorData test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + config_->Initialize(test_data); + + ExpectAllAcceleratorsEqual(test_data, config_->GetAllAccelerators()); + EXPECT_EQ(1, observer_.num_times_accelerator_updated_called()); + + // Add ALT + SHIFT + TAB to SWITCH_TO_LAST_USED_IME, which conflicts with + // CYCLE_BACKWARD_MRU. + const AcceleratorData updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + }; + + const ui::Accelerator new_accelerator(ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN); + AcceleratorConfigResult result = + config_->AddUserAccelerator(SWITCH_TO_LAST_USED_IME, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + + // Compare expected accelerators and that the observer was fired after + // removing an accelerator. + EXPECT_EQ(2, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(updated_test_data, config_->GetAllAccelerators()); + const AcceleratorAction* found_action = + config_->FindAcceleratorAction(new_accelerator); + EXPECT_TRUE(found_action); + EXPECT_EQ(SWITCH_TO_LAST_USED_IME, *found_action); + + // Confirm that conflicting accelerator was removed. + const std::vector<ui::Accelerator>& backward_mru_accelerators = + config_->GetAcceleratorsForAction(CYCLE_BACKWARD_MRU); + EXPECT_TRUE(backward_mru_accelerators.empty()); +} + +// Add accelerator that conflicts with a deprecated accelerator. +TEST_F(AshAcceleratorConfigurationTest, AddAcceleratorDeprecatedConflict) { + EXPECT_EQ(0, observer_.num_times_accelerator_updated_called()); + const AcceleratorData test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + const DeprecatedAcceleratorData deprecated_data[] = { + {SHOW_TASK_MANAGER, /*uma_histogram_name=*/"deprecated.showTaskManager", + /*notification_message_id=*/1, /*old_shortcut_id=*/1, + /*new_shortcut_id=*/2, /*deprecated_enabled=*/true}, + }; + + const AcceleratorData test_deprecated_accelerators[] = { + {/*trigger_on_press=*/true, ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, + SHOW_TASK_MANAGER}, + }; + + const AcceleratorData initial_expected_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, + SHOW_TASK_MANAGER}, + }; + + config_->Initialize(test_data); + config_->InitializeDeprecatedAccelerators(deprecated_data, + test_deprecated_accelerators); + + ExpectAllAcceleratorsEqual(initial_expected_data, + config_->GetAllAccelerators()); + // Initializing deprecated accelerators will also trigger the observer. + EXPECT_EQ(2, observer_.num_times_accelerator_updated_called()); + + const ui::Accelerator deprecated_accelerator(ui::VKEY_ESCAPE, + ui::EF_SHIFT_DOWN); + EXPECT_TRUE(config_->IsDeprecated(deprecated_accelerator)); + + // Add SHIFT + ESCAPE to SWITCH_TO_LAST_USED_IME, which conflicts with + // a deprecated accelerator. + const AcceleratorData updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_ESCAPE, ui::EF_SHIFT_DOWN, + SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + AcceleratorConfigResult result = config_->AddUserAccelerator( + SWITCH_TO_LAST_USED_IME, deprecated_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + + // Compare expected accelerators and that the observer was fired after + // removing an accelerator. + EXPECT_EQ(3, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(updated_test_data, config_->GetAllAccelerators()); + const AcceleratorAction* found_action = + config_->FindAcceleratorAction(deprecated_accelerator); + EXPECT_TRUE(found_action); + EXPECT_EQ(SWITCH_TO_LAST_USED_IME, *found_action); + + // Confirm that the deprecated accelerator was removed. + EXPECT_FALSE(config_->IsDeprecated(deprecated_accelerator)); +} + +// Add and then remove an accelerator. +TEST_F(AshAcceleratorConfigurationTest, AddRemoveAccelerator) { + EXPECT_EQ(0, observer_.num_times_accelerator_updated_called()); + const AcceleratorData test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + config_->Initialize(test_data); + + ExpectAllAcceleratorsEqual(test_data, config_->GetAllAccelerators()); + EXPECT_EQ(1, observer_.num_times_accelerator_updated_called()); + + // Add CTRL + SPACE to SWITCH_TO_LAST_USED_IME. + const AcceleratorData added_updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, + SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + const ui::Accelerator new_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN); + AcceleratorConfigResult result = + config_->AddUserAccelerator(SWITCH_TO_LAST_USED_IME, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + + // Compare expected accelerators and that the observer was fired after + // adding an accelerator. + EXPECT_EQ(2, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(added_updated_test_data, + config_->GetAllAccelerators()); + const AcceleratorAction* found_action = + config_->FindAcceleratorAction(new_accelerator); + EXPECT_TRUE(found_action); + EXPECT_EQ(SWITCH_TO_LAST_USED_IME, *found_action); + + // Remove CTRL + SPACE from SWITCH_TO_LAST_USED_IME. + const AcceleratorData removed_updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + // Remove the accelerator now. + result = config_->RemoveAccelerator(SWITCH_TO_LAST_USED_IME, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + EXPECT_EQ(3, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(removed_updated_test_data, + config_->GetAllAccelerators()); + EXPECT_FALSE(config_->FindAcceleratorAction(new_accelerator)); +} + +// Add accelerator and restore its default. +TEST_F(AshAcceleratorConfigurationTest, AddRestoreAccelerator) { + EXPECT_EQ(0, observer_.num_times_accelerator_updated_called()); + const AcceleratorData test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + config_->Initialize(test_data); + + ExpectAllAcceleratorsEqual(test_data, config_->GetAllAccelerators()); + EXPECT_EQ(1, observer_.num_times_accelerator_updated_called()); + + // Add CTRL + SPACE to SWITCH_TO_LAST_USED_IME. + const AcceleratorData updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, + SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + const ui::Accelerator new_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN); + AcceleratorConfigResult result = + config_->AddUserAccelerator(SWITCH_TO_LAST_USED_IME, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + + // Compare expected accelerators and that the observer was fired after + // adding an accelerator. + EXPECT_EQ(2, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(updated_test_data, config_->GetAllAccelerators()); + const AcceleratorAction* found_action = + config_->FindAcceleratorAction(new_accelerator); + EXPECT_TRUE(found_action); + EXPECT_EQ(SWITCH_TO_LAST_USED_IME, *found_action); + + // Restore default, expect to be back to default state. + result = config_->RestoreDefault(SWITCH_TO_LAST_USED_IME); + EXPECT_EQ(3, observer_.num_times_accelerator_updated_called()); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + EXPECT_FALSE(config_->FindAcceleratorAction(new_accelerator)); + ExpectAllAcceleratorsEqual(test_data, config_->GetAllAccelerators()); +} + +// Add an accelerator, then add the same accelerator to another action. +TEST_F(AshAcceleratorConfigurationTest, ReAddAcceleratorToAnotherAction) { + EXPECT_EQ(0, observer_.num_times_accelerator_updated_called()); + const AcceleratorData test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + config_->Initialize(test_data); + + ExpectAllAcceleratorsEqual(test_data, config_->GetAllAccelerators()); + EXPECT_EQ(1, observer_.num_times_accelerator_updated_called()); + + // Add CTRL + SPACE to SWITCH_TO_LAST_USED_IME. + const AcceleratorData updated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, + SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + }; + + const ui::Accelerator new_accelerator(ui::VKEY_SPACE, ui::EF_CONTROL_DOWN); + AcceleratorConfigResult result = + config_->AddUserAccelerator(SWITCH_TO_LAST_USED_IME, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + + // Compare expected accelerators and that the observer was fired after + // adding an accelerator. + EXPECT_EQ(2, observer_.num_times_accelerator_updated_called()); + ExpectAllAcceleratorsEqual(updated_test_data, config_->GetAllAccelerators()); + const AcceleratorAction* found_action = + config_->FindAcceleratorAction(new_accelerator); + EXPECT_TRUE(found_action); + EXPECT_EQ(SWITCH_TO_LAST_USED_IME, *found_action); + + // Add CTRL + SPACE to CYCLE_BACKWARD_MRU. + const AcceleratorData reupdated_test_data[] = { + {/*trigger_on_press=*/true, ui::VKEY_SPACE, + ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN, SWITCH_TO_LAST_USED_IME}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, ui::EF_ALT_DOWN, + CYCLE_FORWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_TAB, + ui::EF_SHIFT_DOWN | ui::EF_ALT_DOWN, CYCLE_BACKWARD_MRU}, + {/*trigger_on_press=*/true, ui::VKEY_SPACE, ui::EF_CONTROL_DOWN, + CYCLE_BACKWARD_MRU}, + }; + result = config_->AddUserAccelerator(CYCLE_BACKWARD_MRU, new_accelerator); + EXPECT_EQ(AcceleratorConfigResult::kSuccess, result); + ExpectAllAcceleratorsEqual(reupdated_test_data, + config_->GetAllAccelerators()); + const AcceleratorAction* found_action2 = + config_->FindAcceleratorAction(new_accelerator); + EXPECT_TRUE(found_action2); + EXPECT_EQ(CYCLE_BACKWARD_MRU, *found_action2); +} } // namespace ash
diff --git a/ash/clipboard/clipboard_history_controller_impl.cc b/ash/clipboard/clipboard_history_controller_impl.cc index 10b8c69d..9070a1a9 100644 --- a/ash/clipboard/clipboard_history_controller_impl.cc +++ b/ash/clipboard/clipboard_history_controller_impl.cc
@@ -322,20 +322,21 @@ observers_.RemoveObserver(observer); } -void ClipboardHistoryControllerImpl::ShowMenu( +bool ClipboardHistoryControllerImpl::ShowMenu( const gfx::Rect& anchor_rect, ui::MenuSourceType source_type, crosapi::mojom::ClipboardHistoryControllerShowSource show_source) { - ShowMenu(anchor_rect, source_type, show_source, OnMenuClosingCallback()); + return ShowMenu(anchor_rect, source_type, show_source, + OnMenuClosingCallback()); } -void ClipboardHistoryControllerImpl::ShowMenu( +bool ClipboardHistoryControllerImpl::ShowMenu( const gfx::Rect& anchor_rect, ui::MenuSourceType source_type, crosapi::mojom::ClipboardHistoryControllerShowSource show_source, OnMenuClosingCallback callback) { if (IsMenuShowing() || !CanShowMenu()) - return; + return false; // Close the running context menu if any before showing the clipboard history // menu. Because the clipboard history menu should not be nested. @@ -380,6 +381,7 @@ for (auto& observer : observers_) { observer.OnClipboardHistoryMenuShown(show_source); } + return true; } void ClipboardHistoryControllerImpl::GetHistoryValues(
diff --git a/ash/clipboard/clipboard_history_controller_impl.h b/ash/clipboard/clipboard_history_controller_impl.h index 264efd3..934fc154 100644 --- a/ash/clipboard/clipboard_history_controller_impl.h +++ b/ash/clipboard/clipboard_history_controller_impl.h
@@ -91,11 +91,11 @@ // ClipboardHistoryController: void AddObserver(ClipboardHistoryController::Observer* observer) override; void RemoveObserver(ClipboardHistoryController::Observer* observer) override; - void ShowMenu(const gfx::Rect& anchor_rect, + bool ShowMenu(const gfx::Rect& anchor_rect, ui::MenuSourceType source_type, crosapi::mojom::ClipboardHistoryControllerShowSource show_source) override; - void ShowMenu( + bool ShowMenu( const gfx::Rect& anchor_rect, ui::MenuSourceType source_type, crosapi::mojom::ClipboardHistoryControllerShowSource show_source,
diff --git a/ash/clipboard/clipboard_history_controller_unittest.cc b/ash/clipboard/clipboard_history_controller_unittest.cc index bf14d50c..b988dbf 100644 --- a/ash/clipboard/clipboard_history_controller_unittest.cc +++ b/ash/clipboard/clipboard_history_controller_unittest.cc
@@ -235,6 +235,47 @@ "Ash.ClipboardHistory.ContextMenu.UserJourneyTime", 2); } +// Tests that `ShowMenu()` returns whether the menu was shown successfully. +TEST_F(ClipboardHistoryControllerTest, ShowMenuReturnsSuccess) { + // Try to show the menu without populating the clipboard. The menu should not + // show. + EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu( + gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, + crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown)); + EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing()); + + // Copy something to enable the clipboard history menu. + WriteTextToClipboardAndConfirm(u"test"); + + // Try to show the menu with the screen locked. The menu should not show. + auto* session_controller = Shell::Get()->session_controller(); + session_controller->LockScreen(); + GetSessionControllerClient()->FlushForTest(); + EXPECT_TRUE(session_controller->IsScreenLocked()); + + EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu( + gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, + crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown)); + EXPECT_FALSE(GetClipboardHistoryController()->IsMenuShowing()); + + session_controller->HideLockScreen(); + GetSessionControllerClient()->FlushForTest(); + EXPECT_FALSE(session_controller->IsScreenLocked()); + + // Show the menu. + EXPECT_TRUE(GetClipboardHistoryController()->ShowMenu( + gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, + crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown)); + EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing()); + + // Try to show the menu again without closing the active menu. The menu should + // still be showing, but this attempt should fail. + EXPECT_FALSE(GetClipboardHistoryController()->ShowMenu( + gfx::Rect(), ui::MenuSourceType::MENU_SOURCE_NONE, + crosapi::mojom::ClipboardHistoryControllerShowSource::kUnknown)); + EXPECT_TRUE(GetClipboardHistoryController()->IsMenuShowing()); +} + // Tests that the client-provided `OnMenuClosingCallback` runs before the menu // closes. TEST_F(ClipboardHistoryControllerTest, OnMenuClosingCallback) {
diff --git a/ash/components/arc/test/fake_file_system_instance.h b/ash/components/arc/test/fake_file_system_instance.h index 60d42a5..3010f73 100644 --- a/ash/components/arc/test/fake_file_system_instance.h +++ b/ash/components/arc/test/fake_file_system_instance.h
@@ -371,7 +371,7 @@ void OpenUrlsWithPermissionAndWindowInfo( mojom::OpenUrlsRequestPtr request, mojom::WindowInfoPtr window_info, - DEPRECATED_OpenUrlsWithPermissionCallback callback) override; + OpenUrlsWithPermissionAndWindowInfoCallback callback) override; private: // A pair of an authority and a document ID which identifies the location
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 696b454..13257430 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -929,7 +929,7 @@ // Enable inline sync status in Files app. BASE_FEATURE(kFilesInlineSyncStatus, "FilesInlineSyncStatus", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables V2 of search functionality in files. BASE_FEATURE(kFilesSearchV2,
diff --git a/ash/metrics/login_unlock_throughput_recorder.cc b/ash/metrics/login_unlock_throughput_recorder.cc index fe0de18..aced9ce 100644 --- a/ash/metrics/login_unlock_throughput_recorder.cc +++ b/ash/metrics/login_unlock_throughput_recorder.cc
@@ -19,6 +19,7 @@ #include "base/functional/bind.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/histogram_macros_local.h" #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" @@ -541,6 +542,7 @@ REPORT_LOGIN_THROUGHPUT_EVENT("Ash.UnlockAnimation.Jank.TabletMode"); REPORT_LOGIN_THROUGHPUT_EVENT("Ash.UnlockAnimation.Duration.ClamshellMode"); REPORT_LOGIN_THROUGHPUT_EVENT("Ash.UnlockAnimation.Duration.TabletMode"); + REPORT_LOGIN_THROUGHPUT_EVENT("ArcUiAvailable"); if (!reported) { constexpr char kFailedEvent[] = "FailedToReportEvent"; TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP0( @@ -568,6 +570,13 @@ } } +void LoginUnlockThroughputRecorder::ArcUiAvailableAfterLogin() { + AddLoginTimeMarker("ArcUiAvailable"); + const base::TimeDelta duration = + base::TimeTicks::Now() - primary_user_logged_in_; + LOCAL_HISTOGRAM_TIMES("Ash.Tast.ArcUiAvailableAfterLogin.Duration", duration); +} + void LoginUnlockThroughputRecorder::MaybeReportLoginFinished() { if (login_finished_reported_) { return;
diff --git a/ash/metrics/login_unlock_throughput_recorder.h b/ash/metrics/login_unlock_throughput_recorder.h index ef26110b..c71132f1 100644 --- a/ash/metrics/login_unlock_throughput_recorder.h +++ b/ash/metrics/login_unlock_throughput_recorder.h
@@ -94,6 +94,9 @@ // This flag signals that all expected browser windows are already scheduled. void RestoreDataLoaded(); + // Records that ARC has finished booting. + void ArcUiAvailableAfterLogin(); + private: class TimeMarker { public:
diff --git a/ash/public/cpp/clipboard_history_controller.h b/ash/public/cpp/clipboard_history_controller.h index e204f65a..8669345 100644 --- a/ash/public/cpp/clipboard_history_controller.h +++ b/ash/public/cpp/clipboard_history_controller.h
@@ -51,17 +51,16 @@ // Returns whether the clipboard history menu is able to show. virtual bool CanShowMenu() const = 0; - // Shows the clipboard history menu triggered by `source_type` at the - // position specified by `anchor_rect`, provided the menu can currently be + // Attempts to show the clipboard history menu triggered by `source_type` at + // the position specified by `anchor_rect`. Returns whether the menu was // shown. `show_source` indicates how the user opened the menu. As long as the // menu is shown, `callback` runs just before the menu closes to indicate // whether a clipboard history paste is imminent. - // TODO(b/267694199): Make these functions return whether the menu was shown. - virtual void ShowMenu( + virtual bool ShowMenu( const gfx::Rect& anchor_rect, ui::MenuSourceType source_type, crosapi::mojom::ClipboardHistoryControllerShowSource show_source) = 0; - virtual void ShowMenu( + virtual bool ShowMenu( const gfx::Rect& anchor_rect, ui::MenuSourceType source_type, crosapi::mojom::ClipboardHistoryControllerShowSource show_source,
diff --git a/ash/shell.h b/ash/shell.h index a465f060..d53c57d65 100644 --- a/ash/shell.h +++ b/ash/shell.h
@@ -14,6 +14,7 @@ #include "ash/constants/ash_features.h" #include "ash/game_dashboard/game_dashboard_controller.h" #include "ash/in_session_auth/in_session_auth_dialog_controller_impl.h" +#include "ash/metrics/login_unlock_throughput_recorder.h" #include "ash/public/cpp/session/session_observer.h" #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/system_sounds_delegate.h"
diff --git a/ash/style/color_palette_controller.cc b/ash/style/color_palette_controller.cc index 9ffa154..252fcba5 100644 --- a/ash/style/color_palette_controller.cc +++ b/ash/style/color_palette_controller.cc
@@ -7,32 +7,74 @@ #include <memory> #include "ash/constants/ash_pref_names.h" +#include "ash/public/cpp/style/color_mode_observer.h" +#include "ash/public/cpp/style/dark_light_mode_controller.h" +#include "ash/public/cpp/wallpaper/wallpaper_controller.h" +#include "ash/public/cpp/wallpaper/wallpaper_controller_observer.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" +#include "ash/style/color_util.h" +#include "ash/style/dark_light_mode_controller_impl.h" +#include "ash/wallpaper/wallpaper_controller_impl.h" #include "base/logging.h" #include "base/observer_list.h" +#include "base/scoped_observation.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_runner.h" #include "base/time/time.h" +#include "chromeos/constants/chromeos_features.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "ui/color/color_provider_manager.h" +#include "ui/gfx/color_palette.h" namespace ash { namespace { +class ColorPaletteControllerImpl; + +using ColorMode = ui::ColorProviderManager::ColorMode; + +// Returns the wallpaper colors for pre-Jelly. Called for both dark and light. +SkColor GetWallpaperColor(bool is_dark_mode_enabled) { + const SkColor default_color = + is_dark_mode_enabled ? gfx::kGoogleGrey900 : SK_ColorWHITE; + return ColorUtil::GetBackgroundThemedColor(default_color, + is_dark_mode_enabled); +} + PrefService* GetUserPrefService(const AccountId& account_id) { DCHECK(account_id.is_valid()); return Shell::Get()->session_controller()->GetUserPrefServiceForUser( account_id); } +// Returns the currently active user session (at index 0). +const UserSession* GetActiveUserSession() { + return Shell::Get()->session_controller()->GetUserSession(/*index=*/0); +} + +const AccountId& AccountFromSession(const UserSession* session) { + CHECK(session); + return session->user_info.account_id; +} + // TODO(b/258719005): Finish implementation with code that works/uses libmonet. -class ColorPaletteControllerImpl : public ColorPaletteController { +class ColorPaletteControllerImpl : public ColorPaletteController, + public WallpaperControllerObserver, + public ColorModeObserver { public: - ColorPaletteControllerImpl() = default; + ColorPaletteControllerImpl( + DarkLightModeController* dark_light_mode_controller, + WallpaperControllerImpl* wallpaper_controller) + : wallpaper_controller_(wallpaper_controller), + dark_light_mode_controller_(dark_light_mode_controller) { + wallpaper_observation_.Observe(wallpaper_controller); + wallpaper_color_[ColorMode::kDark] = SK_ColorTRANSPARENT; + wallpaper_color_[ColorMode::kLight] = SK_ColorTRANSPARENT; + } ~ColorPaletteControllerImpl() override = default; @@ -57,6 +99,7 @@ static_cast<int>(scheme)); // TODO(b/258719005): Call this after the native theme change has been // applied. + NotifyObservers(account_id); base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, std::move(on_complete), base::Milliseconds(100)); } @@ -77,25 +120,23 @@ pref_service->SetUint64(prefs::kDynamicColorSeedColor, seed_color); // TODO(b/258719005): Call this after the native theme change has been // applied. + NotifyObservers(account_id); base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, std::move(on_complete), base::Milliseconds(100)); } ColorPaletteSeed GetColorPaletteSeed( const AccountId& account_id) const override { - PrefService* pref_service = GetUserPrefService(account_id); - if (!pref_service) { - DVLOG(1) << "No user pref service available. Returning default color " - "palette seed."; - return {.seed_color = SK_ColorBLUE, - .scheme = ColorScheme::kTonalSpot, - .color_mode = ui::ColorProviderManager::ColorMode::kLight}; - } - SkColor color = static_cast<SkColor>( - pref_service->GetUint64(prefs::kDynamicColorSeedColor)); - return {.seed_color = color, - .scheme = GetColorScheme(account_id), - .color_mode = ui::ColorProviderManager::ColorMode::kLight}; + ColorPaletteSeed seed; + seed.color_mode = dark_light_mode_controller_->IsDarkModeEnabled() + ? ui::ColorProviderManager::ColorMode::kDark + : ui::ColorProviderManager::ColorMode::kLight; + seed.seed_color = UsesWallpaperSeedColor(account_id) + ? wallpaper_color_.at(seed.color_mode) + : GetStaticSeedColor(account_id); + seed.scheme = GetColorScheme(account_id); + + return seed; } bool UsesWallpaperSeedColor(const AccountId& account_id) const override { @@ -122,7 +163,7 @@ return absl::nullopt; } if (GetColorScheme(account_id) == ColorScheme::kStatic) { - return pref_service->GetUint64(prefs::kDynamicColorSeedColor); + return GetStaticSeedColor(account_id); } return absl::nullopt; @@ -140,8 +181,52 @@ base::Milliseconds(20)); } + // WallpaperControllerObserver overrides: + void OnWallpaperColorsChanged() override { + if (!chromeos::features::IsJellyEnabled()) { + SkColor dark_color = GetWallpaperColor(true); + SkColor light_color = GetWallpaperColor(false); + SetWallpaperColor(dark_color, light_color); + return; + } + + SkColor wallpaper_color = + wallpaper_controller_->calculated_colors()->celebi_color; + // When Jelly is enabled, light/dark changes are handled in palette + // generation. So it's the same color. + SetWallpaperColor(wallpaper_color, wallpaper_color); + } + + // ColorModeObserver overrides: + void OnColorModeChanged(bool) override { + // Change colors and notify. + auto* session = GetActiveUserSession(); + if (session) { + NotifyObservers(AccountFromSession(session)); + } + } + private: - base::ObserverList<ColorPaletteController::Observer> observers_; + void SetWallpaperColor(SkColor dark_color, SkColor light_color) { + wallpaper_color_[ColorMode::kDark] = dark_color; + wallpaper_color_[ColorMode::kLight] = light_color; + // TODO(b/258719005): Update Native Theme + auto* session = GetActiveUserSession(); + if (session) { + NotifyObservers(AccountFromSession(session)); + } + } + + SkColor GetStaticSeedColor(const AccountId& account_id) const { + PrefService* pref_service = GetUserPrefService(account_id); + if (!pref_service) { + DVLOG(1) << "No user pref service available. Returning default color " + "palette seed."; + return SK_ColorBLUE; + } + return static_cast<SkColor>( + pref_service->GetUint64(prefs::kDynamicColorSeedColor)); + } SampleColorScheme GenerateSampleColorScheme(ColorScheme scheme) const { // TODO(b/258719005): Return correct and different schemes for each @@ -154,13 +239,42 @@ .secondary = SK_ColorGREEN, .tertiary = SK_ColorBLUE}; } + + void NotifyObservers(const AccountId& account_id) { + ColorPaletteSeed seed = GetColorPaletteSeed(account_id); + for (auto& observer : observers_) { + observer.OnColorPaletteChanging(seed); + } + } + + base::flat_map<ui::ColorProviderManager::ColorMode, SkColor> wallpaper_color_; + + base::ScopedObservation<WallpaperController, WallpaperControllerObserver> + wallpaper_observation_{this}; + + base::raw_ptr<WallpaperControllerImpl> wallpaper_controller_; // unowned + + base::raw_ptr<DarkLightModeController> + dark_light_mode_controller_; // unowned + + base::ObserverList<ColorPaletteController::Observer> observers_; }; } // namespace // static std::unique_ptr<ColorPaletteController> ColorPaletteController::Create() { - return std::make_unique<ColorPaletteControllerImpl>(); + Shell* shell = Shell::Get(); + return Create(shell->dark_light_mode_controller(), + shell->wallpaper_controller()); +} + +// static +std::unique_ptr<ColorPaletteController> ColorPaletteController::Create( + DarkLightModeController* dark_light_mode_controller, + WallpaperControllerImpl* wallpaper_controller) { + return std::make_unique<ColorPaletteControllerImpl>( + dark_light_mode_controller, wallpaper_controller); } // static
diff --git a/ash/style/color_palette_controller.h b/ash/style/color_palette_controller.h index 59b7a75..2370b57 100644 --- a/ash/style/color_palette_controller.h +++ b/ash/style/color_palette_controller.h
@@ -18,6 +18,9 @@ namespace ash { +class DarkLightModeController; +class WallpaperControllerImpl; + // Types of ColorSchemes. For a given seed color, each ColorScheme will generate // a different color palette/set of ref colors. enum class ASH_EXPORT ColorScheme { @@ -69,7 +72,12 @@ virtual void OnColorPaletteChanging(const ColorPaletteSeed& seed) = 0; }; - static ASH_EXPORT std::unique_ptr<ColorPaletteController> Create(); + // Temporary factory for migration. DO NOT USE. + static std::unique_ptr<ColorPaletteController> Create(); + + static std::unique_ptr<ColorPaletteController> Create( + DarkLightModeController* dark_light_mode_controller, + WallpaperControllerImpl* wallpaper_controller); ColorPaletteController() = default;
diff --git a/ash/style/color_palette_controller_unittest.cc b/ash/style/color_palette_controller_unittest.cc index 5ab1df13..7bd5ae7 100644 --- a/ash/style/color_palette_controller_unittest.cc +++ b/ash/style/color_palette_controller_unittest.cc
@@ -4,7 +4,10 @@ #include "ash/style/color_palette_controller.h" +#include "ash/shell.h" +#include "ash/style/dark_light_mode_controller_impl.h" #include "ash/test/ash_test_base.h" +#include "ash/wallpaper/wallpaper_controller_impl.h" #include "base/functional/callback_helpers.h" #include "third_party/skia/include/core/SkColor.h" @@ -18,49 +21,65 @@ } // namespace class ColorPaletteControllerTest : public NoSessionAshTestBase { + public: void SetUp() override { NoSessionAshTestBase::SetUp(); GetSessionControllerClient()->Reset(); GetSessionControllerClient()->AddUserSession(kAccountId, kUser); - color_palette_controller = ColorPaletteController::Create(); + color_palette_controller_ = ColorPaletteController::Create( + Shell::Get()->dark_light_mode_controller(), + Shell::Get()->wallpaper_controller()); } - protected: - std::unique_ptr<ColorPaletteController> color_palette_controller; + void TearDown() override { + // Must release the controller before Shell is destructed. + color_palette_controller_.reset(); + + NoSessionAshTestBase::TearDown(); + } + + ColorPaletteController* color_palette_controller() { + return color_palette_controller_.get(); + } + + private: + std::unique_ptr<ColorPaletteController> color_palette_controller_; }; TEST_F(ColorPaletteControllerTest, ExpectedEmptyValues) { EXPECT_EQ(ColorScheme::kTonalSpot, - color_palette_controller->GetColorScheme(kAccountId)); + color_palette_controller()->GetColorScheme(kAccountId)); EXPECT_EQ(absl::nullopt, - color_palette_controller->GetStaticColor(kAccountId)); + color_palette_controller()->GetStaticColor(kAccountId)); } TEST_F(ColorPaletteControllerTest, SetColorScheme) { ColorScheme color_scheme = ColorScheme::kExpressive; - color_palette_controller->SetColorScheme(color_scheme, kAccountId, - base::DoNothing()); + color_palette_controller()->SetColorScheme(color_scheme, kAccountId, + base::DoNothing()); - EXPECT_EQ(color_scheme, color_palette_controller->GetColorScheme(kAccountId)); + EXPECT_EQ(color_scheme, + color_palette_controller()->GetColorScheme(kAccountId)); EXPECT_EQ(absl::nullopt, - color_palette_controller->GetStaticColor(kAccountId)); + color_palette_controller()->GetStaticColor(kAccountId)); auto color_palette_seed = - color_palette_controller->GetColorPaletteSeed(kAccountId); + color_palette_controller()->GetColorPaletteSeed(kAccountId); EXPECT_EQ(color_scheme, color_palette_seed.scheme); } TEST_F(ColorPaletteControllerTest, SetStaticColor) { SkColor static_color = SK_ColorGRAY; - color_palette_controller->SetStaticColor(static_color, kAccountId, - base::DoNothing()); + color_palette_controller()->SetStaticColor(static_color, kAccountId, + base::DoNothing()); - EXPECT_EQ(static_color, color_palette_controller->GetStaticColor(kAccountId)); + EXPECT_EQ(static_color, + color_palette_controller()->GetStaticColor(kAccountId)); EXPECT_EQ(ColorScheme::kStatic, - color_palette_controller->GetColorScheme(kAccountId)); + color_palette_controller()->GetColorScheme(kAccountId)); auto color_palette_seed = - color_palette_controller->GetColorPaletteSeed(kAccountId); + color_palette_controller()->GetColorPaletteSeed(kAccountId); EXPECT_EQ(ColorScheme::kStatic, color_palette_seed.scheme); EXPECT_EQ(static_color, color_palette_seed.seed_color); }
diff --git a/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc b/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc index 072c08e..9f974b3 100644 --- a/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc +++ b/ash/webui/eche_app_ui/eche_recent_app_click_handler_unittest.cc
@@ -68,10 +68,10 @@ void TearDown() override { apps_launch_info_provider_.reset(); - connection_status_handler_.reset(); launch_app_helper_.reset(); handler_.reset(); stream_status_change_handler_.reset(); + connection_status_handler_.reset(); } void FakeLaunchEcheAppFunction(
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider_unittest.cc b/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider_unittest.cc index 24d90be2..35134b1 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider_unittest.cc +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider_unittest.cc
@@ -333,6 +333,9 @@ fake_keyboard_manager_ = std::make_unique<FakeDeviceManager>(); provider_->ignore_layouts_for_testing_ = true; base::RunLoop().RunUntilIdle(); + // After adding a fake keyboard, clear the observer call count. + observer_.clear_num_times_notified(); + EXPECT_EQ(0, observer_.num_times_notified()); } void TearDown() override { @@ -434,13 +437,7 @@ base::RunLoop().RunUntilIdle(); } -// TODO(crbug.com/1426992): Fix flakiness and re-enable. -#if BUILDFLAG(IS_CHROMEOS) -#define MAYBE_InitialAccelInitCalls DISABLED_InitialAccelInitCalls -#else -#define MAYBE_InitialAccelInitCalls InitialAccelInitCalls -#endif -TEST_F(AcceleratorConfigurationProviderTest, MAYBE_InitialAccelInitCalls) { +TEST_F(AcceleratorConfigurationProviderTest, InitialAccelInitCalls) { FakeAcceleratorsUpdatedMojoObserver mojo_observer; SetUpObserver(&mojo_observer); EXPECT_EQ(0, mojo_observer.num_times_notified());
diff --git a/base/feature_list.cc b/base/feature_list.cc index a689df41..9698a298 100644 --- a/base/feature_list.cc +++ b/base/feature_list.cc
@@ -93,10 +93,7 @@ // TODO(crbug.com/1383852): When we believe that all early accesses have // been fixed, remove this base::debug::DumpWithoutCrashing() and change the // above DCHECK to a CHECK. - - // The following line is commented to reduce the crash volume while a fix - // for crbug.com/1392145 is prepared. - // base::debug::DumpWithoutCrashing(); + base::debug::DumpWithoutCrashing(); #endif // !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID) && // !BUILDFLAG(IS_CHROMEOS) }
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index 074417313..51c0d0f 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -12.20230323.1.1 +12.20230323.3.1
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 9a37bd1..fd64cd5 100644 --- a/buildtools/deps_revisions.gni +++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@ declare_args() { # Used to cause full rebuilds on libc++ rolls. This should be kept in sync # with the libcxx_revision vars in //DEPS. - libcxx_revision = "e44019bfac2b2d3ebe1618628884f85c8600e322" + libcxx_revision = "5622befaf8a9d539bc94c9f1341b8e76065334db" }
diff --git a/cc/input/input_handler.cc b/cc/input/input_handler.cc index c1db2de89..51b88ed 100644 --- a/cc/input/input_handler.cc +++ b/cc/input/input_handler.cc
@@ -164,8 +164,6 @@ // freshly created scroller hasn't yet been committed or a // scroller-destroying commit beats the hit test back to the compositor // thread. However, these cases shouldn't be user perceptible. - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNoScrollingLayer; scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; return scroll_status; } @@ -185,8 +183,6 @@ // drop the scroll as continuing could cause us to infinitely bounce // back and forth between here and hit testing on the main thread. NOTREACHED(); - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNoScrollingLayer; scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; return scroll_status; } @@ -261,11 +257,6 @@ scroll_status.thread = InputHandler::ScrollThread::SCROLL_ON_MAIN_THREAD; return scroll_status; } else if (!scrolling_node) { - // TODO(crbug.com/1155663): Make sure to set main_thread_scrolling_reasons - // only when ScrollStatus.thread is set to - // InputHander::ScrollThread::SCROLL_ON_MAIN_THREAD - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNoScrollingLayer; if (compositor_delegate_->GetSettings().is_for_embedded_frame) { // OOPIFs or fenced frames never have a viewport scroll node so if we // can't scroll we need to be bubble up to the parent frame. This happens @@ -323,8 +314,6 @@ if (!OuterViewportScrollNode()) { InputHandler::ScrollStatus scroll_status; scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNoScrollingLayer; return scroll_status; } @@ -1302,16 +1291,12 @@ if (!screen_space_transform.IsInvertible()) { TRACE_EVENT0("cc", "LayerImpl::TryScroll: Ignored NonInvertibleTransform"); scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNonInvertibleTransform; return scroll_status; } if (!scroll_node->scrollable) { TRACE_EVENT0("cc", "LayerImpl::tryScroll: Ignored not scrollable"); scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNotScrollable; return scroll_status; } @@ -1341,8 +1326,6 @@ "LayerImpl::tryScroll: Ignored. Technically scrollable," " but has no affordance in either direction."); scroll_status.thread = InputHandler::ScrollThread::SCROLL_IGNORED; - scroll_status.main_thread_scrolling_reasons = - MainThreadScrollingReason::kNotScrollable; return scroll_status; }
diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index 4b47f75..ddc65a8 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h
@@ -218,9 +218,7 @@ main_thread_scrolling_reasons(main_thread_scrolling_reasons), needs_main_thread_hit_test(needs_main_thread_hit_test) {} ScrollThread thread = ScrollThread::SCROLL_ON_IMPL_THREAD; - // TODO(crbug.com/1155663): Make sure to set main_thread_scrolling_reasons - // only when ScrollStatus.thread is set to - // InputHander::ScrollThread::SCROLL_ON_MAIN_THREAD + // This should be set to nonzero iff `thread` is SCROLL_ON_MAIN_THREAD. uint32_t main_thread_scrolling_reasons = MainThreadScrollingReason::kNotScrollingOnMain; // TODO(crbug.com/1155758): This is a temporary workaround for GuestViews
diff --git a/cc/input/main_thread_scrolling_reason.cc b/cc/input/main_thread_scrolling_reason.cc index e917018..5b351f8 100644 --- a/cc/input/main_thread_scrolling_reason.cc +++ b/cc/input/main_thread_scrolling_reason.cc
@@ -48,10 +48,6 @@ traced_value.AppendString("Failed hit test"); if (reasons & kNoScrollingLayer) traced_value.AppendString("No scrolling layer"); - if (reasons & kNotScrollable) - traced_value.AppendString("Not scrollable"); - if (reasons & kNonInvertibleTransform) - traced_value.AppendString("Non-invertible transform"); if (reasons & kWheelEventHandlerRegion) traced_value.AppendString("Wheel event handler region"); if (reasons & kTouchEventHandlerRegion)
diff --git a/cc/input/main_thread_scrolling_reason.h b/cc/input/main_thread_scrolling_reason.h index 132c9dc..7bb2f73 100644 --- a/cc/input/main_thread_scrolling_reason.h +++ b/cc/input/main_thread_scrolling_reason.h
@@ -59,8 +59,6 @@ kNonFastScrollableRegion = 1 << 8, kFailedHitTest = 1 << 9, kNoScrollingLayer = 1 << 10, - kNotScrollable = 1 << 11, - kNonInvertibleTransform = 1 << 12, kWheelEventHandlerRegion = 1 << 13, kTouchEventHandlerRegion = 1 << 14, @@ -85,8 +83,7 @@ static bool CompositorCanSetScrollReasons(uint32_t reasons) { constexpr uint32_t reasons_set_by_compositor = kNonFastScrollableRegion | kFailedHitTest | kNoScrollingLayer | - kNotScrollable | kNonInvertibleTransform | kWheelEventHandlerRegion | - kTouchEventHandlerRegion; + kWheelEventHandlerRegion | kTouchEventHandlerRegion; return (reasons & reasons_set_by_compositor) == reasons; }
diff --git a/cc/input/main_thread_scrolling_reason_unittest.cc b/cc/input/main_thread_scrolling_reason_unittest.cc index 83fbc30..522e8490 100644 --- a/cc/input/main_thread_scrolling_reason_unittest.cc +++ b/cc/input/main_thread_scrolling_reason_unittest.cc
@@ -21,8 +21,6 @@ "Non fast scrollable region, " "Failed hit test, " "No scrolling layer, " - "Not scrollable, " - "Non-invertible transform, " "Wheel event handler region, " "Touch event handler region", MainThreadScrollingReason::AsText(0xffffffffu));
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index c38b1195..5f394ac 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -1256,7 +1256,7 @@ .get(), ui::ScrollInputType::kWheel); EXPECT_EQ(ScrollThread::SCROLL_IGNORED, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer, + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); status = GetInputHandler().RootScrollBegin( @@ -1265,7 +1265,7 @@ .get(), ui::ScrollInputType::kWheel); EXPECT_EQ(ScrollThread::SCROLL_IGNORED, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer, + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); } @@ -1490,7 +1490,7 @@ .get(), ui::ScrollInputType::kWheel); EXPECT_EQ(ScrollThread::SCROLL_IGNORED, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer, + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); } @@ -6900,7 +6900,7 @@ .get(), ui::ScrollInputType::kWheel); EXPECT_EQ(ScrollThread::SCROLL_IGNORED, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer, + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); EXPECT_FALSE(did_request_redraw_); EXPECT_FALSE(did_request_commit_); @@ -18083,7 +18083,7 @@ ScrollStatus status = ScrollBegin(gfx::Vector2d(0, 10)); status = ContinuedScrollBegin(kUnknown); EXPECT_EQ(ScrollThread::SCROLL_IGNORED, status.thread); - EXPECT_EQ(MainThreadScrollingReason::kNoScrollingLayer, + EXPECT_EQ(MainThreadScrollingReason::kNotScrollingOnMain, status.main_thread_scrolling_reasons); } }
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 5f88f43..fa35cf79 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -209,6 +209,7 @@ ":app_hooks_java", "//chrome/browser/accessibility/hierarchysnapshotter/android:delegate_public_impl_java", "//chrome/browser/feed/android:hooks_public_impl_java", + "//chrome/browser/feedback/android:delegate_public_impl_java", "//chrome/browser/lens:delegate_public_impl_java", "//chrome/browser/locale:delegate_public_impl_java", "//chrome/browser/partnerbookmarks:delegate_public_impl_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index eb251ed..b43431f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -19,7 +19,6 @@ import android.os.Build; import android.os.Bundle; import android.os.CancellationSignal; -import android.os.Handler; import android.os.SystemClock; import android.util.Pair; import android.util.TypedValue; @@ -1663,19 +1662,9 @@ // focus dependency is because doing it earlier can cause drawing bugs, e.g. crbug/673831. if (!mNativeInitialized || !hasWindowFocus()) return; - if (!DeviceFormFactor.isNonMultiDisplayContextOnTablet(this)) { - changeBackgroundColorForResizing(); - } else { - // Post the background update call as a separate task, as doing it synchronously - // here can cause redrawing glitches. See crbug.com/686662 and crbug.com/1260127 for - // example problems. - Handler handler = new Handler(); - handler.post(() -> { - // The window background color is used as the resizing background color in - // Android N+ multi-window mode. See crbug.com/602366. - changeBackgroundColorForResizing(); - }); - } + // The window background color is used as the resizing background color in Android N+ + // multi-window mode. See crbug.com/602366. + changeBackgroundColorForResizing(); mRemoveWindowBackgroundDone = true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java index b5edfbfc..a781fc59 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorView.java
@@ -610,7 +610,7 @@ } mHaveSwappedFramesSinceSurfaceCreated = true; - mRenderHost.didSwapBuffers(swappedCurrentSize); + mRenderHost.didSwapBuffers(swappedCurrentSize, mFramesUntilHideBackground); updateNeedsDidSwapBuffersCallback(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java index 0d6e76e..755cdef2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java
@@ -547,8 +547,6 @@ if (controlContainerVG != null) { controlContainerVG.setBackgroundResource(0); } - - mSetBackgroundRunnable = null; }; } @@ -1220,12 +1218,7 @@ public void didSwapFrame(int pendingFrameCount) { TraceEvent.instant("didSwapFrame"); - if (mHasDrawnOnce && mSetBackgroundRunnable != null) { - post(mSetBackgroundRunnable); - } - mHasDrawnOnce = true; - mPendingFrameCount = pendingFrameCount; if (!mSkipInvalidation || pendingFrameCount == 0) flushInvalidation(); @@ -1237,7 +1230,12 @@ } @Override - public void didSwapBuffers(boolean swappedCurrentSize) { + public void didSwapBuffers(boolean swappedCurrentSize, int framesUntilHideBackground) { + if (mSetBackgroundRunnable != null && mHasDrawnOnce && framesUntilHideBackground == 0) { + post(mSetBackgroundRunnable); + mSetBackgroundRunnable = null; + } + for (Runnable runnable : mDidSwapBuffersCallbacks) { runnable.run(); } @@ -1765,7 +1763,7 @@ // Should be called any time inputs used to compute `needsSwapCallback` changes. private void updateNeedsSwapBuffersCallback() { - boolean needsSwapCallback = !mOnCompositorLayoutCallbacks.isEmpty() + boolean needsSwapCallback = !mHasDrawnOnce || !mOnCompositorLayoutCallbacks.isEmpty() || !mDidSwapFrameCallbacks.isEmpty() || !mDidSwapBuffersCallbacks.isEmpty(); mCompositorView.setRenderHostNeedsDidSwapBuffersCallback(needsSwapCallback); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutRenderHost.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutRenderHost.java index 39dbf2a..a981242 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutRenderHost.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutRenderHost.java
@@ -31,8 +31,10 @@ /** * Indicates that the compositor swapped buffers. * @param swappedCurrentSize Whether the swapped buffer size is the same as the current one. + * @param framesUntilHideBackground The number of buffer swaps needed until the incoming surface + * has a frame ready. Zero if no incoming surface or if the incoming surface is ready. */ - default void didSwapBuffers(boolean swappedCurrentSize) {} + default void didSwapBuffers(boolean swappedCurrentSize, int framesUntilHideBackground) {} /** * Indicates that the rendering surface has just been created.
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index be5b16c..d374e00 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -2708,13 +2708,13 @@ <message name="IDS_SETTINGS_MOUSE_TITLE" desc="In Device Settings, the title of the mouse settings subpage."> Mouse </message> - <message name="IDS_SETTINGS_BUILT_IN_POINTING_STICK_NAME" translateable="false" desc="In Device Settings, the name of the built-in/internal pointing stick device within the settings app."> + <message name="IDS_SETTINGS_BUILT_IN_POINTING_STICK_NAME" desc="In Device Settings, the name of the built-in/internal pointing stick device within the settings app."> Built-in TrackPoint </message> <message name="IDS_SETTINGS_POINTING_STICK_TITLE" desc="In Device Settings, the title of the pointing stick settings subpage. In most cases this will just be 'TrackPoint', the brand name of the pointing sticks used on Chromebooks."> TrackPoint </message> - <message name="IDS_SETTINGS_BUILT_IN_TOUCHPAD_NAME" translateable="false" desc="In Device Settings, the name of the built-in/internal touchpad device within the settings app."> + <message name="IDS_SETTINGS_BUILT_IN_TOUCHPAD_NAME" desc="In Device Settings, the name of the built-in/internal touchpad device within the settings app."> Built-in Touchpad </message> <message name="IDS_SETTINGS_TOUCHPAD_TITLE" desc="In Device Settings, the title of the touchpad settings subpage."> @@ -4641,36 +4641,36 @@ </message> <!-- Per Device Keyboard page (OS settings) --> - <message name="IDS_SETTINGS_BUILT_IN_KEYBOARD_NAME" translateable="false" desc="In Device Settings, the name of the built-in/internal keyboard device within the settings app."> + <message name="IDS_SETTINGS_BUILT_IN_KEYBOARD_NAME" desc="In Device Settings, the name of the built-in/internal keyboard device within the settings app."> Built-in Keyboard </message> - <message name="IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_LABEL" translateable="false" desc="In per-device keyboard Settings, the label of the Remap Keyboard Keys row."> + <message name="IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_LABEL" desc="In per-device keyboard Settings, the label of the Remap Keyboard Keys row."> Remap keyboard keys </message> - <message name="IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_SUB_LABEL" translateable="false" desc="Sub-label with number of remapped keys for the Remap Keyboard Keys row."> + <message name="IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_SUB_LABEL" desc="Sub-label with number of remapped keys for the Remap Keyboard Keys row."> {COUNT, plural, =1 {1 remapped key} other {{COUNT} remapped keys}} </message> - <message name="IDS_SETTINGS_KEYBOARD_REMAP_KEYS_DESCRIPTION" translateable="false" desc="In Keyboard remap keys subpage, the description label above remapping keys to describe the actions user can perform."> + <message name="IDS_SETTINGS_KEYBOARD_REMAP_KEYS_DESCRIPTION" desc="In Keyboard remap keys subpage, the description label above remapping keys to describe the actions user can perform."> For each key listed below, choose the action you want it to perform </message> - <message name="IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS" translateable="false" desc="In Device Settings, the inverted checkbox label for interpreting the top-row keys as function keys instead."> + <message name="IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS" desc="In Device Settings, the inverted checkbox label for interpreting the top-row keys as function keys instead."> Convert F keys to ChromeOS top-row keys </message> - <message name="IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS_DESCRIPTION" translateable="false" desc="In Device Settings, the inverted label describing how to use the top-row keys' original actions when they are set to behave like function keys."> + <message name="IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS_DESCRIPTION" desc="In Device Settings, the inverted label describing how to use the top-row keys' original actions when they are set to behave like function keys."> Change the behavior of F keys to ChromeOS top-row actions </message> - <message name="IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES" translateable="false" desc="In Device Settings, the checkbox label to enable the meta key to switch the behavior of the top-row keys."> + <message name="IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES" desc="In Device Settings, the checkbox label to enable the meta key to switch the behavior of the top-row keys."> Enable System/Launcher key to switch the behavior of the top-row keys </message> - <message name="IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES_DESCRIPTION" translateable="false" desc="In Device Settings, the label describing how to use the meta key to switch the behavior of the top-row keys."> + <message name="IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES_DESCRIPTION" desc="In Device Settings, the label describing how to use the meta key to switch the behavior of the top-row keys."> Hold the key to switch between F keys and ChromeOS actions </message> - <message name="IDS_SETTINGS_KEYBOARD_REMAP_RESTORE_BUTTON_LABEL" translateable="false" desc="In Keyboard remap keys subpage, the restore defaults button label."> + <message name="IDS_SETTINGS_KEYBOARD_REMAP_RESTORE_BUTTON_LABEL" desc="In Keyboard remap keys subpage, the restore defaults button label."> Restore defaults </message> - <message name="IDS_SETTINGS_KEYBOARD_NO_KEYBOARDS_HELP_MESSAGE" translateable="false" desc="In Keyboard remap keys subpage, the message that notifies users that no keyboards are connected."> + <message name="IDS_SETTINGS_KEYBOARD_NO_KEYBOARDS_HELP_MESSAGE" desc="In Keyboard remap keys subpage, the message that notifies users that no keyboards are connected."> No keyboard detected </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_KEYBOARD_NAME.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_KEYBOARD_NAME.png.sha1 new file mode 100644 index 0000000..48c5bb9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_KEYBOARD_NAME.png.sha1
@@ -0,0 +1 @@ +be1a3286e36c52767417e91af37fbf6c9753b079 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_POINTING_STICK_NAME.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_POINTING_STICK_NAME.png.sha1 new file mode 100644 index 0000000..1266392 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_POINTING_STICK_NAME.png.sha1
@@ -0,0 +1 @@ +2b5bb06cba628deb00f9c6b2234a55ea6e83b065 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_TOUCHPAD_NAME.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_TOUCHPAD_NAME.png.sha1 new file mode 100644 index 0000000..f920383 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BUILT_IN_TOUCHPAD_NAME.png.sha1
@@ -0,0 +1 @@ +3a3f8f5128332d21f9ea90a87e571a13980aa180 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES.png.sha1 new file mode 100644 index 0000000..48c5bb9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES.png.sha1
@@ -0,0 +1 @@ +be1a3286e36c52767417e91af37fbf6c9753b079 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..48c5bb9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_BLOCK_META_FUNCTION_KEY_REWRITES_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +be1a3286e36c52767417e91af37fbf6c9753b079 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_NO_KEYBOARDS_HELP_MESSAGE.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_NO_KEYBOARDS_HELP_MESSAGE.png.sha1 new file mode 100644 index 0000000..7a0c4a5 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_NO_KEYBOARDS_HELP_MESSAGE.png.sha1
@@ -0,0 +1 @@ +52a7a581c63cca9059fea5d678a96f7c7c8e1530 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..0ee0fd2 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +17aa5d2dbef604163b7aee42c994defe9e1b4a64 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_LABEL.png.sha1 new file mode 100644 index 0000000..48c5bb9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_LABEL.png.sha1
@@ -0,0 +1 @@ +be1a3286e36c52767417e91af37fbf6c9753b079 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_SUB_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_SUB_LABEL.png.sha1 new file mode 100644 index 0000000..41ed761 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_KEYS_ROW_SUB_LABEL.png.sha1
@@ -0,0 +1 @@ +61b2cffc5c3c4ef8c0a15d739a7a89620d205272 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_RESTORE_BUTTON_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_RESTORE_BUTTON_LABEL.png.sha1 new file mode 100644 index 0000000..9dd935e --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_REMAP_RESTORE_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@ +3f5b7bf6daf0d7c3e2b890ac5173c26444bd07b6 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS.png.sha1 new file mode 100644 index 0000000..48c5bb9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS.png.sha1
@@ -0,0 +1 @@ +be1a3286e36c52767417e91af37fbf6c9753b079 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS_DESCRIPTION.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..48c5bb9 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_KEYBOARD_SEND_INVERTED_FUNCTION_KEYS_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +be1a3286e36c52767417e91af37fbf6c9753b079 \ No newline at end of file
diff --git a/chrome/app/settings_chromium_strings.grdp b/chrome/app/settings_chromium_strings.grdp index 850e42d6..f3d9170 100644 --- a/chrome/app/settings_chromium_strings.grdp +++ b/chrome/app/settings_chromium_strings.grdp
@@ -11,6 +11,12 @@ <message name="IDS_SETTINGS_ABOUT_PROGRAM" desc="Menu title for the About Chromium page."> About Chromium </message> + <message name="IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM" desc="Section title for the 'Get the most out of Chromium' page."> + Get the most ouf of Chromium + </message> + <message name="IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION" desc="Explanatory text for the link to the 'Get the most out of Chromium' page."> + This guide helps you understand your choices, so that Chromium works the way you want to + </message> <message name="IDS_SETTINGS_GET_HELP_USING_CHROME" desc="Text of the button which takes the user to the Chrome help page."> Get help with Chromium </message>
diff --git a/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM.png.sha1 b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM.png.sha1 new file mode 100644 index 0000000..9cdb789 --- /dev/null +++ b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM.png.sha1
@@ -0,0 +1 @@ +2eb8c42afba366b6db5ca4bf4043d5665f18cd74 \ No newline at end of file
diff --git a/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION.png.sha1 b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..9cdb789 --- /dev/null +++ b/chrome/app/settings_chromium_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +2eb8c42afba366b6db5ca4bf4043d5665f18cd74 \ No newline at end of file
diff --git a/chrome/app/settings_google_chrome_strings.grdp b/chrome/app/settings_google_chrome_strings.grdp index 2fd0bbe..242c3c7 100644 --- a/chrome/app/settings_google_chrome_strings.grdp +++ b/chrome/app/settings_google_chrome_strings.grdp
@@ -11,6 +11,12 @@ <message name="IDS_SETTINGS_ABOUT_PROGRAM" desc="Menu title for the About Chrome page."> About Chrome </message> + <message name="IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM" desc="Section title for the 'Get the most out of Chrome' page."> + Get the most ouf of Chrome + </message> + <message name="IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION" desc="Explanatory text for the link to the 'Get the most out of Chrome' page."> + This guide helps you understand your choices, so that Chrome works the way you want to + </message> <message name="IDS_SETTINGS_GET_HELP_USING_CHROME" desc="Text of the button which takes the user to the Chrome help page."> Get help with Chrome </message>
diff --git a/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM.png.sha1 b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM.png.sha1 new file mode 100644 index 0000000..5f2b1ea --- /dev/null +++ b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM.png.sha1
@@ -0,0 +1 @@ +8a9fef939fbfd6a1b92873abfd5ef41fb3d08203 \ No newline at end of file
diff --git a/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION.png.sha1 b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..5f2b1ea --- /dev/null +++ b/chrome/app/settings_google_chrome_strings_grdp/IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +8a9fef939fbfd6a1b92873abfd5ef41fb3d08203 \ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index df00e47b..9fcac612 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -91,6 +91,12 @@ <message name="IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_TITLE" desc="Name of the setting to enable Live Caption feature."> Live Caption </message> + <message name="IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_TITLE" desc="Name of the setting to enable Live Translate feature."> + Live Translate + </message> + <message name="IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_SUBTITLE" desc="Description text for Live Translate feature."> + Automatically translate captions to a target language. + </message> <if expr="chromeos_ash"> <message name="IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_SUBTITLE_ENGLISH_ONLY" desc="Description text for Live Caption feature. When audio or video is playing, the user will see captions on the screen. Only works in Chrome browser initially. Currently only works for English media."> Automatically creates captions for media in Chrome browser (currently available in English). Audio and captions are processed locally and never leave the device. @@ -1565,6 +1571,9 @@ <message name="IDS_SETTINGS_LANGUAGES_MANAGE_LANGUAGES_TITLE" desc="Name of the settings dialog which allows enabling additional languages."> Add languages </message> + <message name="IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED" desc="Placeholder for language list settings when no languages have been added, on the Manage Languages page."> + No languages added + </message> <if expr="not chromeos_ash"> <message name="IDS_SETTINGS_LANGUAGES_EXPAND_ACCESSIBILITY_LABEL" desc="Label for the button that toggles showing the language options. Only visible by screen reader software."> Show language options @@ -1590,9 +1599,6 @@ <message name="IDS_SETTINGS_LANGUAGES_MANAGED_DIALOG_BODY" desc="Body text for the dialog informing users that the language they tried modifying is managed."> Your administrator has set a default language which cannot be modified. </message> - <message name="IDS_SETTINGS_LANGUAGES_NO_LANGUAGES_ADDED" desc="Placeholder for language list settings when no languages have been added, on the Manage Languages page."> - No languages added - </message> <message name="IDS_SETTINGS_LANGUAGES_ADD_ARIA_LABEL" desc="Text read by screen readers when focusing on the checkbox for adding a language. This text is only announced by screen readers and is not visible in the UI."> Add <ph name="LANGUAGE_NAME">$1<ex>Swahili</ex></ph> </message>
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_SUBTITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_SUBTITLE.png.sha1 new file mode 100644 index 0000000..5d87310 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_SUBTITLE.png.sha1
@@ -0,0 +1 @@ +2c2b88390f54b609450727c0b629efda2472d3c5 \ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_TITLE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_TITLE.png.sha1 new file mode 100644 index 0000000..5d87310 --- /dev/null +++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_TITLE.png.sha1
@@ -0,0 +1 @@ +2c2b88390f54b609450727c0b629efda2472d3c5 \ No newline at end of file
diff --git a/chrome/app/shared_settings_strings.grdp b/chrome/app/shared_settings_strings.grdp index 2fa012f9..df803d31 100644 --- a/chrome/app/shared_settings_strings.grdp +++ b/chrome/app/shared_settings_strings.grdp
@@ -94,6 +94,15 @@ <message name="IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING" desc="Name of the default setting for the caption text."> Default </message> + <message name="IDS_SETTINGS_CAPTIONS_LANGUAGE" desc="Name of the language setting for the caption text."> + Caption language + </message> + <message name="IDS_SETTINGS_CAPTIONS_MANAGE_LANGUAGES_TITLE" desc="Name of the caption settings section for managing language packs."> + Manage languages + </message> + <message name="IDS_SETTINGS_CAPTIONS_LIVE_TRANSLATE_TARGET_LANGUAGE" desc="Description of the target language setting for the Live Translate feature."> + Translate to + </message> <!-- Nearby Share --> <message name="IDS_SETTINGS_NEARBY_SHARE_TITLE" desc="Name of the settings page for the Nearby Share feature">
diff --git a/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LANGUAGE.png.sha1 b/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LANGUAGE.png.sha1 new file mode 100644 index 0000000..5d87310 --- /dev/null +++ b/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LANGUAGE.png.sha1
@@ -0,0 +1 @@ +2c2b88390f54b609450727c0b629efda2472d3c5 \ No newline at end of file
diff --git a/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_TRANSLATE_TARGET_LANGUAGE.png.sha1 b/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_TRANSLATE_TARGET_LANGUAGE.png.sha1 new file mode 100644 index 0000000..5d87310 --- /dev/null +++ b/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_TRANSLATE_TARGET_LANGUAGE.png.sha1
@@ -0,0 +1 @@ +2c2b88390f54b609450727c0b629efda2472d3c5 \ No newline at end of file
diff --git a/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_MANAGE_LANGUAGES_TITLE.png.sha1 b/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_MANAGE_LANGUAGES_TITLE.png.sha1 new file mode 100644 index 0000000..5d87310 --- /dev/null +++ b/chrome/app/shared_settings_strings_grdp/IDS_SETTINGS_CAPTIONS_MANAGE_LANGUAGES_TITLE.png.sha1
@@ -0,0 +1 @@ +2c2b88390f54b609450727c0b629efda2472d3c5 \ No newline at end of file
diff --git a/chrome/app_shim/app_shim_controller.mm b/chrome/app_shim/app_shim_controller.mm index 0df1f4aa..51d9451a 100644 --- a/chrome/app_shim/app_shim_controller.mm +++ b/chrome/app_shim/app_shim_controller.mm
@@ -182,7 +182,20 @@ runningApplicationWithProcessIdentifier:chrome_pid], base::scoped_policy::RETAIN); if (!chrome_to_connect_to_) { - LOG(FATAL) << "Failed to open process with PID: " << chrome_pid; + // Sometimes runningApplicationWithProcessIdentifier fails to return the + // application, even though it exists. If that happens, try to find the + // running application in the full list of running applications manually. + // See https://crbug.com/1426897. + NSArray<NSRunningApplication*>* apps = + [NSWorkspace sharedWorkspace].runningApplications; + for (unsigned i = 0; i < [apps count]; ++i) { + if (apps[i].processIdentifier == chrome_pid) { + chrome_to_connect_to_.reset(apps[i], base::scoped_policy::RETAIN); + } + } + if (!chrome_to_connect_to_) { + LOG(FATAL) << "Failed to open process with PID: " << chrome_pid; + } } return true;
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index bbd45870..4732c84 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -9833,6 +9833,13 @@ FEATURE_VALUE_TYPE(ash::features::kDeskButton)}, #endif +#if !BUILDFLAG(IS_ANDROID) + {"settings-enable-get-the-most-out-of-program", + flag_descriptions::kSettingsEnableGetTheMostOutOfProgramName, + flag_descriptions::kSettingsEnableGetTheMostOutOfProgramDescription, + kOsDesktop, FEATURE_VALUE_TYPE(::features::kGetTheMostOutOfProgram)}, +#endif + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/apps/app_service/app_service_proxy_ash.cc b/chrome/browser/apps/app_service/app_service_proxy_ash.cc index 2c3b23b..ea61d19 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_ash.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
@@ -230,6 +230,15 @@ } } + // Close uninstall dialogs for any uninstalled apps. + for (const AppPtr& delta : deltas) { + if (delta->readiness != Readiness::kUnknown && + !apps_util::IsInstalled(delta->readiness) && + base::Contains(uninstall_dialogs_, delta->app_id)) { + uninstall_dialogs_[delta->app_id]->CloseDialog(); + } + } + if (crosapi_subscriber_) { crosapi_subscriber_->OnApps(deltas, app_type, should_notify_initialized); }
diff --git a/chrome/browser/apps/app_service/uninstall_dialog.cc b/chrome/browser/apps/app_service/uninstall_dialog.cc index 041c8a6..0dd2bda 100644 --- a/chrome/browser/apps/app_service/uninstall_dialog.cc +++ b/chrome/browser/apps/app_service/uninstall_dialog.cc
@@ -11,6 +11,7 @@ #include "components/services/app_service/public/cpp/icon_loader.h" #include "extensions/browser/uninstall_reason.h" #include "ui/views/native_window_tracker.h" +#include "ui/views/widget/widget.h" namespace { @@ -62,6 +63,15 @@ weak_ptr_factory_.GetWeakPtr())); } +void UninstallDialog::CloseDialog() { + if (widget_) { + widget_->CloseWithReason(views::Widget::ClosedReason::kUnspecified); + return; + } + + OnDialogClosed(false, false, false); +} + views::Widget* UninstallDialog::GetWidget() { return widget_; } @@ -69,6 +79,7 @@ void UninstallDialog::OnDialogClosed(bool uninstall, bool clear_site_data, bool report_abuse) { + CHECK(uninstall_callback_); std::move(uninstall_callback_) .Run(uninstall, clear_site_data, report_abuse, this); }
diff --git a/chrome/browser/apps/app_service/uninstall_dialog.h b/chrome/browser/apps/app_service/uninstall_dialog.h index 5a58c0b4..c6180e6 100644 --- a/chrome/browser/apps/app_service/uninstall_dialog.h +++ b/chrome/browser/apps/app_service/uninstall_dialog.h
@@ -101,6 +101,11 @@ // the dialog view. void PrepareToShow(IconKey icon_key, apps::IconLoader* icon_loader); + // Closes this dialog if it is open. If the dialog is not open yet because + // icons are still loading, immediately runs `uninstall_callback_` so that + // `this` can be deleted. + void CloseDialog(); + views::Widget* GetWidget(); // Called when the uninstall dialog is closing to process uninstall or cancel
diff --git a/chrome/browser/ash/app_list/search/burn_in_controller.cc b/chrome/browser/ash/app_list/search/burn_in_controller.cc index 39ea509b..be6e7c9 100644 --- a/chrome/browser/ash/app_list/search/burn_in_controller.cc +++ b/chrome/browser/ash/app_list/search/burn_in_controller.cc
@@ -15,10 +15,6 @@ : burn_in_period_elapsed_callback_(std::move(callback)), burn_in_period_(kBurnInPeriod) {} -bool BurnInController::is_post_burn_in() { - return base::Time::Now() - session_start_ > burn_in_period_; -} - void BurnInController::Start() { burn_in_timer_.Start(FROM_HERE, burn_in_period_, burn_in_period_elapsed_callback_); @@ -34,10 +30,13 @@ burn_in_timer_.Stop(); } -void BurnInController::UpdateResults(ResultsMap& results, +bool BurnInController::UpdateResults(ResultsMap& results, CategoriesList& categories, ash::AppListSearchResultType result_type) { - if (is_post_burn_in()) { + // True if the burn-in period has elapsed. + const bool is_post_burn_in = + base::Time::Now() - session_start_ > burn_in_period_; + if (is_post_burn_in) { ++burn_in_iteration_counter_; } @@ -71,6 +70,8 @@ ids_to_burn_in_iteration_[result_id] = burn_in_iteration_counter_; } } + + return is_post_burn_in; } } // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/burn_in_controller.h b/chrome/browser/ash/app_list/search/burn_in_controller.h index e474c17..22fdfc9c 100644 --- a/chrome/browser/ash/app_list/search/burn_in_controller.h +++ b/chrome/browser/ash/app_list/search/burn_in_controller.h
@@ -15,7 +15,7 @@ namespace app_list { // Manages operations related to the burn-in period. Owned by the -// SearchControllerImplNew. +// SearchController. class BurnInController { public: using BurnInPeriodElapsedCallback = base::RepeatingCallback<void()>; @@ -26,9 +26,6 @@ BurnInController(const BurnInController&) = delete; BurnInController& operator=(const BurnInController&) = delete; - // True if the burn-in period has elapsed. - bool is_post_burn_in(); - // Called at the beginning of a query search. Initiates the burn-in/ period. void Start(); @@ -43,11 +40,14 @@ // // Performs house-keeping related to burn-in iteration numbers for categories // and individual results. These are later important for sorting purposes in - // the SearchControllerImplNew - see further documentation below. + // the SearchController - see further documentation below. // // Triggers the BurnInPeriodElapsedCallback if it is the first time // UpdateResults() has been called since the burn-in period has elapsed. - void UpdateResults(ResultsMap& results, + // + // Returns true if results are updated before `burn_in_period_`, and false + // otherwise. + bool UpdateResults(ResultsMap& results, CategoriesList& categories, ash::AppListSearchResultType result_type);
diff --git a/chrome/browser/ash/app_list/search/search_controller.cc b/chrome/browser/ash/app_list/search/search_controller.cc index c93ebd1..12543d3 100644 --- a/chrome/browser/ash/app_list/search/search_controller.cc +++ b/chrome/browser/ash/app_list/search/search_controller.cc
@@ -276,11 +276,11 @@ metrics_manager_->OnSearchResultsUpdated(result->scoring()); } - burn_in_controller_->UpdateResults(results_, categories_, - provider->ResultType()); + bool is_post_burn_in = burn_in_controller_->UpdateResults( + results_, categories_, provider->ResultType()); // If the burn-in period has not yet elapsed, don't call Publish here (this // case is covered by a call scheduled within the burn-in controller). - if (!last_query_.empty() && burn_in_controller_->is_post_burn_in()) { + if (!last_query_.empty() && is_post_burn_in) { Publish(); } }
diff --git a/chrome/browser/ash/arc/arc_optin_uma.cc b/chrome/browser/ash/arc/arc_optin_uma.cc index 7841f403..9ea6d88 100644 --- a/chrome/browser/ash/arc/arc_optin_uma.cc +++ b/chrome/browser/ash/arc/arc_optin_uma.cc
@@ -10,8 +10,10 @@ #include "ash/components/arc/metrics/stability_metrics_manager.h" #include "ash/components/arc/mojom/app.mojom.h" #include "ash/components/arc/mojom/auth.mojom.h" +#include "ash/shell.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/histogram_macros_local.h" #include "chrome/browser/ash/arc/arc_util.h" #include "chrome/browser/ash/arc/policy/arc_policy_util.h" #include "chrome/browser/ash/arc/session/arc_provisioning_result.h" @@ -159,10 +161,19 @@ void UpdateArcUiAvailableTime(const base::TimeDelta& elapsed_time, const std::string& mode, const Profile* profile) { + if (ash::Shell::HasInstance()) { + ash::Shell::Get() + ->login_unlock_throughput_recorder() + ->ArcUiAvailableAfterLogin(); + } base::UmaHistogramCustomTimes( GetHistogramNameByUserType("Arc.UiAvailable." + mode + ".TimeDelta", profile), elapsed_time, base::Seconds(1), base::Minutes(5), 50); + + // This is local test-only histogram. + LOCAL_HISTOGRAM_CUSTOM_TIMES("Arc.Tast.UiAvailable.TimeDelta", elapsed_time, + base::Seconds(1), base::Minutes(5), 50); } void UpdatePlayStoreLaunchTime(const base::TimeDelta& elapsed_time) {
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge.cc b/chrome/browser/ash/arc/policy/arc_policy_bridge.cc index 8f389b8c..65602fa 100644 --- a/chrome/browser/ash/arc/policy/arc_policy_bridge.cc +++ b/chrome/browser/ash/arc/policy/arc_policy_bridge.cc
@@ -510,6 +510,11 @@ ArcPolicyBridge::~ArcPolicyBridge() { VLOG(2) << "ArcPolicyBridge::~ArcPolicyBridge"; + if (is_policy_service_observed) { + policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this); + is_policy_service_observed = false; + policy_service_ = nullptr; + } arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get(); // It can be null in unittests if (arc_session_manager) {
diff --git a/chrome/browser/ash/eche_app/eche_app_manager_factory_unittest.cc b/chrome/browser/ash/eche_app/eche_app_manager_factory_unittest.cc index bf4345a..070754f 100644 --- a/chrome/browser/ash/eche_app/eche_app_manager_factory_unittest.cc +++ b/chrome/browser/ash/eche_app/eche_app_manager_factory_unittest.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/ash/eche_app/eche_app_manager_factory.h" +#include <memory> #include "ash/constants/ash_features.h" #include "ash/system/eche/eche_tray.h" @@ -47,6 +48,9 @@ DCHECK(profile_); DCHECK(test_web_view_factory_.get()); ChromeAshTestBase::SetUp(); + connection_handler_ = std::make_unique<EcheConnectionStatusHandler>(); + apps_launch_info_provider_ = + std::make_unique<AppsLaunchInfoProvider>(connection_handler_.get()); eche_tray_ = StatusAreaWidgetTestHelper::GetStatusAreaWidget()->eche_tray(); phone_hub_tray_ = StatusAreaWidgetTestHelper::GetStatusAreaWidget()->phone_hub_tray(); @@ -99,6 +103,9 @@ } TestingProfile* GetProfile() { return profile_; } + AppsLaunchInfoProvider* GetAppsLaunchInfoProvider() { + return apps_launch_info_provider_.get(); + } EcheTray* eche_tray() { return eche_tray_; } PhoneHubTray* phone_hub_tray() { return phone_hub_tray_; } @@ -106,6 +113,8 @@ base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<TestingProfileManager> profile_manager_; TestingProfile* profile_; + std::unique_ptr<EcheConnectionStatusHandler> connection_handler_; + std::unique_ptr<AppsLaunchInfoProvider> apps_launch_info_provider_; EcheTray* eche_tray_ = nullptr; PhoneHubTray* phone_hub_tray_ = nullptr; EcheAppManagerFactory* eche_app_manager_factory_ = nullptr; @@ -138,10 +147,16 @@ DCHECK(profile_); DCHECK(test_web_view_factory_.get()); ChromeAshTestBase::SetUp(); + connection_handler_ = std::make_unique<EcheConnectionStatusHandler>(); + apps_launch_info_provider_ = + std::make_unique<AppsLaunchInfoProvider>(connection_handler_.get()); eche_tray_ = StatusAreaWidgetTestHelper::GetStatusAreaWidget()->eche_tray(); } TestingProfile* GetProfile() { return profile_; } + AppsLaunchInfoProvider* GetAppsLaunchInfoProvider() { + return apps_launch_info_provider_.get(); + } EcheTray* eche_tray() { return eche_tray_; } @@ -149,6 +164,8 @@ base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<TestingProfileManager> profile_manager_; TestingProfile* profile_; + std::unique_ptr<EcheConnectionStatusHandler> connection_handler_; + std::unique_ptr<AppsLaunchInfoProvider> apps_launch_info_provider_; EcheTray* eche_tray_ = nullptr; // Calling the factory constructor is enough to set it up. std::unique_ptr<TestAshWebViewFactory> test_web_view_factory_ = @@ -160,13 +177,11 @@ const char16_t visible_name_1[] = u"Fake App 1"; const char package_name_1[] = "com.fakeapp1"; const char16_t phone_name[] = u"your phone"; - auto apps_launch_info_provider = std::make_unique<AppsLaunchInfoProvider>( - std::make_unique<EcheConnectionStatusHandler>().get()); EcheAppManagerFactory::LaunchEcheApp( GetProfile(), /*notification_id=*/absl::nullopt, package_name_1, visible_name_1, user_id, gfx::Image(), phone_name, - apps_launch_info_provider.get()); + GetAppsLaunchInfoProvider()); // Wait for Eche Tray to load Eche Web to complete base::RunLoop().RunUntilIdle(); // Eche icon should be visible after launch. @@ -179,7 +194,7 @@ EcheAppManagerFactory::LaunchEcheApp( GetProfile(), /*notification_id=*/absl::nullopt, package_name_2, visible_name_2, user_id, gfx::Image(), phone_name, - apps_launch_info_provider.get()); + GetAppsLaunchInfoProvider()); // Wait for Eche Tray to load Eche Web to complete base::RunLoop().RunUntilIdle(); EXPECT_EQ(widget, eche_tray()->GetBubbleWidget()); @@ -191,12 +206,10 @@ const std::string package_name = "com.fakeapp"; const gfx::Image icon = gfx::test::CreateImage(100, 100); const std::u16string phone_name = u"your phone"; - auto apps_launch_info_provider = std::make_unique<AppsLaunchInfoProvider>( - std::make_unique<EcheConnectionStatusHandler>().get()); EcheAppManagerFactory::LaunchEcheApp( GetProfile(), /*notification_id=*/absl::nullopt, package_name, - visible_name, user_id, icon, phone_name, apps_launch_info_provider.get()); + visible_name, user_id, icon, phone_name, GetAppsLaunchInfoProvider()); std::unique_ptr<LaunchedAppInfo> launched_app_info = EcheAppManagerFactory::GetInstance()->GetLastLaunchedAppInfo(); @@ -216,13 +229,11 @@ const char16_t visible_name[] = u"Fake App"; const char package_name[] = "com.fakeapp"; const char16_t phone_name[] = u"your phone"; - auto apps_launch_info_provider = std::make_unique<AppsLaunchInfoProvider>( - std::make_unique<EcheConnectionStatusHandler>().get()); EcheAppManagerFactory::LaunchEcheApp( GetProfile(), /*notification_id=*/absl::nullopt, package_name, visible_name, user_id, gfx::Image(), phone_name, - apps_launch_info_provider.get()); + GetAppsLaunchInfoProvider()); // Wait for Eche Tray to load Eche Web to complete base::RunLoop().RunUntilIdle(); // Eche tray should be visible when streaming is active, not ative when
diff --git a/chrome/browser/ash/extensions/file_manager/drivefs_event_router.cc b/chrome/browser/ash/extensions/file_manager/drivefs_event_router.cc index c5e5b8f..848a89b 100644 --- a/chrome/browser/ash/extensions/file_manager/drivefs_event_router.cc +++ b/chrome/browser/ash/extensions/file_manager/drivefs_event_router.cc
@@ -53,23 +53,25 @@ DriveFsEventRouter::SyncingStatusState::~SyncingStatusState() = default; void DriveFsEventRouter::OnUnmounted() { - sync_status_state_.completed_bytes = 0; - sync_status_state_.group_id_to_bytes_to_transfer.clear(); - pin_status_state_.completed_bytes = 0; - pin_status_state_.group_id_to_bytes_to_transfer.clear(); + if (!base::FeatureList::IsEnabled(ash::features::kFilesInlineSyncStatus)) { + sync_status_state_.completed_bytes = 0; + sync_status_state_.group_id_to_bytes_to_transfer.clear(); + pin_status_state_.completed_bytes = 0; + pin_status_state_.group_id_to_bytes_to_transfer.clear(); - // Ensure any existing sync progress indicator is cleared. - FileTransferStatus sync_status; - sync_status.transfer_state = file_manager_private::TRANSFER_STATE_FAILED; - sync_status.show_notification = true; - sync_status.hide_when_zero_jobs = true; - FileTransferStatus pin_status; - pin_status.transfer_state = file_manager_private::TRANSFER_STATE_FAILED; - pin_status.show_notification = true; - pin_status.hide_when_zero_jobs = true; + // Ensure any existing sync progress indicator is cleared. + FileTransferStatus sync_status; + sync_status.transfer_state = file_manager_private::TRANSFER_STATE_FAILED; + sync_status.show_notification = true; + sync_status.hide_when_zero_jobs = true; + FileTransferStatus pin_status; + pin_status.transfer_state = file_manager_private::TRANSFER_STATE_FAILED; + pin_status.show_notification = true; + pin_status.hide_when_zero_jobs = true; - BroadcastTransferEvent(kTransferEvent, sync_status); - BroadcastTransferEvent(kPinEvent, pin_status); + BroadcastTransferEvent(kTransferEvent, sync_status); + BroadcastTransferEvent(kPinEvent, pin_status); + } dialog_callback_.Reset(); }
diff --git a/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc b/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc index b0420ff1..8df442f 100644 --- a/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc +++ b/chrome/browser/ash/extensions/file_manager/drivefs_event_router_unittest.cc
@@ -183,6 +183,11 @@ }; class DriveFsEventRouterTest : public testing::Test { + public: + DriveFsEventRouterTest() { + feature_list_.InitWithFeatures({}, {ash::features::kFilesInlineSyncStatus}); + } + protected: void SetUp() override { event_router_ = std::make_unique<TestDriveFsEventRouter>(); @@ -212,6 +217,9 @@ DriveFsEventRouterTestInlineSyncStatus() { feature_list_.InitWithFeatures({ash::features::kFilesInlineSyncStatus}, {}); } + + protected: + base::test::ScopedFeatureList feature_list_; }; inline void AddEvent(std::vector<drivefs::mojom::ItemEventPtr>& events,
diff --git a/chrome/browser/ash/extensions/file_manager/private_api_tasks.cc b/chrome/browser/ash/extensions/file_manager/private_api_tasks.cc index 4500f89..640db834 100644 --- a/chrome/browser/ash/extensions/file_manager/private_api_tasks.cc +++ b/chrome/browser/ash/extensions/file_manager/private_api_tasks.cc
@@ -12,6 +12,7 @@ #include <utility> #include <vector> +#include "ash/webui/system_apps/public/system_web_app_type.h" #include "base/command_line.h" #include "base/functional/bind.h" #include "chrome/browser/ash/drive/file_system_util.h" @@ -22,6 +23,8 @@ #include "chrome/browser/ash/fileapi/file_system_backend.h" #include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/extensions/api/file_manager_private.h" #include "chrome/common/extensions/api/file_manager_private_internal.h" #include "extensions/browser/api/file_handlers/directory_util.h" @@ -133,8 +136,11 @@ urls.push_back(url); } + // Get Files App window, if it exists. + Browser* browser = + FindSystemWebAppBrowser(profile, ash::SystemWebAppType::FILE_MANAGER); gfx::NativeWindow modal_parent = - ChromeExtensionFunctionDetails(this).GetNativeWindowForUI(); + browser ? browser->window()->GetNativeWindow() : nullptr; const bool result = file_manager::file_tasks::ExecuteFileTask( profile, task, urls, modal_parent,
diff --git a/chrome/browser/ash/input_method/assistive_suggester.cc b/chrome/browser/ash/input_method/assistive_suggester.cc index 7bdd71e..9b6c77b6 100644 --- a/chrome/browser/ash/input_method/assistive_suggester.cc +++ b/chrome/browser/ash/input_method/assistive_suggester.cc
@@ -464,15 +464,17 @@ } if (IsLongpressEnabledControlV(current_longpress_keydown_.value())) { - current_suggester_ = &longpress_control_v_suggester_; const auto anchor_rect = IMEBridge::Get()->GetInputContextHandler()->GetTextFieldBounds(); - Shell::Get()->clipboard_history_controller()->ShowMenu( - anchor_rect, ui::MenuSourceType::MENU_SOURCE_KEYBOARD, - crosapi::mojom::ClipboardHistoryControllerShowSource:: - kControlVLongpress, - base::BindOnce(&AssistiveSuggester::OnClipboardHistoryMenuClosing, - weak_ptr_factory_.GetWeakPtr())); + if (Shell::Get()->clipboard_history_controller()->ShowMenu( + anchor_rect, ui::MenuSourceType::MENU_SOURCE_KEYBOARD, + crosapi::mojom::ClipboardHistoryControllerShowSource:: + kControlVLongpress, + base::BindOnce(&AssistiveSuggester::OnClipboardHistoryMenuClosing, + weak_ptr_factory_.GetWeakPtr()))) { + // Only set `current_suggester_` if the clipboard history menu was shown. + current_suggester_ = &longpress_control_v_suggester_; + } } else if (longpress_diacritics_suggester_.TrySuggestOnLongpress( current_longpress_keydown_->GetCharacter())) { current_suggester_ = &longpress_diacritics_suggester_;
diff --git a/chrome/browser/autofill/autofill_interactive_uitest.cc b/chrome/browser/autofill/autofill_interactive_uitest.cc index 49fc7c6..ac7f415 100644 --- a/chrome/browser/autofill/autofill_interactive_uitest.cc +++ b/chrome/browser/autofill/autofill_interactive_uitest.cc
@@ -1322,8 +1322,7 @@ // Test the basic form-fill flow. // TODO(https://crbug.com/1045709): Check back if flakiness is fixed now. -IN_PROC_BROWSER_TEST_F(AutofillInteractiveTestWithHistogramTester, - BasicFormFill) { +IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicFormFill) { CreateTestProfile(); SetTestUrlResponse(kTestShippingFormString); ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetTestUrl())); @@ -1333,15 +1332,6 @@ .after_select = ExpectValues(MergeValue( kEmptyAddress, {"firstname", "M"}))})); EXPECT_THAT(GetFormValues(), ValuesAre(kDefaultAddress)); - - ::metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); - // Assert that the network isolation key is populated for 2 requests: - // - Navigation: /internal/test_url_path - // - Autofill query: https://clients1.google.com/tbproxy/af/query?... - // or "https://content-autofill.googleapis.com/..." (depending on the - // finch configuration of the AutofillUseApi feature). - histogram_tester().ExpectBucketCount("HttpCache.NetworkIsolationKeyPresent2", - 2 /*kPresent*/, 2 /*count*/); } IN_PROC_BROWSER_TEST_F(AutofillInteractiveTest, BasicClear) {
diff --git a/chrome/browser/bluetooth/web_bluetooth_browsertest.cc b/chrome/browser/bluetooth/web_bluetooth_browsertest.cc index 64f61d40..581374e 100644 --- a/chrome/browser/bluetooth/web_bluetooth_browsertest.cc +++ b/chrome/browser/bluetooth/web_bluetooth_browsertest.cc
@@ -9,6 +9,7 @@ #include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/task/single_thread_task_runner.h" @@ -631,8 +632,8 @@ if (base::FieldTrialList::TrialExists("WebBluetoothBlocklist")) { LOG(INFO) << "WebBluetoothBlocklist field trial already configured."; - ASSERT_NE(variations::GetVariationParamValue("WebBluetoothBlocklist", - "blocklist_additions") + ASSERT_NE(base::GetFieldTrialParamValue("WebBluetoothBlocklist", + "blocklist_additions") .find("ed5f25a4"), std::string::npos) << "ERROR: WebBluetoothBlocklist field trial being tested in\n"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 44da0bc..cfbed0fd 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -3259,7 +3259,7 @@ // TODO(crbug.com/598890): Don't disable if // base::CommandLine::ForCurrentProcess()-> // HasSwitch(switches::kEnableWebBluetooth) is true. - if (variations::GetVariationParamValue( + if (base::GetFieldTrialParamValue( permissions::PermissionContextBase::kPermissionsKillSwitchFieldStudy, "Bluetooth") == permissions::PermissionContextBase::kPermissionsKillSwitchBlockedValue) { @@ -3280,8 +3280,8 @@ } std::string ChromeContentBrowserClient::GetWebBluetoothBlocklist() { - return variations::GetVariationParamValue("WebBluetoothBlocklist", - "blocklist_additions"); + return base::GetFieldTrialParamValue("WebBluetoothBlocklist", + "blocklist_additions"); } bool ChromeContentBrowserClient::IsInterestGroupAPIAllowed(
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index 789638c..8449967 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -2611,14 +2611,6 @@ ASSERT_EQ(url, download_items[0]->GetOriginalUrl()); ASSERT_EQ(url, download_items[1]->GetOriginalUrl()); - metrics::SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); - // Assert that the NIK is populated for 4 requests: - // - Navigation: image.jpg - // - favicon.ico - // - SavePage: image.jpg - // - context menu: image.jpg - histogram_tester().ExpectBucketCount("HttpCache.NetworkIsolationKeyPresent2", - 2 /*kPresent*/, 4 /*count*/); ResetURLLoaderInterceptor(); }
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chrome/browser/extensions/api/content_settings/content_settings_api.cc index 0c97213..0db0e1e 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_api.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -25,6 +25,7 @@ #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" +#include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/webplugininfo.h" @@ -229,6 +230,15 @@ content_settings::ContentSettingsRegistry::GetInstance()->Get( content_type); + // The ANTI_ABUSE content setting does not support site-specific settings. + if (content_type == ContentSettingsType::ANTI_ABUSE && + (primary_pattern != ContentSettingsPattern::Wildcard() || + secondary_pattern != ContentSettingsPattern::Wildcard())) { + return RespondNow( + Error("Site-specific settings are not allowed for this type. The URL " + "pattern must be '<all_urls>'.")); + } + // Some content setting types support the full set of values listed in // content_settings.json only for exceptions. For the default setting, // some values might not be supported.
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc index d58b5ef..fca8048 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -130,6 +130,9 @@ EXPECT_EQ(CONTENT_SETTING_ALLOW, map->GetContentSetting(example_url, example_url, ContentSettingsType::AUTOPLAY)); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + map->GetContentSetting(example_url, example_url, + ContentSettingsType::ANTI_ABUSE)); // Check content settings for www.google.com GURL url("http://www.google.com"); @@ -160,6 +163,9 @@ ContentSettingsType::AUTOMATIC_DOWNLOADS)); EXPECT_EQ(CONTENT_SETTING_ALLOW, map->GetContentSetting(url, url, ContentSettingsType::AUTOPLAY)); + EXPECT_EQ( + CONTENT_SETTING_BLOCK, + map->GetContentSetting(url, url, ContentSettingsType::ANTI_ABUSE)); } void CheckContentSettingsDefault() { @@ -198,6 +204,9 @@ ContentSettingsType::AUTOMATIC_DOWNLOADS)); EXPECT_EQ(CONTENT_SETTING_ALLOW, map->GetContentSetting(url, url, ContentSettingsType::AUTOPLAY)); + EXPECT_EQ( + CONTENT_SETTING_ALLOW, + map->GetContentSetting(url, url, ContentSettingsType::ANTI_ABUSE)); } // Returns a snapshot of content settings for a given URL.
diff --git a/chrome/browser/feedback/android/BUILD.gn b/chrome/browser/feedback/android/BUILD.gn index 26f9680..898c99b 100644 --- a/chrome/browser/feedback/android/BUILD.gn +++ b/chrome/browser/feedback/android/BUILD.gn
@@ -28,38 +28,32 @@ android_library("java") { sources = [ - "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSourceAdapter.java", "java/src/org/chromium/chrome/browser/feedback/DeviceInfoFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/FamilyInfoFeedbackSource.java", - "java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java", "java/src/org/chromium/chrome/browser/feedback/FeedbackContextFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/FeedbackReporter.java", - "java/src/org/chromium/chrome/browser/feedback/FeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/FragmentHelpAndFeedbackLauncher.java", "java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncher.java", - "java/src/org/chromium/chrome/browser/feedback/HistogramFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/IMEFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/InterestFeedFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/LowEndDeviceFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/PermissionFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/ProcessIdFeedbackSource.java", - "java/src/org/chromium/chrome/browser/feedback/ScreenshotSource.java", - "java/src/org/chromium/chrome/browser/feedback/StaticScreenshotSource.java", "java/src/org/chromium/chrome/browser/feedback/SystemInfoFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/UrlFeedbackSource.java", "java/src/org/chromium/chrome/browser/feedback/VariationsFeedbackSource.java", ] deps = [ + ":delegate_java", + ":feedback_collector_java", ":java_resources", "//base:base_java", "//base:jni_java", "//build/android:build_java", "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", - "//chrome/browser/signin/services/android:java", "//components/browser_ui/util/android:java", - "//components/signin/public/android:java", "//components/variations/android:variations_java", "//content/public/android:content_java", "//net/android:net_java", @@ -67,10 +61,63 @@ "//third_party/androidx:androidx_annotation_annotation_java", "//ui/android:ui_no_recycler_view_java", ] + public_deps = [ + ":delegate_java", + ":feedback_collector_java", + ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] resources_package = "org.chromium.chrome.browser.feedback" } +android_library("feedback_collector_java") { + sources = [ + "java/src/org/chromium/chrome/browser/feedback/AsyncFeedbackSource.java", + "java/src/org/chromium/chrome/browser/feedback/FeedbackCollector.java", + "java/src/org/chromium/chrome/browser/feedback/FeedbackSource.java", + "java/src/org/chromium/chrome/browser/feedback/HistogramFeedbackSource.java", + "java/src/org/chromium/chrome/browser/feedback/ScreenshotSource.java", + "java/src/org/chromium/chrome/browser/feedback/StaticScreenshotSource.java", + ] + deps = [ + "//base:base_java", + "//build/android:build_java", + "//chrome/browser/profiles/android:java", + "//chrome/browser/signin/services/android:java", + "//components/browser_ui/util/android:java", + "//components/signin/public/android:java", + "//third_party/android_deps:guava_android_java", + "//third_party/androidx:androidx_annotation_annotation_java", + ] +} + +android_library("delegate_java") { + sources = [ + "java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegate.java", + "java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegateImpl.java", + ] + + deps = [ + ":feedback_collector_java", + "//base:base_java", + "//third_party/androidx:androidx_annotation_annotation_java", + ] + + # Add the actual implementation where necessary so that downstream targets + # can provide their own implementations. + jar_excluded_patterns = [ "*/HelpAndFeedbackLauncherDelegateImpl.class" ] +} + +android_library("delegate_public_impl_java") { + sources = [ "java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegateImpl.java" ] + + deps = [ + ":delegate_java", + ":feedback_collector_java", + "//base:base_java", + "//third_party/androidx:androidx_annotation_annotation_java", + ] +} + android_resources("java_resources") { sources = [ "java/res/values/strings.xml" ] }
diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegate.java b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegate.java new file mode 100644 index 0000000..663e657e --- /dev/null +++ b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegate.java
@@ -0,0 +1,54 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.feedback; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.provider.Browser; + +import androidx.annotation.NonNull; + +/** + * Delegate that handles the display of the HelpAndFeedback flows. + */ +public interface HelpAndFeedbackLauncherDelegate { + static final String FALLBACK_SUPPORT_URL = "https://support.google.com/chrome/topic/6069782"; + + /** + * Starts an activity showing a help page for the specified context ID. + * + * @param activity The activity to use for starting the help activity and to take a + * screenshot of. + * @param helpContext One of the CONTEXT_* constants. This should describe the user's current + * context and will be used to show a more relevant help page. + * @param collector the {@link FeedbackCollector} to use for extra data. Must not be null. + */ + void show(Activity activity, String helpContext, @NonNull FeedbackCollector collector); + + /** + * Starts an activity prompting the user to enter feedback. + * + * @param activity The activity to use for starting the feedback activity and to take a + * screenshot of. + * @param collector the {@link FeedbackCollector} to use for extra data. Must not be null. + */ + void showFeedback(Activity activity, @NonNull FeedbackCollector collector); + + /** + * Handles the fallback help case of opening the URL in the browser. + * @param context The context launching the fallback support. + */ + static void launchFallbackSupportUri(Context context) { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(FALLBACK_SUPPORT_URL)); + // Let Chrome know that this intent is from Chrome, so that it does not close the app when + // the user presses 'back' button. + intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); + intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); + intent.setPackage(context.getPackageName()); + context.startActivity(intent); + } +}
diff --git a/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegateImpl.java b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegateImpl.java new file mode 100644 index 0000000..a403deeb --- /dev/null +++ b/chrome/browser/feedback/android/java/src/org/chromium/chrome/browser/feedback/HelpAndFeedbackLauncherDelegateImpl.java
@@ -0,0 +1,32 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.feedback; + +import android.app.Activity; + +import androidx.annotation.NonNull; + +import org.chromium.base.Log; + +/** + * Basic implementation for displaying help support for Chrome. + * + * NOTE: This class is designed to be replaced by downstream targets. + */ +public class HelpAndFeedbackLauncherDelegateImpl implements HelpAndFeedbackLauncherDelegate { + private static final String TAG = "HelpAndFeedback"; + + @Override + public void show(Activity activity, String helpContext, @NonNull FeedbackCollector collector) { + Log.d(TAG, "Feedback data: " + collector.getBundle()); + HelpAndFeedbackLauncherDelegate.launchFallbackSupportUri(activity); + } + + @Override + public void showFeedback(Activity activity, @NonNull FeedbackCollector collector) { + Log.d(TAG, "Feedback data: " + collector.getBundle()); + HelpAndFeedbackLauncherDelegate.launchFallbackSupportUri(activity); + } +}
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 195457e6..34f915c 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -6470,6 +6470,11 @@ "expiry_milestone": 96 }, { + "name": "settings-enable-get-the-most-out-of-program", + "owners": [ "jochen" ], + "expiry_milestone": 130 + }, + { "name": "share-sheet-migration-android", "owners": [ "wenyufu" ], "expiry_milestone": 121
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 01f5e77b..dd747bf 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4535,6 +4535,12 @@ "Enables SCT auditing for users who have opted in to Safe Browsing " "Extended Reporting."; +const char kSettingsEnableGetTheMostOutOfProgramName[] = + "'Get the most out of Chrome' documentation"; +const char kSettingsEnableGetTheMostOutOfProgramDescription[] = + "When enabled, the 'Get the most out of Chrome' documentation section " + "will be available."; + const char kSharingDesktopSharePreviewName[] = "Desktop share hub preview"; const char kSharingDesktopSharePreviewDescription[] = "Adds a preview section to the desktop sharing hub to make it clearer what "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 65ef3cb..441bd3e 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2607,6 +2607,9 @@ extern const char kSCTAuditingName[]; extern const char kSCTAuditingDescription[]; +extern const char kSettingsEnableGetTheMostOutOfProgramName[]; +extern const char kSettingsEnableGetTheMostOutOfProgramDescription[]; + extern const char kSharingDesktopSharePreviewName[]; extern const char kSharingDesktopSharePreviewDescription[];
diff --git a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc index e836dd2..bf28599 100644 --- a/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc +++ b/chrome/browser/metrics/desktop_session_duration/chrome_visibility_observer.cc
@@ -6,12 +6,12 @@ #include "base/functional/bind.h" #include "base/memory/singleton.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "base/task/single_thread_task_runner.h" #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" -#include "components/variations/variations_associated_data.h" namespace metrics { @@ -67,7 +67,7 @@ const int kDefaultVisibilityGapTimeout = 3; int timeout_seconds = kDefaultVisibilityGapTimeout; - std::string param_value = variations::GetVariationParamValue( + std::string param_value = base::GetFieldTrialParamValue( "DesktopSessionDuration", "visibility_gap_timeout"); if (!param_value.empty()) base::StringToInt(param_value, &timeout_seconds);
diff --git a/chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.cc b/chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.cc index 6eb14e9d..3713470 100644 --- a/chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.cc +++ b/chrome/browser/metrics/desktop_session_duration/desktop_session_duration_tracker.cc
@@ -6,10 +6,10 @@ #include "base/functional/bind.h" #include "base/logging.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/observer_list.h" #include "base/strings/string_number_conversions.h" -#include "components/variations/variations_associated_data.h" namespace metrics { @@ -174,7 +174,7 @@ const int kDefaultInactivityTimeoutMinutes = 5; int timeout_minutes = kDefaultInactivityTimeoutMinutes; - std::string param_value = variations::GetVariationParamValue( + std::string param_value = base::GetFieldTrialParamValue( "DesktopSessionDuration", "inactivity_timeout"); if (!param_value.empty()) base::StringToInt(param_value, &timeout_minutes);
diff --git a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc index a8156a6..5101c25e 100644 --- a/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc +++ b/chrome/browser/new_tab_page/modules/history_clusters/history_clusters_page_handler.cc
@@ -78,6 +78,17 @@ categories.end()); } +int GetMinVisitsToShow() { + static int min_visits = base::GetFieldTrialParamByFeatureAsInt( + ntp_features::kNtpHistoryClustersModuleMinimumVisitsRequired, + ntp_features::kNtpHistoryClustersModuleMinimumVisitsRequiredParam, + kMinRequiredVisits); + if (min_visits < 0) { + return kMinRequiredVisits; + } + return min_visits; +} + int GetMinImagesToShow() { static int min_images_to_show = base::GetFieldTrialParamByFeatureAsInt( ntp_features::kNtpHistoryClustersModuleMinimumImagesRequired, @@ -100,6 +111,7 @@ history_clusters::QueryClustersFilterParams GetFilterParamsFromFeatureFlags() { history_clusters::QueryClustersFilterParams filter_params; + filter_params.min_visits = GetMinVisitsToShow(); filter_params.min_visits_with_images = GetMinImagesToShow(); filter_params.categories_allowlist = GetCategories( ntp_features::kNtpHistoryClustersModuleCategoriesAllowlistParam);
diff --git a/chrome/browser/performance_manager/policies/heuristic_memory_saver_policy.cc b/chrome/browser/performance_manager/policies/heuristic_memory_saver_policy.cc index 15f18bb..100d16a 100644 --- a/chrome/browser/performance_manager/policies/heuristic_memory_saver_policy.cc +++ b/chrome/browser/performance_manager/policies/heuristic_memory_saver_policy.cc
@@ -80,7 +80,7 @@ static_cast<float>(pmf_threshold_percent_)) { PageDiscardingHelper::GetFromGraph(graph_)->DiscardAPage( /*post_discard_cb=*/base::DoNothing(), - /*discard_reason=*/::mojom::LifecycleUnitDiscardReason::PROACTIVE, + PageDiscardingHelper::DiscardReason::PROACTIVE, /*minimum_time_in_background=*/minimum_time_in_background_); next_interval = threshold_reached_heartbeat_interval_; }
diff --git a/chrome/browser/performance_manager/policies/high_efficiency_mode_policy.cc b/chrome/browser/performance_manager/policies/high_efficiency_mode_policy.cc index 4273eb2..3abcdf9 100644 --- a/chrome/browser/performance_manager/policies/high_efficiency_mode_policy.cc +++ b/chrome/browser/performance_manager/policies/high_efficiency_mode_policy.cc
@@ -152,7 +152,7 @@ DCHECK(IsHighEfficiencyDiscardingEnabled()); PageDiscardingHelper::GetFromGraph(graph_)->ImmediatelyDiscardSpecificPage( - page_node, ::mojom::LifecycleUnitDiscardReason::PROACTIVE); + page_node, PageDiscardingHelper::DiscardReason::PROACTIVE); } } // namespace performance_manager::policies
diff --git a/chrome/browser/performance_manager/policies/oom_score_policy_lacros.cc b/chrome/browser/performance_manager/policies/oom_score_policy_lacros.cc index 80bb19f..8505825 100644 --- a/chrome/browser/performance_manager/policies/oom_score_policy_lacros.cc +++ b/chrome/browser/performance_manager/policies/oom_score_policy_lacros.cc
@@ -46,13 +46,13 @@ std::vector<PageNodeSortProxy> candidates; for (const auto* page_node : page_nodes) { - PageDiscardingHelper::CanUrgentlyDiscardResult can_discard_result = - discarding_helper->CanUrgentlyDiscard(page_node); - bool is_marked = (can_discard_result == - PageDiscardingHelper::CanUrgentlyDiscardResult::kMarked); - bool is_protected = - (can_discard_result == - PageDiscardingHelper::CanUrgentlyDiscardResult::kProtected); + PageDiscardingHelper::CanDiscardResult can_discard_result = + discarding_helper->CanDiscard( + page_node, PageDiscardingHelper::DiscardReason::URGENT); + bool is_marked = + (can_discard_result == PageDiscardingHelper::CanDiscardResult::kMarked); + bool is_protected = (can_discard_result == + PageDiscardingHelper::CanDiscardResult::kProtected); candidates.emplace_back(page_node, is_marked, is_protected, page_node->GetTimeSinceLastVisibilityChange()); }
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper.cc b/chrome/browser/performance_manager/policies/page_discarding_helper.cc index 31ce278..2e1757c 100644 --- a/chrome/browser/performance_manager/policies/page_discarding_helper.cc +++ b/chrome/browser/performance_manager/policies/page_discarding_helper.cc
@@ -18,7 +18,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/performance_manager/mechanisms/page_discarder.h" #include "chrome/browser/performance_manager/policies/policy_features.h" -#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" #include "components/performance_manager/graph/node_attached_data_impl.h" #include "components/performance_manager/graph/page_node_impl.h" #include "components/performance_manager/public/graph/frame_node.h" @@ -42,7 +41,7 @@ // discard a PageNode. // TODO(sebmarchand): The only reason for a discard attempt to fail is if we try // to discard a prerenderer, remove this once we can detect if a PageNode is a -// prerenderer in |CanUrgentlyDiscard|. +// prerenderer in CanDiscard(). class DiscardAttemptMarker : public NodeAttachedDataImpl<DiscardAttemptMarker> { public: struct Traits : public NodeAttachedDataInMap<PageNodeImpl> {}; @@ -113,7 +112,7 @@ void PageDiscardingHelper::DiscardAPage( base::OnceCallback<void(bool)> post_discard_cb, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background) { DiscardMultiplePages(absl::nullopt, false, std::move(post_discard_cb), discard_reason, minimum_time_in_background); @@ -123,7 +122,7 @@ absl::optional<uint64_t> reclaim_target_kb, bool discard_protected_tabs, base::OnceCallback<void(bool)> post_discard_cb, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -139,13 +138,12 @@ std::vector<PageNodeSortProxy> candidates; for (const auto* page_node : page_nodes) { - CanUrgentlyDiscardResult can_discard_result = - CanUrgentlyDiscard(page_node, minimum_time_in_background); - if (can_discard_result == CanUrgentlyDiscardResult::kMarked) { + CanDiscardResult can_discard_result = + CanDiscard(page_node, discard_reason, minimum_time_in_background); + if (can_discard_result == CanDiscardResult::kMarked) { continue; } - bool is_protected = - (can_discard_result == CanUrgentlyDiscardResult::kProtected); + bool is_protected = (can_discard_result == CanDiscardResult::kProtected); if (!discard_protected_tabs && is_protected) { continue; } @@ -214,12 +212,12 @@ void PageDiscardingHelper::ImmediatelyDiscardSpecificPage( const PageNode* page_node, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::OnceCallback<void(bool)> post_discard_cb) { // Pass 0 TimeDelta to bypass the minimum time in background check. - if (CanUrgentlyDiscard(page_node, - /* minimum_time_in_background */ base::TimeDelta()) == - CanUrgentlyDiscardResult::kEligible) { + if (CanDiscard(page_node, discard_reason, + /*minimum_time_in_background=*/base::TimeDelta()) == + CanDiscardResult::kEligible) { page_discarder_->DiscardPageNodes({page_node}, discard_reason, std::move(post_discard_cb)); } else { @@ -293,45 +291,58 @@ return PageLiveStateDecorator::Data::FromPageNode(page_node); } -PageDiscardingHelper::CanUrgentlyDiscardResult -PageDiscardingHelper::CanUrgentlyDiscard( +PageDiscardingHelper::CanDiscardResult PageDiscardingHelper::CanDiscard( const PageNode* page_node, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background) const { if (DiscardAttemptMarker::Get(PageNodeImpl::FromNode(page_node))) { - return CanUrgentlyDiscardResult::kMarked; + return CanDiscardResult::kMarked; + } + + bool is_proactive; + switch (discard_reason) { + case DiscardReason::EXTERNAL: + // Always allow discards from external sources like extensions. + return CanDiscardResult::kEligible; + case DiscardReason::URGENT: + is_proactive = false; + break; + case DiscardReason::PROACTIVE: + is_proactive = true; + break; } if (page_node->IsVisible()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (page_node->IsAudible()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } // Don't discard tabs that have recently played audio. auto it = last_change_to_non_audible_time_.find(page_node); if (it != last_change_to_non_audible_time_.end()) { if (base::TimeTicks::Now() - it->second < kTabAudioProtectionTime) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } } if (page_node->GetTimeSinceLastVisibilityChange() < minimum_time_in_background) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } // Do not discard PDFs as they might contain entry that is not saved and they // don't remember their scrolling positions. See crbug.com/547286 and // crbug.com/65244. if (page_node->GetContentsMimeType() == "application/pdf") { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } // Don't discard tabs that don't have a main frame yet. auto* main_frame = page_node->GetMainFrameNode(); if (!main_frame) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } // Only discard http(s) pages and internal pages to make sure that we don't @@ -340,16 +351,18 @@ main_frame->GetURL().SchemeIsHTTPOrHTTPS() || main_frame->GetURL().SchemeIs("chrome"); if (!is_web_page_or_internal_page) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (!main_frame->GetURL().is_valid() || main_frame->GetURL().is_empty()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } + // The enterprise policy to except pages from discarding applies to both + // proactive and urgent discards. if (IsPageOptedOutOfDiscarding(page_node->GetBrowserContextID(), main_frame->GetURL())) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } const auto* live_state_data = GetPageNodeLiveStateData(page_node); @@ -357,50 +370,60 @@ // The live state data won't be available if none of these events ever // happened on the page. if (live_state_data) { + // Don't discard the page if an extension is protecting it from discards. if (!live_state_data->IsAutoDiscardable()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsCapturingVideo()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsCapturingAudio()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsBeingMirrored()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsCapturingWindow()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsCapturingDisplay()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsConnectedToBluetoothDevice()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } if (live_state_data->IsConnectedToUSBDevice()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } + // Don't discard the active tab in any window, even if the window is not + // visible. Otherwise the user would see a blank page when the window + // becomes visible again, as the tab isn't reloaded until they click on it. if (live_state_data->IsActiveTab()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } + // Pinning a tab is a strong signal the user wants to keep it. if (live_state_data->IsPinnedTab()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } - if (live_state_data->IsContentSettingTypeAllowed( - ContentSettingsType::NOTIFICATIONS)) { - return CanUrgentlyDiscardResult::kProtected; - } + // Don't discard pages with devtools attached, because when it's restored + // the devtools window won't come back. The user may be monitoring the page + // in the background with devtools. if (live_state_data->IsDevToolsOpen()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } - if (live_state_data->UpdatedTitleOrFaviconInBackground()) { - return CanUrgentlyDiscardResult::kProtected; + if (is_proactive) { + if (live_state_data->IsContentSettingTypeAllowed( + ContentSettingsType::NOTIFICATIONS)) { + return CanDiscardResult::kProtected; + } + if (live_state_data->UpdatedTitleOrFaviconInBackground()) { + return CanDiscardResult::kProtected; + } } #if !BUILDFLAG(IS_CHROMEOS) // TODO(sebmarchand): Skip this check if the Entreprise memory limit is set. if (live_state_data->WasDiscarded()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } // TODO(sebmarchand): Consider resetting the |WasDiscarded| value when the // main frame document changes, also remove the DiscardAttemptMarker in @@ -411,12 +434,12 @@ // `HadUserEdits()` is currently a superset of `HadFormInteraction()` but // that may change so check both here (the check is not expensive). if (page_node->HadFormInteraction() || page_node->HadUserEdits()) { - return CanUrgentlyDiscardResult::kProtected; + return CanDiscardResult::kProtected; } // TODO(sebmarchand): Do not discard crashed tabs. - return CanUrgentlyDiscardResult::kEligible; + return CanDiscardResult::kEligible; } bool PageDiscardingHelper::IsPageOptedOutOfDiscarding( @@ -440,21 +463,20 @@ base::Value::Dict PageDiscardingHelper::DescribePageNodeData( const PageNode* node) const { - base::StringPiece can_discard; - switch (CanUrgentlyDiscard(node, base::TimeDelta())) { - case CanUrgentlyDiscardResult::kEligible: - can_discard = "eligible"; - break; - case CanUrgentlyDiscardResult::kProtected: - can_discard = "protected"; - break; - case CanUrgentlyDiscardResult::kMarked: - can_discard = "marked"; - break; - } + auto can_discard = [this, node](DiscardReason discard_reason) { + switch (this->CanDiscard(node, discard_reason, base::TimeDelta())) { + case CanDiscardResult::kEligible: + return "eligible"; + case CanDiscardResult::kProtected: + return "protected"; + case CanDiscardResult::kMarked: + return "marked"; + } + }; base::Value::Dict ret; - ret.Set("can_urgently_discard", can_discard); + ret.Set("can_urgently_discard", can_discard(DiscardReason::URGENT)); + ret.Set("can_proactively_discard", can_discard(DiscardReason::PROACTIVE)); auto it = last_change_to_non_audible_time_.find(node); if (it != last_change_to_non_audible_time_.end()) { ret.Set("non_audible_change_time", TimeDeltaFromNowToValue(it->second)); @@ -471,7 +493,7 @@ absl::optional<uint64_t> reclaim_target_kb, bool discard_protected_tabs, base::OnceCallback<void(bool)> post_discard_cb, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background, bool success) { // When there is no discard candidate, DiscardMultiplePages returns
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper.h b/chrome/browser/performance_manager/policies/page_discarding_helper.h index 4c6b67a..48c4d31 100644 --- a/chrome/browser/performance_manager/policies/page_discarding_helper.h +++ b/chrome/browser/performance_manager/policies/page_discarding_helper.h
@@ -11,7 +11,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" -#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" +#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom-shared.h" #include "components/performance_manager/public/decorators/page_live_state_decorator.h" #include "components/performance_manager/public/features.h" #include "components/performance_manager/public/graph/graph.h" @@ -85,7 +85,7 @@ public GraphRegisteredImpl<PageDiscardingHelper>, public NodeDataDescriberDefaultImpl { public: - enum class CanUrgentlyDiscardResult { + enum class CanDiscardResult { // Discarding eligible nodes is hard to notice for user. kEligible, // Discarding protected nodes is noticeable to user. @@ -94,6 +94,9 @@ kMarked, }; + // Export discard reason in the public interface. + using DiscardReason = ::mojom::LifecycleUnitDiscardReason; + PageDiscardingHelper(); ~PageDiscardingHelper() override; PageDiscardingHelper(const PageDiscardingHelper& other) = delete; @@ -102,30 +105,30 @@ // Selects a tab to discard and posts to the UI thread to discard it. This // will try to discard a tab until there's been a successful discard or until // there's no more discard candidate. - // `minimum_time_in_background` is passed to `CanUrgentlyDiscard()`, see the - // comment there about its usage. + // `minimum_time_in_background` is passed to `CanDiscard()`, see the comment + // there about its usage. void DiscardAPage(base::OnceCallback<void(bool)> post_discard_cb, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background = kNonVisiblePagesUrgentProtectionTime); // Discards multiple tabs to meet the reclaim target based and posts to the UI // thread to discard these tabs. Retries discarding if all discardings in the // UI thread fail. If |reclaim_target_kb| is nullopt, only discard one tab. If - // |discard_protected_tabs| is true, protected tab (CanUrgentlyDiscard() - // returns kProtected) can also be discarded. - // `minimum_time_in_background` is passed to `CanUrgentlyDiscard()`, see the - // comment there about its usage. + // |discard_protected_tabs| is true, protected tabs (CanDiscard() returns + // kProtected) can also be discarded. + // `minimum_time_in_background` is passed to `CanDiscard()`, see the comment + // there about its usage. void DiscardMultiplePages(absl::optional<uint64_t> reclaim_target_kb, bool discard_protected_tabs, base::OnceCallback<void(bool)> post_discard_cb, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background = kNonVisiblePagesUrgentProtectionTime); void ImmediatelyDiscardSpecificPage( const PageNode* page_node, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::OnceCallback<void(bool)> post_discard_cb = base::DoNothing()); // PageNodeObserver: @@ -138,21 +141,15 @@ void SetMockDiscarderForTesting( std::unique_ptr<mechanism::PageDiscarder> discarder); - bool CanUrgentlyDiscardForTesting( - const PageNode* page_node, - base::TimeDelta minimum_time_in_background = - kNonVisiblePagesUrgentProtectionTime) const { - return CanUrgentlyDiscard(page_node, minimum_time_in_background) == - CanUrgentlyDiscardResult::kEligible; - } - // Indicates if a PageNode can be urgently discarded. - // If `minimum_time_in_background` is non-zero, the page will not be discarded - // if it has not spent at least `minimum_time_in_background` in the - // not-visible state. - CanUrgentlyDiscardResult CanUrgentlyDiscard( - const PageNode* page_node, - base::TimeDelta minimum_time_in_background = - kNonVisiblePagesUrgentProtectionTime) const; + + // Indicates if `page_node` can be urgently discarded, using a list of + // criteria depending on `discard_reason`. If `minimum_time_in_background` is + // non-zero, the page will not be discarded if it has not spent at least + // `minimum_time_in_background` in the not-visible state. + CanDiscardResult CanDiscard(const PageNode* page_node, + DiscardReason discard_reason, + base::TimeDelta minimum_time_in_background = + kNonVisiblePagesUrgentProtectionTime) const; void SetGraphForTesting(Graph* graph) { graph_ = graph; } static void AddDiscardAttemptMarkerForTesting(PageNode* page_node); @@ -182,7 +179,7 @@ absl::optional<uint64_t> reclaim_target_kb, bool discard_protected_tabs, base::OnceCallback<void(bool)> post_discard_cb, - ::mojom::LifecycleUnitDiscardReason discard_reason, + DiscardReason discard_reason, base::TimeDelta minimum_time_in_background, bool success);
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper_browsertest.cc b/chrome/browser/performance_manager/policies/page_discarding_helper_browsertest.cc index aae794d..ba7db7e 100644 --- a/chrome/browser/performance_manager/policies/page_discarding_helper_browsertest.cc +++ b/chrome/browser/performance_manager/policies/page_discarding_helper_browsertest.cc
@@ -4,12 +4,12 @@ #include "chrome/browser/performance_manager/policies/page_discarding_helper.h" +#include "base/location.h" #include "base/memory/weak_ptr.h" #include "base/run_loop.h" #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind.h" -#include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/test/base/in_process_browser_test.h" @@ -34,6 +34,8 @@ namespace { +using DiscardReason = PageDiscardingHelper::DiscardReason; + class FaviconWatcher final : public content::WebContentsObserver { public: explicit FaviconWatcher(content::WebContents* web_contents) @@ -106,18 +108,39 @@ favicon_watcher.Wait(); } - void ExpectImmediateDiscard(int index, bool expected_result) { + void ExpectImmediateDiscard( + int index, + DiscardReason discard_reason, + bool expected_result, + const base::Location& location = base::Location::Current()) { + const char* discard_string; + switch (discard_reason) { + case DiscardReason::URGENT: + discard_string = "Urgent"; + break; + case DiscardReason::PROACTIVE: + discard_string = "Proactive"; + break; + case DiscardReason::EXTERNAL: + discard_string = "External"; + break; + } + SCOPED_TRACE(::testing::Message() + << discard_string << " discard from " << location.ToString()); base::WeakPtr<PageNode> page_node = PerformanceManager::GetPrimaryPageNodeForWebContents( browser()->tab_strip_model()->GetWebContentsAt(index)); base::RunLoop run_loop; PerformanceManager::CallOnGraph( FROM_HERE, base::BindLambdaForTesting([&](Graph* graph) { + SCOPED_TRACE(::testing::Message() + << discard_string << " discard, called on graph from " + << location.ToString()); ASSERT_TRUE(page_node); auto* helper = PageDiscardingHelper::GetFromGraph(graph); ASSERT_TRUE(helper); helper->ImmediatelyDiscardSpecificPage( - page_node.get(), ::mojom::LifecycleUnitDiscardReason::URGENT, + page_node.get(), discard_reason, base::BindLambdaForTesting([&](bool success) { EXPECT_EQ(success, expected_result); run_loop.Quit(); @@ -132,38 +155,59 @@ }; IN_PROC_BROWSER_TEST_F(PageDiscardingHelperBrowserTest, DiscardSpecificPage) { - // Background pages can be discarded. - const int index1 = OpenNewBackgroundPage(); - ExpectImmediateDiscard(index1, true); + // Test urgent and proactive discards in a loop to avoid the overhead of + // starting a new browser every time. + // TODO(crbug.com/1426484): Add tests for all the other heuristics in + // PageDiscardingHelper::CanDiscard(). + for (auto discard_reason : + {DiscardReason::URGENT, DiscardReason::PROACTIVE}) { + { + // Background pages can be discarded. + const int index1 = OpenNewBackgroundPage(); + ExpectImmediateDiscard(index1, discard_reason, true); - // Foreground page should be blocked. - const int index2 = OpenNewBackgroundPage(); - browser()->tab_strip_model()->ActivateTabAt(index2); - ExpectImmediateDiscard(index2, false); + // Foreground page should be blocked. + // TODO(crbug.com/1426484): Also test when the browser window is occluded. + // They should still be blocked. + const int index2 = OpenNewBackgroundPage(); + browser()->tab_strip_model()->ActivateTabAt(index2); + ExpectImmediateDiscard(index2, discard_reason, false); + } - // Updating the title while in the background should block the discard. - const int index3 = OpenNewBackgroundPage(); - UpdatePageTitle(index3); - ExpectImmediateDiscard(index3, false); + { + // Updating the title while in the background should block only proactive + // discards. + const int index1 = OpenNewBackgroundPage(); + UpdatePageTitle(index1); + ExpectImmediateDiscard(index1, discard_reason, + discard_reason == DiscardReason::URGENT); - // Updating the page title while in the foreground should not. - const int index4 = OpenNewBackgroundPage(); - browser()->tab_strip_model()->ActivateTabAt(index4); - UpdatePageTitle(index4); - browser()->tab_strip_model()->ActivateTabAt(index3); - ExpectImmediateDiscard(index4, true); + // Updating the page title while in the foreground should not block any + // discards. + const int index2 = OpenNewBackgroundPage(); + browser()->tab_strip_model()->ActivateTabAt(index2); + UpdatePageTitle(index2); + browser()->tab_strip_model()->ActivateTabAt(index1); + ExpectImmediateDiscard(index2, discard_reason, true); + } - // Updating the favicon while in the background should block the discard. - const int index5 = OpenNewBackgroundPage(); - UpdateFavicon(index5); - ExpectImmediateDiscard(index5, false); + { + // Updating the favicon while in the background should block only + // proactive discards. + const int index1 = OpenNewBackgroundPage(); + UpdateFavicon(index1); + ExpectImmediateDiscard(index1, discard_reason, + discard_reason == DiscardReason::URGENT); - // Updating the favicon while in the foreground should not. - const int index6 = OpenNewBackgroundPage(); - browser()->tab_strip_model()->ActivateTabAt(index6); - UpdateFavicon(index6); - browser()->tab_strip_model()->ActivateTabAt(index5); - ExpectImmediateDiscard(index6, true); + // Updating the favicon while in the foreground should not block any + // discards. + const int index2 = OpenNewBackgroundPage(); + browser()->tab_strip_model()->ActivateTabAt(index2); + UpdateFavicon(index2); + browser()->tab_strip_model()->ActivateTabAt(index1); + ExpectImmediateDiscard(index2, discard_reason, true); + } + } } } // namespace
diff --git a/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc b/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc index 5b6fc64..c7a44fcd 100644 --- a/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc +++ b/chrome/browser/performance_manager/policies/page_discarding_helper_unittest.cc
@@ -21,6 +21,8 @@ namespace performance_manager { namespace policies { +using CanDiscardResult = PageDiscardingHelper::CanDiscardResult; +using DiscardReason = PageDiscardingHelper::DiscardReason; using ::testing::Return; class PageDiscardingHelperTest @@ -42,6 +44,21 @@ testing::GraphTestHarnessWithMockDiscarder::TearDown(); } + // Convenience wrappers for PageNodeHelper::CanDiscard(). + bool CanDiscard(const PageNode* page_node, DiscardReason discard_reason) { + return PageDiscardingHelper::GetFromGraph(graph())->CanDiscard( + page_node, discard_reason) == CanDiscardResult::kEligible; + } + + bool CanDiscardWithMinimumTimeInBackground( + const PageNode* page_node, + DiscardReason discard_reason, + base::TimeDelta minimum_time_in_background) { + return PageDiscardingHelper::GetFromGraph(graph())->CanDiscard( + page_node, discard_reason, minimum_time_in_background) == + CanDiscardResult::kEligible; + } + protected: base::HistogramTester* histogram_tester() { return histogram_tester_.get(); } @@ -51,33 +68,33 @@ TEST_F(PageDiscardingHelperTest, TestCannotDiscardVisiblePage) { page_node()->SetIsVisible(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardAudiblePage) { page_node()->SetIsAudible(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithDiscardAttemptMarker) { PageDiscardingHelper::GetFromGraph(graph()) ->AddDiscardAttemptMarkerForTesting(page_node()); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardRecentlyAudiblePage) { page_node()->SetIsAudible(true); page_node()->SetIsAudible(false); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } #if !BUILDFLAG(IS_CHROMEOS) @@ -86,12 +103,16 @@ page_node()->SetIsVisible(true); page_node()->SetIsVisible(false); AdvanceClock(base::Seconds(1)); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node(), /* minimum_time_in_background */ base::Seconds(1))); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); + + EXPECT_TRUE(CanDiscardWithMinimumTimeInBackground( + page_node(), DiscardReason::URGENT, base::Seconds(1))); + EXPECT_TRUE(CanDiscardWithMinimumTimeInBackground( + page_node(), DiscardReason::PROACTIVE, base::Seconds(1))); + EXPECT_TRUE(CanDiscardWithMinimumTimeInBackground( + page_node(), DiscardReason::EXTERNAL, base::Seconds(1))); } #endif @@ -99,138 +120,139 @@ page_node()->OnMainFrameNavigationCommitted(false, base::TimeTicks::Now(), 53, GURL("https://foo.com/doc.pdf"), "application/pdf"); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithoutMainFrame) { ResetFrameNode(); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardExtension) { frame_node()->OnNavigationCommitted(GURL("chrome-extention://foo"), false); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithInvalidURL) { frame_node()->OnNavigationCommitted(GURL("foo42"), false); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageProtectedByExtension) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsAutoDiscardableForTesting(false); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageCapturingVideo) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsCapturingVideoForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageCapturingAudio) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsCapturingAudioForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageBeingMirrored) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsBeingMirroredForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageCapturingWindow) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsCapturingWindowForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageCapturingDisplay) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsCapturingDisplayForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageConnectedToBluetoothDevice) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsConnectedToBluetoothDeviceForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardIsConnectedToUSBDevice) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsConnectedToUSBDeviceForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } #if !BUILDFLAG(IS_CHROMEOS) TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageMultipleTimes) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetWasDiscardedForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } #endif TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithFormInteractions) { frame_node()->SetHadFormInteraction(); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageWithUserEdits) { frame_node()->SetHadUserEdits(); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } -TEST_F(PageDiscardingHelperTest, TestCannotDiscardIsActiveTab) { +TEST_F(PageDiscardingHelperTest, TestCannotDiscardActiveTab) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsActiveTabForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } -TEST_F(PageDiscardingHelperTest, TestCannotDiscardWithNotificationPermission) { +TEST_F(PageDiscardingHelperTest, + TestCannotProactivelyDiscardWithNotificationPermission) { // The page is discardable if notifications are blocked. PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetContentSettingsForTesting({ {ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK}, }); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); // The page is discardable if notifications aren't found in its permissions // list. @@ -238,18 +260,18 @@ ->SetContentSettingsForTesting({ {ContentSettingsType::AUTO_SELECT_CERTIFICATE, CONTENT_SETTING_ALLOW}, }); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); - // The page is not discardable if it can send notifications. + // The page is not proactively discardable if it can send notifications. PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetContentSettingsForTesting({ {ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW}, }); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, TestCannotDiscardPageOnNoDiscardList) { @@ -263,60 +285,60 @@ static_cast<PageNode*>(page_node())->GetBrowserContextID(), {"youtube.com"}); frame_node()->OnNavigationCommitted(GURL("https://www.youtube.com"), false); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); frame_node()->OnNavigationCommitted(GURL("https://www.example.com"), false); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); // Changing the no discard list rebuilds the matcher PageDiscardingHelper::GetFromGraph(graph())->SetNoDiscardPatternsForProfile( static_cast<PageNode*>(page_node())->GetBrowserContextID(), {"google.com"}); frame_node()->OnNavigationCommitted(GURL("https://www.youtube.com"), false); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); frame_node()->OnNavigationCommitted(GURL("https://www.google.com"), false); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); // Setting the no discard list to empty makes all URLs discardable again. PageDiscardingHelper::GetFromGraph(graph())->SetNoDiscardPatternsForProfile( static_cast<PageNode*>(page_node())->GetBrowserContextID(), {}); frame_node()->OnNavigationCommitted(GURL("https://www.google.com"), false); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } -TEST_F(PageDiscardingHelperTest, TestCannotDiscardIsPinnedTab) { +TEST_F(PageDiscardingHelperTest, TestCannotDiscardPinnedTab) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsPinnedTabForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } -TEST_F(PageDiscardingHelperTest, TestCannotDiscardIsDevToolsOpen) { +TEST_F(PageDiscardingHelperTest, TestCannotDiscardWithDevToolsOpen) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetIsDevToolsOpenForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } TEST_F(PageDiscardingHelperTest, - TestCannotDiscardUpdatedTitleOrFaviconInBackground) { + TestCannotProactivelyDiscardAfterUpdatedTitleOrFaviconInBackground) { PageLiveStateDecorator::Data::GetOrCreateForPageNode(page_node()) ->SetUpdatedTitleOrFaviconInBackgroundForTesting(true); - EXPECT_FALSE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); + EXPECT_FALSE(CanDiscard(page_node(), DiscardReason::PROACTIVE)); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::EXTERNAL)); } // Tests DiscardMultiplePages. @@ -329,7 +351,7 @@ /*reclaim_target_kb*/ 1024, /*discard_protected_tabs*/ false, base::BindOnce([](bool success) { EXPECT_FALSE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -344,7 +366,7 @@ /*reclaim_target_kb*/ 1024, /*discard_protected_tabs*/ true, base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -356,9 +378,7 @@ main_frame_node2->SetIsCurrent(true); testing::MakePageNodeDiscardable(page_node2.get(), task_env()); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node2.get())); + EXPECT_TRUE(CanDiscard(page_node2.get(), DiscardReason::URGENT)); process_node()->set_resident_set_kb(1024); process_node2->set_resident_set_kb(1024); @@ -373,7 +393,7 @@ /*reclaim_target_kb*/ 2048, /*discard_protected_tabs*/ true, base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -388,9 +408,7 @@ main_frame_node2->SetIsCurrent(true); testing::MakePageNodeDiscardable(page_node2.get(), task_env()); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node2.get())); + EXPECT_TRUE(CanDiscard(page_node2.get(), DiscardReason::URGENT)); process_node()->set_resident_set_kb(1024); process_node2->set_resident_set_kb(1024); @@ -404,7 +422,7 @@ /*reclaim_target_kb*/ 1000000, /*discard_protected_tabs*/ false, base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -448,7 +466,7 @@ /*reclaim_target_kb*/ 1500, /*discard_protected_tabs*/ true, base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); histogram_tester()->ExpectBucketCount("Discarding.DiscardCandidatesCount", 3, 1); @@ -498,7 +516,7 @@ /*reclaim_target_kb*/ 1500, /*discard_protected_tabs*/ true, base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -524,7 +542,7 @@ /*reclaim_target_kb*/ 10240, /*discard_protected_tabs*/ true, base::BindOnce([](bool success) { EXPECT_FALSE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -534,7 +552,7 @@ page_node()->SetIsVisible(true); PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_FALSE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -543,7 +561,7 @@ .WillOnce(Return(true)); PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); histogram_tester()->ExpectBucketCount("Discarding.DiscardCandidatesCount", 1, 1); @@ -554,7 +572,7 @@ .WillOnce(Return(false)); PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_FALSE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); // There should be 2 discard attempts, during the first one an attempt will be // made to discard |page_node()|, on the second attempt no discard candidate @@ -579,9 +597,7 @@ AdvanceClock(base::Minutes(30)); page_node2->SetIsVisible(false); AdvanceClock(base::Minutes(30)); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node2.get())); + EXPECT_TRUE(CanDiscard(page_node2.get(), DiscardReason::URGENT)); EXPECT_GT(page_node()->TimeSinceLastVisibilityChange(), page_node2->TimeSinceLastVisibilityChange()); @@ -593,7 +609,7 @@ PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); histogram_tester()->ExpectBucketCount("Discarding.DiscardCandidatesCount", 2, @@ -622,7 +638,7 @@ PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -648,7 +664,7 @@ PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -665,9 +681,7 @@ AdvanceClock(base::Minutes(30)); page_node()->SetIsVisible(false); AdvanceClock(base::Minutes(30)); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); EXPECT_GT(page_node2->TimeSinceLastVisibilityChange(), page_node()->TimeSinceLastVisibilityChange()); @@ -678,7 +692,7 @@ PageDiscardingHelper::GetFromGraph(graph())->DiscardAPage( base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); } @@ -697,9 +711,7 @@ AdvanceClock(base::Minutes(30)); page_node()->SetIsVisible(false); AdvanceClock(base::Minutes(30)); - EXPECT_TRUE( - PageDiscardingHelper::GetFromGraph(graph())->CanUrgentlyDiscardForTesting( - page_node())); + EXPECT_TRUE(CanDiscard(page_node(), DiscardReason::URGENT)); EXPECT_GT(page_node2->TimeSinceLastVisibilityChange(), page_node()->TimeSinceLastVisibilityChange()); @@ -712,7 +724,7 @@ /*reclaim_target_kb*/ absl::nullopt, /*discard_protected_tabs*/ true, base::BindOnce([](bool success) { EXPECT_TRUE(success); }), - ::mojom::LifecycleUnitDiscardReason::URGENT); + DiscardReason::URGENT); ::testing::Mock::VerifyAndClearExpectations(discarder()); }
diff --git a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc index 1b32b87..61e97b6 100644 --- a/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc +++ b/chrome/browser/performance_manager/policies/urgent_page_discarding_policy.cc
@@ -64,7 +64,7 @@ policy->handling_memory_pressure_notification_ = false; }, base::Unretained(this)), - ::mojom::LifecycleUnitDiscardReason::URGENT); + PageDiscardingHelper::DiscardReason::URGENT); } #endif // BUILDFLAG(IS_CHROMEOS_LACROS) @@ -107,7 +107,7 @@ // won't ever run after the destruction of this class and so it's safe // to use Unretained. base::Unretained(this)), - ::mojom::LifecycleUnitDiscardReason::URGENT); + PageDiscardingHelper::DiscardReason::URGENT); #endif // BUILDFLAG(IS_CHROMEOS_LACROS) }
diff --git a/chrome/browser/performance_manager/test_support/page_discarding_utils.cc b/chrome/browser/performance_manager/test_support/page_discarding_utils.cc index 1ff7a290..c6489815 100644 --- a/chrome/browser/performance_manager/test_support/page_discarding_utils.cc +++ b/chrome/browser/performance_manager/test_support/page_discarding_utils.cc
@@ -91,6 +91,9 @@ void MakePageNodeDiscardable(PageNodeImpl* page_node, content::BrowserTaskEnvironment& task_env) { + using CanDiscardResult = policies::PageDiscardingHelper::CanDiscardResult; + using DiscardReason = policies::PageDiscardingHelper::DiscardReason; + page_node->SetIsVisible(false); page_node->SetIsAudible(false); const auto kUrl = GURL("https://foo.com"); @@ -98,8 +101,14 @@ kUrl, "text/html"); (*page_node->main_frame_nodes().begin())->OnNavigationCommitted(kUrl, false); task_env.FastForwardBy(base::Minutes(10)); - DCHECK(policies::PageDiscardingHelper::GetFromGraph(page_node->graph()) - ->CanUrgentlyDiscardForTesting(page_node)); + const auto* helper = + policies::PageDiscardingHelper::GetFromGraph(page_node->graph()); + CHECK_EQ(helper->CanDiscard(page_node, DiscardReason::URGENT), + CanDiscardResult::kEligible); + CHECK_EQ(helper->CanDiscard(page_node, DiscardReason::PROACTIVE), + CanDiscardResult::kEligible); + CHECK_EQ(helper->CanDiscard(page_node, DiscardReason::EXTERNAL), + CanDiscardResult::kEligible); } } // namespace testing
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 56f143c..6ffc3f0 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -1046,7 +1046,8 @@ AppendLinkToTextItems(); } - if (user_notes::IsUserNotesEnabled()) { + if (user_notes::IsUserNotesEnabled() && GetBrowser() && + GetBrowser()->is_type_normal()) { AppendUserNotesItems(); }
diff --git a/chrome/browser/resources/history/BUILD.gn b/chrome/browser/resources/history/BUILD.gn index e31d6e35..2232bb6 100644 --- a/chrome/browser/resources/history/BUILD.gn +++ b/chrome/browser/resources/history/BUILD.gn
@@ -68,4 +68,6 @@ "lazy_load.js", ] } + + enable_source_maps = enable_webui_inline_sourcemaps }
diff --git a/chrome/browser/resources/new_tab_page/lazy_load.ts b/chrome/browser/resources/new_tab_page/lazy_load.ts index 4d88fce6..984abe9d 100644 --- a/chrome/browser/resources/new_tab_page/lazy_load.ts +++ b/chrome/browser/resources/new_tab_page/lazy_load.ts
@@ -16,6 +16,7 @@ import './modules/module_descriptors.js'; import 'chrome://resources/cr_components/most_visited/most_visited.js'; +export {ImageServiceBrowserProxy} from 'chrome://resources/cr_components/image_service/browser_proxy.js'; export {CustomizeBackgroundsElement} from './customize_backgrounds.js'; export {CustomizeDialogElement} from './customize_dialog.js'; export {CustomizeModulesElement} from './customize_modules.js';
diff --git a/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts b/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts index 52da3c4..b881613d 100644 --- a/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts +++ b/chrome/browser/resources/new_tab_page/modules/history_clusters/tile.ts
@@ -72,8 +72,11 @@ await ImageServiceBrowserProxy.getInstance().handler.getPageImageUrl( ImageServiceClientId.NtpQuests, visitUrl, {suggestImages: false, optimizationGuideImages: true}); - if (result && result.result) { - this.imageUrl_ = result.result.imageUrl; + const success = !!(result && result.result); + chrome.metricsPrivate.recordBoolean( + 'NewTabPage.HistoryClusters.ImageLoadSuccess', success); + if (success) { + this.imageUrl_ = result!.result!.imageUrl; return; } }
diff --git a/chrome/browser/resources/settings/about_page/about_page.html b/chrome/browser/resources/settings/about_page/about_page.html index 06e07366..13262ca 100644 --- a/chrome/browser/resources/settings/about_page/about_page.html +++ b/chrome/browser/resources/settings/about_page/about_page.html
@@ -130,6 +130,12 @@ button-aria-description="$i18n{opensInNewTab}" label="$i18n{aboutReportAnIssue}" external></cr-link-row> </if> + <cr-link-row class="hr" id="getTheMostOutOfProgram" + on-click="onGetTheMostOutOfProgramTap_" + label="$i18n{getTheMostOutOfProgram}" + sub-label="$i18n{getTheMostOutOfProgramDescription}" + role-description="$i18n{subpageArrowRoleDescription}" + hidden$="[[!showGetTheMostOutOfProgramSection_]]"></cr-link-row> <cr-link-row class="hr" on-click="onManagementPageTap_" start-icon="cr:domain" label="$i18n{managementPage}" role-description="$i18n{subpageArrowRoleDescription}"
diff --git a/chrome/browser/resources/settings/about_page/about_page.ts b/chrome/browser/resources/settings/about_page/about_page.ts index 33ffbcbe..cf1a524 100644 --- a/chrome/browser/resources/settings/about_page/about_page.ts +++ b/chrome/browser/resources/settings/about_page/about_page.ts
@@ -34,10 +34,11 @@ import {getTemplate} from './about_page.html.js'; import {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, UpdateStatus, UpdateStatusChangedEvent} from './about_page_browser_proxy.js'; +// clang-format off // <if expr="_google_chrome and is_macosx"> import {PromoteUpdaterStatus} from './about_page_browser_proxy.js'; - // </if> +// clang-format on const SettingsAboutPageElementBase = RelaunchMixin(WebUiListenerMixin(I18nMixin(PolymerElement))); @@ -74,6 +75,16 @@ }, }, + /** + * Whether to show the "Get the most out of Chrome" section. + */ + showGetTheMostOutOfProgramSection_: { + type: Boolean, + value() { + return loadTimeData.getBoolean('showGetTheMostOutOfProgramSection'); + }, + }, + // <if expr="_google_chrome and is_macosx"> promoteUpdaterStatus_: Object, // </if> @@ -117,6 +128,7 @@ private currentUpdateStatusEvent_: UpdateStatusChangedEvent|null; private isManaged_: boolean; + private showGetTheMostOutOfProgramSection_: boolean; // <if expr="_google_chrome and is_macosx"> private promoteUpdaterStatus_: PromoteUpdaterStatus; @@ -201,6 +213,10 @@ this.performRestart(RestartType.RELAUNCH); } + private onGetTheMostOutOfProgramTap_() { + // TODO(crbug.com/1423278): implement. + } + // <if expr="not chromeos_ash"> private updateShowUpdateStatus_() { if (this.obsoleteSystemInfo_.endOfLine) {
diff --git a/chrome/browser/resources/settings/chromeos/device_page/device_page.html b/chrome/browser/resources/settings/chromeos/device_page/device_page.html index 6f25c7d3..59c6b7b 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/device_page.html +++ b/chrome/browser/resources/settings/chromeos/device_page/device_page.html
@@ -157,9 +157,8 @@ <template is="dom-if" route-path="/per-device-keyboard/remap-keys"> <os-settings-subpage id="perDeviceKeyboardRemapKeysRow" - page-title="$i18n{remapKeyboardKeysRowLabel}" - keyboards="[[keyboards]]"> - <settings-per-device-keyboard-remap-keys> + page-title="$i18n{remapKeyboardKeysRowLabel}"> + <settings-per-device-keyboard-remap-keys keyboards="[[keyboards]]"> </settings-per-device-keyboard-remap-keys> </os-settings-subpage> </template>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html index c780cd4..7092255 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html +++ b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.html
@@ -20,39 +20,46 @@ default-remappings="[[defaultRemappings]]" key="[[modifierKey.kMeta]]" id="metaKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeMetaPref}}"></keyboard-remap-modifier-key-row> + pref="{{fakeMetaPref}}"> + </keyboard-remap-modifier-key-row> <keyboard-remap-modifier-key-row default-remappings="[[defaultRemappings]]" key="[[modifierKey.kControl]]" id="ctrlKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeCtrlPref}}"></keyboard-remap-modifier-key-row> + pref="{{fakeCtrlPref}}"> + </keyboard-remap-modifier-key-row> <keyboard-remap-modifier-key-row default-remappings="[[defaultRemappings]]" key="[[modifierKey.kAlt]]" id="altKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeAltPref}}"></keyboard-remap-modifier-key-row> + pref="{{fakeAltPref}}"> + </keyboard-remap-modifier-key-row> <keyboard-remap-modifier-key-row default-remappings="[[defaultRemappings]]" key="[[modifierKey.kEscape]]" id="escapeKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeEscPref}}"></keyboard-remap-modifier-key-row> + pref="{{fakeEscPref}}"> + </keyboard-remap-modifier-key-row> <keyboard-remap-modifier-key-row default-remappings="[[defaultRemappings]]" key="[[modifierKey.kBackspace]]" id="backspaceKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeBackspacePref}}"></keyboard-remap-modifier-key-row> - <template is="dom-if" if="[[hasAssistantKey_]]" restamp> + pref="{{fakeBackspacePref}}"> + </keyboard-remap-modifier-key-row> + <template is="dom-if" if="[[hasAssistantKey]]" restamp> <keyboard-remap-modifier-key-row default-remappings="[[defaultRemappings]]" key="[[modifierKey.kAssistant]]" id="assistantKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeAssistantPref}}"></keyboard-remap-modifier-key-row> + pref="{{fakeAssistantPref}}"> + </keyboard-remap-modifier-key-row> </template> <template is="dom-if" if="[[hasCapsLockKey]]" restamp> <keyboard-remap-modifier-key-row default-remappings="[[defaultRemappings]]" key="[[modifierKey.kCapsLock]]" id="capsLockKey" meta-key="[[keyboard.metaKey]]" - pref="{{fakeCapsLockPref}}"></keyboard-remap-modifier-key-row> + pref="{{fakeCapsLockPref}}"> + </keyboard-remap-modifier-key-row> </template> </div>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts index b73c9cf6..f523a0b 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/per_device_keyboard_remap_keys.ts
@@ -19,12 +19,10 @@ import {PolymerElementProperties} from 'chrome://resources/polymer/v3_0/polymer/interfaces.js'; import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {KeyboardSettingsObserverReceiver} from '../mojom-webui/input_device_settings_provider.mojom-webui.js'; import {routes} from '../os_settings_routes.js'; import {RouteObserverMixin, RouteObserverMixinInterface} from '../route_observer_mixin.js'; import {Route, Router} from '../router.js'; -import {FakeInputDeviceSettingsProvider} from './fake_input_device_settings_provider.js'; import {getInputDeviceSettingsProvider} from './input_device_mojo_interface_provider.js'; import {InputDeviceSettingsProviderInterface, Keyboard, MetaKey, ModifierKey} from './input_device_settings_types.js'; import {getTemplate} from './per_device_keyboard_remap_keys.html.js'; @@ -139,6 +137,9 @@ keyboards: { type: Array, + // Prevents the `onKeyboardListUpdated` observer from firing + // when the page is first initialized. + value: undefined, }, metaKeyLabel: { @@ -159,6 +160,11 @@ type: Boolean, value: false, }, + + keyboardId: { + type: Number, + value: -1, + }, }; } @@ -171,6 +177,7 @@ 'fakeBackspacePref.value,' + 'fakeAssistantPref.value,' + 'fakeCapsLockPref.value)', + 'onKeyboardListUpdated(keyboards.*)', ]; } @@ -180,7 +187,7 @@ protected keyboard: Keyboard; private keyboards: Keyboard[]; - private keyboardSettingsObserverReceiver: KeyboardSettingsObserverReceiver; + protected keyboardId: number; protected defaultRemappings: {[key: number]: ModifierKey} = { [ModifierKey.kMeta]: ModifierKey.kMeta, [ModifierKey.kControl]: ModifierKey.kControl, @@ -204,17 +211,15 @@ private metaKeyLabel: string; private isInitialized: boolean; - constructor() { - super(); - this.observeKeyboardSettings(); - } - override currentRouteChanged(route: Route): void { // Does not apply to this page. if (route !== routes.PER_DEVICE_KEYBOARD_REMAP_KEYS) { return; } - this.getKeyboard(); + if (this.hasKeyboards() && + this.keyboardId !== this.getKeyboardIdFromUrl()) { + this.initializeKeyboard(); + } } private computeModifierRemappings(): Map<ModifierKey, ModifierKey> { @@ -236,19 +241,13 @@ * Get the keyboard to display according to the keyboardId in the url query, * initializing the page and pref with the keyboard data. */ - private async getKeyboard(): Promise<void> { + private initializeKeyboard(): void { // Set isInitialized to false to prevent calling update keyboard settings // api while the prefs are initializing. this.isInitialized = false; - - const urlSearchQuery = - Router.getInstance().getQueryParameters().get('keyboardId'); - assert(!!urlSearchQuery); - - // Get the correct keyboard from inputDeviceSettingsProvider with the id. - const keyboardId = Number(urlSearchQuery); - const searchedKeyboard = - this.keyboards.find((keyboard: Keyboard) => keyboard.id === keyboardId); + this.keyboardId = this.getKeyboardIdFromUrl(); + const searchedKeyboard = this.keyboards.find( + (keyboard: Keyboard) => keyboard.id === this.keyboardId); assert(!!searchedKeyboard); this.keyboard = searchedKeyboard; this.updateDefaultRemapping(); @@ -269,35 +268,23 @@ this.isInitialized = true; } - private observeKeyboardSettings(): void { - if (this.inputDeviceSettingsProvider instanceof - FakeInputDeviceSettingsProvider) { - this.inputDeviceSettingsProvider.observeKeyboardSettings(this); - return; - } - - this.keyboardSettingsObserverReceiver = - new KeyboardSettingsObserverReceiver(this); - - this.inputDeviceSettingsProvider.observeKeyboardSettings( - this.keyboardSettingsObserverReceiver.$.bindNewPipeAndPassRemote()); + private keyboardWasDisconnected(id: number): boolean { + return !this.keyboards.find(keyboard => keyboard.id === id); } - onKeyboardListUpdated(keyboards: Keyboard[]): void { - this.keyboards = keyboards; + onKeyboardListUpdated(): void { if (Router.getInstance().currentRoute !== routes.PER_DEVICE_KEYBOARD_REMAP_KEYS) { return; } - const keyboardFound = this.keyboard?.id && - keyboards.find(keyboard => keyboard.id === this.keyboard.id); - - // If the keyboard is disconnected in remapping page, go back to - // per_device_keyboard page. - if (!keyboardFound) { + if (!this.hasKeyboards() || + this.keyboardWasDisconnected(this.getKeyboardIdFromUrl())) { + this.keyboardId = -1; Router.getInstance().navigateTo(routes.PER_DEVICE_KEYBOARD); + return; } + this.initializeKeyboard(); } private defaultInitializePrefs(): void { @@ -415,6 +402,14 @@ ModifierKey.kControl, }; } + + private getKeyboardIdFromUrl(): number { + return Number(Router.getInstance().getQueryParameters().get('keyboardId')); + } + + private hasKeyboards(): boolean { + return this.keyboards?.length > 0; + } } declare global {
diff --git a/chrome/browser/resources/settings/chromeos/lazy_load.ts b/chrome/browser/resources/settings/chromeos/lazy_load.ts index f3afdc9b..f427534 100644 --- a/chrome/browser/resources/settings/chromeos/lazy_load.ts +++ b/chrome/browser/resources/settings/chromeos/lazy_load.ts
@@ -127,3 +127,4 @@ export {OsResetBrowserProxyImpl} from './os_reset_page/os_reset_browser_proxy.js'; export {GoogleAssistantBrowserProxyImpl} from './os_search_page/google_assistant_browser_proxy.js'; export {ConsentStatus, DspHotwordState} from './os_search_page/google_assistant_subpage.js'; +export {SettingsSearchSubpageElement} from './os_search_page/search_subpage.js';
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts b/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts index b2038d2..95676b6 100644 --- a/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts +++ b/chrome/browser/resources/settings/chromeos/os_search_page/search_subpage.ts
@@ -37,7 +37,8 @@ const SettingsSearchSubpageElementBase = DeepLinkingMixin(RouteObserverMixin(PrefsMixin(I18nMixin(PolymerElement)))); -class SettingsSearchSubpageElement extends SettingsSearchSubpageElementBase { +export class SettingsSearchSubpageElement extends + SettingsSearchSubpageElementBase { static get is() { return 'settings-search-subpage'; }
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.ts b/chrome/browser/resources/settings/chromeos/os_settings.ts index 771c54e9..eb4a21f 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.ts +++ b/chrome/browser/resources/settings/chromeos/os_settings.ts
@@ -98,7 +98,10 @@ export {getNearbyShareSettings, observeNearbyShareSettings, setNearbyShareSettingsForTesting} from '/shared/nearby_share_settings.js'; export {NearbySettings, NearbyShareSettingsMixin} from '/shared/nearby_share_settings_mixin.js'; export {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js'; +export {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; export {OpenWindowProxyImpl} from 'chrome://resources/js/open_window_proxy.js'; +export {SettingsDropdownMenuElement} from '../controls/settings_dropdown_menu.js'; +export {SettingsSliderElement} from '../controls/settings_slider.js'; export {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; export {LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.js'; export {ProfileInfoBrowserProxyImpl} from '../people_page/profile_info_browser_proxy.js'; @@ -112,7 +115,7 @@ export {fakeKeyboards, fakeKeyboards2, fakeMice, fakeMice2, fakePointingSticks, fakePointingSticks2, fakeTouchpads, fakeTouchpads2} from './device_page/fake_input_device_data.js'; export {FakeInputDeviceSettingsProvider} from './device_page/fake_input_device_settings_provider.js'; export {getInputDeviceSettingsProvider, setInputDeviceSettingsProviderForTesting, setupFakeInputDeviceSettingsProvider} from './device_page/input_device_mojo_interface_provider.js'; -export {MetaKey, ModifierKey} from './device_page/input_device_settings_types.js'; +export {MetaKey, ModifierKey, Mouse} from './device_page/input_device_settings_types.js'; export {KeyboardRemapModifierKeyRowElement} from './device_page/keyboard_remap_modifier_key_row.js'; export {SettingsPerDeviceKeyboardElement} from './device_page/per_device_keyboard.js'; export {SettingsPerDeviceKeyboardRemapKeysElement} from './device_page/per_device_keyboard_remap_keys.js';
diff --git a/chrome/browser/resources/settings/images/iban.svg b/chrome/browser/resources/settings/images/iban.svg index 36168fc..d0645210 100644 --- a/chrome/browser/resources/settings/images/iban.svg +++ b/chrome/browser/resources/settings/images/iban.svg
@@ -1 +1 @@ -<svg width="32" height="20" viewBox="0 0 32 20" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><rect x=".5" y=".5" width="31" height="19" rx="1.5" fill="#fff" stroke="#DADCE0"/><path d="m9.938 13.102 1.04-6.026h1.029l-1.04 6.026H9.938ZM14.91 13.061a3.362 3.362 0 0 1-.762.082h-2.395l.99-6.025h2.417c.608.01 1.018.225 1.23.641.13.257.177.563.143.92-.038.368-.147.664-.33.886-.098.125-.347.24-.53.343.25.112.428.29.535.531.108.242.143.538.106.884-.04.357-.153.677-.34.96a1.901 1.901 0 0 1-.432.476 1.574 1.574 0 0 1-.633.302h.002Zm-.446-2.57h-1.282l-.223 1.605h1.284c.23 0 .412-.036.548-.106.248-.131.396-.382.44-.752.038-.314-.049-.528-.256-.646-.117-.066-.286-.1-.51-.102h-.001Zm.778-1.15c.15-.098.239-.273.269-.527.03-.28-.041-.465-.211-.556a1.572 1.572 0 0 0-.593-.094h-1.105l-.175 1.328h1.252c.223 0 .412-.05.564-.15h-.001ZM20.341 7.118l.81 6.025h-1.295l-.12-1.238h-2.104l-.643 1.239H15.74l3.25-6.026H20.342Zm-.964 1.377-1.213 2.371h1.449l-.236-2.371ZM24.877 13.143l-1.803-4.28-.625 4.28h-1.112l.978-6.025h1.252l1.755 4.206.566-4.206H27l-.93 6.025h-1.195.002Z" fill="#002F70"/><path d="M7.064 13.045c-.556-.124-1.023-.278-1.388-.479C6.512 14.024 8.04 15 9.786 15c.762 0 1.482-.187 2.122-.518-.442.15-.914.234-1.404.234-1.38 0-2.614-.65-3.44-1.671ZM8.189 12.963a6.534 6.534 0 0 0 1.754-.104l.066-.389c-.404.045-.85.074-1.335.074-.258 0-.49-.014-.702-.038a6.002 6.002 0 0 1-.438-1.713c.001 0-.024-.285-.03-.434a5.52 5.52 0 0 1-.004-.216v-.105c0-.704.134-1.379.37-1.985a5.824 5.824 0 0 1 1.869-2.6 5.045 5.045 0 0 0-2.265 2.664 6.296 6.296 0 0 1-.965-.282c.752-1.504 2.258-2.53 3.995-2.53a4.32 4.32 0 0 1 1.518.274A4.612 4.612 0 0 0 9.786 5C7.855 5 6.19 6.195 5.434 7.916c.235.164.522.31.853.434v-.004c.304.118.65.213 1.023.282a5.355 5.355 0 0 0-.163 1.655A5.34 5.34 0 0 1 6 9.883c.011-.427.077-.839.19-1.23-.341-.12-.64-.265-.883-.422a5.188 5.188 0 0 0-.291 1.352c.206.304.553.585 1.008.798.341.146.734.266 1.169.352.087.626.284 1.215.567 1.745a4.062 4.062 0 0 1-1.324-.442 4.79 4.79 0 0 1-.375-1.249c-.456-.185-.816-.433-1.061-.71.01.642.134 1.253.354 1.815.32.338.833.632 1.47.83-.002-.002.526.163 1.223.228l.142.011v.002Z" fill="#0490F9"/><path d="M8.094 8.222c-.051.16-.096.322-.136.49.228.02.461.035.703.035.753 0 1.454-.106 2.041-.286l.048-.282a9.123 9.123 0 0 1-2.657.043ZM7.8 10.405c.007.145.018.287.035.427a8.92 8.92 0 0 0 2.468-.063l.065-.374c-.415.064-.86.098-1.32.098a8.54 8.54 0 0 1-1.247-.09l-.001.002Z" fill="#0490F9"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h32v20H0z"/></clipPath></defs></svg> \ No newline at end of file +<svg width="32" height="20" viewBox="0 0 32 20" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#a)"><rect x=".5" y=".5" width="31" height="19" rx="1.5" fill="#fff" stroke="#DADCE0"/><path d="M5.494 13V6.556H6.71V13H5.494Zm2.981 0V6.556h2.52c.373 0 .706.078 1 .234.3.15.537.351.71.603.175.252.261.534.261.846 0 .336-.083.621-.252.855a1.577 1.577 0 0 1-.612.531v.072c.33.114.595.303.793.567.204.258.306.573.306.945 0 .366-.097.684-.289.954a1.876 1.876 0 0 1-.764.621 2.545 2.545 0 0 1-1.063.216h-2.61Zm1.215-2.772v1.665h1.35a1.1 1.1 0 0 0 .514-.108.754.754 0 0 0 .314-.297.837.837 0 0 0 .108-.423.855.855 0 0 0-.108-.432.744.744 0 0 0-.324-.297 1.202 1.202 0 0 0-.54-.108H9.69Zm0-1.044h1.216a1 1 0 0 0 .467-.099.724.724 0 0 0 .298-.288.74.74 0 0 0 .107-.387.758.758 0 0 0-.098-.387.697.697 0 0 0-.288-.27.892.892 0 0 0-.45-.108H9.69v1.539ZM13.903 13l2.412-6.444h1.395L20.131 13h-1.34l-.54-1.539h-2.467L15.244 13h-1.34Zm3.951-2.655-.567-1.62-.234-.774h-.072l-.234.774-.567 1.62h1.674ZM21.294 13V6.556h1.412l2.592 4.32h.072l-.072-1.242V6.556h1.206V13h-1.278L22.49 8.437h-.072l.072 1.242V13h-1.197Z" fill="#5F6368"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h32v20H0z"/></clipPath></defs></svg> \ No newline at end of file
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc index 8a334a7..bc2e688 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.cc
@@ -678,19 +678,86 @@ const RepeatedPtrField<ExtensionTelemetryReportRequest_SignalInfo>& signals = report_pb.signals(); for (const auto& signal_pb : signals) { - const auto& tabs_execute_script_info_pb = - signal_pb.tabs_execute_script_info(); - const RepeatedPtrField< - ExtensionTelemetryReportRequest_SignalInfo_TabsExecuteScriptInfo_ScriptInfo>& - scripts = tabs_execute_script_info_pb.scripts(); - if (!scripts.empty()) { - ss << " Signal: TabsExecuteScript\n"; - for (const auto& script_pb : scripts) { - ss << " Script hash: " - << base::HexEncode(script_pb.hash().c_str(), - script_pb.hash().size()) - << " count: " << script_pb.execution_count() << "\n"; + // Tabs Execute Script + if (signal_pb.has_tabs_execute_script_info()) { + const auto& tabs_execute_script_info_pb = + signal_pb.tabs_execute_script_info(); + const RepeatedPtrField< + ExtensionTelemetryReportRequest_SignalInfo_TabsExecuteScriptInfo_ScriptInfo>& + scripts = tabs_execute_script_info_pb.scripts(); + if (!scripts.empty()) { + ss << " Signal: TabsExecuteScript\n"; + for (const auto& script_pb : scripts) { + ss << " Script hash: " + << base::HexEncode(script_pb.hash().c_str(), + script_pb.hash().size()) + << " count: " << script_pb.execution_count() << "\n"; + } } + continue; + } + + // Remote Host Contacted + if (signal_pb.has_remote_host_contacted_info()) { + const auto& remote_host_contacted_info_pb = + signal_pb.remote_host_contacted_info(); + const RepeatedPtrField< + ExtensionTelemetryReportRequest_SignalInfo_RemoteHostContactedInfo_RemoteHostInfo>& + remote_host_infos = remote_host_contacted_info_pb.remote_host(); + if (!remote_host_infos.empty()) { + ss << " Signal: RemoteHostContacted\n"; + for (const auto& remote_host_info_pb : remote_host_infos) { + ss << " RemoteHostInfo:\n" + << " URL: " << remote_host_info_pb.url() << "\n" + << " ConnectionProtocal: " + << remote_host_info_pb.connection_protocol() << "\n" + << " count: " << remote_host_info_pb.contact_count() + << "\n"; + } + } + continue; + } + + // Cookies Get All + if (signal_pb.has_cookies_get_all_info()) { + const auto& cookies_get_all_info_pb = signal_pb.cookies_get_all_info(); + const RepeatedPtrField< + ExtensionTelemetryReportRequest_SignalInfo_CookiesGetAllInfo_GetAllArgsInfo>& + get_all_args_infos = cookies_get_all_info_pb.get_all_args_info(); + if (!get_all_args_infos.empty()) { + ss << " Signal: CookiesGetAll\n"; + for (const auto& get_all_args_pb : get_all_args_infos) { + ss << " GetAllArgsInfo:\n" + << " Domain: " << get_all_args_pb.domain() << "\n" + << " Name: " << get_all_args_pb.name() << "\n" + << " Path: " << get_all_args_pb.path() << "\n" + << " Secure: " << get_all_args_pb.secure() << "\n" + << " StoreId: " << get_all_args_pb.store_id() << "\n" + << " URL: " << get_all_args_pb.url() << "\n" + << " IsSession: " << get_all_args_pb.is_session() << "\n" + << " count: " << get_all_args_pb.count() << "\n"; + } + } + continue; + } + + // Cookies Get + if (signal_pb.has_cookies_get_info()) { + const auto& cookies_get_info_pb = signal_pb.cookies_get_info(); + const RepeatedPtrField< + ExtensionTelemetryReportRequest_SignalInfo_CookiesGetInfo_GetArgsInfo>& + get_args_infos = cookies_get_info_pb.get_args_info(); + if (!get_args_infos.empty()) { + ss << " Signal: CookiesGet\n"; + for (const auto& get_args_pb : get_args_infos) { + ss << " GetArgsInfo:\n" + << " Name: " << get_args_pb.name() << "\n" + << " URL: " << get_args_pb.url() << "\n" + << " StoreId: " << get_args_pb.store_id() << "\n" + << " count: " << get_args_pb.count() << "\n"; + } + } + continue; } } }
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h index 73c8ce97..21edf21 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h
@@ -120,6 +120,7 @@ // signal processors. std::unique_ptr<ExtensionTelemetryReportRequest> CreateReport(); + // Dumps a telemetry report in logs for testing. void DumpReportForTest(const ExtensionTelemetryReportRequest& report); // Collects extension information for reporting.
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 0b8e118..e79695f1 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
@@ -11,21 +11,16 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; -import android.app.Activity; -import android.content.Context; -import android.content.ContextWrapper; -import android.content.pm.PackageManager; +import android.content.res.Resources; import android.view.View; -import androidx.test.filters.MediumTest; +import androidx.test.ext.junit.rules.ActivityScenarioRule; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import org.junit.After; import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; @@ -33,20 +28,16 @@ import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; -import org.chromium.base.BuildInfo; -import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.Supplier; -import org.chromium.base.test.util.Batch; -import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.JniMocker; -import org.chromium.base.test.util.PackageManagerWrapper; import org.chromium.base.test.util.UserActionTester; import org.chromium.chrome.R; import org.chromium.chrome.browser.feature_engagement.TrackerFactory; import org.chromium.chrome.browser.flags.ChromeFeatureList; -import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ChromeShareExtras.DetailedContentType; import org.chromium.chrome.browser.share.ShareContentTypeHelper; @@ -57,8 +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.test.ChromeJUnit4ClassRunner; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.AutomotiveContextWrapperTestRule; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features.DisableFeatures; import org.chromium.chrome.test.util.browser.Features.EnableFeatures; @@ -69,10 +59,12 @@ import org.chromium.components.user_prefs.UserPrefs; import org.chromium.components.user_prefs.UserPrefsJni; import org.chromium.content_public.browser.WebContents; -import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.base.TestActivity; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; +import org.chromium.url.JUnitTestGURLs; +import org.chromium.url.ShadowGURL; import java.util.ArrayList; import java.util.List; @@ -80,24 +72,23 @@ /** * Instrumentation Unit tests {@link ChromeProvidedSharingOptionsProvider}. */ -@Batch(Batch.PER_CLASS) -@RunWith(ChromeJUnit4ClassRunner.class) +@RunWith(BaseRobolectricTestRunner.class) @EnableFeatures({ChromeFeatureList.WEBNOTES_STYLIZE}) @DisableFeatures({ChromeFeatureList.UPCOMING_SHARING_FEATURES, ChromeFeatureList.SEND_TAB_TO_SELF_SIGNIN_PROMO}) -@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@Config(shadows = ShadowGURL.class) public class ChromeProvidedSharingOptionsProviderTest { - @ClassRule - public static ChromeTabbedActivityTestRule sActivityTestRule = - new ChromeTabbedActivityTestRule(); - + @Rule + public ActivityScenarioRule<TestActivity> mActivityScenarioRule = + new ActivityScenarioRule<>(TestActivity.class); @Rule public TestRule mFeatureProcessor = new Features.JUnitProcessor(); - @Rule public JniMocker mJniMocker = new JniMocker(); + @Rule + public AutomotiveContextWrapperTestRule mAutoTestRule = new AutomotiveContextWrapperTestRule(); - private static final String URL = "http://www.google.com/"; + private static final String URL = JUnitTestGURLs.EXAMPLE_URL; @Mock private UserPrefs.Natives mUserPrefsNatives; @@ -124,50 +115,13 @@ @Mock private WindowAndroid mWindowAndroid; - private Activity mActivity; + private TestActivity mActivity; private ChromeProvidedSharingOptionsProvider mChromeProvidedSharingOptionsProvider; private UserActionTester mActionTester; - private Context mContextToRestore; - private TestContext mTestContext; - - @BeforeClass - public static void setUpClass() { - sActivityTestRule.startMainActivityOnBlankPage(); - } - - private class TestContext extends ContextWrapper { - private boolean mIsAutomotive; - - public TestContext(Context baseContext) { - super(baseContext); - mIsAutomotive = false; - } - - public void setIsAutomotive(boolean isAutomotive) { - this.mIsAutomotive = isAutomotive; - TestThreadUtils.runOnUiThreadBlocking(BuildInfo::resetForTesting); - } - - @Override - public PackageManager getPackageManager() { - return new PackageManagerWrapper(super.getPackageManager()) { - @Override - public boolean hasSystemFeature(String name) { - if (name.equals(PackageManager.FEATURE_AUTOMOTIVE)) { - return mIsAutomotive; - } - return super.hasSystemFeature(name); - } - }; - } - } - @Before public void setUp() { - mContextToRestore = ContextUtils.getApplicationContext(); - mTestContext = new TestContext(mContextToRestore); - ContextUtils.initApplicationContextForTests(mTestContext); + mActivityScenarioRule.getScenario().onActivity(activity -> mActivity = activity); MockitoAnnotations.initMocks(this); mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsNatives); @@ -184,23 +138,15 @@ Mockito.doNothing().when(mBottomSheetController).hideContent(any(), anyBoolean()); TrackerFactory.setTrackerForTests(mTracker); - mActivity = sActivityTestRule.getActivity(); } @After public void tearDown() throws Exception { - // DisableAnimationTestRule requires an initialized context to do proper teardown. - // This resets to the original context rather than nulling out. - if (mContextToRestore != null) { - ContextUtils.initApplicationContextForTests(mContextToRestore); - } - TestThreadUtils.runOnUiThreadBlocking(BuildInfo::resetForTesting); TrackerFactory.setTrackerForTests(null); if (mActionTester != null) mActionTester.tearDown(); } @Test - @MediumTest public void getPropertyModels_longScreenshotEnabledNoTab_excludesLongScreenshot() { Mockito.when(mTabProvider.hasValue()).thenReturn(false); setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, @@ -216,7 +162,6 @@ } @Test - @MediumTest public void getPropertyModels_printingEnabledNoTab_excludesPrinting() { Mockito.when(mTabProvider.hasValue()).thenReturn(false); setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, @@ -232,7 +177,6 @@ } @Test - @MediumTest public void getPropertyModels_printingEnabled_includesPrinting() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/true, LinkGeneration.MAX); @@ -247,7 +191,6 @@ } @Test - @MediumTest public void getPropertyModels_multiWindow_doesNotIncludeScreenshot() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/false, LinkGeneration.MAX); @@ -263,7 +206,6 @@ } @Test - @MediumTest public void getPropertyModels_isIncognito_doesNotIncludeQrCode() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/true, /*printingEnabled=*/false, LinkGeneration.MAX); @@ -279,7 +221,6 @@ } @Test - @MediumTest public void getPropertyModels_filtersByContentType() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/true, LinkGeneration.MAX); @@ -297,7 +238,6 @@ } @Test - @MediumTest public void getPropertyModels_multipleTypes_filtersByContentType() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/true, LinkGeneration.MAX); @@ -322,7 +262,6 @@ } @Test - @MediumTest public void getPropertyModels_doesNotFilterByDetailedContentType() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/true, LinkGeneration.MAX); @@ -344,7 +283,6 @@ } @Test - @MediumTest public void getPropertyModels_webnotes_filtersByDetailedContentType() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/true, LinkGeneration.MAX); @@ -363,7 +301,6 @@ } @Test - @MediumTest public void getPropertyModels_onClick_callsOnTargetChosen() { setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/false, LinkGeneration.LINK); @@ -382,9 +319,8 @@ } @Test - @MediumTest public void getPropertyModels_onlyReturnValidOptionsForAutomotive() { - mTestContext.setIsAutomotive(true); + mAutoTestRule.setIsAutomotive(true); setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, /*printingEnabled=*/false, LinkGeneration.MAX); @@ -401,6 +337,72 @@ mActivity.getResources().getString(R.string.qr_code_share_icon_label))); } + @Test + public void getPropertyModels_linkAndTextShare() { + setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, + /*printingEnabled=*/false, LinkGeneration.MAX); + + List<PropertyModel> propertyModels = + mChromeProvidedSharingOptionsProvider.getPropertyModels( + ImmutableSet.of(ContentType.LINK_AND_TEXT, + ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.TEXT), + DetailedContentType.NOT_SPECIFIED, + /*isMultiWindow=*/true); + + assertCorrectModelsAreInTheRightOrder(propertyModels, + ImmutableList.of(mActivity.getResources().getString(R.string.sharing_copy), + mActivity.getResources().getString( + R.string.send_tab_to_self_share_activity_title), + mActivity.getResources().getString(R.string.qr_code_share_icon_label))); + } + + @Test + public void getPropertyModels_linkShare() { + setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, + /*printingEnabled=*/false, LinkGeneration.MAX); + + List<PropertyModel> propertyModels = + mChromeProvidedSharingOptionsProvider.getPropertyModels( + ImmutableSet.of(ContentType.LINK_PAGE_NOT_VISIBLE), + DetailedContentType.NOT_SPECIFIED, + /*isMultiWindow=*/true); + + assertCorrectModelsAreInTheRightOrder(propertyModels, + ImmutableList.of(mActivity.getResources().getString(R.string.sharing_copy_url), + mActivity.getResources().getString( + R.string.send_tab_to_self_share_activity_title), + mActivity.getResources().getString(R.string.qr_code_share_icon_label))); + } + + @Test + public void getPropertyModels_textShare() { + setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, + /*printingEnabled=*/false, LinkGeneration.MAX); + + List<PropertyModel> propertyModels = + mChromeProvidedSharingOptionsProvider.getPropertyModels( + ImmutableSet.of(ContentType.TEXT), DetailedContentType.NOT_SPECIFIED, + /*isMultiWindow=*/true); + + assertCorrectModelsAreInTheRightOrder(propertyModels, + ImmutableList.of(mActivity.getResources().getString(R.string.sharing_copy_text))); + } + + @Test + public void getShareDetailsMetrics_linkGeneration() { + @LinkGeneration + int linkGenerationStatus = LinkGeneration.LINK; + + setUpChromeProvidedSharingOptionsProviderTest(/*isIncognito=*/false, + /*printingEnabled=*/false, linkGenerationStatus); + List<PropertyModel> propertyModels = + mChromeProvidedSharingOptionsProvider.getPropertyModels( + ImmutableSet.of(ContentType.HIGHLIGHTED_TEXT), + DetailedContentType.NOT_SPECIFIED, /*isMultiWindow=*/false); + + assertCorrectLinkGenerationMetrics(propertyModels, linkGenerationStatus); + } + private void setUpChromeProvidedSharingOptionsProviderTest(boolean isIncognito, boolean printingEnabled, @LinkGeneration int linkGenerationStatus) { Mockito.when(mPrefService.getBoolean(anyString())).thenReturn(printingEnabled); @@ -448,17 +450,12 @@ mActionTester = new UserActionTester(); View view = Mockito.mock(View.class); for (PropertyModel propertyModel : propertyModels) { - // There is no link generation for Stylize Cards yet. - if (propertyModel.get(ShareSheetItemViewProperties.LABEL) - .equals(mActivity.getResources().getString( - R.string.sharing_webnotes_create_card))) { - continue; - } - - // There is no link generation for Screenshots yet either. - if (propertyModel.get(ShareSheetItemViewProperties.LABEL) - .equals(mActivity.getResources().getString( - R.string.sharing_screenshot))) { + String label = propertyModel.get(ShareSheetItemViewProperties.LABEL); + Resources res = mActivity.getResources(); + // There is no link generation for Stylize Cards / Screenshots / Long Screenshots. + if (label.equals(res.getString(R.string.sharing_webnotes_create_card)) + || label.equals(res.getString(R.string.sharing_screenshot)) + || label.equals(res.getString(R.string.sharing_long_screenshot))) { continue; }
diff --git a/chrome/browser/share/android/test_java_sources.gni b/chrome/browser/share/android/test_java_sources.gni index 565000c..264cd1e 100644 --- a/chrome/browser/share/android/test_java_sources.gni +++ b/chrome/browser/share/android/test_java_sources.gni
@@ -12,7 +12,6 @@ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/scroll_capture/ScrollCaptureCallbackRenderTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfBottomSheetRenderTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinatorTest.java", - "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetTest.java", ] @@ -38,6 +37,7 @@ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/scroll_capture/ScrollCaptureManagerTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/NotificationSharedPrefManagerTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfAndroidBridgeTest.java", + "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetLinkToggleCoordinatorTest.java", "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetUsageRankingHelperTest.java",
diff --git a/chrome/browser/ssl/certificate_reporting_test_utils.cc b/chrome/browser/ssl/certificate_reporting_test_utils.cc index a6d3acc..1c45b7ee 100644 --- a/chrome/browser/ssl/certificate_reporting_test_utils.cc +++ b/chrome/browser/ssl/certificate_reporting_test_utils.cc
@@ -9,6 +9,7 @@ #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "build/build_config.h" @@ -17,7 +18,6 @@ #include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/security_interstitials/content/cert_report_helper.h" #include "components/security_interstitials/content/certificate_error_report.h" -#include "components/variations/variations_associated_data.h" #include "net/url_request/report_sender.h" #include "testing/gtest/include/gtest/gtest.h" @@ -118,9 +118,9 @@ CertReportHelper::kFinchExperimentName); if (group_name == CertReportHelper::kFinchGroupShowPossiblySend) { - const std::string param = variations::GetVariationParamValue( - CertReportHelper::kFinchExperimentName, - CertReportHelper::kFinchParamName); + const std::string param = + base::GetFieldTrialParamValue(CertReportHelper::kFinchExperimentName, + CertReportHelper::kFinchParamName); double sendingThreshold; if (!base::StringToDouble(param, &sendingThreshold)) return CERT_REPORT_NOT_EXPECTED;
diff --git a/chrome/browser/supervised_user/android/web_content_handler_impl.cc b/chrome/browser/supervised_user/android/web_content_handler_impl.cc index c0d053e..4d004464c 100644 --- a/chrome/browser/supervised_user/android/web_content_handler_impl.cc +++ b/chrome/browser/supervised_user/android/web_content_handler_impl.cc
@@ -40,7 +40,6 @@ void WebContentHandlerImpl::RequestLocalApproval( const GURL& url, const std::u16string& child_display_name, - const gfx::ImageSkia& favicon, ApprovalRequestInitiatedCallback callback) { supervised_user::SupervisedUserSettingsService* settings_service = SupervisedUserSettingsServiceFactory::GetForKey(
diff --git a/chrome/browser/supervised_user/android/web_content_handler_impl.h b/chrome/browser/supervised_user/android/web_content_handler_impl.h index 608b142..572cc45 100644 --- a/chrome/browser/supervised_user/android/web_content_handler_impl.h +++ b/chrome/browser/supervised_user/android/web_content_handler_impl.h
@@ -29,7 +29,6 @@ // supervised_user::WebContentHandler: void RequestLocalApproval(const GURL& url, const std::u16string& child_display_name, - const gfx::ImageSkia& favicon, ApprovalRequestInitiatedCallback callback) override; private:
diff --git a/chrome/browser/supervised_user/chromeos/mock_large_icon_service.cc b/chrome/browser/supervised_user/chromeos/mock_large_icon_service.cc new file mode 100644 index 0000000..131cc24 --- /dev/null +++ b/chrome/browser/supervised_user/chromeos/mock_large_icon_service.cc
@@ -0,0 +1,45 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/supervised_user/chromeos/mock_large_icon_service.h" + +#include "base/task/cancelable_task_tracker.h" +#include "components/favicon_base/favicon_types.h" +#include "net/traffic_annotation/network_traffic_annotation.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "ui/gfx/image/image_unittest_util.h" + +using testing::_; + +namespace { +const base::CancelableTaskTracker::TaskId kTaskId = 1; +} // namespace + +MockLargeIconService::MockLargeIconService() { + ON_CALL(*this, GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( + _, _, _, _, _)) + .WillByDefault( + [this](auto, auto, auto, auto, + favicon_base::GoogleFaviconServerCallback callback) { + StoreIconInCache(); + std::move(callback).Run( + favicon_base::GoogleFaviconServerRequestStatus::SUCCESS); + }); + + ON_CALL(*this, GetLargeIconImageOrFallbackStyleForPageUrl(_, _, _, _, _)) + .WillByDefault([this](auto, auto, auto, + favicon_base::LargeIconImageCallback callback, + auto) { + std::move(callback).Run( + favicon_base::LargeIconImageResult(gfx::Image(favicon_), kIconUrl)); + return kTaskId; + }); +} + +MockLargeIconService::~MockLargeIconService() = default; + +void MockLargeIconService::StoreIconInCache() { + SkBitmap bitmap = gfx::test::CreateBitmap(1, 2); + favicon_ = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); +}
diff --git a/chrome/browser/supervised_user/chromeos/mock_large_icon_service.h b/chrome/browser/supervised_user/chromeos/mock_large_icon_service.h new file mode 100644 index 0000000..816479e9 --- /dev/null +++ b/chrome/browser/supervised_user/chromeos/mock_large_icon_service.h
@@ -0,0 +1,67 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_SUPERVISED_USER_CHROMEOS_MOCK_LARGE_ICON_SERVICE_H_ +#define CHROME_BROWSER_SUPERVISED_USER_CHROMEOS_MOCK_LARGE_ICON_SERVICE_H_ + +#include "components/favicon/core/large_icon_service.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/image/image_skia.h" +#include "url/gurl.h" + +class MockLargeIconService : public favicon::LargeIconService { + public: + MockLargeIconService(); + + MockLargeIconService(const MockLargeIconService&) = delete; + MockLargeIconService& operator=(const MockLargeIconService&) = delete; + ~MockLargeIconService() override; + + void StoreIconInCache(); + + gfx::ImageSkia favicon() const { return favicon_; } + + // LargeIconService overrides. + MOCK_METHOD5(GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache, + void(const GURL& page_url, + bool may_page_url_be_private, + bool should_trim_page_url_path, + const net::NetworkTrafficAnnotationTag& traffic_annotation, + favicon_base::GoogleFaviconServerCallback callback)); + MOCK_METHOD5(GetLargeIconRawBitmapOrFallbackStyleForPageUrl, + base::CancelableTaskTracker::TaskId( + const GURL& page_url, + int min_source_size_in_pixel, + int desired_size_in_pixel, + favicon_base::LargeIconCallback callback, + base::CancelableTaskTracker* tracker)); + MOCK_METHOD5(GetLargeIconImageOrFallbackStyleForPageUrl, + base::CancelableTaskTracker::TaskId( + const GURL& page_url, + int min_source_size_in_pixel, + int desired_size_in_pixel, + favicon_base::LargeIconImageCallback callback, + base::CancelableTaskTracker* tracker)); + MOCK_METHOD5(GetLargeIconRawBitmapOrFallbackStyleForIconUrl, + base::CancelableTaskTracker::TaskId( + const GURL& icon_url, + int min_source_size_in_pixel, + int desired_size_in_pixel, + favicon_base::LargeIconCallback callback, + base::CancelableTaskTracker* tracker)); + MOCK_METHOD4(GetIconRawBitmapOrFallbackStyleForPageUrl, + base::CancelableTaskTracker::TaskId( + const GURL& page_url, + int desired_size_in_pixel, + favicon_base::LargeIconCallback callback, + base::CancelableTaskTracker* tracker)); + MOCK_METHOD1(TouchIconFromGoogleServer, void(const GURL& icon_url)); + + const GURL kIconUrl = GURL("https://www.example.com/icon"); + + private: + gfx::ImageSkia favicon_; +}; + +#endif // CHROME_BROWSER_SUPERVISED_USER_CHROMEOS_MOCK_LARGE_ICON_SERVICE_H_
diff --git a/chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler_unittest.cc b/chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler_unittest.cc index 47e68da..52a9dcb 100644 --- a/chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler_unittest.cc +++ b/chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler_unittest.cc
@@ -8,6 +8,7 @@ #include "base/task/cancelable_task_tracker.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" +#include "chrome/browser/supervised_user/chromeos/mock_large_icon_service.h" #include "components/favicon/core/large_icon_service.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "testing/gmock/include/gmock/gmock.h" @@ -18,87 +19,6 @@ using testing::_; -namespace { -const base::CancelableTaskTracker::TaskId kTaskId = 1; -} // namespace - -class MockLargeIconService : public favicon::LargeIconService { - public: - MockLargeIconService() { - ON_CALL(*this, - GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache( - _, _, _, _, _)) - .WillByDefault( - [this](auto, auto, auto, auto, - favicon_base::GoogleFaviconServerCallback callback) { - StoreIconInCache(); - std::move(callback).Run( - favicon_base::GoogleFaviconServerRequestStatus::SUCCESS); - }); - - ON_CALL(*this, GetLargeIconImageOrFallbackStyleForPageUrl(_, _, _, _, _)) - .WillByDefault([this](auto, auto, auto, - favicon_base::LargeIconImageCallback callback, - auto) { - std::move(callback).Run(favicon_base::LargeIconImageResult( - gfx::Image(favicon_), kIconUrl)); - return kTaskId; - }); - } - - MockLargeIconService(const MockLargeIconService&) = delete; - MockLargeIconService& operator=(const MockLargeIconService&) = delete; - ~MockLargeIconService() override = default; - - void StoreIconInCache() { - SkBitmap bitmap = gfx::test::CreateBitmap(1, 2); - favicon_ = gfx::ImageSkia::CreateFrom1xBitmap(bitmap); - } - - gfx::ImageSkia favicon() const { return favicon_; } - - // LargeIconService overrides. - MOCK_METHOD5(GetLargeIconOrFallbackStyleFromGoogleServerSkippingLocalCache, - void(const GURL& page_url, - bool may_page_url_be_private, - bool should_trim_page_url_path, - const net::NetworkTrafficAnnotationTag& traffic_annotation, - favicon_base::GoogleFaviconServerCallback callback)); - MOCK_METHOD5(GetLargeIconRawBitmapOrFallbackStyleForPageUrl, - base::CancelableTaskTracker::TaskId( - const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, - favicon_base::LargeIconCallback callback, - base::CancelableTaskTracker* tracker)); - MOCK_METHOD5(GetLargeIconImageOrFallbackStyleForPageUrl, - base::CancelableTaskTracker::TaskId( - const GURL& page_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, - favicon_base::LargeIconImageCallback callback, - base::CancelableTaskTracker* tracker)); - MOCK_METHOD5(GetLargeIconRawBitmapOrFallbackStyleForIconUrl, - base::CancelableTaskTracker::TaskId( - const GURL& icon_url, - int min_source_size_in_pixel, - int desired_size_in_pixel, - favicon_base::LargeIconCallback callback, - base::CancelableTaskTracker* tracker)); - MOCK_METHOD4(GetIconRawBitmapOrFallbackStyleForPageUrl, - base::CancelableTaskTracker::TaskId( - const GURL& page_url, - int desired_size_in_pixel, - favicon_base::LargeIconCallback callback, - base::CancelableTaskTracker* tracker)); - MOCK_METHOD1(TouchIconFromGoogleServer, void(const GURL& icon_url)); - - const GURL kIconUrl = GURL("https://www.example.com/icon"); - - private: - gfx::ImageSkia favicon_; -}; - class SupervisedUserFaviconRequestHandlerTest : public ::testing::Test { public: SupervisedUserFaviconRequestHandlerTest() = default;
diff --git a/chrome/browser/supervised_user/chromeos/web_content_handler_impl.cc b/chrome/browser/supervised_user/chromeos/web_content_handler_impl.cc index c0ef8684..70e3740 100644 --- a/chrome/browser/supervised_user/chromeos/web_content_handler_impl.cc +++ b/chrome/browser/supervised_user/chromeos/web_content_handler_impl.cc
@@ -12,9 +12,13 @@ #include "chrome/browser/ash/crosapi/parent_access_ash.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" +#include "chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" +#include "components/favicon/core/large_icon_service.h" #include "components/supervised_user/core/browser/supervised_user_settings_service.h" +#include "components/supervised_user/core/common/features.h" #include "content/public/browser/web_contents.h" +#include "ui/gfx/image/image_skia.h" namespace { @@ -57,15 +61,28 @@ } // namespace -WebContentHandlerImpl::WebContentHandlerImpl(content::WebContents& web_contents) - : web_contents_(web_contents) {} +WebContentHandlerImpl::WebContentHandlerImpl( + content::WebContents& web_contents, + const GURL& url, + favicon::LargeIconService& large_icon_service) + : web_contents_(web_contents), + favicon_handler_(std::make_unique<SupervisedUserFaviconRequestHandler>( + url.GetWithEmptyPath(), + &large_icon_service)) { + if (supervised_user::IsLocalWebApprovalsEnabled()) { + // Prefetch the favicon which will be rendered as part of the web approvals + // ParentAccessDialog. Pass in DoNothing() for the favicon fetched callback + // because if the favicon is by the time the user triggers the opening of + // the ParentAccessDialog, we show the default favicon. + favicon_handler_->StartFaviconFetch(base::DoNothing()); + } +} WebContentHandlerImpl::~WebContentHandlerImpl() = default; void WebContentHandlerImpl::RequestLocalApproval( const GURL& url, const std::u16string& child_display_name, - const gfx::ImageSkia& favicon, ApprovalRequestInitiatedCallback callback) { supervised_user::SupervisedUserSettingsService* settings_service = SupervisedUserSettingsServiceFactory::GetForKey( @@ -76,6 +93,8 @@ crosapi::CrosapiManager::Get()->crosapi_ash()->parent_access_ash(); DCHECK(parent_access); + gfx::ImageSkia favicon = favicon_handler_->GetFaviconOrFallback(); + parent_access->GetWebsiteParentApproval( url.GetWithEmptyPath(), child_display_name, favicon, base::BindOnce(&WebContentHandlerImpl::OnLocalApprovalRequestCompleted,
diff --git a/chrome/browser/supervised_user/chromeos/web_content_handler_impl.h b/chrome/browser/supervised_user/chromeos/web_content_handler_impl.h index 7a58ea55..fe6b0565 100644 --- a/chrome/browser/supervised_user/chromeos/web_content_handler_impl.h +++ b/chrome/browser/supervised_user/chromeos/web_content_handler_impl.h
@@ -19,10 +19,18 @@ class WebContents; } // namespace content +namespace favicon { +class LargeIconService; +} // namespace favicon + +class SupervisedUserFaviconRequestHandler; + // Chrome Ash specific implementation of web content handler. class WebContentHandlerImpl : public supervised_user::WebContentHandler { public: - explicit WebContentHandlerImpl(content::WebContents& web_contents); + WebContentHandlerImpl(content::WebContents& web_contents, + const GURL& url, + favicon::LargeIconService& large_icon_service); WebContentHandlerImpl(const WebContentHandlerImpl&) = delete; WebContentHandlerImpl& operator=(const WebContentHandlerImpl&) = delete; @@ -31,7 +39,6 @@ // supervised_user::WebContentHandler: void RequestLocalApproval(const GURL& url, const std::u16string& child_display_name, - const gfx::ImageSkia& favicon, ApprovalRequestInitiatedCallback callback) override; private: @@ -52,6 +59,7 @@ LocalWebApprovalErrorChromeOSTest); const raw_ref<content::WebContents> web_contents_; + std::unique_ptr<SupervisedUserFaviconRequestHandler> favicon_handler_; base::WeakPtrFactory<WebContentHandlerImpl> weak_ptr_factory_{this}; };
diff --git a/chrome/browser/supervised_user/chromeos/web_content_handler_impl_unittest.cc b/chrome/browser/supervised_user/chromeos/web_content_handler_impl_unittest.cc index 057fbec..3c60589 100644 --- a/chrome/browser/supervised_user/chromeos/web_content_handler_impl_unittest.cc +++ b/chrome/browser/supervised_user/chromeos/web_content_handler_impl_unittest.cc
@@ -9,6 +9,8 @@ #include "base/test/metrics/histogram_tester.h" #include "base/time/time.h" +#include "chrome/browser/supervised_user/chromeos/mock_large_icon_service.h" +#include "chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler.h" #include "chromeos/crosapi/mojom/parent_access.mojom.h" #include "components/supervised_user/core/browser/supervised_user_settings_service.h" #include "content/public/test/browser_task_environment.h" @@ -39,9 +41,13 @@ return task_environment_; } + MockLargeIconService& large_icon_service() { return large_icon_service_; } + private: content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + MockLargeIconService large_icon_service_; }; TEST_F(WebContentHandlerImplTest, LocalWebApprovalApprovedChromeOSTest) { @@ -63,8 +69,11 @@ const base::TimeDelta approval_duration = base::Seconds(35); task_environment().FastForwardBy(approval_duration); + // TODO(b/273692421): The content will need to be a raw_ptr. content::WebContents* content = nullptr; - WebContentHandlerImpl web_content_handler = WebContentHandlerImpl(*content); + WebContentHandlerImpl web_content_handler(*content, url, + large_icon_service()); + web_content_handler.OnLocalApprovalRequestCompleted( supervisedUserSettingsServiceMock, url, start_time, std::move(result)); @@ -100,8 +109,11 @@ const base::TimeDelta approval_duration = base::Seconds(35); task_environment().FastForwardBy(approval_duration); + // TODO(b/273692421): The content will need to be a raw_ptr. content::WebContents* content = nullptr; - WebContentHandlerImpl web_content_handler = WebContentHandlerImpl(*content); + WebContentHandlerImpl web_content_handler(*content, url, + large_icon_service()); + web_content_handler.OnLocalApprovalRequestCompleted( supervisedUserSettingsServiceMock, url, start_time, std::move(result)); @@ -137,8 +149,11 @@ const base::TimeDelta approval_duration = base::Seconds(35); task_environment().FastForwardBy(approval_duration); + // TODO(b/273692421): The content will need to be a raw_ptr. content::WebContents* content = nullptr; - WebContentHandlerImpl web_content_handler = WebContentHandlerImpl(*content); + WebContentHandlerImpl web_content_handler(*content, url, + large_icon_service()); + web_content_handler.OnLocalApprovalRequestCompleted( supervisedUserSettingsServiceMock, url, start_time, std::move(result)); @@ -172,8 +187,11 @@ const base::TimeDelta approval_duration = base::Seconds(35); task_environment().FastForwardBy(approval_duration); + // TODO(b/273692421): The content will need to be a raw_ptr. content::WebContents* content = nullptr; - WebContentHandlerImpl web_content_handler = WebContentHandlerImpl(*content); + WebContentHandlerImpl web_content_handler(*content, url, + large_icon_service()); + web_content_handler.OnLocalApprovalRequestCompleted( supervisedUserSettingsServiceMock, url, start_time, std::move(result));
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.cc b/chrome/browser/supervised_user/supervised_user_interstitial.cc index 750f3bd8..e814095 100644 --- a/chrome/browser/supervised_user/supervised_user_interstitial.cc +++ b/chrome/browser/supervised_user/supervised_user_interstitial.cc
@@ -38,7 +38,6 @@ #include "content/public/browser/web_contents_user_data.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" -#include "ui/gfx/image/image_skia.h" #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/supervised_user/child_accounts/child_account_feedback_reporter_android.h" @@ -54,10 +53,6 @@ #include "components/user_manager/user_manager.h" #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chrome/browser/supervised_user/chromeos/supervised_user_favicon_request_handler.h" -#endif - using content::WebContents; namespace { @@ -159,7 +154,6 @@ WebContents* web_contents, std::unique_ptr<supervised_user::WebContentHandler> web_content_handler, SupervisedUserService& supervised_user_service, - favicon::LargeIconService* large_icon_service, const GURL& url, supervised_user::FilteringBehaviorReason reason, int frame_id, @@ -167,8 +161,7 @@ std::unique_ptr<SupervisedUserInterstitial> interstitial = base::WrapUnique(new SupervisedUserInterstitial( web_contents, std::move(web_content_handler), supervised_user_service, - large_icon_service, url, reason, frame_id, - interstitial_navigation_id)); + url, reason, frame_id, interstitial_navigation_id)); if (web_contents->GetPrimaryMainFrame()->GetFrameTreeNodeId() == frame_id) CleanUpInfoBar(web_contents); @@ -181,31 +174,17 @@ WebContents* web_contents, std::unique_ptr<supervised_user::WebContentHandler> web_content_handler, SupervisedUserService& supervised_user_service, - favicon::LargeIconService* large_icon_service, const GURL& url, supervised_user::FilteringBehaviorReason reason, int frame_id, int64_t interstitial_navigation_id) : supervised_user_service_(supervised_user_service), - large_icon_service_(large_icon_service), web_content_handler_(std::move(web_content_handler)), web_contents_(web_contents), url_(url), reason_(reason), frame_id_(frame_id), - interstitial_navigation_id_(interstitial_navigation_id) { -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) - if (supervised_user::IsLocalWebApprovalsEnabled()) { - favicon_handler_ = std::make_unique<SupervisedUserFaviconRequestHandler>( - url_.GetWithEmptyPath(), large_icon_service_); - // Prefetch the favicon which will be rendered as part of the web approvals - // ParentAccessDialog. Pass in DoNothing() for the favicon fetched callback - // because if the favicon is by the time the user triggers the opening of - // the ParentAccessDialog, we show the default favicon. - favicon_handler_->StartFaviconFetch(base::DoNothing()); - } -#endif -} + interstitial_navigation_id_(interstitial_navigation_id) {} SupervisedUserInterstitial::~SupervisedUserInterstitial() {} @@ -268,12 +247,8 @@ Commands::HISTOGRAM_BOUNDING_VALUE); OutputRequestPermissionSourceMetric(); - gfx::ImageSkia favicon; -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) - favicon = favicon_handler_->GetFaviconOrFallback(); -#endif web_content_handler_->RequestLocalApproval(url_, GetActiveUserFirstName(), - favicon, std::move(callback)); + std::move(callback)); } void SupervisedUserInterstitial::ShowFeedback() {
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.h b/chrome/browser/supervised_user/supervised_user_interstitial.h index 42dd4cd..43ceb38 100644 --- a/chrome/browser/supervised_user/supervised_user_interstitial.h +++ b/chrome/browser/supervised_user/supervised_user_interstitial.h
@@ -23,17 +23,9 @@ class WebContentHandler; } -namespace favicon { -class LargeIconService; -} // namespace favicon - class PrefService; class SupervisedUserService; -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) -class SupervisedUserFaviconRequestHandler; -#endif - // This class is used by SupervisedUserNavigationObserver to handle requests // from supervised user error page. The error page is shown when a page is // blocked because it is on a denylist (in "allow everything" mode), not on any @@ -87,7 +79,6 @@ content::WebContents* web_contents, std::unique_ptr<supervised_user::WebContentHandler> web_content_handler, SupervisedUserService& supervised_user_service, - favicon::LargeIconService* large_icon_service, const GURL& url, supervised_user::FilteringBehaviorReason reason, int frame_id, @@ -118,7 +109,6 @@ content::WebContents* web_contents, std::unique_ptr<supervised_user::WebContentHandler> web_content_handler, SupervisedUserService& supervised_user_service, - favicon::LargeIconService* large_icon_service, const GURL& url, supervised_user::FilteringBehaviorReason reason, int frame_id, @@ -133,10 +123,6 @@ const raw_ref<SupervisedUserService> supervised_user_service_; - // Can be null depending on the Platform. An actual instance - // is needed only for local web approvals on Chrome OS. - const raw_ptr<favicon::LargeIconService> large_icon_service_; - std::unique_ptr<supervised_user::WebContentHandler> web_content_handler_; // Owns SupervisedUserNavigationObserver which owns us. @@ -151,10 +137,6 @@ // The Navigation ID of the navigation that last triggered the interstitial. int64_t interstitial_navigation_id_; - -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) - std::unique_ptr<SupervisedUserFaviconRequestHandler> favicon_handler_; -#endif }; #endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_INTERSTITIAL_H_
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_observer.cc b/chrome/browser/supervised_user/supervised_user_navigation_observer.cc index bcd8ef3..7aef1db 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_observer.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_observer.cc
@@ -35,6 +35,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" +#include "url/gurl.h" #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/supervised_user/android/web_content_handler_impl.h" @@ -47,9 +48,13 @@ namespace { std::unique_ptr<supervised_user::WebContentHandler> CreateWebContentHandler( - content::WebContents* web_contents) { + content::WebContents* web_contents, + GURL url, + Profile* profile) { #if BUILDFLAG(IS_CHROMEOS_ASH) - return std::make_unique<WebContentHandlerImpl>(*web_contents); + return std::make_unique<WebContentHandlerImpl>( + *web_contents, url, + *LargeIconServiceFactory::GetForBrowserContext(profile)); #elif BUILDFLAG(IS_ANDROID) return std::make_unique<WebContentHandlerImpl>(*web_contents); #else @@ -307,10 +312,8 @@ Profile::FromBrowserContext(web_contents()->GetBrowserContext()); std::unique_ptr<SupervisedUserInterstitial> interstitial = SupervisedUserInterstitial::Create( - web_contents(), CreateWebContentHandler(web_contents()), - *supervised_user_service_, - LargeIconServiceFactory::GetForBrowserContext(profile), url, reason, - frame_id, navigation_id); + web_contents(), CreateWebContentHandler(web_contents(), url, profile), + *supervised_user_service_, url, reason, frame_id, navigation_id); supervised_user_interstitials_[frame_id] = std::move(interstitial);
diff --git a/chrome/browser/ui/android/webid/account_selection_view_android.cc b/chrome/browser/ui/android/webid/account_selection_view_android.cc index ed6cb1b..77d4297 100644 --- a/chrome/browser/ui/android/webid/account_selection_view_android.cc +++ b/chrome/browser/ui/android/webid/account_selection_view_android.cc
@@ -155,6 +155,24 @@ // TODO(crbug.com/1357790): add support on Android. } +std::string AccountSelectionViewAndroid::GetTitle() const { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> title = + Java_AccountSelectionBridge_getTitle(env, java_object_internal_); + CHECK(title); + return ConvertJavaStringToUTF8(title); +} + +absl::optional<std::string> AccountSelectionViewAndroid::GetSubtitle() const { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jstring> subtitle = + Java_AccountSelectionBridge_getSubtitle(env, java_object_internal_); + if (!subtitle) { + return absl::nullopt; + } + return ConvertJavaStringToUTF8(subtitle); +} + void AccountSelectionViewAndroid::OnAccountSelected( JNIEnv* env, const JavaParamRef<jobject>& idp_config_url,
diff --git a/chrome/browser/ui/android/webid/account_selection_view_android.h b/chrome/browser/ui/android/webid/account_selection_view_android.h index 8daab35..b7d4403 100644 --- a/chrome/browser/ui/android/webid/account_selection_view_android.h +++ b/chrome/browser/ui/android/webid/account_selection_view_android.h
@@ -29,6 +29,8 @@ const std::string& top_frame_for_display, const std::string& idp_for_display, const content::IdentityProviderMetadata& idp_metadata) override; + std::string GetTitle() const override; + absl::optional<std::string> GetSubtitle() const override; void OnAccountSelected( JNIEnv* env,
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java index 6cf212de..7d8b6be 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionBridge.java
@@ -92,6 +92,16 @@ Arrays.asList(accounts), idpMetadata, clientIdMetadata, isAutoReauthn); } + @CalledByNative + private String getTitle() { + return mAccountSelectionComponent.getTitle(); + } + + @CalledByNative + private String getSubtitle() { + return mAccountSelectionComponent.getSubtitle(); + } + @Override public void onDismissed(@IdentityRequestDialogDismissReason int dismissReason) { if (mNativeView != 0) {
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java index 45c4a18..e154acf2 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java
@@ -9,6 +9,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; +import android.widget.TextView; import androidx.annotation.Px; import androidx.recyclerview.widget.LinearLayoutManager; @@ -125,4 +126,17 @@ public void close() { mMediator.close(); } + + @Override + public String getTitle() { + TextView title = mBottomSheetContent.getContentView().findViewById(R.id.header_title); + return String.valueOf(title.getText()); + } + + @Override + public String getSubtitle() { + TextView subtitle = mBottomSheetContent.getContentView().findViewById(R.id.header_subtitle); + if (subtitle == null || subtitle.getText().length() == 0) return null; + return String.valueOf(subtitle.getText()); + } }
diff --git a/chrome/browser/ui/android/webid/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionComponent.java b/chrome/browser/ui/android/webid/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionComponent.java index 33253106..fa35208 100644 --- a/chrome/browser/ui/android/webid/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionComponent.java +++ b/chrome/browser/ui/android/webid/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionComponent.java
@@ -53,4 +53,13 @@ * Closes the outstanding bottom sheet. */ void close(); + + /** + * Gets the sheet's title. + */ + String getTitle(); + /** + * Gets the sheet's subtitle, if any, or null.. + */ + String getSubtitle(); }
diff --git a/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc b/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc index 63f94db..7bb17cf 100644 --- a/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc +++ b/chrome/browser/ui/ash/projector/pending_screencast_manager_browsertest.cc
@@ -97,7 +97,8 @@ public: PendingScreencastMangerBrowserTest() { scoped_feature_list_.InitWithFeatures( - {features::kProjectorUpdateIndexableText}, {}); + {features::kProjectorUpdateIndexableText}, + {ash::features::kFilesInlineSyncStatus}); } PendingScreencastMangerBrowserTest( const PendingScreencastMangerBrowserTest&) = delete; @@ -133,8 +134,9 @@ virtual drive::DriveIntegrationService* CreateDriveIntegrationService( Profile* profile) { // Ignore non-user profile. - if (!ProfileHelper::IsUserProfile(profile)) + if (!ProfileHelper::IsUserProfile(profile)) { return nullptr; + } base::ScopedAllowBlockingForTesting allow_blocking; base::FilePath mount_path = profile->GetPath().Append("drivefs"); @@ -336,6 +338,7 @@ } base::HistogramTester histogram_tester_; + base::test::ScopedFeatureList scoped_feature_list_; private: void WaitBlockingTaskRunnerFinish() { @@ -344,7 +347,6 @@ FROM_HERE, run_loop.QuitClosure()); run_loop.Run(); } - base::test::ScopedFeatureList scoped_feature_list_; drive::DriveIntegrationServiceFactory::FactoryCallback create_drive_integration_service_;
diff --git a/chrome/browser/ui/ash/projector/screencast_manager_browsertest.cc b/chrome/browser/ui/ash/projector/screencast_manager_browsertest.cc index 7b69ec9..19786ff 100644 --- a/chrome/browser/ui/ash/projector/screencast_manager_browsertest.cc +++ b/chrome/browser/ui/ash/projector/screencast_manager_browsertest.cc
@@ -4,6 +4,7 @@ #include <memory> +#include "ash/constants/ash_features.h" #include "ash/webui/projector_app/buildflags.h" #include "ash/webui/projector_app/projector_app_client.h" #include "ash/webui/projector_app/projector_screencast.h" @@ -77,6 +78,11 @@ class ScreencastManagerTestWithDriveFs : public ScreencastManagerTest { public: + ScreencastManagerTestWithDriveFs() { + scoped_feature_list_.InitWithFeatures( + {}, {ash::features::kFilesInlineSyncStatus}); + } + // ScreencastManagerTest: void SetUpInProcessBrowserTestFixture() override { ScreencastManagerTest::SetUpInProcessBrowserTestFixture(); @@ -120,8 +126,9 @@ const base::FilePath& absolute_path = GetTestFile(title, /*relative=*/false); // Writes a file with `kTestFileContents` if path doesn't exist. - if (!base::PathExists(absolute_path)) + if (!base::PathExists(absolute_path)) { EXPECT_TRUE(base::WriteFile(absolute_path, kTestFileContents)); + } const base::FilePath& relative_path = GetTestFile(title, /*relative=*/true); fake->SetMetadata(relative_path, content_type, title, false, false, @@ -171,6 +178,8 @@ } protected: + base::test::ScopedFeatureList scoped_feature_list_; + drivefs::FakeDriveFs* GetFakeDriveFsForProfile(Profile* profile) { return &fake_drivefs_helpers_[profile]->fake_drivefs(); }
diff --git a/chrome/browser/ui/popup_browsertest.cc b/chrome/browser/ui/popup_browsertest.cc index 2724fed..b9cebda9 100644 --- a/chrome/browser/ui/popup_browsertest.cc +++ b/chrome/browser/ui/popup_browsertest.cc
@@ -7,10 +7,13 @@ #include "base/command_line.h" #include "base/memory/raw_ptr.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h" +#include "chrome/browser/ui/exclusive_access/fullscreen_controller.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" @@ -19,6 +22,8 @@ #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" +#include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/features_generated.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/display/screen_base.h" @@ -327,6 +332,11 @@ : public PopupBrowserTest, public ::testing::WithParamInterface<bool> { public: + WindowManagementPopupBrowserTest() { + scoped_feature_list_.InitWithFeatures( + {blink::features::kFullscreenPopupWindows}, {}); + } + void TearDownOnMainThread() override { #if BUILDFLAG(IS_MAC) virtual_display_util_.reset(); @@ -418,6 +428,8 @@ } private: + base::test::ScopedFeatureList scoped_feature_list_; + #if BUILDFLAG(IS_MAC) std::unique_ptr<display::test::VirtualDisplayMacUtil> virtual_display_util_; #endif @@ -492,4 +504,157 @@ display::Screen::SetScreenInstance(nullptr); #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_MAC) } + +IN_PROC_BROWSER_TEST_P(WindowManagementPopupBrowserTest, BasicFullscreen) { + SetUpWebServer(); + SetUpWindowManagement(); + Browser* new_popup = + OpenPopup(browser(), "open('/empty.html', '_blank', 'popup,fullscreen')"); + content::WebContents* new_contents = + new_popup->tab_strip_model()->GetActiveWebContents(); + if (ShouldTestWindowManagement()) { + WaitForHTMLFullscreen(new_contents); + } + EXPECT_EQ(EvalJs(new_contents, + "!!document.fullscreenElement && document.fullscreenElement " + "== document.documentElement") + .ExtractBool(), + ShouldTestWindowManagement()); + FullscreenController* fullscreen_controller = + new_popup->exclusive_access_manager()->fullscreen_controller(); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_EQ(fullscreen_controller->IsTabFullscreen(), + ShouldTestWindowManagement()); + EXPECT_EQ(EvalJs(new_contents, "document.exitFullscreen()").error.empty(), + ShouldTestWindowManagement()); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_FALSE(fullscreen_controller->IsTabFullscreen()); + + // Test that a navigation doesn't re-trigger fullscreen. + EXPECT_TRUE(EvalJs(new_contents, + "window.location.href = '" + + embedded_test_server()->GetURL("/title1.html").spec() + + "'") + .error.empty()); + EXPECT_TRUE(content::WaitForLoadStop(new_contents)); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_FALSE(fullscreen_controller->IsTabFullscreen()); +} + +IN_PROC_BROWSER_TEST_P(WindowManagementPopupBrowserTest, FullscreenWithBounds) { + SetUpWebServer(); + SetUpWindowManagement(); + Browser* new_popup = + OpenPopup(browser(), + "open('/empty.html', '_blank', " + "'height=200,width=200,top=100,left=100,fullscreen')"); + content::WebContents* new_contents = + new_popup->tab_strip_model()->GetActiveWebContents(); + if (ShouldTestWindowManagement()) { + WaitForHTMLFullscreen(new_contents); + } + EXPECT_EQ(EvalJs(new_contents, + "!!document.fullscreenElement && document.fullscreenElement " + "== document.documentElement") + .ExtractBool(), + ShouldTestWindowManagement()); + FullscreenController* fullscreen_controller = + new_popup->exclusive_access_manager()->fullscreen_controller(); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_EQ(fullscreen_controller->IsTabFullscreen(), + ShouldTestWindowManagement()); +} + +// Fullscreen should not work if the new window is not specified as a popup. +IN_PROC_BROWSER_TEST_P(WindowManagementPopupBrowserTest, + FullscreenRequiresPopupWindowFeature) { + SetUpWebServer(); + SetUpWindowManagement(); + + // OpenPopup() cannot be used here since it waits for a new browser which + // would not open in this case. + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE( + EvalJs(web_contents, "open('/empty.html', '_blank', 'fullscreen')") + .error.empty()); + EXPECT_EQ(browser()->tab_strip_model()->count(), 2); + EXPECT_FALSE( + EvalJs(web_contents, "!!document.fullscreenElement").ExtractBool()); + FullscreenController* fullscreen_controller = + browser()->exclusive_access_manager()->fullscreen_controller(); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_FALSE(fullscreen_controller->IsTabFullscreen()); +} + +// Tests that the fullscreen flag is ignored if the window.open() does not +// result in a new window. +IN_PROC_BROWSER_TEST_P(WindowManagementPopupBrowserTest, + FullscreenRequiresNewWindow) { + SetUpWebServer(); + SetUpWindowManagement(); + + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/iframe.html"))); + // OpenPopup() cannot be used here since it waits for a new browser which + // would not open in this case. open() targeting a frame named "test" in + // "iframe.html" will not create a new window. + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_TRUE( + EvalJs(web_contents, "open('/empty.html', 'test', 'popup,fullscreen')") + .error.empty()); + EXPECT_EQ(browser()->tab_strip_model()->count(), 1); + EXPECT_FALSE( + EvalJs(web_contents, "!!document.fullscreenElement").ExtractBool()); + FullscreenController* fullscreen_controller = + browser()->exclusive_access_manager()->fullscreen_controller(); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_FALSE(fullscreen_controller->IsTabFullscreen()); +} + +IN_PROC_BROWSER_TEST_P(WindowManagementPopupBrowserTest, + FullscreenDifferentScreen) { + if (!SetUpVirtualDisplays()) { + GTEST_SKIP() << "Virtual displays not supported on this platform."; + } + SetUpWebServer(); + SetUpWindowManagement(); + + // Falls back to opening a popup on the current screen in testing scenarios + // where window management is not granted in SetUpWindowManagement(). + Browser* new_popup = OpenPopup(browser(), R"JS( + (() => + { + otherScreen = (!!window.screenDetails && screenDetails.screens + .find(s => s != screenDetails.currentScreen)) || window.screen; + return open('/empty.html', '_blank', + `top=${otherScreen.availTop}, + left=${otherScreen.availLeft}, + height=200, + width=200, + popup, + fullscreen`); + })() + )JS"); + + content::WebContents* new_contents = + new_popup->tab_strip_model()->GetActiveWebContents(); + if (ShouldTestWindowManagement()) { + WaitForHTMLFullscreen(new_contents); + } + EXPECT_EQ(EvalJs(new_contents, + "!!document.fullscreenElement && " + "document.fullscreenElement == document.documentElement") + .ExtractBool(), + ShouldTestWindowManagement()); + EXPECT_TRUE(EvalJs(new_contents, + "screen.availLeft == opener.otherScreen.availLeft && " + "screen.availTop == opener.otherScreen.availTop") + .ExtractBool()); + FullscreenController* fullscreen_controller = + new_popup->exclusive_access_manager()->fullscreen_controller(); + EXPECT_FALSE(fullscreen_controller->IsFullscreenForBrowser()); + EXPECT_EQ(fullscreen_controller->IsTabFullscreen(), + ShouldTestWindowManagement()); +} + } // namespace
diff --git a/chrome/browser/ui/quick_answers/BUILD.gn b/chrome/browser/ui/quick_answers/BUILD.gn index 137ac06..28817d9 100644 --- a/chrome/browser/ui/quick_answers/BUILD.gn +++ b/chrome/browser/ui/quick_answers/BUILD.gn
@@ -20,6 +20,8 @@ "ui/quick_answers_view.h", "ui/rich_answers_pre_target_handler.cc", "ui/rich_answers_pre_target_handler.h", + "ui/rich_answers_translation_view.cc", + "ui/rich_answers_translation_view.h", "ui/rich_answers_view.cc", "ui/rich_answers_view.h", "ui/user_consent_view.cc",
diff --git a/chrome/browser/ui/quick_answers/quick_answers_browsertest.cc b/chrome/browser/ui/quick_answers/quick_answers_browsertest.cc index 6f3bbc8..b2a0a4ca 100644 --- a/chrome/browser/ui/quick_answers/quick_answers_browsertest.cc +++ b/chrome/browser/ui/quick_answers/quick_answers_browsertest.cc
@@ -16,16 +16,20 @@ #include "chrome/browser/notifications/notification_display_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/quick_answers/quick_answers_browsertest_base.h" +#include "chrome/browser/ui/quick_answers/quick_answers_controller_impl.h" #include "chrome/browser/ui/quick_answers/ui/quick_answers_view.h" #include "chrome/browser/ui/quick_answers/ui/rich_answers_view.h" #include "chrome/browser/ui/quick_answers/ui/user_consent_view.h" #include "chrome/test/base/chrome_test_utils.h" #include "chrome/test/base/in_process_browser_test.h" #include "chromeos/components/quick_answers/public/cpp/quick_answers_prefs.h" +#include "chromeos/components/quick_answers/quick_answers_model.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/strings/grit/chromeos_strings.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "third_party/skia/include/core/SkBitmap.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/events/test/event_generator.h" #include "ui/gfx/geometry/rect.h" #include "ui/message_center/public/cpp/notification.h" @@ -225,6 +229,21 @@ quick_answers_view_widget_waiter.WaitIfNeededAndGet(); ASSERT_TRUE(quick_answers_view_widget != nullptr); + // Simulate having received a valid QuickAnswer response, which is necessary + // for triggering the rich answers view. + std::unique_ptr<quick_answers::QuickAnswer> quick_answer = + std::make_unique<quick_answers::QuickAnswer>(); + quick_answer->result_type = ResultType::kTranslationResult; + quick_answer->title.push_back( + std::make_unique<quick_answers::QuickAnswerText>( + l10n_util::GetStringFUTF8(IDS_QUICK_ANSWERS_TRANSLATION_TITLE_TEXT, + u"prodotto", u"Italian"))); + quick_answer->first_answer_row.push_back( + std::make_unique<quick_answers::QuickAnswerResultText>( + l10n_util::GetStringUTF8(IDS_QUICK_ANSWERS_TRANSLATION_INTENT))); + controller()->GetQuickAnswersDelegate()->OnQuickAnswerReceived( + std::move(quick_answer)); + // Click on the quick answers view to trigger the rich answers view. views::NamedWidgetShownWaiter rich_answers_view_widget_waiter( views::test::AnyWidgetTestPasskey(), RichAnswersView::kWidgetName); @@ -232,11 +251,13 @@ quick_answers_view_widget->GetWindowBoundsInScreen().CenterPoint()); event_generator_->ClickLeftButton(); - // Check that the quick answers view closes and the rich answers view pops up. + // Check that the quick answers view closes when the rich answers view shows. views::Widget* rich_answers_view_widget = rich_answers_view_widget_waiter.WaitIfNeededAndGet(); ASSERT_TRUE(quick_answers_view_widget->IsClosed()); ASSERT_TRUE(rich_answers_view_widget != nullptr); + ASSERT_TRUE(controller()->GetVisibilityForTesting() == + QuickAnswersVisibility::kRichAnswersVisible); // Click outside the rich answers view window bounds to dismiss it. gfx::Rect rich_answers_bounds = @@ -249,4 +270,37 @@ ASSERT_TRUE(rich_answers_view_widget->IsClosed()); } +IN_PROC_BROWSER_TEST_F(RichAnswersBrowserTest, + RichAnswersNotTriggeredOnInvalidResult) { + std::unique_ptr<ui::test::EventGenerator> event_generator_ = + std::make_unique<ui::test::EventGenerator>( + ash::Shell::GetPrimaryRootWindow()); + + views::NamedWidgetShownWaiter quick_answers_view_widget_waiter( + views::test::AnyWidgetTestPasskey(), QuickAnswersView::kWidgetName); + + ShowMenuParams params; + params.selected_text = kTestQuery; + params.x = kCursorXToOverlapWithANotification; + params.y = kCursorYToOverlapWithANotification; + ShowMenu(params); + + views::Widget* quick_answers_view_widget = + quick_answers_view_widget_waiter.WaitIfNeededAndGet(); + ASSERT_TRUE(quick_answers_view_widget != nullptr); + + // Click on the quick answers view. This should not trigger the + // rich answers view since no valid QuickAnswer result is provided. + views::NamedWidgetShownWaiter rich_answers_view_widget_waiter( + views::test::AnyWidgetTestPasskey(), RichAnswersView::kWidgetName); + event_generator_->MoveMouseTo( + quick_answers_view_widget->GetWindowBoundsInScreen().CenterPoint()); + event_generator_->ClickLeftButton(); + + // Check that all quick answers views are closed. + ASSERT_TRUE(quick_answers_view_widget->IsClosed()); + ASSERT_TRUE(controller()->GetVisibilityForTesting() == + QuickAnswersVisibility::kClosed); +} + } // namespace quick_answers
diff --git a/chrome/browser/ui/quick_answers/quick_answers_controller_impl.h b/chrome/browser/ui/quick_answers/quick_answers_controller_impl.h index 4a11e32..6c4e9a2f 100644 --- a/chrome/browser/ui/quick_answers/quick_answers_controller_impl.h +++ b/chrome/browser/ui/quick_answers/quick_answers_controller_impl.h
@@ -71,6 +71,8 @@ return quick_answers_ui_controller_.get(); } + quick_answers::QuickAnswer* quick_answer() { return quick_answer_.get(); } + private: void HandleQuickAnswerRequest( const quick_answers::QuickAnswersRequest& request);
diff --git a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc index ad45d1a7..acc5b7a 100644 --- a/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc +++ b/chrome/browser/ui/quick_answers/quick_answers_ui_controller.cc
@@ -102,15 +102,16 @@ // Route dismissal through |controller_| for logging impressions. controller_->DismissQuickAnswers(QuickAnswersExitPoint::kQuickAnswersClick); - if (chromeos::features::IsQuickAnswersRichCardEnabled()) { + if (chromeos::features::IsQuickAnswersRichCardEnabled() && + controller_->quick_answer() != nullptr && + controller_->quick_answer()->result_type != + quick_answers::ResultType::kNoResult) { auto* const rich_answers_view = new quick_answers::RichAnswersView( quick_answers_view_tracker_.view()->bounds(), - weak_factory_.GetWeakPtr()); - rich_answers_view_tracker_.SetView(rich_answers_view); + weak_factory_.GetWeakPtr(), *controller_->quick_answer()); rich_answers_view->GetWidget()->ShowInactive(); - // Temporarily set rich-answers visibility here. Will move after - // setting up rich-answers request handling. + rich_answers_view_tracker_.SetView(rich_answers_view); controller_->SetVisibility(QuickAnswersVisibility::kRichAnswersVisible); return; }
diff --git a/chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.cc b/chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.cc new file mode 100644 index 0000000..53fe5be --- /dev/null +++ b/chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.cc
@@ -0,0 +1,83 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.h" + +#include "base/functional/bind.h" +#include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/color/chrome_color_id.h" +#include "chrome/browser/ui/quick_answers/quick_answers_ui_controller.h" +#include "chromeos/components/quick_answers/quick_answers_model.h" +#include "chromeos/strings/grit/chromeos_strings.h" +#include "components/vector_icons/vector_icons.h" +#include "ui/aura/window.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/color/color_id.h" +#include "ui/color/color_provider.h" +#include "ui/display/screen.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/accessibility/view_accessibility.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/button/button_controller.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/layout/fill_layout.h" +#include "ui/views/widget/widget.h" +#include "ui/wm/core/coordinate_conversion.h" + +// RichAnswersTranslationView +// ----------------------------------------------------------- + +RichAnswersTranslationView::RichAnswersTranslationView( + const quick_answers::QuickAnswer& result) { + InitLayout(); + + // Focus. + // We use custom focus behavior for the quick answers views. + // TODO (b/274665781): Add unit tests for focus behavior. + SetFocusBehavior(views::View::FocusBehavior::ALWAYS); + set_suppress_default_focus_handling(); + focus_search_ = std::make_unique<QuickAnswersFocusSearch>( + this, base::BindRepeating(&RichAnswersTranslationView::GetFocusableViews, + base::Unretained(this))); +} + +RichAnswersTranslationView::~RichAnswersTranslationView() = default; + +const char* RichAnswersTranslationView::GetClassName() const { + return "RichAnswersTranslationView"; +} + +void RichAnswersTranslationView::OnFocus() { + View* wants_focus = focus_search_->FindNextFocusableView( + /* starting_view= */ nullptr, + views::FocusSearch::SearchDirection::kForwards, + views::FocusSearch::TraversalDirection::kDown, + views::FocusSearch::StartingViewPolicy::kCheckStartingView, + views::FocusSearch::AnchoredDialogPolicy::kSkipAnchoredDialog, + /* focus_traversable= */ nullptr, + /* focus_traversable_view= */ nullptr); + if (wants_focus != this) { + wants_focus->RequestFocus(); + } else { + NotifyAccessibilityEvent(ax::mojom::Event::kFocus, true); + } +} + +views::FocusTraversable* RichAnswersTranslationView::GetPaneFocusTraversable() { + return focus_search_.get(); +} + +void RichAnswersTranslationView::InitLayout() { + SetLayoutManager(std::make_unique<views::FillLayout>()); +} + +std::vector<views::View*> RichAnswersTranslationView::GetFocusableViews() { + std::vector<views::View*> focusable_views; + focusable_views.push_back(this); + + return focusable_views; +}
diff --git a/chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.h b/chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.h new file mode 100644 index 0000000..30635116 --- /dev/null +++ b/chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.h
@@ -0,0 +1,52 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_QUICK_ANSWERS_UI_RICH_ANSWERS_TRANSLATION_VIEW_H_ +#define CHROME_BROWSER_UI_QUICK_ANSWERS_UI_RICH_ANSWERS_TRANSLATION_VIEW_H_ + +#include <vector> + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/quick_answers/ui/quick_answers_focus_search.h" +#include "chrome/browser/ui/quick_answers/ui/rich_answers_view.h" +#include "ui/events/event_handler.h" +#include "ui/views/focus/focus_manager.h" +#include "ui/views/view.h" + +namespace views { +class ImageButton; +} // namespace views + +// A bubble style view to show QuickAnswer. +class RichAnswersTranslationView : public views::View { + public: + explicit RichAnswersTranslationView(const quick_answers::QuickAnswer& result); + + RichAnswersTranslationView(const RichAnswersTranslationView&) = delete; + RichAnswersTranslationView& operator=(const RichAnswersTranslationView&) = + delete; + + ~RichAnswersTranslationView() override; + + // views::View: + const char* GetClassName() const override; + void OnFocus() override; + views::FocusTraversable* GetPaneFocusTraversable() override; + + private: + void InitLayout(); + + // QuickAnswersFocusSearch::GetFocusableViewsCallback to poll currently + // focusable views. + std::vector<views::View*> GetFocusableViews(); + + raw_ptr<views::View> base_view_ = nullptr; + raw_ptr<views::ImageButton> settings_button_ = nullptr; + + std::unique_ptr<QuickAnswersFocusSearch> focus_search_; + base::WeakPtrFactory<RichAnswersTranslationView> weak_factory_{this}; +}; + +#endif // CHROME_BROWSER_UI_QUICK_ANSWERS_UI_QUICK_ANSWERS_VIEW_H_
diff --git a/chrome/browser/ui/quick_answers/ui/rich_answers_view.cc b/chrome/browser/ui/quick_answers/ui/rich_answers_view.cc index bc220e7..cd1c3dd19 100644 --- a/chrome/browser/ui/quick_answers/ui/rich_answers_view.cc +++ b/chrome/browser/ui/quick_answers/ui/rich_answers_view.cc
@@ -8,7 +8,10 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/quick_answers/quick_answers_ui_controller.h" +#include "chrome/browser/ui/quick_answers/ui/quick_answers_view.h" #include "chrome/browser/ui/quick_answers/ui/rich_answers_pre_target_handler.h" +#include "chrome/browser/ui/quick_answers/ui/rich_answers_translation_view.h" +#include "chromeos/components/quick_answers/quick_answers_model.h" #include "chromeos/strings/grit/chromeos_strings.h" #include "components/vector_icons/vector_icons.h" #include "ui/aura/window.h" @@ -24,6 +27,7 @@ #include "ui/views/controls/button/button_controller.h" #include "ui/views/controls/button/image_button.h" #include "ui/views/controls/image_view.h" +#include "ui/views/controls/label.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/layout/flex_layout.h" #include "ui/views/widget/widget.h" @@ -31,6 +35,10 @@ namespace { +using quick_answers::QuickAnswer; +using quick_answers::QuickAnswerResultText; +using quick_answers::ResultType; + // Buttons view. constexpr int kButtonsViewMarginDip = 4; constexpr int kButtonsSpacingDip = 4; @@ -44,11 +52,28 @@ namespace quick_answers { +class RichAnswersTextLabel : public views::Label { + public: + explicit RichAnswersTextLabel( + const std::u16string& text, + ui::ColorId color_id = ui::kColorLabelForeground) + : Label(text) { + SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT); + SetEnabledColorId(color_id); + } + + RichAnswersTextLabel(const RichAnswersTextLabel&) = delete; + RichAnswersTextLabel& operator=(const RichAnswersTextLabel&) = delete; + + ~RichAnswersTextLabel() override = default; +}; + // RichAnswersView ----------------------------------------------------------- RichAnswersView::RichAnswersView( const gfx::Rect& anchor_view_bounds, - base::WeakPtr<QuickAnswersUiController> controller) + base::WeakPtr<QuickAnswersUiController> controller, + const quick_answers::QuickAnswer& result) : anchor_view_bounds_(anchor_view_bounds), controller_(std::move(controller)), rich_answers_view_handler_( @@ -57,7 +82,7 @@ this, base::BindRepeating(&RichAnswersView::GetFocusableViews, base::Unretained(this)))) { - InitLayout(); + InitLayout(result); InitWidget(); // Focus. @@ -110,10 +135,10 @@ node_data->role = ax::mojom::Role::kDialog; node_data->SetName( - l10n_util::GetStringUTF8(IDS_QUICK_ANSWERS_VIEW_A11Y_NAME_TEXT)); + l10n_util::GetStringUTF8(IDS_RICH_ANSWERS_VIEW_A11Y_NAME_TEXT)); } -void RichAnswersView::InitLayout() { +void RichAnswersView::InitLayout(const quick_answers::QuickAnswer& result) { SetLayoutManager(std::make_unique<views::FillLayout>()); // Base view Layout. @@ -123,10 +148,22 @@ base_layout->SetOrientation(views::LayoutOrientation::kVertical) .SetCrossAxisAlignment(views::LayoutAlignment::kStretch); - // TODO(b/259440976): Add child views for each result type. - // Add util buttons in the top-right corner. AddFrameButtons(); + + switch (result.result_type) { + case quick_answers::ResultType::kTranslationResult: { + content_view_ = base_view_->AddChildView( + std::make_unique<RichAnswersTranslationView>(result)); + return; + } + case quick_answers::ResultType::kDefinitionResult: + case quick_answers::ResultType::kUnitConversionResult: + default: { + // TODO(b/259440976): Add child views for each result type. + return; + } + } } void RichAnswersView::InitWidget() {
diff --git a/chrome/browser/ui/quick_answers/ui/rich_answers_view.h b/chrome/browser/ui/quick_answers/ui/rich_answers_view.h index d702d1a..f8d415134 100644 --- a/chrome/browser/ui/quick_answers/ui/rich_answers_view.h +++ b/chrome/browser/ui/quick_answers/ui/rich_answers_view.h
@@ -22,15 +22,18 @@ class QuickAnswersUiController; namespace quick_answers { + +struct QuickAnswer; class RichAnswersPreTargetHandler; -// A bubble style view to show QuickAnswer. +// A bubble style view to show RichAnswer. class RichAnswersView : public views::View { public: static constexpr char kWidgetName[] = "RichAnswersViewWidget"; RichAnswersView(const gfx::Rect& anchor_view_bounds, - base::WeakPtr<QuickAnswersUiController> controller); + base::WeakPtr<QuickAnswersUiController> controller, + const quick_answers::QuickAnswer& result); RichAnswersView(const RichAnswersView&) = delete; RichAnswersView& operator=(const RichAnswersView&) = delete; @@ -45,7 +48,7 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override; private: - void InitLayout(); + void InitLayout(const quick_answers::QuickAnswer& result); void InitWidget(); void AddFrameButtons(); void UpdateBounds(); @@ -59,6 +62,7 @@ base::WeakPtr<QuickAnswersUiController> controller_; raw_ptr<views::View> base_view_ = nullptr; + raw_ptr<views::View> content_view_ = nullptr; raw_ptr<views::ImageButton> settings_button_ = nullptr; std::unique_ptr<quick_answers::RichAnswersPreTargetHandler> @@ -69,4 +73,4 @@ } // namespace quick_answers -#endif // CHROME_BROWSER_UI_QUICK_ANSWERS_UI_QUICK_ANSWERS_VIEW_H_ +#endif // CHROME_BROWSER_UI_QUICK_ANSWERS_UI_RICH_ANSWERS_VIEW_H_
diff --git a/chrome/browser/ui/startup/default_browser_prompt.cc b/chrome/browser/ui/startup/default_browser_prompt.cc index eb46357..688e415 100644 --- a/chrome/browser/ui/startup/default_browser_prompt.cc +++ b/chrome/browser/ui/startup/default_browser_prompt.cc
@@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "base/location.h" #include "base/memory/weak_ptr.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "base/task/single_thread_task_runner.h" #include "base/time/time.h" @@ -28,7 +29,6 @@ #include "components/infobars/content/content_infobar_manager.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" -#include "components/variations/variations_associated_data.h" #include "components/version_info/version_info.h" #include "content/public/browser/visibility.h" #include "content/public/browser/web_contents.h" @@ -97,8 +97,8 @@ profile->GetPrefs()->GetInt64(prefs::kDefaultBrowserLastDeclined); if (last_dismissed_value) { int period_days = 0; - base::StringToInt(variations::GetVariationParamValue( - "DefaultBrowserInfobar", "RefreshPeriodDays"), + base::StringToInt(base::GetFieldTrialParamValue("DefaultBrowserInfobar", + "RefreshPeriodDays"), &period_days); if (period_days <= 0 || period_days == std::numeric_limits<int>::max()) return false; // Failed to parse a reasonable period.
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 503e3d2..6673f990 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -72,6 +72,13 @@ "EvDetailsInPageInfo", base::FEATURE_ENABLED_BY_DEFAULT); +// Enables showing the "Get the most out of Chrome" section in settings. +#if !defined(ANDROID) +BASE_FEATURE(kGetTheMostOutOfProgram, + "GetTheMostOutOfProgram", + base::FEATURE_DISABLED_BY_DEFAULT); +#endif + #if BUILDFLAG(ENABLE_EXTENSIONS) // Controls whether we use a different UX for simple extensions overriding // settings.
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index 93618be..19b2a553 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -49,6 +49,10 @@ BASE_DECLARE_FEATURE(kEvDetailsInPageInfo); +#if !defined(ANDROID) +BASE_DECLARE_FEATURE(kGetTheMostOutOfProgram); +#endif + #if BUILDFLAG(ENABLE_EXTENSIONS) BASE_DECLARE_FEATURE(kLightweightExtensionOverrideConfirmations); #endif
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc index be0ea4a..3bbb5fc 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -13,6 +13,7 @@ #include "base/observer_list.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/global_media_controls/media_item_ui_metrics.h" @@ -69,13 +70,11 @@ } // The selected language is only shown when Live Caption is enabled. if (profile_prefs->GetBoolean(prefs::kLiveCaptionEnabled)) { - int language_message_id = speech::GetLanguageDisplayName( - prefs::GetLiveCaptionLanguageCode(profile_prefs)); - if (language_message_id) { - std::u16string language = l10n_util::GetStringUTF16(language_message_id); - return l10n_util::GetStringFUTF16( - IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_SHOW_LANGUAGE, language); - } + std::u16string language = speech::GetLanguageDisplayName( + prefs::GetLiveCaptionLanguageCode(profile_prefs), + g_browser_process->GetApplicationLocale()); + return l10n_util::GetStringFUTF16( + IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_SHOW_LANGUAGE, language); } return l10n_util::GetStringUTF16(IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION); }
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc index e14ae7b2..12549bf 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -928,7 +928,7 @@ EXPECT_TRUE( browser()->profile()->GetPrefs()->GetBoolean(prefs::kLiveCaptionEnabled)); EXPECT_TRUE(GetLiveCaptionTitleLabel()->GetVisible()); - EXPECT_EQ("Live Caption - English", + EXPECT_EQ("Live Caption - English (United States)", base::UTF16ToUTF8(GetLiveCaptionTitleLabel()->GetText())); // Click the Live Caption toggle again to toggle it off. @@ -948,7 +948,7 @@ EXPECT_TRUE(ui_.WaitForDialogOpened()); EXPECT_TRUE(ui_.IsDialogVisible()); EXPECT_TRUE(GetLiveCaptionTitleLabel()->GetVisible()); - EXPECT_EQ("Live Caption - English", + EXPECT_EQ("Live Caption - English (United States)", base::UTF16ToUTF8(GetLiveCaptionTitleLabel()->GetText())); // Click the Live Caption toggle to toggle it off. @@ -1039,7 +1039,7 @@ base::UTF16ToUTF8(GetLiveCaptionTitleLabel()->GetText())); OnSodaInstalled(); - EXPECT_EQ("Live Caption - English", + EXPECT_EQ("Live Caption - English (United States)", base::UTF16ToUTF8(GetLiveCaptionTitleLabel()->GetText())); } @@ -1071,7 +1071,7 @@ // When Live Caption is enabled, the title should show the language. ClickEnableLiveCaptionOnDialog(); EXPECT_TRUE(GetLiveCaptionTitleLabel()->GetVisible()); - EXPECT_EQ("Live Caption - English", + EXPECT_EQ("Live Caption - English (United States)", base::UTF16ToUTF8(GetLiveCaptionTitleLabel()->GetText())); // Close dialog and change live caption language. Reopen dialog. @@ -1085,7 +1085,7 @@ // Live Caption is enabled so the title should show the new language. EXPECT_TRUE(GetLiveCaptionTitleLabel()->GetVisible()); - EXPECT_EQ("Live Caption - German", + EXPECT_EQ("Live Caption - German (Germany)", base::UTF16ToUTF8(GetLiveCaptionTitleLabel()->GetText())); // When Live Caption is disabled, the title should not show the language.
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc index 035a2e4c..19675e11 100644 --- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc +++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -233,7 +233,7 @@ registry.RegisterFeature( std::move(FeaturePromoSpecification::CreateForTutorialPromo( feature_engagement::kIPHDesktopCustomizeChromeFeature, - kTabStripRegionElementId, + kTopContainerElementId, IDS_TUTORIAL_CUSTOMIZE_CHROME_START_TUTORIAL_IPH, kSidePanelCustomizeChromeTutorialId) .SetBubbleArrow(HelpBubbleArrow::kNone) @@ -640,9 +640,8 @@ TutorialDescription::Step success_step( IDS_TUTORIAL_GENERIC_SUCCESS_TITLE, IDS_TUTORIAL_CUSTOMIZE_CHROME_SUCCESS_BODY, - ui::InteractionSequence::StepType::kShown, - CustomizeChromeUI::kChangeChromeThemeClassicElementId, std::string(), - HelpBubbleArrow::kRightCenter, ui::CustomElementEventType(), + ui::InteractionSequence::StepType::kShown, kTopContainerElementId, + std::string(), HelpBubbleArrow::kNone, ui::CustomElementEventType(), /* must_remain_visible =*/false, /* transition_only_on_event =*/false, user_education::TutorialDescription::NameElementsCallback(),
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc index 0ec2b7c..66e44695 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -4822,17 +4822,9 @@ helper_.CheckWindowDisplayTabbed(); } -// TODO(crbug.com/1427085): Re-enable this test -#if BUILDFLAG(IS_MAC) -#define MAYBE_WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_34Standalone_24_94_144 \ - DISABLED_WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_34Standalone_24_94_144 -#else -#define MAYBE_WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_34Standalone_24_94_144 \ - WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_34Standalone_24_94_144 -#endif IN_PROC_BROWSER_TEST_F( WebAppIntegration, - MAYBE_WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_34Standalone_24_94_144) { + WAI_29StandaloneWindowed_24_12Standalone_7Standalone_112StandaloneNotShown_116StandaloneTabbed_143_117Standalone_34Standalone_24_94_144) { // Test contents are generated by script. Please do not modify! // See `docs/webapps/why-is-this-test-failing.md` or // `docs/webapps/integration-testing-framework` for more info.
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc index 89eb96f..f5d2650 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -581,6 +581,21 @@ idp_images_[image_url] = image; } +std::string AccountSelectionBubbleView::GetDialogTitle() const { + // We cannot just return title_ because it is not always set + // (e.g. by ShowFailureDialog). + return base::UTF16ToUTF8(title_label_->GetText()); +} + +absl::optional<std::string> AccountSelectionBubbleView::GetDialogSubtitle() + const { + if (!subtitle_label_) { + return absl::nullopt; + } + + return base::UTF16ToUTF8(subtitle_label_->GetText()); +} + gfx::Rect AccountSelectionBubbleView::GetBubbleBounds() { // The bubble initially looks like this relative to the contents_web_view: // |--------|
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.h b/chrome/browser/ui/views/webid/account_selection_bubble_view.h index 3251c7c..7b20bfb 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view.h +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.h
@@ -96,6 +96,9 @@ // Populates `idp_images` when an IDP image has been fetched. void AddIdpImage(const GURL& image_url, gfx::ImageSkia idp_image); + std::string GetDialogTitle() const override; + absl::optional<std::string> GetDialogSubtitle() const override; + private: gfx::Rect GetBubbleBounds() override;
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view_interface.h b/chrome/browser/ui/views/webid/account_selection_bubble_view_interface.h index 757e9fa..d52695f 100644 --- a/chrome/browser/ui/views/webid/account_selection_bubble_view_interface.h +++ b/chrome/browser/ui/views/webid/account_selection_bubble_view_interface.h
@@ -43,6 +43,9 @@ const std::u16string& top_frame_for_display, const std::u16string& idp_for_display, const content::IdentityProviderMetadata& idp_metadata) = 0; + + virtual std::string GetDialogTitle() const = 0; + virtual absl::optional<std::string> GetDialogSubtitle() const = 0; }; #endif // CHROME_BROWSER_UI_VIEWS_WEBID_ACCOUNT_SELECTION_BUBBLE_VIEW_INTERFACE_H_
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc index 0860fe8..d83d380d 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.cc
@@ -166,6 +166,14 @@ // associated web contents are hidden. } +std::string FedCmAccountSelectionView::GetTitle() const { + return GetBubbleView()->GetDialogTitle(); +} + +absl::optional<std::string> FedCmAccountSelectionView::GetSubtitle() const { + return GetBubbleView()->GetDialogSubtitle(); +} + void FedCmAccountSelectionView::OnVisibilityChanged( content::Visibility visibility) { if (!bubble_widget_) @@ -245,6 +253,11 @@ bubble_widget_->widget_delegate()); } +const AccountSelectionBubbleViewInterface* +FedCmAccountSelectionView::GetBubbleView() const { + return static_cast<const AccountSelectionBubbleView*>( + bubble_widget_->widget_delegate()); +} void FedCmAccountSelectionView::OnWidgetDestroying(views::Widget* widget) { DismissReason dismiss_reason = (bubble_widget_->closed_reason() ==
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h index 16a5263..c0cd6233e 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop.h
@@ -57,6 +57,8 @@ const std::string& top_frame_etld_plus_one, const std::string& idp_etld_plus_one, const content::IdentityProviderMetadata& idp_metadata) override; + std::string GetTitle() const override; + absl::optional<std::string> GetSubtitle() const override; // content::WebContentsObserver void OnVisibilityChanged(content::Visibility visibility) override; @@ -85,6 +87,7 @@ // Returns AccountSelectionBubbleViewInterface for bubble views::Widget. virtual AccountSelectionBubbleViewInterface* GetBubbleView(); + virtual const AccountSelectionBubbleViewInterface* GetBubbleView() const; private: enum class State {
diff --git a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc index 3aac879d..9c6f762 100644 --- a/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc +++ b/chrome/browser/ui/views/webid/fedcm_account_selection_view_desktop_unittest.cc
@@ -81,6 +81,11 @@ account_ids_ = {}; } + std::string GetDialogTitle() const override { return std::string(); } + absl::optional<std::string> GetDialogSubtitle() const override { + return absl::nullopt; + } + bool show_back_button_{false}; absl::optional<SheetType> sheet_type_; std::vector<std::string> account_ids_;
diff --git a/chrome/browser/ui/webid/account_selection_view.h b/chrome/browser/ui/webid/account_selection_view.h index 95983eac..b8547e4 100644 --- a/chrome/browser/ui/webid/account_selection_view.h +++ b/chrome/browser/ui/webid/account_selection_view.h
@@ -74,6 +74,9 @@ const std::string& idp_for_display, const content::IdentityProviderMetadata& idp_metadata) = 0; + virtual std::string GetTitle() const = 0; + virtual absl::optional<std::string> GetSubtitle() const = 0; + protected: raw_ptr<Delegate> delegate_ = nullptr; };
diff --git a/chrome/browser/ui/webid/identity_dialog_controller.cc b/chrome/browser/ui/webid/identity_dialog_controller.cc index 3390e67..b64df15 100644 --- a/chrome/browser/ui/webid/identity_dialog_controller.cc +++ b/chrome/browser/ui/webid/identity_dialog_controller.cc
@@ -65,6 +65,14 @@ NOTIMPLEMENTED(); } +std::string IdentityDialogController::GetTitle() const { + return account_view_->GetTitle(); +} + +absl::optional<std::string> IdentityDialogController::GetSubtitle() const { + return account_view_->GetSubtitle(); +} + void IdentityDialogController::OnAccountSelected(const GURL& idp_config_url, const Account& account) { on_dismiss_.Reset();
diff --git a/chrome/browser/ui/webid/identity_dialog_controller.h b/chrome/browser/ui/webid/identity_dialog_controller.h index ca54642..fe9df3a 100644 --- a/chrome/browser/ui/webid/identity_dialog_controller.h +++ b/chrome/browser/ui/webid/identity_dialog_controller.h
@@ -54,6 +54,9 @@ DismissCallback dismiss_callback) override; void ShowIdpSigninFailureDialog(base::OnceClosure dismiss_callback) override; + std::string GetTitle() const override; + absl::optional<std::string> GetSubtitle() const override; + // AccountSelectionView::Delegate: void OnAccountSelected(const GURL& idp_config_url, const Account& account) override;
diff --git a/chrome/browser/ui/webui/settings/captions_handler.cc b/chrome/browser/ui/webui/settings/captions_handler.cc index 6098de7..c36861e 100644 --- a/chrome/browser/ui/webui/settings/captions_handler.cc +++ b/chrome/browser/ui/webui/settings/captions_handler.cc
@@ -9,12 +9,14 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/translate/chrome_translate_client.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/live_caption/pref_names.h" #include "components/prefs/pref_service.h" #include "components/soda/constants.h" #include "components/soda/soda_installer.h" +#include "components/translate/core/browser/translate_prefs.h" #include "content/public/browser/web_ui.h" #include "media/base/media_switches.h" #include "ui/base/l10n/l10n_util.h" @@ -141,7 +143,9 @@ base::Value::Dict available_language_pack; available_language_pack.Set(kCodeKey, config.language_name); available_language_pack.Set( - kDisplayNameKey, l10n_util::GetStringUTF16(config.display_name)); + kDisplayNameKey, + speech::GetLanguageDisplayName( + config.language_name, g_browser_process->GetApplicationLocale())); available_language_packs.Append(std::move(available_language_pack)); } } @@ -159,7 +163,9 @@ if (config && config->language_code != speech::LanguageCode::kNone) { installed_language_pack.Set(kCodeKey, language.GetString()); installed_language_pack.Set( - kDisplayNameKey, l10n_util::GetStringUTF16(config->display_name)); + kDisplayNameKey, speech::GetLanguageDisplayName( + config->language_name, + g_browser_process->GetApplicationLocale())); installed_language_packs.Append(std::move(installed_language_pack)); } }
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index 38c52fdf..5e3b521 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -309,6 +309,9 @@ #if BUILDFLAG(IS_MAC) {"aboutLearnMoreUpdating", IDS_SETTINGS_ABOUT_PAGE_LEARN_MORE_UPDATING}, #endif + {"getTheMostOutOfProgram", IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM}, + {"getTheMostOutOfProgramDescription", + IDS_SETTINGS_GET_THE_MOST_OUT_OF_PROGRAM_DESCRIPTION}, }; html_source->AddLocalizedStrings(kLocalizedStrings); @@ -351,6 +354,10 @@ html_source->AddLocalizedString("aboutProductTos", IDS_ABOUT_TERMS_OF_SERVICE); #endif + + html_source->AddBoolean( + "showGetTheMostOutOfProgramSection", + base::FeatureList::IsEnabled(features::kGetTheMostOutOfProgram)); } void AddAppearanceStrings(content::WebUIDataSource* html_source,
diff --git a/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc index 6a095eca..3348e01 100644 --- a/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc
@@ -114,6 +114,11 @@ {"captionsColorCyan", IDS_SETTINGS_CAPTIONS_COLOR_CYAN}, {"captionsColorMagenta", IDS_SETTINGS_CAPTIONS_COLOR_MAGENTA}, {"captionsDefaultSetting", IDS_SETTINGS_CAPTIONS_DEFAULT_SETTING}, + {"captionsLanguage", IDS_SETTINGS_CAPTIONS_LANGUAGE}, + {"captionsManageLanguagesTitle", + IDS_SETTINGS_CAPTIONS_MANAGE_LANGUAGES_TITLE}, + {"captionsLiveTranslateTargetLanguage", + IDS_SETTINGS_CAPTIONS_LIVE_TRANSLATE_TARGET_LANGUAGE}, }; html_source->AddLocalizedStrings(kLocalizedStrings); @@ -124,9 +129,19 @@ html_source->AddLocalizedString( "captionsEnableLiveCaptionTitle", IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_TITLE); + html_source->AddLocalizedString( + "captionsEnableLiveTranslateTitle", + IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_TITLE); + html_source->AddLocalizedString( + "captionsEnableLiveTranslateSubtitle", + IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_TRANSLATE_SUBTITLE); const bool liveCaptionMultiLanguageEnabled = base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage); + + const bool liveTranslateEnabled = + base::FeatureList::IsEnabled(media::kLiveTranslate); + const int live_caption_subtitle_message = liveCaptionMultiLanguageEnabled ? IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_SUBTITLE @@ -138,41 +153,57 @@ speech::GetLanguageComponentConfig(speech::LanguageCode::kEnUs); html_source->AddString("sodaLanguageCodeEnglish", englishConfig->language_name); - html_source->AddLocalizedString("sodaLanguageDisplayNameEnglish", - englishConfig->display_name); - absl::optional<speech::SodaLanguagePackComponentConfig> frenchConfig = + html_source->AddString("sodaLanguageDisplayNameEnglish", + speech::GetLanguageDisplayName( + englishConfig->language_name, + g_browser_process->GetApplicationLocale())); + absl::optional<speech::SodaLanguagePackComponentConfig> french_config = speech::GetLanguageComponentConfig(speech::LanguageCode::kFrFr); - html_source->AddString("sodaLanguageCodeFrench", frenchConfig->language_name); - html_source->AddLocalizedString("sodaLanguageDisplayNameFrench", - frenchConfig->display_name); - absl::optional<speech::SodaLanguagePackComponentConfig> germanConfig = + html_source->AddString("sodaLanguageCodeFrench", + french_config->language_name); + html_source->AddString("sodaLanguageDisplayNameFrench", + speech::GetLanguageDisplayName( + french_config->language_name, + g_browser_process->GetApplicationLocale())); + absl::optional<speech::SodaLanguagePackComponentConfig> german_config = speech::GetLanguageComponentConfig(speech::LanguageCode::kDeDe); - html_source->AddString("sodaLanguageCodeGerman", germanConfig->language_name); - html_source->AddLocalizedString("sodaLanguageDisplayNameGerman", - germanConfig->display_name); - absl::optional<speech::SodaLanguagePackComponentConfig> italianConfig = + html_source->AddString("sodaLanguageCodeGerman", + german_config->language_name); + html_source->AddString("sodaLanguageDisplayNameGerman", + speech::GetLanguageDisplayName( + german_config->language_name, + g_browser_process->GetApplicationLocale())); + absl::optional<speech::SodaLanguagePackComponentConfig> italian_config = speech::GetLanguageComponentConfig(speech::LanguageCode::kItIt); html_source->AddString("sodaLanguageCodeItalian", - italianConfig->language_name); - html_source->AddLocalizedString("sodaLanguageDisplayNameItalian", - italianConfig->display_name); - absl::optional<speech::SodaLanguagePackComponentConfig> japaneseConfig = + italian_config->language_name); + html_source->AddString("sodaLanguageDisplayNameItalian", + speech::GetLanguageDisplayName( + italian_config->language_name, + g_browser_process->GetApplicationLocale())); + absl::optional<speech::SodaLanguagePackComponentConfig> japanese_config = speech::GetLanguageComponentConfig(speech::LanguageCode::kJaJp); html_source->AddString("sodaLanguageCodeJapanese", - japaneseConfig->language_name); - html_source->AddLocalizedString("sodaLanguageDisplayNameJapanese", - japaneseConfig->display_name); - absl::optional<speech::SodaLanguagePackComponentConfig> spanishConfig = + japanese_config->language_name); + html_source->AddString("sodaLanguageDisplayNameJapanese", + speech::GetLanguageDisplayName( + japanese_config->language_name, + g_browser_process->GetApplicationLocale())); + absl::optional<speech::SodaLanguagePackComponentConfig> spanish_config = speech::GetLanguageComponentConfig(speech::LanguageCode::kEsEs); html_source->AddString("sodaLanguageCodeSpanish", - spanishConfig->language_name); - html_source->AddLocalizedString("sodaLanguageDisplayNameSpanish", - spanishConfig->display_name); + spanish_config->language_name); + html_source->AddString("sodaLanguageDisplayNameSpanish", + speech::GetLanguageDisplayName( + spanish_config->language_name, + g_browser_process->GetApplicationLocale())); html_source->AddBoolean("enableLiveCaption", captions::IsLiveCaptionFeatureSupported()); html_source->AddBoolean("enableLiveCaptionMultiLanguage", liveCaptionMultiLanguageEnabled); + + html_source->AddBoolean("enableLiveTranslate", liveTranslateEnabled); } #if BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.cc b/chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.cc index 525d7474..e286499 100644 --- a/chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.cc +++ b/chrome/browser/ui/webui/side_panel/companion/companion_side_panel_untrusted_ui.cc
@@ -12,6 +12,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "url/gurl.h" CompanionSidePanelUntrustedUI::CompanionSidePanelUntrustedUI( content::WebUI* web_ui) @@ -31,10 +32,15 @@ network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome-untrusted://resources 'self';"); // Allow the companion homepage URL to be embedded in this WebUI. - std::string frameSrc = std::string("frame-src ") + - features::kHomepageURLForCompanion.Get() + ";"; + GURL frameSrcUrl = + GURL(features::kHomepageURLForCompanion.Get()).GetWithEmptyPath(); + std::string frameSrcString = frameSrcUrl.is_valid() + ? frameSrcUrl.spec() + : features::kHomepageURLForCompanion.Get(); + std::string frameSrcDirective = + std::string("frame-src ") + frameSrcString + ";"; html_source->OverrideContentSecurityPolicy( - network::mojom::CSPDirectiveName::FrameSrc, frameSrc); + network::mojom::CSPDirectiveName::FrameSrc, frameSrcDirective); } CompanionSidePanelUntrustedUI::~CompanionSidePanelUntrustedUI() = default;
diff --git a/chrome/browser/usb/usb_blocklist.cc b/chrome/browser/usb/usb_blocklist.cc index 8494f90..7353ef8 100644 --- a/chrome/browser/usb/usb_blocklist.cc +++ b/chrome/browser/usb/usb_blocklist.cc
@@ -8,9 +8,9 @@ #include <string> #include <tuple> +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" -#include "components/variations/variations_associated_data.h" #include "services/device/public/mojom/usb_device.mojom.h" namespace { @@ -148,8 +148,8 @@ } void UsbBlocklist::PopulateWithServerProvidedValues() { - std::string blocklist_string = variations::GetVariationParamValue( - "WebUSBBlocklist", "blocklist_additions"); + std::string blocklist_string = + base::GetFieldTrialParamValue("WebUSBBlocklist", "blocklist_additions"); for (const auto& entry : base::SplitStringPiece(blocklist_string, ",", base::TRIM_WHITESPACE,
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index ba555868..be48ad9 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1679551190-05d343a0d20ff9d5301807a9a7330460f0fc9056.profdata +chrome-linux-main-1679594402-969487b5ff7ba9e94c57aacf3b915841e40ad605.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index a961e4d..efab59c8 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1679587106-e5f9fd8e7367245bbebfa0238f1ab922d38ff078.profdata +chrome-mac-arm-main-1679601280-1f3de2d387ec0fe09258a51133c012d5b0b9f283.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 8de7066..11c418d 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1679572553-adcc660610aec677cb528284b6e339c44fc16cbb.profdata +chrome-mac-main-1679594402-4993277604a6dadd6d6b732fecba08859a8baef0.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 1043402..8802608 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1679572553-a6596050028c1e98e42c48b3a704a7ddee14c0d1.profdata +chrome-win32-main-1679594402-64cdf14a13f598989a60336d5a937e641c150871.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 102dace8..5bb4db10 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1679583480-b418af276de905716877ef58e4c2b8ec8b66f8ab.profdata +chrome-win64-main-1679594402-559f0f55784157947cc49c7bea88715453008fdb.profdata
diff --git a/chrome/common/extensions/api/content_settings.json b/chrome/common/extensions/api/content_settings.json index f62c827d..d7470a2 100644 --- a/chrome/common/extensions/api/content_settings.json +++ b/chrome/common/extensions/api/content_settings.json
@@ -170,6 +170,11 @@ ] }, { + "id": "AutoVerifyContentSetting", + "type": "string", + "enum": ["allow", "block"] + }, + { "id": "CookiesContentSetting", "type": "string", "enum": ["allow", "block", "session_only"] @@ -236,6 +241,14 @@ } ], "properties": { + "autoVerify": { + "$ref": "ContentSetting", + "description": "Whether to allow sites to use the <a href='https://developer.chrome.com/docs/privacy-sandbox/trust-tokens/'>Private State Tokens API</a>. One of <br><var>allow</var>: Allow sites to use the Private State Tokens API, <br><var>block</var>: Block sites from using the Private State Tokens API. <br>Default is <var>allow</var>.<br> The primary URL is the URL of the top-level frame. The secondary URL is not used. NOTE: When calling <code>set()</code>, the primary pattern must be <code><all_urls></code>.", + "value": [ + "anti-abuse", + {"$ref":"AutoVerifyContentSetting"} + ] + }, "cookies": { "$ref": "ContentSetting", "description": "Whether to allow cookies and other local data to be set by websites. One of<br><var>allow</var>: Accept cookies,<br><var>block</var>: Block cookies,<br><var>session_only</var>: Accept cookies only for the current session. <br>Default is <var>allow</var>.<br>The primary URL is the URL representing the cookie origin. The secondary URL is the URL of the top-level frame.",
diff --git a/chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc b/chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc index 8df654f..dcad6ca 100644 --- a/chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc +++ b/chrome/common/extensions/manifest_tests/extension_manifests_side_panel_unittest.cc
@@ -4,10 +4,12 @@ #include "chrome/common/extensions/api/side_panel/side_panel_info.h" +#include "base/command_line.h" #include "base/strings/stringprintf.h" #include "chrome/common/extensions/manifest_tests/chrome_manifest_test.h" #include "content/public/test/browser_test_utils.h" #include "extensions/common/manifest.h" +#include "extensions/common/switches.h" #include "testing/gtest/include/gtest/gtest.h" namespace extensions { @@ -79,13 +81,13 @@ base::ScopedTempDir temp_dir_; }; -#if defined(OFFICIAL_BUILD) -#define MAYBE_FileDoesntExist DISABLED_FileDoesntExist -#else -#define MAYBE_FileDoesntExist FileDoesntExist -#endif // defined(OFFICIAL_BUILD) // Error loading extension when filepath doesn't exist or is empty. -TEST_F(SidePanelExtensionsTest, MAYBE_FileDoesntExist) { +TEST_F(SidePanelExtensionsTest, FileDoesntExist) { + // This switch is required to make this test pass on official build bots. + // TODO(crbug.com/1413908): Remove once side panel is not experimental. + base::CommandLine::ForCurrentProcess()->AppendSwitch( + extensions::switches::kEnableExperimentalExtensionApis); + for (const auto* default_path : {"", "error"}) { std::string error; std::vector<InstallWarning> warnings;
diff --git a/chrome/renderer/accessibility/read_anything_app_controller.cc b/chrome/renderer/accessibility/read_anything_app_controller.cc index 556b079c..ebb2cd5 100644 --- a/chrome/renderer/accessibility/read_anything_app_controller.cc +++ b/chrome/renderer/accessibility/read_anything_app_controller.cc
@@ -331,15 +331,15 @@ // distillation request. model_.ClearPendingUpdates(); + // TODO(b/1266555): Use v8::Function rather than javascript. If possible, + // replace this function call with firing an event. + std::string script = "chrome.readAnything.showLoading();"; + render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script)); // When the UI first constructs, this function may be called before tree_id // has been added to the tree list in AccessibilityEventReceived. In that // case, do not distill. if (model_.active_tree_id() != ui::AXTreeIDUnknown() && model_.ContainsTree(model_.active_tree_id())) { - // TODO(b/1266555): Use v8::Function rather than javascript. If possible, - // replace this function call with firing an event. - std::string script = "chrome.readAnything.showLoading();"; - render_frame_->ExecuteJavaScript(base::ASCIIToUTF16(script)); Distill(); } }
diff --git a/chrome/services/speech/audio_source_fetcher_impl.cc b/chrome/services/speech/audio_source_fetcher_impl.cc index 5b4aae1..3419a07 100644 --- a/chrome/services/speech/audio_source_fetcher_impl.cc +++ b/chrome/services/speech/audio_source_fetcher_impl.cc
@@ -8,6 +8,7 @@ #include "base/check.h" #include "base/functional/bind.h" +#include "base/metrics/histogram_functions.h" #include "base/task/bind_post_task.h" #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" @@ -36,6 +37,11 @@ constexpr base::TimeDelta kServerBasedRecognitionAudioBufferSize = base::Milliseconds(100); +constexpr char kServerBasedRecognitionSessionLength[] = + "Ash.SpeechRecognitionSessionLength.ServerBased"; +constexpr char kOnDeviceRecognitionSessionLength[] = + "Ash.SpeechRecognitionSessionLength.OnDevice"; + } // namespace AudioSourceFetcherImpl::AudioSourceFetcherImpl( @@ -52,6 +58,10 @@ AudioSourceFetcherImpl::~AudioSourceFetcherImpl() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); Stop(); + const auto* session_length_metric_name = + is_server_based_ ? kServerBasedRecognitionSessionLength + : kOnDeviceRecognitionSessionLength; + base::UmaHistogramLongTimes100(session_length_metric_name, audio_length_); } void AudioSourceFetcherImpl::Create( @@ -162,6 +172,9 @@ base::TimeTicks audio_capture_time, double volume, bool key_pressed) { + audio_length_ += media::AudioTimestampHelper::FramesToTime( + audio_source->frames(), audio_parameters_.sample_rate()); + if (converter_) { // Send the audio callback to the main thread to resample. std::unique_ptr<media::AudioBus> input =
diff --git a/chrome/services/speech/audio_source_fetcher_impl.h b/chrome/services/speech/audio_source_fetcher_impl.h index d81807b..6c55181 100644 --- a/chrome/services/speech/audio_source_fetcher_impl.h +++ b/chrome/services/speech/audio_source_fetcher_impl.h
@@ -10,6 +10,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" +#include "base/time/time.h" #include "chrome/services/speech/audio_source_consumer.h" #include "media/base/audio_bus.h" #include "media/base/audio_capturer_source.h" @@ -130,6 +131,8 @@ bool is_multi_channel_supported_; bool is_server_based_; + base::TimeDelta audio_length_ = base::Seconds(0); + // A callback to push audio data into `converter_`. SendAudioToResampleCallback resample_callback_;
diff --git a/chrome/services/speech/audio_source_fetcher_unittest.cc b/chrome/services/speech/audio_source_fetcher_unittest.cc index 3d83dea7..c3326fb7 100644 --- a/chrome/services/speech/audio_source_fetcher_unittest.cc +++ b/chrome/services/speech/audio_source_fetcher_unittest.cc
@@ -12,6 +12,7 @@ #include "base/path_service.h" #include "base/run_loop.h" #include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "chrome/services/speech/cros_speech_recognition_recognizer_impl.h" #include "chrome/services/speech/speech_recognition_service_impl.h" @@ -34,6 +35,11 @@ constexpr int kOriginalSampleRate = 48000; constexpr int kOriginalFramesPerBuffer = 9600; +constexpr char kServerBasedRecognitionSessionLength[] = + "Ash.SpeechRecognitionSessionLength.ServerBased"; +constexpr char kOnDeviceRecognitionSessionLength[] = + "Ash.SpeechRecognitionSessionLength.OnDevice"; + } // namespace class MockStreamFactory : public audio::FakeStreamFactory { @@ -148,9 +154,11 @@ void OnLanguageIdentificationEvent( media::mojom::LanguageIdentificationEventPtr event) override {} + std::unique_ptr<AudioSourceFetcherImpl> audio_source_fetcher_; + base::HistogramTester histogram_tester_; + private: base::test::TaskEnvironment task_environment; - std::unique_ptr<AudioSourceFetcherImpl> audio_source_fetcher_; MockAudioSourceConsumer* speech_recognition_recognizer_; bool is_server_based_; }; @@ -190,6 +198,18 @@ VerifyAudioBuffer(kServerBasedRecognitionAudioSampleRate, kServerBasedRecognitionAudioFramesPerBuffer); } + + // Let's destroy the audio source fetcher and ensure that the metric + // has been recorded. + audio_source_fetcher_.reset(); + base::TimeDelta length = media::AudioTimestampHelper::FramesToTime( + audio_bus->frames(), kOriginalSampleRate); + + const auto* histogram_name = is_server_based() + ? kServerBasedRecognitionSessionLength + : kOnDeviceRecognitionSessionLength; + histogram_tester_.ExpectTimeBucketCount(histogram_name, length, + /*count=*/1); } INSTANTIATE_TEST_SUITE_P(All, AudioSourceFetcherImplTest, ::testing::Bool());
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 12a71f9..85956df4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4463,6 +4463,7 @@ "//chromeos/ash/services/multidevice_setup/public/cpp:test_support", "//chromeos/ash/services/network_config", "//chromeos/components/onc:test_support", + "//chromeos/components/quick_answers:quick_answers", "//chromeos/components/quick_answers/public/cpp:cpp", "//chromeos/components/quick_answers/public/cpp:prefs", "//chromeos/components/remote_apps/mojom:mojom", @@ -9097,6 +9098,12 @@ "../browser/supervised_user/supervised_user_pref_store_unittest.cc", "../browser/supervised_user/supervised_user_service_unittest.cc", ] + if (is_chromeos) { + sources += [ + "../browser/supervised_user/chromeos/mock_large_icon_service.cc", + "../browser/supervised_user/chromeos/mock_large_icon_service.h", + ] + } if (is_chromeos_ash) { sources += [ "../browser/supervised_user/chromeos/web_content_handler_impl_unittest.cc" ] deps += [ "//chrome/browser/ash/crosapi" ]
diff --git a/chrome/test/data/extensions/api_test/content_settings/incognitoisolation/test.js b/chrome/test/data/extensions/api_test/content_settings/incognitoisolation/test.js index fb7995a..cd0d8a4e 100644 --- a/chrome/test/data/extensions/api_test/content_settings/incognitoisolation/test.js +++ b/chrome/test/data/extensions/api_test/content_settings/incognitoisolation/test.js
@@ -27,7 +27,10 @@ 'automaticDownloads' ]; - function expect(expected, message) { +// Settings that do not support site-specific exceptions. +var globalOnlySettings = ['autoVerify']; + +function expect(expected, message) { return chrome.test.callbackPass(function(value) { chrome.test.assertEq(expected, value, message); }); @@ -50,8 +53,20 @@ }, chrome.test.callbackPass()); }); }, + function setGlobalContentSettings() { + globalOnlySettings.forEach(function(type) { + cs[type].set( + { + 'primaryPattern': '<all_urls>', + 'secondaryPattern': '<all_urls>', + 'setting': givenPermission, + 'scope': 'incognito_session_only' + }, + chrome.test.callbackPass()); + }); + }, function getContentSettings() { - settings.forEach(function(type) { + [...settings, ...globalOnlySettings].forEach(function(type) { var message = 'Setting for ' + type + ' should be ' + givenPermission; cs[type].get({ 'primaryUrl': 'http://www.example.com',
diff --git a/chrome/test/data/extensions/api_test/content_settings/standard/test.js b/chrome/test/data/extensions/api_test/content_settings/standard/test.js index 150932b..641c942 100644 --- a/chrome/test/data/extensions/api_test/content_settings/standard/test.js +++ b/chrome/test/data/extensions/api_test/content_settings/standard/test.js
@@ -7,17 +7,18 @@ var cs = chrome.contentSettings; var default_content_settings = { - "cookies": "session_only", - "images": "allow", - "javascript": "block", - "popups": "block", - "location": "ask", - "notifications": "ask", - "fullscreen": "ask", - "mouselock": "ask", - "microphone": "ask", - "camera": "ask", - "automaticDownloads": "ask" + 'cookies': 'session_only', + 'images': 'allow', + 'javascript': 'block', + 'popups': 'block', + 'location': 'ask', + 'notifications': 'ask', + 'fullscreen': 'ask', + 'mouselock': 'ask', + 'microphone': 'ask', + 'camera': 'ask', + 'automaticDownloads': 'ask', + 'autoVerify': 'allow' }; var settings = { @@ -36,6 +37,9 @@ 'automaticDownloads': 'block' }; +// Settings that do not support site-specific exceptions. +var globalOnlySettings = {'autoVerify': 'block'}; + // List of settings that are expected to return different values than were // written, due to deprecation. For example, "fullscreen" is set to "block" but // we expect this to be ignored, and so read back as "allow". Any setting @@ -51,7 +55,7 @@ // List of deprecated APIs. It is expected to return 'block' to get(), and will // be ignored to set() and clear(). -var deprecatedExtenionApis = [ 'plugins', 'unsandboxedPlugins' ]; +var deprecatedExtenionApis = ['plugins', 'unsandboxedPlugins']; Object.prototype.forEach = function(f) { var k; @@ -103,7 +107,47 @@ }, expect({'setting':setting}, message)); }); }, + function setGlobalContentSettings() { + globalOnlySettings.forEach(function(type, setting) { + cs[type].set( + { + 'primaryPattern': '<all_urls>', + 'secondaryPattern': '<all_urls>', + 'setting': setting + }, + chrome.test.callbackPass()); + }); + }, + function getGlobalSettings() { + globalOnlySettings.forEach(function(type, setting) { + var message = 'Setting for ' + type + ' should be ' + setting; + cs[type].get( + { + 'primaryUrl': 'http://www.google.com', + 'secondaryUrl': 'http://www.google.com' + }, + expect({'setting': setting}, message)); + }); + }, function invalidSettings() { + cs.autoVerify.set( + { + 'primaryPattern': 'http://example.com/*', + 'secondaryPattern': '<all_urls>', + 'setting': 'allow' + }, + chrome.test.callbackFail( + 'Site-specific settings are not allowed for this type. ' + + 'The URL pattern must be \'<all_urls>\'.')); + cs.autoVerify.set( + { + 'primaryPattern': '<all_urls>', + 'secondaryPattern': 'http://example.com/*', + 'setting': 'allow' + }, + chrome.test.callbackFail( + 'Site-specific settings are not allowed for this type. ' + + 'The URL pattern must be \'<all_urls>\'.')); cs.cookies.get({ 'primaryUrl': 'moo' }, chrome.test.callbackFail("The URL \"moo\" is invalid.")); @@ -128,7 +172,6 @@ } chrome.test.assertTrue(caught); }, - function testDeprecatedApi_SetIgnored() { deprecatedExtenionApis.forEach(api => { cs[api].set(
diff --git a/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts b/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts index a8b28f6..a6803c71 100644 --- a/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts +++ b/chrome/test/data/webui/cr_elements/cr_url_list_item_test.ts
@@ -93,4 +93,17 @@ const slotElements = slot.assignedElements(); assertEquals(1, slotElements.length); }); + + test('DisplaysMaxImageCount', () => { + element.imageUrls = [ + 'http://www.first.com', + 'http://www.second.com', + 'http://www.third.com', + ]; + flush(); + const imageElements = + element.shadowRoot!.querySelectorAll<HTMLElement>('.folder-image'); + // No more than two images may be displayed for a folder. + assertEquals(2, imageElements.length); + }); });
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn index ac2b4926..4d05562 100644 --- a/chrome/test/data/webui/new_tab_page/BUILD.gn +++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -45,6 +45,7 @@ "//ui/webui/resources/cr_components/customize_themes:build_ts", "//ui/webui/resources/cr_components/help_bubble:build_ts", "//ui/webui/resources/cr_components/history_clusters:build_ts", + "//ui/webui/resources/cr_components/image_service:build_ts", "//ui/webui/resources/cr_components/most_visited:build_ts", "//ui/webui/resources/cr_components/omnibox:build_ts", "//ui/webui/resources/cr_elements:build_ts",
diff --git a/chrome/test/data/webui/new_tab_page/modules/history_clusters/tile_test.ts b/chrome/test/data/webui/new_tab_page/modules/history_clusters/tile_test.ts index 59a06de2..d833a86 100644 --- a/chrome/test/data/webui/new_tab_page/modules/history_clusters/tile_test.ts +++ b/chrome/test/data/webui/new_tab_page/modules/history_clusters/tile_test.ts
@@ -5,33 +5,46 @@ import 'chrome://webui-test/mojo_webui_test_support.js'; import {URLVisit} from 'chrome://new-tab-page/history_cluster_types.mojom-webui.js'; -import {TileModuleElement} from 'chrome://new-tab-page/lazy_load.js'; +import {ImageServiceBrowserProxy, TileModuleElement} from 'chrome://new-tab-page/lazy_load.js'; import {$$} from 'chrome://new-tab-page/new_tab_page.js'; +import {ImageServiceHandlerRemote} from 'chrome://resources/cr_components/image_service/image_service.mojom-webui.js'; import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {fakeMetricsPrivate, MetricsTracker} from 'chrome://webui-test/metrics_test_support.js'; +import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {TestMock} from 'chrome://webui-test/test_mock.js'; + +import {installMock} from '../../test_support.js'; import {createVisit} from './test_support.js'; suite('NewTabPageModulesHistoryClustersModuleTileTest', () => { + let imageServiceHandler: TestMock<ImageServiceHandlerRemote>; + let metrics: MetricsTracker; + setup(() => { document.body.innerHTML = window.trustedTypes!.emptyHTML; + imageServiceHandler = installMock( + ImageServiceHandlerRemote, + mock => ImageServiceBrowserProxy.setInstance( + new ImageServiceBrowserProxy(mock))); + metrics = fakeMetricsPrivate(); }); - async function initializeModule(visit: URLVisit): Promise<TileModuleElement> { + function initializeModule(visit: URLVisit): TileModuleElement { const tileElement = new TileModuleElement(); tileElement.visit = visit; document.body.append(tileElement); - await waitAfterNextRender(tileElement); return tileElement; } test('Tile element populated with correct data', async () => { // Arrange. - const tileElement = await initializeModule(createVisit( + const tileElement = initializeModule(createVisit( BigInt(1), 'https://www.test.com/1', 'https://www.test.com/1', 'Test Title 1', false, '1 min ago')); // Assert. + await waitAfterNextRender(tileElement); assertTrue(!!tileElement); assertEquals($$(tileElement, '#title')!.innerHTML, 'Test Title 1'); assertEquals('1 min ago', $$(tileElement, '#date')!.innerHTML); @@ -40,4 +53,28 @@ .getPropertyValue('background-image') .trim()); }); + + [true, false].forEach( + (success) => + test(`Metric sent on success ${success} image load`, async () => { + // Arrange. + const imageResult = success ? + {result: {imageUrl: {url: 'https://example.com/image.png'}}} : + null; + imageServiceHandler.setResultFor( + 'getPageImageUrl', Promise.resolve(imageResult)); + initializeModule(createVisit( + BigInt(1), 'https://www.test.com/1', 'https://www.test.com/1', + 'Test Title 1', true, '1 min ago')); + + await flushTasks(); + + // Assert + assertEquals( + 1, imageServiceHandler.getCallCount('getPageImageUrl')); + assertEquals( + 1, + metrics.count( + 'NewTabPage.HistoryClusters.ImageLoadSuccess', success)); + })); });
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn index 15a9763d..c0899144 100644 --- a/chrome/test/data/webui/settings/chromeos/BUILD.gn +++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -123,7 +123,6 @@ "per_device_keyboard_subsection_test.js", "per_device_keyboard_remap_keys_test.js", "per_device_keyboard_test.js", - "per_device_mouse_subsection_test.js", "per_device_pointing_stick_subsection_test.js", "per_device_touchpad_subsection_test.js", "per_device_touchpad_test.js", @@ -131,7 +130,6 @@ "privacy_hub_subpage_tests.js", "quick_unlock_authenticate_browsertest_chromeos.js", "search_engine_test.js", - "search_subpage_test.js", "select_to_speak_subpage_tests.js", "settings_scheduler_slider_test.js", "settings_traffic_counters_test.js", @@ -206,6 +204,7 @@ "date_time_page/timezone_selector_test.ts", "date_time_page/timezone_subpage_test.ts", + "device_page/per_device_mouse_subsection_test.ts", "device_page/per_device_mouse_test.ts", "device_page/per_device_pointing_stick_test.ts", @@ -233,6 +232,8 @@ "os_printing_page/os_printing_page_tests.ts", + "os_search_page/search_subpage_test.ts", + "os_settings_ui/os_settings_ui_about_page_test.js", "os_settings_ui/os_settings_ui_menu_test.js", "os_settings_ui/os_settings_ui_test.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/device_page/per_device_mouse_subsection_test.ts b/chrome/test/data/webui/settings/chromeos/device_page/per_device_mouse_subsection_test.ts new file mode 100644 index 0000000..664b81d --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/device_page/per_device_mouse_subsection_test.ts
@@ -0,0 +1,227 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; + +import {CrToggleElement, FakeInputDeviceSettingsProvider, fakeMice, Mouse, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsDropdownMenuElement, SettingsPerDeviceMouseSubsectionElement, SettingsSliderElement, SettingsToggleButtonElement} from 'chrome://os-settings/chromeos/os_settings.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; +import {isVisible} from 'chrome://webui-test/test_util.js'; + +const MOUSE_ACCELERATION_SETTING_ID = 408; + +suite('<settings-per-device-mouse-subsection>', function() { + let subsection: SettingsPerDeviceMouseSubsectionElement; + let provider: FakeInputDeviceSettingsProvider; + + teardown(() => { + subsection.remove(); + }); + + function initializePerDeviceMouseSubsection(): Promise<void> { + provider = new FakeInputDeviceSettingsProvider(); + provider.setFakeMice(fakeMice); + setInputDeviceSettingsProviderForTesting(provider); + subsection = document.createElement('settings-per-device-mouse-subsection'); + assert(subsection); + subsection.set('mouse', {...fakeMice[0]}); + subsection.set('allowScrollSettings_', true); + document.body.appendChild(subsection); + return flushTasks(); + } + + function changeMouseSubsectionState( + mouse: Mouse, allowScrollSettings: boolean): Promise<void> { + subsection.set('mouse', mouse); + subsection.set('allowScrollSettings_', allowScrollSettings); + return flushTasks(); + } + + /** + * Test that API are updated when mouse settings change. + */ + test('Update API when mouse settings change', async () => { + await initializePerDeviceMouseSubsection(); + const mouseSwapButtonDropdown = + subsection.shadowRoot!.querySelector<SettingsDropdownMenuElement>( + '#mouseSwapButtonDropdown'); + assert(mouseSwapButtonDropdown); + await flushTasks(); + let updatedMice = await provider.getConnectedMouseSettings(); + assertEquals( + updatedMice[0]!.settings.swapRight, + mouseSwapButtonDropdown.pref!.value); + + const mouseAccelerationToggleButton = + subsection.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#mouseAcceleration'); + assert(mouseAccelerationToggleButton); + mouseAccelerationToggleButton.click(); + await flushTasks(); + updatedMice = await provider.getConnectedMouseSettings(); + assertEquals( + updatedMice[0]!.settings.accelerationEnabled, + mouseAccelerationToggleButton.pref!.value); + + const mouseSpeedSlider = + subsection.shadowRoot!.querySelector<SettingsSliderElement>( + '#mouseSpeedSlider'); + assert(mouseSpeedSlider); + const arrowRightEvent = + new KeyboardEvent('keypress', {'key': 'ArrowRight'}); + mouseSpeedSlider.shadowRoot!.querySelector('cr-slider')!.dispatchEvent( + arrowRightEvent); + await flushTasks(); + updatedMice = await provider.getConnectedMouseSettings(); + assertEquals( + updatedMice[0]!.settings.sensitivity, mouseSpeedSlider.pref!.value); + + const mouseReverseScrollToggleButton = + subsection.shadowRoot!.querySelector<CrToggleElement>( + '#mouseReverseScroll'); + assert(mouseReverseScrollToggleButton); + mouseReverseScrollToggleButton.click(); + await flushTasks(); + updatedMice = await provider.getConnectedMouseSettings(); + assertEquals( + updatedMice[0]!.settings.reverseScrolling, + mouseReverseScrollToggleButton.checked); + + const mouseScrollAccelerationToggleButton = + subsection.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#mouseScrollAcceleration'); + assert(mouseScrollAccelerationToggleButton); + mouseScrollAccelerationToggleButton.click(); + await flushTasks(); + updatedMice = await provider.getConnectedMouseSettings(); + assertEquals( + updatedMice[0]!.settings.scrollAcceleration, + mouseScrollAccelerationToggleButton.pref!.value); + + const mouseScrollSpeedSlider = + subsection.shadowRoot!.querySelector<SettingsSliderElement>( + '#mouseScrollSpeedSlider'); + assert(mouseScrollSpeedSlider); + mouseScrollSpeedSlider.shadowRoot!.querySelector('cr-slider')! + .dispatchEvent(arrowRightEvent); + await flushTasks(); + updatedMice = await provider.getConnectedMouseSettings(); + assertEquals( + updatedMice[0]!.settings.scrollSensitivity, + mouseScrollSpeedSlider.pref!.value); + }); + + /** + * Test that mouse settings data are from the mouse provider. + */ + test('Verify mouse settings data', async () => { + await initializePerDeviceMouseSubsection(); + let mouseSwapButtonDropdown = + subsection.shadowRoot!.querySelector<SettingsDropdownMenuElement>( + '#mouseSwapButtonDropdown'); + assertEquals( + fakeMice[0]!.settings.swapRight, mouseSwapButtonDropdown!.pref!.value); + let mouseAccelerationToggleButton = + subsection.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#mouseAcceleration'); + assertEquals( + fakeMice[0]!.settings.accelerationEnabled, + mouseAccelerationToggleButton!.pref!.value); + let mouseSpeedSlider = + subsection.shadowRoot!.querySelector<SettingsSliderElement>( + '#mouseSpeedSlider'); + assertEquals( + fakeMice[0]!.settings.sensitivity, mouseSpeedSlider!.pref!.value); + assertEquals( + fakeMice[0]!.settings.reverseScrolling, + subsection.get('reverseScrollValue')); + let mouseScrollAccelerationToggleButton = + subsection.shadowRoot!.querySelector<SettingsSliderElement>( + '#mouseScrollAcceleration'); + assertTrue(isVisible(mouseScrollAccelerationToggleButton)); + assertEquals( + fakeMice[0]!.settings.scrollAcceleration, + mouseScrollAccelerationToggleButton!.pref!.value); + let mouseScrollSpeedSlider = + subsection.shadowRoot!.querySelector<SettingsSliderElement>( + '#mouseScrollSpeedSlider'); + assert(mouseScrollSpeedSlider); + assertTrue(isVisible(mouseScrollSpeedSlider)); + assertEquals( + fakeMice[0]!.settings.scrollSensitivity, + mouseScrollSpeedSlider.pref!.value); + + assert(fakeMice[1]); + await changeMouseSubsectionState(fakeMice[1], false); + mouseSwapButtonDropdown = + subsection.shadowRoot!.querySelector('#mouseSwapButtonDropdown'); + assertEquals( + fakeMice[1]!.settings.swapRight, mouseSwapButtonDropdown!.pref!.value); + mouseAccelerationToggleButton = + subsection.shadowRoot!.querySelector('#mouseAcceleration'); + assertEquals( + fakeMice[1]!.settings.accelerationEnabled, + mouseAccelerationToggleButton!.pref!.value); + mouseSpeedSlider = + subsection.shadowRoot!.querySelector('#mouseSpeedSlider'); + assertEquals( + fakeMice[1]!.settings.sensitivity, mouseSpeedSlider!.pref!.value); + assertEquals( + fakeMice[1]!.settings.reverseScrolling, + subsection.get('reverseScrollValue')); + mouseScrollAccelerationToggleButton = + subsection.shadowRoot!.querySelector('#mouseScrollAcceleration'); + assertFalse(isVisible(mouseScrollAccelerationToggleButton)); + mouseScrollSpeedSlider = + subsection.shadowRoot!.querySelector('#mouseScrollSpeedSlider'); + assertFalse(isVisible(mouseScrollSpeedSlider)); + }); + + /** + * Verify entering the page with search tags matched will auto focus the + * searched element. + */ + test('deep linking mixin focus on the first searched element', async () => { + await initializePerDeviceMouseSubsection(); + const mouseAccelerationToggle = + subsection.shadowRoot!.querySelector<HTMLElement>('#mouseAcceleration'); + subsection.set('mouseIndex', 0); + // Enter the page from auto repeat search tag. + const url = new URLSearchParams( + 'search=mouse+accel&settingId=' + + encodeURIComponent(MOUSE_ACCELERATION_SETTING_ID)); + + await Router.getInstance().navigateTo( + routes.PER_DEVICE_MOUSE, + /* dynamicParams= */ url, /* removeSearch= */ true); + + assert(mouseAccelerationToggle); + await waitAfterNextRender(mouseAccelerationToggle); + assertEquals(subsection.shadowRoot!.activeElement, mouseAccelerationToggle); + }); + + /** + * Verify entering the page with search tags matched wll not auto focus the + * searched element if it's not the first keyboard displayed. + */ + test('deep linking mixin does not focus on second element', async () => { + await initializePerDeviceMouseSubsection(); + const mouseAccelerationToggle = + subsection.shadowRoot!.querySelector('#mouseAcceleration'); + subsection.set('mouseIndex', 1); + // Enter the page from auto repeat search tag. + const url = new URLSearchParams( + 'search=mouse+accel&settingId=' + + encodeURIComponent(MOUSE_ACCELERATION_SETTING_ID)); + + await Router.getInstance().navigateTo( + routes.PER_DEVICE_MOUSE, + /* dynamicParams= */ url, /* removeSearch= */ true); + await flushTasks(); + + assert(mouseAccelerationToggle); + assertEquals(null, subsection.shadowRoot!.activeElement); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_search_page/search_subpage_test.ts b/chrome/test/data/webui/settings/chromeos/os_search_page/search_subpage_test.ts new file mode 100644 index 0000000..5269d669 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/os_search_page/search_subpage_test.ts
@@ -0,0 +1,291 @@ +// Copyright 2021 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://os-settings/chromeos/lazy_load.js'; + +import {SettingsSearchSubpageElement} from 'chrome://os-settings/chromeos/lazy_load.js'; +import {CrSettingsPrefs, Router, routes, SettingsPrefsElement, SettingsToggleButtonElement} from 'chrome://os-settings/chromeos/os_settings.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; +import {getDeepActiveElement} from 'chrome://resources/js/util_ts.js'; +import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; + +suite('<settings-search-subpage>', () => { + let page: SettingsSearchSubpageElement; + let prefElement: SettingsPrefsElement; + + suiteSetup(() => { + loadTimeData.overrideValues({ + shouldShowQuickAnswersSettings: true, + quickAnswersSubToggleEnabled: true, + }); + }); + + setup(async () => { + prefElement = document.createElement('settings-prefs'); + document.body.appendChild(prefElement); + + await CrSettingsPrefs.initialized; + page = document.createElement('settings-search-subpage'); + page.prefs = prefElement.prefs; + document.body.appendChild(page); + flush(); + }); + + teardown(() => { + page.remove(); + prefElement.remove(); + CrSettingsPrefs.resetForTesting(); + }); + + test('definitionToggleVisibility', () => { + let button = + page.shadowRoot!.querySelector('#quick-answers-definition-enable'); + assertEquals(null, button); + + page.setPrefValue('settings.quick_answers.enabled', true); + flush(); + + button = page.shadowRoot!.querySelector('#quick-answers-definition-enable'); + assert(button); + }); + + test('translationToggleVisibility', () => { + let button = + page.shadowRoot!.querySelector('#quick-answers-translation-enable'); + assertEquals(null, button); + + page.setPrefValue('settings.quick_answers.enabled', true); + flush(); + + button = + page.shadowRoot!.querySelector('#quick-answers-translation-enable'); + assert(button); + }); + + test('unitConversionToggleVisibility', () => { + let button = + page.shadowRoot!.querySelector('#quick-answers-unit-conversion-enable'); + assertEquals(null, button); + + page.setPrefValue('settings.quick_answers.enabled', true); + flush(); + + button = + page.shadowRoot!.querySelector('#quick-answers-unit-conversion-enable'); + assert(button); + }); + + test('toggleQuickAnswers', () => { + flush(); + const button = page.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#quick-answers-enable'); + assert(button); + assertFalse(button.disabled); + assertFalse(button.checked); + + let definitionButton = + page.shadowRoot!.querySelector('#quick-answers-definition-enable'); + let translationButton = + page.shadowRoot!.querySelector('#quick-answers-translation-enable'); + let unitConversionButton = + page.shadowRoot!.querySelector('#quick-answers-unit-conversion-enable'); + assertEquals(null, definitionButton); + assertEquals(null, translationButton); + assertEquals(null, unitConversionButton); + + // Tap the enable toggle button and ensure the state becomes enabled. + button.click(); + flush(); + assertTrue(button.checked); + + definitionButton = + page.shadowRoot!.querySelector('#quick-answers-definition-enable'); + translationButton = + page.shadowRoot!.querySelector('#quick-answers-translation-enable'); + unitConversionButton = + page.shadowRoot!.querySelector('#quick-answers-unit-conversion-enable'); + assert(definitionButton); + assert(translationButton); + assert(unitConversionButton); + }); + + test('toggleQuickAnswersDefinition', () => { + let button = page.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#quick-answers-definition-enable'); + assertEquals(null, button); + page.setPrefValue('settings.quick_answers.enabled', true); + page.setPrefValue('settings.quick_answers.definition.enabled', false); + flush(); + + button = page.shadowRoot!.querySelector('#quick-answers-definition-enable'); + assert(button); + assertFalse(button.disabled); + assertFalse(button.checked); + + button.click(); + flush(); + assertTrue(button.checked); + assertTrue(page.getPref('settings.quick_answers.definition.enabled').value); + }); + + test('toggleQuickAnswersTranslation', () => { + let button = page.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#quick-answers-translation-enable'); + assertEquals(null, button); + page.setPrefValue('settings.quick_answers.enabled', true); + page.setPrefValue('settings.quick_answers.translation.enabled', false); + flush(); + + button = + page.shadowRoot!.querySelector('#quick-answers-translation-enable'); + assert(button); + assertFalse(button.disabled); + assertFalse(button.checked); + + button.click(); + flush(); + assertTrue(button.checked); + assertTrue( + page.getPref('settings.quick_answers.translation.enabled').value); + }); + + test('clickLanguageSettingsLink', () => { + let button = page.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#quick-answers-translation-enable'); + assertEquals(null, button); + page.setPrefValue('settings.quick_answers.enabled', true); + page.setPrefValue('settings.quick_answers.translation.enabled', false); + flush(); + + button = + page.shadowRoot!.querySelector('#quick-answers-translation-enable'); + assert(button); + assertFalse(button.disabled); + assertFalse(button.checked); + + const languageSettingsLink = + button.shadowRoot!.querySelector( + '#sub-label-text-with-link')!.querySelector('a'); + assert(languageSettingsLink); + + languageSettingsLink.click(); + flush(); + assertFalse(button.checked); + assertFalse( + page.getPref('settings.quick_answers.translation.enabled').value); + + assertEquals( + routes.OS_LANGUAGES_LANGUAGES, Router.getInstance().currentRoute); + }); + + test('toggleQuickAnswersUnitConversion', () => { + let button = page.shadowRoot!.querySelector<SettingsToggleButtonElement>( + '#quick-answers-unit-conversion-enable'); + assertEquals(null, button); + page.setPrefValue('settings.quick_answers.enabled', true); + page.setPrefValue('settings.quick_answers.unit_conversion.enabled', false); + flush(); + + button = + page.shadowRoot!.querySelector('#quick-answers-unit-conversion-enable'); + assert(button); + assertFalse(button.disabled); + assertFalse(button.checked); + + button.click(); + flush(); + assertTrue(button.checked); + assertTrue( + page.getPref('settings.quick_answers.unit_conversion.enabled').value); + }); + + test('Deep link to Preferred Search Engine', async () => { + const params = new URLSearchParams(); + params.append('settingId', '600'); + Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); + + const browserSearchSettingsLink = + page.shadowRoot!.querySelector('settings-search-engine')!.shadowRoot! + .querySelector('#browserSearchSettingsLink'); + const deepLinkElement = + browserSearchSettingsLink!.shadowRoot!.querySelector('cr-icon-button'); + assert(deepLinkElement); + await waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Preferred Search Engine button should be focused for settingId=600.'); + }); + + test('Deep link to Quick Answers On/Off', async () => { + const params = new URLSearchParams(); + params.append('settingId', '608'); + Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); + + const deepLinkElement = + page.shadowRoot!.querySelector('#quick-answers-enable')!.shadowRoot! + .querySelector('cr-toggle'); + assert(deepLinkElement); + await waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Quick Answer On/Off toggle should be focused for settingId=608.'); + }); + + test('Deep link to Quick Answers Definition', async () => { + page.setPrefValue('settings.quick_answers.enabled', true); + flush(); + + const params = new URLSearchParams(); + params.append('settingId', '609'); + Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); + + const deepLinkElement = + page.shadowRoot!.querySelector('#quick-answers-definition-enable')! + .shadowRoot!.querySelector('cr-toggle'); + assert(deepLinkElement); + await waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Quick Answer definition toggle should be focused for settingId=609.'); + }); + + test('Deep link to Quick Answers Translation', async () => { + page.setPrefValue('settings.quick_answers.enabled', true); + flush(); + + const params = new URLSearchParams(); + params.append('settingId', '610'); + Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); + + const deepLinkElement = + page.shadowRoot!.querySelector('#quick-answers-translation-enable')! + .shadowRoot!.querySelector('cr-toggle'); + assert(deepLinkElement); + await waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Quick Answer translation toggle should be focused for settingId=610.'); + }); + + test('Deep link to Quick Answers Unit Conversion', async () => { + page.setPrefValue('settings.quick_answers.enabled', true); + flush(); + + const params = new URLSearchParams(); + params.append('settingId', '611'); + Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); + + const deepLinkElement = + page.shadowRoot!.querySelector('#quick-answers-unit-conversion-enable')! + .shadowRoot!.querySelector('cr-toggle'); + assert(deepLinkElement); + await waitAfterNextRender(deepLinkElement); + assertEquals( + deepLinkElement, getDeepActiveElement(), + 'Quick Answer unit conversion toggle should be focused for settingId=611.'); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index 1cbb3b1..a52a8c8df 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -266,6 +266,11 @@ {enabled: ['ash::features::kInputDeviceSettingsSplit']} ], [ + 'DevicePagePerDeviceMouseSubsection', + 'device_page/per_device_mouse_subsection_test.js', + {enabled: ['ash::features::kInputDeviceSettingsSplit']} + ], + [ 'DevicePagePerDevicePointingStick', 'device_page/per_device_pointing_stick_test.js', {enabled: ['ash::features::kInputDeviceSettingsSplit']} @@ -424,6 +429,7 @@ ['OsPairedBluetoothListItem', 'os_paired_bluetooth_list_item_tests.js'], ['OsPeoplePageAddUserDialog', 'os_people_page/add_user_dialog_tests.js'], ['OsPrintingPage', 'os_printing_page/os_printing_page_tests.js'], + ['OsSearchPageSearchSubpage', 'os_search_page/search_subpage_test.js'], ['OsSettingsPage', 'os_settings_page_test.js'], ['OsSettingsUi', 'os_settings_ui/os_settings_ui_test.js'], ['OsSettingsUiAboutPage', 'os_settings_ui/os_settings_ui_about_page_test.js'], @@ -468,10 +474,6 @@ {enabled: ['ash::features::kInputDeviceSettingsSplit']}, ], [ - 'PerDeviceMouseSubsection', 'per_device_mouse_subsection_test.js', - {enabled: ['ash::features::kInputDeviceSettingsSplit']} - ], - [ 'PerDevicePointingStickSubsection', 'per_device_pointing_stick_subsection_test.js', {enabled: ['ash::features::kInputDeviceSettingsSplit']} @@ -497,7 +499,6 @@ ['PrivacyPage', 'os_privacy_page_test.js'], ['ResetPage', 'os_reset_page_test.js'], ['SettingsSchedulerSlider', 'settings_scheduler_slider_test.js'], - ['SearchSubpage', 'search_subpage_test.js'], [ 'SelectToSpeakSubpage', 'select_to_speak_subpage_tests.js',
diff --git a/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js b/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js index 5ea449f1..a21782c 100644 --- a/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js +++ b/chrome/test/data/webui/settings/chromeos/per_device_keyboard_remap_keys_test.js
@@ -28,13 +28,13 @@ provider = null; }); - async function initializeRemapKeysPage() { + async function initializeRemapKeysPage(keyboards = fakeKeyboards) { page = document.createElement('settings-per-device-keyboard-remap-keys'); - assertFalse(page.isInitialized); + page.keyboards = keyboards; // Set the current route with keyboardId as search param and notify // the observer to update keyboard settings. const url = new URLSearchParams( - 'keyboardId=' + encodeURIComponent(fakeKeyboards[0].id)); + 'keyboardId=' + encodeURIComponent(keyboards[0].id)); await Router.getInstance().setCurrentRoute( routes.PER_DEVICE_KEYBOARD_REMAP_KEYS, /* dynamicParams= */ url, /* removeSearch= */ true); @@ -44,6 +44,11 @@ return flushTasks(); } + async function setKeyboards(keyboards) { + page.keyboards = keyboards; + return flushTasks(); + } + /** * Check that all the prefs are set to default keyboard value. */ @@ -63,11 +68,6 @@ assertEquals(page.fakeMetaPref.value, metaDefaultMapping); } - async function getConnectedKeyboardSettings() { - const keyboards = await provider.getConnectedKeyboardSettings(); - return keyboards; - } - /** * Verify that the remap subpage is correctly loaded with keyboard data. */ @@ -241,8 +241,9 @@ assertEquals( routes.PER_DEVICE_KEYBOARD_REMAP_KEYS, Router.getInstance().currentRoute); + assertEquals(page.keyboardId, page.keyboards[0].id); const updatedKeyboards = [fakeKeyboards[1], fakeKeyboards[2]]; - page.onKeyboardListUpdated(updatedKeyboards); + await setKeyboards(updatedKeyboards); assertEquals(routes.PER_DEVICE_KEYBOARD, Router.getInstance().currentRoute); }); @@ -266,7 +267,7 @@ page.set('fakeEscPref.value', ModifierKey.kVoid); // Verify that the keyboard settings in the provider are updated. - const keyboards = await getConnectedKeyboardSettings(); + const keyboards = page.keyboards; assertTrue(!!keyboards); const updatedRemapping = keyboards[0].settings.modifierRemappings; assertTrue(!!updatedRemapping);
diff --git a/chrome/test/data/webui/settings/chromeos/per_device_mouse_subsection_test.js b/chrome/test/data/webui/settings/chromeos/per_device_mouse_subsection_test.js deleted file mode 100644 index 5f0cc4a..0000000 --- a/chrome/test/data/webui/settings/chromeos/per_device_mouse_subsection_test.js +++ /dev/null
@@ -1,226 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -import 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; - -import {FakeInputDeviceSettingsProvider, fakeMice, Router, routes, setInputDeviceSettingsProviderForTesting, SettingsPerDeviceMouseSubsectionElement} from 'chrome://os-settings/chromeos/os_settings.js'; -import {assert} from 'chrome://resources/ash/common/assert.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; -import {isVisible} from 'chrome://webui-test/test_util.js'; - -const MOUSE_ACCELERATION_SETTING_ID = 408; - -suite('PerDeviceMouseSubsection', function() { - /** - * @type {?SettingsPerDeviceMouseSubsectionElement} - */ - let subsection = null; - /** - * @type {?FakeInputDeviceSettingsProvider} - */ - let provider = null; - - setup(() => { - PolymerTest.clearBody(); - }); - - teardown(() => { - subsection = null; - provider = null; - }); - - /** - * @return {!Promise} - */ - function initializePerDeviceMouseSubsection() { - provider = new FakeInputDeviceSettingsProvider(); - provider.setFakeMice(fakeMice); - setInputDeviceSettingsProviderForTesting(provider); - subsection = document.createElement('settings-per-device-mouse-subsection'); - assertTrue(subsection != null); - subsection.mouse = {...fakeMice[0]}; - subsection.allowScrollSettings_ = true; - document.body.appendChild(subsection); - return flushTasks(); - } - - /** - * @param {!Object} mouse - * @param {!Boolean} allowScrollSettings - * @return {!Promise} - */ - function changeMouseSubsectionState(mouse, allowScrollSettings) { - subsection.mouse = mouse; - subsection.allowScrollSettings_ = allowScrollSettings; - return flushTasks(); - } - - async function getConnectedMouseSettings() { - const mice = await provider.getConnectedMouseSettings(); - return mice; - } - - // Test that API are updated when mouse settings change. - test('Update API when mouse settings change', async () => { - await initializePerDeviceMouseSubsection(); - const mouseSwapButtonDropdown = - subsection.shadowRoot.querySelector('#mouseSwapButtonDropdown'); - mouseSwapButtonDropdown.pref = { - ...mouseSwapButtonDropdown.pref, - value: false, - }; - await flushTasks(); - let updatedMice = await getConnectedMouseSettings(); - assertEquals( - updatedMice[0].settings.swapRight, mouseSwapButtonDropdown.pref.value); - - const mouseAccelerationToggleButton = - subsection.shadowRoot.querySelector('#mouseAcceleration'); - mouseAccelerationToggleButton.click(); - await flushTasks(); - updatedMice = await getConnectedMouseSettings(); - assertEquals( - updatedMice[0].settings.accelerationEnabled, - mouseAccelerationToggleButton.pref.value); - - const mouseSpeedSlider = - assert(subsection.shadowRoot.querySelector('#mouseSpeedSlider')); - MockInteractions.pressAndReleaseKeyOn( - mouseSpeedSlider.shadowRoot.querySelector('cr-slider'), 39 /* right */, - [], 'ArrowRight'); - await flushTasks(); - updatedMice = await getConnectedMouseSettings(); - assertEquals( - updatedMice[0].settings.sensitivity, mouseSpeedSlider.pref.value); - - const mouseReverseScrollToggleButton = - subsection.shadowRoot.querySelector('#mouseReverseScroll'); - mouseReverseScrollToggleButton.click(); - await flushTasks(); - updatedMice = await getConnectedMouseSettings(); - assertEquals( - updatedMice[0].settings.reverseScrolling, - mouseReverseScrollToggleButton.checked); - - const mouseScrollAccelerationToggleButton = - subsection.shadowRoot.querySelector('#mouseScrollAcceleration'); - mouseScrollAccelerationToggleButton.click(); - await flushTasks(); - updatedMice = await getConnectedMouseSettings(); - assertEquals( - updatedMice[0].settings.scrollAcceleration, - mouseScrollAccelerationToggleButton.pref.value); - - const mouseScrollSpeedSlider = - assert(subsection.shadowRoot.querySelector('#mouseScrollSpeedSlider')); - MockInteractions.pressAndReleaseKeyOn( - mouseScrollSpeedSlider.shadowRoot.querySelector('cr-slider'), - 39 /* right */, [], 'ArrowRight'); - await flushTasks(); - updatedMice = await getConnectedMouseSettings(); - assertEquals( - updatedMice[0].settings.scrollSensitivity, - mouseScrollSpeedSlider.pref.value); - }); - - // Test that mouse settings data are from the mouse provider. - test('Verify mouse settings data', async () => { - await initializePerDeviceMouseSubsection(); - let mouseSwapButtonDropdown = - subsection.shadowRoot.querySelector('#mouseSwapButtonDropdown'); - assertEquals( - fakeMice[0].settings.swapRight, mouseSwapButtonDropdown.pref.value); - let mouseAccelerationToggleButton = - subsection.shadowRoot.querySelector('#mouseAcceleration'); - assertEquals( - fakeMice[0].settings.accelerationEnabled, - mouseAccelerationToggleButton.pref.value); - let mouseSpeedSlider = - assert(subsection.shadowRoot.querySelector('#mouseSpeedSlider')); - assertEquals(fakeMice[0].settings.sensitivity, mouseSpeedSlider.pref.value); - assertEquals( - fakeMice[0].settings.reverseScrolling, subsection.reverseScrollValue); - let mouseScrollAccelerationToggleButton = - subsection.shadowRoot.querySelector('#mouseScrollAcceleration'); - assertTrue(isVisible(mouseScrollAccelerationToggleButton)); - assertEquals( - fakeMice[0].settings.scrollAcceleration, - mouseScrollAccelerationToggleButton.pref.value); - let mouseScrollSpeedSlider = - assert(subsection.shadowRoot.querySelector('#mouseScrollSpeedSlider')); - assertTrue(isVisible(mouseScrollSpeedSlider)); - assertEquals( - fakeMice[0].settings.scrollSensitivity, - mouseScrollSpeedSlider.pref.value); - - await changeMouseSubsectionState(fakeMice[1], false); - mouseSwapButtonDropdown = - subsection.shadowRoot.querySelector('#mouseSwapButtonDropdown'); - assertEquals( - fakeMice[1].settings.swapRight, mouseSwapButtonDropdown.pref.value); - mouseAccelerationToggleButton = - subsection.shadowRoot.querySelector('#mouseAcceleration'); - assertEquals( - fakeMice[1].settings.accelerationEnabled, - mouseAccelerationToggleButton.pref.value); - mouseSpeedSlider = - assert(subsection.shadowRoot.querySelector('#mouseSpeedSlider')); - assertEquals(fakeMice[1].settings.sensitivity, mouseSpeedSlider.pref.value); - assertEquals( - fakeMice[1].settings.reverseScrolling, subsection.reverseScrollValue); - mouseScrollAccelerationToggleButton = - subsection.shadowRoot.querySelector('#mouseScrollAcceleration'); - assertFalse(isVisible(mouseScrollAccelerationToggleButton)); - mouseScrollSpeedSlider = - subsection.shadowRoot.querySelector('#mouseScrollSpeedSlider'); - assertFalse(isVisible(mouseScrollSpeedSlider)); - }); - - /** - * Verify entering the page with search tags matched will auto focus the - * searched element. - */ - test('deep linking mixin focus on the first searched element', async () => { - await initializePerDeviceMouseSubsection(); - const mouseAccelerationToggle = - subsection.shadowRoot.querySelector('#mouseAcceleration'); - subsection.mouseIndex = 0; - // Enter the page from auto repeat search tag. - const url = new URLSearchParams( - 'search=mouse+accel&settingId=' + - encodeURIComponent(MOUSE_ACCELERATION_SETTING_ID)); - - await Router.getInstance().navigateTo( - routes.PER_DEVICE_MOUSE, - /* dynamicParams= */ url, /* removeSearch= */ true); - - await waitAfterNextRender(mouseAccelerationToggle); - assertTrue(!!mouseAccelerationToggle); - assertEquals(subsection.shadowRoot.activeElement, mouseAccelerationToggle); - }); - - /** - * Verify entering the page with search tags matched wll not auto focus the - * searched element if it's not the first keyboard displayed. - */ - test('deep linkng mixin does not focus on second element', async () => { - await initializePerDeviceMouseSubsection(); - const mouseAccelerationToggle = - subsection.shadowRoot.querySelector('#mouseAcceleration'); - subsection.mouseIndex = 1; - // Enter the page from auto repeat search tag. - const url = new URLSearchParams( - 'search=mouse+accel&settingId=' + - encodeURIComponent(MOUSE_ACCELERATION_SETTING_ID)); - - await Router.getInstance().navigateTo( - routes.PER_DEVICE_MOUSE, - /* dynamicParams= */ url, /* removeSearch= */ true); - await flushTasks(); - - assertTrue(!!mouseAccelerationToggle); - assertFalse(!!subsection.shadowRoot.activeElement); - }); -});
diff --git a/chrome/test/data/webui/settings/chromeos/search_subpage_test.js b/chrome/test/data/webui/settings/chromeos/search_subpage_test.js deleted file mode 100644 index 6f2b5fd..0000000 --- a/chrome/test/data/webui/settings/chromeos/search_subpage_test.js +++ /dev/null
@@ -1,286 +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 'chrome://os-settings/chromeos/lazy_load.js'; - -import {CrSettingsPrefs, Router, routes} from 'chrome://os-settings/chromeos/os_settings.js'; -import {getDeepActiveElement} from 'chrome://resources/ash/common/util.js'; -import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import {waitAfterNextRender} from 'chrome://webui-test/polymer_test_util.js'; - -suite('SearchSubpage', function() { - /** @type {SearchSubpageElement} */ - let page = null; - - suiteSetup(function() { - loadTimeData.overrideValues({ - shouldShowQuickAnswersSettings: true, - quickAnswersSubToggleEnabled: true, - }); - }); - - setup(function() { - PolymerTest.clearBody(); - - const prefElement = document.createElement('settings-prefs'); - document.body.appendChild(prefElement); - - return CrSettingsPrefs.initialized.then(function() { - page = document.createElement('settings-search-subpage'); - page.prefs = prefElement.prefs; - document.body.appendChild(page); - flush(); - }); - }); - - teardown(function() { - page.remove(); - CrSettingsPrefs.resetForTesting(); - }); - - test('definitionToggleVisibility', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-definition-enable'); - assertFalse(!!button); - - page.setPrefValue('settings.quick_answers.enabled', true); - flush(); - - button = page.shadowRoot.querySelector('#quick-answers-definition-enable'); - assertTrue(!!button); - }); - - test('translationToggleVisibility', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-translation-enable'); - assertFalse(!!button); - - page.setPrefValue('settings.quick_answers.enabled', true); - flush(); - - button = page.shadowRoot.querySelector('#quick-answers-translation-enable'); - assertTrue(!!button); - }); - - test('unitConversionToggleVisibility', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable'); - assertFalse(!!button); - - page.setPrefValue('settings.quick_answers.enabled', true); - flush(); - - button = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable'); - assertTrue(!!button); - }); - - test('toggleQuickAnswers', function() { - flush(); - const button = page.shadowRoot.querySelector('#quick-answers-enable'); - assertTrue(!!button); - assertFalse(button.disabled); - assertFalse(button.checked); - - let definition_button = - page.shadowRoot.querySelector('#quick-answers-definition-enable'); - let translation_button = - page.shadowRoot.querySelector('#quick-answers-translation-enable'); - let unit_conversion_button = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable'); - assertFalse(!!definition_button); - assertFalse(!!translation_button); - assertFalse(!!unit_conversion_button); - - // Tap the enable toggle button and ensure the state becomes enabled. - button.click(); - flush(); - assertTrue(button.checked); - - definition_button = - page.shadowRoot.querySelector('#quick-answers-definition-enable'); - translation_button = - page.shadowRoot.querySelector('#quick-answers-translation-enable'); - unit_conversion_button = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable'); - assertTrue(!!definition_button); - assertTrue(!!translation_button); - assertTrue(!!unit_conversion_button); - }); - - test('toggleQuickAnswersDefinition', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-definition-enable'); - assertFalse(!!button); - page.setPrefValue('settings.quick_answers.enabled', true); - page.setPrefValue('settings.quick_answers.definition.enabled', false); - flush(); - - button = page.shadowRoot.querySelector('#quick-answers-definition-enable'); - assertTrue(!!button); - assertFalse(button.disabled); - assertFalse(button.checked); - - button.click(); - flush(); - assertTrue(button.checked); - assertTrue(page.getPref('settings.quick_answers.definition.enabled.value')); - }); - - test('toggleQuickAnswersTranslation', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-translation-enable'); - assertFalse(!!button); - page.setPrefValue('settings.quick_answers.enabled', true); - page.setPrefValue('settings.quick_answers.translation.enabled', false); - flush(); - - button = page.shadowRoot.querySelector('#quick-answers-translation-enable'); - assertTrue(!!button); - assertFalse(button.disabled); - assertFalse(button.checked); - - button.click(); - flush(); - assertTrue(button.checked); - assertTrue( - page.getPref('settings.quick_answers.translation.enabled.value')); - }); - - test('clickLanguageSettingsLink', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-translation-enable'); - assertFalse(!!button); - page.setPrefValue('settings.quick_answers.enabled', true); - page.setPrefValue('settings.quick_answers.translation.enabled', false); - flush(); - - button = page.shadowRoot.querySelector('#quick-answers-translation-enable'); - assertTrue(!!button); - assertFalse(button.disabled); - assertFalse(button.checked); - - const languageSettingsLink = - button.shadowRoot.querySelector('#sub-label-text-with-link') - .querySelector('a'); - assertTrue(!!languageSettingsLink); - - languageSettingsLink.click(); - flush(); - assertFalse(button.checked); - assertFalse( - page.getPref('settings.quick_answers.translation.enabled.value')); - - assertEquals( - routes.OS_LANGUAGES_LANGUAGES, Router.getInstance().currentRoute); - }); - - test('toggleQuickAnswersUnitConversion', function() { - let button = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable'); - assertFalse(!!button); - page.setPrefValue('settings.quick_answers.enabled', true); - page.setPrefValue('settings.quick_answers.unit_conversion.enabled', false); - flush(); - - button = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable'); - assertTrue(!!button); - assertFalse(button.disabled); - assertFalse(button.checked); - - button.click(); - flush(); - assertTrue(button.checked); - assertTrue( - page.getPref('settings.quick_answers.unit_conversion.enabled.value')); - }); - - test('Deep link to Preferred Search Engine', async () => { - const params = new URLSearchParams(); - params.append('settingId', '600'); - Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); - - const browserSearchSettingsLink = - page.shadowRoot.querySelector('settings-search-engine') - .shadowRoot.querySelector('#browserSearchSettingsLink'); - const deepLinkElement = - browserSearchSettingsLink.shadowRoot.querySelector('cr-icon-button'); - assertTrue(!!deepLinkElement); - await waitAfterNextRender(deepLinkElement); - assertEquals( - deepLinkElement, getDeepActiveElement(), - 'Preferred Search Engine button should be focused for settingId=600.'); - }); - - test('Deep link to Quick Answers On/Off', async () => { - const params = new URLSearchParams(); - params.append('settingId', '608'); - Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); - - const deepLinkElement = - page.shadowRoot.querySelector('#quick-answers-enable') - .shadowRoot.querySelector('cr-toggle'); - assertTrue(!!deepLinkElement); - await waitAfterNextRender(deepLinkElement); - assertEquals( - deepLinkElement, getDeepActiveElement(), - 'Quick Answer On/Off toggle should be focused for settingId=608.'); - }); - - test('Deep link to Quick Answers Definition', async () => { - page.setPrefValue('settings.quick_answers.enabled', true); - flush(); - - const params = new URLSearchParams(); - params.append('settingId', '609'); - Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); - - const deepLinkElement = - page.shadowRoot.querySelector('#quick-answers-definition-enable') - .shadowRoot.querySelector('cr-toggle'); - assertTrue(!!deepLinkElement); - await waitAfterNextRender(deepLinkElement); - assertEquals( - deepLinkElement, getDeepActiveElement(), - 'Quick Answer definition toggle should be focused for settingId=609.'); - }); - - test('Deep link to Quick Answers Translation', async () => { - page.setPrefValue('settings.quick_answers.enabled', true); - flush(); - - const params = new URLSearchParams(); - params.append('settingId', '610'); - Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); - - const deepLinkElement = - page.shadowRoot.querySelector('#quick-answers-translation-enable') - .shadowRoot.querySelector('cr-toggle'); - assertTrue(!!deepLinkElement); - await waitAfterNextRender(deepLinkElement); - assertEquals( - deepLinkElement, getDeepActiveElement(), - 'Quick Answer translation toggle should be focused for settingId=610.'); - }); - - test('Deep link to Quick Answers Unit Conversion', async () => { - page.setPrefValue('settings.quick_answers.enabled', true); - flush(); - - const params = new URLSearchParams(); - params.append('settingId', '611'); - Router.getInstance().navigateTo(routes.SEARCH_SUBPAGE, params); - - const deepLinkElement = - page.shadowRoot.querySelector('#quick-answers-unit-conversion-enable') - .shadowRoot.querySelector('cr-toggle'); - assertTrue(!!deepLinkElement); - await waitAfterNextRender(deepLinkElement); - assertEquals( - deepLinkElement, getDeepActiveElement(), - 'Quick Answer unit conversion toggle should be focused for settingId=611.'); - }); -});
diff --git a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc index fd05563e..8f93014 100644 --- a/chromeos/ash/components/drivefs/drivefs_pin_manager.cc +++ b/chromeos/ash/components/drivefs/drivefs_pin_manager.cc
@@ -912,9 +912,12 @@ using State = mojom::ItemEvent::State; switch (event.state) { case State::kQueued: - // kQueued events come with a bytes_to_transfer field incorrectly set to - // zero (b/266462624). So we set it to -1 to ignore it. - event.bytes_to_transfer = -1; + // (TODO b/266462624) kQueued events come with a bytes_to_transfer field + // incorrectly set to zero. So we set it to -1 to ignore it. + if (event.bytes_to_transfer == 0) { + VLOG(3) << "Zero bytes_to_transfer in " << Quote(event); + event.bytes_to_transfer = -1; + } [[fallthrough]]; case State::kInProgress:
diff --git a/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl_unittest.cc b/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl_unittest.cc index 348380e..46c376db 100644 --- a/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl_unittest.cc +++ b/chromeos/ash/services/bluetooth_config/device_pairing_handler_impl_unittest.cc
@@ -94,12 +94,16 @@ true, success_count); } - void CheckPairingFailureReasonHistogram( + void CheckPairingFailureHistogram( device::ConnectionFailureReason failure_reason, - int count) { + size_t failure_count, + size_t filtered_count) { histogram_tester.ExpectBucketCount( "Bluetooth.ChromeOS.Pairing.Result.FailureReason", failure_reason, - count); + failure_count); + histogram_tester.ExpectBucketCount( + "Bluetooth.ChromeOS.Pairing.Result.FilteredFailureReason", + failure_reason, filtered_count); } void CheckDurationHistogramMetrics(base::TimeDelta bucket, @@ -368,8 +372,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -384,8 +388,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/2, /*failure_count=*/1, /*success_count=*/1); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/1, /*failure_count=*/0, /*transport_name=*/"Classic"); @@ -409,8 +413,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kInvalid, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(base::Milliseconds(0), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Invalid"); @@ -434,8 +438,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -454,8 +458,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(base::Milliseconds(0), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -512,8 +516,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -530,10 +534,10 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/2, /*failure_count=*/2, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -561,8 +565,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kInvalid, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Invalid"); @@ -586,8 +590,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -601,8 +605,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kInvalid, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(base::Milliseconds(0), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Invalid"); @@ -659,8 +663,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthRejected, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthRejected, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -684,8 +688,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kInvalid, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Invalid"); @@ -706,8 +710,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kInprogress, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kInprogress, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -732,8 +736,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kInvalid, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Invalid"); @@ -756,8 +760,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -770,8 +774,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -803,8 +807,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -857,8 +861,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -880,8 +884,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -900,8 +904,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -926,8 +930,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic"); @@ -954,10 +958,10 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/2, /*failure_count=*/2, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthCanceled, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthCanceled, + /*failure_count=*/1, /*filtered_count=*/0); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/2, /*transport_name=*/"Classic"); @@ -984,8 +988,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kInvalid, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram(device::ConnectionFailureReason::kFailed, - /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(kTestDuration, /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Invalid"); @@ -1008,8 +1012,8 @@ CheckPairingHistograms(device::BluetoothTransportType::kClassic, /*type_count=*/1, /*failure_count=*/1, /*success_count=*/0); - CheckPairingFailureReasonHistogram( - device::ConnectionFailureReason::kAuthFailed, /*count=*/1); + CheckPairingFailureHistogram(device::ConnectionFailureReason::kAuthFailed, + /*failure_count=*/1, /*filtered_count=*/1); CheckDurationHistogramMetrics(GetPairingFailureDelay(), /*success_count=*/0, /*failure_count=*/1, /*transport_name=*/"Classic");
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index f24ef42c..2da53294 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -301,6 +301,11 @@ Report this query </message> + <!-- Rich Answers --> + <message name="IDS_RICH_ANSWERS_VIEW_A11Y_NAME_TEXT" desc="A11y name text for the Rich Answers view."> + Additional info related to your selection + </message> + <!-- Multitask Menu --> <message name="IDS_MULTITASK_MENU_HALF_BUTTON_NAME" desc="Title of the half button on the multitask menu."> Half
diff --git a/chromeos/chromeos_strings_grd/IDS_RICH_ANSWERS_VIEW_A11Y_NAME_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_RICH_ANSWERS_VIEW_A11Y_NAME_TEXT.png.sha1 new file mode 100644 index 0000000..46f3913 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_RICH_ANSWERS_VIEW_A11Y_NAME_TEXT.png.sha1
@@ -0,0 +1 @@ +9cb8d4b5c369e3b5be33f51039fd837d12ab708e \ No newline at end of file
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc index e13fafa9..2346210 100644 --- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc +++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
@@ -67,10 +67,11 @@ suggestion_shown_timestamp_ = AutofillTickClock::NowTicks(); - // Log if metadata is shown for any of the suggestions. - if (metadata_logging_context_.IsCardMetadataShown()) { - Log(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN, form); - } + // Log if any of the suggestions had metadata. + Log(metadata_logging_context_.card_metadata_available + ? FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN + : FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SHOWN, + form); } void CreditCardFormEventLogger::OnDidSelectCardSuggestion( @@ -114,12 +115,13 @@ AutofillTickClock::NowTicks() - suggestion_shown_timestamp_, metadata_logging_context_, credit_card); - // Log if the selected suggestion had metadata shown. + // Log if the selected suggestion had metadata. metadata_logging_context_ = autofill_metrics::GetMetadataLoggingContext({credit_card}); - if (metadata_logging_context_.IsCardMetadataShown()) { - Log(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED, form); - } + Log(metadata_logging_context_.card_metadata_available + ? FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED + : FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SELECTED, + form); } void CreditCardFormEventLogger::OnDidFillSuggestion(
diff --git a/components/autofill/core/browser/metrics/form_events/form_events.h b/components/autofill/core/browser/metrics/form_events/form_events.h index 013d1452..f213e08 100644 --- a/components/autofill/core/browser/metrics/form_events/form_events.h +++ b/components/autofill/core/browser/metrics/form_events/form_events.h
@@ -143,11 +143,15 @@ // after being autofilled. Recorded once per form. FORM_EVENT_AUTOFILLED_FIELD_CLEARED_BY_JAVASCRIPT_AFTER_FILL_ONCE = 57, - // Suggestions were shown, and they included a credit card that had metadata - // shown. + // Credit card suggestions were shown, and it included at least one suggestion + // with metadata. FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN = 58, - // The selected card suggestion had metadata shown. - FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED = 59, + // Credit card suggestions were shown, and none had metadata. + FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SHOWN = 59, + // The selected credit card suggestion had metadata. + FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED = 60, + // The selected credit card suggestion did not have metadata. + FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SELECTED = 61, NUM_FORM_EVENTS, };
diff --git a/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc b/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc index 01799a9..0e466c8 100644 --- a/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc +++ b/components/autofill/core/browser/metrics/payments/card_metadata_metrics_unittest.cc
@@ -16,43 +16,20 @@ namespace { -constexpr char kCardWithoutMetadataId[] = - "10000000-0000-0000-0000-000000000001"; -constexpr char kCardWithMetadataId[] = "10000000-0000-0000-0000-000000000002"; +constexpr char kCardGuid[] = "10000000-0000-0000-0000-000000000001"; } // namespace -// Params: -// 1) Whether card product name feature flag is enabled. -// 2) whether card art image feature flag is enabled. -// 3) Whether card metadata (both product name and card art image) are provided. -// 4) Whether the card has linked virtual card (only card art is provided). -class CardMetadataMetricsTest +// Param: Whether card metadata is available. +class CardMetadataFormEventMetricsTest : public AutofillMetricsBaseTest, public testing::Test, - public testing::WithParamInterface<std::tuple<bool, bool, bool, bool>> { + public testing::WithParamInterface<bool> { public: - CardMetadataMetricsTest() - : card_product_name_enabled_(std::get<0>(GetParam())), - card_art_image_enabled_(std::get<1>(GetParam())), - card_metadata_available_(std::get<2>(GetParam())), - card_has_linked_virtual_card_(std::get<3>(GetParam())) { - feature_list_card_product_name_.InitWithFeatureState( - features::kAutofillEnableCardProductName, card_product_name_enabled_); - feature_list_card_art_image_.InitWithFeatureState( - features::kAutofillEnableCardArtImage, card_art_image_enabled_); - } - ~CardMetadataMetricsTest() override = default; + CardMetadataFormEventMetricsTest() : card_metadata_available_(GetParam()) {} + ~CardMetadataFormEventMetricsTest() override = default; - bool card_product_name_enabled() { return card_product_name_enabled_; } - bool card_art_image_enabled() { return card_art_image_enabled_; } bool card_metadata_available() { return card_metadata_available_; } - bool card_has_linked_virtual_card() { return card_has_linked_virtual_card_; } - bool card_metadata_shown() { - return (card_metadata_available_ && - (card_product_name_enabled_ || card_art_image_enabled_)) || - card_has_linked_virtual_card_; - } FormData form() { return form_; } @@ -68,29 +45,134 @@ {.role = CREDIT_CARD_EXP_2_DIGIT_YEAR}}, .action = ""}); - // Add 2 masked server cards. - CreditCard card_without_metadata = - test::GetRandomCreditCard(CreditCard::MASKED_SERVER_CARD); - card_without_metadata.set_guid(kCardWithoutMetadataId); - CreditCard card_with_metadata = - test::GetRandomCreditCard(CreditCard::MASKED_SERVER_CARD); - card_with_metadata.set_guid(kCardWithMetadataId); - card_with_metadata.set_issuer_id("capitalone"); - // Set card_with_metadata as the virtual card. - if (card_has_linked_virtual_card()) { - card_with_metadata.set_virtual_card_enrollment_state( - CreditCard::VirtualCardEnrollmentState::ENROLLED); - card_with_metadata.set_card_art_url( - GURL("https://www.example.com/cardart.png")); - } - // Set metadata to card_with_metadata. + // Add a masked server card. + CreditCard card = test::GetRandomCreditCard(CreditCard::MASKED_SERVER_CARD); + card.set_guid(kCardGuid); + // Set metadata to card. if (card_metadata_available()) { - card_with_metadata.set_product_description(u"card_description"); - card_with_metadata.set_card_art_url( + card.set_product_description(u"card_description"); + card.set_card_art_url(GURL("https://www.example.com/cardart.png")); + } + personal_data().AddServerCreditCard(card); + personal_data().Refresh(); + } + + void TearDown() override { TearDownHelper(); } + + private: + const bool card_metadata_available_; + FormData form_; +}; + +INSTANTIATE_TEST_SUITE_P(All, + CardMetadataFormEventMetricsTest, + testing::Bool()); + +// Test metadata shown metrics are correctly logged. +TEST_P(CardMetadataFormEventMetricsTest, LogShownMetrics) { + base::HistogramTester histogram_tester; + + // Simulate activating the autofill popup for the credit card field. + autofill_manager().OnAskForValuesToFillTest(form(), form().fields.back()); + autofill_manager().DidShowSuggestions(/*has_autofill_suggestions=*/true, + form(), form().fields.back()); + + // Verify that: + // 1. if the suggestion shown had metadata, + // `FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN` is logged. + // 2. if the suggestion shown did not have metadata, + // `FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SHOWN` is logged. + EXPECT_THAT( + histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), + BucketsInclude(Bucket(FORM_EVENT_SUGGESTIONS_SHOWN, 1), + Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN, + card_metadata_available()), + Bucket(FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SHOWN, + !card_metadata_available()))); +} + +// Test metadata selected metrics are correctly logged. +TEST_P(CardMetadataFormEventMetricsTest, LogSelectedMetrics) { + base::HistogramTester histogram_tester; + + // Simulate selecting the card. + autofill_manager().OnAskForValuesToFillTest(form(), form().fields.back()); + autofill_manager().DidShowSuggestions(/*has_autofill_suggestions=*/true, + form(), form().fields.back()); + autofill_manager().FillOrPreviewForm( + mojom::RendererFormDataAction::kFill, form(), form().fields.back(), + MakeFrontendId({.credit_card_id = kCardGuid})); + + // Verify that: + // 1. if the selected card had metadata, + // `FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED` is logged. + // 2. if the selected card did not have metadata, + // `FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SELECTED` is logged. + EXPECT_THAT(histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), + BucketsInclude( + Bucket(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1), + Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED, + card_metadata_available()), + Bucket(FORM_EVENT_CARD_SUGGESTION_WITHOUT_METADATA_SELECTED, + !card_metadata_available()))); +} + +// Params: +// 1) Whether card product name feature flag is enabled. +// 2) whether card art image feature flag is enabled. +// 3) Whether card metadata (both product name and card art image) are provided. +// 4) Whether the card has linked virtual card (only card art is provided). +class CardMetadataLatencyMetricsTest + : public AutofillMetricsBaseTest, + public testing::Test, + public testing::WithParamInterface<std::tuple<bool, bool, bool, bool>> { + public: + CardMetadataLatencyMetricsTest() + : card_product_name_enabled_(std::get<0>(GetParam())), + card_art_image_enabled_(std::get<1>(GetParam())), + card_metadata_available_(std::get<2>(GetParam())), + card_has_linked_virtual_card_(std::get<3>(GetParam())) { + feature_list_card_product_name_.InitWithFeatureState( + features::kAutofillEnableCardProductName, card_product_name_enabled_); + feature_list_card_art_image_.InitWithFeatureState( + features::kAutofillEnableCardArtImage, card_art_image_enabled_); + } + ~CardMetadataLatencyMetricsTest() override = default; + + bool card_product_name_enabled() { return card_product_name_enabled_; } + bool card_art_image_enabled() { return card_art_image_enabled_; } + bool card_metadata_available() { return card_metadata_available_; } + bool card_has_linked_virtual_card() { return card_has_linked_virtual_card_; } + + FormData form() { return form_; } + + void SetUp() override { + SetUpHelper(); + // Set up the form data. Reset form action to skip the IsFormMixedContent + // check. + form_ = + GetAndAddSeenForm({.description_for_logging = "CardMetadata", + .fields = {{.role = CREDIT_CARD_NAME_FULL}, + {.role = CREDIT_CARD_NUMBER}, + {.role = CREDIT_CARD_EXP_MONTH}, + {.role = CREDIT_CARD_EXP_2_DIGIT_YEAR}}, + .action = ""}); + + CreditCard masked_server_card = test::GetMaskedServerCard(); + masked_server_card.set_guid(kTestMaskedCardId); + masked_server_card.set_issuer_id("capitalone"); + if (card_has_linked_virtual_card()) { + masked_server_card.set_virtual_card_enrollment_state( + CreditCard::VirtualCardEnrollmentState::ENROLLED); + masked_server_card.set_card_art_url( GURL("https://www.example.com/cardart.png")); } - personal_data().AddServerCreditCard(card_without_metadata); - personal_data().AddServerCreditCard(card_with_metadata); + if (card_metadata_available()) { + masked_server_card.set_product_description(u"card_description"); + masked_server_card.set_card_art_url( + GURL("https://www.example.com/cardart.png")); + } + personal_data().AddServerCreditCard(masked_server_card); personal_data().Refresh(); } @@ -107,94 +189,15 @@ }; INSTANTIATE_TEST_SUITE_P(All, - CardMetadataMetricsTest, + CardMetadataLatencyMetricsTest, testing::Combine(testing::Bool(), testing::Bool(), testing::Bool(), testing::Bool())); -// Test to ensure that the FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN is -// correctly logged when any card in the suggestion has metadata. -TEST_P(CardMetadataMetricsTest, LogCardMetadataShownMetrics) { - base::HistogramTester histogram_tester; - - // Simulate activating the autofill popup for the credit card field. - autofill_manager().OnAskForValuesToFillTest(form(), form().fields.back()); - autofill_manager().DidShowSuggestions(/*has_autofill_suggestions=*/true, - form(), form().fields.back()); - - // Verify that if metadata is shown for any of the cards, it is logged. - EXPECT_THAT( - histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), - BucketsInclude(Bucket(FORM_EVENT_SUGGESTIONS_SHOWN, 1), - Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN, - card_metadata_shown()))); -} - -// Test to ensure that the FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED is -// not logged if a card without metadata is selected. -TEST_P(CardMetadataMetricsTest, - LogCardMetadataSelectedMetrics_CardWithoutMetadataSelected) { - base::HistogramTester histogram_tester; - - // Simulate selecting card_without_metadata. - autofill_manager().OnAskForValuesToFillTest(form(), form().fields.back()); - autofill_manager().DidShowSuggestions(/*has_autofill_suggestions=*/true, - form(), form().fields.back()); - autofill_manager().FillOrPreviewForm( - mojom::RendererFormDataAction::kFill, form(), form().fields.back(), - MakeFrontendId({.credit_card_id = kCardWithoutMetadataId})); - - // Verify that if metadata is shown, metrics for 'card with metadata shown' is - // logged, but metrics for 'card with metadata selected' is not logged. - EXPECT_THAT( - histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), - BucketsInclude( - Bucket(FORM_EVENT_SUGGESTIONS_SHOWN, 1), - Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN, - card_metadata_shown()), - Bucket(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, 1), - Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED, 0))); -} - -// Test to ensure that the FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED is -// logged if a card with metadata is selected. -TEST_P(CardMetadataMetricsTest, - LogCardMetadataSelectedMetrics_CardWithMetadataSelected) { - base::HistogramTester histogram_tester; - - // Simulate selecting card_with_metadata. - autofill_manager().OnAskForValuesToFillTest(form(), form().fields.back()); - autofill_manager().DidShowSuggestions(/*has_autofill_suggestions=*/true, - form(), form().fields.back()); - if (card_has_linked_virtual_card()) { - autofill_manager().FillOrPreviewVirtualCardInformation( - mojom::RendererFormDataAction::kFill, kCardWithMetadataId, form(), - form().fields.back()); - } else { - autofill_manager().FillOrPreviewForm( - mojom::RendererFormDataAction::kFill, form(), form().fields.back(), - MakeFrontendId({.credit_card_id = kCardWithMetadataId})); - } - - // Verify that if metadata is shown, metrics for both 'card with metadata - // shown' and 'card with metadata selected' is logged. - EXPECT_THAT( - histogram_tester.GetAllSamples("Autofill.FormEvents.CreditCard"), - BucketsInclude(Bucket(FORM_EVENT_SUGGESTIONS_SHOWN, 1), - Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SHOWN, - card_metadata_shown()), - Bucket(FORM_EVENT_MASKED_SERVER_CARD_SUGGESTION_SELECTED, - !card_has_linked_virtual_card()), - Bucket(FORM_EVENT_VIRTUAL_CARD_SUGGESTION_SELECTED, - card_has_linked_virtual_card()), - Bucket(FORM_EVENT_CARD_SUGGESTION_WITH_METADATA_SELECTED, - card_metadata_shown()))); -} - // Test to ensure that we log card metadata related metrics only when card // metadata is available. -TEST_P(CardMetadataMetricsTest, LogCardMetadataLatencyMetrics) { +TEST_P(CardMetadataLatencyMetricsTest, LogMetrics) { base::TimeTicks now = AutofillTickClock::NowTicks(); TestAutofillTickClock test_clock; test_clock.SetNowTicks(now);
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc index c36b8317..7f86fbc 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.cc
@@ -271,6 +271,13 @@ void VirtualCardEnrollmentManager::OnDidGetUpdateVirtualCardEnrollmentResponse( VirtualCardEnrollmentRequestType type, AutofillClient::PaymentsRpcResult result) { + // Add a strike if enrollment attempt was not successful. + if (type == VirtualCardEnrollmentRequestType::kEnroll && + result != AutofillClient::PaymentsRpcResult::kSuccess) { + AddStrikeToBlockOfferingVirtualCardEnrollment(base::NumberToString( + state_.virtual_card_enrollment_fields.credit_card.instrument_id())); + } + LogUpdateVirtualCardEnrollmentRequestResult( state_.virtual_card_enrollment_fields.virtual_card_enrollment_source, type, result == AutofillClient::PaymentsRpcResult::kSuccess);
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h index 74558965..7bedf37 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager.h
@@ -267,6 +267,8 @@ FRIEND_TEST_ALL_PREFIXES(VirtualCardEnrollmentManagerTest, StrikeDatabase_BubbleCanceled); FRIEND_TEST_ALL_PREFIXES(VirtualCardEnrollmentManagerTest, + StrikeDatabase_EnrollmentAttemptFailed); + FRIEND_TEST_ALL_PREFIXES(VirtualCardEnrollmentManagerTest, StrikeDatabase_SettingsPageNotBlocked); FRIEND_TEST_ALL_PREFIXES(VirtualCardEnrollmentManagerTest, VirtualCardEnrollmentFields_LastShow);
diff --git a/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc b/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc index 3c22339..54c14f4 100644 --- a/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc +++ b/components/autofill/core/browser/payments/virtual_card_enrollment_manager_unittest.cc
@@ -706,6 +706,44 @@ } TEST_F(VirtualCardEnrollmentManagerTest, + StrikeDatabase_EnrollmentAttemptFailed) { + base::HistogramTester histogram_tester; + SetUpStrikeDatabaseTest(); + + std::vector<AutofillClient::PaymentsRpcResult> failure_results = { + AutofillClient::PaymentsRpcResult::kTryAgainFailure, + AutofillClient::PaymentsRpcResult::kPermanentFailure}; + + VirtualCardEnrollmentProcessState* state = + virtual_card_enrollment_manager_->GetVirtualCardEnrollmentProcessState(); + + for (int i = 0; i < static_cast<int>(failure_results.size()); i++) { + virtual_card_enrollment_manager_ + ->OnDidGetUpdateVirtualCardEnrollmentResponse( + VirtualCardEnrollmentRequestType::kEnroll, failure_results[i]); + histogram_tester.ExpectBucketCount( + "Autofill.StrikeDatabase.NthStrikeAdded.VirtualCardEnrollment", + /*sample=*/i + 1, /*count=*/1); + + EXPECT_EQ(virtual_card_enrollment_manager_ + ->GetVirtualCardEnrollmentStrikeDatabase() + ->GetStrikes( + base::NumberToString(state->virtual_card_enrollment_fields + .credit_card.instrument_id())), + i + 1); + + histogram_tester.ExpectBucketCount( + "Autofill.VirtualCardEnrollmentStrikeDatabase." + + VirtualCardEnrollmentSourceToMetricSuffix( + state->virtual_card_enrollment_fields + .virtual_card_enrollment_source), + VirtualCardEnrollmentStrikeDatabaseEvent:: + VIRTUAL_CARD_ENROLLMENT_STRIKE_DATABASE_STRIKE_LOGGED, + i + 1); + } +} + +TEST_F(VirtualCardEnrollmentManagerTest, StrikeDatabase_SettingsPageNotBlocked) { SetUpStrikeDatabaseTest(); base::HistogramTester histogram_tester;
diff --git a/components/components_strings.grd b/components/components_strings.grd index d5b3885..2c8c3216 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -326,7 +326,6 @@ <part file="send_tab_to_self_strings.grdp" /> <part file="site_settings_strings.grdp" /> <part file="sms_strings.grdp" /> - <part file="soda_strings.grdp" /> <part file="ssl_errors_strings.grdp" /> <part file="subresource_filter_strings.grdp" /> <part file="supervised_user_strings.grdp" />
diff --git a/components/contextual_search/core/browser/contextual_search_field_trial.cc b/components/contextual_search/core/browser/contextual_search_field_trial.cc index b7dac73..cc5ecbe6 100644 --- a/components/contextual_search/core/browser/contextual_search_field_trial.cc +++ b/components/contextual_search/core/browser/contextual_search_field_trial.cc
@@ -9,7 +9,6 @@ #include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "components/contextual_search/core/browser/public.h" -#include "components/variations/variations_associated_data.h" namespace { @@ -130,6 +129,6 @@ } std::string ContextualSearchFieldTrial::GetParam(const std::string& name) { - return variations::GetVariationParamValue( + return base::GetFieldTrialParamValue( contextual_search::kContextualSearchFieldTrialName, name); }
diff --git a/components/flags_ui/flags_state_unittest.cc b/components/flags_ui/flags_state_unittest.cc index 8db9633c..2b64ff74 100644 --- a/components/flags_ui/flags_state_unittest.cc +++ b/components/flags_ui/flags_state_unittest.cc
@@ -367,7 +367,7 @@ flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_, feature_list.get()); // No value should be associated. - EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1)); + EXPECT_EQ("", base::GetFieldTrialParamValue(kTestTrial, kTestParam1)); // The trial should not be created. base::FieldTrial* trial = base::FieldTrialList::Find(kTestTrial); EXPECT_EQ(nullptr, trial); @@ -379,7 +379,7 @@ flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_, feature_list.get()); // No value should be associated as this is the default option. - EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1)); + EXPECT_EQ("", base::GetFieldTrialParamValue(kTestTrial, kTestParam1)); // The trial should be created. trial = base::FieldTrialList::Find(kTestTrial); @@ -393,7 +393,7 @@ flags_state_->RegisterAllFeatureVariationParameters(&flags_storage_, feature_list.get()); // Associating for the second time should not change the value. - EXPECT_EQ("", variations::GetVariationParamValue(kTestTrial, kTestParam1)); + EXPECT_EQ("", base::GetFieldTrialParamValue(kTestTrial, kTestParam1)); } TEST_F(FlagsStateTest, RegisterAllFeatureVariationParametersNonDefault) { @@ -413,7 +413,7 @@ // The param should have the value predefined in this variation. EXPECT_EQ(kTestParamValue, - variations::GetVariationParamValue(kTestTrial, kTestParam1)); + base::GetFieldTrialParamValue(kTestTrial, kTestParam1)); // The value should be associated also via the name of the feature. EXPECT_EQ(kTestParamValue, @@ -446,9 +446,9 @@ base::GetFieldTrialParamValueByFeature(kTestFeature2, kTestParam2)); // The params are registered in the same trial. EXPECT_EQ(kTestParamValue, - variations::GetVariationParamValue(kTestTrial, kTestParam1)); + base::GetFieldTrialParamValue(kTestTrial, kTestParam1)); EXPECT_EQ(kTestParamValue, - variations::GetVariationParamValue(kTestTrial, kTestParam2)); + base::GetFieldTrialParamValue(kTestTrial, kTestParam2)); } base::CommandLine::StringType CreateSwitch(const std::string& value) {
diff --git a/components/history_clusters/core/filter_cluster_processor.cc b/components/history_clusters/core/filter_cluster_processor.cc index 2f7bcd5..fc486b7 100644 --- a/components/history_clusters/core/filter_cluster_processor.cc +++ b/components/history_clusters/core/filter_cluster_processor.cc
@@ -28,7 +28,8 @@ // Returns whether `filter_params` is a filter that would actually filter // clusters out. bool IsFunctionalFilter(QueryClustersFilterParams filter_params) { - return filter_params.min_visits_with_images > 0 || + return filter_params.min_visits > 0 || + filter_params.min_visits_with_images > 0 || !filter_params.categories_allowlist.empty() || !filter_params.categories_blocklist.empty() || filter_params.is_search_initiated || @@ -117,7 +118,7 @@ bool is_search_initiated = false; bool has_related_searches = false; size_t num_interesting_visits = 0; - size_t num_visits = 0; + int num_visits = 0; bool is_content_visible = true; for (const auto& visit : cluster.visits) { @@ -161,6 +162,11 @@ } bool matches_filter = true; + if (num_visits < filter_params_->min_visits) { + RecordClusterFilterReasonHistogram(clustering_request_source_, + ClusterFilterReason::kNotEnoughVisits); + matches_filter = false; + } if (num_visits_with_images < filter_params_->min_visits_with_images) { RecordClusterFilterReasonHistogram(clustering_request_source_, ClusterFilterReason::kNotEnoughImages);
diff --git a/components/history_clusters/core/filter_cluster_processor.h b/components/history_clusters/core/filter_cluster_processor.h index 0acb192..9a7a2c5 100644 --- a/components/history_clusters/core/filter_cluster_processor.h +++ b/components/history_clusters/core/filter_cluster_processor.h
@@ -24,11 +24,12 @@ kSingleVisit = 6, kNotContentVisible = 7, kHasBlockedCategory = 8, + kNotEnoughVisits = 9, // Add above here and make sure to keep `ClusterFilterReason` up to date in // enums.xml. - kMaxValue = kHasBlockedCategory + kMaxValue = kNotEnoughVisits }; // A cluster processor that removes clusters that do not match the filter.
diff --git a/components/history_clusters/core/filter_cluster_processor_unittest.cc b/components/history_clusters/core/filter_cluster_processor_unittest.cc index 953ac99..2de28f6 100644 --- a/components/history_clusters/core/filter_cluster_processor_unittest.cc +++ b/components/history_clusters/core/filter_cluster_processor_unittest.cc
@@ -188,6 +188,33 @@ 0); } +TEST_F(FilterClusterProcessorTest, OnlyVisitsConstraint) { + base::HistogramTester histogram_tester; + + QueryClustersFilterParams params; + params.min_visits = 2; + + EXPECT_THAT(GetTestClusterIdsThatPassFilter(params), + ElementsAre(2, 3, 4, 5, 6, 7, 9, 10, 11)); + + histogram_tester.ExpectUniqueSample( + "History.Clusters.Backend.FilterClusterProcessor.NumClusters.PreFilter." + "NewTabPage", + 12, 1); + histogram_tester.ExpectUniqueSample( + "History.Clusters.Backend.FilterClusterProcessor.NumClusters.PostFilter." + "NewTabPage", + 9, 1); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.FilterClusterProcessor.ClusterFilterReason." + "NewTabPage", + ClusterFilterReason::kNotFiltered, 9); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.FilterClusterProcessor.ClusterFilterReason." + "NewTabPage", + ClusterFilterReason::kNotEnoughVisits, 3); +} + TEST_F(FilterClusterProcessorTest, OnlyImageConstraint) { base::HistogramTester histogram_tester; @@ -400,6 +427,7 @@ base::HistogramTester histogram_tester; QueryClustersFilterParams params; + params.min_visits = 2; params.min_visits_with_images = 2; params.categories_allowlist = {"category1", "category2"}; params.categories_blocklist = {"blocked"}; @@ -424,6 +452,10 @@ histogram_tester.ExpectBucketCount( "History.Clusters.Backend.FilterClusterProcessor.ClusterFilterReason." "NewTabPage", + ClusterFilterReason::kNotEnoughVisits, 3); + histogram_tester.ExpectBucketCount( + "History.Clusters.Backend.FilterClusterProcessor.ClusterFilterReason." + "NewTabPage", ClusterFilterReason::kNotEnoughImages, 5); histogram_tester.ExpectBucketCount( "History.Clusters.Backend.FilterClusterProcessor.ClusterFilterReason."
diff --git a/components/history_clusters/core/history_clusters_types.h b/components/history_clusters/core/history_clusters_types.h index 0b914ad..afdcb63 100644 --- a/components/history_clusters/core/history_clusters_types.h +++ b/components/history_clusters/core/history_clusters_types.h
@@ -34,6 +34,11 @@ // Parameters related to the minimum requirements for returned clusters. + // The minimum number of non-hidden visits that are required for returned + // clusters. Note that this also implicitly works as a visit filter such that + // if fewer than `min_total_visits` are in a cluster, it will be filtered out. + int min_visits = 0; + // The minimum number of visits within a cluster that have associated images. // Note that this also implicitly works as a visit filter such that if fewer // than `min_visits_with_images` are in a cluster, it will be filtered out.
diff --git a/components/image_service/features.cc b/components/image_service/features.cc index 045270eb..e4ed9c1 100644 --- a/components/image_service/features.cc +++ b/components/image_service/features.cc
@@ -14,9 +14,9 @@ "ImageServiceSuggestPoweredImages", base::FEATURE_DISABLED_BY_DEFAULT); -// Disabled by default, usage is approved but we still want to control rollout. +// Enabled the capability by default, can be used as a killswitch. BASE_FEATURE(kImageServiceOptimizationGuideSalientImages, "ImageServiceOptimizationGuideSalientImages", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); } // namespace image_service
diff --git a/components/image_service/image_service_unittest.cc b/components/image_service/image_service_unittest.cc index 6cf51de..26d78f3 100644 --- a/components/image_service/image_service_unittest.cc +++ b/components/image_service/image_service_unittest.cc
@@ -316,4 +316,36 @@ << "Expect that making more request restarts the queue."; } +class DisabledOptGuideImageServiceTest : public ImageServiceTest { + public: + DisabledOptGuideImageServiceTest() = default; + + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + /*enabled_features=*/{kImageService, kImageServiceSuggestPoweredImages}, + /*disabled_features=*/{kImageServiceOptimizationGuideSalientImages}); + + test_opt_guide_ = + std::make_unique<optimization_guide::ImageServiceTestOptGuide>(); + test_sync_service_ = std::make_unique<syncer::TestSyncService>(); + image_service_ = std::make_unique<ImageService>( + nullptr, test_opt_guide_.get(), test_sync_service_.get()); + } +}; + +TEST_F(DisabledOptGuideImageServiceTest, DoesNotFetch) { + mojom::Options options; + options.suggest_images = false; + options.optimization_guide_images = true; + + GURL image_url_response; + image_service_->FetchImageFor( + mojom::ClientId::Journeys, GURL("https://page-url.com"), options, + base::BindOnce(&StoreImageUrlResponse, &image_url_response)); + + // Verify that the OptimizationGuide backend did not get called. + EXPECT_EQ(test_opt_guide_->requests_received_, 0U); + EXPECT_EQ(image_url_response, GURL()); +} + } // namespace image_service
diff --git a/components/ntp_tiles/popular_sites_impl.cc b/components/ntp_tiles/popular_sites_impl.cc index 5868b3c..ff1f274 100644 --- a/components/ntp_tiles/popular_sites_impl.cc +++ b/components/ntp_tiles/popular_sites_impl.cc
@@ -13,6 +13,7 @@ #include "base/command_line.h" #include "base/feature_list.h" #include "base/functional/bind.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -130,18 +131,16 @@ } std::string GetVariationCountry() { - return variations::GetVariationParamValue(kPopularSitesFieldTrialName, - "country"); + return base::GetFieldTrialParamValue(kPopularSitesFieldTrialName, "country"); } std::string GetVariationVersion() { - return variations::GetVariationParamValue(kPopularSitesFieldTrialName, - "version"); + return base::GetFieldTrialParamValue(kPopularSitesFieldTrialName, "version"); } std::string GetVariationDirectory() { - return variations::GetVariationParamValue(kPopularSitesFieldTrialName, - "directory"); + return base::GetFieldTrialParamValue(kPopularSitesFieldTrialName, + "directory"); } PopularSites::SitesVector ParseSiteList(const base::Value::List& list) {
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 12589c1..e75dd05 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -201,7 +201,7 @@ } int OmniboxFieldTrial::GetDisabledProviderTypes() { - const std::string& types_string = variations::GetVariationParamValue( + const std::string& types_string = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kDisableProvidersRule); int types = 0; if (types_string.empty() || !base::StringToInt(types_string, &types)) { @@ -375,7 +375,7 @@ } float OmniboxFieldTrial::HQPBookmarkValue() { - std::string bookmark_value_str = variations::GetVariationParamValue( + std::string bookmark_value_str = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kHQPBookmarkValueRule); if (bookmark_value_str.empty()) { return 10; @@ -389,24 +389,23 @@ } bool OmniboxFieldTrial::HQPAllowMatchInTLDValue() { - return variations::GetVariationParamValue(kBundledExperimentFieldTrialName, - kHQPAllowMatchInTLDRule) == "true"; + return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName, + kHQPAllowMatchInTLDRule) == "true"; } bool OmniboxFieldTrial::HQPAllowMatchInSchemeValue() { - return variations::GetVariationParamValue(kBundledExperimentFieldTrialName, - kHQPAllowMatchInSchemeRule) == - "true"; + return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName, + kHQPAllowMatchInSchemeRule) == "true"; } void OmniboxFieldTrial::GetSuggestPollingStrategy(bool* from_last_keystroke, int* polling_delay_ms) { *from_last_keystroke = - variations::GetVariationParamValue( + base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kMeasureSuggestPollingDelayFromLastKeystrokeRule) == "true"; - const std::string& polling_delay_string = variations::GetVariationParamValue( + const std::string& polling_delay_string = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kSuggestPollingDelayMsRule); if (polling_delay_string.empty() || !base::StringToInt(polling_delay_string, polling_delay_ms) || @@ -416,12 +415,12 @@ } std::string OmniboxFieldTrial::HQPExperimentalScoringBuckets() { - return variations::GetVariationParamValue( - kBundledExperimentFieldTrialName, kHQPExperimentalScoringBucketsParam); + return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName, + kHQPExperimentalScoringBucketsParam); } float OmniboxFieldTrial::HQPExperimentalTopicalityThreshold() { - std::string topicality_threshold_str = variations::GetVariationParamValue( + std::string topicality_threshold_str = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kHQPExperimentalScoringTopicalityThresholdParam); @@ -456,7 +455,7 @@ } size_t OmniboxFieldTrial::HQPMaxVisitsToScore() { - std::string max_visits_str = variations::GetVariationParamValue( + std::string max_visits_str = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kHQPMaxVisitsToScoreRule); constexpr size_t kDefaultMaxVisitsToScore = 10; static_assert( @@ -474,7 +473,7 @@ } float OmniboxFieldTrial::HQPTypedValue() { - std::string typed_value_str = variations::GetVariationParamValue( + std::string typed_value_str = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kHQPTypedValueRule); if (typed_value_str.empty()) { return 1.5; @@ -488,7 +487,7 @@ } OmniboxFieldTrial::NumMatchesScores OmniboxFieldTrial::HQPNumMatchesScores() { - std::string str = variations::GetVariationParamValue( + std::string str = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kHQPNumMatchesScoresRule); static constexpr char kDefaultNumMatchesScores[] = "1:3,2:2.5,3:2,4:1.5"; if (str.empty()) { @@ -519,8 +518,8 @@ // size_t) containing the number of words. size_t num_title_words; if (!base::StringToSizeT( - variations::GetVariationParamValue(kBundledExperimentFieldTrialName, - kHQPNumTitleWordsRule), + base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName, + kHQPNumTitleWordsRule), &num_title_words)) { return 20; } @@ -528,19 +527,18 @@ } bool OmniboxFieldTrial::HQPAlsoDoHUPLikeScoring() { - return variations::GetVariationParamValue(kBundledExperimentFieldTrialName, - kHQPAlsoDoHUPLikeScoringRule) == - "true"; + return base::GetFieldTrialParamValue(kBundledExperimentFieldTrialName, + kHQPAlsoDoHUPLikeScoringRule) == "true"; } bool OmniboxFieldTrial::HUPSearchDatabase() { - const std::string& value = variations::GetVariationParamValue( + const std::string& value = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kHUPSearchDatabaseRule); return value.empty() || (value == "true"); } int OmniboxFieldTrial::KeywordScoreForSufficientlyCompleteMatch() { - std::string value_str = variations::GetVariationParamValue( + std::string value_str = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kKeywordScoreForSufficientlyCompleteMatchRule); if (value_str.empty()) {
diff --git a/components/optimization_guide/proto/hints.proto b/components/optimization_guide/proto/hints.proto index 31dba807..74148b6 100644 --- a/components/optimization_guide/proto/hints.proto +++ b/components/optimization_guide/proto/hints.proto
@@ -113,7 +113,7 @@ // Must sync with enum OptimizationType in enums.xml for metric recording. enum OptimizationType { // Values for obsolete optimizations. - reserved 11, 12; + reserved 11, 12, 29; TYPE_UNSPECIFIED = 0; // This optimization blocks JavaScript on the page.
diff --git a/components/password_manager/core/browser/ui/credential_ui_entry.cc b/components/password_manager/core/browser/ui/credential_ui_entry.cc index 9ab1c4a0..c1f7466 100644 --- a/components/password_manager/core/browser/ui/credential_ui_entry.cc +++ b/components/password_manager/core/browser/ui/credential_ui_entry.cc
@@ -203,6 +203,7 @@ std::vector<CredentialUIEntry::DomainInfo> CredentialUIEntry::GetAffiliatedDomains() const { std::vector<CredentialUIEntry::DomainInfo> domains; + std::set<std::string> unique_domain; for (const auto& facet : facets) { CredentialUIEntry::DomainInfo domain; domain.signon_realm = facet.signon_realm; @@ -222,7 +223,9 @@ domain.name = GetOrigin(url::Origin::Create(facet.url)); domain.url = facet.url; } - domains.push_back(std::move(domain)); + if (unique_domain.insert(domain.name).second) { + domains.push_back(std::move(domain)); + } } return domains; }
diff --git a/components/password_manager/core/browser/ui/credential_ui_entry_unittest.cc b/components/password_manager/core/browser/ui/credential_ui_entry_unittest.cc index 1e90c04..83db04b 100644 --- a/components/password_manager/core/browser/ui/credential_ui_entry_unittest.cc +++ b/components/password_manager/core/browser/ui/credential_ui_entry_unittest.cc
@@ -199,4 +199,18 @@ EXPECT_TRUE(reused_entry.IsReused()); } +TEST(CredentialUIEntryTest, TestGetAffiliatedDomainsWithDuplicates) { + PasswordForm form1; + form1.signon_realm = "https://g.com/"; + form1.url = GURL("https://g.com/"); + + PasswordForm form2; + form2.signon_realm = "https://g.com/"; + form2.url = GURL("https://g.com/"); + + CredentialUIEntry entry = CredentialUIEntry({form1, form2}); + EXPECT_THAT(entry.GetAffiliatedDomains(), + ElementsAre(ExpectDomain("g.com", form1.url))); +} + } // namespace password_manager
diff --git a/components/safe_browsing/android/remote_database_manager.cc b/components/safe_browsing/android/remote_database_manager.cc index 4c1d7765..196be8e 100644 --- a/components/safe_browsing/android/remote_database_manager.cc +++ b/components/safe_browsing/android/remote_database_manager.cc
@@ -10,6 +10,7 @@ #include "base/functional/bind.h" #include "base/memory/raw_ptr.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_number_conversions.h" @@ -20,7 +21,6 @@ #include "components/safe_browsing/core/browser/db/v4_get_hash_protocol_manager.h" #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" #include "components/safe_browsing/core/common/features.h" -#include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -131,7 +131,7 @@ // The param is expected to be a comma-separated list of ints // corresponding to the enum types. We're keeping this finch // control around so we can add back types if they later become dangerous. - const std::string ints_str = variations::GetVariationParamValue( + const std::string ints_str = base::GetFieldTrialParamValue( kAndroidFieldExperiment, kAndroidTypesToCheckParam); if (ints_str.empty()) { // By default, we check all types except a few.
diff --git a/components/safe_browsing/core/browser/BUILD.gn b/components/safe_browsing/core/browser/BUILD.gn index 67a2f6a..9053fc30 100644 --- a/components/safe_browsing/core/browser/BUILD.gn +++ b/components/safe_browsing/core/browser/BUILD.gn
@@ -109,6 +109,7 @@ "//base/test:test_support", "//components/safe_browsing/core/browser/db:v4_protocol_manager_util", "//components/safe_browsing/core/browser/db:v4_test_util", + "//components/safe_browsing/core/common", "//testing/gtest", ] }
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc index 94061e4..e3c8cb85 100644 --- a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter.cc
@@ -12,6 +12,7 @@ #include "components/safe_browsing/core/browser/hash_realtime_mechanism.h" #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" #include "components/safe_browsing/core/browser/url_realtime_mechanism.h" +#include "components/safe_browsing/core/common/features.h" namespace safe_browsing { SafeBrowsingLookupMechanismExperimenter:: @@ -481,6 +482,9 @@ } } void SafeBrowsingLookupMechanismExperimenter::MaybeLogUrlLevelResults() const { + if (!safe_browsing::kUrlLevelValidationForHprtExperimentEnabled.Get()) { + return; + } if (checks_to_run_.size() != 1 || !checks_to_run_.back()->would_check_show_warning_if_unsafe.has_value()) { DCHECK(false);
diff --git a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc index 93deab1..2cbde05 100644 --- a/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc +++ b/components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_experimenter_unittest.cc
@@ -8,11 +8,13 @@ #include "base/memory/scoped_refptr.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/mock_callback.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "components/safe_browsing/core/browser/db/v4_protocol_manager_util.h" #include "components/safe_browsing/core/browser/db/v4_test_util.h" #include "components/safe_browsing/core/browser/safe_browsing_lookup_mechanism_runner.h" +#include "components/safe_browsing/core/common/features.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -280,6 +282,15 @@ absl::optional<AllInOneResult> delayed_response_result; }; + void SetUp() override { + std::map<std::string, std::string> params = { + {"UrlLevelValidationForHprtExperimentEnabled", "true"}}; + feature_list_.InitAndEnableFeatureWithParameters( + kSafeBrowsingLookupMechanismExperiment, params); + } + + void TearDown() override { feature_list_.Reset(); } + void ResetMetrics() { histogram_tester_ = std::make_unique<base::HistogramTester>(); } @@ -1090,6 +1101,16 @@ std::make_unique<PretendUrlCheckerDelegate>(); std::unique_ptr<safe_browsing::MockPingManager> ping_manager_ = std::make_unique<safe_browsing::MockPingManager>(); + base::test::ScopedFeatureList feature_list_; +}; +class SafeBrowsingLookupMechanismExperimenterUrlLevelValidationDisabledTest + : public SafeBrowsingLookupMechanismExperimenterTest { + void SetUp() override { + std::map<std::string, std::string> params = { + {"UrlLevelValidationForHprtExperimentEnabled", "false"}}; + feature_list_.InitAndEnableFeatureWithParameters( + kSafeBrowsingLookupMechanismExperiment, params); + } }; TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestLifetimes) { @@ -1356,6 +1377,34 @@ } } +TEST_F(SafeBrowsingLookupMechanismExperimenterUrlLevelValidationDisabledTest, + TestUrlLevelValidation) { + std::vector<bool> no_time_outs = {false, false, false}; + std::vector<absl::optional<UrlLevelValidationDetails>> + urt_hpd_hprt_url_level_validation_details = { + UrlLevelValidationDetails( + /*locally_cached_results_threat_type=*/SB_THREAT_TYPE_SAFE, + /*real_time_request_failed=*/false, + /*matched_high_confidence_allowlist=*/true), + UrlLevelValidationDetails( + /*locally_cached_results_threat_type=*/absl::nullopt, + /*real_time_request_failed=*/false, + /*matched_high_confidence_allowlist=*/absl::nullopt), + UrlLevelValidationDetails( + /*locally_cached_results_threat_type=*/SB_THREAT_TYPE_BILLING, + /*real_time_request_failed=*/false, + /*matched_high_confidence_allowlist=*/true)}; + std::vector<SBThreatType> urt_hpd_hprt_threat_types = { + SB_THREAT_TYPE_SAFE, SB_THREAT_TYPE_URL_MALWARE, + SB_THREAT_TYPE_URL_PHISHING}; + + // The report is not sent if the feature is disabled. + RunUrlLevelValidationTest(urt_hpd_hprt_threat_types, + urt_hpd_hprt_url_level_validation_details, + /*urt_hpd_hprt_time_out=*/no_time_outs, + /*expect_report_sent=*/false); +} + TEST_F(SafeBrowsingLookupMechanismExperimenterTest, TestGetExperimentDetailsThreatType) { struct TestCase {
diff --git a/components/safe_browsing/core/common/features.cc b/components/safe_browsing/core/common/features.cc index cfc446f..8182741 100644 --- a/components/safe_browsing/core/common/features.cc +++ b/components/safe_browsing/core/common/features.cc
@@ -193,6 +193,11 @@ "SafeBrowsingLookupMechanismExperiment", base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<bool> kUrlLevelValidationForHprtExperimentEnabled{ + &kSafeBrowsingLookupMechanismExperiment, + "UrlLevelValidationForHprtExperimentEnabled", + /*default_value=*/true}; + BASE_FEATURE(kSafeBrowsingOnUIThread, "SafeBrowsingOnUIThread", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/safe_browsing/core/common/features.h b/components/safe_browsing/core/common/features.h index ec30f31..7f62a7a 100644 --- a/components/safe_browsing/core/common/features.h +++ b/components/safe_browsing/core/common/features.h
@@ -198,6 +198,12 @@ // known as the hash-prefix real-time lookup experiment, since that mechanism is // the main comparison anchor. BASE_DECLARE_FEATURE(kSafeBrowsingLookupMechanismExperiment); +// Controls whether the SafeBrowsingLookupMechanismExperiment (AKA HPRT +// experiment) conditionally logs a Client Safe Browsing Report when the +// experiment ends for URL-level validation purposes. This is only relevant +// while the HPRT experiment is running, which is only enabled for ESB users. +extern const base::FeatureParam<bool> + kUrlLevelValidationForHprtExperimentEnabled; // Run Safe Browsing code on UI thread. BASE_DECLARE_FEATURE(kSafeBrowsingOnUIThread);
diff --git a/components/search/ntp_features.cc b/components/search/ntp_features.cc index 666e8815..d9beb2d 100644 --- a/components/search/ntp_features.cc +++ b/components/search/ntp_features.cc
@@ -248,6 +248,11 @@ "NtpHistoryClustersModuleBeginTimeDuration", base::FEATURE_DISABLED_BY_DEFAULT); +// Dummy feature to set kNtpHistoryClustersModuleMinimumVisitsRequiredParam. +BASE_FEATURE(kNtpHistoryClustersModuleMinimumVisitsRequired, + "NtpHistoryClustersModuleMinimumVisitsRequired", + base::FEATURE_DISABLED_BY_DEFAULT); + // Dummy feature to set kNtpHistoryClustersModuleMinimumImagesRequiredParam. BASE_FEATURE(kNtpHistoryClustersModuleMinimumImagesRequired, "NtpHistoryClustersModuleMinimumImagesRequired", @@ -332,6 +337,8 @@ "NtpRecipeTasksModuleExperimentGroupParam"; const char kNtpHistoryClustersModuleBeginTimeDurationHoursParam[] = "NtpHistoryClustersModuleBeginTimeDurationHoursParam"; +const char kNtpHistoryClustersModuleMinimumVisitsRequiredParam[] = + "NtpHistoryClustersModuleMinimumVisitsRequiredParam"; const char kNtpHistoryClustersModuleMinimumImagesRequiredParam[] = "NtpHistoryClustersModuleMinimumImagesRequiredParam"; const char kNtpHistoryClustersModuleCategoriesAllowlistParam[] =
diff --git a/components/search/ntp_features.h b/components/search/ntp_features.h index 44c57a5..61a57c6 100644 --- a/components/search/ntp_features.h +++ b/components/search/ntp_features.h
@@ -67,6 +67,7 @@ BASE_DECLARE_FEATURE(kNtpHandleMostVisitedNavigationExplicitly); BASE_DECLARE_FEATURE(kNtpHistoryClustersModule); BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleBeginTimeDuration); +BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleMinimumVisitsRequired); BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleMinimumImagesRequired); BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleCategories); BASE_DECLARE_FEATURE(kNtpHistoryClustersModuleLoad); @@ -144,6 +145,9 @@ // Parameter for determining the maximum number of hours to look back to show a // history cluster. extern const char kNtpHistoryClustersModuleBeginTimeDurationHoursParam[]; +// Parameter for determining the minimum number of visits that are required in +// order to show a history cluster. +extern const char kNtpHistoryClustersModuleMinimumVisitsRequiredParam[]; // Parameter for determining the minimum number of visits with an image that are // required in order to show a history cluster. extern const char kNtpHistoryClustersModuleMinimumImagesRequiredParam[];
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc index 2bd1ce0..77763f7 100644 --- a/components/search_engines/template_url_service.cc +++ b/components/search_engines/template_url_service.cc
@@ -15,6 +15,7 @@ #include "base/functional/callback_helpers.h" #include "base/i18n/case_conversion.h" #include "base/memory/raw_ptr.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/observer_list.h" @@ -38,7 +39,6 @@ #include "components/sync/protocol/entity_specifics.pb.h" #include "components/sync/protocol/search_engine_specifics.pb.h" #include "components/url_formatter/url_fixer.h" -#include "components/variations/variations_associated_data.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "url/gurl.h" @@ -171,7 +171,7 @@ constexpr char kBundledExperimentFieldTrialName[] = "OmniboxBundledExperimentV1"; constexpr char kKeywordRequiresRegistryRule[] = "KeywordRequiresRegistry"; - const std::string value = variations::GetVariationParamValue( + const std::string value = base::GetFieldTrialParamValue( kBundledExperimentFieldTrialName, kKeywordRequiresRegistryRule); return value.empty() || (value == "true"); }
diff --git a/components/security_interstitials/content/cert_report_helper.cc b/components/security_interstitials/content/cert_report_helper.cc index 5054f69..8fa1029 100644 --- a/components/security_interstitials/content/cert_report_helper.cc +++ b/components/security_interstitials/content/cert_report_helper.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -20,7 +21,6 @@ #include "components/security_interstitials/core/metrics_helper.h" #include "components/strings/grit/components_strings.h" #include "components/user_prefs/user_prefs.h" -#include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" @@ -243,7 +243,7 @@ // for all of these users. Check the Finch configuration for a sending // threshold and only send reports in case the threshold isn't exceeded. const std::string param = - variations::GetVariationParamValue(kFinchExperimentName, kFinchParamName); + base::GetFieldTrialParamValue(kFinchExperimentName, kFinchParamName); if (!param.empty()) { double sendingThreshold; if (base::StringToDouble(param, &sendingThreshold)) {
diff --git a/components/site_engagement/content/site_engagement_score.cc b/components/site_engagement/content/site_engagement_score.cc index 00092e5..b5f8f39 100644 --- a/components/site_engagement/content/site_engagement_score.cc +++ b/components/site_engagement/content/site_engagement_score.cc
@@ -8,6 +8,7 @@ #include <cmath> #include <utility> +#include "base/metrics/field_trial_params.h" #include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" #include "base/time/clock.h" @@ -19,7 +20,6 @@ #include "components/content_settings/core/common/content_settings_utils.h" #include "components/site_engagement/content/engagement_type.h" #include "components/site_engagement/content/site_engagement_metrics.h" -#include "components/variations/variations_associated_data.h" #include "third_party/blink/public/mojom/site_engagement/site_engagement.mojom.h" namespace site_engagement { @@ -191,8 +191,8 @@ double param_vals[MAX_VARIATION]; for (int i = 0; i < MAX_VARIATION; ++i) { - std::string param_string = variations::GetVariationParamValue( - param_name, GetParamValues()[i].first); + std::string param_string = + base::GetFieldTrialParamValue(param_name, GetParamValues()[i].first); // Bail out if we didn't get a param string for the key, or if we couldn't // convert the param string to a double, or if we get a negative value.
diff --git a/components/soda/BUILD.gn b/components/soda/BUILD.gn index 30eaba1..91498497 100644 --- a/components/soda/BUILD.gn +++ b/components/soda/BUILD.gn
@@ -58,6 +58,7 @@ "//components/component_updater", "//components/crx_file", "//components/strings/", + "//ui/base", ] }
diff --git a/components/soda/constants.cc b/components/soda/constants.cc index bd046b4..9d0004e7 100644 --- a/components/soda/constants.cc +++ b/components/soda/constants.cc
@@ -15,6 +15,7 @@ #include "components/component_updater/component_updater_paths.h" #include "components/crx_file/id_util.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/base/l10n/l10n_util.h" namespace speech { @@ -183,13 +184,15 @@ return LanguageCode::kNone; } -int GetLanguageDisplayName(const std::string& language_name) { +const std::u16string GetLanguageDisplayName(const std::string& language_name, + const std::string& display_locale) { absl::optional<SodaLanguagePackComponentConfig> language_config = GetLanguageComponentConfig(language_name); if (language_config.has_value()) { - return language_config.value().display_name; + return l10n_util::GetDisplayNameForLocale( + language_config.value().language_name, display_locale, true); } - return 0; + return std::u16string(); } const std::string GetInstallationSuccessTimeMetricForLanguagePack(
diff --git a/components/soda/constants.h b/components/soda/constants.h index 367a8c8..82b2b98 100644 --- a/components/soda/constants.h +++ b/components/soda/constants.h
@@ -43,10 +43,6 @@ // The language name for the language component (e.g. "en-US"). const char* language_name = nullptr; - // The message ID for the display name of the language component (e.g. - // "English"). - const int display_name; - // The name of the config file path pref for the language pack. const char* config_path_pref = nullptr; @@ -55,47 +51,39 @@ const uint8_t public_key_sha[32] = {}; }; -// TODO(crbug.com/1161569): Replace the display name mapping with -// GetDisplayNameForLocale. constexpr SodaLanguagePackComponentConfig kLanguageComponentConfigs[] = { {LanguageCode::kEnUs, "en-US", - IDS_SODA_LANGUAGE_DISPLAY_NAME_ENGLISH, prefs::kSodaEnUsConfigPath, {0xe4, 0x64, 0x1c, 0xc2, 0x8c, 0x2a, 0x97, 0xa7, 0x16, 0x61, 0xbd, 0xa9, 0xbe, 0xe6, 0x93, 0x56, 0xf5, 0x05, 0x33, 0x9b, 0x8b, 0x0b, 0x02, 0xe2, 0x6b, 0x7e, 0x6c, 0x40, 0xa1, 0xd2, 0x7e, 0x18}}, {LanguageCode::kDeDe, "de-DE", - IDS_SODA_LANGUAGE_DISPLAY_NAME_GERMAN, prefs::kSodaDeDeConfigPath, {0x92, 0xb6, 0xd8, 0xa3, 0x0b, 0x09, 0xce, 0x21, 0xdb, 0x68, 0x48, 0x15, 0xcb, 0x49, 0xd7, 0xc6, 0x21, 0x3f, 0xe5, 0x96, 0x10, 0x97, 0x6e, 0x0f, 0x08, 0x31, 0xec, 0xe4, 0x7f, 0xed, 0xef, 0x3d}}, {LanguageCode::kEsEs, "es-ES", - IDS_SODA_LANGUAGE_DISPLAY_NAME_SPANISH, prefs::kSodaEsEsConfigPath, {0x9a, 0x22, 0xac, 0x04, 0x97, 0xc1, 0x70, 0x61, 0x24, 0x1f, 0x49, 0x18, 0x72, 0xd8, 0x67, 0x31, 0x72, 0x7a, 0xf9, 0x77, 0x04, 0xf0, 0x17, 0xb5, 0xfe, 0x88, 0xac, 0x60, 0xdd, 0x8a, 0x67, 0xdd}}, {LanguageCode::kFrFr, "fr-FR", - IDS_SODA_LANGUAGE_DISPLAY_NAME_FRENCH, prefs::kSodaFrFrConfigPath, {0x6e, 0x0e, 0x2b, 0xd3, 0xc6, 0xe5, 0x1b, 0x5e, 0xfa, 0xef, 0x42, 0x3f, 0x57, 0xb9, 0x2b, 0x13, 0x56, 0x47, 0x58, 0xdb, 0x76, 0x89, 0x71, 0xeb, 0x1f, 0xed, 0x48, 0x6c, 0xac, 0xd5, 0x31, 0xa0}}, {LanguageCode::kItIt, "it-IT", - IDS_SODA_LANGUAGE_DISPLAY_NAME_ITALIAN, prefs::kSodaItItConfigPath, {0x97, 0x45, 0xd7, 0xbc, 0xf0, 0x61, 0x24, 0xb3, 0x0e, 0x13, 0xf2, 0x97, 0xaa, 0xd5, 0x9e, 0x78, 0xa5, 0x81, 0x35, 0x75, 0xb5, 0x9d, 0x3b, 0xbb, 0xde, 0xba, 0x0e, 0xf7, 0xf0, 0x48, 0x56, 0x01}}, {LanguageCode::kJaJp, "ja-JP", - IDS_SODA_LANGUAGE_DISPLAY_NAME_JAPANESE, prefs::kSodaJaJpConfigPath, {0xed, 0x7f, 0x96, 0xa5, 0x60, 0x9c, 0xaa, 0x4d, 0x80, 0xe5, 0xb8, 0x26, 0xea, 0xf0, 0x41, 0x50, 0x09, 0x52, 0xa4, 0xb3, 0x1e, 0x6a, @@ -164,7 +152,8 @@ LanguageCode GetLanguageCode(const std::string& language_name); -int GetLanguageDisplayName(const std::string& language_name); +const std::u16string GetLanguageDisplayName(const std::string& language_name, + const std::string& display_locale); // Returns the `SodaInstaller.Language.{language}.InstallationSuccessTime` uma // metric string for the language code.
diff --git a/components/soda_strings.grdp b/components/soda_strings.grdp deleted file mode 100644 index 998a4ac..0000000 --- a/components/soda_strings.grdp +++ /dev/null
@@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <message name="IDS_SODA_LANGUAGE_DISPLAY_NAME_ENGLISH" desc="The display name of the SODA English language component."> - English - </message> - <message name="IDS_SODA_LANGUAGE_DISPLAY_NAME_FRENCH" desc="The display name of the SODA French language component."> - French - </message> - <message name="IDS_SODA_LANGUAGE_DISPLAY_NAME_GERMAN" desc="The display name of the SODA German language component."> - German - </message> - <message name="IDS_SODA_LANGUAGE_DISPLAY_NAME_ITALIAN" desc="The display name of the SODA Italian language component."> - Italian - </message> - <message name="IDS_SODA_LANGUAGE_DISPLAY_NAME_JAPANESE" desc="The display name of the SODA Japanese language component."> - Japanese - </message> - <message name="IDS_SODA_LANGUAGE_DISPLAY_NAME_SPANISH" desc="The display name of the SODA Spanish language component."> - Spanish - </message> -</grit-part>
diff --git a/components/soda_strings_grdp/DIR_METADATA b/components/soda_strings_grdp/DIR_METADATA deleted file mode 100644 index 6667e7f..0000000 --- a/components/soda_strings_grdp/DIR_METADATA +++ /dev/null
@@ -1,3 +0,0 @@ -monorail { - component: "Internals>Media" -}
diff --git a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_ENGLISH.png.sha1 b/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_ENGLISH.png.sha1 deleted file mode 100644 index 7e1549b..0000000 --- a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_ENGLISH.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0f9def9b80dae916d6c25c529c8fc8bba7995395 \ No newline at end of file
diff --git a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_FRENCH.png.sha1 b/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_FRENCH.png.sha1 deleted file mode 100644 index 7e1549b..0000000 --- a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_FRENCH.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0f9def9b80dae916d6c25c529c8fc8bba7995395 \ No newline at end of file
diff --git a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_GERMAN.png.sha1 b/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_GERMAN.png.sha1 deleted file mode 100644 index 7e1549b..0000000 --- a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_GERMAN.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0f9def9b80dae916d6c25c529c8fc8bba7995395 \ No newline at end of file
diff --git a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_ITALIAN.png.sha1 b/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_ITALIAN.png.sha1 deleted file mode 100644 index 7e1549b..0000000 --- a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_ITALIAN.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0f9def9b80dae916d6c25c529c8fc8bba7995395 \ No newline at end of file
diff --git a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_JAPANESE.png.sha1 b/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_JAPANESE.png.sha1 deleted file mode 100644 index 7e1549b..0000000 --- a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_JAPANESE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0f9def9b80dae916d6c25c529c8fc8bba7995395 \ No newline at end of file
diff --git a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_SPANISH.png.sha1 b/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_SPANISH.png.sha1 deleted file mode 100644 index 7e1549b..0000000 --- a/components/soda_strings_grdp/IDS_SODA_LANGUAGE_DISPLAY_NAME_SPANISH.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -0f9def9b80dae916d6c25c529c8fc8bba7995395 \ No newline at end of file
diff --git a/components/soda_strings_grdp/OWNERS b/components/soda_strings_grdp/OWNERS deleted file mode 100644 index 57d73f8..0000000 --- a/components/soda_strings_grdp/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -file://components/soda/OWNERS
diff --git a/components/soda_strings_grdp/README.md b/components/soda_strings_grdp/README.md deleted file mode 100644 index 119d8b9..0000000 --- a/components/soda_strings_grdp/README.md +++ /dev/null
@@ -1,5 +0,0 @@ -This directory of image SHA-1 hashes is used to improve translations of UI -strings through context images for translators. - -See also: [Chrome Translation Screenshots - Instructions & FAQ -](https://docs.google.com/document/d/1nwYWDny20icMSpLUuV_LgrlbWKrYpbXOERUIZNH636o/edit#heading=h.2t7lc4cxo2au)
diff --git a/components/supervised_user/core/browser/web_content_handler.h b/components/supervised_user/core/browser/web_content_handler.h index 7dfb766..90a552cf 100644 --- a/components/supervised_user/core/browser/web_content_handler.h +++ b/components/supervised_user/core/browser/web_content_handler.h
@@ -10,12 +10,7 @@ #include "base/functional/callback.h" #include "base/time/time.h" -namespace gfx { -class ImageSkia; -} // namespace gfx - class GURL; - namespace supervised_user { class SupervisedUserSettingsService; @@ -49,7 +44,6 @@ virtual void RequestLocalApproval( const GURL& url, const std::u16string& child_display_name, - const gfx::ImageSkia& favicon, ApprovalRequestInitiatedCallback callback) = 0; static const char* GetLocalApprovalDurationMillisecondsHistogram();
diff --git a/components/translate/core/browser/translate_language_list.cc b/components/translate/core/browser/translate_language_list.cc index 6934580..b1f0a92 100644 --- a/components/translate/core/browser/translate_language_list.cc +++ b/components/translate/core/browser/translate_language_list.cc
@@ -9,10 +9,10 @@ #include <iterator> #include "base/check.h" +#include "base/debug/dump_without_crashing.h" #include "base/functional/bind.h" #include "base/json/json_reader.h" #include "base/lazy_instance.h" -#include "base/notreached.h" #include "base/ranges/algorithm.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -327,7 +327,7 @@ if (!json_value || !json_value->is_dict()) { NotifyEvent(__LINE__, "Language list is invalid"); - NOTREACHED(); + base::debug::DumpWithoutCrashing(); return false; } // The first level dictionary contains two sub-dicts, first for source @@ -337,7 +337,7 @@ json_value->FindDictPath(TranslateLanguageList::kTargetLanguagesKey); if (!target_languages) { NotifyEvent(__LINE__, "Target languages are not found in the response"); - NOTREACHED(); + base::debug::DumpWithoutCrashing(); return false; }
diff --git a/components/variations/android/variations_associated_data_android.cc b/components/variations/android/variations_associated_data_android.cc index 55d58be..7035756 100644 --- a/components/variations/android/variations_associated_data_android.cc +++ b/components/variations/android/variations_associated_data_android.cc
@@ -5,6 +5,7 @@ #include <string> #include "base/android/jni_string.h" +#include "base/metrics/field_trial_params.h" #include "components/variations/jni/VariationsAssociatedData_jni.h" #include "components/variations/variations_associated_data.h" #include "components/variations/variations_ids_provider.h" @@ -24,7 +25,7 @@ std::string trial_name(ConvertJavaStringToUTF8(env, jtrial_name)); std::string param_name(ConvertJavaStringToUTF8(env, jparam_name)); std::string param_value = - variations::GetVariationParamValue(trial_name, param_name); + base::GetFieldTrialParamValue(trial_name, param_name); return ConvertUTF8ToJavaString(env, param_value); }
diff --git a/components/variations/field_trial_config/field_trial_util_unittest.cc b/components/variations/field_trial_config/field_trial_util_unittest.cc index 9bcf0a16..356aa452 100644 --- a/components/variations/field_trial_config/field_trial_util_unittest.cc +++ b/components/variations/field_trial_config/field_trial_util_unittest.cc
@@ -115,9 +115,9 @@ ASSERT_TRUE(AssociateParamsFromString(kVariationsString)); base::FieldTrialList::CreateFieldTrial(kTrialName, "B"); - EXPECT_EQ("/", GetVariationParamValue(kTrialName, "a")); - EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "b")); - EXPECT_EQ(std::string(), GetVariationParamValue(kTrialName, "x")); + EXPECT_EQ("/", base::GetFieldTrialParamValue(kTrialName, "a")); + EXPECT_EQ(std::string(), base::GetFieldTrialParamValue(kTrialName, "b")); + EXPECT_EQ(std::string(), base::GetFieldTrialParamValue(kTrialName, "x")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams(kTrialName, ¶ms)); @@ -203,8 +203,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial1", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial1", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial1", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial1", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial1", ¶ms)); @@ -407,8 +407,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -454,8 +454,8 @@ kConfig, override_callback_.callback(), Study::PLATFORM_ANDROID_WEBVIEW, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -498,8 +498,8 @@ kConfig, override_callback_.callback(), Study::PLATFORM_ANDROID_WEBVIEW, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -537,8 +537,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -574,8 +574,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -618,8 +618,8 @@ kConfig, override_callback_.callback(), Study::PLATFORM_ANDROID_WEBVIEW, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -870,8 +870,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -920,8 +920,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -963,8 +963,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -1005,8 +1005,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("1", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("2", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("1", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("2", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_TRUE(base::GetFieldTrialParams("TestTrial", ¶ms)); @@ -1052,8 +1052,8 @@ kConfig, override_callback_.callback(), platform, variation_service_client_.GetCurrentFormFactor(), &feature_list); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "x")); - EXPECT_EQ("", GetVariationParamValue("TestTrial", "y")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "x")); + EXPECT_EQ("", base::GetFieldTrialParamValue("TestTrial", "y")); std::map<std::string, std::string> params; EXPECT_FALSE(base::GetFieldTrialParams("TestTrial", ¶ms));
diff --git a/components/variations/variations_associated_data.cc b/components/variations/variations_associated_data.cc index 26b3bc5..1dfda64 100644 --- a/components/variations/variations_associated_data.cc +++ b/components/variations/variations_associated_data.cc
@@ -158,11 +158,6 @@ return base::AssociateFieldTrialParams(trial_name, group_name, params); } -std::string GetVariationParamValue(const std::string& trial_name, - const std::string& param_name) { - return base::GetFieldTrialParamValue(trial_name, param_name); -} - // Functions below are exposed for testing explicitly behind this namespace. // They simply wrap existing functions in this file. namespace testing {
diff --git a/components/variations/variations_associated_data.h b/components/variations/variations_associated_data.h index 2674d0a..d5e04ae29 100644 --- a/components/variations/variations_associated_data.h +++ b/components/variations/variations_associated_data.h
@@ -33,7 +33,7 @@ // // use |params| // } // -// std::string value = GetVariationParamValue("trial", "param_x"); +// std::string value = base::GetFieldTrialParamValue("trial", "param_x"); // // use |value|, which will be "" if it does not exist // // VariationID id = GetGoogleVariationID( @@ -126,11 +126,6 @@ const std::string& group_name, const std::map<std::string, std::string>& params); -// Deprecated. Use base::GetFieldTrialParamValue() instead. -COMPONENT_EXPORT(VARIATIONS) -std::string GetVariationParamValue(const std::string& trial_name, - const std::string& param_name); - // Expose some functions for testing. namespace testing {
diff --git a/components/variations/variations_request_scheduler.cc b/components/variations/variations_request_scheduler.cc index 69805d3..19a16b40 100644 --- a/components/variations/variations_request_scheduler.cc +++ b/components/variations/variations_request_scheduler.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "build/build_config.h" #include "components/variations/variations_associated_data.h" @@ -93,8 +94,8 @@ return overridden_period.value(); // The fetch interval can be overridden by a variation param. - std::string period_min_str = - GetVariationParamValue("VariationsServiceControl", "fetch_period_min"); + std::string period_min_str = base::GetFieldTrialParamValue( + "VariationsServiceControl", "fetch_period_min"); size_t period_min; if (base::StringToSizeT(period_min_str, &period_min)) return base::Minutes(period_min);
diff --git a/components/variations/variations_seed_processor_unittest.cc b/components/variations/variations_seed_processor_unittest.cc index f11fbed..870fe9a2 100644 --- a/components/variations/variations_seed_processor_unittest.cc +++ b/components/variations/variations_seed_processor_unittest.cc
@@ -18,6 +18,7 @@ #include "base/format_macros.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -407,13 +408,13 @@ Study::Experiment* experiment2 = AddExperiment("B", 0, study); this->CreateTrialsFromSeed(seed); - EXPECT_EQ("y", GetVariationParamValue("Study1", "x")); + EXPECT_EQ("y", base::GetFieldTrialParamValue("Study1", "x")); study->set_name("Study2"); experiment1->set_probability_weight(0); experiment2->set_probability_weight(1); this->CreateTrialsFromSeed(seed); - EXPECT_EQ(std::string(), GetVariationParamValue("Study2", "x")); + EXPECT_EQ(std::string(), base::GetFieldTrialParamValue("Study2", "x")); } TYPED_TEST(VariationsSeedProcessorTest, VariationParamsWithForcingFlag) { @@ -427,7 +428,7 @@ base::CommandLine::ForCurrentProcess()->AppendSwitch(kForcingFlag1); this->CreateTrialsFromSeed(seed); EXPECT_EQ(kFlagGroup1Name, base::FieldTrialList::FindFullName(study->name())); - EXPECT_EQ("y", GetVariationParamValue(study->name(), "x")); + EXPECT_EQ("y", base::GetFieldTrialParamValue(study->name(), "x")); } TYPED_TEST(VariationsSeedProcessorTest, StartsActive) { @@ -503,7 +504,7 @@ base::FieldTrialList::FindFullName(study->name())); // Check that params and experiment ids correspond. - EXPECT_EQ("y", GetVariationParamValue(study->name(), "x")); + EXPECT_EQ("y", base::GetFieldTrialParamValue(study->name(), "x")); VariationID id = GetGoogleVariationID(GOOGLE_WEB_PROPERTIES_ANY_CONTEXT, kFlagStudyName, kNonFlagGroupName); EXPECT_EQ(kExperimentId, id);
diff --git a/components/viz/service/display/resolved_frame_data.cc b/components/viz/service/display/resolved_frame_data.cc index 641c102..e27f4cbe 100644 --- a/components/viz/service/display/resolved_frame_data.cc +++ b/components/viz/service/display/resolved_frame_data.cc
@@ -269,16 +269,6 @@ gfx::Rect ResolvedFrameData::GetSurfaceDamage() const { DCHECK(valid_); - // The |damage_rect| set in |SurfaceAnimationManager| is the |output_rect|. - // However, we dont use |damage_rect| because when we transition from - // interpolated frame we would end up using the |damage_rect| from the - // original non interpolated frame. - // TODO(vmpstr): This damage may be too large, but I think it's hard to figure - // out a small bounds on the damage given an animation that happens in - // SurfaceAnimationManager. - if (surface_->HasSurfaceAnimationDamage()) - return GetOutputRect(); - if (IsSameFrameAsLastAggregation()) { return gfx::Rect(); } else if (IsNextFrameSinceLastAggregation()) {
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index d521e118..4f82f6b 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -407,12 +407,6 @@ const gfx::Transform& parent_target_transform, const Surface* surface, size_t* overlay_damage_index) { - // If we have damage from a surface animation, then we shouldn't have an - // overlay candidate from the root render pass, since that's an interpolated - // pass with "artificial" damage. - if (surface->HasSurfaceAnimationDamage()) - return nullptr; - // Only process the damage rect at the root render pass, once per surface. const CompositorFrame& frame = surface->GetActiveFrame(); bool is_last_pass_on_src_surface = @@ -552,8 +546,7 @@ // If there is a new CompositorFrame for `surface` compute resolved frame // data for the new resolved CompositorFrame. if (resolved_frame.previous_frame_index() != - surface->GetActiveFrameIndex() || - surface->HasSurfaceAnimationDamage()) { + surface->GetActiveFrameIndex()) { base::ElapsedTimer timer; ProcessResolvedFrame(resolved_frame); stats_->declare_resources_time += timer.Elapsed(); @@ -912,7 +905,6 @@ } referenced_surfaces_.erase(surface_id); - surface->DidAggregate(); } void SurfaceAggregator::EmitDefaultBackgroundColorQuad(
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 1e477e96..54ac755 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -732,23 +732,10 @@ return active_frame_data_->frame.metadata; } -void Surface::ResetInterpolatedFrame() { - interpolated_frame_.reset(); - has_damage_from_interpolated_frame_ = true; -} - void Surface::SetInterpolatedFrame(CompositorFrame frame) { interpolated_frame_.emplace(std::move(frame)); } -bool Surface::HasSurfaceAnimationDamage() const { - return interpolated_frame_.has_value() || has_damage_from_interpolated_frame_; -} - -void Surface::DidAggregate() { - has_damage_from_interpolated_frame_ = false; -} - const CompositorFrame& Surface::GetPendingFrame() { DCHECK(pending_frame_data_); return pending_frame_data_->frame;
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h index 16ed8468..d7630fa8 100644 --- a/components/viz/service/surfaces/surface.h +++ b/components/viz/service/surfaces/surface.h
@@ -202,7 +202,6 @@ const CompositorFrame& GetActiveFrame() const; const CompositorFrameMetadata& GetActiveFrameMetadata() const; - void ResetInterpolatedFrame(); void SetInterpolatedFrame(CompositorFrame frame); const CompositorFrame& GetActiveOrInterpolatedFrame() const; bool HasInterpolatedFrame() const; @@ -311,8 +310,6 @@ std::unique_ptr<CopyOutputRequest> copy_request, CompositorRenderPassId render_pass_id); - void DidAggregate(); - // Returns frame id of the oldest uncommitted frame if any, absl::optional<BeginFrameId> GetFirstUncommitedFrameId(); @@ -440,8 +437,6 @@ const raw_ptr<SurfaceAllocationGroup> allocation_group_; - bool has_damage_from_interpolated_frame_ = false; - const size_t max_uncommitted_frames_; base::WeakPtrFactory<Surface> weak_factory_{this};
diff --git a/components/webapps/browser/banners/app_banner_settings_helper.cc b/components/webapps/browser/banners/app_banner_settings_helper.cc index f71cdf9a..9679ee41 100644 --- a/components/webapps/browser/banners/app_banner_settings_helper.cc +++ b/components/webapps/browser/banners/app_banner_settings_helper.cc
@@ -15,12 +15,12 @@ #include "base/json/values_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/raw_ref.h" +#include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/permissions/permissions_client.h" -#include "components/variations/variations_associated_data.h" #include "components/webapps/browser/banners/app_banner_manager.h" #include "components/webapps/browser/banners/app_banner_metrics.h" #include "components/webapps/common/switches.h" @@ -134,9 +134,9 @@ // Queries variations for the number of days which dismissing and ignoring the // banner should prevent a banner from showing. void UpdateDaysBetweenShowing() { - std::string dismiss_param = variations::GetVariationParamValue( + std::string dismiss_param = base::GetFieldTrialParamValue( kBannerParamsKey, kBannerParamsDaysAfterBannerDismissedKey); - std::string ignore_param = variations::GetVariationParamValue( + std::string ignore_param = base::GetFieldTrialParamValue( kBannerParamsKey, kBannerParamsDaysAfterBannerIgnoredKey); if (!dismiss_param.empty() && !ignore_param.empty()) { @@ -154,7 +154,7 @@ // Queries variations for the maximum site engagement score required to trigger // the banner showing. void UpdateSiteEngagementToTrigger() { - std::string total_param = variations::GetVariationParamValue( + std::string total_param = base::GetFieldTrialParamValue( kBannerParamsKey, kBannerParamsEngagementTotalKey); if (!total_param.empty()) {
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h index 5378451..b6087d71 100644 --- a/content/browser/bad_message.h +++ b/content/browser/bad_message.h
@@ -324,6 +324,8 @@ BIBI_BIND_PRESSURE_MANAGER_BLOCKED_BY_PERMISSIONS_POLICY = 297, RFSCI_BROWSER_VALIDATION_BAD_ORIGIN_TRIAL_TOKEN = 298, RFH_RECEIVED_INVALID_BROWSING_TOPICS_ATTRIBUTE = 299, + RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT = 300, + RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME = 301, // Please add new elements here. The naming convention is abbreviated class // name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/content/browser/devtools/protocol/fedcm_handler.cc b/content/browser/devtools/protocol/fedcm_handler.cc index e80e0e60..f07766eb 100644 --- a/content/browser/devtools/protocol/fedcm_handler.cc +++ b/content/browser/devtools/protocol/fedcm_handler.cc
@@ -111,7 +111,15 @@ accounts->push_back(std::move(entry)); } } - frontend_->DialogShown(dialog_id_, std::move(accounts)); + IdentityRequestDialogController* dialog = auth_request->GetDialogController(); + CHECK(dialog); + Maybe<String> maybe_subtitle; + absl::optional<std::string> subtitle = dialog->GetSubtitle(); + if (subtitle) { + maybe_subtitle = *subtitle; + } + frontend_->DialogShown(dialog_id_, std::move(accounts), dialog->GetTitle(), + std::move(maybe_subtitle)); } DispatchResponse FedCmHandler::SelectAccount(const String& in_dialogId,
diff --git a/content/browser/devtools/protocol/storage_handler.cc b/content/browser/devtools/protocol/storage_handler.cc index a75318b..1b5a97b 100644 --- a/content/browser/devtools/protocol/storage_handler.cc +++ b/content/browser/devtools/protocol/storage_handler.cc
@@ -10,7 +10,9 @@ #include <vector> #include "base/functional/bind.h" +#include "base/notreached.h" #include "base/scoped_observation.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" #include "components/services/storage/privileged/mojom/indexed_db_control.mojom.h" @@ -29,11 +31,14 @@ #include "content/public/browser/storage_partition.h" #include "services/network/public/mojom/trust_tokens.mojom.h" #include "storage/browser/quota/quota_manager.h" +#include "storage/browser/quota/quota_manager_impl.h" +#include "storage/browser/quota/quota_manager_observer.mojom-forward.h" #include "storage/browser/quota/quota_manager_proxy.h" #include "storage/browser/quota/quota_override_handle.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/common/interest_group/interest_group.h" #include "third_party/blink/public/common/storage_key/storage_key.h" +#include "third_party/blink/public/mojom/buckets/bucket_manager_host.mojom-shared.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" #include "url/gurl.h" #include "url/origin.h" @@ -118,6 +123,30 @@ base::BindOnce(&GotUsageAndQuotaDataCallback, std::move(callback))); } +std::unique_ptr<protocol::Storage::StorageBucketInfo> BuildBucketInfo( + const storage::BucketInfo& bucket) { + std::string durability_enum; + switch (bucket.durability) { + case blink::mojom::BucketDurability::kRelaxed: + durability_enum = Storage::StorageBucketsDurabilityEnum::Relaxed; + break; + case blink::mojom::BucketDurability::kStrict: + durability_enum = Storage::StorageBucketsDurabilityEnum::Strict; + break; + } + + return protocol::Storage::StorageBucketInfo::Create() + .SetStorageKey(bucket.storage_key.Serialize()) + .SetId(base::NumberToString(bucket.id.value())) + .SetName(bucket.name) + .SetIsDefault(bucket.is_default()) + .SetExpiration(bucket.expiration.ToDoubleT()) + .SetQuota(bucket.quota) + .SetPersistent(bucket.persistent) + .SetDurability(durability_enum) + .Build(); +} + } // namespace // Observer that listens on the UI thread for cache storage notifications and @@ -140,8 +169,9 @@ void TrackStorageKey(const blink::StorageKey& storage_key) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (storage_keys_.find(storage_key) != storage_keys_.end()) + if (storage_keys_.find(storage_key) != storage_keys_.end()) { return; + } storage_keys_.insert(storage_key); } @@ -153,16 +183,18 @@ void OnCacheListChanged(const blink::StorageKey& storage_key) override { DCHECK_CURRENTLY_ON(BrowserThread::UI); auto found = storage_keys_.find(storage_key); - if (found == storage_keys_.end()) + if (found == storage_keys_.end()) { return; + } owner_->NotifyCacheStorageListChanged(storage_key); } void OnCacheContentChanged(const blink::StorageKey& storage_key, const std::string& cache_name) override { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (storage_keys_.find(storage_key) == storage_keys_.end()) + if (storage_keys_.find(storage_key) == storage_keys_.end()) { return; + } owner_->NotifyCacheStorageContentChanged(storage_key, cache_name); } @@ -196,8 +228,9 @@ void TrackStorageKey(const blink::StorageKey& storage_key) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (storage_keys_.find(storage_key) != storage_keys_.end()) + if (storage_keys_.find(storage_key) != storage_keys_.end()) { return; + } storage_keys_.insert(storage_key); } @@ -209,12 +242,14 @@ void OnIndexedDBListChanged( const storage::BucketLocator& bucket_locator) override { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!owner_) + if (!owner_) { return; + } // TODO(crbug.com/1315371): Allow custom bucket names. auto found = storage_keys_.find(bucket_locator.storage_key); - if (found == storage_keys_.end()) + if (found == storage_keys_.end()) { return; + } owner_->NotifyIndexedDBListChanged( bucket_locator.storage_key.origin().Serialize(), @@ -226,12 +261,14 @@ const std::u16string& database_name, const std::u16string& object_store_name) override { DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (!owner_) + if (!owner_) { return; + } // TODO(crbug.com/1315371): Allow custom bucket names. auto found = storage_keys_.find(bucket_locator.storage_key); - if (found == storage_keys_.end()) + if (found == storage_keys_.end()) { return; + } owner_->NotifyIndexedDBContentChanged( bucket_locator.storage_key.origin().Serialize(), @@ -242,8 +279,9 @@ private: void ReconnectObserver() { DCHECK(!receiver_.is_bound()); - if (!owner_) + if (!owner_) { return; + } auto& control = owner_->storage_partition_->GetIndexedDBControl(); mojo::PendingRemote<storage::mojom::IndexedDBObserver> remote; @@ -307,6 +345,69 @@ scoped_observation_{this}; }; +class StorageHandler::QuotaManagerObserver + : storage::mojom::QuotaManagerObserver { + public: + QuotaManagerObserver(base::WeakPtr<StorageHandler> owner_storage_handler, + storage::QuotaManagerProxy* quota_manager_proxy) + : owner_(owner_storage_handler) { + quota_manager_proxy->AddObserver(receiver_.BindNewPipeAndPassRemote()); + } + + QuotaManagerObserver(const QuotaManagerObserver&) = delete; + QuotaManagerObserver& operator=(const QuotaManagerObserver&) = delete; + + ~QuotaManagerObserver() override = default; + + void TrackStorageKey(const blink::StorageKey& storage_key, + storage::QuotaManagerProxy* manager) { + if (!storage_keys_.insert(storage_key).second) { + return; + } + manager->GetBucketsForStorageKey( + storage_key, blink::mojom::StorageType::kTemporary, false, + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::BindOnce( + [](base::WeakPtr<StorageHandler> owner_storage_handler, + storage::QuotaErrorOr<std::set<storage::BucketInfo>> buckets) { + if (!buckets.has_value()) { + return; + } + + for (const storage::BucketInfo& bucket : buckets.value()) { + owner_storage_handler->NotifyCreateOrUpdateBucket(bucket); + } + }, + owner_)); + } + + void UntrackStorageKey(const blink::StorageKey& storage_key) { + storage_keys_.erase(storage_key); + } + + private: + void OnCreateOrUpdateBucket(const storage::BucketInfo& bucket_info) override { + auto found = storage_keys_.find(bucket_info.storage_key); + if (found == storage_keys_.end()) { + return; + } + owner_->NotifyCreateOrUpdateBucket(bucket_info); + } + + void OnDeleteBucket(const storage::BucketLocator& bucket_locator) override { + auto found = storage_keys_.find(bucket_locator.storage_key); + if (found == storage_keys_.end()) { + return; + } + owner_->NotifyDeleteBucket(bucket_locator); + } + + base::flat_set<blink::StorageKey> storage_keys_; + + base::WeakPtr<StorageHandler> owner_; + mojo::Receiver<storage::mojom::QuotaManagerObserver> receiver_{this}; +}; + StorageHandler::StorageHandler(bool client_is_trusted) : DevToolsDomainHandler(Storage::Metainfo::domainName), client_is_trusted_(client_is_trusted) {} @@ -334,13 +435,15 @@ quota_override_handle_.reset(); SetInterestGroupTracking(false); shared_storage_observer_.reset(); + quota_manager_observer_.reset(); return Response::Success(); } void StorageHandler::GetCookies(Maybe<std::string> browser_context_id, std::unique_ptr<GetCookiesCallback> callback) { - if (!client_is_trusted_) + if (!client_is_trusted_) { callback->sendFailure(Response::ServerError("Permission denied")); + } StoragePartition* storage_partition = nullptr; Response response = StorageHandler::FindStoragePartition(browser_context_id, &storage_partition); @@ -405,17 +508,20 @@ Response StorageHandler::GetStorageKeyForFrame( const std::string& frame_id, std::string* serialized_storage_key) { - if (!frame_host_) + if (!frame_host_) { return Response::InvalidParams("Frame host not found"); + } FrameTreeNode* node = protocol::FrameTreeNodeFromDevToolsFrameToken( frame_host_->frame_tree_node(), frame_id); - if (!node) + if (!node) { return Response::InvalidParams("Frame tree node for given frame not found"); + } RenderFrameHostImpl* rfh = node->current_frame_host(); - if (rfh->storage_key().origin().opaque()) + if (rfh->storage_key().origin().opaque()) { return Response::ServerError( "Frame corresponds to an opaque origin and its storage key cannot be " "serialized"); + } *serialized_storage_key = rfh->storage_key().Serialize(); return Response::Success(); } @@ -426,28 +532,39 @@ storage_types, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); std::unordered_set<std::string> set(types.begin(), types.end()); uint32_t remove_mask = 0; - if (set.count(Storage::StorageTypeEnum::Cookies)) + if (set.count(Storage::StorageTypeEnum::Cookies)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_COOKIES; - if (set.count(Storage::StorageTypeEnum::File_systems)) + } + if (set.count(Storage::StorageTypeEnum::File_systems)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_FILE_SYSTEMS; - if (set.count(Storage::StorageTypeEnum::Indexeddb)) + } + if (set.count(Storage::StorageTypeEnum::Indexeddb)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_INDEXEDDB; - if (set.count(Storage::StorageTypeEnum::Local_storage)) + } + if (set.count(Storage::StorageTypeEnum::Local_storage)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_LOCAL_STORAGE; - if (set.count(Storage::StorageTypeEnum::Shader_cache)) + } + if (set.count(Storage::StorageTypeEnum::Shader_cache)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_SHADER_CACHE; - if (set.count(Storage::StorageTypeEnum::Websql)) + } + if (set.count(Storage::StorageTypeEnum::Websql)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_WEBSQL; - if (set.count(Storage::StorageTypeEnum::Service_workers)) + } + if (set.count(Storage::StorageTypeEnum::Service_workers)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_SERVICE_WORKERS; - if (set.count(Storage::StorageTypeEnum::Cache_storage)) + } + if (set.count(Storage::StorageTypeEnum::Cache_storage)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_CACHE_STORAGE; - if (set.count(Storage::StorageTypeEnum::Interest_groups)) + } + if (set.count(Storage::StorageTypeEnum::Interest_groups)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_INTEREST_GROUPS; - if (set.count(Storage::StorageTypeEnum::Shared_storage)) + } + if (set.count(Storage::StorageTypeEnum::Shared_storage)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_SHARED_STORAGE; - if (set.count(Storage::StorageTypeEnum::All)) + } + if (set.count(Storage::StorageTypeEnum::All)) { remove_mask |= StoragePartition::REMOVE_DATA_MASK_ALL; + } return remove_mask; } } // namespace @@ -456,8 +573,9 @@ const std::string& origin, const std::string& storage_types, std::unique_ptr<ClearDataForOriginCallback> callback) { - if (!storage_partition_) + if (!storage_partition_) { return callback->sendFailure(Response::InternalError()); + } uint32_t remove_mask = GetRemoveDataMask(storage_types); @@ -478,8 +596,9 @@ const std::string& storage_key, const std::string& storage_types, std::unique_ptr<ClearDataForStorageKeyCallback> callback) { - if (!storage_partition_) + if (!storage_partition_) { return callback->sendFailure(Response::InternalError()); + } uint32_t remove_mask = GetRemoveDataMask(storage_types); @@ -504,8 +623,9 @@ void StorageHandler::GetUsageAndQuota( const String& origin_string, std::unique_ptr<GetUsageAndQuotaCallback> callback) { - if (!storage_partition_) + if (!storage_partition_) { return callback->sendFailure(Response::InternalError()); + } GURL origin_url(origin_string); url::Origin origin = url::Origin::Create(origin_url); @@ -555,13 +675,15 @@ Response StorageHandler::TrackCacheStorageForOrigin( const std::string& origin_string) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } GURL origin_url(origin_string); url::Origin origin = url::Origin::Create(origin_url); - if (!origin_url.is_valid() || origin.opaque()) + if (!origin_url.is_valid() || origin.opaque()) { return Response::InvalidParams(origin_string + " is not a valid URL"); + } GetCacheStorageObserver()->TrackStorageKey( blink::StorageKey::CreateFirstParty(origin)); @@ -570,13 +692,15 @@ Response StorageHandler::TrackCacheStorageForStorageKey( const std::string& storage_key) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } absl::optional<blink::StorageKey> key = blink::StorageKey::Deserialize(storage_key); - if (!key) + if (!key) { return Response::InvalidParams("Unable to deserialize storage key"); + } GetCacheStorageObserver()->TrackStorageKey(*key); return Response::Success(); @@ -584,13 +708,15 @@ Response StorageHandler::UntrackCacheStorageForOrigin( const std::string& origin_string) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } GURL origin_url(origin_string); url::Origin origin = url::Origin::Create(origin_url); - if (!origin_url.is_valid() || origin.opaque()) + if (!origin_url.is_valid() || origin.opaque()) { return Response::InvalidParams(origin_string + " is not a valid URL"); + } GetCacheStorageObserver()->UntrackStorageKey( blink::StorageKey::CreateFirstParty(origin)); @@ -599,13 +725,15 @@ Response StorageHandler::UntrackCacheStorageForStorageKey( const std::string& storage_key) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } absl::optional<blink::StorageKey> key = blink::StorageKey::Deserialize(storage_key); - if (!key) + if (!key) { return Response::InvalidParams("Unable to deserialize storage key"); + } GetCacheStorageObserver()->UntrackStorageKey(*key); return Response::Success(); @@ -613,13 +741,15 @@ Response StorageHandler::TrackIndexedDBForOrigin( const std::string& origin_string) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } GURL origin_url(origin_string); url::Origin origin = url::Origin::Create(origin_url); - if (!origin_url.is_valid() || origin.opaque()) + if (!origin_url.is_valid() || origin.opaque()) { return Response::InvalidParams(origin_string + " is not a valid URL"); + } GetIndexedDBObserver()->TrackStorageKey( blink::StorageKey::CreateFirstParty(origin)); @@ -628,13 +758,15 @@ Response StorageHandler::TrackIndexedDBForStorageKey( const std::string& storage_key) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } absl::optional<blink::StorageKey> key = blink::StorageKey::Deserialize(storage_key); - if (!key) + if (!key) { return Response::InvalidParams("Unable to deserialize storage key"); + } GetIndexedDBObserver()->TrackStorageKey(*key); return Response::Success(); @@ -642,13 +774,15 @@ Response StorageHandler::UntrackIndexedDBForOrigin( const std::string& origin_string) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } GURL origin_url(origin_string); url::Origin origin = url::Origin::Create(origin_url); - if (!origin_url.is_valid() || origin.opaque()) + if (!origin_url.is_valid() || origin.opaque()) { return Response::InvalidParams(origin_string + " is not a valid URL"); + } GetIndexedDBObserver()->UntrackStorageKey( blink::StorageKey::CreateFirstParty(origin)); @@ -657,13 +791,15 @@ Response StorageHandler::UntrackIndexedDBForStorageKey( const std::string& storage_key) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } absl::optional<blink::StorageKey> key = blink::StorageKey::Deserialize(storage_key); - if (!key) + if (!key) { return Response::InvalidParams("Unable to deserialize storage key"); + } GetIndexedDBObserver()->UntrackStorageKey(*key); return Response::Success(); @@ -701,8 +837,9 @@ absl::variant<protocol::Response, storage::SharedStorageManager*> StorageHandler::GetSharedStorageManager() { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } if (auto* manager = static_cast<StoragePartitionImpl*>(storage_partition_) ->GetSharedStorageManager()) { @@ -711,6 +848,13 @@ return Response::ServerError("Shared storage is disabled"); } +storage::QuotaManagerProxy* StorageHandler::GetQuotaManagerProxy() { + DCHECK(storage_partition_); + + return static_cast<StoragePartitionImpl*>(storage_partition_) + ->GetQuotaManagerProxy(); +} + void StorageHandler::NotifyCacheStorageListChanged( const blink::StorageKey& storage_key) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -750,11 +894,13 @@ BrowserContext* browser_context = nullptr; Response response = BrowserHandler::FindBrowserContext(browser_context_id, &browser_context); - if (!response.IsSuccess()) + if (!response.IsSuccess()) { return response; + } *storage_partition = browser_context->GetDefaultStoragePartition(); - if (!*storage_partition) + if (!*storage_partition) { return Response::InternalError(); + } return Response::Success(); } @@ -874,8 +1020,9 @@ auto trusted_bidding_signals_keys = std::make_unique<protocol::Array<std::string>>(); if (group.trusted_bidding_signals_keys) { - for (const auto& key : group.trusted_bidding_signals_keys.value()) + for (const auto& key : group.trusted_bidding_signals_keys.value()) { trusted_bidding_signals_keys->push_back(key); + } } auto ads = std::make_unique<protocol::Array<protocol::Storage::InterestGroupAd>>(); @@ -884,8 +1031,9 @@ auto protocol_ad = protocol::Storage::InterestGroupAd::Create() .SetRenderUrl(ad.render_url.spec()) .Build(); - if (ad.metadata) + if (ad.metadata) { protocol_ad->SetMetadata(*ad.metadata); + } ads->push_back(std::move(protocol_ad)); } } @@ -896,8 +1044,9 @@ auto protocol_ad = protocol::Storage::InterestGroupAd::Create() .SetRenderUrl(ad.render_url.spec()) .Build(); - if (ad.metadata) + if (ad.metadata) { protocol_ad->SetMetadata(*ad.metadata); + } ad_components->push_back(std::move(protocol_ad)); } } @@ -911,19 +1060,23 @@ .SetAds(std::move(ads)) .SetAdComponents(std::move(ad_components)) .Build(); - if (group.bidding_url) + if (group.bidding_url) { protocol_group->SetBiddingUrl(group.bidding_url->spec()); - if (group.bidding_wasm_helper_url) + } + if (group.bidding_wasm_helper_url) { protocol_group->SetBiddingWasmHelperUrl( group.bidding_wasm_helper_url->spec()); + } if (group.update_url) { protocol_group->SetUpdateUrl(group.update_url->spec()); } - if (group.trusted_bidding_signals_url) + if (group.trusted_bidding_signals_url) { protocol_group->SetTrustedBiddingSignalsUrl( group.trusted_bidding_signals_url->spec()); - if (group.user_bidding_signals) + } + if (group.user_bidding_signals) { protocol_group->SetUserBiddingSignals(*group.user_bidding_signals); + } callback->sendSuccess(std::move(protocol_group)); } @@ -961,20 +1114,23 @@ } Response StorageHandler::SetInterestGroupTracking(bool enable) { - if (!storage_partition_) + if (!storage_partition_) { return Response::InternalError(); + } InterestGroupManagerImpl* manager = static_cast<InterestGroupManagerImpl*>( storage_partition_->GetInterestGroupManager()); - if (!manager) + if (!manager) { return Response::ServerError("Interest group storage is disabled."); + } if (enable) { // Only add if we are not already registered as an observer. We only // observe the interest group manager, so if we're observing anything then // we are already registered. - if (!IsInObserverList()) + if (!IsInObserverList()) { manager->AddInterestGroupObserver(this); + } } else { // Removal doesn't care if we are not registered. manager->RemoveInterestGroupObserver(this); @@ -1231,8 +1387,9 @@ Response StorageHandler::SetSharedStorageTracking(bool enable) { if (enable) { - if (!GetSharedStorageWorkletHostManager()) + if (!GetSharedStorageWorkletHostManager()) { return Response::ServerError("Shared storage is disabled."); + } shared_storage_observer_ = std::make_unique<SharedStorageObserver>(this); } else { shared_storage_observer_.reset(); @@ -1334,16 +1491,21 @@ auto protocol_params = protocol::Storage::SharedStorageAccessParams::Create().Build(); - if (params.script_source_url) + if (params.script_source_url) { protocol_params->SetScriptSourceUrl(*params.script_source_url); - if (params.operation_name) + } + if (params.operation_name) { protocol_params->SetOperationName(*params.operation_name); - if (params.serialized_data) + } + if (params.serialized_data) { protocol_params->SetSerializedData(*params.serialized_data); - if (params.key) + } + if (params.key) { protocol_params->SetKey(*params.key); - if (params.value) + } + if (params.value) { protocol_params->SetValue(*params.value); + } if (params.urls_with_metadata) { auto protocol_urls = std::make_unique< @@ -1378,5 +1540,55 @@ std::move(protocol_params)); } +DispatchResponse StorageHandler::SetStorageBucketTracking( + const std::string& serialized_storage_key, + bool enable) { + auto storage_key = blink::StorageKey::Deserialize(serialized_storage_key); + if (!storage_key.has_value()) { + return Response::InvalidParams("Invalid Storage Key given."); + } + + if (enable) { + storage::QuotaManagerProxy* manager = GetQuotaManagerProxy(); + if (!quota_manager_observer_) { + quota_manager_observer_ = + std::make_unique<StorageHandler::QuotaManagerObserver>( + weak_ptr_factory_.GetWeakPtr(), manager); + } + quota_manager_observer_->TrackStorageKey(storage_key.value(), manager); + } else if (quota_manager_observer_) { + quota_manager_observer_->UntrackStorageKey(storage_key.value()); + } + return Response::Success(); +} + +DispatchResponse StorageHandler::DeleteStorageBucket( + const std::string& serialized_storage_key, + const std::string& bucket_name) { + storage::QuotaManagerProxy* manager = GetQuotaManagerProxy(); + DCHECK(manager); + + auto storage_key = blink::StorageKey::Deserialize(serialized_storage_key); + if (!storage_key.has_value()) { + return Response::InvalidParams("Invalid Storage Key given."); + } + + manager->DeleteBucket(storage_key.value(), bucket_name, + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::DoNothing()); + return Response::Success(); +} + +void StorageHandler::NotifyCreateOrUpdateBucket( + const storage::BucketInfo& bucket_info) { + frontend_->StorageBucketCreatedOrUpdated(BuildBucketInfo(bucket_info)); +} + +void StorageHandler::NotifyDeleteBucket( + const storage::BucketLocator& bucket_locator) { + frontend_->StorageBucketDeleted( + base::NumberToString(bucket_locator.id.value())); +} + } // namespace protocol } // namespace content
diff --git a/content/browser/devtools/protocol/storage_handler.h b/content/browser/devtools/protocol/storage_handler.h index 5fa6df9..99b2f02 100644 --- a/content/browser/devtools/protocol/storage_handler.h +++ b/content/browser/devtools/protocol/storage_handler.h
@@ -16,6 +16,7 @@ #include "content/browser/renderer_host/frame_tree_node.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/shared_storage/shared_storage_worklet_host_manager.h" +#include "storage/browser/quota/quota_manager.h" namespace storage { class QuotaOverrideHandle; @@ -129,12 +130,21 @@ const std::string& owner_origin_string, std::unique_ptr<ResetSharedStorageBudgetCallback> callback) override; + DispatchResponse SetStorageBucketTracking( + const std::string& serialized_storage_key, + bool enable) override; + + DispatchResponse DeleteStorageBucket( + const std::string& serialized_storage_key, + const std::string& bucket_name) override; + private: // See definition for lifetime information. class CacheStorageObserver; class IndexedDBObserver; class InterestGroupObserver; class SharedStorageObserver; + class QuotaManagerObserver; // Not thread safe. CacheStorageObserver* GetCacheStorageObserver(); @@ -143,6 +153,7 @@ SharedStorageWorkletHostManager* GetSharedStorageWorkletHostManager(); absl::variant<protocol::Response, storage::SharedStorageManager*> GetSharedStorageManager(); + storage::QuotaManagerProxy* GetQuotaManagerProxy(); // content::InterestGroupManagerImpl::InterestGroupObserver void OnInterestGroupAccessed( @@ -168,6 +179,8 @@ const std::string& storage_key, const std::u16string& database_name, const std::u16string& object_store_name); + void NotifyCreateOrUpdateBucket(const storage::BucketInfo& bucket_info); + void NotifyDeleteBucket(const storage::BucketLocator& bucket_locator); Response FindStoragePartition(const Maybe<std::string>& browser_context_id, StoragePartition** storage_partition); @@ -178,6 +191,7 @@ std::unique_ptr<CacheStorageObserver> cache_storage_observer_; std::unique_ptr<IndexedDBObserver> indexed_db_observer_; std::unique_ptr<SharedStorageObserver> shared_storage_observer_; + std::unique_ptr<QuotaManagerObserver> quota_manager_observer_; // Exposes the API for managing storage quota overrides. std::unique_ptr<storage::QuotaOverrideHandle> quota_override_handle_;
diff --git a/content/browser/devtools/protocol_config.json b/content/browser/devtools/protocol_config.json index ceb55e5..f5afd91 100644 --- a/content/browser/devtools/protocol_config.json +++ b/content/browser/devtools/protocol_config.json
@@ -99,7 +99,7 @@ }, { "domain": "Storage", - "async": ["getUsageAndQuota", "clearDataForOrigin", "clearDataForStorageKey", "getCookies", "setCookies", "clearCookies", "overrideQuotaForOrigin", "getTrustTokens", "clearTrustTokens", "getInterestGroupDetails", "getSharedStorageMetadata", "getSharedStorageEntries", "setSharedStorageEntry", "deleteSharedStorageEntry", "clearSharedStorageEntries", "resetSharedStorageBudget"] + "async": ["getUsageAndQuota", "clearDataForOrigin", "clearDataForStorageKey", "getCookies", "setCookies", "clearCookies", "overrideQuotaForOrigin", "getTrustTokens", "clearTrustTokens", "getInterestGroupDetails", "getSharedStorageMetadata", "getSharedStorageEntries", "setSharedStorageEntry", "deleteSharedStorageEntry", "clearSharedStorageEntries", "resetSharedStorageBudget", "getStorageBucketList"] }, { "domain": "SystemInfo",
diff --git a/content/browser/loader/navigation_url_loader.h b/content/browser/loader/navigation_url_loader.h index 2ebfd46d..38f82bb 100644 --- a/content/browser/loader/navigation_url_loader.h +++ b/content/browser/loader/navigation_url_loader.h
@@ -11,8 +11,10 @@ #include "content/browser/loader/navigation_loader_interceptor.h" #include "content/common/content_export.h" +#include "services/network/public/mojom/cookie_access_observer.mojom.h" #include "services/network/public/mojom/devtools_observer.mojom-forward.h" #include "services/network/public/mojom/trust_token_access_observer.mojom-forward.h" +#include "services/network/public/mojom/url_loader_network_service_observer.mojom.h" namespace net { class HttpRequestHeaders;
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc index 556cd55..258c8be 100644 --- a/content/browser/loader/navigation_url_loader_impl_unittest.cc +++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -238,7 +238,8 @@ absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation, - false /* is_container_initiated */); + false /* is_container_initiated */, + false /* is_fullscreen_requested */); auto common_params = blink::CreateCommonNavigationParams(); common_params->url = url;
diff --git a/content/browser/loader/navigation_url_loader_unittest.cc b/content/browser/loader/navigation_url_loader_unittest.cc index 32a7402..6b55c1a1 100644 --- a/content/browser/loader/navigation_url_loader_unittest.cc +++ b/content/browser/loader/navigation_url_loader_unittest.cc
@@ -99,7 +99,8 @@ absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation, - false /* is_container_initiated */); + false /* is_container_initiated */, + false /* is_fullscreen_requested */); auto common_params = blink::CreateCommonNavigationParams(); common_params->url = url; common_params->initiator_origin = url::Origin::Create(url);
diff --git a/content/browser/preloading/prefetch/prefetch_container.cc b/content/browser/preloading/prefetch/prefetch_container.cc index 7388fb2..a4eabd709 100644 --- a/content/browser/preloading/prefetch/prefetch_container.cc +++ b/content/browser/preloading/prefetch/prefetch_container.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/notreached.h" #include "base/time/time.h" @@ -231,6 +232,40 @@ } } +std::string GetEagernessHistogramSuffix( + const blink::mojom::SpeculationEagerness& eagerness) { + switch (eagerness) { + case blink::mojom::SpeculationEagerness::kEager: + return "Eager"; + case blink::mojom::SpeculationEagerness::kModerate: + return "Moderate"; + case blink::mojom::SpeculationEagerness::kConservative: + return "Conservative"; + } +} + +void RecordWasBlockedUntilHeadWhenServingHistogram( + const blink::mojom::SpeculationEagerness& eagerness, + bool blocked_until_head) { + base::UmaHistogramBoolean( + base::StringPrintf( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.%s", + GetEagernessHistogramSuffix(eagerness).c_str()), + blocked_until_head); +} + +void RecordBlockUntilHeadDurationHistogram( + const blink::mojom::SpeculationEagerness& eagerness, + const base::TimeDelta& block_until_head_duration, + bool served) { + base::UmaHistogramTimes( + base::StringPrintf( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.%s.%s", + served ? "Served" : "NotServed", + GetEagernessHistogramSuffix(eagerness).c_str()), + block_until_head_duration); +} + } // namespace PrefetchContainer::PrefetchContainer( @@ -604,7 +639,8 @@ bool PrefetchContainer::ShouldBlockUntilHeadReceived() const { // Can only block until head if the request has been started using a streaming // URL loader and head hasn't been received yet. - if (!streaming_loader_ || streaming_loader_->GetHead()) { + if (!streaming_loader_ || streaming_loader_->GetHead() || + streaming_loader_->Failed()) { return false; } return PrefetchShouldBlockUntilHead(prefetch_type_.GetEagerness()); @@ -694,6 +730,28 @@ return internal_url == no_vary_search_match_url.value(); } +void PrefetchContainer::OnGetPrefetchToServe(bool blocked_until_head) { + if (blocked_until_head) { + blocked_until_head_start_time_ = base::TimeTicks::Now(); + } + + RecordWasBlockedUntilHeadWhenServingHistogram(prefetch_type_.GetEagerness(), + blocked_until_head); +} + +void PrefetchContainer::OnReturnPrefetchToServe(bool served) { + if (served) { + navigated_to_ = true; + } + + if (blocked_until_head_start_time_.has_value()) { + RecordBlockUntilHeadDurationHistogram( + prefetch_type_.GetEagerness(), + base::TimeTicks::Now() - blocked_until_head_start_time_.value(), + served); + } +} + PrefetchContainer::SinglePrefetch::SinglePrefetch(const GURL& url) : url_(url) {}
diff --git a/content/browser/preloading/prefetch/prefetch_container.h b/content/browser/preloading/prefetch/prefetch_container.h index c2522ad6..fd6612d 100644 --- a/content/browser/preloading/prefetch/prefetch_container.h +++ b/content/browser/preloading/prefetch/prefetch_container.h
@@ -172,9 +172,10 @@ // The |PrefetchDocumentManager| that requested |this|. PrefetchDocumentManager* GetPrefetchDocumentManager() const; - // Called when a navigation is started that could pottentially use this - // prefetch. - void OnNavigationToPrefetch() { navigated_to_ = true; } + // Called when |PrefetchService::GetPrefetchToServe| and + // |PrefetchService::ReturnPrefetchToServe| with |this|. + void OnGetPrefetchToServe(bool blocked_until_head); + void OnReturnPrefetchToServe(bool served); // Returns whether or not this prefetch has been considered to serve for a // navigation in the past. If it has, then it shouldn't be used for any future @@ -419,6 +420,10 @@ const absl::optional<base::UnguessableToken> initiator_devtools_navigation_token_; + // The time at which |PrefetchService| started blocking until the head of + // |this| was received. + absl::optional<base::TimeTicks> blocked_until_head_start_time_; + base::WeakPtrFactory<PrefetchContainer> weak_method_factory_{this}; };
diff --git a/content/browser/preloading/prefetch/prefetch_container_unittest.cc b/content/browser/preloading/prefetch/prefetch_container_unittest.cc index f19f3dfa..3be79ad 100644 --- a/content/browser/preloading/prefetch/prefetch_container_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_container_unittest.cc
@@ -418,7 +418,7 @@ // Simulates the URL of the prefetch being navigated to and the prefetch being // considered for serving. - prefetch_container->OnNavigationToPrefetch(); + prefetch_container->OnReturnPrefetchToServe(/*served=*/true); // Simulate a successful DNS probe for this prefetch. Not this will also // update the status of the prefetch to @@ -713,4 +713,73 @@ GURL("https://test.com?a=2"))); } +TEST_F(PrefetchContainerTest, BlockUntilHeadHistograms) { + struct TestCase { + blink::mojom::SpeculationEagerness eagerness; + bool block_until_head; + base::TimeDelta block_until_head_duration; + bool served; + }; + + std::vector<TestCase> test_cases{ + {blink::mojom::SpeculationEagerness::kEager, true, base::Milliseconds(10), + true}, + {blink::mojom::SpeculationEagerness::kModerate, false, + base::Milliseconds(20), false}, + {blink::mojom::SpeculationEagerness::kConservative, true, + base::Milliseconds(40), false}}; + + base::HistogramTester histogram_tester; + for (const auto& test_case : test_cases) { + PrefetchContainer prefetch_container( + GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"), + PrefetchType(/*use_isolated_network_context=*/true, + /*use_prefetch_proxy=*/true, test_case.eagerness), + blink::mojom::Referrer(), nullptr); + + prefetch_container.OnGetPrefetchToServe(test_case.block_until_head); + if (test_case.block_until_head) { + task_environment()->FastForwardBy(test_case.block_until_head_duration); + } + prefetch_container.OnReturnPrefetchToServe(test_case.served); + } + + histogram_tester.ExpectBucketCount( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.Eager", true, 1); + histogram_tester.ExpectBucketCount( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.Eager", false, + 0); + + histogram_tester.ExpectBucketCount( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.Moderate", true, + 0); + histogram_tester.ExpectBucketCount( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.Moderate", false, + 1); + + histogram_tester.ExpectBucketCount( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.Conservative", + true, 1); + histogram_tester.ExpectBucketCount( + "PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.Conservative", + false, 0); + + histogram_tester.ExpectUniqueTimeSample( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.Served.Eager", + base::Milliseconds(10), 1); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.NotServed.Eager", 0); + + histogram_tester.ExpectTotalCount( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.Served.Moderate", 0); + histogram_tester.ExpectTotalCount( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.NotServed.Moderate", 0); + + histogram_tester.ExpectTotalCount( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.Served.Conservative", 0); + histogram_tester.ExpectUniqueTimeSample( + "PrefetchProxy.AfterClick.BlockUntilHeadDuration.NotServed.Conservative", + base::Milliseconds(40), 1); +} + } // namespace content
diff --git a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc index 036ffcd..b647074 100644 --- a/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_document_manager_unittest.cc
@@ -283,7 +283,8 @@ // Cover the case where we want to navigate again to the same prefetched // Url. // Simulate that we've already navigated to prefetched URL. - GetPrefetchesPreparedToServe()[0].second->OnNavigationToPrefetch(); + GetPrefetchesPreparedToServe()[0].second->OnReturnPrefetchToServe( + /*served=*/true); // Try to navigate again to the same URL. NavigateMainframeRendererTo(GetCrossOriginUrl("/candidate2.html?a=2&b=3")); EXPECT_EQ(GetPrefetchesPreparedToServe().size(), 2u);
diff --git a/content/browser/preloading/prefetch/prefetch_params.cc b/content/browser/preloading/prefetch/prefetch_params.cc index 6df1aa1..cd1d7f57 100644 --- a/content/browser/preloading/prefetch/prefetch_params.cc +++ b/content/browser/preloading/prefetch/prefetch_params.cc
@@ -224,7 +224,7 @@ case blink::mojom::SpeculationEagerness::kEager: return base::GetFieldTrialParamByFeatureAsBool( features::kPrefetchUseContentRefactor, - "block_until_head_eager_prefetch", false); + "block_until_head_eager_prefetch", true); case blink::mojom::SpeculationEagerness::kModerate: return base::GetFieldTrialParamByFeatureAsBool( features::kPrefetchUseContentRefactor,
diff --git a/content/browser/preloading/prefetch/prefetch_service.cc b/content/browser/preloading/prefetch/prefetch_service.cc index c0d2a10..f3599c4 100644 --- a/content/browser/preloading/prefetch/prefetch_service.cc +++ b/content/browser/preloading/prefetch/prefetch_service.cc
@@ -1230,12 +1230,14 @@ } if (prefetch_container->IsPrefetchServable(PrefetchCacheableDuration())) { + prefetch_container->OnGetPrefetchToServe(/*blocked_until_head=*/false); ReturnPrefetchToServe(prefetch_container, std::move(on_prefetch_to_serve_ready)); return; } if (prefetch_container->ShouldBlockUntilHeadReceived()) { + prefetch_container->OnGetPrefetchToServe(/*blocked_until_head=*/false); prefetch_container->GetStreamingLoader()->SetOnReceivedHeadCallback( base::BindOnce(&PrefetchService::ReturnPrefetchToServe, weak_method_factory_.GetWeakPtr(), prefetch_container, @@ -1257,6 +1259,7 @@ !prefetch_container->IsPrefetchServable(PrefetchCacheableDuration()) || prefetch_container->HaveDefaultContextCookiesChanged( prefetch_container->GetURL())) { + prefetch_container->OnReturnPrefetchToServe(/*served=*/false); std::move(on_prefetch_to_serve_ready).Run(nullptr); return; } @@ -1265,8 +1268,7 @@ CopyIsolatedCookies(prefetch_container); } - prefetch_container->OnNavigationToPrefetch(); - + prefetch_container->OnReturnPrefetchToServe(/*served=*/true); std::move(on_prefetch_to_serve_ready).Run(prefetch_container); return; }
diff --git a/content/browser/preloading/prefetch/prefetch_streaming_url_loader.cc b/content/browser/preloading/prefetch/prefetch_streaming_url_loader.cc index 4613f37c..1d99c221 100644 --- a/content/browser/preloading/prefetch/prefetch_streaming_url_loader.cc +++ b/content/browser/preloading/prefetch/prefetch_streaming_url_loader.cc
@@ -70,6 +70,31 @@ response_complete_time_.value() + cacheable_duration); } +bool PrefetchStreamingURLLoader::Failed() const { + switch (status_) { + case PrefetchStreamingURLLoaderStatus::kWaitingOnHead: + case PrefetchStreamingURLLoaderStatus::kHeadReceivedWaitingOnBody: + case PrefetchStreamingURLLoaderStatus::kSuccessfulNotServed: + case PrefetchStreamingURLLoaderStatus::kSuccessfulServedAfterCompletion: + case PrefetchStreamingURLLoaderStatus::kSuccessfulServedBeforeCompletion: + case PrefetchStreamingURLLoaderStatus::kPrefetchWasDecoy: + case PrefetchStreamingURLLoaderStatus::kFollowRedirect: + case PrefetchStreamingURLLoaderStatus::kPauseRedirectForEligibilityCheck: + return false; + case PrefetchStreamingURLLoaderStatus::kFailedInvalidHead: + case PrefetchStreamingURLLoaderStatus::kFailedInvalidHeaders: + case PrefetchStreamingURLLoaderStatus::kFailedNon2XX: + case PrefetchStreamingURLLoaderStatus::kFailedMIMENotSupported: + case PrefetchStreamingURLLoaderStatus::kFailedNetError: + case PrefetchStreamingURLLoaderStatus::kFailedNetErrorButServed: + case PrefetchStreamingURLLoaderStatus::kFailedInvalidRedirect: + return true; + case PrefetchStreamingURLLoaderStatus::kRedirected_DEPRECATED: + NOTREACHED(); + return true; + } +} + void PrefetchStreamingURLLoader::DisconnectPrefetchURLLoaderMojo() { prefetch_url_loader_.reset(); prefetch_url_loader_client_receiver_.reset(); @@ -208,9 +233,15 @@ PrefetchStreamingURLLoaderStatus new_status) { DCHECK(redirect_head_); + // If the prefetch_url_loader_ is no longer connected, mark this as failed. + if (!prefetch_url_loader_) { + new_status = PrefetchStreamingURLLoaderStatus::kFailedInvalidRedirect; + } + status_ = new_status; switch (status_) { case PrefetchStreamingURLLoaderStatus::kFollowRedirect: + DCHECK(prefetch_url_loader_); prefetch_url_loader_->FollowRedirect( /*removed_headers=*/std::vector<std::string>(), /*modified_headers=*/net::HttpRequestHeaders(),
diff --git a/content/browser/preloading/prefetch/prefetch_streaming_url_loader.h b/content/browser/preloading/prefetch/prefetch_streaming_url_loader.h index 77eef55..f1c40c8 100644 --- a/content/browser/preloading/prefetch/prefetch_streaming_url_loader.h +++ b/content/browser/preloading/prefetch/prefetch_streaming_url_loader.h
@@ -72,6 +72,7 @@ void SetOnReceivedHeadCallback(base::OnceClosure on_received_head_callback); bool Servable(base::TimeDelta cacheable_duration) const; + bool Failed() const; absl::optional<network::URLLoaderCompletionStatus> GetCompletionStatus() const {
diff --git a/content/browser/preloading/prefetch/prefetch_streaming_url_loader_unittest.cc b/content/browser/preloading/prefetch/prefetch_streaming_url_loader_unittest.cc index e04e6fb..fa9aad3843 100644 --- a/content/browser/preloading/prefetch/prefetch_streaming_url_loader_unittest.cc +++ b/content/browser/preloading/prefetch/prefetch_streaming_url_loader_unittest.cc
@@ -1162,6 +1162,66 @@ PrefetchStreamingURLLoaderStatus::kFailedInvalidRedirect, 1); } +TEST_F(PrefetchStreamingURLLoaderTest, + PausedEligibleRedirect_UrlLoaderDisconnect) { + base::HistogramTester histogram_tester; + const GURL kTestUrl = GURL("https://example.com"); + const std::string kBodyContent = "example body"; + + std::unique_ptr<network::ResourceRequest> prefetch_request = + std::make_unique<network::ResourceRequest>(); + prefetch_request->url = kTestUrl; + prefetch_request->method = "GET"; + + base::RunLoop on_receive_redirect_loop; + + // Create the |PrefetchStreamingURLLoader| that is being tested. + std::unique_ptr<PrefetchStreamingURLLoader> streaming_loader = + std::make_unique<PrefetchStreamingURLLoader>( + test_url_loader_factory(), std::move(prefetch_request), + TRAFFIC_ANNOTATION_FOR_TESTS, /*timeout_duration=*/base::TimeDelta(), + base::BindOnce([](network::mojom::URLResponseHead* head) { + NOTREACHED(); + return PrefetchStreamingURLLoaderStatus::kHeadReceivedWaitingOnBody; + }), + base::BindOnce( + [](const network::URLLoaderCompletionStatus& completion_status) { + NOTREACHED(); + }), + base::BindRepeating( + [](base::RunLoop* on_receive_redirect_loop, + const net::RedirectInfo& redirect_info, + const network::mojom::URLResponseHead& response_head) { + on_receive_redirect_loop->Quit(); + return PrefetchStreamingURLLoaderStatus:: + kPauseRedirectForEligibilityCheck; + }, + &on_receive_redirect_loop)); + + // Simulate a redirect that should be followed by the URL loader. The URL + // loader needs to pause until the eligibility check is complete. + test_url_loader_factory()->SimulateRedirect(GURL("https://redirect.com"), + net::HTTP_PERMANENT_REDIRECT); + on_receive_redirect_loop.Run(); + + // Simulate the network URL loader stopping before the result of the + // eligibility check is done. + test_url_loader_factory()->DisconnectMojoPipes(); + task_environment()->RunUntilIdle(); + + streaming_loader->OnEligibilityCheckForRedirectComplete(/*is_eligible=*/true); + + // Since the network URL loader was disconnected, then redirect cannot be + // followed and the prefetch should not be servable. + EXPECT_FALSE(streaming_loader->Servable(base::TimeDelta::Max())); + + streaming_loader.reset(); + + histogram_tester.ExpectUniqueSample( + "PrefetchProxy.Prefetch.StreamingURLLoaderFinalStatus", + PrefetchStreamingURLLoaderStatus::kFailedInvalidRedirect, 1); +} + TEST_F(PrefetchStreamingURLLoaderTest, Decoy) { base::HistogramTester histogram_tester; const GURL kTestUrl = GURL("https://example.com");
diff --git a/content/browser/private_aggregation/private_aggregation_budgeter.cc b/content/browser/private_aggregation/private_aggregation_budgeter.cc index 3d851c41..073471c 100644 --- a/content/browser/private_aggregation/private_aggregation_budgeter.cc +++ b/content/browser/private_aggregation/private_aggregation_budgeter.cc
@@ -27,6 +27,7 @@ #include "content/browser/private_aggregation/private_aggregation_budget_key.h" #include "content/browser/private_aggregation/private_aggregation_budget_storage.h" #include "content/browser/private_aggregation/proto/private_aggregation_budgets.pb.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/protobuf/src/google/protobuf/repeated_field.h" #include "url/gurl.h" @@ -81,7 +82,8 @@ RecordBudgetValidity(ValidityStatus::kContainsTimestampNotRoundedToHour); return; - } else if (budget > PrivateAggregationBudgeter::kMaxBudgetPerScope) { + } else if (budget > + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get()) { RecordBudgetValidity(ValidityStatus::kContainsValueExceedingLimit); return; @@ -236,6 +238,9 @@ int additional_budget, const PrivateAggregationBudgetKey& budget_key, base::OnceCallback<void(RequestResult)> on_done) { + const int kMaxBudgetPerScope = + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(); + switch (storage_status_) { case StorageStatus::kInitializing: NOTREACHED();
diff --git a/content/browser/private_aggregation/private_aggregation_budgeter.h b/content/browser/private_aggregation/private_aggregation_budgeter.h index bec2e2e9f..93c660bc 100644 --- a/content/browser/private_aggregation/private_aggregation_budgeter.h +++ b/content/browser/private_aggregation/private_aggregation_budgeter.h
@@ -73,9 +73,6 @@ kMaxValue = kContainsNonPositiveValue, }; - // Maximum budget allowed to be claimed per-origin per-day per-API. - static constexpr int kMaxBudgetPerScope = 65536; - // To avoid unbounded memory growth, limit the number of pending calls during // initialization. Data clearing calls can be posted even if it would exceed // this limit.
diff --git a/content/browser/private_aggregation/private_aggregation_budgeter_unittest.cc b/content/browser/private_aggregation/private_aggregation_budgeter_unittest.cc index 5646c518..a997f1a 100644 --- a/content/browser/private_aggregation/private_aggregation_budgeter_unittest.cc +++ b/content/browser/private_aggregation/private_aggregation_budgeter_unittest.cc
@@ -24,6 +24,7 @@ #include "base/task/updateable_sequenced_task_runner.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" #include "content/browser/private_aggregation/private_aggregation_budget_key.h" @@ -31,6 +32,7 @@ #include "content/browser/private_aggregation/proto/private_aggregation_budgets.pb.h" #include "content/browser/storage_partition_impl.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/storage_key/storage_key.h" #include "third_party/protobuf/src/google/protobuf/repeated_ptr_field.h" #include "url/gurl.h" @@ -245,13 +247,14 @@ url::Origin::Create(GURL("https://a.example/")), base::Time::FromJavaTime(1652984901234), PrivateAggregationBudgetKey::Api::kFledge); - budgeter()->ConsumeBudget(PrivateAggregationBudgeter::kMaxBudgetPerScope, - example_key, - base::BindLambdaForTesting( - [&num_queries_processed](RequestResult result) { - EXPECT_EQ(result, RequestResult::kApproved); - ++num_queries_processed; - })); + budgeter()->ConsumeBudget( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, + base::BindLambdaForTesting( + [&num_queries_processed](RequestResult result) { + EXPECT_EQ(result, RequestResult::kApproved); + ++num_queries_processed; + })); // Ensure database has a chance to persist storage. EnsureDbFlushes(); @@ -282,13 +285,14 @@ url::Origin::Create(GURL("https://a.example/")), base::Time::FromJavaTime(1652984901234), PrivateAggregationBudgetKey::Api::kFledge); - budgeter()->ConsumeBudget(PrivateAggregationBudgeter::kMaxBudgetPerScope, - example_key, - base::BindLambdaForTesting( - [&num_queries_processed](RequestResult result) { - EXPECT_EQ(result, RequestResult::kApproved); - ++num_queries_processed; - })); + budgeter()->ConsumeBudget( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, + base::BindLambdaForTesting( + [&num_queries_processed](RequestResult result) { + EXPECT_EQ(result, RequestResult::kApproved); + ++num_queries_processed; + })); // Ensure database has a chance to persist storage. EnsureDbFlushes(); @@ -330,7 +334,8 @@ // Budget can be increased to max budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope - 1), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 1), example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { @@ -372,9 +377,9 @@ // Consuming this budget 24 times in a day would not exceed the daily budget, // but 25 times would. int budget_to_use_per_hour = - PrivateAggregationBudgeter::kMaxBudgetPerScope / 24; + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() / 24; EXPECT_GT(budget_to_use_per_hour * 25, - PrivateAggregationBudgeter::kMaxBudgetPerScope); + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get()); // Use budget in the first 24 keys. for (int i = 0; i < 24; ++i) { @@ -431,7 +436,8 @@ PrivateAggregationBudgetKey::Api::kSharedStorage); budgeter()->ConsumeBudget( - PrivateAggregationBudgeter::kMaxBudgetPerScope, fledge_key, + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + fledge_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult request) { EXPECT_EQ(request, RequestResult::kApproved); @@ -442,7 +448,8 @@ // The budget for one API does not interfere with the other. budgeter()->ConsumeBudget( - PrivateAggregationBudgeter::kMaxBudgetPerScope, shared_storage_key, + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + shared_storage_key, base::BindLambdaForTesting([&](RequestResult request) { EXPECT_EQ(request, RequestResult::kApproved); ++num_queries_processed; @@ -469,18 +476,18 @@ base::Time::FromJavaTime(1652984901234), PrivateAggregationBudgetKey::Api::kFledge); - budgeter()->ConsumeBudget(PrivateAggregationBudgeter::kMaxBudgetPerScope, - key_a, - base::BindLambdaForTesting( - [&num_queries_processed](RequestResult result) { - EXPECT_EQ(result, RequestResult::kApproved); - ++num_queries_processed; - })); + budgeter()->ConsumeBudget( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), key_a, + base::BindLambdaForTesting( + [&num_queries_processed](RequestResult result) { + EXPECT_EQ(result, RequestResult::kApproved); + ++num_queries_processed; + })); base::RunLoop run_loop; // The budget for one origin does not interfere with the other. budgeter()->ConsumeBudget( - PrivateAggregationBudgeter::kMaxBudgetPerScope, key_b, + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), key_b, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; @@ -521,7 +528,8 @@ // Request will be rejected if budget exceeds maximum budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope + 1), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() + 1), example_key, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kRequestedMoreThanTotalBudget); ++num_queries_processed; @@ -552,7 +560,8 @@ int64_t after_latest_window_start = latest_window_start + window_duration; int64_t before_oldest_window_start = oldest_window_start - window_duration; - constexpr int max_budget = PrivateAggregationBudgeter::kMaxBudgetPerScope; + const int max_budget = + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(); struct HourlyBudget { int budget; @@ -645,7 +654,8 @@ EXPECT_EQ(++num_queries_processed, 1); })); budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope - 1), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 1), example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { @@ -697,7 +707,8 @@ EXPECT_EQ(++num_queries_processed, 1); })); budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope - 1), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 1), example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { @@ -848,7 +859,8 @@ PrivateAggregationBudgetKey::Api::kFledge); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); @@ -876,8 +888,8 @@ // After clearing, we can use the full budget again budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, - base::BindLambdaForTesting([&](RequestResult result) { + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; })); @@ -913,7 +925,8 @@ })); budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope - 1), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 1), example_key_2, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { @@ -945,8 +958,8 @@ // After clearing, we can use the full budget again. budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_2, - base::BindLambdaForTesting([&](RequestResult result) { + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_2, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; })); @@ -994,7 +1007,8 @@ /*budget=*/1, key_before, expect_approved); budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope - 2), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 2), key_to_clear, expect_approved); budgeter()->ConsumeBudget( @@ -1022,9 +1036,11 @@ })); // After clearing, we can have a budget of exactly - // (`PrivateAggregationBudgeter::kMaxBudgetPerScope` - 2) that we can use. + // (`blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get()` - 2) that + // we can use. budgeter()->ConsumeBudget( - /*budget=*/(PrivateAggregationBudgeter::kMaxBudgetPerScope - 2), + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 2), key_after, expect_approved); budgeter()->ConsumeBudget( @@ -1066,15 +1082,15 @@ }); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, fledge_key, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + fledge_key, expect_approved); // Maximum budget has been used so this should fail. budgeter()->ConsumeBudget( /*budget=*/1, fledge_key, expect_insufficient_budget); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), shared_storage_key, expect_approved); // Maximum budget has been used so this should fail. @@ -1093,11 +1109,11 @@ // After clearing, we can use the full budget again budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, fledge_key, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + fledge_key, expect_approved); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), shared_storage_key, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; @@ -1117,7 +1133,8 @@ PrivateAggregationBudgetKey::Api::kFledge); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); @@ -1145,8 +1162,8 @@ // After clearing, we can use the full budget again budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, - base::BindLambdaForTesting([&](RequestResult result) { + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; })); @@ -1165,7 +1182,8 @@ PrivateAggregationBudgetKey::Api::kFledge); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); @@ -1193,8 +1211,8 @@ // After clearing, we can use the full budget again budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, - base::BindLambdaForTesting([&](RequestResult result) { + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; })); @@ -1213,7 +1231,8 @@ PrivateAggregationBudgetKey::Api::kFledge); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); @@ -1241,8 +1260,8 @@ // After clearing, we can use the full budget again budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, - base::BindLambdaForTesting([&](RequestResult result) { + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting([&](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); ++num_queries_processed; })); @@ -1280,16 +1299,16 @@ }); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_a, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_a, expect_approved); // Maximum budget has been used so this should fail. budgeter()->ConsumeBudget( /*budget=*/1, example_key_a, expect_insufficient_budget); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_b, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_b, expect_approved); // Maximum budget has been used so this should fail. budgeter()->ConsumeBudget( @@ -1310,11 +1329,11 @@ // After clearing, we can use the full budget again for the cleared origin. budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_a, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_a, expect_approved); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_b, - expect_insufficient_budget); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_b, expect_insufficient_budget); run_loop.Run(); EXPECT_EQ(num_queries_processed, 7); } @@ -1349,16 +1368,16 @@ }); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_a, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_a, expect_approved); // Maximum budget has been used so this should fail. budgeter()->ConsumeBudget( /*budget=*/1, example_key_a, expect_insufficient_budget); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_b, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_b, expect_approved); // Maximum budget has been used so this should fail. budgeter()->ConsumeBudget( @@ -1379,12 +1398,12 @@ // After clearing, we can use the full budget again for the cleared origin. budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_a, - expect_approved); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_a, expect_approved); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key_b, - expect_insufficient_budget); + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key_b, expect_insufficient_budget); run_loop.Run(); EXPECT_EQ(num_queries_processed, 7); } @@ -1401,7 +1420,8 @@ PrivateAggregationBudgetKey::Api::kFledge); budgeter()->ConsumeBudget( - /*budget=*/PrivateAggregationBudgeter::kMaxBudgetPerScope, example_key, + /*budget=*/blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get(), + example_key, base::BindLambdaForTesting( [&num_queries_processed](RequestResult result) { EXPECT_EQ(result, RequestResult::kApproved); @@ -1422,6 +1442,58 @@ EXPECT_EQ(num_queries_processed, 2); } +TEST_F(PrivateAggregationBudgeterTest, DifferentMaxScope_StillFunctions) { + for (const std::string& max_budget_param : {"10", "16777216"}) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + blink::features::kPrivateAggregationApi, + {{"max_budget_per_scope", max_budget_param}}); + + int num_queries_processed = 0; + + CreateBudgeterAndWait(); + + PrivateAggregationBudgetKey example_key = + PrivateAggregationBudgetKey::CreateForTesting( + url::Origin::Create(GURL("https://a.example/")), + base::Time::FromJavaTime(1652984901234), + PrivateAggregationBudgetKey::Api::kFledge); + + // Budget can be increased to below max + budgeter()->ConsumeBudget( + /*budget=*/1, example_key, + base::BindLambdaForTesting( + [&num_queries_processed](RequestResult result) { + EXPECT_EQ(result, RequestResult::kApproved); + ++num_queries_processed; + })); + + // Budget can be increased to max + budgeter()->ConsumeBudget( + /*budget=*/( + blink::features::kPrivateAggregationApiMaxBudgetPerScope.Get() - 1), + example_key, + base::BindLambdaForTesting( + [&num_queries_processed](RequestResult result) { + EXPECT_EQ(result, RequestResult::kApproved); + ++num_queries_processed; + })); + + base::RunLoop run_loop; + + // Budget cannot be increased above max + budgeter()->ConsumeBudget( + /*budget=*/1, example_key, + base::BindLambdaForTesting([&](RequestResult result) { + EXPECT_EQ(result, RequestResult::kInsufficientBudget); + ++num_queries_processed; + run_loop.Quit(); + })); + run_loop.Run(); + EXPECT_EQ(num_queries_processed, 3); + } +} + } // namespace } // namespace content
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index ea2dc4a..09e2e34 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -1138,7 +1138,7 @@ base::TimeTicks() /* renderer_before_unload_start */, base::TimeTicks() /* renderer_before_unload_end */, std::move(web_bundle_token_params), initiator_activation_and_ad_status, - is_container_initiated); + is_container_initiated, false /* is_fullscreen_requested */); // Shift-Reload forces bypassing caches and service workers. if (common_params->navigation_type ==
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index c3d3fd5..246c29c 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -223,6 +223,7 @@ #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/common/chrome_debug_urls.h" #include "third_party/blink/public/common/features.h" +#include "third_party/blink/public/common/features_generated.h" #include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h" #include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h" #include "third_party/blink/public/common/frame/frame_owner_element_type.h" @@ -251,6 +252,7 @@ #include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h" #include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h" #include "third_party/blink/public/mojom/opengraph/metadata.mojom.h" +#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h" #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h" #include "third_party/blink/public/mojom/storage_key/ancestor_chain_bit.mojom.h" @@ -6287,6 +6289,17 @@ delegate_->PrimaryMainDocumentElementAvailable(); + if (base::FeatureList::IsEnabled(blink::features::kFullscreenPopupWindows) && + fullscreen_document_on_document_element_ready_ && + (*fullscreen_document_on_document_element_ready_) == GetDocumentToken()) { + fullscreen_document_on_document_element_ready_ = absl::nullopt; + // Create a fullscreen request token to waive the user activation + // requirement when the request is received back to the browser in + // `EnterFullscreen`. + fullscreen_request_token_.Activate(); + GetAssociatedLocalFrame()->RequestFullscreenDocumentElement(); + } + if (!uses_temporary_zoom_level) return; @@ -8405,6 +8418,34 @@ return; } + if (begin_params->is_fullscreen_requested) { + // Fullscreen requests on navigation are only allowed from initial empty + // documents that are the outermost main frame. The initiator must also have + // window management granted, otherwise the fullscreen bit is dropped. + if (!is_initial_empty_document()) { + bad_message::ReceivedBadMessage( + GetProcess(), + bad_message::RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT); + return; + } + if (!IsOutermostMainFrame()) { + bad_message::ReceivedBadMessage( + GetProcess(), + bad_message::RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME); + return; + } + RenderFrameHostImpl* initiator_render_frame_host = + begin_params->initiator_frame_token + ? RenderFrameHostImpl::FromFrameToken( + initiator_process_id, + begin_params->initiator_frame_token.value()) + : nullptr; + if (!initiator_render_frame_host || + !IsWindowManagementGranted(initiator_render_frame_host)) { + begin_params->is_fullscreen_requested = false; + } + } + GetProcess()->FilterURL(true, &begin_params->searchable_form_url); // If the request was for a blob URL, but the validated URL is no longer a @@ -12627,6 +12668,19 @@ early_hints_manager_ = navigation_request->TakeEarlyHintsManager(); + // If fullscreen was requested on the navigation, then set a signal to trigger + // a fullscreen request when the document element is ready. If a previous + // navigation was committed without a call to `MainDocumentElementAvailable` + // before the current navigation then this value is overwritten by the current + // navigation. + fullscreen_document_on_document_element_ready_.reset(); + if (navigation_request->begin_params().is_fullscreen_requested) { + fullscreen_document_on_document_element_ready_ = + navigation_request->GetDocumentToken(); + } + CHECK(!fullscreen_document_on_document_element_ready_ || + IsOutermostMainFrame()); + // Only take some properties if this is not the synchronous initial // `about:blank` navigation, because the values set at construction time // should remain unmodified.
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h index 24bd1304..1f798b5 100644 --- a/content/browser/renderer_host/render_frame_host_impl.h +++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -4982,6 +4982,14 @@ // `cookie_change_listener_` in `NavigationRequest`. std::unique_ptr<CookieChangeListener> cookie_change_listener_; + // Contains a document token to fullscreen when the document element is ready. + // Set when a committed navigation requested fullscreen (e.g. Fullscreen popup + // window) and triggers a fullscreen on the document element once it is ready + // (`MainDocumentElementAvailable` dispatched). + // See: https://chromestatus.com/feature/6002307972464640 + absl::optional<blink::DocumentToken> + fullscreen_document_on_document_element_ready_ = absl::nullopt; + // WeakPtrFactories are the last members, to ensure they are destroyed before // all other fields of `this`. base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_{this};
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc index 17b9ff4d..eca3652 100644 --- a/content/browser/security_exploit_browsertest.cc +++ b/content/browser/security_exploit_browsertest.cc
@@ -1541,7 +1541,8 @@ absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation, - false /* is_container_initiated */); + false /* is_container_initiated */, + false /* is_fullscreen_requested */); // Receiving the invalid IPC message should lead to renderer process // termination. @@ -1575,6 +1576,39 @@ EXPECT_TRUE(result.empty()); } +// Test to verify that an exploited renderer process trying to specify a +// a fullscreen request should not work from a non-initially-empty document. +IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest, + FullscreenRequestMustBeFromEmptyDocument) { + GURL start_url(embedded_test_server()->GetURL("/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), start_url)); + + RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>( + shell()->web_contents()->GetPrimaryMainFrame()); + + // Setup a BeginNavigate IPC with is_fullscreen_requested set to true. + blink::mojom::CommonNavigationParamsPtr common_params = + blink::mojom::CommonNavigationParams::New(); + common_params->url = GetTestUrl("", "simple_page.html"), + common_params->initiator_origin = url::Origin::Create(start_url); + blink::mojom::BeginNavigationParamsPtr begin_params = + blink::mojom::BeginNavigationParams::New(); + begin_params->is_fullscreen_requested = true; + + // Receiving the invalid IPC message should lead to renderer process + // termination. + RenderProcessHostBadIpcMessageWaiter process_kill_waiter(rfh->GetProcess()); + + mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client; + auto navigation_client_receiver = + navigation_client.InitWithNewEndpointAndPassReceiver(); + rfh->frame_host_receiver_for_testing().impl()->BeginNavigation( + std::move(common_params), std::move(begin_params), mojo::NullRemote(), + std::move(navigation_client), mojo::NullRemote(), mojo::NullReceiver()); + EXPECT_EQ(bad_message::RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT, + process_kill_waiter.Wait()); +} + // Tests what happens when a web renderer asks to begin navigating to a file // url. IN_PROC_BROWSER_TEST_F(SecurityExploitViaDisabledWebSecurityTest,
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc index 8df6a58..ff94579 100644 --- a/content/browser/tracing/background_tracing_manager_impl.cc +++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -12,6 +12,7 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/location.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/task/single_thread_task_runner.h" @@ -19,7 +20,6 @@ #include "base/values.h" #include "build/build_config.h" #include "components/tracing/common/trace_startup_config.h" -#include "components/variations/variations_associated_data.h" #include "content/browser/tracing/background_startup_tracing_observer.h" #include "content/browser/tracing/background_tracing_active_scenario.h" #include "content/browser/tracing/background_tracing_agent_client_impl.h" @@ -313,7 +313,7 @@ BackgroundTracingManagerImpl::GetBackgroundTracingConfig( const std::string& trial_name) { std::string config_text = - variations::GetVariationParamValue(trial_name, kBackgroundTracingConfig); + base::GetFieldTrialParamValue(trial_name, kBackgroundTracingConfig); if (config_text.empty()) return nullptr;
diff --git a/content/browser/utility_sandbox_delegate.cc b/content/browser/utility_sandbox_delegate.cc index 68db1862..5a8f79c 100644 --- a/content/browser/utility_sandbox_delegate.cc +++ b/content/browser/utility_sandbox_delegate.cc
@@ -113,6 +113,14 @@ if (sandbox::policy::IsUnsandboxedSandboxType(sandbox_type_)) return nullptr; + // TODO(crbug.com/1427280): remove this special case and fork from the zygote. + // For now, browser tests fail when forking the network service from the + // unsandboxed zygote, as the forked process only creates the + // NetworkServiceTestHelper if the process is exec'd. + if (sandbox_type_ == sandbox::mojom::Sandbox::kNetwork) { + return nullptr; + } + // Utility processes which need specialized sandboxes fork from the // unsandboxed zygote and then apply their actual sandboxes in the forked // process upon startup.
diff --git a/content/browser/web_contents/web_contents_observer_browsertest.cc b/content/browser/web_contents/web_contents_observer_browsertest.cc index 86ed03b8..f75c568f 100644 --- a/content/browser/web_contents/web_contents_observer_browsertest.cc +++ b/content/browser/web_contents/web_contents_observer_browsertest.cc
@@ -487,8 +487,8 @@ cookie_tracker.cookie_accesses().clear(); } -// TODO(https://crbug.com/1288573): Flaky on Mac. -#if BUILDFLAG(IS_MAC) +// TODO(https://crbug.com/1288573): Flaky on Mac and Android. +#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_ANDROID) #define MAYBE_CookieCallbacks_Subframe DISABLED_CookieCallbacks_Subframe #else #define MAYBE_CookieCallbacks_Subframe CookieCallbacks_Subframe
diff --git a/content/browser/webid/fake_identity_request_dialog_controller.cc b/content/browser/webid/fake_identity_request_dialog_controller.cc index 221133c..f7766d6 100644 --- a/content/browser/webid/fake_identity_request_dialog_controller.cc +++ b/content/browser/webid/fake_identity_request_dialog_controller.cc
@@ -4,6 +4,8 @@ #include "content/browser/webid/fake_identity_request_dialog_controller.h" +#include "third_party/blink/public/mojom/webid/federated_auth_request.mojom.h" + namespace content { FakeIdentityRequestDialogController::FakeIdentityRequestDialogController( @@ -26,7 +28,26 @@ // support multiple IDPs. std::vector<IdentityRequestAccount> accounts = identity_provider_data[0].accounts; - DCHECK_GT(accounts.size(), 0ul); + CHECK_GT(accounts.size(), 0ul); + CHECK_GT(identity_provider_data.size(), 0ul); + + // We're faking this so that browser automation and tests can verify that + // the RP context was read properly. + switch (identity_provider_data[0].rp_context) { + case blink::mojom::RpContext::kSignIn: + title_ = "Sign in"; + break; + case blink::mojom::RpContext::kSignUp: + title_ = "Sign up"; + break; + case blink::mojom::RpContext::kUse: + title_ = "Use"; + break; + case blink::mojom::RpContext::kContinue: + title_ = "Continue"; + break; + }; + if (is_interception_enabled_) { // Browser automation will handle selecting an account/canceling. return; @@ -38,4 +59,8 @@ /* is_sign_in= */ true); } +std::string FakeIdentityRequestDialogController::GetTitle() const { + return title_; +} + } // namespace content
diff --git a/content/browser/webid/fake_identity_request_dialog_controller.h b/content/browser/webid/fake_identity_request_dialog_controller.h index 9ccb6ff..dde6e47 100644 --- a/content/browser/webid/fake_identity_request_dialog_controller.h +++ b/content/browser/webid/fake_identity_request_dialog_controller.h
@@ -32,8 +32,11 @@ AccountSelectionCallback on_selected, DismissCallback dismmiss_callback) override; + std::string GetTitle() const override; + private: absl::optional<std::string> selected_account_; + std::string title_; }; } // namespace content
diff --git a/content/public/browser/identity_request_dialog_controller.cc b/content/public/browser/identity_request_dialog_controller.cc index 1d1e4724..b5c5dee 100644 --- a/content/public/browser/identity_request_dialog_controller.cc +++ b/content/public/browser/identity_request_dialog_controller.cc
@@ -7,6 +7,7 @@ #include <memory> #include "content/public/browser/web_contents.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace content { @@ -75,6 +76,15 @@ } } +std::string IdentityRequestDialogController::GetTitle() const { + return std::string(); +} + +absl::optional<std::string> IdentityRequestDialogController::GetSubtitle() + const { + return absl::nullopt; +} + void IdentityRequestDialogController::ShowIdpSigninFailureDialog( base::OnceClosure dismiss_callback) { if (!is_interception_enabled_) {
diff --git a/content/public/browser/identity_request_dialog_controller.h b/content/public/browser/identity_request_dialog_controller.h index dfb6ecba..8a77a34 100644 --- a/content/public/browser/identity_request_dialog_controller.h +++ b/content/public/browser/identity_request_dialog_controller.h
@@ -125,6 +125,10 @@ const IdentityProviderMetadata& idp_metadata, DismissCallback dismiss_callback); + // Only to be called after a dialog is shown. + virtual std::string GetTitle() const; + virtual absl::optional<std::string> GetSubtitle() const; + // Show dialog notifying user that IdP sign-in failed. virtual void ShowIdpSigninFailureDialog(base::OnceClosure dismiss_callback);
diff --git a/content/public/renderer/window_features_converter.cc b/content/public/renderer/window_features_converter.cc index 331f60e3..f80e71e 100644 --- a/content/public/renderer/window_features_converter.cc +++ b/content/public/renderer/window_features_converter.cc
@@ -24,6 +24,7 @@ result->bounds.set_height(web_window_features.height); result->has_height = web_window_features.height_set; result->is_popup = web_window_features.is_popup; + result->is_fullscreen = web_window_features.is_fullscreen; return result; } @@ -39,6 +40,7 @@ result.height = window_features.bounds.height(); result.height_set = window_features.has_height; result.is_popup = window_features.is_popup; + result.is_fullscreen = window_features.is_fullscreen; return result; }
diff --git a/content/public/test/fake_local_frame.cc b/content/public/test/fake_local_frame.cc index f648ddf..f74d5074 100644 --- a/content/public/test/fake_local_frame.cc +++ b/content/public/test/fake_local_frame.cc
@@ -211,6 +211,8 @@ const std::string& normalized_server_timing, const ::network::URLLoaderCompletionStatus& completion_status) {} +void FakeLocalFrame::RequestFullscreenDocumentElement() {} + void FakeLocalFrame::BindFrameHostReceiver( mojo::ScopedInterfaceEndpointHandle handle) { receiver_.Bind(mojo::PendingAssociatedReceiver<blink::mojom::LocalFrame>(
diff --git a/content/public/test/fake_local_frame.h b/content/public/test/fake_local_frame.h index 8930e12..becdf02 100644 --- a/content/public/test/fake_local_frame.h +++ b/content/public/test/fake_local_frame.h
@@ -162,6 +162,7 @@ bool is_validated, const std::string& normalized_server_timing, const ::network::URLLoaderCompletionStatus& completion_status) override; + void RequestFullscreenDocumentElement() override; private: void BindFrameHostReceiver(mojo::ScopedInterfaceEndpointHandle handle);
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 77a944d5..b0ec203b 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -5779,7 +5779,8 @@ : nullptr, info->impression, renderer_before_unload_start, renderer_before_unload_end, web_bundle_token_params, - initiator_activation_and_ad_status, info->is_container_initiated); + initiator_activation_and_ad_status, info->is_container_initiated, + info->is_fullscreen_requested); mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client_remote;
diff --git a/content/test/navigation_simulator_impl.cc b/content/test/navigation_simulator_impl.cc index 002f817..5816a543 100644 --- a/content/test/navigation_simulator_impl.cc +++ b/content/test/navigation_simulator_impl.cc
@@ -1335,7 +1335,8 @@ kStartedWithTransientActivationFromNonAd : blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation, - false /* is_container_initiated */); + false /* is_container_initiated */, + false /* is_fullscreen_requested */); auto common_params = blink::CreateCommonNavigationParams(); common_params->navigation_start = base::TimeTicks::Now(); common_params->input_start = navigation_input_start_;
diff --git a/content/test/test_render_frame_host.cc b/content/test/test_render_frame_host.cc index afde979..86ab9b4 100644 --- a/content/test/test_render_frame_host.cc +++ b/content/test/test_render_frame_host.cc
@@ -426,7 +426,8 @@ absl::nullopt /* web_bundle_token */, blink::mojom::NavigationInitiatorActivationAndAdStatus:: kDidNotStartWithTransientActivation, - false /* is_container_initiated */); + false /* is_container_initiated */, + false /* is_fullscreen_requested */); auto common_params = blink::CreateCommonNavigationParams(); common_params->url = url; common_params->initiator_origin = GetLastCommittedOrigin();
diff --git a/device/bluetooth/chromeos/bluetooth_utils.cc b/device/bluetooth/chromeos/bluetooth_utils.cc index 96435aa..0c782f1a 100644 --- a/device/bluetooth/chromeos/bluetooth_utils.cc +++ b/device/bluetooth/chromeos/bluetooth_utils.cc
@@ -149,6 +149,44 @@ } } +void EmitFilteredFailureReason(ConnectionFailureReason failure_reason, + const std::string& transport_name) { + switch (failure_reason) { + case ConnectionFailureReason::kAuthCanceled: + [[fallthrough]]; + case ConnectionFailureReason::kAuthRejected: + return; + case ConnectionFailureReason::kUnknownError: + [[fallthrough]]; + case ConnectionFailureReason::kAuthFailed: + [[fallthrough]]; + case ConnectionFailureReason::kAuthTimeout: + [[fallthrough]]; + case ConnectionFailureReason::kUnknownConnectionError: + [[fallthrough]]; + case ConnectionFailureReason::kUnsupportedDevice: + [[fallthrough]]; + case ConnectionFailureReason::kNotConnectable: + [[fallthrough]]; + case ConnectionFailureReason::kSystemError: + [[fallthrough]]; + case ConnectionFailureReason::kFailed: + [[fallthrough]]; + case ConnectionFailureReason::kInprogress: + const std::string result_histogram_name_prefix = + "Bluetooth.ChromeOS.Pairing.Result"; + base::UmaHistogramEnumeration( + result_histogram_name_prefix + ".FilteredFailureReason", + failure_reason); + base::UmaHistogramEnumeration(result_histogram_name_prefix + + ".FilteredFailureReason." + + transport_name, + failure_reason); + return; + } + NOTREACHED(); +} + #if BUILDFLAG(IS_CHROMEOS_ASH) bool IsPolyDevice(const device::BluetoothDevice* device) { // OUI portions of Bluetooth addresses for devices manufactured by Poly. See @@ -286,6 +324,7 @@ base::UmaHistogramEnumeration( result_histogram_name_prefix + ".FailureReason." + transport_name, *failure_reason); + EmitFilteredFailureReason(*failure_reason, transport_name); } }
diff --git a/device/bluetooth/chromeos/bluetooth_utils_unittest.cc b/device/bluetooth/chromeos/bluetooth_utils_unittest.cc index 4a9b7887..e1122b23 100644 --- a/device/bluetooth/chromeos/bluetooth_utils_unittest.cc +++ b/device/bluetooth/chromeos/bluetooth_utils_unittest.cc
@@ -328,29 +328,49 @@ failure_reason, 1); }; + auto assert_filtered_failure_histograms = + [&](device::ConnectionFailureReason error, size_t expected_count) { + histogram_tester.ExpectBucketCount( + "Bluetooth.ChromeOS.Pairing.Result.FilteredFailureReason", error, + expected_count); + histogram_tester.ExpectBucketCount( + "Bluetooth.ChromeOS.Pairing.Result.FilteredFailureReason.Classic", + error, expected_count); + }; + RecordPairingResult(device::ConnectionFailureReason::kAuthFailed, device::BluetoothTransport::BLUETOOTH_TRANSPORT_CLASSIC, base::Seconds(2)); total_count++; assert_histograms(device::ConnectionFailureReason::kAuthFailed); + assert_filtered_failure_histograms( + device::ConnectionFailureReason::kAuthFailed, /*expected_count=*/1); RecordPairingResult(device::ConnectionFailureReason::kAuthCanceled, device::BluetoothTransport::BLUETOOTH_TRANSPORT_CLASSIC, base::Seconds(2)); total_count++; assert_histograms(device::ConnectionFailureReason::kAuthCanceled); + assert_filtered_failure_histograms( + device::ConnectionFailureReason::kAuthCanceled, + /*expected_count=*/0); RecordPairingResult(device::ConnectionFailureReason::kAuthRejected, device::BluetoothTransport::BLUETOOTH_TRANSPORT_CLASSIC, base::Seconds(2)); total_count++; assert_histograms(device::ConnectionFailureReason::kAuthRejected); + assert_filtered_failure_histograms( + device::ConnectionFailureReason::kAuthRejected, + /*expected_count=*/0); RecordPairingResult(device::ConnectionFailureReason::kInprogress, device::BluetoothTransport::BLUETOOTH_TRANSPORT_CLASSIC, base::Seconds(2)); total_count++; assert_histograms(device::ConnectionFailureReason::kInprogress); + assert_filtered_failure_histograms( + device::ConnectionFailureReason::kInprogress, /*expected_count=*/1); } TEST_F(BluetoothUtilsTest, TestUserAttemptedReconnectionMetric) {
diff --git a/device/bluetooth/floss/bluetooth_adapter_floss.cc b/device/bluetooth/floss/bluetooth_adapter_floss.cc index fe27749..69df1a3b 100644 --- a/device/bluetooth/floss/bluetooth_adapter_floss.cc +++ b/device/bluetooth/floss/bluetooth_adapter_floss.cc
@@ -793,7 +793,10 @@ BluetoothPairingFloss* pairing = device->pairing(); if (!pairing) { - LOG(WARNING) << "SSP request for an unknown pairing"; + // For incoming bonding, reject it right away to avoid users try to pair + // with it while the remote is waiting reply. + FlossDBusManager::Get()->GetAdapterClient()->SetPairingConfirmation( + base::DoNothing(), remote_device, /*accept=*/false); return; }
diff --git a/extensions/browser/api/messaging/extension_message_port.cc b/extensions/browser/api/messaging/extension_message_port.cc index a1f35b4..d308f51 100644 --- a/extensions/browser/api/messaging/extension_message_port.cc +++ b/extensions/browser/api/messaging/extension_message_port.cc
@@ -318,8 +318,7 @@ base::Unretained(this), message)); } -void ExtensionMessagePort::IncrementLazyKeepaliveCount( - bool should_have_strong_keepalive) { +void ExtensionMessagePort::IncrementLazyKeepaliveCount() { ProcessManager* pm = ProcessManager::Get(browser_context_); ExtensionHost* host = pm->GetBackgroundHostForExtension(extension_id_); if (host && BackgroundInfo::HasLazyBackgroundPage(host->extension())) { @@ -335,7 +334,7 @@ pm->GetServiceWorkersForExtension(extension_id_)) { std::string request_uuid = pm->IncrementServiceWorkerKeepaliveCount( worker_id, - should_have_strong_keepalive + should_have_strong_keepalive() ? content::ServiceWorkerExternalRequestTimeoutType::kDoesNotTimeout : content::ServiceWorkerExternalRequestTimeoutType::kDefault, Activity::MESSAGE_PORT, PortIdToString(port_id_));
diff --git a/extensions/browser/api/messaging/extension_message_port.h b/extensions/browser/api/messaging/extension_message_port.h index da34e6b..4879903 100644 --- a/extensions/browser/api/messaging/extension_message_port.h +++ b/extensions/browser/api/messaging/extension_message_port.h
@@ -92,7 +92,7 @@ absl::optional<url::Origin> source_origin) override; void DispatchOnDisconnect(const std::string& error_message) override; void DispatchOnMessage(const Message& message) override; - void IncrementLazyKeepaliveCount(bool should_have_strong_keepalive) override; + void IncrementLazyKeepaliveCount() override; void DecrementLazyKeepaliveCount() override; void OpenPort(int process_id, const PortContext& port_context) override; void ClosePort(int process_id, int routing_id, int worker_thread_id) override;
diff --git a/extensions/browser/api/messaging/message_port.cc b/extensions/browser/api/messaging/message_port.cc index 3abb33a..e1273c1 100644 --- a/extensions/browser/api/messaging/message_port.cc +++ b/extensions/browser/api/messaging/message_port.cc
@@ -36,8 +36,7 @@ int routing_id, int worker_thread_id) {} -void MessagePort::IncrementLazyKeepaliveCount( - bool should_have_strong_keepalive) {} +void MessagePort::IncrementLazyKeepaliveCount() {} void MessagePort::DecrementLazyKeepaliveCount() {}
diff --git a/extensions/browser/api/messaging/message_port.h b/extensions/browser/api/messaging/message_port.h index a43d0ff..70d33bc 100644 --- a/extensions/browser/api/messaging/message_port.h +++ b/extensions/browser/api/messaging/message_port.h
@@ -89,15 +89,24 @@ // MessagePorts that target extensions will need to adjust their keepalive // counts for their lazy background page. - virtual void IncrementLazyKeepaliveCount(bool should_have_strong_keepalive); + virtual void IncrementLazyKeepaliveCount(); virtual void DecrementLazyKeepaliveCount(); // Notifies the message port that one of the receivers intents to respond // later. virtual void NotifyResponsePending(); + bool should_have_strong_keepalive() { return should_have_strong_keepalive_; } + void set_should_have_strong_keepalive(bool should_have_strong_keepalive) { + should_have_strong_keepalive_ = should_have_strong_keepalive; + } + protected: MessagePort(); + + private: + // This port should keep the service worker alive while it is open. + bool should_have_strong_keepalive_ = false; }; } // namespace extensions
diff --git a/extensions/browser/api/messaging/message_service.cc b/extensions/browser/api/messaging/message_service.cc index e35c3847..cf74dea7 100644 --- a/extensions/browser/api/messaging/message_service.cc +++ b/extensions/browser/api/messaging/message_service.cc
@@ -514,8 +514,8 @@ channel->receiver = std::move(receiver); // Keep the opener alive until the channel is closed. - channel->opener->IncrementLazyKeepaliveCount( - /* should_have_strong_keepalive= */ true); + channel->opener->set_should_have_strong_keepalive(true); + channel->opener->IncrementLazyKeepaliveCount(); AddChannel(std::move(channel), receiver_port_id); #else // !(BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || @@ -715,29 +715,20 @@ url::Origin target_origin = Extension::CreateOriginFromExtensionId(params->target_extension_id); - bool should_grant_opener_strong_keepalive = false; - bool should_grant_receiver_strong_keepalive = false; - for (const url::Origin& origin : extended_lifetime_origins) { if (origin == source_origin) { // Opener found in allowlist, keep receiver SW alive. - should_grant_receiver_strong_keepalive = true; + channel->receiver->set_should_have_strong_keepalive(true); } if (origin == target_origin) { // Receiver found in allowlist, keep opener SW alive. - should_grant_opener_strong_keepalive = true; + channel->opener->set_should_have_strong_keepalive(true); } } // Keep both ends of the channel alive until the channel is closed. - channel->opener->IncrementLazyKeepaliveCount( - /* should_have_strong_keepalive= */ should_grant_opener_strong_keepalive); - // Note: Though the receiver can be SW for native hosts connecting to it, we - // don't support long lived SW for this particular case yet and specify false - // below. - channel->receiver->IncrementLazyKeepaliveCount( - /* should_have_strong_keepalive= */ - should_grant_receiver_strong_keepalive); + channel->opener->IncrementLazyKeepaliveCount(); + channel->receiver->IncrementLazyKeepaliveCount(); } void MessageService::AddChannel(std::unique_ptr<MessageChannel> channel,
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index 8e85243..bb4d68a46 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -381,7 +381,7 @@ bool force_fallback) const; // Decide if a device feature is exposed to render process. - bool IsFeatureExposed(WGPUFeatureName feature) const; + bool IsFeatureExposed(WGPUAdapter adapter, WGPUFeatureName feature) const; // Dawn wire uses procs which forward their calls to these methods. void RequestAdapterImpl(WGPUInstance instance, @@ -444,6 +444,7 @@ std::vector<std::string> require_disabled_toggles_; bool allow_unsafe_apis_; bool tiered_adapter_limits_; + bool use_dxc_ = false; // Isolation key that is necessary for device requests. Optional to // differentiate between an empty isolation key, and an unset one. @@ -1115,6 +1116,8 @@ tiered_adapter_limits_ = !base::Contains(require_disabled_toggles_, "tiered_adapter_limits"); + use_dxc_ = base::Contains(require_enabled_toggles_, "use_dxc"); + DawnProcTable wire_procs = dawn::native::GetProcs(); wire_procs.createInstance = [](const WGPUInstanceDescriptor*) -> WGPUInstance { @@ -1178,7 +1181,8 @@ return ContextResult::kSuccess; } -bool WebGPUDecoderImpl::IsFeatureExposed(WGPUFeatureName feature) const { +bool WebGPUDecoderImpl::IsFeatureExposed(WGPUAdapter adapter, + WGPUFeatureName feature) const { switch (feature) { case WGPUFeatureName_TimestampQuery: case WGPUFeatureName_TimestampQueryInsidePasses: @@ -1199,6 +1203,18 @@ case WGPUFeatureName_RG11B10UfloatRenderable: case WGPUFeatureName_BGRA8UnormStorage: return true; + case WGPUFeatureName_ShaderF16: { + if (!use_dxc_) { + WGPUAdapterProperties properties{}; + dawn::native::GetProcs().adapterGetProperties(adapter, &properties); + if (properties.backendType == WGPUBackendType_D3D12) { + // On D3D12, shader-f16 requires DXC. Hide it if the use_dxc toggle is + // not enabled. + return false; + } + } + return true; + } default: return false; } @@ -1259,7 +1275,7 @@ if (!dawn::native::GetProcs().adapterHasFeature(adapter, feature)) { return false; } - return IsFeatureExposed(feature); + return IsFeatureExposed(adapter, feature); } size_t WebGPUDecoderImpl::AdapterEnumerateFeaturesImpl( @@ -1270,9 +1286,9 @@ std::vector<WGPUFeatureName> features(count); dawn::native::GetProcs().adapterEnumerateFeatures(adapter, features.data()); - auto it = - std::partition(features.begin(), features.end(), - [&](WGPUFeatureName f) { return IsFeatureExposed(f); }); + auto it = std::partition( + features.begin(), features.end(), + [&](WGPUFeatureName f) { return IsFeatureExposed(adapter, f); }); count = std::distance(features.begin(), it); if (features_out != nullptr) { @@ -1312,7 +1328,7 @@ // Check that no disallowed features were requested. They should be hidden // by AdapterEnumerateFeaturesImpl. for (const WGPUFeatureName& f : required_features) { - if (!IsFeatureExposed(f)) { + if (!IsFeatureExposed(adapter, f)) { callback(WGPURequestDeviceStatus_Error, nullptr, "Disallowed feature requested.", userdata); return;
diff --git a/infra/config/dev/subprojects/chromium/ci.star b/infra/config/dev/subprojects/chromium/ci.star index e8f9e59..5f80a8f 100644 --- a/infra/config/dev/subprojects/chromium/ci.star +++ b/infra/config/dev/subprojects/chromium/ci.star
@@ -93,7 +93,7 @@ ############################################################################### ci_builder( - name = "android-pie-arm64-rel-swarming", + name = "android-pie-arm64-rel-dev", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config( config = "chromium", @@ -115,7 +115,7 @@ ) ci_builder( - name = "linux-rel-swarming", + name = "linux-rel-dev", description_html = "Test description. <b>Test HTML</b>.", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"), @@ -128,7 +128,7 @@ ) ci_builder( - name = "linux-ssd-rel-swarming", + name = "linux-ssd-rel-dev", description_html = "Ensures builders are using available local SSDs", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"), @@ -142,7 +142,7 @@ ) ci_builder( - name = "mac-rel-swarming", + name = "mac-rel-dev", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"), chromium_config = builder_config.chromium_config( @@ -155,7 +155,7 @@ ) ci_builder( - name = "mac-arm-rel-swarming", + name = "mac-arm-rel-dev", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"), chromium_config = builder_config.chromium_config( @@ -169,7 +169,7 @@ ) ci_builder( - name = "win-rel-swarming", + name = "win-rel-dev", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"), chromium_config = builder_config.chromium_config( @@ -182,7 +182,7 @@ ) ci_builder( - name = "win11-rel-swarming", + name = "win11-rel-dev", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"), chromium_config = builder_config.chromium_config(
diff --git a/infra/config/dev/subprojects/chromium/consoles/chromium.swarm.star b/infra/config/dev/subprojects/chromium/consoles/chromium.swarm.star index 0b46753..7e63938d 100644 --- a/infra/config/dev/subprojects/chromium/consoles/chromium.swarm.star +++ b/infra/config/dev/subprojects/chromium/consoles/chromium.swarm.star
@@ -7,12 +7,12 @@ repo = "https://chromium.googlesource.com/chromium/src", header = "//dev/chromium-header.textpb", entries = [ - luci.console_view_entry(builder = "ci/android-pie-arm64-rel-swarming"), - luci.console_view_entry(builder = "ci/linux-rel-swarming"), - luci.console_view_entry(builder = "ci/linux-ssd-rel-swarming"), - luci.console_view_entry(builder = "ci/mac-rel-swarming"), - luci.console_view_entry(builder = "ci/mac-arm-rel-swarming"), - luci.console_view_entry(builder = "ci/win-rel-swarming"), - luci.console_view_entry(builder = "ci/win11-rel-swarming"), + luci.console_view_entry(builder = "ci/android-pie-arm64-rel-dev"), + luci.console_view_entry(builder = "ci/linux-rel-dev"), + luci.console_view_entry(builder = "ci/linux-ssd-rel-dev"), + luci.console_view_entry(builder = "ci/mac-rel-dev"), + luci.console_view_entry(builder = "ci/mac-arm-rel-dev"), + luci.console_view_entry(builder = "ci/win-rel-dev"), + luci.console_view_entry(builder = "ci/win11-rel-dev"), ], )
diff --git a/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/properties.json b/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/properties.json new file mode 100644 index 0000000..e57a1c0 --- /dev/null +++ b/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg-persistent-emulator/properties.json
@@ -0,0 +1,94 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fuchsia.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "fuchsia" + }, + "legacy_gclient_config": { + "apply_configs": [ + "fuchsia_x64" + ], + "config": "chromium" + } + } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg-persistent-emulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fuchsia.fyi", + "execution_mode": "TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "fuchsia" + }, + "legacy_gclient_config": { + "apply_configs": [ + "fuchsia_x64" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg", + "project": "chromium" + }, + "run_tests_serially": true + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg-persistent-emulator", + "project": "chromium" + } + ] + } + }, + "$build/reclient": { + "instance": "rbe-chromium-trusted", + "jobs": 250, + "metrics_project": "chromium-reclient-metrics" + }, + "$recipe_engine/resultdb/test_presentation": { + "column_keys": [], + "grouping_keys": [ + "status", + "v.test_suite" + ] + }, + "builder_group": "chromium.fuchsia.fyi", + "recipe": "chromium", + "sheriff_rotations": [ + "fuchsia" + ] +} \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg/properties.json b/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg/properties.json index 82a9f3e..2605e87 100644 --- a/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg/properties.json +++ b/infra/config/generated/builders/ci/fuchsia-fyi-x64-dbg/properties.json
@@ -29,6 +29,39 @@ "config": "chromium" } } + }, + { + "builder_id": { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg-persistent-emulator", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fuchsia.fyi", + "execution_mode": "TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Debug", + "config": "chromium", + "target_bits": 64, + "target_platform": "fuchsia" + }, + "legacy_gclient_config": { + "apply_configs": [ + "fuchsia_x64" + ], + "config": "chromium" + }, + "parent": { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg", + "project": "chromium" + }, + "run_tests_serially": true + } } ] }, @@ -39,6 +72,13 @@ "project": "chromium" } ], + "builder_ids_in_scope_for_testing": [ + { + "bucket": "ci", + "builder": "fuchsia-fyi-x64-dbg-persistent-emulator", + "project": "chromium" + } + ], "mirroring_builder_group_and_names": [ { "builder": "fuchsia-fyi-x64-dbg",
diff --git a/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json index 02ac44c..d934a03 100644 --- a/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Linux Builder reclient test untrusted/properties.json
@@ -44,7 +44,7 @@ "$build/reclient": { "bootstrap_env": { "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json index 0130029..a33de77 100644 --- a/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Linux Builder reclient test/properties.json
@@ -44,7 +44,7 @@ "$build/reclient": { "bootstrap_env": { "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json index 1e8d04bc..f4bdc36 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient test untrusted/properties.json
@@ -47,7 +47,7 @@ "bootstrap_env": { "GLOG_vmodule": "bridge*=2", "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json index 690aeac..76ddc883 100644 --- a/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Mac Builder reclient test/properties.json
@@ -47,7 +47,7 @@ "bootstrap_env": { "GLOG_vmodule": "bridge*=2", "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json index c5dddb5..5dc470e4 100644 --- a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test untrusted/properties.json
@@ -52,7 +52,7 @@ "$build/reclient": { "bootstrap_env": { "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", - "RBE_compression_threshold": "4000000", + "RBE_compression_threshold": "100000000", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s"
diff --git a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json index 0d55c773d..eea665df 100644 --- a/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Simple Chrome Builder reclient test/properties.json
@@ -52,7 +52,7 @@ "$build/reclient": { "bootstrap_env": { "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", - "RBE_compression_threshold": "4000000", + "RBE_compression_threshold": "100000000", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s"
diff --git a/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json index 33453d1..db00b0b 100644 --- a/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/Win x64 Builder reclient test untrusted/properties.json
@@ -45,7 +45,7 @@ "$build/reclient": { "bootstrap_env": { "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", - "RBE_compression_threshold": "4000000", + "RBE_compression_threshold": "100000000", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s"
diff --git a/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json b/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json index 6e244aab..17a4b25d 100644 --- a/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json +++ b/infra/config/generated/builders/reclient/Win x64 Builder reclient test/properties.json
@@ -45,7 +45,7 @@ "$build/reclient": { "bootstrap_env": { "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "false", - "RBE_compression_threshold": "4000000", + "RBE_compression_threshold": "100000000", "RBE_deps_cache_mode": "reproxy", "RBE_experimental_goma_deps_cache": "True", "RBE_ip_reset_min_delay": "-1s"
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json index 1b6e4d06..a7b82f22 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient test untrusted/properties.json
@@ -47,7 +47,7 @@ "bootstrap_env": { "GLOG_vmodule": "bridge*=2", "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json b/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json index e509680..28e7e34 100644 --- a/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json +++ b/infra/config/generated/builders/reclient/ios-simulator reclient test/properties.json
@@ -47,7 +47,7 @@ "bootstrap_env": { "GLOG_vmodule": "bridge*=2", "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json index ce1ea21..16525bb 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test untrusted/properties.json
@@ -46,7 +46,7 @@ "bootstrap_env": { "GLOG_vmodule": "bridge*=2", "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-untrusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json index b4a02ea0..4daa5f5a1 100644 --- a/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json +++ b/infra/config/generated/builders/reclient/mac-arm64-rel reclient test/properties.json
@@ -46,7 +46,7 @@ "bootstrap_env": { "GLOG_vmodule": "bridge*=2", "GOMA_COMPILER_PROXY_ENABLE_CRASH_DUMP": "true", - "RBE_compression_threshold": "4000000" + "RBE_compression_threshold": "100000000" }, "instance": "rbe-chromium-trusted-test", "metrics_project": "chromium-reclient-metrics",
diff --git a/infra/config/generated/luci/cr-buildbucket-dev.cfg b/infra/config/generated/luci/cr-buildbucket-dev.cfg index 4bf30476..d1f34957 100644 --- a/infra/config/generated/luci/cr-buildbucket-dev.cfg +++ b/infra/config/generated/luci/cr-buildbucket-dev.cfg
@@ -8,7 +8,7 @@ name: "ci" swarming { builders { - name: "android-pie-arm64-rel-swarming" + name: "android-pie-arm64-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" @@ -26,7 +26,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "android-pie-arm64-rel-swarming",' + ' "builder": "android-pie-arm64-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -55,7 +55,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "android-pie-arm64-rel-swarming",' + ' "builder": "android-pie-arm64-rel-dev",' ' "project": "chromium"' ' }' ' ]' @@ -103,7 +103,7 @@ } } builders { - name: "linux-rel-swarming" + name: "linux-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" @@ -121,7 +121,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "linux-rel-swarming",' + ' "builder": "linux-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -144,7 +144,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "linux-rel-swarming",' + ' "builder": "linux-rel-dev",' ' "project": "chromium"' ' }' ' ]' @@ -193,9 +193,9 @@ description_html: "Test description. <b>Test HTML</b>." } builders { - name: "linux-ssd-rel-swarming" + name: "linux-ssd-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" - dimensions: "builder:linux-ssd-rel-swarming" + dimensions: "builder:linux-ssd-rel-dev" dimensions: "cpu:x86-64" dimensions: "os:Ubuntu-18.04" exe { @@ -212,7 +212,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "linux-ssd-rel-swarming",' + ' "builder": "linux-ssd-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -235,7 +235,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "linux-ssd-rel-swarming",' + ' "builder": "linux-ssd-rel-dev",' ' "project": "chromium"' ' }' ' ]' @@ -284,7 +284,7 @@ description_html: "Ensures builders are using available local SSDs" } builders { - name: "mac-arm-rel-swarming" + name: "mac-arm-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" dimensions: "cpu:arm64" dimensions: "os:Mac-12" @@ -302,7 +302,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "mac-arm-rel-swarming",' + ' "builder": "mac-arm-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -325,7 +325,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "mac-arm-rel-swarming",' + ' "builder": "mac-arm-rel-dev",' ' "project": "chromium"' ' }' ' ]' @@ -374,7 +374,7 @@ } } builders { - name: "mac-rel-swarming" + name: "mac-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Mac-12" @@ -392,7 +392,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "mac-rel-swarming",' + ' "builder": "mac-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -415,7 +415,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "mac-rel-swarming",' + ' "builder": "mac-rel-dev",' ' "project": "chromium"' ' }' ' ]' @@ -464,7 +464,7 @@ } } builders { - name: "win-rel-swarming" + name: "win-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Windows-10" @@ -482,7 +482,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "win-rel-swarming",' + ' "builder": "win-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -505,7 +505,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "win-rel-swarming",' + ' "builder": "win-rel-dev",' ' "project": "chromium"' ' }' ' ]' @@ -553,7 +553,7 @@ } } builders { - name: "win11-rel-swarming" + name: "win11-rel-dev" swarming_host: "chromium-swarm-dev.appspot.com" dimensions: "cpu:x86-64" dimensions: "os:Windows-11" @@ -571,7 +571,7 @@ ' {' ' "builder_id": {' ' "bucket": "ci",' - ' "builder": "win11-rel-swarming",' + ' "builder": "win11-rel-dev",' ' "project": "chromium"' ' },' ' "builder_spec": {' @@ -594,7 +594,7 @@ ' "builder_ids": [' ' {' ' "bucket": "ci",' - ' "builder": "win11-rel-swarming",' + ' "builder": "win11-rel-dev",' ' "project": "chromium"' ' }' ' ]'
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 06532f8..4fe6534f 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -30829,6 +30829,93 @@ } } builders { + name: "fuchsia-fyi-x64-dbg-persistent-emulator" + 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/fuchsia-fyi-x64-dbg-persistent-emulator/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.fuchsia.fyi",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium",' + ' "sheriff_rotations": [' + ' "fuchsia"' + ' ]' + '}' + execution_timeout_secs: 36000 + 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: "fuchsia-official" swarming_host: "chromium-swarm.appspot.com" dimensions: "builder:fuchsia-official" @@ -52326,6 +52413,90 @@ } } builders { + name: "Comparison Linux (reclient vs reclient remote links)(compression)" + 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/recipe_bundles/chromium.googlesource.com/chromium/tools/build" + cipd_version: "refs/heads/main" + cmd: "luciexe" + } + properties: + '{' + ' "$build/reclient": {' + ' "bootstrap_env": {' + ' "GOMA_DEPS_CACHE_TABLE_THRESHOLD": "40000",' + ' "RBE_clang_depscan_archive": "true",' + ' "RBE_compression_threshold": "100000000",' + ' "RBE_ip_reset_min_delay": "-1s",' + ' "RBE_use_unified_uploads": "false"' + ' },' + ' "cache_silo": "Comparison Linux remote links - cache siloed",' + ' "instance": "rbe-chromium-trusted-test",' + ' "jobs": 250,' + ' "metrics_project": "chromium-reclient-metrics"' + ' },' + ' "$recipe_engine/resultdb/test_presentation": {' + ' "column_keys": [],' + ' "grouping_keys": [' + ' "status",' + ' "v.test_suite"' + ' ]' + ' },' + ' "builder_group": "chromium.reclient.fyi",' + ' "recipe": "reclient_reclient_comparison"' + '}' + execution_timeout_secs: 21600 + 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: "Comparison Linux (reclient vs reclient remote links)(small)" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1" @@ -52346,7 +52517,6 @@ ' "bootstrap_env": {' ' "GOMA_DEPS_CACHE_TABLE_THRESHOLD": "40000",' ' "RBE_clang_depscan_archive": "true",' - ' "RBE_compression_threshold": "4000000",' ' "RBE_ip_reset_min_delay": "-1s",' ' "RBE_use_unified_uploads": "false"' ' },'
diff --git a/infra/config/generated/luci/luci-milo-dev.cfg b/infra/config/generated/luci/luci-milo-dev.cfg index 229008ea..18568701 100644 --- a/infra/config/generated/luci/luci-milo-dev.cfg +++ b/infra/config/generated/luci/luci-milo-dev.cfg
@@ -11,25 +11,25 @@ refs: "regexp:refs/heads/main" manifest_name: "REVISION" builders { - name: "buildbucket/luci.chromium.ci/android-pie-arm64-rel-swarming" + name: "buildbucket/luci.chromium.ci/android-pie-arm64-rel-dev" } builders { - name: "buildbucket/luci.chromium.ci/linux-rel-swarming" + name: "buildbucket/luci.chromium.ci/linux-rel-dev" } builders { - name: "buildbucket/luci.chromium.ci/linux-ssd-rel-swarming" + name: "buildbucket/luci.chromium.ci/linux-ssd-rel-dev" } builders { - name: "buildbucket/luci.chromium.ci/mac-rel-swarming" + name: "buildbucket/luci.chromium.ci/mac-rel-dev" } builders { - name: "buildbucket/luci.chromium.ci/mac-arm-rel-swarming" + name: "buildbucket/luci.chromium.ci/mac-arm-rel-dev" } builders { - name: "buildbucket/luci.chromium.ci/win-rel-swarming" + name: "buildbucket/luci.chromium.ci/win-rel-dev" } builders { - name: "buildbucket/luci.chromium.ci/win11-rel-swarming" + name: "buildbucket/luci.chromium.ci/win11-rel-dev" } header { oncalls {
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index 49ee1fe..96e4adf 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -8134,6 +8134,11 @@ short_name: "x64" } builders { + name: "buildbucket/luci.chromium.ci/fuchsia-fyi-x64-dbg-persistent-emulator" + category: "debug" + short_name: "x64-llemu" + } + builders { name: "buildbucket/luci.chrome.ci/fuchsia-fyi-arm64-size" category: "p/chrome|arm64" short_name: "size" @@ -13542,6 +13547,11 @@ short_name: "cmp" } builders { + name: "buildbucket/luci.chromium.reclient/Comparison Linux (reclient vs reclient remote links)(compression)" + category: "linux" + short_name: "cmp" + } + builders { name: "buildbucket/luci.chromium.reclient/Comparison Linux (reclient vs reclient remote links)(small)" category: "linux" short_name: "cmp"
diff --git a/infra/config/generated/luci/luci-notify.cfg b/infra/config/generated/luci/luci-notify.cfg index a0d63daa..7e4ed86 100644 --- a/infra/config/generated/luci/luci-notify.cfg +++ b/infra/config/generated/luci/luci-notify.cfg
@@ -2746,6 +2746,18 @@ } notifiers { notifications { + on_change: true + email { + recipients: "chrome-fuchsia-gardener@grotations.appspotmail.com" + } + } + builders { + bucket: "ci" + name: "fuchsia-fyi-x64-dbg-persistent-emulator" + } +} +notifiers { + notifications { on_new_status: FAILURE email { recipients: "chrome-a11y-alerts@google.com"
diff --git a/infra/config/generated/luci/luci-scheduler-dev.cfg b/infra/config/generated/luci/luci-scheduler-dev.cfg index 5cde5e7..f32dca7 100644 --- a/infra/config/generated/luci/luci-scheduler-dev.cfg +++ b/infra/config/generated/luci/luci-scheduler-dev.cfg
@@ -5,78 +5,78 @@ # https://luci-config.appspot.com/schemas/projects:luci-scheduler.cfg job { - id: "android-pie-arm64-rel-swarming" + id: "android-pie-arm64-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "android-pie-arm64-rel-swarming" + builder: "android-pie-arm64-rel-dev" } } job { - id: "linux-rel-swarming" + id: "linux-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "linux-rel-swarming" + builder: "linux-rel-dev" } } job { - id: "linux-ssd-rel-swarming" + id: "linux-ssd-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "linux-ssd-rel-swarming" + builder: "linux-ssd-rel-dev" } } job { - id: "mac-arm-rel-swarming" + id: "mac-arm-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "mac-arm-rel-swarming" + builder: "mac-arm-rel-dev" } } job { - id: "mac-rel-swarming" + id: "mac-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "mac-rel-swarming" + builder: "mac-rel-dev" } } job { - id: "win-rel-swarming" + id: "win-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "win-rel-swarming" + builder: "win-rel-dev" } } job { - id: "win11-rel-swarming" + id: "win11-rel-dev" realm: "ci" buildbucket { server: "cr-buildbucket-dev.appspot.com" bucket: "ci" - builder: "win11-rel-swarming" + builder: "win11-rel-dev" } } trigger { id: "chromium-gitiles-trigger" realm: "ci" - triggers: "android-pie-arm64-rel-swarming" - triggers: "linux-rel-swarming" - triggers: "linux-ssd-rel-swarming" - triggers: "mac-arm-rel-swarming" - triggers: "mac-rel-swarming" - triggers: "win-rel-swarming" - triggers: "win11-rel-swarming" + triggers: "android-pie-arm64-rel-dev" + triggers: "linux-rel-dev" + triggers: "linux-ssd-rel-dev" + triggers: "mac-arm-rel-dev" + triggers: "mac-rel-dev" + triggers: "win-rel-dev" + triggers: "win11-rel-dev" gitiles { repo: "https://chromium.googlesource.com/chromium/src" refs: "regexp:refs/heads/main"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index a2994ab7..ed1682f 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -631,6 +631,15 @@ } } job { + id: "Comparison Linux (reclient vs reclient remote links)(compression)" + realm: "reclient" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "reclient" + builder: "Comparison Linux (reclient vs reclient remote links)(compression)" + } +} +job { id: "Comparison Linux (reclient vs reclient remote links)(small)" realm: "reclient" buildbucket { @@ -4169,6 +4178,15 @@ } } job { + id: "fuchsia-fyi-x64-dbg-persistent-emulator" + realm: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "fuchsia-fyi-x64-dbg-persistent-emulator" + } +} +job { id: "fuchsia-official" realm: "ci" buildbucket { @@ -6628,6 +6646,7 @@ triggers: "mac-archive-rel-goma-rbe-canary" triggers: "mac-archive-rel-goma-rbe-latest" triggers: "Comparison Linux (reclient vs reclient remote links)" + triggers: "Comparison Linux (reclient vs reclient remote links)(compression)" triggers: "Comparison Linux (reclient vs reclient remote links)(small)" triggers: "Linux Builder reclient staging" triggers: "Linux Builder reclient staging untrusted"
diff --git a/infra/config/generated/luci/realms.cfg b/infra/config/generated/luci/realms.cfg index fe0cd36..6976a89 100644 --- a/infra/config/generated/luci/realms.cfg +++ b/infra/config/generated/luci/realms.cfg
@@ -157,6 +157,7 @@ values: "android-webview-10-x86-rel-tests" values: "android-webview-12-x64-dbg-tests" values: "android-webview-13-x64-dbg-tests" + values: "fuchsia-fyi-x64-dbg-persistent-emulator" values: "linux-lacros-dbg-tests-fyi" values: "linux-lacros-tester-fyi-rel" values: "linux-lacros-tester-rel"
diff --git a/infra/config/generated/sheriff-rotations/fuchsia.txt b/infra/config/generated/sheriff-rotations/fuchsia.txt index e3fbfe9..f91b5e8 100644 --- a/infra/config/generated/sheriff-rotations/fuchsia.txt +++ b/infra/config/generated/sheriff-rotations/fuchsia.txt
@@ -2,4 +2,5 @@ ci/fuchsia-fyi-arm64-dbg ci/fuchsia-fyi-x64-asan ci/fuchsia-fyi-x64-dbg +ci/fuchsia-fyi-x64-dbg-persistent-emulator ci/fuchsia-x64-chrome-rel
diff --git a/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star index df800af..1da85ae8 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fuchsia.fyi.star
@@ -217,3 +217,34 @@ ), ], ) + +ci.builder( + name = "fuchsia-fyi-x64-dbg-persistent-emulator", + triggered_by = ["ci/fuchsia-fyi-x64-dbg"], + builder_spec = builder_config.builder_spec( + execution_mode = builder_config.execution_mode.TEST, + gclient_config = builder_config.gclient_config( + config = "chromium", + apply_configs = [ + "fuchsia_x64", + ], + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = [ + "mb", + ], + build_config = builder_config.build_config.DEBUG, + target_bits = 64, + target_platform = builder_config.target_platform.FUCHSIA, + ), + build_gs_bucket = "chromium-fyi-archive", + run_tests_serially = True, + ), + console_view_entry = [ + consoles.console_view_entry( + category = "debug", + short_name = "x64-llemu", + ), + ], +)
diff --git a/infra/config/subprojects/reclient/reclient.star b/infra/config/subprojects/reclient/reclient.star index d654d32..9228747 100644 --- a/infra/config/subprojects/reclient/reclient.star +++ b/infra/config/subprojects/reclient/reclient.star
@@ -115,7 +115,7 @@ **kwargs): reclient_bootstrap_env = kwargs.pop("reclient_bootstrap_env", {}) reclient_bootstrap_env.update({ - "RBE_compression_threshold": "4000000", + "RBE_compression_threshold": "100000000", }) return fyi_reclient_staging_builder( name = name, @@ -442,7 +442,27 @@ "RBE_clang_depscan_archive": "true", "RBE_use_unified_uploads": "false", "GOMA_DEPS_CACHE_TABLE_THRESHOLD": "40000", - "RBE_compression_threshold": "4000000", + }, + reclient_cache_silo = "Comparison Linux remote links - cache siloed", + reclient_instance = reclient.instance.TEST_TRUSTED, + reclient_jobs = reclient.jobs.DEFAULT, +) + +ci.builder( + name = "Comparison Linux (reclient vs reclient remote links)(compression)", + executable = "recipe:reclient_reclient_comparison", + os = os.LINUX_DEFAULT, + console_view_entry = consoles.console_view_entry( + category = "linux", + short_name = "cmp", + ), + execution_timeout = 6 * time.hour, + reclient_bootstrap_env = { + "RBE_ip_reset_min_delay": "-1s", + "RBE_clang_depscan_archive": "true", + "RBE_use_unified_uploads": "false", + "GOMA_DEPS_CACHE_TABLE_THRESHOLD": "40000", + "RBE_compression_threshold": "100000000", }, reclient_cache_silo = "Comparison Linux remote links - cache siloed", reclient_instance = reclient.instance.TEST_TRUSTED,
diff --git a/ios/chrome/app/feed_app_agent.mm b/ios/chrome/app/feed_app_agent.mm index fc3e8bf..c091280c 100644 --- a/ios/chrome/app/feed_app_agent.mm +++ b/ios/chrome/app/feed_app_agent.mm
@@ -140,7 +140,7 @@ // Do not DCHECK IsFeedBackgroundRefreshEnabled() because this is also called // from the background task handler, and the value could have changed during a // cold start. - if (!IsFeedBackgroundRefreshEnabled() || + if (!IsFeedBackgroundRefreshEnabled() && !IsFeedAppCloseBackgroundRefreshEnabled()) { return; }
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 index fed2534..4c23423c 100644 --- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -bc29cbf3272f9b13f3c3cf31f5156983f6bb8b17 \ No newline at end of file +5c74394f743ebe55442f3c29204574a8fc86d5a4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 index 0b15ed30..8cfc5aa 100644 --- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 +++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@ -dd8afb48840dc3d777544965c0b5758968e68d23 \ No newline at end of file +8b11256fc4303a9ab52f4c8511124f5913442b2a \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index 2494633..09c8909 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -9a8a878567b057d6f8ed9b1145812cfda67a62a1 \ No newline at end of file +432d0af248b9196057a165db7eed989d903a20ee \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 403b650e..2440278 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -b6283d98e8f1169bd01379852195791c79dedf10 \ No newline at end of file +9f073788a5f6bf6868488a03bffea68985bac0a5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index a833e11..e236903 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -0a0a78019057f307d27a8bb84e5af63031ae8c94 \ No newline at end of file +27d696b43dae417093ff060f797c2ee04d057673 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index be57e95..4b89945 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -2b250a42a6930f4f5086bfb86dfc935cfb3fc987 \ No newline at end of file +b1e3dc3fb5de54f402002b1f9a8dba06a3ee0a94 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 index 84b9452..29ace98 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -8af4adcf88ced6d7d3210c0d163d8d803775a28b \ No newline at end of file +23db85df160bdf1803293e0939b56c06ae5edbed \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 index 2daf219..92081c4c 100644 --- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -505a2249e47f22562992b11f7c684a7876b44673 \ No newline at end of file +4e4c3538733bb66e2ac6cbe0e5fe04aea779f6d0 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index 4d5b6155..70cceedb 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -a617fda87ce89ba470294300df12d33b7afbce86 \ No newline at end of file +e051ba68a8417da89533a9ec8ab8db1976b4db87 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 1f67c7e..cfd88829 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -f9347d4e5583a2c3a7d73598eaf73874eaa702e0 \ No newline at end of file +8031f8eaf91a8e217e9ecab521b46bf52d375e41 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 642a995..3dc4e2a3 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -10c9f903fc6bc7e7f8a380086e395a311355dd47 \ No newline at end of file +0eb88025fd03cba3bd008527b416dbbc2aae6aec \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 1e91aa5..ef3fe432 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -57fc2cff02b748cd9969cd3f8e5b34d819d011c0 \ No newline at end of file +e37132d0066cc38375a7bb44c6774593deea2016 \ No newline at end of file
diff --git a/ios/web/content/BUILD.gn b/ios/web/content/BUILD.gn index b2146bad..f4d5424 100644 --- a/ios/web/content/BUILD.gn +++ b/ios/web/content/BUILD.gn
@@ -11,6 +11,8 @@ sources = [ "content_browser_context.h", "content_browser_context.mm", + "js_messaging/content_web_frame.h", + "js_messaging/content_web_frame.mm", "js_messaging/content_web_frames_manager.h", "js_messaging/content_web_frames_manager.mm", "navigation/content_navigation_context.h", @@ -30,6 +32,7 @@ "//content/public/browser", "//ios/web/common:user_agent", "//ios/web/find_in_page:find_in_page", + "//ios/web/js_messaging", "//ios/web/navigation:core", "//ios/web/public", "//ios/web/public/favicon",
diff --git a/ios/web/content/js_messaging/content_web_frame.h b/ios/web/content/js_messaging/content_web_frame.h new file mode 100644 index 0000000..1e3024b --- /dev/null +++ b/ios/web/content/js_messaging/content_web_frame.h
@@ -0,0 +1,100 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_CONTENT_JS_MESSAGING_CONTENT_WEB_FRAME_H_ +#define IOS_WEB_CONTENT_JS_MESSAGING_CONTENT_WEB_FRAME_H_ + +#import <map> +#import <string> + +#import "base/cancelable_callback.h" +#import "base/values.h" +#import "content/public/browser/global_routing_id.h" +#import "ios/web/js_messaging/web_frame_internal.h" +#import "ios/web/public/js_messaging/web_frame.h" +#import "ios/web/public/web_state_observer.h" +#import "url/gurl.h" + +namespace content { +class RenderFrameHost; +} + +namespace web { + +class ContentWebState; + +// ContentWebFrame is a WebFrame that wraps a content::RenderFrameHost. +class ContentWebFrame : public WebFrame, + public WebFrameInternal, + public WebStateObserver { + public: + ContentWebFrame(const std::string& web_frame_id, + const content::GlobalRenderFrameHostId& content_id, + ContentWebState* content_web_state); + + ContentWebFrame(const ContentWebFrame&) = delete; + ContentWebFrame& operator=(const ContentWebFrame&) = delete; + + ~ContentWebFrame() override; + + // WebFrame: + WebFrameInternal* GetWebFrameInternal() override; + std::string GetFrameId() const override; + bool IsMainFrame() const override; + GURL GetSecurityOrigin() const override; + BrowserState* GetBrowserState() override; + + bool CallJavaScriptFunction( + const std::string& name, + const std::vector<base::Value>& parameters) override; + bool CallJavaScriptFunction( + const std::string& name, + const std::vector<base::Value>& parameters, + base::OnceCallback<void(const base::Value*)> callback, + base::TimeDelta timeout) override; + + bool ExecuteJavaScript(const std::u16string& script) override; + bool ExecuteJavaScript( + const std::u16string& script, + base::OnceCallback<void(const base::Value*)> callback) override; + bool ExecuteJavaScript(const std::u16string& script, + ExecuteJavaScriptCallbackWithError callback) override; + + // WebFrameInternal: + bool CallJavaScriptFunctionInContentWorld( + const std::string& name, + const std::vector<base::Value>& parameters, + JavaScriptContentWorld* content_world) override; + bool CallJavaScriptFunctionInContentWorld( + const std::string& name, + const std::vector<base::Value>& parameters, + JavaScriptContentWorld* content_world, + base::OnceCallback<void(const base::Value*)> callback, + base::TimeDelta timeout) override; + + // WebStateObserver: + void WebStateDestroyed(WebState* web_state) override; + + private: + // Detaches the receiver from the associated WebState. + void DetachFromWebState(); + + // Returns the RenderFrameHost corresponding to this WebFrame. + content::RenderFrameHost* GetRenderFrameHost() const; + + // The web frame identifier which uniquely identifies this frame across the + // application's lifetime. + std::string web_frame_id_; + + // The content frame identifier which uniquely identifies this frame across + // the application's lifetime. + content::GlobalRenderFrameHostId content_id_; + + // The web state corresponding to the WebContents for this frame. + raw_ptr<ContentWebState> content_web_state_; +}; + +} // namespace web + +#endif // IOS_WEB_CONTENT_JS_MESSAGING_CONTENT_WEB_FRAME_H_
diff --git a/ios/web/content/js_messaging/content_web_frame.mm b/ios/web/content/js_messaging/content_web_frame.mm new file mode 100644 index 0000000..7f840be --- /dev/null +++ b/ios/web/content/js_messaging/content_web_frame.mm
@@ -0,0 +1,121 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/web/content/js_messaging/content_web_frame.h" + +#import "content/public/browser/render_frame_host.h" +#import "ios/web/content/web_state/content_web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace web { + +ContentWebFrame::ContentWebFrame( + const std::string& web_frame_id, + const content::GlobalRenderFrameHostId& content_id, + ContentWebState* content_web_state) + : web_frame_id_(web_frame_id), + content_id_(content_id), + content_web_state_(content_web_state) { + content_web_state->AddObserver(this); +} + +ContentWebFrame::~ContentWebFrame() { + DetachFromWebState(); +} + +WebFrameInternal* ContentWebFrame::GetWebFrameInternal() { + return this; +} + +std::string ContentWebFrame::GetFrameId() const { + return web_frame_id_; +} + +content::RenderFrameHost* ContentWebFrame::GetRenderFrameHost() const { + return content::RenderFrameHost::FromID(content_id_); +} + +bool ContentWebFrame::IsMainFrame() const { + return GetRenderFrameHost()->IsInPrimaryMainFrame(); +} + +GURL ContentWebFrame::GetSecurityOrigin() const { + // TODO(crbug.com/1423501): Once GetSecurityOrigin is changed to return an + // Origin instead of a URL, this should use GetLastCommittedOrigin(). + return GetRenderFrameHost()->GetLastCommittedURL(); +} + +BrowserState* ContentWebFrame::GetBrowserState() { + return content_web_state_->GetBrowserState(); + ; +} + +bool ContentWebFrame::CallJavaScriptFunction( + const std::string& name, + const std::vector<base::Value>& parameters) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +bool ContentWebFrame::CallJavaScriptFunction( + const std::string& name, + const std::vector<base::Value>& parameters, + base::OnceCallback<void(const base::Value*)> callback, + base::TimeDelta timeout) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +bool ContentWebFrame::CallJavaScriptFunctionInContentWorld( + const std::string& name, + const std::vector<base::Value>& parameters, + JavaScriptContentWorld* content_world) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +bool ContentWebFrame::CallJavaScriptFunctionInContentWorld( + const std::string& name, + const std::vector<base::Value>& parameters, + JavaScriptContentWorld* content_world, + base::OnceCallback<void(const base::Value*)> callback, + base::TimeDelta timeout) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +bool ContentWebFrame::ExecuteJavaScript(const std::u16string& script) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +bool ContentWebFrame::ExecuteJavaScript( + const std::u16string& script, + base::OnceCallback<void(const base::Value*)> callback) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +bool ContentWebFrame::ExecuteJavaScript( + const std::u16string& script, + ExecuteJavaScriptCallbackWithError callback) { + // TODO(crbug.com/1423527): Implement this. + return false; +} + +void ContentWebFrame::DetachFromWebState() { + if (content_web_state_) { + content_web_state_->RemoveObserver(this); + content_web_state_ = nullptr; + } +} + +void ContentWebFrame::WebStateDestroyed(web::WebState* web_state) { + DetachFromWebState(); +} + +} // namespace web
diff --git a/ios/web/content/js_messaging/content_web_frames_manager.h b/ios/web/content/js_messaging/content_web_frames_manager.h index 00389b6..61057eb 100644 --- a/ios/web/content/js_messaging/content_web_frames_manager.h +++ b/ios/web/content/js_messaging/content_web_frames_manager.h
@@ -7,7 +7,10 @@ #import "ios/web/public/js_messaging/web_frames_manager.h" +#import "base/observer_list.h" #import "build/blink_buildflags.h" +#import "content/public/browser/global_routing_id.h" +#import "content/public/browser/web_contents_observer.h" #if !BUILDFLAG(USE_BLINK) #error File can only be included when USE_BLINK is true @@ -15,11 +18,17 @@ namespace web { +class ContentWebState; + // ContentWebFramesManager is a WebFramesManager that is built on top -// of //content. -class ContentWebFramesManager : public WebFramesManager { +// of //content. As a WebContentsObserver, it finds out about all frame creation +// and destruction. It uses two id schemes to identify frames: content's id +// scheme for RenderFrameHosts, and a scheme that mimics WebFrameImpl's string +// id scheme. +class ContentWebFramesManager : public WebFramesManager, + public content::WebContentsObserver { public: - ContentWebFramesManager(); + ContentWebFramesManager(ContentWebState* content_web_state); ~ContentWebFramesManager() override; // WebFramesManager impl. @@ -28,6 +37,26 @@ std::set<WebFrame*> GetAllWebFrames() override; WebFrame* GetMainWebFrame() override; WebFrame* GetFrameWithId(const std::string& frame_id) override; + + // WebContentsObserver overrides. + void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; + void PrimaryPageChanged(content::Page& page) override; + + private: + // List of pointers to all web frames. + std::map<std::string, std::unique_ptr<WebFrame>> web_frames_; + + // Map from content's id scheme to web's id scheme. + std::map<content::GlobalRenderFrameHostId, std::string> + content_to_web_id_map_; + + // Reference to the current main frame + content::GlobalRenderFrameHostId main_frame_content_id_; + base::ObserverList<Observer, /*check_empty=*/false> observers_; + + // The ContentWebState that owns this object. + raw_ptr<ContentWebState> content_web_state_; }; } // namespace web
diff --git a/ios/web/content/js_messaging/content_web_frames_manager.mm b/ios/web/content/js_messaging/content_web_frames_manager.mm index c334022..64b9c3c 100644 --- a/ios/web/content/js_messaging/content_web_frames_manager.mm +++ b/ios/web/content/js_messaging/content_web_frames_manager.mm
@@ -6,30 +6,97 @@ #import <set> +#import "base/ios/device_util.h" +#import "content/public/browser/page.h" +#import "content/public/browser/web_contents.h" +#import "ios/web/content/js_messaging/content_web_frame.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif namespace web { -ContentWebFramesManager::ContentWebFramesManager() {} +ContentWebFramesManager::ContentWebFramesManager( + ContentWebState* content_web_state) + : content::WebContentsObserver(nullptr), + content_web_state_(content_web_state) { + // TODO(crbug.com/1419001) Pass a WebContents* to WebContentsObserver's + // constructor once ContentWebState exposes it. +} -ContentWebFramesManager::~ContentWebFramesManager() {} +ContentWebFramesManager::~ContentWebFramesManager() = default; -void ContentWebFramesManager::AddObserver(Observer* observer) {} +void ContentWebFramesManager::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} -void ContentWebFramesManager::RemoveObserver(Observer* observer) {} +void ContentWebFramesManager::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} std::set<WebFrame*> ContentWebFramesManager::GetAllWebFrames() { - return std::set<WebFrame*>(); + std::set<WebFrame*> frames; + for (const auto& it : web_frames_) { + frames.insert(it.second.get()); + } + return frames; } WebFrame* ContentWebFramesManager::GetMainWebFrame() { - return nullptr; + auto web_id_it = content_to_web_id_map_.find(main_frame_content_id_); + if (web_id_it == content_to_web_id_map_.end()) { + return nullptr; + } + + return GetFrameWithId(web_id_it->second); } WebFrame* ContentWebFramesManager::GetFrameWithId(const std::string& frame_id) { - return nullptr; + DCHECK(!frame_id.empty()); + auto web_frames_it = web_frames_.find(frame_id); + return web_frames_it == web_frames_.end() ? nullptr + : web_frames_it->second.get(); +} + +void ContentWebFramesManager::RenderFrameCreated( + content::RenderFrameHost* render_frame_host) { + // TODO(crbug.com/1423527): Ensure that the random id chosen here is either + // injected into the frame or directly attached to JavaScript messages + // received from the frame, since features expect this. + std::string web_frame_id = ios::device_util::GetRandomId(); + auto web_frame = std::make_unique<ContentWebFrame>( + web_frame_id, render_frame_host->GetGlobalId(), content_web_state_); + WebFrame* new_frame = web_frame.get(); + web_frames_[web_frame_id] = std::move(web_frame); + content_to_web_id_map_[render_frame_host->GetGlobalId()] = web_frame_id; + + for (auto& observer : observers_) { + observer.WebFrameBecameAvailable(this, new_frame); + } +} + +void ContentWebFramesManager::RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) { + content::GlobalRenderFrameHostId content_id = + render_frame_host->GetGlobalId(); + auto web_id_it = content_to_web_id_map_.find(main_frame_content_id_); + DCHECK(web_id_it != content_to_web_id_map_.end()); + + for (auto& observer : observers_) { + observer.WebFrameBecameUnavailable(this, web_id_it->second); + } + + if (main_frame_content_id_ == content_id) { + main_frame_content_id_ = content::GlobalRenderFrameHostId(); + } + + web_frames_.erase(web_id_it->second); + content_to_web_id_map_.erase(web_id_it); +} + +void ContentWebFramesManager::PrimaryPageChanged(content::Page& page) { + main_frame_content_id_ = page.GetMainDocument().GetGlobalId(); } } // namespace web
diff --git a/ios/web/content/web_state/content_web_state.mm b/ios/web/content/web_state/content_web_state.mm index 975a10d..25001f9 100644 --- a/ios/web/content/web_state/content_web_state.mm +++ b/ios/web/content/web_state/content_web_state.mm
@@ -76,7 +76,7 @@ params.browser_state); navigation_manager_ = std::make_unique<ContentNavigationManager>( this, params.browser_state, controller); - web_frames_manager_ = std::make_unique<ContentWebFramesManager>(); + web_frames_manager_ = std::make_unique<ContentWebFramesManager>(this); web_view_ = [[UIScrollView alloc] init]; web_view_.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/web_view/internal/sync/cwv_sync_controller.mm b/ios/web_view/internal/sync/cwv_sync_controller.mm index 96a250e2..7a010534 100644 --- a/ios/web_view/internal/sync/cwv_sync_controller.mm +++ b/ios/web_view/internal/sync/cwv_sync_controller.mm
@@ -31,9 +31,6 @@ // Called by WebViewSyncControllerObserverBridge's |OnStateChanged|. - (void)syncStateDidChange; -// Call to reload accounts from the |dataSource|. -- (void)reloadAccounts; - @end namespace ios_web_view { @@ -104,18 +101,6 @@ std::make_unique<ios_web_view::WebViewSyncControllerObserverBridge>( self); _syncService->AddObserver(_observer.get()); - - // Refresh access tokens on foreground to extend expiration dates. - [[NSNotificationCenter defaultCenter] - addObserver:self - selector:@selector(reloadAccounts) - name:UIApplicationWillEnterForegroundNotification - object:nil]; - - // This allows internals of |_identityManager| to fetch and store the user's - // info and profile image. This must be called manually *after* all services - // have been started to avoid issues in https://crbug.com/441399. - _identityManager->OnNetworkInitialized(); } return self; } @@ -218,11 +203,4 @@ } } -- (void)reloadAccounts { - _identityManager->GetDeviceAccountsSynchronizer() - ->ReloadAllAccountsFromSystemWithPrimaryAccount( - _identityManager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync) - .account_id); -} - @end
diff --git a/net/base/features.cc b/net/base/features.cc index ded71dda..dc35d57 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -325,6 +325,11 @@ base::FEATURE_DISABLED_BY_DEFAULT); #endif +// A flag to use asynchronous session creation for new QUIC sessions. +BASE_FEATURE(kAsyncQuicSession, + "AsyncQuicSession", + base::FEATURE_DISABLED_BY_DEFAULT); + // IP protection experiment configuration settings BASE_FEATURE(kEnableIpProtectionProxy, "EnableIpPrivacyProxy",
diff --git a/net/base/features.h b/net/base/features.h index 6df993e..948e9a9c 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -363,6 +363,9 @@ NET_EXPORT BASE_DECLARE_FEATURE(kKerberosInBrowserRedirect); #endif +// A flag to use asynchronous session creation for new QUIC sessions. +NET_EXPORT BASE_DECLARE_FEATURE(kAsyncQuicSession); + // Enables custom proxy configuration for the IP Protection experimental proxy. NET_EXPORT BASE_DECLARE_FEATURE(kEnableIpProtectionProxy);
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc index 066df342..8fc1c92c 100644 --- a/net/http/http_cache_transaction.cc +++ b/net/http/http_cache_transaction.cc
@@ -2753,16 +2753,6 @@ cacheable = false; } - NetworkIsolationKeyPresent nik_present_enum = - request_->network_isolation_key.IsFullyPopulated() - ? NetworkIsolationKeyPresent::kPresent - : cacheable - ? NetworkIsolationKeyPresent::kNotPresentCacheableRequest - : NetworkIsolationKeyPresent::kNotPresentNonCacheableRequest; - - UMA_HISTOGRAM_ENUMERATION("HttpCache.NetworkIsolationKeyPresent2", - nik_present_enum); - return !cacheable; }
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc index 6d6cb25..7722bd5 100644 --- a/net/http/http_cache_unittest.cc +++ b/net/http/http_cache_unittest.cc
@@ -11199,7 +11199,6 @@ if (!IsSplitCacheEnabled()) { return; } - base::HistogramTester histograms; MockHttpCache cache; HttpResponseInfo response; @@ -11216,10 +11215,6 @@ RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, trans_info, &response); EXPECT_FALSE(response.was_cached); - histograms.ExpectBucketCount( - "HttpCache.NetworkIsolationKeyPresent2", - HttpCache::Transaction::NetworkIsolationKeyPresent::kPresent, 1); - histograms.ExpectTotalCount("HttpCache.NetworkIsolationKeyPresent2", 1); // The second request should be cached. RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, @@ -11428,7 +11423,6 @@ if (!IsSplitCacheEnabled()) { return; } - base::HistogramTester histograms; MockHttpCache cache; HttpResponseInfo response; @@ -11443,11 +11437,6 @@ RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, trans_info, &response); EXPECT_FALSE(response.was_cached); - histograms.ExpectUniqueSample( - "HttpCache.NetworkIsolationKeyPresent2", - HttpCache::Transaction::NetworkIsolationKeyPresent:: - kNotPresentNonCacheableRequest, - 1); RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, trans_info, &response); @@ -11462,10 +11451,6 @@ RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, trans_info, &response); EXPECT_FALSE(response.was_cached); - histograms.ExpectBucketCount( - "HttpCache.NetworkIsolationKeyPresent2", - HttpCache::Transaction::NetworkIsolationKeyPresent::kPresent, 1); - histograms.ExpectTotalCount("HttpCache.NetworkIsolationKeyPresent2", 3); // The second request should be cached. RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, @@ -11589,7 +11574,6 @@ if (!IsSplitCacheEnabled()) { return; } - base::HistogramTester histograms; MockHttpCache cache; HttpResponseInfo response; MockHttpRequest trans_info = MockHttpRequest(kSimpleGET_Transaction); @@ -11604,9 +11588,6 @@ RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, trans_info, &response); EXPECT_FALSE(response.was_cached); - histograms.ExpectBucketCount( - "HttpCache.NetworkIsolationKeyPresent2", - HttpCache::Transaction::NetworkIsolationKeyPresent::kPresent, 1); // The second request with a different origin but the same registrable domain // should be a cache hit. @@ -11634,7 +11615,6 @@ feature_list.InitAndDisableFeature( net::features::kSplitCacheByNetworkIsolationKey); - base::HistogramTester histograms; MockHttpCache cache; HttpResponseInfo response; @@ -11660,10 +11640,6 @@ RunTransactionTestWithRequest(cache.http_cache(), kSimpleGET_Transaction, trans_info, &response); EXPECT_TRUE(response.was_cached); - histograms.ExpectBucketCount( - "HttpCache.NetworkIsolationKeyPresent2", - HttpCache::Transaction::NetworkIsolationKeyPresent::kPresent, 1); - histograms.ExpectTotalCount("HttpCache.NetworkIsolationKeyPresent2", 3); } TEST_F(HttpCacheTest, SkipVaryCheck) {
diff --git a/net/http/http_stream_factory_job_controller_unittest.cc b/net/http/http_stream_factory_job_controller_unittest.cc index 69fd513..edb985a 100644 --- a/net/http/http_stream_factory_job_controller_unittest.cc +++ b/net/http/http_stream_factory_job_controller_unittest.cc
@@ -345,26 +345,40 @@ } void TestAltJobSucceedsAfterMainJobFailed( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestMainJobSucceedsAfterAltJobFailed( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestMainJobSucceedsAfterIgnoredError(int net_error, + bool async_quic_session, bool expect_broken = false, std::string alternate_host = ""); void TestAltJobSucceedsAfterMainJobSucceeded( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestOnStreamFailedForBothJobs( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestAltJobFailsAfterMainJobSucceeded( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestMainJobSucceedsAfterAltJobSucceeded( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestMainJobFailsAfterAltJobSucceeded( - bool alt_job_retried_on_non_default_network); + bool alt_job_retried_on_non_default_network, + bool async_quic_session); void TestAltSvcVersionSelection( const std::string& alt_svc_header, const quic::ParsedQuicVersion& expected_version, const quic::ParsedQuicVersionVector& supported_versions); + void TestResumeMainJobWhenAltJobStalls(bool async_quic_session); + void TestAltJobSucceedsMainJobDestroyed(bool async_quic_session); + void TestOrphanedJobCompletesControllerDestroyed(bool async_quic_session); + void TestDoNotDelayMainJobIfQuicWasRecentlyBroken(bool async_quic_session); + void TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed( + bool async_quic_session); bool dns_https_alpn_enabled() const { return dns_https_alpn_enabled_; } @@ -1306,8 +1320,17 @@ EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_)); } -TEST_P(HttpStreamFactoryJobControllerTest, - DoNotDelayMainJobIfQuicWasRecentlyBroken) { +void HttpStreamFactoryJobControllerTestBase:: + TestDoNotDelayMainJobIfQuicWasRecentlyBroken(bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::COLD_START); quic_data_ = std::make_unique<MockQuicData>(version_); @@ -1345,8 +1368,11 @@ // once yet. EXPECT_EQ(job_controller_->get_main_job_wait_time_for_tests(), base::TimeDelta()); - EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); - + if (async_quic_session) { + EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); + } else { + EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_)); + } // Make |alternative_job| succeed. auto http_stream = std::make_unique<HttpBasicStream>( std::make_unique<ClientSocketHandle>(), false); @@ -1368,7 +1394,27 @@ } TEST_P(HttpStreamFactoryJobControllerTest, - DelayMainJobAfterRecentlyBrokenQuicWasConfirmed) { + DoNotDelayMainJobIfQuicWasRecentlyBroken) { + TestDoNotDelayMainJobIfQuicWasRecentlyBroken(false); +} + +TEST_P(HttpStreamFactoryJobControllerTest, + DoNotDelayMainJobIfQuicWasRecentlyBrokenAsyncQuicSession) { + TestDoNotDelayMainJobIfQuicWasRecentlyBroken(true); +} + +void HttpStreamFactoryJobControllerTestBase:: + TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed( + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::COLD_START); quic_data_ = std::make_unique<MockQuicData>(version_); @@ -1410,7 +1456,11 @@ // 0. EXPECT_TRUE(job_controller_->ShouldWait( const_cast<net::HttpStreamFactory::Job*>(job_controller_->main_job()))); - EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); + if (async_quic_session) { + EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); + } else { + EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_)); + } EXPECT_GE(job_controller_->get_main_job_wait_time_for_tests(), base::TimeDelta()); @@ -1434,8 +1484,28 @@ EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_)); } +TEST_P(HttpStreamFactoryJobControllerTest, + DelayMainJobAfterRecentlyBrokenQuicWasConfirmed) { + TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(false); +} + +TEST_P(HttpStreamFactoryJobControllerTest, + DelayMainJobAfterRecentlyBrokenQuicWasConfirmedAsyncQuicSession) { + TestDelayMainJobAfterRecentlyBrokenQuicWasConfirmed(true); +} + void HttpStreamFactoryJobControllerTestBase::TestOnStreamFailedForBothJobs( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddConnect(ASYNC, ERR_FAILED); tcp_data_ = std::make_unique<SequencedSocketData>(); @@ -1462,9 +1532,11 @@ JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_); } - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } // The failure of second Job should be reported to Request as there's no more // pending Job to serve the Request. EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _, _)).Times(1); @@ -1478,19 +1550,46 @@ // jobs fail, and the alternative job is not retried on the alternate network. TEST_P(HttpStreamFactoryJobControllerTest, OnStreamFailedForBothJobsWithoutQuicRetry) { - TestOnStreamFailedForBothJobs(false); + TestOnStreamFailedForBothJobs(false, false); } // This test verifies that the alternative service is not marked broken if both // jobs fail, and the alternative job is retried on the alternate network. TEST_P(HttpStreamFactoryJobControllerTest, OnStreamFailedForBothJobsWithQuicRetriedOnAlternateNetwork) { - TestOnStreamFailedForBothJobs(true); + TestOnStreamFailedForBothJobs(true, false); +} + +// This test verifies that the alternative service is not marked broken if both +// jobs fail, and the alternative job is not retried on the alternate network. +// This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + OnStreamFailedForBothJobsWithoutQuicRetryAsyncQuicSession) { + TestOnStreamFailedForBothJobs(false, true); +} + +// This test verifies that the alternative service is not marked broken if both +// jobs fail, and the alternative job is retried on the alternate network. This +// test uses asynchronous QUIC session creation. +TEST_P( + HttpStreamFactoryJobControllerTest, + OnStreamFailedForBothJobsWithQuicRetriedOnAlternateNetworkAsyncQuicSession) { + TestOnStreamFailedForBothJobs(true, true); } void HttpStreamFactoryJobControllerTestBase:: TestAltJobFailsAfterMainJobSucceeded( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(ASYNC, ERR_FAILED); crypto_client_stream_factory_.set_handshake_mode( @@ -1522,9 +1621,11 @@ JobControllerPeer::SetAltJobFailedOnDefaultNetwork(job_controller_); } - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } // Main job succeeds, starts serving Request and it should report status // to Request. The alternative job will mark the main job complete and gets // orphaned. @@ -1546,24 +1647,51 @@ VerifyBrokenAlternateProtocolMapping(request_info, true); } -// This test verifies that the alternatvie service is marked broken when the +// This test verifies that the alternative service is marked broken when the // alternative job fails on default after the main job succeeded. The // brokenness should not be cleared when the default network changes. TEST_P(HttpStreamFactoryJobControllerTest, AltJobFailsOnDefaultNetworkAfterMainJobSucceeded) { - TestAltJobFailsAfterMainJobSucceeded(false); + TestAltJobFailsAfterMainJobSucceeded(false, false); } -// This test verifies that the alternatvie service is marked broken when the +// This test verifies that the alternative service is marked broken when the // alternative job fails on both networks after the main job succeeded. The // brokenness should not be cleared when the default network changes. TEST_P(HttpStreamFactoryJobControllerTest, AltJobFailsOnBothNetworksAfterMainJobSucceeded) { - TestAltJobFailsAfterMainJobSucceeded(true); + TestAltJobFailsAfterMainJobSucceeded(true, false); } -// Tests that when alt job succeeds, main job is destroyed. -TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsMainJobDestroyed) { +// This test verifies that the alternative service is marked broken when the +// alternative job fails on default after the main job succeeded. The +// brokenness should not be cleared when the default network changes. This test +// uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobFailsOnDefaultNetworkAfterMainJobSucceededAsyncQuicSession) { + TestAltJobFailsAfterMainJobSucceeded(false, true); +} + +// This test verifies that the alternative service is marked broken when the +// alternative job fails on both networks after the main job succeeded. The +// brokenness should not be cleared when the default network changes. This test +// uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobFailsOnBothNetworksAfterMainJobSucceededAsyncQuicSession) { + TestAltJobFailsAfterMainJobSucceeded(true, true); +} + +void HttpStreamFactoryJobControllerTestBase::TestAltJobSucceedsMainJobDestroyed( + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Use cold start and complete alt job manually. @@ -1586,8 +1714,11 @@ HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY); EXPECT_TRUE(job_controller_->main_job()); EXPECT_TRUE(job_controller_->alternative_job()); - EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); - + if (async_quic_session) { + EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); + } else { + EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_)); + } // Make |alternative_job| succeed. auto http_stream = std::make_unique<HttpBasicStream>( std::make_unique<ClientSocketHandle>(), false); @@ -1607,6 +1738,17 @@ EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_)); } +// Tests that when alt job succeeds, main job is destroyed. +TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsMainJobDestroyed) { + TestAltJobSucceedsMainJobDestroyed(false); +} + +// Tests that when alt job succeeds, main job is destroyed. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobSucceedsMainJobDestroyedAsyncQuicSession) { + TestAltJobSucceedsMainJobDestroyed(true); +} + // Tests that if alt job succeeds and main job is blocked, main job should be // cancelled immediately. |request_| completion will clean up the JobController. // Regression test for crbug.com/678768. @@ -1686,10 +1828,17 @@ EXPECT_EQ(origin_port, alternative_host_port_pair.port()); } -// Tests that if an orphaned job completes after |request_| is gone, -// JobController will be cleaned up. -TEST_P(HttpStreamFactoryJobControllerTest, - OrphanedJobCompletesControllerDestroyed) { +void HttpStreamFactoryJobControllerTestBase:: + TestOrphanedJobCompletesControllerDestroyed(bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Use cold start and complete alt job manually. @@ -1717,9 +1866,12 @@ EXPECT_TRUE(job_controller_->main_job()); EXPECT_TRUE(job_controller_->alternative_job()); - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } + EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _)); // Complete main job now. @@ -1743,9 +1895,33 @@ EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_)); } +// Tests that if an orphaned job completes after |request_| is gone, +// JobController will be cleaned up. +TEST_P(HttpStreamFactoryJobControllerTest, + OrphanedJobCompletesControllerDestroyed) { + TestOrphanedJobCompletesControllerDestroyed(false); +} + +// Tests that if an orphaned job completes after |request_| is gone, +// JobController will be cleaned up. +TEST_P(HttpStreamFactoryJobControllerTest, + OrphanedJobCompletesControllerDestroyedAsyncQuicSession) { + TestOrphanedJobCompletesControllerDestroyed(true); +} + void HttpStreamFactoryJobControllerTestBase:: TestAltJobSucceedsAfterMainJobFailed( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Use cold start and complete alt job manually. @@ -1784,14 +1960,16 @@ // Make |alternative_job| succeed. auto http_stream = std::make_unique<HttpBasicStream>( std::make_unique<ClientSocketHandle>(), false); - base::RunLoop run_loop; - EXPECT_CALL(*job_factory_.main_job(), Resume()) - .Times(1) - .WillOnce([&run_loop, this]() { - run_loop.Quit(); - job_factory_.main_job()->DoResume(); - }); - run_loop.Run(); + if (async_quic_session) { + base::RunLoop run_loop; + EXPECT_CALL(*job_factory_.main_job(), Resume()) + .Times(1) + .WillOnce([&run_loop, this]() { + run_loop.Quit(); + job_factory_.main_job()->DoResume(); + }); + run_loop.Run(); + } EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, http_stream.get())); HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(), @@ -1808,19 +1986,45 @@ // alternative job succeeds on the default network after the main job failed. TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsOnDefaultNetworkAfterMainJobFailed) { - TestAltJobSucceedsAfterMainJobFailed(false); + TestAltJobSucceedsAfterMainJobFailed(false, false); } // This test verifies that the alternative service is not mark broken if the // alternative job succeeds on the alternate network after the main job failed. TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsOnAlternateNetworkAfterMainJobFailed) { - TestAltJobSucceedsAfterMainJobFailed(true); + TestAltJobSucceedsAfterMainJobFailed(true, false); +} + +// This test verifies that the alternative service is not mark broken if the +// alternative job succeeds on the default network after the main job failed. +// This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobSucceedsOnDefaultNetworkAfterMainJobFailedAsyncQuicSession) { + TestAltJobSucceedsAfterMainJobFailed(false, true); +} + +// This test verifies that the alternative service is not mark broken if the +// alternative job succeeds on the alternate network after the main job failed. +// This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobSucceedsOnAlternateNetworkAfterMainJobFailedAsyncQuicSession) { + TestAltJobSucceedsAfterMainJobFailed(true, true); } void HttpStreamFactoryJobControllerTestBase:: TestAltJobSucceedsAfterMainJobSucceeded( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Use cold start and complete alt job manually. @@ -1851,9 +2055,12 @@ EXPECT_TRUE(job_controller_->main_job()); EXPECT_TRUE(job_controller_->alternative_job()); - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } + // Run the message loop to make |main_job| succeed and status will be // reported to Request. EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _)); @@ -1891,7 +2098,7 @@ // alternative job succeeds on the default network after the main job succeeded. TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsOnDefaultNetworkAfterMainJobSucceeded) { - TestAltJobSucceedsAfterMainJobSucceeded(false); + TestAltJobSucceedsAfterMainJobSucceeded(false, false); } // This test verifies that the alternative service is marked broken until the @@ -1901,12 +2108,40 @@ // changes. TEST_P(HttpStreamFactoryJobControllerTest, AltJobSucceedsOnAlternateNetworkAfterMainJobSucceeded) { - TestAltJobSucceedsAfterMainJobSucceeded(true); + TestAltJobSucceedsAfterMainJobSucceeded(true, false); +} + +// This test verifies that the alternative service is not marked broken if the +// alternative job succeeds on the default network after the main job succeeded. +// This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobSucceedsOnDefaultNetworkAfterMainJobSucceededAsyncQuicSession) { + TestAltJobSucceedsAfterMainJobSucceeded(false, true); +} + +// This test verifies that the alternative service is marked broken until the +// default network changes if the alternative job succeeds on the non-default +// network, which failed on the default network previously, after the main job +// succeeded. The brokenness should be cleared when the default network +// changes. This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + AltJobSucceedsOnAlternateNetworkAfterMainJobSucceededAsyncQuicSession) { + TestAltJobSucceedsAfterMainJobSucceeded(true, true); } void HttpStreamFactoryJobControllerTestBase:: TestMainJobSucceedsAfterAltJobSucceeded( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Use cold start and complete alt job manually. @@ -1942,14 +2177,16 @@ // Make |alternative_job| succeed. auto http_stream = std::make_unique<HttpBasicStream>( std::make_unique<ClientSocketHandle>(), false); - base::RunLoop run_loop; - EXPECT_CALL(*job_factory_.main_job(), Resume()) - .Times(1) - .WillOnce([&run_loop, this]() { - run_loop.Quit(); - job_factory_.main_job()->DoResume(); - }); - run_loop.Run(); + if (async_quic_session) { + base::RunLoop run_loop; + EXPECT_CALL(*job_factory_.main_job(), Resume()) + .Times(1) + .WillOnce([&run_loop, this]() { + run_loop.Quit(); + job_factory_.main_job()->DoResume(); + }); + run_loop.Run(); + } EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, http_stream.get())); HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(), @@ -1976,7 +2213,7 @@ // main job succeeds after the alternative job succeeded on the default network. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterAltJobSucceededOnDefaultNetwork) { - TestMainJobSucceedsAfterAltJobSucceeded(false); + TestMainJobSucceedsAfterAltJobSucceeded(false, false); } // This test verifies that the alternative service is marked broken until the @@ -1986,12 +2223,40 @@ // changes. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterAltJobSucceededOnAlternateNetwork) { - TestMainJobSucceedsAfterAltJobSucceeded(true); + TestMainJobSucceedsAfterAltJobSucceeded(true, false); +} + +// This test verifies that the alternative service is not marked broken if the +// main job succeeds after the alternative job succeeded on the default network. +// This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterAltJobSucceededOnDefaultNetworkAsyncQuicSession) { + TestMainJobSucceedsAfterAltJobSucceeded(false, true); +} + +// This test verifies that the alternative service is marked broken until the +// default network changes if the main job succeeds after the alternative job +// succeeded on the non-default network, i.e., failed on the default network +// previously. The brokenness should be cleared when the default network +// changes. This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterAltJobSucceededOnAlternateNetworkAsyncQuicSession) { + TestMainJobSucceedsAfterAltJobSucceeded(true, true); } void HttpStreamFactoryJobControllerTestBase:: TestMainJobFailsAfterAltJobSucceeded( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Use cold start and complete alt job manually. @@ -2025,14 +2290,16 @@ // Make |alternative_job| succeed. auto http_stream = std::make_unique<HttpBasicStream>( std::make_unique<ClientSocketHandle>(), false); - base::RunLoop run_loop; - EXPECT_CALL(*job_factory_.main_job(), Resume()) - .Times(1) - .WillOnce([&run_loop, this]() { - run_loop.Quit(); - job_factory_.main_job()->DoResume(); - }); - run_loop.Run(); + if (async_quic_session) { + base::RunLoop run_loop; + EXPECT_CALL(*job_factory_.main_job(), Resume()) + .Times(1) + .WillOnce([&run_loop, this]() { + run_loop.Quit(); + job_factory_.main_job()->DoResume(); + }); + run_loop.Run(); + } EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, http_stream.get())); HttpStreamFactoryJobPeer::SetStream(job_factory_.alternative_job(), @@ -2050,7 +2317,7 @@ // main job fails after the alternative job succeeded on the default network. TEST_P(HttpStreamFactoryJobControllerTest, MainJobFailsAfterAltJobSucceededOnDefaultNetwork) { - TestMainJobFailsAfterAltJobSucceeded(false); + TestMainJobFailsAfterAltJobSucceeded(false, false); } // This test verifies that the alternative service is not marked broken if the @@ -2058,12 +2325,39 @@ // network, i.e., failed on the default network previously. TEST_P(HttpStreamFactoryJobControllerTest, MainJobFailsAfterAltJobSucceededOnAlternateNetwork) { - TestMainJobFailsAfterAltJobSucceeded(true); + TestMainJobFailsAfterAltJobSucceeded(true, false); +} + +// This test verifies that the alternative service is not marked broken if the +// main job fails after the alternative job succeeded on the default network. +// This test uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobFailsAfterAltJobSucceededOnDefaultNetworkAsyncQuicSession) { + TestMainJobFailsAfterAltJobSucceeded(false, true); +} + +// This test verifies that the alternative service is not marked broken if the +// main job fails after the alternative job succeeded on the non-default +// network, i.e., failed on the default network previously. This test uses +// asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobFailsAfterAltJobSucceededOnAlternateNetworkAsyncQuicSession) { + TestMainJobFailsAfterAltJobSucceeded(true, true); } void HttpStreamFactoryJobControllerTestBase:: TestMainJobSucceedsAfterAltJobFailed( - bool alt_job_retried_on_non_default_network) { + bool alt_job_retried_on_non_default_network, + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddConnect(SYNCHRONOUS, ERR_FAILED); @@ -2091,9 +2385,11 @@ // |alternative_job| fails but should not report status to Request. EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _, _)).Times(0); - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } // |main_job| succeeds and should report status to Request. EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _)); @@ -2120,7 +2416,7 @@ // the alternative job fails on the default network and main job succeeds later. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterAltJobFailedOnDefaultNetwork) { - TestMainJobSucceedsAfterAltJobFailed(false); + TestMainJobSucceedsAfterAltJobFailed(false, false); } // This test verifies that the alternative service will be marked broken when @@ -2128,13 +2424,39 @@ // succeeds later. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterAltJobFailedOnBothNetworks) { - TestMainJobSucceedsAfterAltJobFailed(true); + TestMainJobSucceedsAfterAltJobFailed(true, false); +} + +// This test verifies that the alternative service will be marked broken when +// the alternative job fails on the default network and main job succeeds later. +// This test uses asynchronous Quic session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterAltJobFailedOnDefaultNetworkAsyncQuicSession) { + TestMainJobSucceedsAfterAltJobFailed(false, true); +} + +// This test verifies that the alternative service will be marked broken when +// the alternative job fails on both default and alternate networks and main job +// succeeds later. This test uses asynchronous Quic session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterAltJobFailedOnBothNetworksAsyncQuicSession) { + TestMainJobSucceedsAfterAltJobFailed(true, true); } void HttpStreamFactoryJobControllerTestBase:: TestMainJobSucceedsAfterIgnoredError(int net_error, + bool async_quic_session, bool expect_broken, std::string alternate_host) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddConnect(SYNCHRONOUS, net_error); tcp_data_ = std::make_unique<SequencedSocketData>(); @@ -2164,9 +2486,11 @@ // |alternative_job| fails but should not report status to Request. EXPECT_CALL(request_delegate_, OnStreamFailed(_, _, _, _, _)).Times(0); - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } // |main_job| succeeds and should report status to Request. EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _)); base::RunLoop().RunUntilIdle(); @@ -2185,27 +2509,60 @@ // then the alternative service is not marked as broken. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterConnectionChanged) { - TestMainJobSucceedsAfterIgnoredError(ERR_NETWORK_CHANGED); + TestMainJobSucceedsAfterIgnoredError(ERR_NETWORK_CHANGED, false); } // Verifies that if the alternative job fails due to a disconnected network, // then the alternative service is not marked as broken. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterInternetDisconnected) { - TestMainJobSucceedsAfterIgnoredError(ERR_INTERNET_DISCONNECTED); + TestMainJobSucceedsAfterIgnoredError(ERR_INTERNET_DISCONNECTED, false); +} + +// Verifies that if the alternative job fails due to a connection change event, +// then the alternative service is not marked as broken. This test uses +// asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterConnectionChangedAsyncQuicSession) { + TestMainJobSucceedsAfterIgnoredError(ERR_NETWORK_CHANGED, true); +} + +// Verifies that if the alternative job fails due to a disconnected network, +// then the alternative service is not marked as broken. This test uses +// asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterInternetDisconnectedAsyncQuicSession) { + TestMainJobSucceedsAfterIgnoredError(ERR_INTERNET_DISCONNECTED, true); } // Verifies that if the alternative job fails due to a DNS failure, // then the alternative service is not marked as broken. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterDnsFailure) { - TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED); + TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, false); +} + +// Verifies that if the alternative job fails due to a DNS failure, +// then the alternative service is not marked as broken. This test uses +// asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterDnsFailureAsyncQuicSession) { + TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, true); } // Verifies that if the alternative job fails due to a DNS failure on a // different name, then the alternative service is marked as broken. TEST_P(HttpStreamFactoryJobControllerTest, MainJobSucceedsAfterDnsFailureWithAlternateName) { - TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, true, + TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, false, true, + "alternate.google.com"); +} + +// Verifies that if the alternative job fails due to a DNS failure on a +// different name, then the alternative service is marked as broken. This test +// uses asynchronous QUIC session creation. +TEST_P(HttpStreamFactoryJobControllerTest, + MainJobSucceedsAfterDnsFailureWithAlternateNameAsyncQuicSession) { + TestMainJobSucceedsAfterIgnoredError(ERR_NAME_NOT_RESOLVED, true, true, "alternate.google.com"); } @@ -2258,7 +2615,17 @@ EXPECT_TRUE(HttpStreamFactoryPeer::IsJobControllerDeleted(factory_)); } -TEST_P(HttpStreamFactoryJobControllerTest, ResumeMainJobWhenAltJobStalls) { +void HttpStreamFactoryJobControllerTestBase::TestResumeMainJobWhenAltJobStalls( + bool async_quic_session) { + if (async_quic_session) { + feature_list_.Reset(); + std::vector<base::test::FeatureRef> enabled_features = { + features::kAsyncQuicSession}; + if (dns_https_alpn_enabled_) { + enabled_features.push_back(features::kUseDnsHttpsSvcbAlpn); + } + feature_list_.InitWithFeatures(enabled_features, {}); + } // Use COLD_START to stall alt job. quic_data_ = std::make_unique<MockQuicData>(version_); quic_data_->AddRead(SYNCHRONOUS, ERR_IO_PENDING); @@ -2284,16 +2651,26 @@ HttpStreamRequest::HTTP_STREAM, DEFAULT_PRIORITY); EXPECT_TRUE(job_controller_->main_job()); EXPECT_TRUE(job_controller_->alternative_job()); - - EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { - job_factory_.main_job()->DoResume(); - }); + if (async_quic_session) { + EXPECT_CALL(*job_factory_.main_job(), Resume()).Times(1).WillOnce([this]() { + job_factory_.main_job()->DoResume(); + }); + } // Alt job is stalled and main job should complete successfully. EXPECT_CALL(request_delegate_, OnStreamReadyImpl(_, _, _)); base::RunLoop().RunUntilIdle(); } +TEST_P(HttpStreamFactoryJobControllerTest, ResumeMainJobWhenAltJobStalls) { + TestResumeMainJobWhenAltJobStalls(false); +} + +TEST_P(HttpStreamFactoryJobControllerTest, + ResumeMainJobWhenAltJobStallsAsyncQuicSession) { + TestResumeMainJobWhenAltJobStalls(true); +} + TEST_P(HttpStreamFactoryJobControllerTest, InvalidPortForQuic) { HttpRequestInfo request_info; request_info.method = "GET"; @@ -2816,7 +3193,7 @@ // succeeded or failed at least once yet. EXPECT_EQ(job_controller_->get_main_job_wait_time_for_tests(), base::TimeDelta()); - EXPECT_TRUE(JobControllerPeer::main_job_is_blocked(job_controller_)); + EXPECT_FALSE(JobControllerPeer::main_job_is_blocked(job_controller_)); } // Check the case that while a preconnect is waiting in the H2 request queue, @@ -4270,12 +4647,10 @@ CheckJobsStatus(/*main_job_exists=*/true, /*alternative_job_exists=*/false, /*dns_alpn_h3_job_exists=*/true, "Main job and DNS ALPN job must be created."); - // `main_job` is blocked because we are waiting for quic session to be - // created. However `dns_alpn_h3_job` should not be waiting for dns host + // `dns_alpn_h3_job` should not be waiting for dns host // resolution as that was resolved synchronously. EXPECT_FALSE(job_controller_->dns_alpn_h3_job() ->expect_on_quic_host_resolution_for_tests()); - EXPECT_TRUE(job_controller_->main_job()->is_waiting()); base::HistogramTester histogram_tester; // Make |dns_alpn_h3_job| succeed.
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 9b387c1..854d315 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -194531,9 +194531,6 @@ { "name": "go.microsoft.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "airbnb.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "airbnb.tools", "policy": "custom", "mode": "force-https", "include_subdomains": true }, - { "name": "account.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, - { "name": "session.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, - { "name": "session.bbc.co.uk", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "bank.barclays.co.uk", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "www.raiffeisen.ch", "policy": "custom", "mode": "force-https", "include_subdomains": true }, { "name": "ebanking.raiffeisen.ch", "policy": "custom", "mode": "force-https", "include_subdomains": true }, @@ -194680,6 +194677,13 @@ "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "account.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "session.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "session.bbc.co.uk", "policy": "custom", "mode": "force-https", "include_subdomains": true }, + { "name": "bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": false }, + { "name": "www.bbc.com", "policy": "custom", "mode": "force-https", "include_subdomains": false }, + { "name": "bbc.co.uk", "policy": "custom", "mode": "force-https", "include_subdomains": false }, + { "name": "www.bbc.co.uk", "policy": "custom", "mode": "force-https", "include_subdomains": false }, // END OF MANUAL CUSTOM ENTRIES // eTLD owners who are working towards wide HSTS adoption can request to
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 59faad7..774b13d8 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -102,10 +102,12 @@ }; enum class JobProtocolErrorLocation { - kSessionStartReadingFailed = 0, - kCreateSessionFailed = 1, - kCryptoConnectFailedSync = 2, - kCryptoConnectFailedAsync = 3, + kSessionStartReadingFailedAsync = 0, + kSessionStartReadingFailedSync = 1, + kCreateSessionFailedAsync = 2, + kCreateSessionFailedSync = 3, + kCryptoConnectFailedSync = 4, + kCryptoConnectFailedAsync = 5, kMaxValue = kCryptoConnectFailedAsync, }; @@ -362,7 +364,8 @@ int DoResolveHost(); int DoResolveHostComplete(int rv); int DoCreateSession(); - int DoConnect(); + int DoCreateSessionComplete(int rv); + int DoConnect(int rv); int DoConnectComplete(int rv); int DoConfirmConnection(int rv); int DoValidateHost(); @@ -386,7 +389,10 @@ if (!host_resolution_finished_) { request->ExpectOnHostResolution(); } - if (!quic_session_created_) { + // Callers do not need to wait for OnQuicSessionCreationComplete if the + // kAsyncQuicSession flag is not set because session creation will be fully + // synchronous, so no need to call ExpectQuicSessionCreation. + if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { request->ExpectQuicSessionCreation(); } } @@ -423,6 +429,7 @@ STATE_RESOLVE_HOST, STATE_RESOLVE_HOST_COMPLETE, STATE_CREATE_SESSION, + STATE_CREATE_SESSION_COMPLETE, STATE_CONNECT, STATE_CONNECT_COMPLETE, STATE_HOST_VALIDATION, @@ -663,8 +670,11 @@ case STATE_CREATE_SESSION: rv = DoCreateSession(); break; + case STATE_CREATE_SESSION_COMPLETE: + rv = DoCreateSessionComplete(rv); + break; case STATE_CONNECT: - rv = DoConnect(); + rv = DoConnect(rv); break; case STATE_CONNECT_COMPLETE: rv = DoConnectComplete(rv); @@ -899,7 +909,7 @@ DCHECK(!session_); if (rv == ERR_QUIC_PROTOCOL_ERROR) { HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kCreateSessionFailed); + JobProtocolErrorLocation::kCreateSessionFailedAsync); } if (!create_session_on_stale_dns_) { MaybeOnQuicSessionCreationComplete(rv); @@ -911,18 +921,7 @@ DCHECK(session_); create_session_on_stale_dns_ = false; DVLOG(1) << "Created session on network: " << network_; - if (!session_->connection()->connected()) { - MaybeOnQuicSessionCreationComplete(ERR_CONNECTION_CLOSED); - return; - } - - session_->StartReading(); - if (!session_->connection()->connected()) { - HistogramProtocolErrorLocation( - JobProtocolErrorLocation::kSessionStartReadingFailed); - MaybeOnQuicSessionCreationComplete(ERR_QUIC_PROTOCOL_ERROR); - return; - } + io_state_ = STATE_CREATE_SESSION_COMPLETE; rv = DoLoop(rv); if (host_resolution_finished_) { @@ -969,25 +968,66 @@ quic_connection_start_time_ = base::TimeTicks::Now(); DCHECK(dns_resolution_end_time_ != base::TimeTicks()); - io_state_ = STATE_CONNECT; + io_state_ = STATE_CREATE_SESSION_COMPLETE; bool require_confirmation = was_alternative_service_recently_broken_; net_log_.AddEntryWithBoolParams( NetLogEventType::QUIC_STREAM_FACTORY_JOB_CONNECT, NetLogEventPhase::BEGIN, "require_confirmation", require_confirmation); DCHECK_NE(quic_version_used_, quic::ParsedQuicVersion::Unsupported()); - return factory_->CreateSession( - base::BindOnce(&QuicStreamFactory::Job::OnCreateSessionComplete, - GetWeakPtr()), + if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { + return factory_->CreateSessionAsync( + base::BindOnce(&QuicStreamFactory::Job::OnCreateSessionComplete, + GetWeakPtr()), + key_, quic_version_used_, cert_verify_flags_, require_confirmation, + endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_, + net_log_, &session_, &network_); + } + int rv = factory_->CreateSessionSync( key_, quic_version_used_, cert_verify_flags_, require_confirmation, endpoint_result_, dns_resolution_start_time_, dns_resolution_end_time_, net_log_, &session_, &network_); + + DVLOG(1) << "Created session on network: " << network_; + + if (rv == ERR_QUIC_PROTOCOL_ERROR) { + DCHECK(!session_); + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kCreateSessionFailedSync); + } + + return rv; +} +int QuicStreamFactory::Job::DoCreateSessionComplete(int rv) { + if (rv != OK) { + return rv; + } + io_state_ = STATE_CONNECT; + if (!session_->connection()->connected()) { + return ERR_CONNECTION_CLOSED; + } + + session_->StartReading(); + if (!session_->connection()->connected()) { + if (base::FeatureList::IsEnabled(net::features::kAsyncQuicSession)) { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kSessionStartReadingFailedAsync); + } else { + HistogramProtocolErrorLocation( + JobProtocolErrorLocation::kSessionStartReadingFailedSync); + } + return ERR_QUIC_PROTOCOL_ERROR; + } + return OK; } -int QuicStreamFactory::Job::DoConnect() { +int QuicStreamFactory::Job::DoConnect(int rv) { + if (rv != OK) { + return rv; + } DCHECK(session_); io_state_ = STATE_CONNECT_COMPLETE; - int rv = session_->CryptoConnect(base::BindOnce( + rv = session_->CryptoConnect(base::BindOnce( &QuicStreamFactory::Job::OnCryptoConnectComplete, GetWeakPtr())); if (!session_->connection()->connected() && @@ -1725,15 +1765,13 @@ socket->UseNonBlockingIO(); int rv; - if (params_.migrate_sessions_on_network_change_v2) { - // If caller leaves network unspecified, use current default network. - if (network == handles::kInvalidNetworkHandle) { - rv = socket->ConnectUsingDefaultNetwork(addr); - } else { - rv = socket->ConnectUsingNetwork(network, addr); - } - } else { + if (!params_.migrate_sessions_on_network_change_v2) { rv = socket->Connect(addr); + } else if (network == handles::kInvalidNetworkHandle) { + // If caller leaves network unspecified, use current default network. + rv = socket->ConnectUsingDefaultNetwork(addr); + } else { + rv = socket->ConnectUsingNetwork(network, addr); } if (rv != OK) { HistogramCreateSessionFailure(CREATION_ERROR_CONNECTING_SOCKET); @@ -2048,7 +2086,46 @@ return base::Contains(active_jobs_, session_key); } -int QuicStreamFactory::CreateSession( +int QuicStreamFactory::CreateSessionSync( + const QuicSessionAliasKey& key, + quic::ParsedQuicVersion quic_version, + int cert_verify_flags, + bool require_confirmation, + const HostResolverEndpointResult& endpoint_result, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + const NetLogWithSource& net_log, + QuicChromiumClientSession** session, + handles::NetworkHandle* network) { + TRACE_EVENT0(NetTracingCategory(), "QuicStreamFactory::CreateSession"); + // TODO(https://crbug.com/1416409): This logic only knows how to try one IP + // endpoint. + IPEndPoint addr = endpoint_result.ip_endpoints.front(); + std::unique_ptr<DatagramClientSocket> socket( + CreateSocket(net_log.net_log(), net_log.source())); + + // If migrate_sessions_on_network_change_v2 is on, passing in + // handles::kInvalidNetworkHandle will bind the socket to the default network. + int rv = ConfigureSocket(socket.get(), addr, *network, + key.session_key().socket_tag()); + if (rv != OK) { + return rv; + } + bool closed_during_initialize = CreateSessionHelper( + key, quic_version, cert_verify_flags, require_confirmation, + endpoint_result, dns_resolution_start_time, dns_resolution_end_time, + net_log, session, network, std::move(socket)); + if (closed_during_initialize) { + DLOG(DFATAL) << "Session closed during initialize"; + *session = nullptr; + + return ERR_CONNECTION_CLOSED; + } + + return OK; +} + +int QuicStreamFactory::CreateSessionAsync( CompletionOnceCallback callback, const QuicSessionAliasKey& key, quic::ParsedQuicVersion quic_version, @@ -2073,7 +2150,8 @@ require_confirmation, endpoint_result, dns_resolution_start_time, dns_resolution_end_time, net_log, session, network, std::move(socket)); - // Passing in handles::kInvalidNetworkHandle binds socket to default network. + // If migrate_sessions_on_network_change_v2 is on, passing in + // handles::kInvalidNetworkHandle will bind the socket to the default network. return ConnectAndConfigureSocket(std::move(connect_and_configure_callback), socket_ptr, addr, *network, key.session_key().socket_tag()); @@ -2097,6 +2175,33 @@ std::move(callback).Run(rv); return; } + bool closed_during_initialize = CreateSessionHelper( + key, quic_version, cert_verify_flags, require_confirmation, + endpoint_result, dns_resolution_start_time, dns_resolution_end_time, + net_log, session, network, std::move(socket)); + if (closed_during_initialize) { + DLOG(DFATAL) << "Session closed during initialize"; + *session = nullptr; + + std::move(callback).Run(ERR_CONNECTION_CLOSED); + return; + } + + std::move(callback).Run(OK); +} + +bool QuicStreamFactory::CreateSessionHelper( + const QuicSessionAliasKey& key, + quic::ParsedQuicVersion quic_version, + int cert_verify_flags, + bool require_confirmation, + const HostResolverEndpointResult& endpoint_result, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + const NetLogWithSource& net_log, + QuicChromiumClientSession** session, + handles::NetworkHandle* network, + std::unique_ptr<DatagramClientSocket> socket) { // TODO(https://crbug.com/1416409): This logic only knows how to try one IP // endpoint. IPEndPoint addr = endpoint_result.ip_endpoints.front(); @@ -2164,8 +2269,9 @@ // Wait for handshake confirmation before allowing streams to be created if // either this session or the factory require confirmation. - if (!is_quic_known_to_work_on_current_network_) + if (!is_quic_known_to_work_on_current_network_) { require_confirmation = true; + } *session = new QuicChromiumClientSession( connection, std::move(socket), this, quic_crypto_client_stream_factory_, @@ -2195,15 +2301,7 @@ !(*session)->connection()->connected(); UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.ClosedDuringInitializeSession", closed_during_initialize); - if (closed_during_initialize) { - DLOG(DFATAL) << "Session closed during initialize"; - *session = nullptr; - - std::move(callback).Run(ERR_CONNECTION_CLOSED); - return; - } - - std::move(callback).Run(OK); + return closed_during_initialize; } void QuicStreamFactory::ActivateSession(const QuicSessionAliasKey& key,
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index 672b949d..940c235 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -477,17 +477,27 @@ void OnJobComplete(Job* job, int rv); bool HasActiveSession(const QuicSessionKey& session_key) const; bool HasActiveJob(const QuicSessionKey& session_key) const; - int CreateSession(CompletionOnceCallback callback, - const QuicSessionAliasKey& key, - quic::ParsedQuicVersion quic_version, - int cert_verify_flags, - bool require_confirmation, - const HostResolverEndpointResult& endpoint_result, - base::TimeTicks dns_resolution_start_time, - base::TimeTicks dns_resolution_end_time, - const NetLogWithSource& net_log, - QuicChromiumClientSession** session, - handles::NetworkHandle* network); + int CreateSessionSync(const QuicSessionAliasKey& key, + quic::ParsedQuicVersion quic_version, + int cert_verify_flags, + bool require_confirmation, + const HostResolverEndpointResult& endpoint_result, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + const NetLogWithSource& net_log, + QuicChromiumClientSession** session, + handles::NetworkHandle* network); + int CreateSessionAsync(CompletionOnceCallback callback, + const QuicSessionAliasKey& key, + quic::ParsedQuicVersion quic_version, + int cert_verify_flags, + bool require_confirmation, + const HostResolverEndpointResult& endpoint_result, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + const NetLogWithSource& net_log, + QuicChromiumClientSession** session, + handles::NetworkHandle* network); void FinishCreateSession(CompletionOnceCallback callback, const QuicSessionAliasKey& key, quic::ParsedQuicVersion quic_version, @@ -501,6 +511,17 @@ handles::NetworkHandle* network, std::unique_ptr<DatagramClientSocket> socket, int rv); + bool CreateSessionHelper(const QuicSessionAliasKey& key, + quic::ParsedQuicVersion quic_version, + int cert_verify_flags, + bool require_confirmation, + const HostResolverEndpointResult& endpoint_result, + base::TimeTicks dns_resolution_start_time, + base::TimeTicks dns_resolution_end_time, + const NetLogWithSource& net_log, + QuicChromiumClientSession** session, + handles::NetworkHandle* network, + std::unique_ptr<DatagramClientSocket> socket); void ActivateSession(const QuicSessionAliasKey& key, QuicChromiumClientSession* session, std::set<std::string> dns_aliases);
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 5444a163..39863c4 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -288,6 +288,7 @@ } else { disabled_features.push_back(features::kPriorityIncremental); } + enabled_features.push_back(features::kAsyncQuicSession); scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); FLAGS_quic_enable_http3_grease_randomness = false; context_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1)); @@ -1012,7 +1013,9 @@ ::testing::ValuesIn(GetTestParams()), ::testing::PrintToStringParamName()); -TEST_P(QuicStreamFactoryTest, Create) { +TEST_P(QuicStreamFactoryTest, CreateSyncQuicSession) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); Initialize(); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); @@ -1067,7 +1070,98 @@ EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } -TEST_P(QuicStreamFactoryTest, CreateZeroRtt) { +TEST_P(QuicStreamFactoryTest, CreateAsyncQuicSession) { + Initialize(); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + EXPECT_EQ(DEFAULT_PRIORITY, host_resolver_->last_request_priority()); + + QuicStreamRequest request2(factory_.get()); + EXPECT_EQ(OK, + request2.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + // Will reset stream 3. + stream = CreateStream(&request2); + + EXPECT_TRUE(stream.get()); + + // TODO(rtenneti): We should probably have a tests that HTTP and HTTPS result + // in streams on different sessions. + QuicStreamRequest request3(factory_.get()); + EXPECT_EQ(OK, + request3.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + stream = CreateStream(&request3); // Will reset stream 5. + stream.reset(); // Will reset stream 7. + + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); +} + +// This test uses synchronous QUIC session creation +TEST_P(QuicStreamFactoryTest, SyncCreateZeroRtt) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); + Initialize(); + factory_->set_is_quic_known_to_work_on_current_network(true); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::ZERO_RTT); + host_resolver_->set_synchronous_mode(true); + host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + "192.168.0.1", ""); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(OK, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); +} + +TEST_P(QuicStreamFactoryTest, AsyncCreateZeroRtt) { Initialize(); factory_->set_is_quic_known_to_work_on_current_network(true); ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); @@ -1199,6 +1293,49 @@ } TEST_P(QuicStreamFactoryTest, RequireConfirmation) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::ZERO_RTT); + host_resolver_->set_synchronous_mode(true); + host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + "192.168.0.1", ""); + Initialize(); + factory_->set_is_quic_known_to_work_on_current_network(false); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + EXPECT_FALSE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); + + crypto_client_stream_factory_.last_stream() + ->NotifySessionOneRttKeyAvailable(); + + EXPECT_TRUE(http_server_properties_->HasLastLocalAddressWhenQuicWorked()); + + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + std::unique_ptr<HttpStream> stream = CreateStream(&request); + EXPECT_TRUE(stream.get()); + + QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_); + EXPECT_TRUE(session->require_confirmation()); +} + +TEST_P(QuicStreamFactoryTest, RequireConfirmationAsyncQuicSession) { crypto_client_stream_factory_.set_handshake_mode( MockCryptoClientStream::ZERO_RTT); host_resolver_->set_synchronous_mode(true); @@ -1911,8 +2048,8 @@ } TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithDifferentPins) { - base::test::ScopedFeatureList scoped_feature_list_; - scoped_feature_list_.InitAndEnableFeature( + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature( net::features::kStaticKeyPinningEnforcement); Initialize(); @@ -2163,7 +2300,10 @@ EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } -TEST_P(QuicStreamFactoryTest, ConnectErrorInCreate) { +// This test uses synchronous QUIC session creation. +TEST_P(QuicStreamFactoryTest, SyncConnectErrorInCreate) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); Initialize(); MockQuicData socket_data(version_); @@ -2185,7 +2325,69 @@ EXPECT_TRUE(socket_data.AllWriteDataConsumed()); } -TEST_P(QuicStreamFactoryTest, CancelCreate) { +TEST_P(QuicStreamFactoryTest, AsyncConnectErrorInCreate) { + Initialize(); + + MockQuicData socket_data(version_); + socket_data.AddConnect(SYNCHRONOUS, ERR_ADDRESS_IN_USE); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_ADDRESS_IN_USE)); + + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); +} + +// This test uses synchronous QUIC session creation. +TEST_P(QuicStreamFactoryTest, SyncCancelCreate) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); + Initialize(); + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + { + QuicStreamRequest request(factory_.get()); + EXPECT_EQ( + ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + } + + base::RunLoop().RunUntilIdle(); + + QuicStreamRequest request2(factory_.get()); + EXPECT_EQ(OK, + request2.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + std::unique_ptr<HttpStream> stream = CreateStream(&request2); + + EXPECT_TRUE(stream.get()); + stream.reset(); + + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); +} + +TEST_P(QuicStreamFactoryTest, AsyncCancelCreate) { Initialize(); MockQuicData socket_data(version_); socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); @@ -2296,7 +2498,9 @@ // report QUIC_HANDSHAKE_FAILED to upper layers. Subsequent // QuicStreamRequest should succeed without hanging. TEST_P(QuicStreamFactoryTest, - WriteErrorInCryptoConnectWithAsyncHostResolution) { + WriteErrorInCryptoConnectWithAsyncHostResolutionSyncSessionCreation) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); Initialize(); // Use unmocked crypto stream to do crypto connect. crypto_client_stream_factory_.set_handshake_mode( @@ -2362,7 +2566,146 @@ EXPECT_TRUE(socket_data2.AllWriteDataConsumed()); } -TEST_P(QuicStreamFactoryTest, WriteErrorInCryptoConnectWithSyncHostResolution) { +TEST_P(QuicStreamFactoryTest, + WriteErrorInCryptoConnectWithAsyncHostResolutionAsyncSessionCreation) { + Initialize(); + // Use unmocked crypto stream to do crypto connect. + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::COLD_START_WITH_CHLO_SENT); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + // Trigger PACKET_WRITE_ERROR when sending packets in crypto connect. + socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + // Create request, should fail after the write of the CHLO fails. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult()); + EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + + // Verify new requests can be sent normally without hanging. + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::COLD_START); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + client_maker_.Reset(); + MockQuicData socket_data2(version_); + socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data2.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request2(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request2.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + // Run the message loop to complete host resolution. + base::RunLoop().RunUntilIdle(); + + // Complete handshake. QuicStreamFactory::Job should complete and succeed. + crypto_client_stream_factory_.last_stream() + ->NotifySessionOneRttKeyAvailable(); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + + // Create QuicHttpStream. + std::unique_ptr<HttpStream> stream = CreateStream(&request2); + EXPECT_TRUE(stream.get()); + stream.reset(); + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + EXPECT_TRUE(socket_data2.AllReadDataConsumed()); + EXPECT_TRUE(socket_data2.AllWriteDataConsumed()); +} + +TEST_P(QuicStreamFactoryTest, + WriteErrorInCryptoConnectWithSyncHostResolutionSyncQuicSession) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); + Initialize(); + // Use unmocked crypto stream to do crypto connect. + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::COLD_START_WITH_CHLO_SENT); + host_resolver_->set_synchronous_mode(true); + host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), + "192.168.0.1", ""); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + // Trigger PACKET_WRITE_ERROR when sending packets in crypto connect. + socket_data.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE); + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + // Create request, should fail immediately. + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + // Check no active session, or active jobs left for this server. + EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + + // Verify new requests can be sent normally without hanging. + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::COLD_START); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + client_maker_.Reset(); + MockQuicData socket_data2(version_); + socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + socket_data2.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request2(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request2.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + EXPECT_FALSE(HasActiveSession(scheme_host_port_)); + EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_)); + + base::RunLoop().RunUntilIdle(); + // Complete handshake. + crypto_client_stream_factory_.last_stream() + ->NotifySessionOneRttKeyAvailable(); + EXPECT_THAT(callback_.WaitForResult(), IsOk()); + EXPECT_TRUE(HasActiveSession(scheme_host_port_)); + EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_)); + + // Create QuicHttpStream. + std::unique_ptr<HttpStream> stream = CreateStream(&request2); + EXPECT_TRUE(stream.get()); + stream.reset(); + EXPECT_TRUE(socket_data.AllReadDataConsumed()); + EXPECT_TRUE(socket_data.AllWriteDataConsumed()); + EXPECT_TRUE(socket_data2.AllReadDataConsumed()); + EXPECT_TRUE(socket_data2.AllWriteDataConsumed()); +} + +TEST_P(QuicStreamFactoryTest, + WriteErrorInCryptoConnectWithSyncHostResolutionAsyncQuicSession) { Initialize(); // Use unmocked crypto stream to do crypto connect. crypto_client_stream_factory_.set_handshake_mode( @@ -2495,7 +2838,74 @@ // Regression test for b/267653996. Sets up dns race with stale session waiting // on CryptoConnect. Forces job to retry on alternate network before the // handshake and then disconnects the idle network. -TEST_P(QuicStreamFactoryTest, OnIdleNetworkDetected) { +TEST_P(QuicStreamFactoryTest, OnIdleNetworkDetectedSyncQuicSession) { + if (!version_.UsesTls()) { + return; + } + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(net::features::kAsyncQuicSession); + quic_params_->race_stale_dns_on_connection = true; + quic_params_->retry_on_alternate_network_before_handshake = true; + host_resolver_ = std::make_unique<MockCachingHostResolver>(); + InitializeConnectionMigrationV2Test( + {kDefaultNetworkForTests, kNewNetworkForTests}); + ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails(); + crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details); + + client_maker_.SetEncryptionLevel(quic::ENCRYPTION_ZERO_RTT); + crypto_client_stream_factory_.set_handshake_mode( + MockCryptoClientStream::ASYNC_ZERO_RTT); + + host_resolver_->set_ondemand_mode(true); + host_resolver_->rules()->AddRule(scheme_host_port_.host(), kCachedIPAddress); + host_resolver_->LoadIntoCache(scheme_host_port_, NetworkAnonymizationKey(), + /*optional_parameters=*/absl::nullopt); + + // Expire the cache + host_resolver_->GetHostCache()->Invalidate(); + + MockQuicData socket_data(version_); + socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + if (VersionUsesHttp3(version_.transport_version)) { + socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + } + socket_data.AddSocketDataToFactory(socket_factory_.get()); + + MockQuicData socket_data1(version_); + socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); + if (VersionUsesHttp3(version_.transport_version)) { + socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket()); + } + socket_data1.AddSocketDataToFactory(socket_factory_.get()); + + QuicStreamRequest request(factory_.get()); + EXPECT_EQ(ERR_IO_PENDING, + request.Request( + scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, + SocketTag(), NetworkAnonymizationKey(), SecureDnsPolicy::kAllow, + /*use_dns_aliases=*/true, /*require_dns_https_alpn=*/false, + /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_, + failed_on_default_network_callback_, callback_.callback())); + + TestCompletionCallback host_resolution_callback; + EXPECT_TRUE( + request.WaitForHostResolution(host_resolution_callback.callback())); + + base::RunLoop().RunUntilIdle(); + host_resolver_->ResolveAllPending(); + base::RunLoop().RunUntilIdle(); + crypto_client_stream_factory_.last_stream()->NotifySessionZeroRttComplete(); + EXPECT_FALSE( + crypto_client_stream_factory_.last_stream()->one_rtt_keys_available()); + quic::QuicServerId server_id(scheme_host_port_.host(), + scheme_host_port_.port(), false); + EXPECT_TRUE(HasLiveSession(scheme_host_port_)); + QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_); + session->connection()->OnIdleNetworkDetected(); +} + +TEST_P(QuicStreamFactoryTest, OnIdleNetworkDetectedAsyncQuicSession) { if (!version_.UsesTls()) { return; }
diff --git a/sandbox/linux/syscall_broker/broker_file_permission.h b/sandbox/linux/syscall_broker/broker_file_permission.h index 8878f56..f4f3aa0 100644 --- a/sandbox/linux/syscall_broker/broker_file_permission.h +++ b/sandbox/linux/syscall_broker/broker_file_permission.h
@@ -107,6 +107,16 @@ kBlockInotifyAddWatchWithIntermediates); } + static BrokerFilePermission AllPermissionsRecursive(const std::string& path) { + return BrokerFilePermission( + path, RecursionOption::kRecursive, PersistenceOption::kPermanent, + ReadPermission::kAllowRead, WritePermission::kAllowWrite, + CreatePermission::kAllowCreate, + StatWithIntermediatesPermission::kAllowStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kAllowInotifyAddWatchWithIntermediates); + } + // Temporary files must always be newly created and do not confer rights to // use pre-existing files of the same name. static BrokerFilePermission ReadWriteCreateTemporary(
diff --git a/services/network/network_sandbox_hook_linux.cc b/services/network/network_sandbox_hook_linux.cc index 188a8aca..47f5667 100644 --- a/services/network/network_sandbox_hook_linux.cc +++ b/services/network/network_sandbox_hook_linux.cc
@@ -23,12 +23,12 @@ sandbox::syscall_broker::COMMAND_RMDIR, sandbox::syscall_broker::COMMAND_STAT, sandbox::syscall_broker::COMMAND_UNLINK, + sandbox::syscall_broker::COMMAND_INOTIFY_ADD_WATCH, }); } std::vector<BrokerFilePermission> GetNetworkFilePermissions() { - // TODO(tsepez): remove universal permission under filesystem root. - return {BrokerFilePermission::ReadWriteCreateRecursive("/")}; + return {BrokerFilePermission::AllPermissionsRecursive("/")}; } bool NetworkPreSandboxHook(sandbox::policy::SandboxLinux::Options options) { @@ -38,7 +38,6 @@ GetNetworkBrokerCommandSet(), GetNetworkFilePermissions(), sandbox::policy::SandboxLinux::PreSandboxHook(), options); - instance->EngageNamespaceSandboxIfPossible(); return true; }
diff --git a/services/network/network_service_memory_cache.h b/services/network/network_service_memory_cache.h index de1b973..e561109 100644 --- a/services/network/network_service_memory_cache.h +++ b/services/network/network_service_memory_cache.h
@@ -19,6 +19,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "net/cookies/cookie_partition_key.h" +#include "services/network/public/mojom/client_security_state.mojom-forward.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/public/mojom/url_loader_completion_status.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h"
diff --git a/services/network/public/cpp/data_element.h b/services/network/public/cpp/data_element.h index dc3d8ee..a3a6c1ba 100644 --- a/services/network/public/cpp/data_element.h +++ b/services/network/public/cpp/data_element.h
@@ -22,7 +22,7 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/chunked_data_pipe_getter.mojom-forward.h" #include "services/network/public/mojom/data_pipe_getter.mojom-forward.h" -#include "services/network/public/mojom/url_loader.mojom-shared.h" +#include "services/network/public/mojom/url_request.mojom-shared.h" #include "third_party/abseil-cpp/absl/types/variant.h" namespace network {
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom index af07d51e..6246d09 100644 --- a/services/network/public/mojom/url_loader.mojom +++ b/services/network/public/mojom/url_loader.mojom
@@ -5,24 +5,11 @@ module network.mojom; import "mojo/public/mojom/base/big_buffer.mojom"; -import "services/network/public/mojom/url_loader_network_service_observer.mojom"; -import "services/network/public/mojom/client_security_state.mojom"; -import "services/network/public/mojom/cors.mojom"; -import "services/network/public/mojom/cookie_access_observer.mojom"; -import "services/network/public/mojom/chunked_data_pipe_getter.mojom"; -import "services/network/public/mojom/data_pipe_getter.mojom"; import "services/network/public/mojom/early_hints.mojom"; -import "services/network/public/mojom/fetch_api.mojom"; import "services/network/public/mojom/http_request_headers.mojom"; -import "services/network/public/mojom/isolation_info.mojom"; -import "services/network/public/mojom/network_param.mojom"; import "services/network/public/mojom/request_priority.mojom"; -import "services/network/public/mojom/site_for_cookies.mojom"; -import "services/network/public/mojom/trust_tokens.mojom"; import "services/network/public/mojom/url_loader_completion_status.mojom"; -import "services/network/public/mojom/url_request.mojom"; import "services/network/public/mojom/url_response_head.mojom"; -import "services/network/public/mojom/web_bundle_handle.mojom"; import "url/mojom/url.mojom"; [Native]
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json index 9b9e7bd..ea3e5e5 100644 --- a/testing/buildbot/chromium.chromiumos.json +++ b/testing/buildbot/chromium.chromiumos.json
@@ -1661,7 +1661,7 @@ "bucket": "chromiumos-image-archive", "cros_board": "jacuzzi", "cros_img": "jacuzzi-public/R109-15222.0.0", - "name": "lacros_all_tast_tests JACUZZI_PUBLIC", + "name": "lacros_all_tast_tests JACUZZI_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -1671,7 +1671,7 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "JACUZZI_PUBLIC" + "variant_id": "JACUZZI_PUBLIC_LKGM" } ] }, @@ -1690,7 +1690,7 @@ "bucket": "chromiumos-image-archive", "cros_board": "kevin", "cros_img": "kevin64-public/R109-15222.0.0", - "name": "lacros_all_tast_tests KEVIN_PUBLIC", + "name": "lacros_all_tast_tests KEVIN_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -1700,7 +1700,7 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "KEVIN_PUBLIC" + "variant_id": "KEVIN_PUBLIC_LKGM" } ] },
diff --git a/testing/buildbot/chromium.dev.json b/testing/buildbot/chromium.dev.json index f92365903..1fa5dca 100644 --- a/testing/buildbot/chromium.dev.json +++ b/testing/buildbot/chromium.dev.json
@@ -1,7 +1,7 @@ { "AAAAA1 AUTOGENERATED FILE DO NOT EDIT": {}, "AAAAA2 See generate_buildbot_json.py to make changes": {}, - "android-pie-arm64-rel-swarming": { + "android-pie-arm64-rel-dev": { "gtest_tests": [ { "args": [ @@ -50,7 +50,7 @@ } ] }, - "linux-rel-swarming": { + "linux-rel-dev": { "gtest_tests": [ { "merge": { @@ -183,8 +183,8 @@ } ] }, - "linux-ssd-rel-swarming": {}, - "mac-arm-rel-swarming": { + "linux-ssd-rel-dev": {}, + "mac-arm-rel-dev": { "gtest_tests": [ { "merge": { @@ -296,7 +296,7 @@ } ] }, - "mac-rel-swarming": { + "mac-rel-dev": { "gtest_tests": [ { "merge": { @@ -409,7 +409,7 @@ } ] }, - "win-rel-swarming": { + "win-rel-dev": { "gtest_tests": [ { "merge": { @@ -485,7 +485,7 @@ } ] }, - "win11-rel-swarming": { + "win11-rel-dev": { "gtest_tests": [ { "merge": {
diff --git a/testing/buildbot/chromium.fuchsia.fyi.json b/testing/buildbot/chromium.fuchsia.fyi.json index 57198ec..2419717 100644 --- a/testing/buildbot/chromium.fuchsia.fyi.json +++ b/testing/buildbot/chromium.fuchsia.fyi.json
@@ -3663,6 +3663,175 @@ } ] }, + "fuchsia-fyi-x64-dbg-persistent-emulator": { + "additional_compile_targets": [ + "all" + ], + "gtest_tests": [ + { + "args": [ + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "aura_unittests", + "test_id_prefix": "ninja://ui/aura:aura_unittests/" + }, + { + "args": [ + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "blink_common_unittests", + "test_id_prefix": "ninja://third_party/blink/common:blink_common_unittests/" + }, + { + "args": [ + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "courgette_unittests", + "test_id_prefix": "ninja://courgette:courgette_unittests/" + }, + { + "args": [ + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "crypto_unittests", + "test_id_prefix": "ninja://crypto:crypto_unittests/" + }, + { + "args": [ + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "filesystem_service_unittests", + "test_id_prefix": "ninja://components/services/filesystem:filesystem_service_unittests/" + }, + { + "args": [ + "--test-arg=--vmodule=test_navigation_listener=1", + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "web_engine_integration_tests", + "test_id_prefix": "ninja://fuchsia_web/webengine:web_engine_integration_tests/" + }, + { + "args": [ + "--everlasting" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "machine_type": "e2-standard-2", + "os": "Ubuntu-18.04", + "pool": "chromium.tests.fuchsia" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" + }, + "test": "web_engine_unittests", + "test_id_prefix": "ninja://fuchsia_web/webengine:web_engine_unittests/" + } + ] + }, "fuchsia-x64-chrome-rel": { "gtest_tests": [ {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 9c7680d..fd8b71315 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -45227,7 +45227,7 @@ "bucket": "chromiumos-image-archive", "cros_board": "octopus", "cros_img": "octopus-public/R109-15222.0.0", - "name": "lacros_all_tast_tests OCTOPUS_FULL", + "name": "lacros_all_tast_tests OCTOPUS_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45237,14 +45237,14 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "OCTOPUS_FULL" + "variant_id": "OCTOPUS_PUBLIC_LKGM" }, { "args": [], "bucket": "chromiumos-image-archive", "cros_board": "eve", "cros_img": "eve-public/R109-15222.0.0", - "name": "lacros_all_tast_tests EVE_FULL", + "name": "lacros_all_tast_tests EVE_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45254,7 +45254,7 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "EVE_FULL" + "variant_id": "EVE_PUBLIC_LKGM" } ] }, @@ -45268,7 +45268,7 @@ "bucket": "chromiumos-image-archive", "cros_board": "jacuzzi", "cros_img": "jacuzzi-public/R109-15222.0.0", - "name": "lacros_all_tast_tests JACUZZI_PUBLIC", + "name": "lacros_all_tast_tests JACUZZI_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45278,14 +45278,14 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "JACUZZI_PUBLIC" + "variant_id": "JACUZZI_PUBLIC_LKGM" }, { "args": [], "bucket": "chromiumos-image-archive", "cros_board": "kevin", "cros_img": "kevin64-public/R109-15222.0.0", - "name": "lacros_all_tast_tests KEVIN_PUBLIC", + "name": "lacros_all_tast_tests KEVIN_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45295,7 +45295,7 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "KEVIN_PUBLIC" + "variant_id": "KEVIN_PUBLIC_LKGM" } ] }, @@ -45309,7 +45309,7 @@ "bucket": "chromiumos-image-archive", "cros_board": "jacuzzi", "cros_img": "jacuzzi-public/R109-15222.0.0", - "name": "lacros_all_tast_tests JACUZZI_PUBLIC", + "name": "lacros_all_tast_tests JACUZZI_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45319,14 +45319,14 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "JACUZZI_PUBLIC" + "variant_id": "JACUZZI_PUBLIC_LKGM" }, { "args": [], "bucket": "chromiumos-image-archive", "cros_board": "jacuzzi", "cros_img": "jacuzzi-public/R109-15222.0.0", - "name": "lacros_all_tast_tests JACUZZI_CQ_PUBLIC", + "name": "lacros_all_tast_tests JACUZZI_CQ_PUBLIC_LKGM", "public_builder": "cros_test_platform_public", "public_builder_bucket": "testplatform-public", "resultdb": { @@ -45338,14 +45338,14 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "JACUZZI_CQ_PUBLIC" + "variant_id": "JACUZZI_CQ_PUBLIC_LKGM" }, { "args": [], "bucket": "chromiumos-image-archive", "cros_board": "kevin", "cros_img": "kevin64-public/R109-15222.0.0", - "name": "lacros_all_tast_tests KEVIN_PUBLIC", + "name": "lacros_all_tast_tests KEVIN_PUBLIC_LKGM", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45355,7 +45355,7 @@ "test": "lacros_all_tast_tests", "test_id_prefix": "ninja://chromeos/lacros:lacros_all_tast_tests/", "timeout_sec": 10800, - "variant_id": "KEVIN_PUBLIC" + "variant_id": "KEVIN_PUBLIC_LKGM" } ] },
diff --git a/testing/buildbot/chromium.reclient.fyi.json b/testing/buildbot/chromium.reclient.fyi.json index b90b2f81..1b97e04 100644 --- a/testing/buildbot/chromium.reclient.fyi.json +++ b/testing/buildbot/chromium.reclient.fyi.json
@@ -6,6 +6,11 @@ "all" ] }, + "Comparison Linux (reclient vs reclient remote links)(compression)": { + "additional_compile_targets": [ + "all" + ] + }, "Comparison Linux (reclient vs reclient remote links)(small)": { "additional_compile_targets": [ "all"
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 8ba4bde3..c3d950b 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -546,6 +546,13 @@ ], }, }, + 'fuchsia-persistent-emulator': { + '$mixin_append': { + 'args': [ + '--everlasting' + ], + }, + }, 'fuchsia_logs': { '$mixin_append': { 'args': [
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index d2bffec..b0825289 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1454,7 +1454,7 @@ ], 'ci_only': True, # https://crbug.com/1233700 }, - 'android-pie-arm64-rel-swarming': { + 'android-pie-arm64-rel-dev': { 'swarming': { 'service_account': 'chrome-gold-dev@chops-service-accounts.iam.gserviceaccount.com' }, @@ -2052,7 +2052,7 @@ }, }, # https://crbug.com/1255940 - 'mac-rel-swarming': { + 'mac-rel-dev': { 'swarming': { 'dimension_sets': [ { @@ -3935,7 +3935,7 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/android.asan.unit_tests.filter', ], }, - 'android-pie-arm64-rel-swarming': { + 'android-pie-arm64-rel-dev': { 'swarming': { 'shards': 8, },
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index e89e6a6..9f877d2 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -2598,6 +2598,24 @@ }, }, + # This is a set of selected tests to test the test facility only. The + # principle of the selection includes time cost, scenario coverage, + # stability, etc; and it's subject to change. In theory, it should only be + # used by the EngProd team to verify a new test facility setup. + 'fuchsia_facility_gtests': { + 'aura_unittests': {}, + 'blink_common_unittests': {}, + 'courgette_unittests': {}, + 'crypto_unittests': {}, + 'filesystem_service_unittests': {}, + 'web_engine_integration_tests': { + 'args': [ + '--test-arg=--vmodule=test_navigation_listener=1', + ], + }, + 'web_engine_unittests': {}, + }, + 'fuchsia_sizes_tests': { 'fuchsia_sizes': { 'merge': { @@ -7391,8 +7409,8 @@ 'lacros_amd64_generic_rel_skylab_fyi': { 'lacros_skylab_tests': { 'variants': [ - 'CROS_OCTOPUS_FULL', - 'CROS_EVE_FULL', + 'CROS_OCTOPUS_PUBLIC_LKGM', + 'CROS_EVE_PUBLIC_LKGM', ] }, }, @@ -7400,7 +7418,7 @@ 'lacros_arm64_generic_rel_skylab': { 'lacros_skylab_tests': { 'variants': [ - 'CROS_KEVIN_PUBLIC', + 'CROS_KEVIN_PUBLIC_LKGM', ] }, }, @@ -7408,9 +7426,9 @@ 'lacros_arm64_generic_rel_skylab_fyi': { 'lacros_skylab_tests': { 'variants': [ - 'CROS_JACUZZI_PUBLIC', - 'CROS_JACUZZI_CQ_PUBLIC', - 'CROS_KEVIN_PUBLIC', + 'CROS_JACUZZI_PUBLIC_LKGM', + 'CROS_JACUZZI_CQ_PUBLIC_LKGM', + 'CROS_KEVIN_PUBLIC_LKGM', ] }, }, @@ -7418,7 +7436,7 @@ 'lacros_arm_generic_rel_skylab': { 'lacros_skylab_tests': { 'variants': [ - 'CROS_JACUZZI_PUBLIC', + 'CROS_JACUZZI_PUBLIC_LKGM', ] }, }, @@ -7426,8 +7444,8 @@ 'lacros_arm_generic_rel_skylab_fyi': { 'lacros_skylab_tests': { 'variants': [ - 'CROS_JACUZZI_PUBLIC', - 'CROS_KEVIN_PUBLIC', + 'CROS_JACUZZI_PUBLIC_LKGM', + 'CROS_KEVIN_PUBLIC_LKGM', ] }, },
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 0778a21..212cfb68 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -524,7 +524,7 @@ 'enabled': True, 'identifier': 'EVE_RELEASE_STABLE', }, - 'CROS_EVE_FULL': { + 'CROS_EVE_PUBLIC_LKGM': { 'skylab': { 'cros_board': 'eve', 'cros_chrome_version': '109.0.5367.0', @@ -532,7 +532,7 @@ 'bucket': 'chromiumos-image-archive', }, 'enabled': True, - 'identifier': 'EVE_FULL', + 'identifier': 'EVE_PUBLIC_LKGM', }, 'CROS_HANA_RELEASE_LKGM': { 'skylab': { @@ -615,7 +615,7 @@ 'enabled': True, 'identifier': 'JACUZZI_RELEASE_STABLE', }, - 'CROS_JACUZZI_PUBLIC': { + 'CROS_JACUZZI_PUBLIC_LKGM': { 'skylab': { 'cros_board': 'jacuzzi', 'cros_chrome_version': '109.0.5367.0', @@ -623,9 +623,9 @@ 'bucket': 'chromiumos-image-archive', }, 'enabled': True, - 'identifier': 'JACUZZI_PUBLIC', + 'identifier': 'JACUZZI_PUBLIC_LKGM', }, - 'CROS_JACUZZI_CQ_PUBLIC': { + 'CROS_JACUZZI_CQ_PUBLIC_LKGM': { 'skylab': { 'cros_board': 'jacuzzi', 'cros_chrome_version': '109.0.5367.0', @@ -635,9 +635,9 @@ 'public_builder_bucket': 'testplatform-public', }, 'enabled': True, - 'identifier': 'JACUZZI_CQ_PUBLIC', + 'identifier': 'JACUZZI_CQ_PUBLIC_LKGM', }, - 'CROS_KEVIN_PUBLIC': { + 'CROS_KEVIN_PUBLIC_LKGM': { 'skylab': { 'cros_board': 'kevin', 'cros_chrome_version': '109.0.5367.0', @@ -645,9 +645,9 @@ 'bucket': 'chromiumos-image-archive', }, 'enabled': True, - 'identifier': 'KEVIN_PUBLIC', + 'identifier': 'KEVIN_PUBLIC_LKGM', }, - 'CROS_OCTOPUS_FULL': { + 'CROS_OCTOPUS_PUBLIC_LKGM': { 'skylab': { 'cros_board': 'octopus', 'cros_chrome_version': '109.0.5367.0', @@ -655,7 +655,7 @@ 'bucket': 'chromiumos-image-archive', }, 'enabled': True, - 'identifier': 'OCTOPUS_FULL', + 'identifier': 'OCTOPUS_PUBLIC_LKGM', }, 'CROS_OCTOPUS_RELEASE_CHROME_FROM_TLS_LKGM': { 'skylab': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 22d51a6..09e5320 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2577,7 +2577,7 @@ 'name': 'chromium.dev', 'mixins': ['chromium-tester-dev-service-account'], 'machines': { - 'android-pie-arm64-rel-swarming': { + 'android-pie-arm64-rel-dev': { 'mixins': [ 'has_native_resultdb_integration', 'pie_fleet', @@ -2596,7 +2596,7 @@ }, 'os_type': 'android', }, - 'linux-rel-swarming': { + 'linux-rel-dev': { 'mixins': [ 'linux-bionic', ], @@ -2604,12 +2604,12 @@ 'gtest_tests': 'chromium_dev_linux_gtests', }, }, - 'linux-ssd-rel-swarming': { + 'linux-ssd-rel-dev': { 'mixins': [ 'linux-bionic', ], }, - 'mac-arm-rel-swarming': { + 'mac-arm-rel-dev': { 'mixins': [ 'mac_12_arm64', ], @@ -2617,7 +2617,7 @@ 'gtest_tests': 'chromium_dev_desktop_gtests', }, }, - 'mac-rel-swarming': { + 'mac-rel-dev': { 'mixins': [ 'mac_x64', ], @@ -2625,12 +2625,12 @@ 'gtest_tests': 'chromium_dev_desktop_gtests', }, }, - 'win-rel-swarming': { + 'win-rel-dev': { 'test_suites': { 'gtest_tests': 'chromium_dev_desktop_gtests', }, }, - 'win11-rel-swarming': { + 'win11-rel-dev': { 'mixins': [ 'win11', ], @@ -2806,6 +2806,29 @@ 'isolated_scripts': 'gpu_angle_fuchsia_unittests_isolated_scripts', }, }, + 'fuchsia-fyi-x64-dbg-persistent-emulator' : { + 'additional_compile_targets': [ + 'all', + ], + 'browser_config': 'web-engine-shell', + 'os_type': 'fuchsia', + 'mixins': [ + 'fuchsia-persistent-emulator', + 'linux-bionic', + ], + 'swarming': { + 'dimension_sets': [ + { + 'kvm': '1', + 'machine_type': 'e2-standard-2', + 'pool': 'chromium.tests.fuchsia', + }, + ], + }, + 'test_suites': { + 'gtest_tests': 'fuchsia_facility_gtests', + }, + }, 'fuchsia-x64-chrome-rel': { 'browser_config': 'fuchsia-chrome', 'os_type': 'fuchsia', @@ -5366,6 +5389,14 @@ 'all' ], }, + 'Comparison Linux (reclient vs reclient remote links)(compression)': { + 'mixins': [ + 'isolate_profile_data', + ], + 'additional_compile_targets': [ + 'all' + ], + }, 'Comparison Linux (reclient vs reclient remote links)(small)': { 'mixins': [ 'isolate_profile_data',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 50f85b4..d0e8f57c 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -976,6 +976,28 @@ ] } ], + "AutofillEnableCardArtAndCardProductName": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillEnableCardArtImage", + "AutofillEnableCardProductName", + "AutofillEnableVirtualCardMetadata" + ] + } + ] + } + ], "AutofillEnableLabelPrecedenceForTurkishAddresses": [ { "platforms": [ @@ -10609,6 +10631,31 @@ ] } ], + "RenderBlockingFonts": [ + { + "platforms": [ + "android", + "android_webview", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "EnabledWith1000BlockingAnd100Delay", + "params": { + "max-blocking-time": "1000", + "max-fcp-delay": "100" + }, + "enable_features": [ + "RenderBlockingFonts" + ] + } + ] + } + ], "ReportCertificateErrors": [ { "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 341a804..57dec7b3 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -287,6 +287,11 @@ "fledge_extensions_enabled", /*default_value=*/false}; +// Maximum budget allowed to be claimed per-origin per-day per-API. See +// `content::PrivateAggregationBudgeter` for more detail. +constexpr base::FeatureParam<int> kPrivateAggregationApiMaxBudgetPerScope{ + &kPrivateAggregationApi, "max_budget_per_scope", /*default_value=*/65536}; + // Enable the shared storage API. Note that enabling this feature does not // automatically expose this API to the web, it only allows the element to be // enabled by the runtime enabled feature, for origin trials.
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index da86eb4..8280f637 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -83,6 +83,8 @@ kPrivateAggregationApiEnabledInFledge; BLINK_COMMON_EXPORT extern const base::FeatureParam<bool> kPrivateAggregationApiFledgeExtensionsEnabled; +BLINK_COMMON_EXPORT extern const base::FeatureParam<int> + kPrivateAggregationApiMaxBudgetPerScope; enum class SharedStorageWorkletImplementationType { // The worklet thread is created via base::SequenceBound, and JS bindings are
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 883dd157..c8d0e1d 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -8984,6 +8984,7 @@ cache_storage interest_groups shared_storage + storage_buckets all other @@ -9119,6 +9120,23 @@ # SharedStorageAccessType.workletSet. optional boolean ignoreIfPresent + type StorageBucketsDurability extends string + enum + relaxed + strict + + type StorageBucketInfo extends object + properties + SerializedStorageKey storageKey + string id + string name + boolean isDefault + Network.TimeSinceEpoch expiration + # Storage quota (bytes). + number quota + boolean persistent + StorageBucketsDurability durability + # Returns a storage key given a frame id. command getStorageKeyForFrame parameters @@ -9315,6 +9333,18 @@ parameters boolean enable + # Set tracking for a storage key's buckets. + experimental command setStorageBucketTracking + parameters + string storageKey + boolean enable + + # Deletes the Storage Bucket with the given storage key and bucket name. + experimental command deleteStorageBucket + parameters + string storageKey + string bucketName + # A cache's contents have been modified. event cacheStorageContentUpdated parameters @@ -9377,6 +9407,14 @@ # presence/absence depends on `type`. SharedStorageAccessParams params + event storageBucketCreatedOrUpdated + parameters + StorageBucketInfo bucket + + event storageBucketDeleted + parameters + string bucketId + # The SystemInfo domain defines methods and events for querying low-level system information. experimental domain SystemInfo @@ -10951,6 +10989,10 @@ parameters string dialogId array of Account accounts + # These exist primarily so that the caller can verify the + # RP context was used appropriately. + string title + optional string subtitle command enable parameters
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom index 924799a..bf2bcf1 100644 --- a/third_party/blink/public/mojom/frame/frame.mojom +++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -995,6 +995,10 @@ string normalized_server_timing, network.mojom.URLLoaderCompletionStatus completion_status ); + + // The browser requests the renderer to fullscreen the document element. + // See: https://chromestatus.com/feature/6002307972464640 + RequestFullscreenDocumentElement(); }; // Also implemented in Blink, this interface defines frame-specific methods
diff --git a/third_party/blink/public/mojom/navigation/navigation_params.mojom b/third_party/blink/public/mojom/navigation/navigation_params.mojom index 5200d8d..cb373f2 100644 --- a/third_party/blink/public/mojom/navigation/navigation_params.mojom +++ b/third_party/blink/public/mojom/navigation/navigation_params.mojom
@@ -167,6 +167,10 @@ // navigations should create a resource timing entry. // TODO(https://github.com/whatwg/html/issues/8846): clarify this further. bool is_container_initiated = false; + + // True if the initiator requested the tab become fullscreen after navigation. + // See: https://chromestatus.com/feature/6002307972464640 + bool is_fullscreen_requested = false; }; // Provided by the browser or the renderer -------------------------------------
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom index df19a8b7..11c77e9 100644 --- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom +++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -3863,6 +3863,9 @@ kHtmlClipboardApiUnsanitizedRead = 4522, kHtmlClipboardApiUnsanitizedWrite = 4523, kAsyncClipboardAPIUnsanitizedRead = 4524, + kWindowOpenFullscreenRequested = 4525, + kFullscreenAllowedByWindowOpen = 4526, + kAttributeValueContainsLtOrGt = 4527, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/mojom/window_features/window_features.mojom b/third_party/blink/public/mojom/window_features/window_features.mojom index 288cbae..254f60a 100644 --- a/third_party/blink/public/mojom/window_features/window_features.mojom +++ b/third_party/blink/public/mojom/window_features/window_features.mojom
@@ -17,4 +17,9 @@ bool has_height = false; bool is_popup = false; + + // True if the new window was requested to be shown fullscreen. + // Window management permission must be granted on the opener. + // See: https://chromestatus.com/feature/6002307972464640 + bool is_fullscreen = false; };
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h index 6d34aa5e..c13058bc 100644 --- a/third_party/blink/public/web/web_navigation_params.h +++ b/third_party/blink/public/web/web_navigation_params.h
@@ -195,6 +195,11 @@ // src. Only container-initiated navigation report resource timing to the // parent. bool is_container_initiated = false; + + // True if the initiator requested that the tab become fullscreen + // after navigation (e.g. the initial navigation of a fullscreen popup). + // See: https://chromestatus.com/feature/6002307972464640 + bool is_fullscreen_requested = false; }; // This structure holds all information provided by the embedder that is
diff --git a/third_party/blink/public/web/web_window_features.h b/third_party/blink/public/web/web_window_features.h index a50a83d3..19e505a2 100644 --- a/third_party/blink/public/web/web_window_features.h +++ b/third_party/blink/public/web/web_window_features.h
@@ -49,6 +49,11 @@ bool is_popup = false; + // True if the new window was requested to be shown fullscreen. + // Window management permission must be granted on the opener. + // See: https://chromestatus.com/feature/6002307972464640 + bool is_fullscreen = false; + // The members above this line are transferred through mojo // in the form of |struct WindowFeatures| defined in window_features.mojom, // to be used across process boundaries.
diff --git a/third_party/blink/renderer/core/animation/BUILD.gn b/third_party/blink/renderer/core/animation/BUILD.gn index 4ce94baa..21a2ede9 100644 --- a/third_party/blink/renderer/core/animation/BUILD.gn +++ b/third_party/blink/renderer/core/animation/BUILD.gn
@@ -89,6 +89,8 @@ "css_custom_list_interpolation_type.h", "css_default_interpolation_type.cc", "css_default_interpolation_type.h", + "css_display_interpolation_type.cc", + "css_display_interpolation_type.h", "css_filter_list_interpolation_type.cc", "css_filter_list_interpolation_type.h", "css_font_size_interpolation_type.cc",
diff --git a/third_party/blink/renderer/core/animation/css_display_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_display_interpolation_type.cc new file mode 100644 index 0000000..29152dc --- /dev/null +++ b/third_party/blink/renderer/core/animation/css_display_interpolation_type.cc
@@ -0,0 +1,210 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/animation/css_display_interpolation_type.h" + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "third_party/blink/renderer/core/css/css_primitive_value_mappings.h" +#include "third_party/blink/renderer/core/css/resolver/style_resolver.h" +#include "third_party/blink/renderer/core/css/resolver/style_resolver_state.h" +#include "third_party/blink/renderer/core/style/computed_style.h" + +namespace blink { + +class CSSDisplayNonInterpolableValue final : public NonInterpolableValue { + public: + ~CSSDisplayNonInterpolableValue() final = default; + + static scoped_refptr<CSSDisplayNonInterpolableValue> Create(EDisplay start, + EDisplay end) { + return base::AdoptRef(new CSSDisplayNonInterpolableValue(start, end)); + } + + EDisplay Display() const { + DCHECK_EQ(start_, end_); + return start_; + } + + EDisplay Display(double fraction) const { + if ((start_ == EDisplay::kNone || end_ == EDisplay::kNone) && + start_ != end_) { + // No halfway transition when transitioning to or from display:none + if (start_ == EDisplay::kNone) { + return fraction > 0 ? end_ : start_; + } else { + return fraction >= 1 ? end_ : start_; + } + } + return fraction >= 0.5 ? end_ : start_; + } + + DECLARE_NON_INTERPOLABLE_VALUE_TYPE(); + + private: + CSSDisplayNonInterpolableValue(EDisplay start, EDisplay end) + : start_(start), end_(end) {} + + const EDisplay start_; + const EDisplay end_; +}; + +DEFINE_NON_INTERPOLABLE_VALUE_TYPE(CSSDisplayNonInterpolableValue); +template <> +struct DowncastTraits<CSSDisplayNonInterpolableValue> { + static bool AllowFrom(const NonInterpolableValue* value) { + return value && AllowFrom(*value); + } + static bool AllowFrom(const NonInterpolableValue& value) { + return value.GetType() == CSSDisplayNonInterpolableValue::static_type_; + } +}; + +class UnderlyingDisplayChecker final + : public CSSInterpolationType::CSSConversionChecker { + public: + explicit UnderlyingDisplayChecker(EDisplay display) : display_(display) {} + + ~UnderlyingDisplayChecker() final = default; + + private: + bool IsValid(const StyleResolverState&, + const InterpolationValue& underlying) const final { + double underlying_fraction = + To<InterpolableNumber>(*underlying.interpolable_value).Value(); + EDisplay underlying_display = + To<CSSDisplayNonInterpolableValue>(*underlying.non_interpolable_value) + .Display(underlying_fraction); + return display_ == underlying_display; + } + + const EDisplay display_; +}; + +class InheritedDisplayChecker + : public CSSInterpolationType::CSSConversionChecker { + public: + explicit InheritedDisplayChecker(EDisplay display) : display_(display) {} + + private: + bool IsValid(const StyleResolverState& state, + const InterpolationValue& underlying) const final { + return display_ == state.ParentStyle()->Display(); + } + + const EDisplay display_; +}; + +InterpolationValue CSSDisplayInterpolationType::CreateDisplayValue( + EDisplay display) const { + return InterpolationValue( + std::make_unique<InterpolableNumber>(0), + CSSDisplayNonInterpolableValue::Create(display, display)); +} + +InterpolationValue CSSDisplayInterpolationType::MaybeConvertNeutral( + const InterpolationValue& underlying, + ConversionCheckers& conversion_checkers) const { + double underlying_fraction = + To<InterpolableNumber>(*underlying.interpolable_value).Value(); + EDisplay underlying_display = + To<CSSDisplayNonInterpolableValue>(*underlying.non_interpolable_value) + .Display(underlying_fraction); + conversion_checkers.push_back( + std::make_unique<UnderlyingDisplayChecker>(underlying_display)); + return CreateDisplayValue(underlying_display); +} + +InterpolationValue CSSDisplayInterpolationType::MaybeConvertInitial( + const StyleResolverState& state, + ConversionCheckers&) const { + return CreateDisplayValue( + state.GetDocument().GetStyleResolver().InitialStyle().Display()); +} + +InterpolationValue CSSDisplayInterpolationType::MaybeConvertInherit( + const StyleResolverState& state, + ConversionCheckers& conversion_checkers) const { + if (!state.ParentStyle()) { + return nullptr; + } + EDisplay inherited_display = state.ParentStyle()->Display(); + conversion_checkers.push_back( + std::make_unique<InheritedDisplayChecker>(inherited_display)); + return CreateDisplayValue(inherited_display); +} + +InterpolationValue CSSDisplayInterpolationType::MaybeConvertValue( + const CSSValue& value, + const StyleResolverState*, + ConversionCheckers& conversion_checkers) const { + const auto* identifier_value = DynamicTo<CSSIdentifierValue>(value); + if (!identifier_value) { + return nullptr; + } + + CSSValueID keyword = identifier_value->GetValueID(); + + switch (keyword) { + case CSSValueID::kBlock: + case CSSValueID::kContents: + case CSSValueID::kFlex: + case CSSValueID::kFlowRoot: + case CSSValueID::kGrid: + case CSSValueID::kInline: + case CSSValueID::kInlineBlock: + case CSSValueID::kInlineFlex: + case CSSValueID::kInlineGrid: + case CSSValueID::kListItem: + case CSSValueID::kNone: + case CSSValueID::kTable: + case CSSValueID::kTableRow: + return CreateDisplayValue(identifier_value->ConvertTo<EDisplay>()); + default: + return nullptr; + } +} + +InterpolationValue +CSSDisplayInterpolationType::MaybeConvertStandardPropertyUnderlyingValue( + const ComputedStyle& style) const { + return CreateDisplayValue(style.Display()); +} + +PairwiseInterpolationValue CSSDisplayInterpolationType::MaybeMergeSingles( + InterpolationValue&& start, + InterpolationValue&& end) const { + EDisplay start_display = + To<CSSDisplayNonInterpolableValue>(*start.non_interpolable_value) + .Display(); + EDisplay end_display = + To<CSSDisplayNonInterpolableValue>(*end.non_interpolable_value).Display(); + return PairwiseInterpolationValue( + std::make_unique<InterpolableNumber>(0), + std::make_unique<InterpolableNumber>(1), + CSSDisplayNonInterpolableValue::Create(start_display, end_display)); +} + +void CSSDisplayInterpolationType::Composite( + UnderlyingValueOwner& underlying_value_owner, + double underlying_fraction, + const InterpolationValue& value, + double interpolation_fraction) const { + underlying_value_owner.Set(*this, value); +} + +void CSSDisplayInterpolationType::ApplyStandardPropertyValue( + const InterpolableValue& interpolable_value, + const NonInterpolableValue* non_interpolable_value, + StyleResolverState& state) const { + // Display interpolation has been deferred to application time here due to + // its non-linear behaviour. + double fraction = To<InterpolableNumber>(interpolable_value).Value(); + EDisplay display = To<CSSDisplayNonInterpolableValue>(non_interpolable_value) + ->Display(fraction); + state.StyleBuilder().SetDisplay(display); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/animation/css_display_interpolation_type.h b/third_party/blink/renderer/core/animation/css_display_interpolation_type.h new file mode 100644 index 0000000..42607b6 --- /dev/null +++ b/third_party/blink/renderer/core/animation/css_display_interpolation_type.h
@@ -0,0 +1,49 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_DISPLAY_INTERPOLATION_TYPE_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_DISPLAY_INTERPOLATION_TYPE_H_ + +#include "base/check_op.h" +#include "third_party/blink/renderer/core/animation/css_interpolation_type.h" +#include "third_party/blink/renderer/core/style/computed_style_constants.h" + +namespace blink { + +class CSSDisplayInterpolationType : public CSSInterpolationType { + public: + explicit CSSDisplayInterpolationType(PropertyHandle property) + : CSSInterpolationType(property) { + DCHECK_EQ(CssProperty().PropertyID(), CSSPropertyID::kDisplay); + } + + InterpolationValue MaybeConvertStandardPropertyUnderlyingValue( + const ComputedStyle&) const final; + PairwiseInterpolationValue MaybeMergeSingles( + InterpolationValue&& start, + InterpolationValue&& end) const final; + void Composite(UnderlyingValueOwner&, + double underlying_fraction, + const InterpolationValue&, + double interpolation_fraction) const final; + void ApplyStandardPropertyValue(const InterpolableValue&, + const NonInterpolableValue*, + StyleResolverState&) const final; + + private: + InterpolationValue CreateDisplayValue(EDisplay) const; + InterpolationValue MaybeConvertNeutral(const InterpolationValue& underlying, + ConversionCheckers&) const final; + InterpolationValue MaybeConvertInitial(const StyleResolverState&, + ConversionCheckers&) const final; + InterpolationValue MaybeConvertInherit(const StyleResolverState&, + ConversionCheckers&) const final; + InterpolationValue MaybeConvertValue(const CSSValue&, + const StyleResolverState*, + ConversionCheckers&) const final; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_ANIMATION_CSS_DISPLAY_INTERPOLATION_TYPE_H_
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc index 0f33f0ee..f237965 100644 --- a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc +++ b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
@@ -17,6 +17,7 @@ #include "third_party/blink/renderer/core/animation/css_custom_length_interpolation_type.h" #include "third_party/blink/renderer/core/animation/css_custom_list_interpolation_type.h" #include "third_party/blink/renderer/core/animation/css_default_interpolation_type.h" +#include "third_party/blink/renderer/core/animation/css_display_interpolation_type.h" #include "third_party/blink/renderer/core/animation/css_filter_list_interpolation_type.h" #include "third_party/blink/renderer/core/animation/css_font_size_interpolation_type.h" #include "third_party/blink/renderer/core/animation/css_font_stretch_interpolation_type.h" @@ -405,6 +406,11 @@ applicable_types->push_back( std::make_unique<CSSBasicShapeInterpolationType>(used_property)); break; + case CSSPropertyID::kDisplay: + DCHECK(RuntimeEnabledFeatures::CSSDisplayAnimationEnabled()); + applicable_types->push_back( + std::make_unique<CSSDisplayInterpolationType>(used_property)); + break; default: DCHECK(!css_property.IsInterpolable()); break;
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni index 93c3b4c..05608a9 100644 --- a/third_party/blink/renderer/core/css/build.gni +++ b/third_party/blink/renderer/core/css/build.gni
@@ -703,6 +703,8 @@ "vision_deficiency.h", "white_space.h", "zoom_adjusted_pixel_value.h", + "css_style_sheet_ids.cc", + "css_style_sheet_ids.h", ] blink_core_tests_css = [
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc index cd679ed..0fdf2b4 100644 --- a/third_party/blink/renderer/core/css/css_math_expression_node.cc +++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -254,7 +254,20 @@ : CSSMathExpressionNode(UnitCategory(value->GetType()), false /* has_comparisons*/, false /* needs_tree_scope_population*/), - value_(value) {} + value_(value) { + if (!value_->IsNumber() && CanEagerlySimplify(Category())) { + // "If root is a dimension that is not expressed in its canonical unit, and + // there is enough information available to convert it to the canonical + // unit, do so, and return the value." + // https://w3c.github.io/csswg-drafts/css-values/#calc-simplification + // + // However, Numbers should not be eagerly simplified here since that would + // result in converting Integers to Doubles (kNumber, canonical unit for + // Numbers). + + value_ = value_->CreateCanonicalUnitValue(); + } +} bool CSSMathExpressionNumericLiteral::IsZero() const { return !value_->GetDoubleValue();
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc index e359a39..81e212b 100644 --- a/third_party/blink/renderer/core/css/css_numeric_literal_value.cc +++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.cc
@@ -115,6 +115,11 @@ return DoubleValue() * ConversionToCanonicalUnitsScaleFactor(GetType()); } +double CSSNumericLiteralValue::ComputeInCanonicalUnit() const { + return DoubleValue() * + CSSPrimitiveValue::ConversionToCanonicalUnitsScaleFactor(GetType()); +} + double CSSNumericLiteralValue::ComputeLengthPx( const CSSLengthResolver& length_resolver) const { DCHECK(IsLength()); @@ -339,4 +344,13 @@ } } +CSSPrimitiveValue::UnitType CSSNumericLiteralValue::CanonicalUnit() const { + return CanonicalUnitTypeForCategory(UnitTypeToUnitCategory(GetType())); +} + +CSSNumericLiteralValue* CSSNumericLiteralValue::CreateCanonicalUnitValue() + const { + return Create(ComputeInCanonicalUnit(), CanonicalUnit()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_numeric_literal_value.h b/third_party/blink/renderer/core/css/css_numeric_literal_value.h index f62f53f..7feba2a 100644 --- a/third_party/blink/renderer/core/css/css_numeric_literal_value.h +++ b/third_party/blink/renderer/core/css/css_numeric_literal_value.h
@@ -69,6 +69,7 @@ double ComputeSeconds() const; double ComputeDegrees() const; double ComputeDotsPerPixel() const; + double ComputeInCanonicalUnit() const; double ComputeLengthPx(const CSSLengthResolver&) const; bool AccumulateLengthArray(CSSLengthArray& length_array, @@ -78,10 +79,13 @@ String CustomCSSText() const; bool Equals(const CSSNumericLiteralValue& other) const; + UnitType CanonicalUnit() const; + CSSNumericLiteralValue* CreateCanonicalUnitValue() const; + void TraceAfterDispatch(blink::Visitor* visitor) const; private: - double num_; + const double num_; }; template <>
diff --git a/third_party/blink/renderer/core/css/css_property_equality.cc b/third_party/blink/renderer/core/css/css_property_equality.cc index cde036a..2e40ef9 100644 --- a/third_party/blink/renderer/core/css/css_property_equality.cc +++ b/third_party/blink/renderer/core/css/css_property_equality.cc
@@ -28,7 +28,7 @@ return false; } - base::ranges::equal(*a_map, *b_map, [](const auto& a, const auto& b) { + return base::ranges::equal(*a_map, *b_map, [](const auto& a, const auto& b) { switch (property) { case CSSPropertyID::kCounterIncrement: if (a.value.IncrementValue() != b.value.IncrementValue()) { @@ -53,7 +53,6 @@ } return true; }); - return true; } template <CSSPropertyID property>
diff --git a/third_party/blink/renderer/core/css/css_style_sheet_ids.cc b/third_party/blink/renderer/core/css/css_style_sheet_ids.cc new file mode 100644 index 0000000..c8f242e8 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_style_sheet_ids.cc
@@ -0,0 +1,24 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/css/css_style_sheet_ids.h" + +#include "third_party/blink/renderer/core/inspector/identifiers_factory.h" +#include "third_party/blink/renderer/platform/heap/persistent.h" + +namespace blink { + +DEFINE_WEAK_IDENTIFIER_MAP(CSSStyleSheet) + +// static +String CSSStyleSheetIds::IdForCSSStyleSheet(const CSSStyleSheet* style_sheet) { + if (style_sheet == nullptr) { + return "ua-style-sheet"; + } + const int id = WeakIdentifierMap<CSSStyleSheet>::Identifier( + const_cast<CSSStyleSheet*>(style_sheet)); + return "style-sheet-" + String::Number(id); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_style_sheet_ids.h b/third_party/blink/renderer/core/css/css_style_sheet_ids.h new file mode 100644 index 0000000..98fce59 --- /dev/null +++ b/third_party/blink/renderer/core/css/css_style_sheet_ids.h
@@ -0,0 +1,37 @@ +// Copyright 2023 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STYLE_SHEET_IDS_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STYLE_SHEET_IDS_H_ + +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/core/css/css_style_sheet.h" +#include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/dom/weak_identifier_map.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" + +namespace blink { + +class CSSStyleSheet; + +DECLARE_WEAK_IDENTIFIER_MAP(CSSStyleSheet); + +// The CSSStyleSheetIds::IdForCSSStyleSheet() function generates unique +// IDs for CSS style sheets. These IDs are used to identify the style sheets +// within the InspectorStyleSheet, InspectorCSSAgent, and ElementRuleCollector +// classes. If the style sheet has a CSSStyleSheet object, its ID will have a +// "style-sheet-" prefix. If it lacks a CSSStyleSheet object (a UA stylesheet), +// its ID will be "ua-style-sheet". +class CORE_EXPORT CSSStyleSheetIds { + STATIC_ONLY(CSSStyleSheetIds); + + public: + // Return the existing ID if it has already been assigned, otherwise, + // assign a new ID and return that. + static String IdForCSSStyleSheet(const CSSStyleSheet*); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_STYLE_SHEET_IDS_H_
diff --git a/third_party/blink/renderer/core/css/element_rule_collector.cc b/third_party/blink/renderer/core/css/element_rule_collector.cc index b8b6ab99..caba9c3b 100644 --- a/third_party/blink/renderer/core/css/element_rule_collector.cc +++ b/third_party/blink/renderer/core/css/element_rule_collector.cc
@@ -44,6 +44,7 @@ #include "third_party/blink/renderer/core/css/css_selector.h" #include "third_party/blink/renderer/core/css/css_style_rule.h" #include "third_party/blink/renderer/core/css/css_style_sheet.h" +#include "third_party/blink/renderer/core/css/css_style_sheet_ids.h" #include "third_party/blink/renderer/core/css/css_supports_rule.h" #include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h" #include "third_party/blink/renderer/core/css/resolver/style_resolver.h" @@ -60,6 +61,25 @@ #include "third_party/blink/renderer/core/style/computed_style.h" namespace blink { +namespace { +struct CumulativeRulePerfKey { + String selector; + String style_sheet_id; + CumulativeRulePerfKey(const String& selector, const String& style_sheet_id) + : selector(selector), style_sheet_id(style_sheet_id) {} +}; +} // namespace +} // namespace blink + +namespace WTF { +template <> +struct HashTraits<blink::CumulativeRulePerfKey> + : TwoFieldsHashTraits<blink::CumulativeRulePerfKey, + &blink::CumulativeRulePerfKey::selector, + &blink::CumulativeRulePerfKey::style_sheet_id> {}; +} // namespace WTF + +namespace blink { namespace { @@ -222,22 +242,26 @@ }; using SelectorStatisticsRuleMap = - HashMap<const RuleData*, CumulativeRulePerfData>; + HashMap<CumulativeRulePerfKey, CumulativeRulePerfData>; SelectorStatisticsRuleMap& GetSelectorStatisticsRuleMap() { DEFINE_STATIC_LOCAL(SelectorStatisticsRuleMap, rule_map, {}); return rule_map; } void AggregateRulePerfData( - const HeapVector<RulePerfDataPerRequest>& rules_statistics) { + const HeapVector<RulePerfDataPerRequest>& rules_statistics, + const CSSStyleSheet* style_sheet) { SelectorStatisticsRuleMap& map = GetSelectorStatisticsRuleMap(); for (const auto& rule_stats : rules_statistics) { - auto it = map.find(rule_stats.rule); + CumulativeRulePerfKey key{ + rule_stats.rule->Selector().SelectorText(), + CSSStyleSheetIds::IdForCSSStyleSheet(style_sheet)}; + auto it = map.find(key); if (it == map.end()) { CumulativeRulePerfData data{ /*match_attempts*/ 1, (rule_stats.fast_reject) ? 1 : 0, (rule_stats.did_match) ? 1 : 0, rule_stats.elapsed}; - map.insert(rule_stats.rule, data); + map.insert(key, data); } else { it->value.elapsed += rule_stats.elapsed; it->value.match_attempts++; @@ -519,8 +543,10 @@ } if (perf_trace_enabled) { + DCHECK_EQ(mode_, SelectorChecker::kResolvingStyle); selector_statistics_collector.EndCollectionForCurrentRule(); - AggregateRulePerfData(selector_statistics_collector.PerRuleStatistics()); + AggregateRulePerfData(selector_statistics_collector.PerRuleStatistics(), + style_sheet); } StyleEngine& style_engine = @@ -1013,8 +1039,8 @@ perfetto::TracedValue item = array.AppendItem(); perfetto::TracedDictionary item_dict = std::move(item).WriteDictionary(); - const CSSSelector& selector = it.key->Selector(); - item_dict.Add("selector", selector.SelectorText()); + item_dict.Add("selector", it.key.selector); + item_dict.Add("style_sheet_id", it.key.style_sheet_id); item_dict.Add("elapsed (us)", it.value.elapsed); item_dict.Add("match_attempts", it.value.match_attempts); item_dict.Add("fast_reject_count", it.value.fast_reject_count);
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc index d514228..cb76da1 100644 --- a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc +++ b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.cc
@@ -167,7 +167,8 @@ case Node::kAttributeNode: // Only XMLSerializer can pass an Attr. So, |documentIsHTML| flag is // false. - formatter_.AppendAttributeValue(markup_, To<Attr>(node).value(), false); + formatter_.AppendAttributeValue(markup_, To<Attr>(node).value(), false, + node.GetDocument()); break; default: formatter_.AppendStartMarkup(markup_, node); @@ -315,7 +316,8 @@ formatter_.AppendStartTagOpen(markup_, prefix, element.localName()); data.serialized_prefix_ = prefix; // 12.5.5. Append the following to markup, in the order listed: - MarkupFormatter::AppendAttribute(markup_, g_xmlns_atom, prefix, ns, false); + MarkupFormatter::AppendAttribute(markup_, g_xmlns_atom, prefix, ns, false, + element.GetDocument()); // 12.5.5.7. If local default namespace is not null (there exists a // locally-defined default namespace declaration attribute), then let // inherited ns get the value of local default namespace unless the local @@ -336,7 +338,7 @@ formatter_.AppendStartTagOpen(markup_, element); // 12.6.5. Append the following to markup, in the order listed: MarkupFormatter::AppendAttribute(markup_, g_null_atom, g_xmlns_atom, ns, - false); + false, element.GetDocument()); return data; } @@ -357,7 +359,8 @@ const Attribute& attribute) { String value = formatter_.ResolveURLIfNeeded(element, attribute); if (SerializeAsHTML()) { - MarkupFormatter::AppendAttributeAsHTML(markup_, attribute, value); + MarkupFormatter::AppendAttributeAsHTML(markup_, attribute, value, + element.GetDocument()); } else { AppendAttributeAsXMLWithNamespace(element, attribute, value); } @@ -377,7 +380,8 @@ if (attribute_namespace.IsNull()) { MarkupFormatter::AppendAttribute(markup_, candidate_prefix, - attribute.LocalName(), value, false); + attribute.LocalName(), value, false, + element.GetDocument()); return; } // 3.5. If attribute namespace is not null, then run these sub-steps: @@ -404,15 +408,17 @@ // 3.5.3.2. Append the following to result, in the order listed: MarkupFormatter::AppendAttribute(markup_, g_xmlns_atom, candidate_prefix, attribute_namespace, - false); + false, element.GetDocument()); } else { DCHECK(candidate_prefix); - AppendNamespace(candidate_prefix, attribute_namespace); + AppendNamespace(candidate_prefix, attribute_namespace, + element.GetDocument()); } } } MarkupFormatter::AppendAttribute(markup_, candidate_prefix, - attribute.LocalName(), value, false); + attribute.LocalName(), value, false, + element.GetDocument()); } bool MarkupAccumulator::ShouldAddNamespaceAttribute( @@ -434,16 +440,17 @@ } void MarkupAccumulator::AppendNamespace(const AtomicString& prefix, - const AtomicString& namespace_uri) { + const AtomicString& namespace_uri, + const Document& document) { AtomicString found_uri = LookupNamespaceURI(prefix); if (!EqualIgnoringNullity(found_uri, namespace_uri)) { AddPrefix(prefix, namespace_uri); if (prefix.empty()) { MarkupFormatter::AppendAttribute(markup_, g_null_atom, g_xmlns_atom, - namespace_uri, false); + namespace_uri, false, document); } else { MarkupFormatter::AppendAttribute(markup_, g_xmlns_atom, prefix, - namespace_uri, false); + namespace_uri, false, document); } } }
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h index b14296bd..a1141e02 100644 --- a/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h +++ b/third_party/blink/renderer/core/editing/serializers/markup_accumulator.h
@@ -81,7 +81,8 @@ ElementSerializationData AppendStartTagOpen(const Element&); void AppendStartTagClose(const Element&); void AppendNamespace(const AtomicString& prefix, - const AtomicString& namespace_uri); + const AtomicString& namespace_uri, + const Document& document); void AppendAttributeAsXMLWithNamespace(const Element& element, const Attribute& attribute, const String& value);
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc b/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc index dba6bbe3..0fdc9da0 100644 --- a/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc +++ b/third_party/blink/renderer/core/editing/serializers/markup_formatter.cc
@@ -27,11 +27,13 @@ #include "third_party/blink/renderer/core/editing/serializers/markup_formatter.h" +#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-shared.h" #include "third_party/blink/renderer/core/dom/cdata_section.h" #include "third_party/blink/renderer/core/dom/comment.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" #include "third_party/blink/renderer/core/dom/document_type.h" +#include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/processing_instruction.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/editing/editor.h" @@ -42,6 +44,7 @@ #include "third_party/blink/renderer/core/xlink_names.h" #include "third_party/blink/renderer/core/xml_names.h" #include "third_party/blink/renderer/core/xmlns_names.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/wtf/text/character_names.h" #include "third_party/blink/renderer/platform/wtf/text/character_visitor.h" @@ -209,18 +212,28 @@ void MarkupFormatter::AppendAttributeValue(StringBuilder& result, const String& attribute, - bool document_is_html) { - AppendCharactersReplacingEntities(result, attribute, - document_is_html - ? kEntityMaskInHTMLAttributeValue - : kEntityMaskInAttributeValue); + bool document_is_html, + const Document& document) { + if (attribute.Contains('<') || attribute.Contains('>')) { + document.CountUse(mojom::blink::WebFeature::kAttributeValueContainsLtOrGt); + } + + EntityMask entity_mask = + document_is_html + ? (RuntimeEnabledFeatures::EscapeLtGtInAttributesEnabled() + ? kEntityExperimentalMaskInHTMLAttributeValue + : kEntityMaskInHTMLAttributeValue) + : kEntityMaskInAttributeValue; + + AppendCharactersReplacingEntities(result, attribute, entity_mask); } void MarkupFormatter::AppendAttribute(StringBuilder& result, const AtomicString& prefix, const AtomicString& local_name, const String& value, - bool document_is_html) { + bool document_is_html, + const Document& document) { result.Append(' '); if (!prefix.empty()) { result.Append(prefix); @@ -228,7 +241,7 @@ } result.Append(local_name); result.Append("=\""); - AppendAttributeValue(result, value, document_is_html); + AppendAttributeValue(result, value, document_is_html, document); result.Append('"'); } @@ -333,7 +346,8 @@ void MarkupFormatter::AppendAttributeAsHTML(StringBuilder& result, const Attribute& attribute, - const String& value) { + const String& value, + const Document& document) { // https://html.spec.whatwg.org/C/#attribute's-serialised-name QualifiedName prefixed_name = attribute.GetName(); if (attribute.NamespaceURI() == xmlns_names::kNamespaceURI) { @@ -345,13 +359,14 @@ prefixed_name.SetPrefix(g_xlink_atom); } AppendAttribute(result, prefixed_name.Prefix(), prefixed_name.LocalName(), - value, true); + value, true, document); } void MarkupFormatter::AppendAttributeAsXMLWithoutNamespace( StringBuilder& result, const Attribute& attribute, - const String& value) { + const String& value, + const Document& document) { const AtomicString& attribute_namespace = attribute.NamespaceURI(); AtomicString candidate_prefix = attribute.Prefix(); if (attribute_namespace == xmlns_names::kNamespaceURI) { @@ -364,8 +379,8 @@ if (!candidate_prefix) candidate_prefix = g_xlink_atom; } - AppendAttribute(result, candidate_prefix, attribute.LocalName(), value, - false); + AppendAttribute(result, candidate_prefix, attribute.LocalName(), value, false, + document); } void MarkupFormatter::AppendCDATASection(StringBuilder& result,
diff --git a/third_party/blink/renderer/core/editing/serializers/markup_formatter.h b/third_party/blink/renderer/core/editing/serializers/markup_formatter.h index c3dd275..c2719a6 100644 --- a/third_party/blink/renderer/core/editing/serializers/markup_formatter.h +++ b/third_party/blink/renderer/core/editing/serializers/markup_formatter.h
@@ -55,11 +55,14 @@ kEntityMaskInCDATA = 0, kEntityMaskInPCDATA = kEntityAmp | kEntityLt | kEntityGt, kEntityMaskInHTMLPCDATA = kEntityMaskInPCDATA | kEntityNbsp, - kEntityMaskInAttributeValue = - kEntityAmp | kEntityQuot | kEntityLt | kEntityGt | kEntityTab | - kEntityLineFeed | - kEntityCarriageReturn, + kEntityMaskInAttributeValue = kEntityAmp | kEntityQuot | kEntityLt | + kEntityGt | kEntityTab | kEntityLineFeed | + kEntityCarriageReturn, kEntityMaskInHTMLAttributeValue = kEntityAmp | kEntityQuot | kEntityNbsp, + // Entity mask for an experiment with escaping "<" and ">" in attributes. + // See: crbug.com/1175016 + kEntityExperimentalMaskInHTMLAttributeValue = + kEntityMaskInHTMLAttributeValue | kEntityLt | kEntityGt, }; enum class SerializationType { kHTML, kXML }; @@ -68,18 +71,24 @@ STACK_ALLOCATED(); public: - static void AppendAttributeValue(StringBuilder&, const String&, bool); + static void AppendAttributeValue(StringBuilder&, + const String&, + bool, + const Document&); static void AppendAttributeAsHTML(StringBuilder& result, const Attribute& attribute, - const String& value); + const String& value, + const Document& node); static void AppendAttributeAsXMLWithoutNamespace(StringBuilder& result, const Attribute& attribute, - const String& value); + const String& value, + const Document& document); static void AppendAttribute(StringBuilder& result, const AtomicString& prefix, const AtomicString& local_name, const String& value, - bool document_is_html); + bool document_is_html, + const Document& document); static void AppendCDATASection(StringBuilder&, const String&); static void AppendCharactersReplacingEntities(StringBuilder& result, const StringView& source,
diff --git a/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc b/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc index 9fddbd6..0640eb2f 100644 --- a/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc +++ b/third_party/blink/renderer/core/editing/serializers/styled_markup_accumulator.cc
@@ -109,7 +109,8 @@ result_.Append("<span style=\""); MarkupFormatter::AppendAttributeValue( - result_, inline_style->Style()->AsText(), IsA<HTMLDocument>(document_)); + result_, inline_style->Style()->AsText(), IsA<HTMLDocument>(document_), + *document_); result_.Append("\">"); } if (!ShouldAnnotate()) { @@ -154,8 +155,8 @@ } if (style && !style->IsEmpty()) { out.Append(" style=\""); - MarkupFormatter::AppendAttributeValue(out, style->Style()->AsText(), - document_is_html); + MarkupFormatter::AppendAttributeValue( + out, style->Style()->AsText(), document_is_html, element.GetDocument()); out.Append('\"'); } formatter_.AppendStartTagClose(out, element); @@ -179,10 +180,11 @@ const Attribute& attribute) { String value = formatter_.ResolveURLIfNeeded(element, attribute); if (formatter_.SerializeAsHTML()) { - MarkupFormatter::AppendAttributeAsHTML(result, attribute, value); + MarkupFormatter::AppendAttributeAsHTML(result, attribute, value, + element.GetDocument()); } else { - MarkupFormatter::AppendAttributeAsXMLWithoutNamespace(result, attribute, - value); + MarkupFormatter::AppendAttributeAsXMLWithoutNamespace( + result, attribute, value, element.GetDocument()); } } @@ -195,8 +197,8 @@ StringBuilder open_tag; open_tag.Append("<div style=\""); - MarkupFormatter::AppendAttributeValue(open_tag, style->AsText(), - IsA<HTMLDocument>(document_)); + MarkupFormatter::AppendAttributeValue( + open_tag, style->AsText(), IsA<HTMLDocument>(document_), *document_); open_tag.Append("\">"); reversed_preceding_markup_.push_back(open_tag.ToString());
diff --git a/third_party/blink/renderer/core/frame/frame_serializer.cc b/third_party/blink/renderer/core/frame/frame_serializer.cc index b8fe5f5..948d8bd 100644 --- a/third_party/blink/renderer/core/frame/frame_serializer.cc +++ b/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -250,8 +250,8 @@ void SerializerMarkupAccumulator::AppendAttributeValue( const String& attribute_value) { - MarkupFormatter::AppendAttributeValue(markup_, attribute_value, - IsA<HTMLDocument>(document_)); + MarkupFormatter::AppendAttributeValue( + markup_, attribute_value, IsA<HTMLDocument>(document_), *document_); } void SerializerMarkupAccumulator::AppendRewrittenAttribute(
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index 8e675fc..df00c3f2 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -2248,6 +2248,14 @@ if (!result.frame) return nullptr; + // If the resulting frame didn't create a new window and fullscreen was + // requested, reset the flag to prevent making a pre-existing frame + // fullscreen. + if (!result.new_window && window_features.is_fullscreen) { + window_features.is_fullscreen = false; + frame_request.SetFeaturesForWindowOpen(window_features); + } + if (window_features.x_set || window_features.y_set) { // This runs after FindOrCreateFrameForNavigation() so blocked popups are // not counted.
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 57c53a50..e3bfcfb 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -188,7 +188,8 @@ std::unique_ptr<SourceLocation> source_location, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle> initiator_policy_container_handle, - bool is_container_initiated) = 0; + bool is_container_initiated, + bool is_fullscreen_requested) = 0; virtual void DispatchWillSendSubmitEvent(HTMLFormElement*) = 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc index a673808..d7276e6 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -530,7 +530,8 @@ std::unique_ptr<SourceLocation> source_location, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle> initiator_policy_container_keep_alive_handle, - bool is_container_initiated) { + bool is_container_initiated, + bool is_fullscreen_requested) { if (!web_frame_->Client()) return; @@ -580,6 +581,7 @@ } navigation_info->impression = impression; + navigation_info->is_fullscreen_requested = is_fullscreen_requested; // Propagate `has_storage_access` to the next document under certain // circumstances. This corresponds to the "snapshotting source snapshot
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h index 18bd283..b891843 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -139,7 +139,8 @@ std::unique_ptr<SourceLocation> source_location, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle> initiator_policy_container_keep_alive_handle, - bool is_container_initiated) override; + bool is_container_initiated, + bool is_fullscreen_requested) override; void DispatchWillSendSubmitEvent(HTMLFormElement*) override; void DidStartLoading() override; void DidStopLoading() override;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc index fe43461..a99952f 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" #include "third_party/blink/renderer/bindings/core/v8/script_evaluation_result.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h" +#include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" @@ -48,6 +49,7 @@ #include "third_party/blink/renderer/core/frame/savable_resources.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/fullscreen/fullscreen.h" +#include "third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h" #include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html/html_link_element.h" #include "third_party/blink/renderer/core/html/html_meta_element.h" @@ -1390,6 +1392,16 @@ subframe->Owner()->AddResourceTiming(std::move(info)); } +void LocalFrameMojoHandler::RequestFullscreenDocumentElement() { + if (auto* document_element = frame_->GetDocument()->documentElement()) { + // `kWindowOpen` assumes this function is only invoked for newly created + // windows (e.g. fullscreen popups). Update this if additional callers are + // added. See: https://chromestatus.com/feature/6002307972464640 + ScopedAllowFullscreen allow_fullscreen(ScopedAllowFullscreen::kWindowOpen); + Fullscreen::RequestFullscreen(*document_element); + } +} + void LocalFrameMojoHandler::RequestFullscreenVideoElement() { // Find the first video element of the frame. for (auto* child = frame_->GetDocument()->documentElement(); child;
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h index 3b62aac2..bbad16f 100644 --- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h +++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.h
@@ -10,6 +10,7 @@ #include "services/device/public/mojom/device_posture_provider.mojom-blink.h" #include "third_party/blink/public/mojom/frame/back_forward_cache_controller.mojom-blink.h" #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h" +#include "third_party/blink/public/mojom/frame/fullscreen.mojom-blink-forward.h" #include "third_party/blink/public/mojom/media/fullscreen_video_element.mojom-blink.h" #include "third_party/blink/public/mojom/reporting/reporting.mojom-blink.h" #include "third_party/blink/public/mojom/timing/resource_timing.mojom-blink-forward.h" @@ -218,6 +219,7 @@ bool is_validated, const WTF::String& normalized_server_timing, const ::network::URLLoaderCompletionStatus& completion_status) final; + void RequestFullscreenDocumentElement() final; // blink::mojom::LocalMainFrame overrides: void AnimateDoubleTapZoom(const gfx::Point& point,
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc index f0bc66f..896e907 100644 --- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc +++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -349,6 +349,16 @@ return true; } + // The algorithm is triggered by a browser initiated fullscreen of the + // frame's document element. Used in cases like fullscreen popups where the + // browser triggers fullscreen after a navigation. See: + // https://chromestatus.com/feature/6002307972464640 + if (ScopedAllowFullscreen::FullscreenAllowedReason() == + ScopedAllowFullscreen::kWindowOpen) { + UseCounter::Count(document, WebFeature::kFullscreenAllowedByWindowOpen); + return true; + } + // The algorithm is triggered by another event with transient affordances, // e.g. permission-gated events for user-generated screens changes. if (RuntimeEnabledFeatures::WindowPlacementFullscreenOnScreensChangeEnabled(
diff --git a/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h b/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h index 718e36a..59c302b 100644 --- a/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h +++ b/third_party/blink/renderer/core/fullscreen/scoped_allow_fullscreen.h
@@ -15,7 +15,7 @@ STACK_ALLOCATED(); public: - enum Reason { kOrientationChange, kXrOverlay, kXrSession }; + enum Reason { kOrientationChange, kXrOverlay, kXrSession, kWindowOpen }; static absl::optional<Reason> FullscreenAllowedReason(); explicit ScopedAllowFullscreen(Reason);
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc index 39e5417..70ccac6 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -41,6 +41,7 @@ #include "third_party/blink/renderer/core/css/css_scope_rule.h" #include "third_party/blink/renderer/core/css/css_style_rule.h" #include "third_party/blink/renderer/core/css/css_style_sheet.h" +#include "third_party/blink/renderer/core/css/css_style_sheet_ids.h" #include "third_party/blink/renderer/core/css/css_supports_rule.h" #include "third_party/blink/renderer/core/css/parser/css_parser.h" #include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h" @@ -991,8 +992,8 @@ visitor->Trace(source_data_); } -InspectorStyleSheetBase::InspectorStyleSheetBase(Listener* listener) - : id_(IdentifiersFactory::CreateIdentifier()), +InspectorStyleSheetBase::InspectorStyleSheetBase(Listener* listener, String id) + : id_(id), listener_(listener), line_endings_(std::make_unique<LineEndings>()) {} @@ -1046,7 +1047,9 @@ const String& document_url, InspectorStyleSheetBase::Listener* listener, InspectorResourceContainer* resource_container) - : InspectorStyleSheetBase(listener), + : InspectorStyleSheetBase( + listener, + CSSStyleSheetIds::IdForCSSStyleSheet(page_style_sheet)), resource_container_(resource_container), network_agent_(network_agent), page_style_sheet_(page_style_sheet), @@ -2298,7 +2301,8 @@ InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle( Element* element, Listener* listener) - : InspectorStyleSheetBase(listener), element_(element) { + : InspectorStyleSheetBase(listener, IdentifiersFactory::CreateIdentifier()), + element_(element) { DCHECK(element_); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.h b/third_party/blink/renderer/core/inspector/inspector_style_sheet.h index 4d667585..4d5a21f 100644 --- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.h +++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.h
@@ -115,7 +115,7 @@ virtual bool IsInlineStyle() = 0; protected: - explicit InspectorStyleSheetBase(Listener*); + explicit InspectorStyleSheetBase(Listener*, String id); Listener* GetListener() { return listener_; } void OnStyleSheetTextChanged();
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc index 6b63bf1..33f5bba 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.cc +++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -127,7 +127,8 @@ const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation>, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>, - bool is_container_initiated) {} + bool is_container_initiated, + bool is_fullscreen_requested) {} void EmptyLocalFrameClient::DispatchWillSendSubmitEvent(HTMLFormElement*) {}
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index c953da5..ca0c223 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -339,7 +339,8 @@ const LocalFrameToken* initiator_frame_token, std::unique_ptr<SourceLocation>, mojo::PendingRemote<mojom::blink::PolicyContainerHostKeepAliveHandle>, - bool is_container_initiated) override; + bool is_container_initiated, + bool is_fullscreen_requested) override; void DispatchWillSendSubmitEvent(HTMLFormElement*) override;
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.h b/third_party/blink/renderer/core/loader/frame_load_request.h index 8d28e63..9faa981 100644 --- a/third_party/blink/renderer/core/loader/frame_load_request.h +++ b/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -209,6 +209,13 @@ return force_history_push_; } + bool IsFullscreenRequested() const { + // If the window was requested as fullscreen and a popup, then the loaded + // frame should enter fullscreen. + // See: https://chromestatus.com/feature/6002307972464640 + return GetWindowFeatures().is_fullscreen && GetWindowFeatures().is_popup; + } + private: LocalDOMWindow* origin_window_; ResourceRequest resource_request_;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index c924edb..48552a8 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -875,7 +875,7 @@ request.Impression(), request.GetInitiatorFrameToken(), request.TakeSourceLocation(), request.TakeInitiatorPolicyContainerKeepAliveHandle(), - request.IsContainerInitiated()); + request.IsContainerInitiated(), request.IsFullscreenRequested()); } static void FillStaticResponseIfNeeded(WebNavigationParams* params,
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index 894a712..af61cbf 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -166,7 +166,7 @@ } if (!ui_features_were_disabled && key_string != "noopener" && - key_string != "noreferrer" && + key_string != "noreferrer" && key_string != "fullscreen" && (!attribution_reporting_enabled || key_string != "attributionsrc")) { ui_features_were_disabled = true; menu_bar = false; @@ -208,6 +208,13 @@ window_features.background = true; } else if (key_string == "persistent") { window_features.persistent = true; + } else if (key_string == "fullscreen" && + RuntimeEnabledFeatures::FullscreenPopupWindowsEnabled()) { + // TODO(crbug.com/1142516): Add permission check to give earlier + // feedback / console warning if permission isn't granted, and/or just + // silently drop the flag. Currently the browser will block the popup + // entirely if this flag is set and permission is not granted. + window_features.is_fullscreen = value; } else if (attribution_reporting_enabled && key_string == "attributionsrc") { // attributionsrc values are URLs, and as such their original case needs @@ -257,6 +264,11 @@ if (window_features.noreferrer) window_features.noopener = true; + if (window_features.is_fullscreen) { + UseCounter::Count(dom_window->document(), + WebFeature::kWindowOpenFullscreenRequested); + } + return window_features; }
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc index 0101f5f..429ebc6 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_enum_conversions.cc
@@ -677,8 +677,6 @@ return WGPUFeatureName_TimestampQuery; case V8GPUFeatureName::Enum::kTimestampQueryInsidePasses: return WGPUFeatureName_TimestampQueryInsidePasses; - case V8GPUFeatureName::Enum::kShaderFloat16: - return WGPUFeatureName_DawnShaderFloat16; case V8GPUFeatureName::Enum::kDepthClipControl: return WGPUFeatureName_DepthClipControl; case V8GPUFeatureName::Enum::kDepth32FloatStencil8: @@ -691,6 +689,8 @@ return WGPUFeatureName_RG11B10UfloatRenderable; case V8GPUFeatureName::Enum::kBgra8UnormStorage: return WGPUFeatureName_BGRA8UnormStorage; + case V8GPUFeatureName::Enum::kShaderF16: + return WGPUFeatureName_ShaderF16; } }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc index c616db8..6d00c5223 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_adapter.cc
@@ -46,14 +46,14 @@ return V8GPUFeatureName::Enum::kIndirectFirstInstance; case WGPUFeatureName_DepthClipControl: return V8GPUFeatureName::Enum::kDepthClipControl; - case WGPUFeatureName_DawnShaderFloat16: - return V8GPUFeatureName::Enum::kShaderFloat16; case WGPUFeatureName_RG11B10UfloatRenderable: return V8GPUFeatureName::Enum::kRg11B10UfloatRenderable; case WGPUFeatureName_BGRA8UnormStorage: return V8GPUFeatureName::Enum::kBgra8UnormStorage; case WGPUFeatureName_ChromiumExperimentalDp4a: return V8GPUFeatureName::Enum::kChromiumExperimentalDp4A; + case WGPUFeatureName_ShaderF16: + return V8GPUFeatureName::Enum::kShaderF16; default: return absl::nullopt; }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl index 077b8a6..f1848229 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_compute_pass_encoder.idl
@@ -8,15 +8,15 @@ Exposed(Window WebGPU, DedicatedWorker WebGPU), SecureContext ] interface GPUComputePassEncoder { - void setPipeline(GPUComputePipeline pipeline); + [NoAllocDirectCall] void setPipeline(GPUComputePipeline pipeline); [NoAllocDirectCall] void dispatchWorkgroups(GPUSize32 workgroupCountX, optional GPUSize32 workgroupCountY = 1, optional GPUSize32 workgroupCountZ = 1); - void dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, - GPUSize64 indirectOffset); + [NoAllocDirectCall] void dispatchWorkgroupsIndirect(GPUBuffer indirectBuffer, + GPUSize64 indirectOffset); [RaisesException] void writeTimestamp(GPUQuerySet querySet, GPUSize32 queryIndex); - void end(); + [NoAllocDirectCall] void end(); }; GPUComputePassEncoder includes GPUObjectBase; GPUComputePassEncoder includes GPUProgrammablePassEncoder;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc index f8616b2..e9e7ef4 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_external_texture.cc
@@ -51,10 +51,16 @@ auto cache = from_html_video_element_.find(video); if (cache != from_html_video_element_.end()) { external_texture = cache->value; - } else { - external_texture = GPUExternalTexture::FromHTMLVideoElement( - this, video, descriptor, exception_state); + if (external_texture->ContinueCheckingCurrentVideoFrame()) { + break; + } } + // If we got a cache miss, or `ContinueCheckingCurrentVideoFrame` returned + // false, make a new external texture. `ContinueCheckingCurrentVideoFrame` + // returns false if the frame has expired and it no longer needs to be + // checked for expiry. + external_texture = GPUExternalTexture::FromHTMLVideoElement( + this, video, descriptor, exception_state); break; } case V8UnionHTMLVideoElementOrVideoFrame::ContentType::kVideoFrame: { @@ -372,11 +378,11 @@ } bool GPUExternalTexture::ContinueCheckingCurrentVideoFrame() { - DCHECK(video_); DCHECK(media_video_frame_unique_id_.has_value()); - if (destroyed()) + if (destroyed() || !video_) { return false; + } WebMediaPlayer* media_player = video_->GetWebMediaPlayer();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl index 7c8dd9b..b3edb579 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_supported_features.idl
@@ -11,13 +11,13 @@ "texture-compression-astc", "timestamp-query", "timestamp-query-inside-passes", - "shader-float16", "depth-clip-control", "depth32float-stencil8", "indirect-first-instance", "chromium-experimental-dp4a", "rg11b10ufloat-renderable", "bgra8unorm-storage", + "shader-f16", }; [
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 4019776..46abae6 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1390,6 +1390,13 @@ status: "experimental", }, { + // Experiment with preventing some instances of mutation XSS + // by escaping "<" and ">" in attribute values. + // See: crbug.com/1175016 + name: "EscapeLtGtInAttributes", + status: "experimental", + }, + { // Non-standard API Event.path. Should be replaced by Event.composedPath. name: "EventPath", public: true, @@ -1733,6 +1740,12 @@ base_feature: "none", }, { + // Enables `fullscreen` windowFeatures parameter in window.open(). + name: "FullscreenPopupWindows", + status: "experimental", + base_feature: "FullscreenPopupWindows" + }, + { // If enabled, `window.screen` always provides display dimensions. // Otherwise, `window.screen` provides viewport dimensions in fullscreen // as a speculative site compatibility measure, because web authors may
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc index bda7fbf8..ebeb76ca 100644 --- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc +++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.cc
@@ -418,15 +418,6 @@ DispatchSingleInputEvent(std::move(event_with_callback), tick_clock_->NowTicks()); } else { - // TODO(bokan): This looks odd but is actually what happens in the - // non-unified path. If a scroll is DROP_EVENT'ed, we still call - // RecordMainThreadScrollingReasons and then LTHI::RecordScrollEnd when we - // DROP the ScrollEnd. We call this to ensure symmetry between - // RecordScrollBegin and RecordScrollEnd but we should probably be avoiding - // this if the scroll never starts. https://crbug.com/1082601. - RecordMainThreadScrollingReasons(gesture_event->SourceDevice(), 0, false, - 0); - // If the main thread failed to return a scroller for whatever reason, // consider the ScrollBegin to be dropped. scroll_sequence_ignored_ = true; @@ -850,7 +841,7 @@ } } -void InputHandlerProxy::RecordMainThreadScrollingReasons( +void InputHandlerProxy::RecordScrollBegin( WebGestureDevice device, uint32_t reasons_from_scroll_begin, bool was_main_thread_hit_tested, @@ -992,6 +983,8 @@ scroll_status = input_handler_->ScrollBegin( &scroll_state, GestureScrollInputType(gesture_event.SourceDevice())); } + DCHECK_EQ(scroll_status.thread == ScrollThread::SCROLL_ON_MAIN_THREAD, + !!scroll_status.main_thread_scrolling_reasons); // If we need a hit test from the main thread, we'll reinject this scroll // begin event once the hit test is complete so avoid everything below for @@ -1002,10 +995,12 @@ return REQUIRES_MAIN_THREAD_HIT_TEST; } - RecordMainThreadScrollingReasons(gesture_event.SourceDevice(), - scroll_status.main_thread_scrolling_reasons, - scroll_state.is_main_thread_hit_tested(), - scroll_status.main_thread_repaint_reasons); + if (scroll_status.thread != ScrollThread::SCROLL_IGNORED) { + RecordScrollBegin(gesture_event.SourceDevice(), + scroll_status.main_thread_scrolling_reasons, + scroll_state.is_main_thread_hit_tested(), + scroll_status.main_thread_repaint_reasons); + } InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE; scroll_sequence_ignored_ = false; @@ -1152,20 +1147,14 @@ const WebGestureEvent& gesture_event) { TRACE_EVENT0("input", "InputHandlerProxy::HandleGestureScrollEnd"); - // TODO(bokan): It seems odd that we'd record a ScrollEnd for a scroll - // secuence that was ignored (i.e. the ScrollBegin was dropped). However, - // RecordScrollBegin does get called in that case so this needs to be this - // way for now. This makes life rather awkward for the unified scrolling path - // so perhaps we should only record a scrolling thread if a scroll actually - // started? https://crbug.com/1082601. - input_handler_->RecordScrollEnd( - GestureScrollInputType(gesture_event.SourceDevice())); - if (scroll_sequence_ignored_) { DCHECK(!currently_active_gesture_device_.has_value()); return DROP_EVENT; } + input_handler_->RecordScrollEnd( + GestureScrollInputType(gesture_event.SourceDevice())); + if (!handling_gesture_on_impl_thread_) { DCHECK(!currently_active_gesture_device_.has_value()); return base::FeatureList::IsEnabled(::features::kScrollUnification)
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h index dae6317..a0c340d 100644 --- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h +++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy.h
@@ -320,10 +320,10 @@ event_attribution_enabled_ = enabled; } - void RecordMainThreadScrollingReasons(blink::WebGestureDevice device, - uint32_t reasons_from_scroll_begin, - bool was_main_thread_hit_tested, - uint32_t main_thread_repaint_reasons); + void RecordScrollBegin(blink::WebGestureDevice device, + uint32_t reasons_from_scroll_begin, + bool was_main_thread_hit_tested, + uint32_t main_thread_repaint_reasons); bool HasQueuedEventsReadyForDispatch();
diff --git a/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc b/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc index f7b7628..598e185 100644 --- a/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc +++ b/third_party/blink/renderer/platform/widget/input/input_handler_proxy_unittest.cc
@@ -335,7 +335,7 @@ const cc::InputHandler::ScrollStatus kScrollIgnoredScrollState( cc::InputHandler::ScrollThread::SCROLL_IGNORED, - cc::MainThreadScrollingReason::kNotScrollable); + cc::MainThreadScrollingReason::kNotScrollingOnMain); } // namespace @@ -344,9 +344,8 @@ TestInputHandlerProxy(cc::InputHandler& input_handler, InputHandlerProxyClient* client) : InputHandlerProxy(input_handler, client) {} - void RecordMainThreadScrollingReasonsForTest(WebGestureDevice device, - uint32_t reasons) { - RecordMainThreadScrollingReasons(device, reasons, false, false); + void RecordScrollBeginForTest(WebGestureDevice device, uint32_t reasons) { + RecordScrollBegin(device, reasons, false, 0); } MOCK_METHOD0(SetNeedsAnimateInput, void()); @@ -1043,10 +1042,7 @@ EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)) .WillOnce(testing::Return(kScrollIgnoredScrollState)); - EXPECT_CALL( - mock_input_handler_, - RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain)) - .Times(1); + EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(0); gesture_.SetType(WebInputEvent::Type::kGestureScrollBegin); EXPECT_EQ(expected_disposition_, @@ -1058,7 +1054,7 @@ // the main thread, either. expected_disposition_ = InputHandlerProxy::DROP_EVENT; gesture_.SetType(WebInputEvent::Type::kGestureScrollEnd); - EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1); + EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(0); EXPECT_EQ(expected_disposition_, HandleInputEventWithLatencyInfo(input_handler_.get(), gesture_)); @@ -2324,18 +2320,14 @@ } // Ensure we don't record either a begin or an end if the hit test fails. - // TODO(bokan): Though it looks odd, it appears that today we do record the - // scrolling thread if the scroll is dropped. We should fix that but in the - // mean-time we add a test for the unified path in this case. - // https://crbug.com/1082601. { EXPECT_CALL(mock_input_handler_, ScrollBegin(_, _)) .WillOnce(Return(kRequiresMainThreadHitTestState)); EXPECT_CALL(mock_input_handler_, ScrollUpdate(_, _)).Times(0); EXPECT_CALL(mock_input_handler_, ScrollEnd(_)).Times(0); - EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(1); - EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(1); + EXPECT_CALL(mock_input_handler_, RecordScrollBegin(_, _)).Times(0); + EXPECT_CALL(mock_input_handler_, RecordScrollEnd(_)).Times(0); DispatchEvent(ScrollBegin()); EXPECT_TRUE(MainThreadHitTestInProgress()); @@ -3812,7 +3804,7 @@ mock_input_handler_, RecordScrollBegin(_, cc::ScrollBeginThreadState::kScrollingOnMain)) .Times(1); - input_handler_->RecordMainThreadScrollingReasonsForTest( + input_handler_->RecordScrollBeginForTest( WebGestureDevice::kTouchpad, kSampleMainThreadScrollingReason | cc::MainThreadScrollingReason::kThreadedScrollingDisabled);
diff --git a/third_party/blink/tools/blinkpy/common/net/web_test_results.py b/third_party/blink/tools/blinkpy/common/net/web_test_results.py index 9b93a24..16da1ed 100644 --- a/third_party/blink/tools/blinkpy/common/net/web_test_results.py +++ b/third_party/blink/tools/blinkpy/common/net/web_test_results.py
@@ -97,7 +97,7 @@ def last_retry_result(self): return self.actual_results()[-1] - def has_non_reftest_mismatch(self): + def has_mismatch(self): """Returns true if a test without reference failed due to mismatch. This happens when the actual output of a non-reftest does not match the @@ -107,9 +107,7 @@ artifact_names = self._result_dict.get('artifacts', {}).keys() return ('FAIL' in actual_results and any( artifact_name.startswith('actual') - for artifact_name in artifact_names) - and 'reference_file_mismatch' not in artifact_names - and 'reference_file_match' not in artifact_names) + for artifact_name in artifact_names)) def is_missing_baseline(self): return (self.is_missing_image() or self.is_missing_text()
diff --git a/third_party/blink/tools/blinkpy/common/net/web_test_results_unittest.py b/third_party/blink/tools/blinkpy/common/net/web_test_results_unittest.py index 3889fc8..447dfb08 100644 --- a/third_party/blink/tools/blinkpy/common/net/web_test_results_unittest.py +++ b/third_party/blink/tools/blinkpy/common/net/web_test_results_unittest.py
@@ -182,18 +182,15 @@ results.result_for_test('fast/dom/expected-flaky.html'). expected_results(), 'PASS FAIL') - def test_has_non_reftest_mismatch(self): + def test_has_mismatch(self): results = WebTestResults.results_from_string( self.example_full_results_json) self.assertTrue( - results.result_for_test('fast/dom/many-mismatches.html'). - has_non_reftest_mismatch()) + results.result_for_test( + 'fast/dom/many-mismatches.html').has_mismatch()) self.assertTrue( - results.result_for_test('fast/dom/mismatch-implicit-baseline.html' - ).has_non_reftest_mismatch()) - self.assertFalse( - results.result_for_test('fast/dom/reference-mismatch.html'). - has_non_reftest_mismatch()) + results.result_for_test( + 'fast/dom/mismatch-implicit-baseline.html').has_mismatch()) def test_is_missing_baseline(self): results = WebTestResults.results_from_string(
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py index b184d9b0..f45df6d 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline.py
@@ -311,10 +311,15 @@ build_steps_to_fetch_from = self.build_steps_to_fetch_from( test_baseline_set.all_build_steps()) rebaselinable_set = TestBaselineSet(self._tool.builders) + port = self._tool.port_factory.get() for test, build, step_name, port_name in test_baseline_set: if (build.builder_name, step_name) not in build_steps_to_fetch_from: continue + if port.reference_files(test): + # TODO(crbug.com/1149035): Add a `[ Failure ]` line here + # instead. + continue suffixes = list( self._suffixes_for_actual_failures(test, build, step_name)) if suffixes:
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py index 561186f..59188e7 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl.py
@@ -372,9 +372,8 @@ A sorted list of tests to rebaseline for this build. """ unexpected_results = web_test_results.didnt_run_as_expected_results() - tests = sorted( - r.test_name() for r in unexpected_results - if r.is_missing_baseline() or r.has_non_reftest_mismatch()) + tests = sorted(r.test_name() for r in unexpected_results + if r.is_missing_baseline() or r.has_mismatch()) if not tests: # no need to fetch retry summary in this case return []
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py index 0bd4534b..ba57ff7 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_unittest.py
@@ -435,6 +435,21 @@ ]), ]) + def test_rebaseline_reftest(self): + """Do not download the `actual_image` artifact for reftests.""" + self._write('userscripts/first-test-expected.html', 'reference') + self._remove('userscripts/first-test-expected.txt') + self._remove('userscripts/first-test-expected.png') + self._remove('userscripts/first-test-expected.wav') + test_baseline_set = TestBaselineSet(self.tool.builders) + test_baseline_set.add('userscripts/first-test.html', + Build('MOCK Win7'), + 'blink_web_tests (with patch)') + self.command.rebaseline(self.options(), test_baseline_set) + + self._mock_copier.find_baselines_to_copy.assert_not_called() + self.tool.main.assert_not_called() + def test_rebaseline_debug(self): test_baseline_set = TestBaselineSet(self.tool.builders) test_baseline_set.add('userscripts/first-test.html',
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 8ecdd86..3e4cca8a 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -6671,3 +6671,11 @@ # Sheriff 2023-03-23 crbug.com/952717 [ Win10.20h2 ] http/tests/xmlhttprequest/redirect-cross-origin-post.html [ Failure Pass ] + +# Sheriff 2023-02-23 flaking on Mac +crbug.com/1427239 [ Mac ] virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/massive-element-below-and-on-top-of-viewport-partially-onscreen-new.html [ Failure Pass ] +crbug.com/1427239 [ Mac ] virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/massive-element-left-of-viewport-offscreen-new.html [ Failure Pass ] +crbug.com/1427239 [ Mac ] virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/massive-element-on-top-of-viewport-offscreen-new.html [ Failure Pass ] +crbug.com/1427239 [ Mac ] virtual/view-transition-wide-gamut/external/wpt/css/css-view-transitions/massive-element-right-of-viewport-offscreen-new.html [ Failure Pass ] +crbug.com/1427239 [ Mac ] virtual/view-transition/external/wpt/css/css-view-transitions/massive-element-right-and-left-of-viewport-partially-onscreen-new.html [ Failure Pass ] +crbug.com/1427239 [ Mac ] virtual/view-transition/external/wpt/css/css-view-transitions/massive-element-right-of-viewport-offscreen-new.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/dom/domparsing/attribute-lt-gt-use-counter.html b/third_party/blink/web_tests/dom/domparsing/attribute-lt-gt-use-counter.html new file mode 100644 index 0000000..f39a0b30 --- /dev/null +++ b/third_party/blink/web_tests/dom/domparsing/attribute-lt-gt-use-counter.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> + +<body> +<script> +test(() => { + assert_not_equals(window.internals,undefined,'This test must be run from the test runner'); + const kAttributeValueContainsLtOrGt = 4527; + assert_false(internals.isUseCounted(document,kAttributeValueContainsLtOrGt)); + + const div = document.createElement("div"); + div.title = "no-special-characters"; + const s1 = div.outerHTML; + assert_false(internals.isUseCounted(document,kAttributeValueContainsLtOrGt)); + + div.title = "aaa <u>test"; + const s2 = div.outerHTML; + assert_true(internals.isUseCounted(document,kAttributeValueContainsLtOrGt)); +}, 'Attribute value containing ">" or "<" should be use counted'); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html index f86cb4d..3f9e22b4 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html
@@ -12,7 +12,7 @@ // Steps 1-3 under the "Escaping a string" heading are relevant to attributes. window.htmlElement = document.createElement('div'); htmlElement.setAttribute('quoteme', attrValue); -assert_equals(htmlElement.outerHTML, "<div quoteme=\"< > & " ' \"></div>"); +assert_equals(htmlElement.outerHTML, "<div quoteme=\"< > & " ' \"></div>"); // XML case. // DOM parsing and serialization: https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#dfn-concept-serialize-xml-attributes
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/display-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-animations/display-interpolation.html new file mode 100644 index 0000000..791e794c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-animations/display-interpolation.html
@@ -0,0 +1,77 @@ +<!DOCTYPE html> +<link rel=author href="mailto:jarhar@chromium.org"> +<link rel=help href="https://github.com/w3c/csswg-drafts/issues/6429"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +const alwaysBlock = [ + {at: -1, expect: 'block'}, + {at: 0, expect: 'block'}, + {at: 0.1, expect: 'block'}, + {at: 0.9, expect: 'block'}, + {at: 1, expect: 'block'}, + {at: 1.5, expect: 'block'}, +]; +const alwaysNone = [ + {at: -1, expect: 'none'}, + {at: 0, expect: 'none'}, + {at: 0.1, expect: 'none'}, + {at: 0.9, expect: 'none'}, + {at: 1, expect: 'none'}, + {at: 1.5, expect: 'none'}, +]; + +test_interpolation({ + property: 'display', + from: 'block', + to: 'none', + // transition:all is not supposed to allow display to be transitioned. + 'CSS Transitions with transition: all': alwaysNone +}, [ + {at: -1, expect: 'block'}, + {at: 0, expect: 'block'}, + {at: 0.1, expect: 'block'}, + {at: 0.9, expect: 'block'}, + {at: 1, expect: 'none'}, + {at: 1.5, expect: 'none'}, +]); + +// This transitions tests expect 'block' at every point because transitioning +// from display:none does not provide an initial style. This is expected and +// can be worked around by using @initial. +test_interpolation({ + property: 'display', + from: 'none', + to: 'block', + 'CSS Transitions with transition: all': alwaysBlock, + 'CSS Transitions': alwaysBlock +}, [ + {at: -1, expect: 'none'}, + {at: 0, expect: 'none'}, + {at: 0.1, expect: 'block'}, + {at: 0.9, expect: 'block'}, + {at: 1, expect: 'block'}, + {at: 1.5, expect: 'block'}, +]); + +test_no_interpolation({ + property: 'display', + from: 'inline', + to: 'block' +}); + +test_interpolation({ + property: 'display', + from: 'block', + to: 'block' +}, alwaysBlock); + +test_interpolation({ + property: 'display', + from: 'none', + to: 'none' +}, alwaysNone); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-lists/css-lists-no-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-lists/css-lists-no-interpolation.html index 8250bc2..a0e1005 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-lists/css-lists-no-interpolation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-lists/css-lists-no-interpolation.html
@@ -14,6 +14,12 @@ }); test_no_interpolation({ + property: 'counter-increment', + from: 'add 5', + to: 'add 123' +}); + +test_no_interpolation({ property: 'counter-reset', from: 'initial', to: 'add 123'
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-serialization/cssTransformValue.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-serialization/cssTransformValue.tentative.html index 856b931..c098868 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-serialization/cssTransformValue.tentative.html +++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/stylevalue-serialization/cssTransformValue.tentative.html
@@ -107,7 +107,7 @@ new CSSMathProduct(CSS.number(3)) ), ]), - cssText: 'translate(calc(1px + 1em), 0px) rotate(calc(90deg + 1turn)) perspective(calc(1px + 1em)) skew(calc(90deg * 2), calc(1turn * 2)) scale3d(calc(1 * 2), calc(1 + 1), calc(3))', + cssText: 'translate(calc(1px + 1em), 0px) rotate(calc(90deg + 360deg)) perspective(calc(1px + 1em)) skew(calc(90deg * 2), calc(360deg * 2)) scale3d(calc(1 * 2), calc(1 + 1), calc(3))', desc: 'CSSTransformValue containing CSSMathValues' }, {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/resources/testsuite.js b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/resources/testsuite.js index 9708c5c..cecd72a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/resources/testsuite.js +++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/properties/resources/testsuite.js
@@ -148,8 +148,7 @@ { description: "a calc time", input: new CSSMathSum(new CSSUnitValue(0, 's'), new CSSUnitValue(0, 'ms')), - // Specified/computed calcs are usually simplified. - // FIXME: Test this properly + specifiedExpected: new CSSMathSum(new CSSUnitValue(0, 's'), new CSSUnitValue(0, 's')), defaultSpecified: (_, result) => assert_is_calc_sum(result), defaultComputed: (_, result) => assert_is_unit('s', result) } @@ -311,7 +310,7 @@ 'Specified value must be a CSSStyleValue'); if (specified || example.defaultSpecified) { - (specified || example.defaultSpecified)(example.input, specifiedResult); + (specified || example.defaultSpecified)(example.specifiedExpected || example.input, specifiedResult); } else { assert_style_value_equals(specifiedResult, example.input, `Setting ${example.description} and getting its specified value`);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-angle-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-angle-expected.txt deleted file mode 100644 index 3dfd64dd..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-angle-expected.txt +++ /dev/null
@@ -1,33 +0,0 @@ -This is a testharness.js-based test. -PASS 'rotate(calc(1deg * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -FAIL 'rotate(calc(1rad * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. assert_equals: 'rotate(calc(1rad * NaN))' and 'rotate(calc(NaN * 1deg))' should serialize the same in specified values. expected "rotate(calc(NaN * 1deg))" but got "rotate(calc(NaN * 1rad))" -FAIL 'rotate(calc(1turn * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. assert_equals: 'rotate(calc(1turn * NaN))' and 'rotate(calc(NaN * 1deg))' should serialize the same in specified values. expected "rotate(calc(NaN * 1deg))" but got "rotate(calc(NaN * 1turn))" -FAIL 'rotate(calc(1grad * nan))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. assert_equals: 'rotate(calc(1grad * nan))' and 'rotate(calc(NaN * 1deg))' should serialize the same in specified values. expected "rotate(calc(NaN * 1deg))" but got "rotate(calc(NaN * 1grad))" -PASS 'rotate(calc(1deg * infinity / infinity))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * 0 * infinity))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * (infinity + -infinity)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * (-infinity + infinity)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * (infinity - infinity)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * infinity))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'. -PASS 'rotate(calc(1deg * -infinity))' as a specified value should serialize as 'rotate(calc(-infinity * 1deg))'. -PASS 'rotate(calc(1deg * iNFinIty))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'. -PASS 'rotate(calc(1deg * (infinity + infinity)))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'. -PASS 'rotate(calc(1deg * (-infinity + -infinity)))' as a specified value should serialize as 'rotate(calc(-infinity * 1deg))'. -PASS 'rotate(calc(1deg * 1/infinity))' as a specified value should serialize as 'rotate(calc(0deg))'. -PASS 'rotate(calc(1deg * infinity * infinity))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'. -PASS 'rotate(calc(1deg * -infinity * -infinity))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'. -PASS 'rotate(calc(1 * max(INFinity*3deg, 0deg)))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'. -PASS 'rotate(calc(1 * min(inFInity*4deg, 0deg)))' as a specified value should serialize as 'rotate(calc(0deg))'. -PASS 'rotate(calc(1 * max(nAn*2deg, 0deg)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1 * min(nan*3deg, 0deg)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1 * clamp(-INFINITY*20deg, 0deg, infiniTY*10deg)))' as a specified value should serialize as 'rotate(calc(0deg))'. -PASS 'rotate(calc(1deg * max(NaN, min(0,10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * clamp(NaN, 0, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * max(0, min(10, NaN))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * clamp(0, 10, NaN)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * max(0, min(NaN, 10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * clamp(0, NaN, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'. -PASS 'rotate(calc(1deg * clamp(-Infinity, 0, infinity)))' as a specified value should serialize as 'rotate(calc(0deg))'. -PASS 'rotate(calc(1deg * clamp(-inFinity, infinity, 10)))' as a specified value should serialize as 'rotate(calc(10deg))'. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-angle.html.ini b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-angle.html.ini deleted file mode 100644 index 95ef823..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-angle.html.ini +++ /dev/null
@@ -1,48 +0,0 @@ -[calc-infinity-nan-serialize-angle.html] - ['rotate(calc(1 * clamp(-INFINITY*20deg, 0deg, infiniTY*10deg)))' as a specified value should serialize as 'rotate(calc(0deg))'.] - expected: FAIL - - ['rotate(calc(1 * max(INFinity*3deg, 0deg)))' as a specified value should serialize as 'rotate(calc(infinity * 1deg))'.] - expected: FAIL - - ['rotate(calc(1 * max(nAn*2deg, 0deg)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1 * min(inFInity*4deg, 0deg)))' as a specified value should serialize as 'rotate(calc(0deg))'.] - expected: FAIL - - ['rotate(calc(1 * min(nan*3deg, 0deg)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1deg * clamp(-Infinity, 0, infinity)))' as a specified value should serialize as 'rotate(calc(0deg))'.] - expected: FAIL - - ['rotate(calc(1deg * clamp(-inFinity, infinity, 10)))' as a specified value should serialize as 'rotate(calc(10deg))'.] - expected: FAIL - - ['rotate(calc(1deg * clamp(0, 10, NaN)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1deg * clamp(0, NaN, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1deg * clamp(NaN, 0, 10)))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1deg * max(0, min(10, NaN))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1deg * max(0, min(NaN, 10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1deg * max(NaN, min(0,10))))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1grad * nan))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1rad * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL - - ['rotate(calc(1turn * NaN))' as a specified value should serialize as 'rotate(calc(NaN * 1deg))'.] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-time-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-time-expected.txt deleted file mode 100644 index 43afde9..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-time-expected.txt +++ /dev/null
@@ -1,32 +0,0 @@ -This is a testharness.js-based test. -PASS 'calc(1s * NaN)' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * nan)' as a specified value should serialize as 'calc(NaN * 1s)'. -FAIL 'calc(1ms * NaN)' as a specified value should serialize as 'calc(NaN * 1s)'. assert_equals: 'calc(1ms * NaN)' and 'calc(NaN * 1s)' should serialize the same in specified values. expected "calc(NaN * 1s)" but got "calc(NaN * 1ms)" -PASS 'calc(1s * infinity / infinity)' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * 0 * infinity)' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * (infinity + -infinity))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * (-infinity + infinity))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * (infinity - infinity))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * infinity)' as a specified value should serialize as 'calc(infinity * 1s)'. -PASS 'calc(1s * -infinity)' as a specified value should serialize as 'calc(-infinity * 1s)'. -PASS 'calc(1s * iNFinIty)' as a specified value should serialize as 'calc(infinity * 1s)'. -PASS 'calc(1s * (infinity + infinity))' as a specified value should serialize as 'calc(infinity * 1s)'. -PASS 'calc(1s * (-infinity + -infinity))' as a specified value should serialize as 'calc(-infinity * 1s)'. -PASS 'calc(1s * 1/infinity)' as a specified value should serialize as 'calc(0s)'. -PASS 'calc(1s * infinity * infinity)' as a specified value should serialize as 'calc(infinity * 1s)'. -PASS 'calc(1s * -infinity * -infinity)' as a specified value should serialize as 'calc(infinity * 1s)'. -PASS 'calc(1 * max(INFinity*3s, 0s))' as a specified value should serialize as 'calc(infinity * 1s)'. -PASS 'calc(1 * min(inFInity*4s, 0s))' as a specified value should serialize as 'calc(0s)'. -PASS 'calc(1 * max(nAn*2s, 0s))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1 * min(nan*3s, 0s))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1 * clamp(-INFINITY*20s, 0s, infiniTY*10s))' as a specified value should serialize as 'calc(0s)'. -PASS 'calc(1s * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1s)'. -PASS 'calc(1s * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0s)'. -PASS 'calc(1s * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10s)'. -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-time.html.ini b/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-time.html.ini deleted file mode 100644 index eaa5df0..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-values/calc-infinity-nan-serialize-time.html.ini +++ /dev/null
@@ -1,42 +0,0 @@ -[calc-infinity-nan-serialize-time.html] - ['calc(1 * clamp(-INFINITY*20s, 0s, infiniTY*10s))' as a specified value should serialize as 'calc(0s)'.] - expected: FAIL - - ['calc(1 * max(INFinity*3s, 0s))' as a specified value should serialize as 'calc(infinity * 1s)'.] - expected: FAIL - - ['calc(1 * max(nAn*2s, 0s))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1 * min(inFInity*4s, 0s))' as a specified value should serialize as 'calc(0s)'.] - expected: FAIL - - ['calc(1 * min(nan*3s, 0s))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1ms * NaN)' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1s * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0s)'.] - expected: FAIL - - ['calc(1s * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10s)'.] - expected: FAIL - - ['calc(1s * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1s * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1s * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1s * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1s * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL - - ['calc(1s * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN * 1s)'.] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/support/interpolation-testcommon.js b/third_party/blink/web_tests/external/wpt/css/support/interpolation-testcommon.js index 283a2d8..2ee00e4 100644 --- a/third_party/blink/web_tests/external/wpt/css/support/interpolation-testcommon.js +++ b/third_party/blink/web_tests/external/wpt/css/support/interpolation-testcommon.js
@@ -274,6 +274,8 @@ } else if (expectations === expectNotAnimatable) { expectations = interpolationMethod.notAnimatableExpectations(from, to, interpolationTest.options.underlying); applyUnderlying = true; + } else if (interpolationTest.options[interpolationMethod.name]) { + expectations = interpolationTest.options[interpolationMethod.name]; } // Setup a standard equality function if an override is not provided.
diff --git a/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt b/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt new file mode 100644 index 0000000..dc32f824 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/syntax/serializing-html-fragments/serializing-expected.txt
@@ -0,0 +1,242 @@ +This is a testharness.js-based test. +Found 238 tests; 232 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS innerHTML 0 +PASS innerHTML 1 <a></a> +PASS innerHTML 2 <a b="c"></a> +PASS innerHTML 3 <a b="c"></a> +PASS innerHTML 4 <a b="&"></a> +PASS innerHTML 5 <a b=" "></a> +PASS innerHTML 6 <a b="""></a> +FAIL innerHTML 7 <a b="<"></a> assert_equals: expected "<a b=\"<\"></a>" but got "<a b=\"<\"></a>" +FAIL innerHTML 8 <a b=">"></a> assert_equals: expected "<a b=\">\"></a>" but got "<a b=\">\"></a>" +FAIL innerHTML 9 <a href="javascript:"<>""></a> assert_equals: expected "<a href=\"javascript:"<>"\"></a>" but got "<a href=\"javascript:"<>"\"></a>" +PASS innerHTML 10 <svg xlink:href="a"></svg> +PASS innerHTML 11 <svg xmlns:svg="test"></svg> +PASS innerHTML 12 a +PASS innerHTML 13 & +PASS innerHTML 14 +PASS innerHTML 15 < +PASS innerHTML 16 > +PASS innerHTML 17 " +PASS innerHTML 18 <style><&></style> +PASS innerHTML 19 <script type="test"><&></script> +PASS innerHTML 20 <&> +PASS innerHTML 21 <xmp><&></xmp> +PASS innerHTML 22 <iframe><&></iframe> +PASS innerHTML 23 <noembed><&></noembed> +PASS innerHTML 24 <noframes><&></noframes> +PASS innerHTML 25 <noscript><&></noscript> +PASS innerHTML 26 <!--data--> +PASS innerHTML 27 <a><b><c></c></b><d>e</d><f><g>h</g></f></a> +PASS innerHTML 28 +PASS outerHTML 0 <span></span> +PASS outerHTML 1 <span><a></a></span> +PASS outerHTML 2 <span><a b="c"></a></span> +PASS outerHTML 3 <span><a b="c"></a></span> +PASS outerHTML 4 <span><a b="&"></a></span> +PASS outerHTML 5 <span><a b=" "></a></span> +PASS outerHTML 6 <span><a b="""></a></span> +FAIL outerHTML 7 <span><a b="<"></a></span> assert_equals: expected "<span><a b=\"<\"></a></span>" but got "<span><a b=\"<\"></a></span>" +FAIL outerHTML 8 <span><a b=">"></a></span> assert_equals: expected "<span><a b=\">\"></a></span>" but got "<span><a b=\">\"></a></span>" +FAIL outerHTML 9 <span><a href="javascript:"<>""></a></span> assert_equals: expected "<span><a href=\"javascript:"<>"\"></a></span>" but got "<span><a href=\"javascript:"<>"\"></a></span>" +PASS outerHTML 10 <span><svg xlink:href="a"></svg></span> +PASS outerHTML 11 <span><svg xmlns:svg="test"></svg></span> +PASS outerHTML 12 <span>a</span> +PASS outerHTML 13 <span>&</span> +PASS outerHTML 14 <span> </span> +PASS outerHTML 15 <span><</span> +PASS outerHTML 16 <span>></span> +PASS outerHTML 17 <span>"</span> +PASS outerHTML 18 <span><style><&></style></span> +PASS outerHTML 19 <span><script type="test"><&></script></span> +PASS outerHTML 20 <script type="test"><&></script> +PASS outerHTML 21 <span><xmp><&></xmp></span> +PASS outerHTML 22 <span><iframe><&></iframe></span> +PASS outerHTML 23 <span><noembed><&></noembed></span> +PASS outerHTML 24 <span><noframes><&></noframes></span> +PASS outerHTML 25 <span><noscript><&></noscript></span> +PASS outerHTML 26 <span><!--data--></span> +PASS outerHTML 27 <span><a><b><c></c></b><d>e</d><f><g>h</g></f></a></span> +PASS outerHTML 28 <span b="c"></span> +PASS innerHTML Attribute in the XML namespace +PASS innerHTML Attribute in the XML namespace with the prefix not set to xml: +PASS innerHTML Non-'xmlns' attribute in the xmlns namespace +PASS innerHTML 'xmlns' attribute in the xmlns namespace +PASS innerHTML Attribute in non-standard namespace +PASS innerHTML <span> starting with U+000A +PASS outerHTML Attribute in the XML namespace +PASS outerHTML Attribute in the XML namespace with the prefix not set to xml: +PASS outerHTML Non-'xmlns' attribute in the xmlns namespace +PASS outerHTML 'xmlns' attribute in the xmlns namespace +PASS outerHTML Attribute in non-standard namespace +PASS outerHTML <span> starting with U+000A +PASS innerHTML <pre> context starting with U+000A +PASS innerHTML <textarea> context starting with U+000A +PASS innerHTML <listing> context starting with U+000A +PASS innerHTML <pre> context not starting with U+000A +PASS innerHTML <textarea> context not starting with U+000A +PASS innerHTML <listing> context not starting with U+000A +PASS innerHTML <pre> non-context starting with U+000A +PASS innerHTML <textarea> non-context starting with U+000A +PASS innerHTML <listing> non-context starting with U+000A +PASS innerHTML <pre> non-context not starting with U+000A +PASS innerHTML <textarea> non-context not starting with U+000A +PASS innerHTML <listing> non-context not starting with U+000A +PASS outerHTML <pre> context starting with U+000A +PASS outerHTML <textarea> context starting with U+000A +PASS outerHTML <listing> context starting with U+000A +PASS outerHTML <pre> context not starting with U+000A +PASS outerHTML <textarea> context not starting with U+000A +PASS outerHTML <listing> context not starting with U+000A +PASS outerHTML <pre> non-context starting with U+000A +PASS outerHTML <textarea> non-context starting with U+000A +PASS outerHTML <listing> non-context starting with U+000A +PASS outerHTML <pre> non-context not starting with U+000A +PASS outerHTML <textarea> non-context not starting with U+000A +PASS outerHTML <listing> non-context not starting with U+000A +PASS innerHTML Void context node area +PASS innerHTML Void context node base +PASS innerHTML Void context node basefont +PASS innerHTML Void context node bgsound +PASS innerHTML Void context node br +PASS innerHTML Void context node col +PASS innerHTML Void context node embed +PASS innerHTML Void context node frame +PASS innerHTML Void context node hr +PASS innerHTML Void context node img +PASS innerHTML Void context node input +PASS innerHTML Void context node keygen +PASS innerHTML Void context node link +PASS innerHTML Void context node meta +PASS innerHTML Void context node param +PASS innerHTML Void context node source +PASS innerHTML Void context node track +PASS innerHTML Void context node wbr +PASS innerHTML void as first child with following siblings area +PASS innerHTML void as first child with following siblings base +PASS innerHTML void as first child with following siblings basefont +PASS innerHTML void as first child with following siblings bgsound +PASS innerHTML void as first child with following siblings br +PASS innerHTML void as first child with following siblings col +PASS innerHTML void as first child with following siblings embed +PASS innerHTML void as first child with following siblings frame +PASS innerHTML void as first child with following siblings hr +PASS innerHTML void as first child with following siblings img +PASS innerHTML void as first child with following siblings input +PASS innerHTML void as first child with following siblings keygen +PASS innerHTML void as first child with following siblings link +PASS innerHTML void as first child with following siblings meta +PASS innerHTML void as first child with following siblings param +PASS innerHTML void as first child with following siblings source +PASS innerHTML void as first child with following siblings track +PASS innerHTML void as first child with following siblings wbr +PASS innerHTML void as second child with following siblings area +PASS innerHTML void as second child with following siblings base +PASS innerHTML void as second child with following siblings basefont +PASS innerHTML void as second child with following siblings bgsound +PASS innerHTML void as second child with following siblings br +PASS innerHTML void as second child with following siblings col +PASS innerHTML void as second child with following siblings embed +PASS innerHTML void as second child with following siblings frame +PASS innerHTML void as second child with following siblings hr +PASS innerHTML void as second child with following siblings img +PASS innerHTML void as second child with following siblings input +PASS innerHTML void as second child with following siblings keygen +PASS innerHTML void as second child with following siblings link +PASS innerHTML void as second child with following siblings meta +PASS innerHTML void as second child with following siblings param +PASS innerHTML void as second child with following siblings source +PASS innerHTML void as second child with following siblings track +PASS innerHTML void as second child with following siblings wbr +PASS innerHTML void as last child with preceding siblings area +PASS innerHTML void as last child with preceding siblings base +PASS innerHTML void as last child with preceding siblings basefont +PASS innerHTML void as last child with preceding siblings bgsound +PASS innerHTML void as last child with preceding siblings br +PASS innerHTML void as last child with preceding siblings col +PASS innerHTML void as last child with preceding siblings embed +PASS innerHTML void as last child with preceding siblings frame +PASS innerHTML void as last child with preceding siblings hr +PASS innerHTML void as last child with preceding siblings img +PASS innerHTML void as last child with preceding siblings input +PASS innerHTML void as last child with preceding siblings keygen +PASS innerHTML void as last child with preceding siblings link +PASS innerHTML void as last child with preceding siblings meta +PASS innerHTML void as last child with preceding siblings param +PASS innerHTML void as last child with preceding siblings source +PASS innerHTML void as last child with preceding siblings track +PASS innerHTML void as last child with preceding siblings wbr +PASS outerHTML Void context node area +PASS outerHTML Void context node base +PASS outerHTML Void context node basefont +PASS outerHTML Void context node bgsound +PASS outerHTML Void context node br +PASS outerHTML Void context node col +PASS outerHTML Void context node embed +PASS outerHTML Void context node frame +PASS outerHTML Void context node hr +PASS outerHTML Void context node img +PASS outerHTML Void context node input +PASS outerHTML Void context node keygen +PASS outerHTML Void context node link +PASS outerHTML Void context node meta +PASS outerHTML Void context node param +PASS outerHTML Void context node source +PASS outerHTML Void context node track +PASS outerHTML Void context node wbr +PASS outerHTML void as first child with following siblings area +PASS outerHTML void as first child with following siblings base +PASS outerHTML void as first child with following siblings basefont +PASS outerHTML void as first child with following siblings bgsound +PASS outerHTML void as first child with following siblings br +PASS outerHTML void as first child with following siblings col +PASS outerHTML void as first child with following siblings embed +PASS outerHTML void as first child with following siblings frame +PASS outerHTML void as first child with following siblings hr +PASS outerHTML void as first child with following siblings img +PASS outerHTML void as first child with following siblings input +PASS outerHTML void as first child with following siblings keygen +PASS outerHTML void as first child with following siblings link +PASS outerHTML void as first child with following siblings meta +PASS outerHTML void as first child with following siblings param +PASS outerHTML void as first child with following siblings source +PASS outerHTML void as first child with following siblings track +PASS outerHTML void as first child with following siblings wbr +PASS outerHTML void as second child with following siblings area +PASS outerHTML void as second child with following siblings base +PASS outerHTML void as second child with following siblings basefont +PASS outerHTML void as second child with following siblings bgsound +PASS outerHTML void as second child with following siblings br +PASS outerHTML void as second child with following siblings col +PASS outerHTML void as second child with following siblings embed +PASS outerHTML void as second child with following siblings frame +PASS outerHTML void as second child with following siblings hr +PASS outerHTML void as second child with following siblings img +PASS outerHTML void as second child with following siblings input +PASS outerHTML void as second child with following siblings keygen +PASS outerHTML void as second child with following siblings link +PASS outerHTML void as second child with following siblings meta +PASS outerHTML void as second child with following siblings param +PASS outerHTML void as second child with following siblings source +PASS outerHTML void as second child with following siblings track +PASS outerHTML void as second child with following siblings wbr +PASS outerHTML void as last child with preceding siblings area +PASS outerHTML void as last child with preceding siblings base +PASS outerHTML void as last child with preceding siblings basefont +PASS outerHTML void as last child with preceding siblings bgsound +PASS outerHTML void as last child with preceding siblings br +PASS outerHTML void as last child with preceding siblings col +PASS outerHTML void as last child with preceding siblings embed +PASS outerHTML void as last child with preceding siblings frame +PASS outerHTML void as last child with preceding siblings hr +PASS outerHTML void as last child with preceding siblings img +PASS outerHTML void as last child with preceding siblings input +PASS outerHTML void as last child with preceding siblings keygen +PASS outerHTML void as last child with preceding siblings link +PASS outerHTML void as last child with preceding siblings meta +PASS outerHTML void as last child with preceding siblings param +PASS outerHTML void as last child with preceding siblings source +PASS outerHTML void as last child with preceding siblings track +PASS outerHTML void as last child with preceding siblings wbr +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event-expected.txt index 3f7435e..613e047 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event-expected.txt
@@ -1,27 +1,31 @@ Check that the dialogShown event works after enabling the FedCm domain -accounts: [ - [0] : { - accountId : 1234 - email : john_doe@idp.example - givenName : John - idpConfigUrl : https://devtools.test:8443/resources/fedcm/fedcm.json - idpSigninUrl : https://idp.example/signin - loginState : SignIn - name : John Doe - pictureUrl : https://idp.example/profile/123 - } - [1] : { - accountId : 5678 - email : aisha@idp.example - givenName : Aisha - idpConfigUrl : https://devtools.test:8443/resources/fedcm/fedcm.json - idpSigninUrl : https://idp.example/signin - loginState : SignUp - name : Aisha Ahmad - pictureUrl : https://idp.example/profile/567 - privacyPolicyUrl : https://rp.example/privacy_policy.html - termsOfServiceUrl : https://rp.example/terms_of_service.html - } -] +msg.params: { + accounts : [ + [0] : { + accountId : 1234 + email : john_doe@idp.example + givenName : John + idpConfigUrl : https://devtools.test:8443/resources/fedcm/fedcm.json + idpSigninUrl : https://idp.example/signin + loginState : SignIn + name : John Doe + pictureUrl : https://idp.example/profile/123 + } + [1] : { + accountId : 5678 + email : aisha@idp.example + givenName : Aisha + idpConfigUrl : https://devtools.test:8443/resources/fedcm/fedcm.json + idpSigninUrl : https://idp.example/signin + loginState : SignUp + name : Aisha Ahmad + pictureUrl : https://idp.example/profile/567 + privacyPolicyUrl : https://rp.example/privacy_policy.html + termsOfServiceUrl : https://rp.example/terms_of_service.html + } + ] + dialogId : <string> + title : Sign in +} token: 1234
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event.js b/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event.js index 388d330..c092708 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-dialog-event.js
@@ -14,7 +14,7 @@ if (msg.error) { testRunner.log(msg.error); } else { - testRunner.log(msg.params.accounts, "accounts: "); + testRunner.log(msg.params, "msg.params: ", ["dialogId"]); dp.FedCm.selectAccount({dialogId: msg.params.dialogId, accountIndex: 0}); const token = await dialogPromise; testRunner.log("token: " + token);
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-bucket-storage-key-track-untrack-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-bucket-storage-key-track-untrack-expected.txt new file mode 100644 index 0000000..9b8b232 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-bucket-storage-key-track-untrack-expected.txt
@@ -0,0 +1,39 @@ +Tests that tracking and untracking Storage Bucket for storage key works + +Create bucket +bucket created successfully +Created bucket: { + durability : relaxed + expiration : <number> + id : <string> + isDefault : false + name : test-bucket + persistent : false + quota : 0 + storageKey : <string> +} +bucket.expiration equals zero + +Update bucket +bucket updated successfully +Updated bucket: { + durability : relaxed + expiration : <number> + id : <string> + isDefault : false + name : test-bucket + persistent : false + quota : 0 + storageKey : <string> +} +bucket.expiration does not equal zero + +Delete bucket +bucket deleted successfully +Deleted bucket: { + bucketId : <string> +} + +Create another bucket after untracking. +Another bucket opened successfully +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-bucket-storage-key-track-untrack.js b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-bucket-storage-key-track-untrack.js new file mode 100644 index 0000000..bc19473 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-bucket-storage-key-track-untrack.js
@@ -0,0 +1,113 @@ +(async function(testRunner) { + const stabilizeNames = + [...TestRunner.stabilizeNames, 'storageKey', 'bucketId', 'expiration']; + const {dp, session} = await testRunner.startBlank( + `Tests that tracking and untracking Storage Bucket for storage key works\n`); + await dp.Page.enable(); + + const frameId = (await dp.Page.getResourceTree()).result.frameTree.frame.id; + const storageKey = (await dp.Storage.getStorageKeyForFrame({ + frameId: frameId + })).result.storageKey; + + await dp.Storage.setStorageBucketTracking({storageKey, enable: true}); + + { + testRunner.log(`Create bucket`); + + const eventPromise = dp.Storage.onceStorageBucketCreatedOrUpdated(); + + // Create bucket. + const result = await session.evaluateAsync(` + (async function() { + try { + await navigator.storageBuckets.open("test-bucket"); + return 'bucket created successfully'; + } catch (err) { + return err; + } + })()`); + + testRunner.log(result); + const {params: {bucket}} = await eventPromise; + testRunner.log(bucket, `Created bucket: `, stabilizeNames); + if (bucket.expiration === 0) { + testRunner.log('bucket.expiration equals zero\n'); + } else { + testRunner.log(`bucket.expiration equals ${bucket.expiration}`); + } + } + + { + testRunner.log(`Update bucket`); + + const eventPromise = dp.Storage.onceStorageBucketCreatedOrUpdated(); + + // Update bucket. + const result = await session.evaluateAsync(` + (async function() { + try { + await navigator.storageBuckets.open("test-bucket", {expires: Number.MAX_SAFE_INTEGER}); + return 'bucket updated successfully'; + } catch (err) { + return err; + } + })()`); + + testRunner.log(result); + const {params: {bucket}} = await eventPromise; + testRunner.log(bucket, `Updated bucket: `, stabilizeNames); + if (bucket.expiration !== 0) { + testRunner.log('bucket.expiration does not equal zero\n'); + } else { + testRunner.log(`bucket.expiration equals ${bucket.expiration}`); + } + } + + { + testRunner.log(`Delete bucket`); + + const eventPromise = dp.Storage.onceStorageBucketDeleted(); + + // Delete bucket. + const result = await session.evaluateAsync(` + (async function() { + try { + await navigator.storageBuckets.delete("test-bucket"); + return 'bucket deleted successfully'; + } catch (err) { + return err; + } + })()`); + + testRunner.log(result); + const {params} = await eventPromise; + testRunner.log(params, `Deleted bucket: `, stabilizeNames); + } + + await dp.Storage.setStorageBucketTracking({storageKey, enable: false}); + + { + dp.Storage.onStorageBucketCreatedOrUpdated( + message => {testRunner.log(message.params.bucket)}); + dp.Storage.onStorageBucketDeleted( + message => {testRunner.log(message.params.bucketLocator)}); + + testRunner.log('\nCreate another bucket after untracking.'); + + // Create one more bucket. + const result = await session.evaluateAsync(` + (async function() { + try { + await navigator.storageBuckets.open("test-bucket-2"); + return 'Another bucket opened successfully'; + } catch (err) { + return err; + } + })()`); + + testRunner.log(result); + } + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-buckets-delete-storage-bucket-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-buckets-delete-storage-bucket-expected.txt new file mode 100644 index 0000000..6e7d825 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-buckets-delete-storage-bucket-expected.txt
@@ -0,0 +1,9 @@ +Tests that deleting a bucket works correctly + +Create bucket +buckets added successfully +Delete bucket +Deleted bucket: { + bucketId : <string> +} +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-buckets-delete-storage-bucket.js b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-buckets-delete-storage-bucket.js new file mode 100644 index 0000000..c746ef7 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/storage-buckets-delete-storage-bucket.js
@@ -0,0 +1,40 @@ +(async function(testRunner) { + const {dp, session} = await testRunner.startBlank( + `Tests that deleting a bucket works correctly\n`); + await dp.Page.enable(); + + const stabilizeNames = + [...TestRunner.stabilizeNames, 'storageKey', 'bucketId']; + + const frameId = (await dp.Page.getResourceTree()).result.frameTree.frame.id; + const storageKey = + (await dp.Storage.getStorageKeyForFrame({frameId})).result.storageKey; + await dp.Storage.setStorageBucketTracking({storageKey, enable: true}); + const bucketName = 'test-bucket'; + + { + testRunner.log(`Create bucket`); + const result = await session.evaluateAsync(` + (async function() { + try { + await navigator.storageBuckets.open("${bucketName}"); + return 'buckets added successfully'; + } catch (err) { + return err; + } + })() + `); + + testRunner.log(result); + } + + { + testRunner.log(`Delete bucket`); + + dp.Storage.deleteStorageBucket({storageKey, bucketName}); + const {params} = await dp.Storage.onceStorageBucketDeleted(); + testRunner.log(params, 'Deleted bucket: ', stabilizeNames); + } + + testRunner.completeTest(); +})
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPUComputePassEncoder.dispatchWorkgroupsIndirect.https.html b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPUComputePassEncoder.dispatchWorkgroupsIndirect.https.html new file mode 100644 index 0000000..1004d7c8 --- /dev/null +++ b/third_party/blink/web_tests/wpt_internal/webgpu/fast_api/GPUComputePassEncoder.dispatchWorkgroupsIndirect.https.html
@@ -0,0 +1,47 @@ +<!DOCTYPE html> +<html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +<script> +function optimizedMethodCall(computePassEncoder, indirectBuffer, indirectOffset) { + computePassEncoder.dispatchWorkgroupsIndirect(indirectBuffer, indirectOffset); +} + +promise_test(async t => { + const adapter = await navigator.gpu.requestAdapter(); + assert_true(adapter instanceof GPUAdapter, 'Failed to request WebGPU adapter'); + const device = await adapter.requestDevice(); + assert_true(device instanceof GPUDevice, 'Failed to request WebGPU device'); + + const encoder = device.createCommandEncoder(); + const computePassEncoder = encoder.beginComputePass(); + + const indirectBuffer = device.createBuffer({ + size: 20, + usage: GPUBufferUsage.INDIRECT | GPUBufferUsage.COPY_DST, + }); + + function hotLoop(count, computePassEncoder, indirectBuffer, indirectOffset) { + for (let i = 0; i < count; ++i) { + optimizedMethodCall(computePassEncoder, indirectBuffer, indirectOffset); + } + } + hotLoop(100, computePassEncoder, indirectBuffer, 4); + + // Wait a bit for V8 to optimize. Then call again with an out-of-bounds value. + // An exception should be thrown. + await new Promise(resolve => t.step_timeout(resolve, 50)); + + // kJSMaxInteger = 0x20000000000000 - 1; + try { + hotLoop(1, computePassEncoder, indirectBuffer, 0x20000000000000); + } catch(e) { + assert_true(e instanceof TypeError); + } +}); +</script> +</body> +</html>
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index f247fda4..71c7a0dd 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby -Version: 39df20d821ba6988fa3e2aa0ae42eadf4298c617 +Version: 3f1b0c81e3c441f89b94843a60461677972f163e License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/omnibox_proto/README.chromium b/third_party/omnibox_proto/README.chromium index f658965..5c0f1a3 100644 --- a/third_party/omnibox_proto/README.chromium +++ b/third_party/omnibox_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Omnibox Protos Short Name: omnibox_proto URL: This is the canonical public repository -Version: 517274885 -Date: 2023/03/17 UTC +Version: 518911953 +Date: 2023/03/23 UTC License: BSD Security Critical: Yes
diff --git a/third_party/omnibox_proto/entity_info.proto b/third_party/omnibox_proto/entity_info.proto index c4c70e28..e786538 100644 --- a/third_party/omnibox_proto/entity_info.proto +++ b/third_party/omnibox_proto/entity_info.proto
@@ -46,6 +46,9 @@ // List of categories this entity belongs to. repeated CategoryInfo.Category category = 14; + + // The entity's official website uri. + optional string website_uri = 17; } // Entity Suggestion Action descriptor. @@ -68,6 +71,15 @@ // When present, specifies the intent to send to the package to execute the // Action. optional string intent_name = 7; + + // Kesem Action Type. + optional KesemActionType kesem_action_type = 8; + + enum KesemActionType { + DIRECTIONS = 2; + CALL = 3; + WEBSITE = 6; + } } // Entity Suggestion Category info. @@ -93,4 +105,4 @@ PRODUCT_LINES = 24; LOCAL_POI = 25; } -} +} \ No newline at end of file
diff --git a/third_party/wpt_tools/README.chromium b/third_party/wpt_tools/README.chromium index ac8ec6d1..b23ec1f 100644 --- a/third_party/wpt_tools/README.chromium +++ b/third_party/wpt_tools/README.chromium
@@ -1,7 +1,7 @@ Name: web-platform-tests - Test Suites for Web Platform specifications Short Name: wpt URL: https://github.com/web-platform-tests/wpt/ -Version: 071134cb4d44b95f8068828830498a19c60ad120 +Version: 1c7c03b58d24fa64c4cd3240b8ce5bc6c4f62eb6 License: LICENSES FOR W3C TEST SUITES (https://www.w3.org/Consortium/Legal/2008/03-bsd-license.html) License File: NOT_SHIPPED Security Critical: no
diff --git a/third_party/wpt_tools/wpt/tools/ci/requirements_build.txt b/third_party/wpt_tools/wpt/tools/ci/requirements_build.txt index da3f93c..03fe7d7 100644 --- a/third_party/wpt_tools/wpt/tools/ci/requirements_build.txt +++ b/third_party/wpt_tools/wpt/tools/ci/requirements_build.txt
@@ -1,4 +1,4 @@ -cairocffi==1.3.0 +cairocffi==1.5.0 fonttools==4.33.2 genshi==0.7.7 jinja2==3.1.2
diff --git a/third_party/wpt_tools/wpt/tools/ci/update_built.py b/third_party/wpt_tools/wpt/tools/ci/update_built.py index d3850d3..44b950b 100644 --- a/third_party/wpt_tools/wpt/tools/ci/update_built.py +++ b/third_party/wpt_tools/wpt/tools/ci/update_built.py
@@ -15,6 +15,7 @@ "conformance-checkers/tools/ins-del-datetime.py", "conformance-checkers/tools/picture.py", "conformance-checkers/tools/url.py"], + "css-images": ["css/css-images/tools/generate_object_view_box_tests.py"], "css-ui": ["css/css-ui/tools/appearance-build-webkit-reftests.py"], # FIXME: https://github.com/web-platform-tests/wpt/issues/32060 # "css-text": ["css/css-text/line-breaking/tools/generate-segment-break-transformation-rules-tests.py"],
diff --git a/third_party/wpt_tools/wpt/tools/manifest/requirements.txt b/third_party/wpt_tools/wpt/tools/manifest/requirements.txt index 9f5bc8a..0236020 100644 --- a/third_party/wpt_tools/wpt/tools/manifest/requirements.txt +++ b/third_party/wpt_tools/wpt/tools/manifest/requirements.txt
@@ -1 +1 @@ -zstandard==0.17.0 +zstandard==0.20.0
diff --git a/third_party/wpt_tools/wpt/tools/webtransport/requirements.txt b/third_party/wpt_tools/wpt/tools/webtransport/requirements.txt index 4e347c6..d3b88d7 100644 --- a/third_party/wpt_tools/wpt/tools/webtransport/requirements.txt +++ b/third_party/wpt_tools/wpt/tools/webtransport/requirements.txt
@@ -1,4 +1 @@ -# aioquic 0.9.15 is the last to support Python 3.6, but doesn't have prebuilt -# wheels for Python 3.10, so use a different version depending on Python. -aioquic==0.9.15; python_version == '3.6' -aioquic==0.9.19; python_version != '3.6' +aioquic==0.9.20
diff --git a/third_party/wpt_tools/wpt/tools/wpt/testfiles.py b/third_party/wpt_tools/wpt/tools/wpt/testfiles.py index 172ad20..74c97ce 100644 --- a/third_party/wpt_tools/wpt/tools/wpt/testfiles.py +++ b/third_party/wpt_tools/wpt/tools/wpt/testfiles.py
@@ -35,7 +35,7 @@ from typing import Text from typing import Tuple -DEFAULT_IGNORE_RULERS = ("resources/testharness*", "resources/testdriver*") +DEFAULT_IGNORE_RULES = ("resources/testharness*", "resources/testdriver*") here = os.path.dirname(__file__) wpt_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir)) @@ -189,7 +189,7 @@ def exclude_ignored(files, ignore_rules): # type: (Iterable[Text], Optional[Sequence[Text]]) -> Tuple[List[Text], List[Text]] if ignore_rules is None: - ignore_rules = DEFAULT_IGNORE_RULERS + ignore_rules = DEFAULT_IGNORE_RULES compiled_ignore_rules = [compile_ignore_rule(item) for item in set(ignore_rules)] changed = [] @@ -362,7 +362,7 @@ "or the end matching anything other than a path separator and ** in that " "position matching anything. This flag can be used multiple times for " "multiple rules. Specifying this flag overrides the default: " + - ", ".join(DEFAULT_IGNORE_RULERS)) + ", ".join(DEFAULT_IGNORE_RULES)) parser.add_argument("--modified", action="store_true", help="Include files under version control that have been " "modified or staged")
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt index 5864139..ccf09be 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements.txt
@@ -4,6 +4,6 @@ mozlog==7.1.0 mozprocess==1.3.0 pillow==8.4.0 -requests==2.27.1 +requests==2.28.2 six==1.16.0 -urllib3[secure]==1.26.14 +urllib3[secure]==1.26.15
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_edge.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_edge.txt index 12920a99..dfbdc6d 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_edge.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_edge.txt
@@ -1 +1 @@ -selenium==4.3.0 +selenium==4.8.2
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt index 1f9033c..64546d5 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_firefox.txt
@@ -6,4 +6,4 @@ mozprofile==2.5.0 mozrunner==8.2.1 mozversion==2.3.0 -psutil==5.9.1 +psutil==5.9.4
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_ie.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_ie.txt index 1726afa6..83948c6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_ie.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_ie.txt
@@ -1,2 +1,2 @@ mozprocess==1.3.0 -selenium==4.3.0 +selenium==4.8.2
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_opera.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_opera.txt index 1726afa6..83948c6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_opera.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_opera.txt
@@ -1,2 +1,2 @@ mozprocess==1.3.0 -selenium==4.3.0 +selenium==4.8.2
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt index 8d303aa..069e31c6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_safari.txt
@@ -1 +1 @@ -psutil==5.9.1 +psutil==5.9.4
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_sauce.txt b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_sauce.txt index 5089b0c..64fb139 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/requirements_sauce.txt +++ b/third_party/wpt_tools/wpt/tools/wptrunner/requirements_sauce.txt
@@ -1,2 +1,2 @@ -selenium==4.3.0 -requests==2.27.1 +selenium==4.8.2 +requests==2.28.2
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini b/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini index 3a1afda..82df778f 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini +++ b/third_party/wpt_tools/wpt/tools/wptrunner/tox.ini
@@ -2,7 +2,7 @@ xfail_strict=true [tox] -envlist = py310-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py36,py37,py38,py39}-base +envlist = py310-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py37,py38,py39}-base skip_missing_interpreters = False [testenv]
diff --git a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py index 4bc193d..f62ded6 100644 --- a/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py +++ b/third_party/wpt_tools/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -644,6 +644,7 @@ session_config = {"host": self.browser.host, "port": self.browser.port, "capabilities": self.capabilities, + "timeout_multiplier": self.timeout_multiplier, "webdriver": { "binary": self.webdriver_binary, "args": self.webdriver_args
diff --git a/third_party/wpt_tools/wpt/wpt b/third_party/wpt_tools/wpt/wpt index b0e415d8..e0abacd 100755 --- a/third_party/wpt_tools/wpt/wpt +++ b/third_party/wpt_tools/wpt/wpt
@@ -2,8 +2,8 @@ if __name__ == "__main__": import sys - if sys.version_info < (3, 6): - sys.stderr.write("wpt requires Python 3.6 or higher\n") + if sys.version_info < (3, 7): + sys.stderr.write("wpt requires Python 3.7 or higher\n") sys.exit(1) from tools.wpt import wpt
diff --git a/tools/clang/scripts/upload_revision.py b/tools/clang/scripts/upload_revision.py index 8fb6a94a..8dc1405d 100755 --- a/tools/clang/scripts/upload_revision.py +++ b/tools/clang/scripts/upload_revision.py
@@ -280,10 +280,10 @@ default=False, help=('Print out `git` commands instead of running them. Still generates ' 'a local diff for debugging purposes.')) - parser.add_argument('--roll-rust', + parser.add_argument('--skip-rust', action='store_true', default=False, - help=('Update the rust revision.')) + help=('Skip updating the rust revision.')) args = parser.parse_args() @@ -314,10 +314,11 @@ Git('checkout', 'origin/main', '-b', branch_name, no_run=args.no_git) old_clang_version = PatchClangRevision(clang_version) - # Avoiding changing Rust versions when rolling Clang until we can fetch - # stdlib sources at the same revisionas the compiler, from the - # FALLBACK_REVISION in update.py. - if args.roll_rust: + if args.skip_rust: + assert (clang_version != + old_clang_version), ('Change the sub-revision of Clang if there is ' + 'no major version change.') + else: old_rust_version = PatchRustRevision(rust_version) assert (clang_version != old_clang_version or rust_version != old_rust_version), ( @@ -327,10 +328,6 @@ # TODO: Do this when we block Clang updates without a matching Rust # compiler. # PatchRustRemoveFallback() - else: - assert (clang_version != - old_clang_version), ('Change the sub-revision of Clang if there is ' - 'no major version change.') clang_change = f'{old_clang_version} : {clang_version}' clang_change_log = ( @@ -338,15 +335,15 @@ f'{old_clang_version.short_git_hash}..{clang_version.short_git_hash}' f'\n\n') - if args.roll_rust: + if args.skip_rust: + rust_change = '[skipping Rust]' + rust_change_log = '' + else: rust_change = f'{old_rust_version} : {rust_version}' rust_change_log = (f'{RUST_GIT_URL}/+log/' f'{old_rust_version.short_git_hash}..' f'{rust_version.short_git_hash}' f'\n\n') - else: - rust_change = '[skipping Rust]' - rust_change_log = '' title = f'Roll clang+rust {clang_change} / {rust_change}' @@ -354,7 +351,7 @@ body = f'{clang_change_log}{rust_change_log}Ran: {cmd}' commit_message = f'{title}\n\n{body}\n{COMMIT_FOOTER}' - if args.roll_rust: + if not args.skip_rust: commit_message += f'\n{RUST_BOTS}' Git('add',
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index acd81dc..64eeac17 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -270,19 +270,19 @@ 'chromium.dev': { # This should be the same with 'android-pie-arm64-rel'. - 'android-pie-arm64-rel-swarming': 'android_release_bot_minimal_symbols_arm64_webview_monochrome_reclient', + 'android-pie-arm64-rel-dev': 'android_release_bot_minimal_symbols_arm64_webview_monochrome_reclient', # These should be the same with 'Linux Builder'. - 'linux-rel-swarming': 'gpu_tests_release_bot_do_typecheck_reclient', - 'linux-ssd-rel-swarming': 'gpu_tests_release_bot_do_typecheck_reclient', + 'linux-rel-dev': 'gpu_tests_release_bot_do_typecheck_reclient', + 'linux-ssd-rel-dev': 'gpu_tests_release_bot_do_typecheck_reclient', # This should be the same with 'Mac Builder'. - 'mac-arm-rel-swarming': 'gpu_tests_release_bot_minimal_symbols_no_nacl_reclient', - 'mac-rel-swarming': 'gpu_tests_release_bot_minimal_symbols_no_nacl_reclient', + 'mac-arm-rel-dev': 'gpu_tests_release_bot_minimal_symbols_no_nacl_reclient', + 'mac-rel-dev': 'gpu_tests_release_bot_minimal_symbols_no_nacl_reclient', # This should be the same with 'Win x64 Builder'. - 'win-rel-swarming': 'gpu_tests_release_bot_minimal_symbols_reclient', - 'win11-rel-swarming': 'gpu_tests_release_bot_minimal_symbols_reclient', + 'win-rel-dev': 'gpu_tests_release_bot_minimal_symbols_reclient', + 'win11-rel-dev': 'gpu_tests_release_bot_minimal_symbols_reclient', }, 'chromium.devtools-frontend': { @@ -717,6 +717,10 @@ 'build1': 'gpu_tests_release_bot_reclient', 'build2': 'gpu_tests_release_bot_remote_links_reclient', }, + 'Comparison Linux (reclient vs reclient remote links)(compression)': { + 'build1': 'gpu_tests_release_bot_no_nacl_reclient', + 'build2': 'gpu_tests_release_bot_remote_links_small_reclient', + }, 'Comparison Linux (reclient vs reclient remote links)(small)': { 'build1': 'gpu_tests_release_bot_no_nacl_reclient', 'build2': 'gpu_tests_release_bot_remote_links_small_reclient',
diff --git a/tools/mb/mb_config_expectations/chromium.dev.json b/tools/mb/mb_config_expectations/chromium.dev.json index 88725f9..9c9e478 100644 --- a/tools/mb/mb_config_expectations/chromium.dev.json +++ b/tools/mb/mb_config_expectations/chromium.dev.json
@@ -1,5 +1,5 @@ { - "android-pie-arm64-rel-swarming": { + "android-pie-arm64-rel-dev": { "gn_args": { "dcheck_always_on": false, "debuggable_apks": false, @@ -15,7 +15,7 @@ "use_remoteexec": true } }, - "linux-rel-swarming": { + "linux-rel-dev": { "gn_args": { "dcheck_always_on": false, "devtools_skip_typecheck": false, @@ -26,7 +26,7 @@ "use_remoteexec": true } }, - "linux-ssd-rel-swarming": { + "linux-ssd-rel-dev": { "gn_args": { "dcheck_always_on": false, "devtools_skip_typecheck": false, @@ -37,7 +37,7 @@ "use_remoteexec": true } }, - "mac-arm-rel-swarming": { + "mac-arm-rel-dev": { "gn_args": { "dcheck_always_on": false, "enable_nacl": false, @@ -49,7 +49,7 @@ "use_remoteexec": true } }, - "mac-rel-swarming": { + "mac-rel-dev": { "gn_args": { "dcheck_always_on": false, "enable_nacl": false, @@ -61,7 +61,7 @@ "use_remoteexec": true } }, - "win-rel-swarming": { + "win-rel-dev": { "gn_args": { "dcheck_always_on": false, "ffmpeg_branding": "Chrome", @@ -72,7 +72,7 @@ "use_remoteexec": true } }, - "win11-rel-swarming": { + "win11-rel-dev": { "gn_args": { "dcheck_always_on": false, "ffmpeg_branding": "Chrome",
diff --git a/tools/mb/mb_config_expectations/chromium.reclient.fyi.json b/tools/mb/mb_config_expectations/chromium.reclient.fyi.json index 57c2206..b1ade2f7 100644 --- a/tools/mb/mb_config_expectations/chromium.reclient.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.reclient.fyi.json
@@ -22,6 +22,33 @@ } } }, + "Comparison Linux (reclient vs reclient remote links)(compression)": { + "build1": { + "gn_args": { + "dcheck_always_on": false, + "enable_nacl": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "use_remoteexec": true + } + }, + "build2": { + "gn_args": { + "concurrent_links": 50, + "dcheck_always_on": false, + "enable_nacl": false, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "rbe_link_cfg_file": "../../buildtools/reclient_cfgs/chromium-browser-clang/rewrapper_linux_link_small.cfg", + "use_remoteexec": true, + "use_remoteexec_links": true + } + } + }, "Comparison Linux (reclient vs reclient remote links)(small)": { "build1": { "gn_args": {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index b081b2c5..76475fb 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -7357,9 +7357,10 @@ <int value="57" label="Autofilled field was cleared by JavaScript within kLimitBeforeRefill (1s) after being filled (once)"/> - <int value="58" - label="Suggestions shown and included a card that had metadata shown"/> - <int value="59" label="Selected card suggestion had metadata shown"/> + <int value="58" label="Suggestions shown and included a card with metadata"/> + <int value="59" label="Suggestions shown and none had metadata"/> + <int value="60" label="Selected card suggestion had metadata"/> + <int value="61" label="Selected card suggestion did not have metadata"/> </enum> <enum name="AutofillFormSubmittedState"> @@ -10956,6 +10957,8 @@ label="BIBI_BIND_PRESSURE_MANAGER_BLOCKED_BY_PERMISSIONS_POLICY"/> <int value="298" label="RFSCI_BROWSER_VALIDATION_BAD_ORIGIN_TRIAL_TOKEN"/> <int value="299" label="RFH_RECEIVED_INVALID_BROWSING_TOPICS_ATTRIBUTE"/> + <int value="300" label="RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT"/> + <int value="301" label="RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME"/> </enum> <enum name="BadMessageReasonExtensions"> @@ -17731,6 +17734,7 @@ <int value="6" label="Only contained a single visit"/> <int value="7" label="Contains content that should not be visible"/> <int value="8" label="Contains blocked category"/> + <int value="9" label="Not enough non-hidden visits"/> </enum> <enum name="CoalescePotentialPackets"> @@ -42599,6 +42603,9 @@ <int value="4522" label="HtmlClipboardApiUnsanitizedRead"/> <int value="4523" label="HtmlClipboardApiUnsanitizedWrite"/> <int value="4524" label="AsyncClipboardAPIUnsanitizedRead"/> + <int value="4525" label="WindowOpenFullscreenRequested"/> + <int value="4526" label="FullscreenAllowedByWindowOpen"/> + <int value="4527" label="AttributeValueContainsLtOrGt"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -54769,10 +54776,12 @@ </enum> <enum name="JobProtocolErrorLocation"> - <int value="0" label="SessionStartReadingFailed"/> - <int value="1" label="CreateSessionFailed"/> - <int value="2" label="CryptoConnectFailedSync"/> - <int value="3" label="CryptoConnectFailedAsync"/> + <int value="0" label="kSessionStartReadingFailedAsync"/> + <int value="1" label="kSessionStartReadingFailedSync"/> + <int value="2" label="kCreateSessionFailedAsync"/> + <int value="3" label="kCreateSessionFailedSync"/> + <int value="4" label="CryptoConnectFailedSync"/> + <int value="5" label="CryptoConnectFailedAsync"/> </enum> <enum name="JpegColorSpace"> @@ -58876,6 +58885,7 @@ <int value="-1919683750" label="EnableOopPrintDrivers:disabled"/> <int value="-1919199528" label="AlwaysShowServerCardsInSyncTransport:disabled"/> + <int value="-1917538656" label="GetTheMostOutOfProgram:disabled"/> <int value="-1917031398" label="OmniboxNativeVoiceSuggestProvider:disabled"/> <int value="-1916060206" label="enable-display-zoom-setting"/> <int value="-1915854488" label="enable-offline-pages"/> @@ -65605,6 +65615,7 @@ label="ExtractRelatedSearchesFromPrefetchedZPSResponse:enabled"/> <int value="1806220475" label="IgnoreSyncEncryptionKeysLongMissing:disabled"/> <int value="1806450300" label="WebUsbDeviceDetection:enabled"/> + <int value="1806868888" label="GetTheMostOutOfProgram:enabled"/> <int value="1807088829" label="JourneysOnDeviceClusteringContentClustering:disabled"/> <int value="1807178878" label="FedCmAutoReauthn:enabled"/> @@ -66987,8 +66998,8 @@ <int value="8" label="Non-fast scrollable region"/> <int value="9" label="Failed hit test"/> <int value="10" label="No scrolling layer"/> - <int value="11" label="Not scrollable"/> - <int value="12" label="Non-invertible transform"/> + <int value="11" label="Not scrollable (obsolete)"/> + <int value="12" label="Non-invertible transform (obsolete)"/> <int value="13" label="Blocking wheel event handler region"/> <int value="14" label="Blocking touch event handler region"/> </enum>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index f8f7bae..2cedfa3 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -79,6 +79,12 @@ <variant name=".TabletMode" summary="Animates in Tablet mode w/o split view"/> </variants> +<variants name="RecognizerLocation"> + <variant name="OnDevice" summary="Speech recognition happened on device"/> + <variant name="ServerBased" + summary="Speech recognition happened on remote servers"/> +</variants> + <variants name="SplitViewResizeModes"> <variant name=".ClamshellMode.SingleWindow" summary=""/> <variant name=".ClamshellMode.WithOverview" summary=""/> @@ -4630,19 +4636,15 @@ </summary> </histogram> -<histogram name="Ash.Projector.SpeechRecognitionEndState.{RecognizerLocation}" +<histogram name="Ash.Projector.SpeechRecognitionEndState.{Location}" enum="SpeechRecognitionEndState" expires_after="2023-11-01"> <owner>yilkal@chromium.org</owner> <owner>cros-projector@google.com</owner> <summary> - For a recognition session happening at {RecognizerLocation}, this histogram - records the recognition status at the end of the session. + For a recognition session happening at {Location}, this histogram records + the recognition status at the end of the session. </summary> - <token key="RecognizerLocation"> - <variant name="OnDevice" summary="Speech recognition happened on device"/> - <variant name="ServerBased" - summary="Speech recognition happened on remote servers"/> - </token> + <token key="Location" variants="RecognizerLocation"/> </histogram> <histogram name="Ash.Projector.Toolbar.{TabletOrClamshell}" @@ -5257,6 +5259,17 @@ </token> </histogram> +<histogram name="Ash.SpeechRecognitionSessionLength.{Location}" units="ms" + expires_after="2023-11-01"> + <owner>yilkal@chromium.org</owner> + <owner>cros-projector@google.com</owner> + <summary> + The length of the speech recognition session happening on {Location}. This + histogram records the length at the end of the session. + </summary> + <token key="Location" variants="RecognizerLocation"/> +</histogram> + <histogram name="Ash.SplitView.DeviceOrientation.{DeviceUIMode}" enum="DeviceOrientation" expires_after="2023-07-27"> <owner>zxdan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/bluetooth/histograms.xml b/tools/metrics/histograms/metadata/bluetooth/histograms.xml index 9ccd427..1ca03374 100644 --- a/tools/metrics/histograms/metadata/bluetooth/histograms.xml +++ b/tools/metrics/histograms/metadata/bluetooth/histograms.xml
@@ -1620,6 +1620,26 @@ </token> </histogram> +<histogram + name="Bluetooth.ChromeOS.Pairing.Result.FilteredFailureReason{BluetoothTransportTypes}" + enum="BluetoothConnectionFailureReason" expires_after="2024-02-01"> + <owner>khorimoto@chromium.org</owner> + <owner>cros-connectivity@google.com</owner> + <summary> + Breaks down why a pairing attempt to a peripheral failed (see + 'Bluetooth.ChromeOS.Pairing.Result'). Emits the result of pairing attempts + that have explicitly failed, filtering out results where the device was not + paired due to non-error reasons e.g. the user cancelled the pairing attempt. + + Suffixed by Bluetooth transport type. View the base histogram to see results + for all transport types aggregated together, and suffixed histograms for the + results of just that particular transport type. {BluetoothTransportTypes} + </summary> + <token key="BluetoothTransportTypes" variants="BluetoothTransportTypes"> + <variant name=""/> + </token> +</histogram> + <histogram name="Bluetooth.ChromeOS.Pairing.Result{BluetoothTransportTypes}" enum="BooleanSuccess" expires_after="2023-06-01"> <owner>khorimoto@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml index f03cd25..637e4dd9 100644 --- a/tools/metrics/histograms/metadata/ios/histograms.xml +++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -1911,7 +1911,7 @@ </histogram> <histogram name="IOS.SadTab.FileIsPDF" enum="Boolean" - expires_after="2023-04-29"> + expires_after="2024-03-20"> <owner>ajuma@chromium.org</owner> <owner>gambard@chromium.org</owner> <summary> @@ -1921,7 +1921,7 @@ </histogram> <histogram name="IOS.SadTab.URLIsChromeExternalFile" enum="Boolean" - expires_after="2023-04-29"> + expires_after="2024-03-20"> <owner>ajuma@chromium.org</owner> <owner>gambard@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml index 71b0735..8c82c59 100644 --- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml +++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -995,6 +995,19 @@ </summary> </histogram> +<histogram name="NewTabPage.HistoryClusters.ImageLoadSuccess" enum="Boolean" + expires_after="2023-08-08"> + <owner>romanarora@chromium.org</owner> + <owner>tiborg@chromium.org</owner> + <owner>chrome-desktop-ntp@google.com</owner> + <summary> + Logs whether loading an image for a quests tile succeeded or failed (true + for success and false for failure). This is determined by whether or not we + get a URL back from the ImageService for a visit that we expected to have an + image for. Only logged in 1P NTP with the history clusters module enabled. + </summary> +</histogram> + <histogram name="NewTabPage.HistoryClusters.IneligibleReason" enum="NTPHistoryClustersIneligibleReason" expires_after="2023-08-08"> <owner>romanarora@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 5cc35e4..ba47cbd 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -14765,7 +14765,7 @@ </histogram> <histogram name="WebController.CertVerificationErrorsCacheHit" - enum="BooleanCacheHit" expires_after="2023-05-01"> + enum="BooleanCacheHit" expires_after="2024-03-20"> <owner>ajuma@chromium.org</owner> <owner>gambard@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/prefetch/histograms.xml b/tools/metrics/histograms/metadata/prefetch/histograms.xml index 0bfc0ed..e58155d8 100644 --- a/tools/metrics/histograms/metadata/prefetch/histograms.xml +++ b/tools/metrics/histograms/metadata/prefetch/histograms.xml
@@ -27,6 +27,36 @@ <variant name="TLS" summary="TLS canary check"/> </variants> +<variants name="SpeculationEagerness"> + <variant name="Conservative" summary="Conservative"/> + <variant name="Eager" summary="Eager"/> + <variant name="Moderate" summary="Moderate"/> +</variants> + +<histogram + name="PrefetchProxy.AfterClick.BlockUntilHeadDuration.{WasServed}.{SpeculationEagerness}" + units="ms" expires_after="2023-09-10"> + <owner>curranmax@chromium.org</owner> + <owner>ryansturm@chromium.org</owner> + <owner>spelchat@chromium.org</owner> + <summary> + If a prefetch request has started but the head of the prefetch response has + not been received yet when a navigation to a URL that matches the prefetch, + then the prefetch service will block until the head of the prefetch response + is received and then decide to serve or not serve the prefetch. + + This histogram records the amount of time that the prefetch service blocked + until the head of the prefetch response was received. This histogram is only + recorded for prefetches that are {WasServed} and with an Eagerness of + {SpeculationEagerness}. + </summary> + <token key="WasServed"> + <variant name="NotServed" summary="not served"/> + <variant name="Served" summary="served"/> + </token> + <token key="SpeculationEagerness" variants="SpeculationEagerness"/> +</histogram> + <histogram name="PrefetchProxy.AfterClick.Mainframe.CookieCopyStartToInterceptorCheck" units="ms" expires_after="2024-04-25"> @@ -118,6 +148,25 @@ </histogram> <histogram + name="PrefetchProxy.AfterClick.WasBlockedUntilHeadWhenServing.{SpeculationEagerness}" + enum="Boolean" expires_after="2023-09-10"> + <owner>curranmax@chromium.org</owner> + <owner>ryansturm@chromium.org</owner> + <owner>spelchat@chromium.org</owner> + <summary> + If a prefetch request has started but the head of the prefetch response has + not been received yet when a navigation to a URL that matches the prefetch, + then the prefetch service will block until the head of the prefetch response + is received and then decide to serve or not serve the prefetch. + + This histogram records whether or not prefetch service will block or not for + a prefetch. This histogram is only for prefetches with an Eagerness of + {SpeculationEagerness}. + </summary> + <token key="SpeculationEagerness" variants="SpeculationEagerness"/> +</histogram> + +<histogram name="PrefetchProxy.CanaryChecker.CacheEntryAge.{PrefetchProxyCanaryCheckerClient}" units="hours" expires_after="2024-04-25"> <owner>curranmax@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml index 1d2421b..d690b0a 100644 --- a/tools/metrics/histograms/metadata/stability/histograms.xml +++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -392,7 +392,7 @@ </histogram> <histogram name="Stability.IOS.Experimental.Counts2" - enum="IOSStabilityUserVisibleTerminationType" expires_after="2023-05-03"> + enum="IOSStabilityUserVisibleTerminationType" expires_after="2024-03-20"> <owner>ajuma@chromium.org</owner> <owner>olivierrobin@chromium.org</owner> <summary>
diff --git a/tools/typescript/path_mappings.py b/tools/typescript/path_mappings.py index 21ee3ca..7e2e2a36 100644 --- a/tools/typescript/path_mappings.py +++ b/tools/typescript/path_mappings.py
@@ -2,6 +2,8 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +from os import path + def _add_ui_webui_resources_mappings(path_mappings, root_gen_dir): # Calculate mappings for ui/webui/resources/ sub-folders that have a dedicated @@ -33,6 +35,24 @@ )] +def _add_third_party_polymer_mappings(path_mappings, root_src_dir): + # Use path.join() below, since root_src_dir can end with trailing slashes. + path_mappings[f'//third_party/polymer/v3_0:library'] = [ + ( + f'//resources/polymer/v3_0/polymer/polymer_bundled.min.js', + path.join( + root_src_dir, + 'third_party/polymer/v3_0/components-chromium/polymer/polymer.d.ts' + ), + ), + ( + f'//resources/polymer/v3_0/*', + path.join(root_src_dir, + 'third_party/polymer/v3_0/components-chromium/*'), + ), + ] + + # Ash-only def _add_ash_webui_resources_mappings(path_mappings, root_gen_dir): path_mappings['//ash/webui/common/resources:build_ts'] = [( @@ -41,10 +61,11 @@ )] -def GetDepToPathMappings(root_gen_dir, platform): +def GetDepToPathMappings(root_gen_dir, root_src_dir, platform): path_mappings = {} _add_ui_webui_resources_mappings(path_mappings, root_gen_dir) + _add_third_party_polymer_mappings(path_mappings, root_src_dir) if platform == 'chromeos_ash': _add_ash_webui_resources_mappings(path_mappings, root_gen_dir)
diff --git a/tools/typescript/ts_library.gni b/tools/typescript/ts_library.gni index 7a9eab7..33ba2ba 100644 --- a/tools/typescript/ts_library.gni +++ b/tools/typescript/ts_library.gni
@@ -62,6 +62,8 @@ args = [ "--root_gen_dir", rebase_path(root_gen_dir, target_gen_dir), + "--root_src_dir", + rebase_path("//", target_gen_dir), "--root_dir", rebase_path(root_dir, root_build_dir), @@ -142,24 +144,11 @@ } path_mappings = [ - "chrome://resources/polymer/v3_0/*|" + - rebase_path("//third_party/polymer/v3_0/components-chromium/*", - target_gen_dir), - "//resources/polymer/v3_0/*|" + - rebase_path("//third_party/polymer/v3_0/components-chromium/*", - target_gen_dir), - "chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js|" + rebase_path( - "//third_party/polymer/v3_0/components-chromium/polymer/polymer.d.ts", - target_gen_dir), - "//resources/polymer/v3_0/polymer/polymer_bundled.min.js|" + rebase_path( - "//third_party/polymer/v3_0/components-chromium/polymer/polymer.d.ts", - target_gen_dir), "/tools/typescript/definitions/*|" + rebase_path("//tools/typescript/definitions/*", target_gen_dir), - - # NOTE(crbug/1402829): path_mappings corresponding to files generated by other - # ts_library() deps have been moved to path_mappings.py, in preparation of - # automatically inferring them from |deps|. Don't add new such mappings here. + # NOTE: path_mappings corresponding to files generated by + # other ts_library() deps are automatically inferred from |deps| in + # path_mappings.py. Don't add any such mappings here. ] # The |platform| flag is used in path_mappings.py and validate_tsconfig.py,
diff --git a/tools/typescript/ts_library.py b/tools/typescript/ts_library.py index 1235659..d3d72f8f 100644 --- a/tools/typescript/ts_library.py +++ b/tools/typescript/ts_library.py
@@ -39,6 +39,7 @@ parser.add_argument('--path_mappings', nargs='*') parser.add_argument('--root_gen_dir', required=True) + parser.add_argument('--root_src_dir', required=True) parser.add_argument('--root_dir', required=True) parser.add_argument('--out_dir', required=True) @@ -161,6 +162,7 @@ assert args.raw_deps is not None dep_to_path_mappings = GetDepToPathMappings(args.root_gen_dir, + args.root_src_dir, args.platform) for dep in args.raw_deps:
diff --git a/tools/typescript/ts_library_test.py b/tools/typescript/ts_library_test.py index 0a23828e..2a87bfb 100755 --- a/tools/typescript/ts_library_test.py +++ b/tools/typescript/ts_library_test.py
@@ -46,6 +46,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(os.path.join(_HERE_DIR, 'tests', 'project1'), _CWD), '--gen_dir', @@ -99,6 +101,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--raw_deps', '//ui/webui/resources/js:build_ts', '--root_dir', @@ -146,6 +150,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(os.path.join(_HERE_DIR, 'tests', 'project3'), _CWD), '--gen_dir', @@ -177,6 +183,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(os.path.join(_HERE_DIR, 'tests', 'project4'), _CWD), '--gen_dir', @@ -224,6 +232,8 @@ '--composite', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(os.path.join(_HERE_DIR, 'tests', 'project5'), _CWD), '--gen_dir', @@ -243,6 +253,8 @@ os.path.join(gen_dir, 'tsconfig_build_ts.json'), '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(os.path.join(_HERE_DIR, 'tests', 'project5'), _CWD), '--gen_dir', @@ -284,6 +296,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath( os.path.join(_HERE_DIR, 'tests', 'ui', 'webui', 'resources', 'js'), @@ -355,6 +369,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(os.path.join(_HERE_DIR, 'tests', 'project1'), _CWD), '--gen_dir', @@ -386,6 +402,8 @@ 'build_ts', '--root_gen_dir', os.path.relpath(self._out_folder, gen_dir), + '--root_src_dir', + os.path.relpath(os.path.join(_HERE_DIR, 'tests'), gen_dir), '--root_dir', os.path.relpath(root_dir, _CWD), '--gen_dir',
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc index 2678857..df6bfb6 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -1552,6 +1552,17 @@ if (!old_selection_node) return; + // We should not remove the focus when the selection remains in the same text + // field. It's possible for the new selection to be located on a descendant + // inline text box in the text field, so make sure we compare the nodes at the + // root of the text field. + AXNode* old_text_field_ancestor = old_selection_node->GetTextFieldAncestor(); + AXNode* new_text_field_ancestor = new_selection_node->GetTextFieldAncestor(); + if (old_text_field_ancestor && new_text_field_ancestor && + old_text_field_ancestor == new_text_field_ancestor) { + return; + } + if (!new_selection_node || (old_selection_node->HasState(ax::mojom::State::kFocusable) && !new_selection_node->HasState(ax::mojom::State::kFocusable))) {
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index da83c18..5b1a82a 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -5421,6 +5421,66 @@ } TEST_F(AXPlatformNodeTextRangeProviderTest, + TestTextRangeProviderWinUnfocusableNodeForSelection) { + TestAXTreeUpdate update(std::string(R"HTML( + ++1 kRootWebArea + ++++2 kTextField states=kFocusable + ++++++3 kGenericContainer state=kEditable + ++++++++4 kStaticText state=kEditable + ++++++++++5 kInlineTextBox state=kEditable + )HTML")); + + update.nodes[1].SetName("Hello World"); + update.nodes[3].SetName("Hello World"); + update.nodes[4].SetName("Hello World"); + + AXTree* tree = Init(update); + + AXNode* input_node = GetNodeFromTree(tree->GetAXTreeID(), 2); + + AXPlatformNodeWin* input_platform_node = + static_cast<AXPlatformNodeWin*>(AXPlatformNodeFromNode(input_node)); + + AXPlatformNodeWin* root = static_cast<AXPlatformNodeWin*>( + AXPlatformNodeFromNode(GetNodeFromTree(tree->GetAXTreeID(), 1))); + + input_platform_node->SetFocus(); + + // start: TextPosition, anchor_id=2, text_offset=0, annotated_text=<h>ello + // world end : TextPosition, anchor_id=2, text_offset=0, + // annotated_text=<h>ello world + ComPtr<AXPlatformNodeTextRangeProviderWin> text_range_provider; + CreateTextRangeProviderWin( + text_range_provider, input_platform_node, + /*start_anchor=*/input_node, /*start_offset=*/0, + /*start_affinity*/ ax::mojom::TextAffinity::kDownstream, + /*end_anchor=*/input_node, /*end_offset=*/0, + /*end_affinity*/ ax::mojom::TextAffinity::kDownstream); + + text_range_provider->Select(); + + // start: TextPosition, anchor_id=5, text_offset=6, annotated_text=hello + // <w>orld end : TextPosition, anchor_id=5, text_offset=6, + // annotated_text=hello <w>orld + EXPECT_UIA_MOVE_ENDPOINT_BY_UNIT( + text_range_provider, TextPatternRangeEndpoint_Start, TextUnit_Word, + /*count*/ 1, + /*expected_text*/ L"", + /*expected_count*/ 1); + + text_range_provider->Select(); + // Verify selection. + AXSelection unignored_selection = + root->GetDelegate()->GetUnignoredSelection(); + EXPECT_EQ(5, unignored_selection.anchor_object_id); + EXPECT_EQ(5, unignored_selection.focus_object_id); + // Before patch that added this test, code this scenario would result in + // us focusing the root of the document, which is incorrect behavior. + EXPECT_FALSE(root->IsFocused()); + EXPECT_TRUE(input_platform_node->IsFocused()); +} + +TEST_F(AXPlatformNodeTextRangeProviderTest, TestTextRangeProviderWinFindTextInContentEditable) { // Before the commit that added this test, we had incorrect behavior when // finding text in this tree scenario.
diff --git a/ui/display/mac/display_link_mac.cc b/ui/display/mac/display_link_mac.cc index 2ab7e0fe..45657313 100644 --- a/ui/display/mac/display_link_mac.cc +++ b/ui/display/mac/display_link_mac.cc
@@ -11,7 +11,6 @@ #include "base/logging.h" #include "base/no_destructor.h" #include "base/numerics/safe_conversions.h" -#include "base/synchronization/lock.h" #include "base/task/bind_post_task.h" #include "base/task/single_thread_task_runner.h" #include "base/trace_event/trace_event.h" @@ -31,8 +30,6 @@ namespace ui { -using DisplayLinkMap = std::map<CGDirectDisplayID, DisplayLinkMac*>; - namespace { bool ComputeVSyncParameters(const CVTimeStamp& cv_time, @@ -64,20 +61,41 @@ return true; } -struct DisplayLinkGlobals { - std::map<CGDirectDisplayID, DisplayLinkMac*> GUARDED_BY(lock) map; - base::Lock lock; - - static DisplayLinkGlobals& Get() { - static base::NoDestructor<DisplayLinkGlobals> instance; - return *instance; - } -}; - } // namespace -//////////////////////////////////////////////////////////////////////////////// -// DisplayLinkMac +using DisplayLinkMap = std::map<CGDirectDisplayID, DisplayLinkMac*>; + +namespace { + +// The task runner to post tasks to from the display link thread. Note that this +// is initialized with the very first DisplayLinkMac instance, and is never +// changed (even, e.g, in tests that re-initialize the main thread task runner). +// https://885329 +// TODO(ccameron): crbug.com/969157 - Save this ask_runner to DisplayLinkMac. +// configs += [ "//build/config/compiler:wexit_time_destructors" ] in +// ui/display/BUILD.gn has to be removed because GetMainThreadTaskRunner() +// causes a compiler error. +scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner() { + static scoped_refptr<base::SingleThreadTaskRunner> task_runner = + base::SingleThreadTaskRunner::GetCurrentDefault(); + return task_runner; +} + +// Each display link instance consumes a non-negligible number of cycles, so +// make all display links on the same screen share the same object. +// +// Note that this is a weak map, holding non-owning pointers to the +// DisplayLinkMac objects. DisplayLinkMac is a ref-counted class, and is +// jointly owned by the various callers that got a copy by calling +// GetForDisplay(). +// +// ** This map may only be accessed from the main thread. ** +DisplayLinkMap& GetAllDisplayLinks() { + static base::NoDestructor<DisplayLinkMap> all_display_links; + return *all_display_links; +} + +} // namespace // static scoped_refptr<DisplayLinkMac> DisplayLinkMac::GetForDisplay( @@ -85,16 +103,12 @@ if (!display_id) return nullptr; - auto& globals = DisplayLinkGlobals::Get(); - base::AutoLock lock(globals.lock); - // Return the existing display link for this display, if it exists. - auto found = globals.map.find(display_id); - if (found != globals.map.end()) { + DisplayLinkMap& all_display_links = GetAllDisplayLinks(); + auto found = all_display_links.find(display_id); + if (found != all_display_links.end()) return found->second; - } - // Create a new DisplayLink, outside of the lock. CVReturn ret = kCVReturnSuccess; base::ScopedTypeRef<CVDisplayLinkRef> display_link; @@ -123,17 +137,17 @@ return nullptr; } - ret = CVDisplayLinkSetOutputCallback(display_link, &DisplayLinkCallback, + scoped_refptr<DisplayLinkMac> display_link_mac( + new DisplayLinkMac(display_id, display_link)); + ret = CVDisplayLinkSetOutputCallback(display_link_mac->display_link_, + &DisplayLinkCallback, reinterpret_cast<void*>(display_id)); if (ret != kCVReturnSuccess) { LOG(ERROR) << "CVDisplayLinkSetOutputCallback failed: " << ret; return nullptr; } - scoped_refptr<DisplayLinkMac> result( - new DisplayLinkMac(display_id, display_link)); - globals.map.emplace(display_id, result.get()); - return result; + return display_link_mac; } double DisplayLinkMac::GetRefreshRate() { @@ -150,18 +164,49 @@ DisplayLinkMac::DisplayLinkMac( CGDirectDisplayID display_id, base::ScopedTypeRef<CVDisplayLinkRef> display_link) - : display_id_(display_id), display_link_(display_link) {} + : display_id_(display_id), display_link_(display_link) { + DisplayLinkMap& all_display_links = GetAllDisplayLinks(); + DCHECK(all_display_links.find(display_id) == all_display_links.end()); + all_display_links.emplace(display_id_, this); +} DisplayLinkMac::~DisplayLinkMac() { - auto& globals = DisplayLinkGlobals::Get(); - base::AutoLock lock(globals.lock); - DCHECK(callbacks_.empty()); - auto found = globals.map.find(display_id_); - DCHECK(found != globals.map.end()); + DisplayLinkMap& all_display_links = GetAllDisplayLinks(); + auto found = all_display_links.find(display_id_); + DCHECK(found != all_display_links.end()); DCHECK(found->second == this); - globals.map.erase(found); + all_display_links.erase(found); +} + +// static +void DisplayLinkMac::DisplayLinkCallbackOnMainThread(CGDirectDisplayID display, + VSyncParamsMac params) { + DisplayLinkMap& all_display_links = GetAllDisplayLinks(); + auto found = all_display_links.find(display); + if (found == all_display_links.end()) { + // This might reasonably happen (and does; see https://crbug.com/564780). It + // occasionally happens that the CVDisplayLink calls back on the video + // thread, but by the time the callback makes it to the main thread for + // processing, the DisplayLinkMac object has lost all its references and + // has been deleted. + return; + } + + DisplayLinkMac* display_link_mac = found->second; + display_link_mac->OnDisplayLinkCallback(params); +} + +void DisplayLinkMac::OnDisplayLinkCallback(VSyncParamsMac params) { + TRACE_EVENT0("ui", "DisplayLinkMac::OnDisplayLinkCallbackOnMainThread"); + + auto callbacks_copy = callbacks_; + for (auto* callback : callbacks_copy) { + if (callbacks_.count(callback)) { + callback->callback_.Run(params); + } + } } // static @@ -172,41 +217,33 @@ CVOptionFlags* flags_out, void* context) { TRACE_EVENT0("ui", "DisplayLinkMac::DisplayLinkCallback"); + CGDirectDisplayID display_id = + static_cast<CGDirectDisplayID>(reinterpret_cast<uintptr_t>(context)); - // Convert the time parameters to our VSync parameters. VSyncParamsMac params; params.callback_times_valid = ComputeVSyncParameters( *now, ¶ms.callback_timebase, ¶ms.callback_interval); params.display_times_valid = ComputeVSyncParameters( *output_time, ¶ms.display_timebase, ¶ms.display_interval); - // Locate the DisplayLinkMac for this display. - auto& globals = DisplayLinkGlobals::Get(); - base::AutoLock lock(globals.lock); - CGDirectDisplayID display_id = - static_cast<CGDirectDisplayID>(reinterpret_cast<uintptr_t>(context)); - auto found = globals.map.find(display_id); - if (found == globals.map.end()) { - return kCVReturnSuccess; - } - - // Issue all of its callbacks. - DisplayLinkMac* display_link_mac = found->second; - for (auto* callback : display_link_mac->callbacks_) { - callback->callback_for_cvdisplaylink_thread_.Run(params); - } + GetMainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(&DisplayLinkMac::DisplayLinkCallbackOnMainThread, + display_id, params)); return kCVReturnSuccess; } std::unique_ptr<VSyncCallbackMac> DisplayLinkMac::RegisterCallback( - VSyncCallbackMac::Callback callback, - bool do_callback_on_register_thread) { - base::AutoLock lock(DisplayLinkGlobals::Get().lock); - + VSyncCallbackMac::Callback callback) { // Start the display link, if needed. If we fail to start the link, return // nullptr. if (callbacks_.empty()) { DCHECK(!CVDisplayLinkIsRunning(display_link_)); + + if (!task_runner_) { + task_runner_ = GetMainThreadTaskRunner(); + } + CVReturn ret = CVDisplayLinkStart(display_link_); if (ret != kCVReturnSuccess) { LOG(ERROR) << "CVDisplayLinkStart failed: " << ret; @@ -214,15 +251,13 @@ } } - std::unique_ptr<VSyncCallbackMac> new_observer(new VSyncCallbackMac( - this, std::move(callback), do_callback_on_register_thread)); + std::unique_ptr<VSyncCallbackMac> new_observer( + new VSyncCallbackMac(this, std::move(callback))); callbacks_.insert(new_observer.get()); return new_observer; } void DisplayLinkMac::UnregisterCallback(VSyncCallbackMac* observer) { - base::AutoLock lock(DisplayLinkGlobals::Get().lock); - auto found = callbacks_.find(observer); CHECK(found != callbacks_.end()); callbacks_.erase(found); @@ -241,24 +276,8 @@ // VSyncCallbackMac VSyncCallbackMac::VSyncCallbackMac(scoped_refptr<DisplayLinkMac> display_link, - Callback callback, - bool do_callback_on_ctor_thread) - : display_link_(std::move(display_link)), weak_factory_(this) { - if (do_callback_on_ctor_thread) { - auto lambda = [](base::WeakPtr<VSyncCallbackMac> weak_this, - Callback callback, VSyncParamsMac params) { - if (weak_this) { - callback.Run(params); - } - }; - auto callback_for_current_thread = - base::BindRepeating(lambda, weak_factory_.GetWeakPtr(), callback); - callback_for_cvdisplaylink_thread_ = - base::BindPostTaskToCurrentDefault(callback_for_current_thread); - } else { - callback_for_cvdisplaylink_thread_ = std::move(callback); - } -} + Callback callback) + : display_link_(std::move(display_link)), callback_(std::move(callback)) {} VSyncCallbackMac::~VSyncCallbackMac() { display_link_->UnregisterCallback(this);
diff --git a/ui/display/mac/display_link_mac.h b/ui/display/mac/display_link_mac.h index ce3e281f..5355ff0c 100644 --- a/ui/display/mac/display_link_mac.h +++ b/ui/display/mac/display_link_mac.h
@@ -36,7 +36,6 @@ }; // Object used to control the lifetime of callbacks from DisplayLinkMac. -// See notes in DisplayLinkMac::RegisterCallback class DISPLAY_EXPORT VSyncCallbackMac { public: using Callback = base::RepeatingCallback<void(VSyncParamsMac)>; @@ -45,43 +44,28 @@ private: friend class DisplayLinkMac; VSyncCallbackMac(scoped_refptr<DisplayLinkMac> display_link, - Callback callback, - bool do_callback_on_ctor_thread); + Callback callback); // The DisplayLinkMac that `this` is observing is kept alive while `this` is // alive. scoped_refptr<DisplayLinkMac> display_link_; - - // The callback that will be run on the CVDisplayLink thread. If `this` was - // created with `do_callback_on_ctor_thread`, then this callback will post a - // task to the creating thread, - Callback callback_for_cvdisplaylink_thread_; - - base::WeakPtrFactory<VSyncCallbackMac> weak_factory_; + Callback callback_; }; class DISPLAY_EXPORT DisplayLinkMac : public base::RefCountedThreadSafe<DisplayLinkMac> { public: - // Get the DisplayLinkMac for the specified display. This may be called on - // any thread. + // Get the DisplayLinkMac for the specified display. All calls to this + // function (and all other functions on this class) must be on the same + // thread. + // TODO(https://crbug.com/1419870): Remove this restriction. static scoped_refptr<DisplayLinkMac> GetForDisplay( CGDirectDisplayID display_id); - // Register an observer callback. - // * The specified callback will be called at every VSync tick, until the - // returned VSyncCallbackMac object is destroyed. - // * The resulting VSyncCallbackMac object must be destroyed on the same - // thread on which it was created. - // * If `do_callback_on_register_thread` is true, then the callback is - // guaranteed to be made on the calling thread and is guaranteed to be made - // only if the resulting VSyncCallbackMac has not been destroyed. - // * If `do_callback_on_register_thread` is false then the callback may come - // from any thread, and may happen after the resulting VSyncCallbackMac is - // destroyed. + // Register an observer callback. The specified callback will be called at + // every VSync tick until the returned object is destroyed. std::unique_ptr<VSyncCallbackMac> RegisterCallback( - VSyncCallbackMac::Callback callback, - bool do_callback_on_register_thread = true); + VSyncCallbackMac::Callback callback); // Get the panel/monitor refresh rate double GetRefreshRate(); @@ -94,6 +78,7 @@ base::ScopedTypeRef<CVDisplayLinkRef> display_link); virtual ~DisplayLinkMac(); + void OnDisplayLinkCallback(VSyncParamsMac params); void UnregisterCallback(VSyncCallbackMac* callback); // Called by the system on the display link thread, and posts a call to @@ -105,14 +90,21 @@ CVOptionFlags* flags_out, void* context); + // Looks up the display and calls UpdateVSyncParameters() on the corresponding + // DisplayLinkMac. + static void DisplayLinkCallbackOnMainThread(CGDirectDisplayID display, + VSyncParamsMac params); + // The display that this display link is attached to. CGDirectDisplayID display_id_; // CVDisplayLink for querying VSync timing info. base::ScopedTypeRef<CVDisplayLinkRef> display_link_; - // Each VSyncCallbackMac holds a reference to `this`. This member may only - // be accessed while DisplayLinkGlobals::lock is held. + // The task runner to post tasks to from the display link thread. + scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + + // Each VSyncCallbackMac holds a reference to `this`. std::set<VSyncCallbackMac*> callbacks_; };
diff --git a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js index 3110c2b0..5261b51 100644 --- a/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js +++ b/ui/file_manager/file_manager/background/js/drive_sync_handler_unittest.js
@@ -7,6 +7,7 @@ import {installMockChrome} from '../../common/js/mock_chrome.js'; import {ProgressItemState} from '../../common/js/progress_center_common.js'; import {toFilesAppURL} from '../../common/js/url_constants.js'; +import {util} from '../../common/js/util.js'; import {DriveSyncHandlerImpl} from './drive_sync_handler.js'; import {MockProgressCenter} from './mock_progress_center.js'; @@ -35,6 +36,8 @@ */ const mockChrome = {}; +util.isInlineSyncStatusEnabled = () => false; + mockChrome.fileManagerPrivate = { onFileTransfersUpdated: { addListener: function(callback) {
diff --git a/ui/ozone/platform/drm/common/drm_util.cc b/ui/ozone/platform/drm/common/drm_util.cc index 4006b63..85ce642 100644 --- a/ui/ozone/platform/drm/common/drm_util.cc +++ b/ui/ozone/platform/drm/common/drm_util.cc
@@ -539,8 +539,7 @@ std::unique_ptr<display::DisplaySnapshot> CreateDisplaySnapshot( const DrmWrapper& drm, HardwareDisplayControllerInfo* info, - uint8_t device_index, - const display::DrmFormatsAndModifiers& drm_formats_and_modifiers) { + uint8_t device_index) { const uint8_t display_index = display::ConnectorIndex8(device_index, info->index()); const uint16_t connector_index = @@ -628,6 +627,9 @@ display::DisplaySnapshot::DisplayModeList modes = ExtractDisplayModes(info, active_pixel_size, ¤t_mode, &native_mode); + const display::DrmFormatsAndModifiers drm_formats_and_modifiers = + drm.GetFormatsAndModifiersForCrtc(info->crtc()->crtc_id); + return std::make_unique<display::DisplaySnapshot>( port_display_id, port_display_id, edid_display_id, connector_index, gfx::Point(), physical_size, type, base_connector_id, path_topology,
diff --git a/ui/ozone/platform/drm/common/drm_util.h b/ui/ozone/platform/drm/common/drm_util.h index f1f2c770..9a90451 100644 --- a/ui/ozone/platform/drm/common/drm_util.h +++ b/ui/ozone/platform/drm/common/drm_util.h
@@ -140,8 +140,7 @@ std::unique_ptr<display::DisplaySnapshot> CreateDisplaySnapshot( const DrmWrapper& drm, HardwareDisplayControllerInfo* info, - uint8_t device_index, - const display::DrmFormatsAndModifiers& drm_formats_and_modifiers); + uint8_t device_index); int GetFourCCFormatForOpaqueFramebuffer(gfx::BufferFormat format);
diff --git a/ui/ozone/platform/drm/common/drm_wrapper.cc b/ui/ozone/platform/drm/common/drm_wrapper.cc index 7966dcb..5673fa3e 100644 --- a/ui/ozone/platform/drm/common/drm_wrapper.cc +++ b/ui/ozone/platform/drm/common/drm_wrapper.cc
@@ -507,6 +507,11 @@ return std::string(version->name, version->name_len); } +display::DrmFormatsAndModifiers DrmWrapper::GetFormatsAndModifiersForCrtc( + uint32_t crtc_id) const { + return display::DrmFormatsAndModifiers(); +} + base::ScopedFD DrmWrapper::ToScopedFD(std::unique_ptr<DrmWrapper> drm) { return std::move(drm->drm_fd_); }
diff --git a/ui/ozone/platform/drm/common/drm_wrapper.h b/ui/ozone/platform/drm/common/drm_wrapper.h index bb988a8..d12eea8 100644 --- a/ui/ozone/platform/drm/common/drm_wrapper.h +++ b/ui/ozone/platform/drm/common/drm_wrapper.h
@@ -15,6 +15,7 @@ #include "base/functional/callback.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h" +#include "ui/display/types/display_constants.h" #include "ui/display/types/gamma_ramp_rgb_entry.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/size.h" @@ -267,6 +268,14 @@ virtual absl::optional<std::string> GetDriverName() const; + // TODO(gildekel): remove once DrmWrapper and DrmDevice are completely + // decoupled. + // Returns a list of supported drm formats and modifiers for |crtc_id|. Note: + // implementation in wrapper is a stub. Full implementation is in + // DrmDevice::GetFormatsAndModifiersForCrtc(). + virtual display::DrmFormatsAndModifiers GetFormatsAndModifiersForCrtc( + uint32_t crtc_id) const; + // Extracts the FD from the given |drm|. The |drm| object will be invalidated. static base::ScopedFD ToScopedFD(std::unique_ptr<DrmWrapper> drm); @@ -276,8 +285,8 @@ protected: // TODO(gildekel): move CommitProperties() and PageFlip() to the public API - // once DrmWrapper DrmDevice are completely decoupled. Consider changing the - // signature to `void* user_data` instead of |page_flip_id|, which is too + // once DrmWrapper and DrmDevice are completely decoupled. Consider changing + // the signature to `void* user_data` instead of |page_flip_id|, which is too // specific. bool CommitProperties(drmModeAtomicReq* properties, uint32_t flags,
diff --git a/ui/ozone/platform/drm/gpu/drm_device.cc b/ui/ozone/platform/drm/gpu/drm_device.cc index 965d1ce..4045bf1d 100644 --- a/ui/ozone/platform/drm/gpu/drm_device.cc +++ b/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -267,6 +267,17 @@ DrmWrapper::WriteIntoTrace(std::move(dict)); } +display::DrmFormatsAndModifiers DrmDevice::GetFormatsAndModifiersForCrtc( + uint32_t crtc_id) const { + display::DrmFormatsAndModifiers drm_formats_and_modifiers; + for (uint32_t format : plane_manager_->GetSupportedFormats()) { + std::vector<uint64_t> modifiers = + plane_manager_->GetFormatModifiers(crtc_id, format); + drm_formats_and_modifiers.emplace(format, modifiers); + } + return drm_formats_and_modifiers; +} + int DrmDevice::modeset_sequence_id() const { return modeset_sequence_id_; } } // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/drm_device.h b/ui/ozone/platform/drm/gpu/drm_device.h index 822086e..86a44ba 100644 --- a/ui/ozone/platform/drm/gpu/drm_device.h +++ b/ui/ozone/platform/drm/gpu/drm_device.h
@@ -68,6 +68,9 @@ // Adds trace records to |context|. void WriteIntoTrace(perfetto::TracedDictionary dict) const override; + display::DrmFormatsAndModifiers GetFormatsAndModifiersForCrtc( + uint32_t crtc_id) const override; + virtual int modeset_sequence_id() const; HardwareDisplayPlaneManager* plane_manager() { return plane_manager_.get(); } GbmDevice* gbm_device() const { return gbm_.get(); }
diff --git a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc index 59dbb0a..8e396944 100644 --- a/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc +++ b/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.cc
@@ -36,6 +36,12 @@ // configuration (modeset) via a udev display CHANGE event. const char* kBlockedEventsByTriggerProperty[] = {"Content Protection"}; +struct DrmDisplayParams { + scoped_refptr<DrmDevice> drm; + std::unique_ptr<HardwareDisplayControllerInfo> display_info; + display::DisplaySnapshot* snapshot; +}; + class DisplayComparator { public: explicit DisplayComparator(const DrmDisplay* display) @@ -131,7 +137,8 @@ MovableDisplaySnapshots DrmGpuDisplayManager::GetDisplays() { std::vector<std::unique_ptr<DrmDisplay>> old_displays; old_displays.swap(displays_); - MovableDisplaySnapshots all_display_snapshots; + std::vector<DrmDisplayParams> displays_to_create; + MovableDisplaySnapshots display_snapshots; const DrmDeviceVector& devices = drm_device_manager_->GetDrmDevices(); size_t device_index = 0; @@ -144,7 +151,6 @@ << devices.size() - kMaxDrmCount << " connected devices."; break; } - MovableDisplaySnapshots display_snapshots; // Receiving a signal that DRM state was updated. Need to reset the plane // manager's resource cache since IDs may have changed. @@ -152,19 +158,9 @@ // Create new DisplaySnapshots and resolve display ID collisions. auto display_infos = GetDisplayInfosAndUpdateCrtcs(*drm); - for (const auto& display_info : display_infos) { - // Create list of supported drm formats and modifiers - display::DrmFormatsAndModifiers drm_formats_and_modifiers; - for (uint32_t format : drm->plane_manager()->GetSupportedFormats()) { - std::vector<uint64_t> modifiers = - drm->plane_manager()->GetFormatModifiers( - display_info->crtc()->crtc_id, format); - drm_formats_and_modifiers.emplace(format, modifiers); - } - + for (auto& display_info : display_infos) { display_snapshots.emplace_back(CreateDisplaySnapshot( - *drm, display_info.get(), static_cast<uint8_t>(device_index), - drm_formats_and_modifiers)); + *drm, display_info.get(), static_cast<uint8_t>(device_index))); display::DisplaySnapshot* current_display_snapshot = display_snapshots.back().get(); @@ -183,44 +179,41 @@ } edid_id_collision_map[current_display_snapshot->edid_display_id()] = current_display_snapshot; + + // Ownership of |display_info| is handed over. + displays_to_create.push_back( + {drm, std::move(display_info), current_display_snapshot}); } - DCHECK_EQ(display_infos.size(), display_snapshots.size()); - - // Create a new DrmDisplay with each of the corresponding display info and - // display snapshot. Note: do not use |display_infos| beyond this point, - // since some of the objects' internal references will be surrendered. - for (size_t i = 0; i < display_infos.size(); ++i) { - // If the DrmDisplay was present previously, copy its origin to the - // corresponding DisplaySnapshot before creating a new DrmDisplay. - const auto& display_info = display_infos[i]; - auto old_drm_display_it = base::ranges::find_if( - old_displays, - DisplayComparator(drm, display_info->crtc()->crtc_id, - display_info->connector()->connector_id)); - if (old_drm_display_it != old_displays.end()) { - display_snapshots[i]->set_origin(old_drm_display_it->get()->origin()); - old_displays.erase(old_drm_display_it); - } - - displays_.emplace_back(std::make_unique<DrmDisplay>( - drm, display_info.get(), *display_snapshots[i])); - } - all_display_snapshots.insert( - all_display_snapshots.end(), - std::make_move_iterator(display_snapshots.begin()), - std::make_move_iterator(display_snapshots.end())); - device_index++; } - const bool multiple_connected_displays = all_display_snapshots.size() > 1; + // Create a new DrmDisplay with each of the corresponding display info and + // display snapshot. Note: do not use |display_infos| beyond this point, + // since some of the objects' internal references will be surrendered. + for (const DrmDisplayParams& params : displays_to_create) { + // If the DrmDisplay was present previously, copy its origin to the + // corresponding DisplaySnapshot before creating a new DrmDisplay. + auto old_drm_display_it = base::ranges::find_if( + old_displays, + DisplayComparator(params.drm, params.display_info->crtc()->crtc_id, + params.display_info->connector()->connector_id)); + if (old_drm_display_it != old_displays.end()) { + params.snapshot->set_origin(old_drm_display_it->get()->origin()); + old_displays.erase(old_drm_display_it); + } + + displays_.emplace_back(std::make_unique<DrmDisplay>( + params.drm, params.display_info.get(), *params.snapshot)); + } + + const bool multiple_connected_displays = display_snapshots.size() > 1; if (multiple_connected_displays) { base::UmaHistogramBoolean(kMultipleDisplayIdsCollisionDetected, collision_detected); } NotifyScreenManager(displays_, old_displays); - return all_display_snapshots; + return display_snapshots; } bool DrmGpuDisplayManager::TakeDisplayControl() {
diff --git a/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/ui/ozone/platform/drm/host/drm_display_host_manager.cc index 4c063df..e803c55 100644 --- a/ui/ozone/platform/drm/host/drm_display_host_manager.cc +++ b/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -285,8 +285,7 @@ for (auto& display_info : display_infos) { // Create a dummy DisplaySnapshot and resolve display ID collisions. std::unique_ptr<display::DisplaySnapshot> current_display_snapshot = - CreateDisplaySnapshot(*primary_drm_device_, display_info.get(), 0, - display::DrmFormatsAndModifiers()); + CreateDisplaySnapshot(*primary_drm_device_, display_info.get(), 0); const auto colliding_display_snapshot_iter = edid_id_collision_map.find(current_display_snapshot->edid_display_id());
diff --git a/ui/views/OWNERS b/ui/views/OWNERS index 32e5ffae..74e21447 100644 --- a/ui/views/OWNERS +++ b/ui/views/OWNERS
@@ -4,6 +4,7 @@ # 5 minutes. This approach helps our team to load-balance incoming reviews. # Googlers can read more about this at go/gwsq-gerrit. +dfried@chromium.org elainechien@chromium.org ellyjones@chromium.org kerenzhu@chromium.org
diff --git a/ui/views/bubble/OWNERS b/ui/views/bubble/OWNERS deleted file mode 100644 index ee6c77a26..0000000 --- a/ui/views/bubble/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -msw@chromium.org -dfried@chromium.org
diff --git a/ui/views/controls/button/button.cc b/ui/views/controls/button/button.cc index e4e9090a..d50193d 100644 --- a/ui/views/controls/button/button.cc +++ b/ui/views/controls/button/button.cc
@@ -161,11 +161,15 @@ void Button::SetTooltipText(const std::u16string& tooltip_text) { if (tooltip_text == tooltip_text_) return; + + if (GetAccessibleName().empty() || GetAccessibleName() == tooltip_text_) { + SetAccessibleName(tooltip_text); + } + tooltip_text_ = tooltip_text; OnSetTooltipText(tooltip_text); TooltipTextChanged(); OnPropertyChanged(&tooltip_text_, kPropertyEffectsNone); - NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, true); } std::u16string Button::GetTooltipText() const { @@ -176,9 +180,11 @@ callback_ = std::move(callback); } -const std::u16string& Button::GetAccessibleName() const { - return View::GetAccessibleName().empty() ? tooltip_text_ - : View::GetAccessibleName(); +void Button::AdjustAccessibleName(std::u16string& new_name, + ax::mojom::NameFrom& name_from) { + if (new_name.empty()) { + new_name = tooltip_text_; + } } Button::ButtonState Button::GetState() const {
diff --git a/ui/views/controls/button/button.h b/ui/views/controls/button/button.h index 4c2544f..134942a 100644 --- a/ui/views/controls/button/button.h +++ b/ui/views/controls/button/button.h
@@ -132,7 +132,8 @@ virtual void SetCallback(PressedCallback callback); - const std::u16string& GetAccessibleName() const override; + void AdjustAccessibleName(std::u16string& new_name, + ax::mojom::NameFrom& name_from) override; // Get/sets the current display state of the button. ButtonState GetState() const;
diff --git a/ui/views/controls/label.cc b/ui/views/controls/label.cc index cf14820..37c22391 100644 --- a/ui/views/controls/label.cc +++ b/ui/views/controls/label.cc
@@ -119,9 +119,11 @@ stored_selection_range_ = gfx::Range::InvalidRange(); } -const std::u16string& Label::GetAccessibleName() const { - return View::GetAccessibleName().empty() ? full_text_->GetDisplayText() - : View::GetAccessibleName(); +void Label::AdjustAccessibleName(std::u16string& new_name, + ax::mojom::NameFrom& name_from) { + if (new_name.empty()) { + new_name = full_text_->GetDisplayText(); + } } int Label::GetTextContext() const {
diff --git a/ui/views/controls/label.h b/ui/views/controls/label.h index cfcc785..03c33a8 100644 --- a/ui/views/controls/label.h +++ b/ui/views/controls/label.h
@@ -102,9 +102,8 @@ const std::u16string& GetText() const; virtual void SetText(const std::u16string& text); - // Returns the value of `accessible_name_` if it has been set, otherwise the - // text value. - const std::u16string& GetAccessibleName() const override; + void AdjustAccessibleName(std::u16string& new_name, + ax::mojom::NameFrom& name_from) override; // Where the label appears in the UI. Passed in from the constructor. This is // a value from views::style::TextContext or an enum that extends it.
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index c46a94f..9752106b 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -2172,7 +2172,7 @@ // taken into account within CalculateBubbleMenuBounds() and elsewhere. gfx::Rect bounds = MenuItemView::IsBubble(state_.anchor) || - (menu_config.use_bubble_border && + (!IsCombobox() && menu_config.use_bubble_border && menu_config.CornerRadiusForMenu(this)) ? CalculateBubbleMenuBounds(item, prefer_leading, &resulting_direction, &anchor)
diff --git a/ui/views/controls/menu/menu_scroll_view_container.cc b/ui/views/controls/menu/menu_scroll_view_container.cc index 93ef017f..6298779 100644 --- a/ui/views/controls/menu/menu_scroll_view_container.cc +++ b/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -392,7 +392,8 @@ void MenuScrollViewContainer::CreateDefaultBorder() { DCHECK_EQ(arrow_, BubbleBorder::NONE); - + MenuController* menu_controller = + content_view_->GetMenuItem()->GetMenuController(); const MenuConfig& menu_config = MenuConfig::instance(); corner_radius_ = menu_config.CornerRadiusForMenu( content_view_->GetMenuItem()->GetMenuController()); @@ -410,9 +411,8 @@ int bottom_inset = GetFootnote() ? 0 : vertical_inset; if (menu_config.use_outer_border) { - if (menu_config.use_bubble_border && - menu_config.CornerRadiusForMenu( - content_view_->GetMenuItem()->GetMenuController())) { + if (menu_config.use_bubble_border && (corner_radius_ > 0) && + !menu_controller->IsCombobox()) { CreateBubbleBorder(); } else { gfx::Insets insets = gfx::Insets::TLBR(vertical_inset, horizontal_inset, @@ -425,6 +425,9 @@ return; } + SetBackground(CreateThemedRoundedRectBackground(ui::kColorMenuBackground, + corner_radius_)); + SkColor color = GetWidget() ? GetColorProvider()->GetColor(ui::kColorMenuBorder) : gfx::kPlaceholderColor;
diff --git a/ui/views/examples/OWNERS b/ui/views/examples/OWNERS deleted file mode 100644 index ae1ee7d..0000000 --- a/ui/views/examples/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -per-file *layout*=dfried@chromium.org
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn index eea0223d..1b8c167 100644 --- a/ui/webui/resources/cr_elements/BUILD.gn +++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -17,7 +17,6 @@ ] non_web_component_files = [ - "cr_lazy_render/cr_lazy_render.ts", "cr_splitter/cr_splitter.ts", "cr_tree/cr_tree_base.ts", ] @@ -73,6 +72,7 @@ non_web_component_files += [ "cr_auto_img/cr_auto_img.ts", "cr_container_shadow_mixin.ts", + "cr_lazy_render/cr_lazy_render.ts", "cr_menu_selector/cr_menu_selector.ts", "cr_radio_button/cr_radio_button_mixin.ts", "cr_scrollable_mixin.ts",
diff --git a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html index ab4b752..8a054b7 100644 --- a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html +++ b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.html
@@ -1,5 +1,10 @@ <style include="cr-hidden-style cr-icons"> :host { + --cr-url-list-item-image-container-border_: 2px solid white; + /* Intentionally 1px higher than the inherited border radius to avoid + * anti-aliasing issues. + */ + --cr-url-list-item-image-container-border-radius_: 5px; align-items: center; box-sizing: border-box; cursor: default; @@ -9,11 +14,22 @@ width: 100%; } + @media (prefers-color-scheme: dark) { + :host { + --cr-url-list-item-image-container-border_: 2px solid black; + } + } + :host-context([chrome-refresh-2023]):host { height: 48px; padding: 4px 16px; } + :host-context([chrome-refresh-2023]):host([size=medium]), + :host-context([chrome-refresh-2023]):host([size=large]) { + --cr-url-list-item-image-container-border-radius_: 9px; + } + :host([size=compact]) { height: 32px; padding: 8px 20px; @@ -124,10 +140,20 @@ } .folder-and-count .image-container { + border-bottom: var(--cr-url-list-item-image-container-border_); + border-radius: 0 var(--cr-url-list-item-image-container-border-radius_) + 0 0; + box-sizing: border-box; height: 100%; + overflow: hidden; width: 100%; } + :host-context([dir=rtl]) .folder-and-count .image-container { + border-radius: var(--cr-url-list-item-image-container-border-radius_) + 0 0 0; + } + .folder-and-count .image-container img { height: 100%; object-fit: cover; @@ -135,14 +161,26 @@ width: 100%; } - /* If there is only 1 img, span the entire grid. */ - .folder-and-count .image-container:first-of-type:not(:has(~ .image-container:nth-child(2))) { - grid-column: 1 / span 2; + /* If there is only 2 imgs, span the 1st image across both rows. */ + .folder-and-count:not(:has(div:nth-child(3))) + .image-container:first-of-type { + border-bottom: none; + border-inline-end: var(--cr-url-list-item-image-container-border_); + border-radius: var(--cr-url-list-item-image-container-border-radius_) 0 0 + var(--cr-url-list-item-image-container-border-radius_); grid-row: 1 / span 2; } - /* If there is only 2 imgs, span the 1st image across both rows. */ - .folder-and-count .image-container:first-of-type:not(:has(~ .image-container:nth-of-type(3))) { + :host-context([dir=rtl]) .folder-and-count:not(:has(div:nth-child(3))) + .image-container:first-of-type { + border-radius: 0 var(--cr-url-list-item-image-container-border-radius_) + var(--cr-url-list-item-image-container-border-radius_) 0; + } + + /* If there is only 1 img, span the entire grid. */ + .folder-and-count:not(:has(div:nth-child(2))) .image-container:first-of-type { + border: none; + grid-column: 1 / span 2; grid-row: 1 / span 2; } @@ -154,13 +192,14 @@ } .count { + --cr-url-list-item-count-border-radius: 4px; display: none; } :host([size=large]) .count { align-items: center; background: var(--google-grey-50); - border-radius: 4px 0 0 0; + border-radius: var(--cr-url-list-item-count-border-radius) 0 0 0; display: flex; grid-column: 2; grid-row: 2; @@ -170,6 +209,14 @@ z-index: 1; } + :host-context([dir=rtl]):host([size=large]) .count { + border-radius: 0 var(--cr-url-list-item-count-border-radius) 0 0; + } + + .folder-and-count:has(div:nth-child(2)) .count { + border-radius: 0; + } + @media (prefers-color-scheme: dark) { :host([size=large]) .count { background: rgba(var(--google-grey-200-rgb), .11); @@ -187,10 +234,7 @@ * against the row background. */ background: black; - /* Intentionally 1px higher than the inherited border radius to avoid - * anti-aliasing issues. - */ - border-radius: 5px; + border-radius: var(--cr-url-list-item-image-container-border-radius_); height: 100%; width: 100%; } @@ -201,11 +245,6 @@ } } - :host-context([chrome-refresh-2023]):host([size=medium]) .image-container, - :host-context([chrome-refresh-2023]):host([size=large]) .image-container { - border-radius: 9px; - } - .metadata { display: flex; flex-direction: column; @@ -342,14 +381,17 @@ <div class="favicon" hidden$="[[!shouldShowFavicon_(url, size, imageUrls)]]" style$="background-image: [[getFavicon_(url)]];"> </div> - <div class="image-container" hidden$="[[!shouldShowUrlImage_(url, size, imageUrls)]]"> + <div class="image-container" + hidden$="[[!shouldShowUrlImage_(url, size, imageUrls)]]"> <img class="url-image" is="cr-auto-img" auto-src="[[imageUrls.0]]"> </div> - <div class="folder-and-count" hidden$="[[!shouldShowFolderCount_(url, count)]]"> + <div class="folder-and-count" + hidden$="[[!shouldShowFolderCount_(url, count)]]"> <template is="dom-if" if="[[shouldShowFolderImages_(size)]]" restamp> - <template is="dom-repeat" items="[[imageUrls]]" filter="shouldShowImageUrl_"> + <template is="dom-repeat" items="[[imageUrls]]" + filter="shouldShowImageUrl_"> <div class="image-container"> - <img is="cr-auto-img" auto-src="[[item]]"> + <img class="folder-image" is="cr-auto-img" auto-src="[[item]]"> </div> </template> </template>
diff --git a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts index 75d01e4..0968b4d9 100644 --- a/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts +++ b/ui/webui/resources/cr_elements/cr_url_list_item/cr_url_list_item.ts
@@ -126,7 +126,7 @@ } private shouldShowImageUrl_(_url: string, index: number) { - return index <= 2; + return index <= 1; } private onBadgesSlotChange_() {