diff --git a/DEPS b/DEPS index b9824936..62ddcc3 100644 --- a/DEPS +++ b/DEPS
@@ -229,7 +229,7 @@ # # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-amd64-generic-chrome-skylab # CQ_INCLUDE_TRYBOTS=luci.chrome.try:lacros-arm-generic-chrome-skylab - 'lacros_sdk_version': '15274.0.0', + 'lacros_sdk_version': '15275.0.0', # Generate location tag metadata to include in tests result data uploaded # to ResultDB. This isn't needed on some configs and the tool that generates @@ -299,7 +299,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': 'c466f3cc8f9ec2426a150538e3e25eb408fcbc26', + 'skia_revision': '5e69caecd1662c38c14fb5317ef3c60e5b447068', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -307,7 +307,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': '001ba94e3d7ccfcc4de4b5fee6a14b2fa7159832', + 'angle_revision': 'ef6f212741f86526b45525500eab8edabfacaba8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -370,7 +370,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'bf0782db65682f3918886ba69807c03fe515c2e8', + 'catapult_revision': 'c6c22477986b41016ba45c0bd6fbe56a3a6a211a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -418,7 +418,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': 'bb8ac619a1e6563a94cf2abd0e59df9d795fa8a3', + 'quiche_revision': 'df493d7b57cb3ebba5e9bc6f6ccf9fefeb51ade0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -478,7 +478,7 @@ # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. - 'libcxx_revision': '2fc3d704672fbd3e85fad8492d39e02d49412891', + 'libcxx_revision': '2948540a20cbb5b2192119f791b04dd62ca7af1c', # GN CIPD package version. 'gn_version': 'git_revision:5e19d2fb166fbd4f6f32147fbb2f497091a54ad8', @@ -771,7 +771,7 @@ 'src/clank': { 'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' + - 'e5a34e1311d08d400344132fe2c9f950d95b09dd', + 'c4059e60bbab0bd98f495fce64739433b234b799', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1123,7 +1123,7 @@ Var('boringssl_git') + '/boringssl.git' + '@' + Var('boringssl_revision'), 'src/third_party/breakpad/breakpad': - Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'cc7abac08b0c52e6581b9c9c4226816b17a4c26d', + Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '80430d73aee1fe591bea1475ba3b7fc30c67dfc2', 'src/third_party/byte_buddy': { 'packages': [ @@ -1211,7 +1211,7 @@ Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'aa28943dc8caddd449134912571d51f0f50d671e', + 'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'f6289dce686d0e4dc0f00e89bd451be7c07b1e1a', 'condition': 'checkout_src_internal', }, @@ -1623,7 +1623,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'db956674bbdfbaab5acdd3fdb4117c2fef5527e9', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '9942fb6d07c9c72b9dcee9e777c544e256f1fb61', + Var('chromium_git') + '/openscreen' + '@' + '76d25f8ec350f778a73d9040e6289e9dc78a2167', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245', @@ -1640,7 +1640,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '42498077f54f5e3093b865b22cf6822f14c73222', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '39f3c505498164c3ad9ca31a4f5924de5d6aa8d0', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1822,10 +1822,10 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'd1b65aa5a88f6efd900604dfcda840154e9f16e2', 'src/third_party/webgpu-cts/src': - Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e0e7353ccfe5e97a53aed37b4d3d49799fc8de5c', + Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e583fa45095a98e12cc28748b30c2b1a9e5babcf', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '2e1a9a4ae0234d4b1ea7a6fd4188afa1fb20379d', + Var('webrtc_git') + '/src.git' + '@' + 'adddc10684259341975292f97227fd3475f0433e', # 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. @@ -1895,7 +1895,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@3d104f2aeaf16bf5d185c1f4459b7ca0ff55cdcf', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f104cd966e5513ce48b931a2dc8a8808a653c255', 'condition': 'checkout_src_internal', }, @@ -1936,7 +1936,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'OEBt9gPj59-k8q24vYKZksVSx7x0ium6Vv_5VqjOqcQC', + 'version': '0UTlluPAiKIWx1AV31tqb0ghjdO_4tLoZXL2sA-8CUIC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1947,7 +1947,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/projector_app/app', - 'version': 'FEgnPkcHkeDWehL6Lgt_7aeLRFMDt0iL7Dkl0xWEaf4C', + 'version': 'r3WZGfNcq6NNemjXUw3EkQEb76_BLcQgkTELM0rbAqUC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4862,7 +4862,7 @@ { 'name': 'Fetch PGO profiles for mac', 'pattern': '.', - 'condition': 'checkout_pgo_profiles and (checkout_mac or checkout_fuchsia)', + 'condition': 'checkout_pgo_profiles and checkout_mac', 'action': [ 'python3', 'src/tools/update_pgo_profiles.py', '--target=mac', @@ -4873,7 +4873,7 @@ { 'name': 'Fetch PGO profiles for mac arm', 'pattern': '.', - 'condition': 'checkout_pgo_profiles and (checkout_mac or checkout_android or checkout_fuchsia)', + 'condition': 'checkout_pgo_profiles and (checkout_mac or checkout_android)', 'action': [ 'python3', 'src/tools/update_pgo_profiles.py', '--target=mac-arm',
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn index 7575e4ee..6e539cc 100644 --- a/android_webview/BUILD.gn +++ b/android_webview/BUILD.gn
@@ -16,6 +16,7 @@ import("//chrome/android/trichrome.gni") import("//components/safe_browsing/buildflags.gni") import("//components/spellcheck/spellcheck_build_features.gni") +import("//components/supervised_user/buildflags.gni") import("//device/vr/buildflags/buildflags.gni") import("//pdf/features.gni") import("//printing/buildflags/buildflags.gni") @@ -1113,6 +1114,7 @@ defines = [ "enable_printing=$enable_printing", "safe_browsing_mode=$safe_browsing_mode", + "enable_supervised_users=$enable_supervised_users", ] # See :generate_webui_resources for an explanation of the allowlist
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index aba1cadb..a760f72 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1940,6 +1940,8 @@ "system/video_conference/bubble/bubble_view_ids.h", "system/video_conference/bubble/return_to_app_button.cc", "system/video_conference/bubble/return_to_app_button.h", + "system/video_conference/bubble/set_value_effects_view.cc", + "system/video_conference/bubble/set_value_effects_view.h", "system/video_conference/bubble/toggle_effects_view.cc", "system/video_conference/bubble/toggle_effects_view.h", "system/video_conference/effects/fake_video_conference_effects.cc",
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc index 21f6e33..b970370 100644 --- a/ash/app_list/views/app_list_view_unittest.cc +++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -671,6 +671,7 @@ result->set_display_score(score); result->SetTitle(ASCIIToUTF16(title)); result->set_best_match(true); + result->SetCategory(ash::AppListSearchResultCategory::kWeb); GetSearchModel()->results()->Add(std::move(result)); base::RunLoop().RunUntilIdle(); } @@ -1002,8 +1003,8 @@ TestFocusTraversal(backward_view_list, ui::VKEY_UP, false); } -// Tests that focus changes update the search box text. -TEST_F(AppListViewFocusTest, SearchBoxTextUpdatesOnResultFocus) { +// Tests that focus changes does not update the search box text. +TEST_F(AppListViewFocusTest, SearchBoxTextDoesNotUpdateOnResultFocus) { Show(); views::Textfield* search_box = search_box_view()->search_box(); search_box->InsertText( @@ -1019,18 +1020,24 @@ // Change focus to the next result SimulateKeyPress(ui::VKEY_TAB, false); - EXPECT_EQ(search_box->GetText(), u"TestResult2"); + EXPECT_EQ(search_box->GetText(), u"TestText"); + EXPECT_EQ(search_box_view()->GetSearchBoxGhostTextForTest(), + "TestResult2 - Websites"); SimulateKeyPress(ui::VKEY_TAB, true); - EXPECT_EQ(search_box->GetText(), u"TestResult1"); + EXPECT_EQ(search_box->GetText(), u"TestText"); + EXPECT_EQ(search_box_view()->GetSearchBoxGhostTextForTest(), + "TestResult1 - Websites"); SimulateKeyPress(ui::VKEY_TAB, false); // Change focus to the final result SimulateKeyPress(ui::VKEY_TAB, false); - EXPECT_EQ(search_box->GetText(), u"TestResult3"); + EXPECT_EQ(search_box->GetText(), u"TestText"); + EXPECT_EQ(search_box_view()->GetSearchBoxGhostTextForTest(), + "TestResult3 - Websites"); } // Tests that ctrl-A selects all text in the searchbox when the SearchBoxView is
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 32d9149..5745207 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -251,7 +251,7 @@ // Enables or disables extended autocomplete results. BASE_FEATURE(kAutocompleteExtendedSuggestions, "AutocompleteExtendedSuggestions", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Enables params tuning experiment for autocorrect on ChromeOS. BASE_FEATURE(kAutocorrectParamsTuning, @@ -507,7 +507,7 @@ // the user. BASE_FEATURE(kChromadAvailable, "ChromadAvailable", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); // Enables or disables always using device-activity-status data to filter // eligible host phones.
diff --git a/ash/projector/projector_controller_impl.cc b/ash/projector/projector_controller_impl.cc index f670cc7c..05972743 100644 --- a/ash/projector/projector_controller_impl.cc +++ b/ash/projector/projector_controller_impl.cc
@@ -237,8 +237,13 @@ void ProjectorControllerImpl::OnTranscriptionError() { is_speech_recognition_on_ = false; - ProjectorUiController::ShowFailureNotification( - IDS_ASH_PROJECTOR_FAILURE_MESSAGE_TRANSCRIPTION); + // TODO(b/261093550) Investigate the real reason why + // we get a speech recognition error after we notify it to + // stop. + if (!pending_speech_recognition_stop_) { + ProjectorUiController::ShowFailureNotification( + IDS_ASH_PROJECTOR_FAILURE_MESSAGE_TRANSCRIPTION); + } auto* capture_mode_controller = CaptureModeController::Get(); if (capture_mode_controller->is_recording_in_progress()) { @@ -247,11 +252,13 @@ } else { MaybeWrapUpRecording(); } + + pending_speech_recognition_stop_ = false; } void ProjectorControllerImpl::OnSpeechRecognitionStopped() { is_speech_recognition_on_ = false; - + pending_speech_recognition_stop_ = false; // Try to wrap up recording. This can be no-op if DLP check is not completed. MaybeWrapUpRecording(); } @@ -495,6 +502,7 @@ DCHECK(!is_speech_recognition_on_); client_->StartSpeechRecognition(); is_speech_recognition_on_ = true; + pending_speech_recognition_stop_ = false; } void ProjectorControllerImpl::MaybeStopSpeechRecognition() { @@ -507,6 +515,7 @@ DCHECK(client_->GetSpeechRecognitionAvailability().IsAvailable()); client_->StopSpeechRecognition(); + pending_speech_recognition_stop_ = true; } void ProjectorControllerImpl::OnContainerFolderCreated(
diff --git a/ash/projector/projector_controller_impl.h b/ash/projector/projector_controller_impl.h index 3990484e..d93587c0 100644 --- a/ash/projector/projector_controller_impl.h +++ b/ash/projector/projector_controller_impl.h
@@ -195,6 +195,10 @@ std::unique_ptr<ProjectorUiController> ui_controller_; std::unique_ptr<ProjectorMetadataController> metadata_controller_; + // Whether ProjectorController has informed its client to stop + // speech recognition. + bool pending_speech_recognition_stop_ = false; + // Whether speech recognition is taking place or not. bool is_speech_recognition_on_ = false;
diff --git a/ash/system/video_conference/bubble/bubble_view.cc b/ash/system/video_conference/bubble/bubble_view.cc index c83ffe5b..1978bea 100644 --- a/ash/system/video_conference/bubble/bubble_view.cc +++ b/ash/system/video_conference/bubble/bubble_view.cc
@@ -7,6 +7,7 @@ #include "ash/system/tray/tray_bubble_view.h" #include "ash/system/video_conference/bubble/bubble_view_ids.h" #include "ash/system/video_conference/bubble/return_to_app_button.h" +#include "ash/system/video_conference/bubble/set_value_effects_view.h" #include "ash/system/video_conference/bubble/toggle_effects_view.h" #include "ash/system/video_conference/effects/video_conference_tray_effects_manager.h" #include "ash/system/video_conference/video_conference_tray_controller.h" @@ -37,6 +38,10 @@ if (controller->effects_manager().HasToggleEffects()) AddChildView(std::make_unique<ToggleEffectsView>(controller)); + if (controller->effects_manager().HasSetValueEffects()) { + AddChildView(std::make_unique<SetValueEffectsView>(controller)); + } + SetBorder(views::CreateEmptyBorder( gfx::Insets::VH(kBorderInsetDimension, kBorderInsetDimension))); }
diff --git a/ash/system/video_conference/bubble/bubble_view_ids.h b/ash/system/video_conference/bubble/bubble_view_ids.h index 6c49072..0b9d68d 100644 --- a/ash/system/video_conference/bubble/bubble_view_ids.h +++ b/ash/system/video_conference/bubble/bubble_view_ids.h
@@ -29,9 +29,16 @@ // `kToggleEffectsContainer`. kToggleEffectsButton, - // Button for setting an individual value of a "set-value" VC effect, a child - // of `kSetValueEffectsContainer`. - kSetValueButton, + // Buttons for setting an individual value of a "set-value" VC effect, + // children of `kSetValueEffectsContainer`. Since the number of values for a + // given effect can't be known at compile-time, an allowable range of IDs + // [`kSetValueButtonMin`..`kSetValueButtonMax`] is allocated, with IDs clamped + // at kSetValueButtonMax. If a specific ID doesn't matter, then just use + // `kSetValueButton`. + kSetValueButtonMin = kToggleEffectsButton + 1, + kSetValueButton = kSetValueButtonMin, + kSetValueButtonMax = kSetValueButtonMin + 100, + kNextAvailableId = kSetValueButtonMax + 1, }; } // namespace ash::video_conference
diff --git a/ash/system/video_conference/bubble/bubble_view_unittest.cc b/ash/system/video_conference/bubble/bubble_view_unittest.cc index aea661c..3c89fb4 100644 --- a/ash/system/video_conference/bubble/bubble_view_unittest.cc +++ b/ash/system/video_conference/bubble/bubble_view_unittest.cc
@@ -46,6 +46,7 @@ // Instantiate these fake effects, to be registered/unregistered as needed. office_bunny_ = std::make_unique<fake_video_conference::OfficeBunnyEffect>(); + shaggy_fur_ = std::make_unique<fake_video_conference::ShaggyFurEffect>(); set_create_global_cras_audio_handler(false); AshTestBase::SetUp(); @@ -54,11 +55,21 @@ void TearDown() override { AshTestBase::TearDown(); office_bunny_.reset(); + shaggy_fur_.reset(); controller_.reset(); CrasAudioHandler::Shutdown(); CrasAudioClient::Shutdown(); } + views::View* GetSetValueEffectButton(int index) { + // Map `index` to a `BubbleViewID`, for lookup. + BubbleViewID id = + static_cast<BubbleViewID>(index + BubbleViewID::kSetValueButtonMin); + DCHECK_GE(id, BubbleViewID::kSetValueButtonMin); + DCHECK_LE(id, BubbleViewID::kSetValueButtonMax); + return bubble_view()->GetViewByID(id); + } + VideoConferenceTray* video_conference_tray() { return StatusAreaWidgetTestHelper::GetStatusAreaWidget() ->video_conference_tray(); @@ -79,6 +90,11 @@ video_conference::BubbleViewID::kToggleEffectsView); } + views::View* set_value_effects_view() { + return bubble_view()->GetViewByID( + video_conference::BubbleViewID::kSetValueEffectsView); + } + views::View* return_to_app() { return bubble_view()->GetViewByID( video_conference::BubbleViewID::kReturnToApp); @@ -93,10 +109,15 @@ return office_bunny_.get(); } + ash::fake_video_conference::ShaggyFurEffect* shaggy_fur() { + return shaggy_fur_.get(); + } + private: base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<FakeVideoConferenceTrayController> controller_; std::unique_ptr<ash::fake_video_conference::OfficeBunnyEffect> office_bunny_; + std::unique_ptr<ash::fake_video_conference::ShaggyFurEffect> shaggy_fur_; }; TEST_F(BubbleViewTest, NoEffects) { @@ -174,4 +195,80 @@ EXPECT_EQ(office_bunny()->num_activations_for_testing(), 1); } +TEST_F(BubbleViewTest, RegisterSetValueEffect) { + // Open up the bubble, no set-value effects present. + LeftClickOn(toggle_bubble_button()); + EXPECT_FALSE(toggle_effects_view()); + + // Close the bubble. + LeftClickOn(toggle_bubble_button()); + + // Add one set-value effect. + controller()->effects_manager().RegisterDelegate(shaggy_fur()); + + // Open up the bubble, set-value effects container view is present/visible. + LeftClickOn(toggle_bubble_button()); + EXPECT_TRUE(set_value_effects_view()); + EXPECT_TRUE(set_value_effects_view()->GetVisible()); +} + +TEST_F(BubbleViewTest, UnregisterSetValueEffect) { + // Add one set-value effect. + controller()->effects_manager().RegisterDelegate(shaggy_fur()); + + // Open up the bubble, set-value effects are present/visible. + LeftClickOn(toggle_bubble_button()); + EXPECT_TRUE(set_value_effects_view()); + EXPECT_TRUE(set_value_effects_view()->GetVisible()); + + // Take down the bubble. + LeftClickOn(toggle_bubble_button()); + + // Remove the set-value effect. + controller()->effects_manager().UnregisterDelegate(shaggy_fur()); + + // Open up the bubble again, no effects present. + LeftClickOn(toggle_bubble_button()); + EXPECT_FALSE(set_value_effects_view()); +} + +TEST_F(BubbleViewTest, SetValueButtonClicked) { + // Verify that the delegate hosts a single effect which has at least two + // values. + EXPECT_EQ(shaggy_fur()->GetNumEffects(), 1); + EXPECT_GE(shaggy_fur()->GetEffect(0)->GetNumStates(), 2); + + // Add one set-value effect. + controller()->effects_manager().RegisterDelegate(shaggy_fur()); + + // Click to open the bubble, effect value 0 button is present/visible. + LeftClickOn(toggle_bubble_button()); + views::View* button = GetSetValueEffectButton(0); + EXPECT_TRUE(button); + EXPECT_TRUE(button->GetVisible()); + + // Effect button for value 0 has not yet been clicked. + EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(0), 0); + + // Click the effect value 0 button, verify that the value has been "activated" + // once. + LeftClickOn(button); + EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(0), 1); + + // Now test another button, confirm that set-value effect button 1 is + // present/visible. + button = GetSetValueEffectButton(1); + EXPECT_TRUE(button); + EXPECT_TRUE(button->GetVisible()); + + // Effect button for value 1 has not yet been clicked. + EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(1), 0); + + // Click the effect value 1 button, verify that value 1 has been "activated" + // once, and confirm that value 0 has still only been activated once i.e. we + // just activated value 1 and not value 0. + LeftClickOn(button); + EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(1), 1); + EXPECT_EQ(shaggy_fur()->GetNumActivationsForTesting(0), 1); +} } // namespace ash::video_conference \ No newline at end of file
diff --git a/ash/system/video_conference/bubble/set_value_effects_view.cc b/ash/system/video_conference/bubble/set_value_effects_view.cc new file mode 100644 index 0000000..7c6bec1 --- /dev/null +++ b/ash/system/video_conference/bubble/set_value_effects_view.cc
@@ -0,0 +1,85 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/system/video_conference/bubble/set_value_effects_view.h" + +#include "ash/system/video_conference/bubble/bubble_view_ids.h" +#include "ash/system/video_conference/effects/video_conference_tray_effects_manager_types.h" +#include "ash/system/video_conference/video_conference_tray_controller.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/radio_button.h" +#include "ui/views/controls/label.h" +#include "ui/views/controls/separator.h" +#include "ui/views/layout/flex_layout.h" + +namespace ash::video_conference { + +namespace { + +// A view with label (for the effect name) that allows the user to select from +// one of several integer values. TODO(b/253273036) Implement this as a +// tab-slider view instead of a radio switch. +class ValueButtonContainer : public views::View { + public: + explicit ValueButtonContainer(const VcHostedEffect* effect) { + views::FlexLayout* layout = + SetLayoutManager(std::make_unique<views::FlexLayout>()); + layout->SetOrientation(views::LayoutOrientation::kVertical); + layout->SetMainAxisAlignment(views::LayoutAlignment::kCenter); + layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch); + + if (!effect->label_text().empty()) { + AddChildView(std::make_unique<views::Label>(effect->label_text())); + } + + // Add a button for each state. + for (int i = 0; i < effect->GetNumStates(); ++i) { + const VcEffectState* state = effect->GetState(/*index=*/i); + std::unique_ptr<views::RadioButton> state_button = + std::make_unique<views::RadioButton>(state->label_text(), + /*group_id=*/effect->id()); + state_button->SetCallback(state->button_callback()); + + // See comments above `kSetValueButton*` in `BubbleViewID` for details + // on how the IDs of these buttons are set. + state_button->SetID(i <= BubbleViewID::kSetValueButtonMax - + BubbleViewID::kSetValueButtonMin + ? BubbleViewID::kSetValueButtonMin + i + : BubbleViewID::kSetValueButtonMax); + + AddChildView(std::move(state_button)); + } + + SetBorder(views::CreateEmptyBorder(gfx::Insets::VH(10, 10))); + SetBackground(views::CreateRoundedRectBackground(gfx::kGoogleGreen800, + /*radius=*/10)); + } + + ValueButtonContainer(const ValueButtonContainer&) = delete; + ValueButtonContainer& operator=(const ValueButtonContainer&) = delete; + + ~ValueButtonContainer() override = default; +}; + +} // namespace + +SetValueEffectsView::SetValueEffectsView( + VideoConferenceTrayController* controller) { + SetID(BubbleViewID::kSetValueEffectsView); + + views::FlexLayout* layout = + SetLayoutManager(std::make_unique<views::FlexLayout>()); + layout->SetOrientation(views::LayoutOrientation::kVertical); + layout->SetMainAxisAlignment(views::LayoutAlignment::kCenter); + layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch); + + if (controller->effects_manager().HasSetValueEffects()) { + for (auto* effect : controller->effects_manager().GetSetValueEffects()) { + AddChildView(std::make_unique<ValueButtonContainer>(effect)); + } + } +} + +} // namespace ash::video_conference \ No newline at end of file
diff --git a/ash/system/video_conference/bubble/set_value_effects_view.h b/ash/system/video_conference/bubble/set_value_effects_view.h new file mode 100644 index 0000000..f27a0d3 --- /dev/null +++ b/ash/system/video_conference/bubble/set_value_effects_view.h
@@ -0,0 +1,34 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_SYSTEM_VIDEO_CONFERENCE_BUBBLE_SET_VALUE_EFFECTS_VIEW_H_ +#define ASH_SYSTEM_VIDEO_CONFERENCE_BUBBLE_SET_VALUE_EFFECTS_VIEW_H_ + +#include "ui/views/view.h" + +namespace ash { + +class VideoConferenceTrayController; + +namespace video_conference { + +// The set-value effects view, that resides in the video conference bubble. It +// functions as a "factory" that constructs and hosts selector-views for effects +// that are set to one of several integral values. The selector-views host the +// individual effects and are registered with the +// `VideoConferenceTrayEffectsManager`, which is in turn owned by the passed-in +// controller. +class SetValueEffectsView : public views::View { + public: + explicit SetValueEffectsView(VideoConferenceTrayController* controller); + SetValueEffectsView(const SetValueEffectsView&) = delete; + SetValueEffectsView& operator=(const SetValueEffectsView&) = delete; + ~SetValueEffectsView() override = default; +}; + +} // namespace video_conference + +} // namespace ash + +#endif // ASH_SYSTEM_VIDEO_CONFERENCE_BUBBLE_SET_VALUE_EFFECTS_VIEW_H_
diff --git a/ash/system/video_conference/effects/fake_video_conference_effects.cc b/ash/system/video_conference/effects/fake_video_conference_effects.cc index 78f203b..683399f8 100644 --- a/ash/system/video_conference/effects/fake_video_conference_effects.cc +++ b/ash/system/video_conference/effects/fake_video_conference_effects.cc
@@ -74,7 +74,7 @@ : SimpleToggleEffect( /*label_text=*/u"Greenhouse") {} -// Delegate that hosts a set-value effect. +// Delegates that host a set-value effect. ShaggyFurEffect::ShaggyFurEffect() { std::unique_ptr<VcHostedEffect> effect = @@ -116,8 +116,9 @@ AddEffect(std::move(effect)); // Initialize click counts. - for (int i = 0; i < static_cast<int>(FurShagginess::kMaxNumValues); ++i) + for (int i = 0; i < static_cast<int>(FurShagginess::kMaxNumValues); ++i) { num_activations_for_testing_.push_back(0); + } } ShaggyFurEffect::~ShaggyFurEffect() = default; @@ -136,4 +137,77 @@ return num_activations_for_testing_[value]; } +SuperCutnessEffect::SuperCutnessEffect() { + std::unique_ptr<VcHostedEffect> effect = + std::make_unique<VcHostedEffect>(VcEffectType::kSetValue); + std::unique_ptr<VcEffectState> ugly_dog_state = + std::make_unique<VcEffectState>( + /*icon=*/nullptr, + /*label_text=*/u"Ugly Dog", + /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, + /*button_callback=*/ + base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, + base::Unretained(this), + /*effect_id=*/0, + /*value=*/static_cast<int>(HowCute::kUglyDog))); + std::unique_ptr<VcEffectState> teddy_bear_state = + std::make_unique<VcEffectState>( + /*icon=*/nullptr, + /*label_text=*/u"Teddy Bear", + /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, + /*button_callback=*/ + base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, + base::Unretained(this), + /*effect_id=*/0, + /*value=*/static_cast<int>(HowCute::kTeddyBear))); + std::unique_ptr<VcEffectState> zara_state = std::make_unique<VcEffectState>( + /*icon=*/nullptr, + /*label_text=*/u"Zara", + /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, + /*button_callback=*/ + base::BindRepeating(&SuperCutnessEffect::OnEffectControlActivated, + base::Unretained(this), + /*effect_id=*/0, + /*value=*/static_cast<int>(HowCute::kZara))); + std::unique_ptr<VcEffectState> inscrutable_state = + std::make_unique<VcEffectState>( + /*icon=*/nullptr, + /*label_text=*/u"Inscrutable", + /*accessible_name_id=*/IDS_PRIVACY_NOTIFICATION_TITLE_CAMERA, + /*button_callback=*/ + base::BindRepeating( + &SuperCutnessEffect::OnEffectControlActivated, + base::Unretained(this), + /*effect_id=*/0, + /*value=*/static_cast<int>(HowCute::kInscrutable))); + effect->AddState(std::move(ugly_dog_state)); + effect->AddState(std::move(teddy_bear_state)); + effect->AddState(std::move(zara_state)); + effect->AddState(std::move(inscrutable_state)); + effect->set_label_text(u"Super Cuteness"); + effect->set_id(200); + AddEffect(std::move(effect)); + + // Initialize click counts. + for (int i = 0; i < static_cast<int>(HowCute::kMaxNumValues); ++i) { + num_activations_for_testing_.push_back(0); + } +} + +SuperCutnessEffect::~SuperCutnessEffect() = default; + +int SuperCutnessEffect::GetEffectState(int effect_id) { + return static_cast<int>(HowCute::kTeddyBear); +} + +void SuperCutnessEffect::OnEffectControlActivated(int effect_id, int value) { + DCHECK(value >= 0 && value < static_cast<int>(HowCute::kMaxNumValues)); + ++num_activations_for_testing_[value]; +} + +int SuperCutnessEffect::GetNumActivationsForTesting(int value) { + DCHECK(value >= 0 && value < static_cast<int>(HowCute::kMaxNumValues)); + return num_activations_for_testing_[value]; +} + } // namespace ash::fake_video_conference
diff --git a/ash/system/video_conference/effects/fake_video_conference_effects.h b/ash/system/video_conference/effects/fake_video_conference_effects.h index 99c8048..75672b05 100644 --- a/ash/system/video_conference/effects/fake_video_conference_effects.h +++ b/ash/system/video_conference/effects/fake_video_conference_effects.h
@@ -150,6 +150,37 @@ std::vector<int> num_activations_for_testing_; }; +class ASH_EXPORT SuperCutnessEffect : public VcEffectsDelegate { + public: + enum class HowCute { + kUglyDog = 0, + kTeddyBear = 1, + kZara = 2, + kInscrutable = 3, + kMaxNumValues = 4, + }; + + SuperCutnessEffect(); + + SuperCutnessEffect(const SuperCutnessEffect&) = delete; + SuperCutnessEffect& operator=(const SuperCutnessEffect&) = delete; + + ~SuperCutnessEffect() override; + + // VcEffectsDelegate: + int GetEffectState(int effect_id) override; + void OnEffectControlActivated(int effect_id, int value) override; + + // Returns the number of times the button/state for `value` has been + // activated. + int GetNumActivationsForTesting(int value); + + private: + // Number of times each value has been clicked, one count for each value in + // `HowCute`. + std::vector<int> num_activations_for_testing_; +}; + } // namespace ash::fake_video_conference #endif // ASH_SYSTEM_VIDEO_CONFERENCE_EFFECTS_FAKE_VIDEO_CONFERENCE_EFFECTS_H_
diff --git a/ash/webui/common/resources/network/network_proxy.d.ts b/ash/webui/common/resources/network/network_proxy.d.ts index 983fe59..1fc89dd 100644 --- a/ash/webui/common/resources/network/network_proxy.d.ts +++ b/ash/webui/common/resources/network/network_proxy.d.ts
@@ -2,4 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -export {}; +import {LegacyElementMixin} from 'chrome://resources/polymer/v3_0/polymer/lib/legacy/legacy-element-mixin.js'; +interface NetworkProxyElement extends LegacyElementMixin, HTMLElement { + reset(): void; +} +export {NetworkProxyElement};
diff --git a/ash/webui/shortcut_customization_ui/backend/BUILD.gn b/ash/webui/shortcut_customization_ui/backend/BUILD.gn index 0712361..02cbe730 100644 --- a/ash/webui/shortcut_customization_ui/backend/BUILD.gn +++ b/ash/webui/shortcut_customization_ui/backend/BUILD.gn
@@ -17,6 +17,7 @@ "//ash/public/cpp", "//ash/public/mojom", "//ash/webui/shortcut_customization_ui/mojom", + "//chromeos/strings", "//components/prefs:prefs", "//ui/base/ime/ash", "//ui/chromeos/events",
diff --git a/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc b/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc index 7868183..9b1dbaf3 100644 --- a/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc +++ b/ash/webui/shortcut_customization_ui/backend/accelerator_configuration_provider.cc
@@ -19,6 +19,7 @@ #include "base/notreached.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" +#include "chromeos/strings/grit/chromeos_strings.h" #include "components/prefs/pref_service.h" #include "mojo/public/cpp/bindings/clone_traits.h" #include "mojo/public/cpp/bindings/pending_receiver.h" @@ -59,6 +60,16 @@ {ui::KeyboardCode::VKEY_DICTATE, u"ToggleDictation"}, {ui::KeyboardCode::VKEY_WLAN, u"ToggleWifi"}, {ui::KeyboardCode::VKEY_EMOJI_PICKER, u"EmojiPicker"}, + {ui::KeyboardCode::VKEY_SPACE, + l10n_util::GetStringUTF16(IDS_SHORTCUT_CUSTOMIZATION_KEY_SPACE)}, + {ui::KeyboardCode::VKEY_TAB, + l10n_util::GetStringUTF16(IDS_SHORTCUT_CUSTOMIZATION_KEY_TAB)}, + {ui::KeyboardCode::VKEY_ESCAPE, + l10n_util::GetStringUTF16(IDS_SHORTCUT_CUSTOMIZATION_KEY_ESCAPE)}, + {ui::KeyboardCode::VKEY_RETURN, + l10n_util::GetStringUTF16(IDS_SHORTCUT_CUSTOMIZATION_KEY_RETURN)}, + {ui::KeyboardCode::VKEY_BACK, + l10n_util::GetStringUTF16(IDS_SHORTCUT_CUSTOMIZATION_KEY_BACKSPACE)}, })); return *key_display_map; } @@ -66,7 +77,7 @@ mojom::DefaultAcceleratorPropertiesPtr CreateDefaultAcceleratorProps( const ui::Accelerator& accelerator) { return mojom::DefaultAcceleratorProperties::New( - accelerator, KeycodeToKeyString(accelerator.key_code())); + accelerator, shortcut_ui::GetKeyDisplay(accelerator.key_code())); } std::u16string LookupAcceleratorDescription(mojom::AcceleratorSource source, @@ -429,20 +440,15 @@ } std::u16string GetKeyDisplay(ui::KeyboardCode key_code) { - // TODO(cambickel): All key_displays should be lowercase - const std::u16string key_display = KeycodeToKeyString(key_code); - if (key_display.empty()) { - // If key_display is empty and there's an entry for this key_code in our - // map, return that entry's value. - auto it = GetKeyDisplayMap().find(key_code); - if (it != GetKeyDisplayMap().end()) { - return it->second; - } - } else if (key_display == u" ") { - // If key_display is a space character, instead return the string "Space". - return l10n_util::GetStringUTF16(IDS_KSV_KEY_SPACE); + // If there's an entry for this key_code in our + // map, return that entry's value. + auto it = GetKeyDisplayMap().find(key_code); + if (it != GetKeyDisplayMap().end()) { + return it->second; + } else { + // Otherwise, get the key_display from a util function. + return KeycodeToKeyString(key_code); } - return key_display; } } // namespace shortcut_ui
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 9d3494a..018c2b5 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
@@ -103,7 +103,7 @@ expected_accelerator == actual_info->layout_properties->get_default_accelerator()->accelerator; const bool key_display_equals = - KeycodeToKeyString(expected_accelerator.key_code()) == + shortcut_ui::GetKeyDisplay(expected_accelerator.key_code()) == actual_info->layout_properties->get_default_accelerator()->key_display; return accelerator_equals && key_display_equals; } @@ -598,11 +598,14 @@ TEST_F(AcceleratorConfigurationProviderTest, TestGetKeyDisplay) { EXPECT_EQ(u"c", GetKeyDisplay(ui::VKEY_C)); - EXPECT_EQ(u"Tab", GetKeyDisplay(ui::VKEY_TAB)); EXPECT_EQ(u"MicrophoneMuteToggle", GetKeyDisplay(ui::VKEY_MICROPHONE_MUTE_TOGGLE)); EXPECT_EQ(u"ToggleWifi", GetKeyDisplay(ui::VKEY_WLAN)); - EXPECT_EQ(u"Space", GetKeyDisplay(ui::VKEY_SPACE)); + EXPECT_EQ(u"tab", GetKeyDisplay(ui::VKEY_TAB)); + EXPECT_EQ(u"esc", GetKeyDisplay(ui::VKEY_ESCAPE)); + EXPECT_EQ(u"backspace", GetKeyDisplay(ui::VKEY_BACK)); + EXPECT_EQ(u"enter", GetKeyDisplay(ui::VKEY_RETURN)); + EXPECT_EQ(u"space", GetKeyDisplay(ui::VKEY_SPACE)); } TEST_F(AcceleratorConfigurationProviderTest, TextAcceleratorParsing) {
diff --git a/base/android/jni_generator/OWNERS b/base/android/jni_generator/OWNERS index 410f01e..0afb537 100644 --- a/base/android/jni_generator/OWNERS +++ b/base/android/jni_generator/OWNERS
@@ -1,2 +1,3 @@ agrieve@chromium.org mthiesse@chromium.org +smaier@chromium.org
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc index 4e56f7d..8f70dd39 100644 --- a/base/files/file_util_win.cc +++ b/base/files/file_util_win.cc
@@ -1014,44 +1014,18 @@ return false; } -namespace { - -// ::PrefetchVirtualMemory() is only available on Windows 8 and above. Chrome -// supports Windows 7, so we need to check for the function's presence -// dynamically. -using PrefetchVirtualMemoryPtr = decltype(&::PrefetchVirtualMemory); - -// Returns null if ::PrefetchVirtualMemory() is not available. -PrefetchVirtualMemoryPtr GetPrefetchVirtualMemoryPtr() { - HMODULE kernel32_dll = ::GetModuleHandleA("kernel32.dll"); - return reinterpret_cast<PrefetchVirtualMemoryPtr>( - GetProcAddress(kernel32_dll, "PrefetchVirtualMemory")); -} - -} // namespace - bool PreReadFile(const FilePath& file_path, bool is_executable, int64_t max_bytes) { DCHECK_GE(max_bytes, 0); - // On Win8 and higher use ::PrefetchVirtualMemory(). This is better than a - // simple data file read, more from a RAM perspective than CPU. This is - // because reading the file as data results in double mapping to - // Image/executable pages for all pages of code executed. - static PrefetchVirtualMemoryPtr prefetch_virtual_memory = - GetPrefetchVirtualMemoryPtr(); - - if (prefetch_virtual_memory == nullptr) - return internal::PreReadFileSlow(file_path, max_bytes); - if (max_bytes == 0) { - // PrefetchVirtualMemory() fails when asked to read zero bytes. + // ::PrefetchVirtualMemory() fails when asked to read zero bytes. // base::MemoryMappedFile::Initialize() fails on an empty file. return true; } - // PrefetchVirtualMemory() fails if the file is opened with write access. + // ::PrefetchVirtualMemory() fails if the file is opened with write access. MemoryMappedFile::Access access = is_executable ? MemoryMappedFile::READ_CODE_IMAGE : MemoryMappedFile::READ_ONLY; @@ -1063,7 +1037,11 @@ std::min(base::saturated_cast<::SIZE_T>(max_bytes), base::saturated_cast<::SIZE_T>(mapped_file.length())); ::_WIN32_MEMORY_RANGE_ENTRY address_range = {mapped_file.data(), length}; - if (!prefetch_virtual_memory(::GetCurrentProcess(), + // Use ::PrefetchVirtualMemory(). This is better than a + // simple data file read, more from a RAM perspective than CPU. This is + // because reading the file as data results in double mapping to + // Image/executable pages for all pages of code executed. + if (!::PrefetchVirtualMemory(::GetCurrentProcess(), /*NumberOfEntries=*/1, &address_range, /*Flags=*/0)) { return internal::PreReadFileSlow(file_path, max_bytes);
diff --git a/base/test/gtest_xml_unittest_result_printer.cc b/base/test/gtest_xml_unittest_result_printer.cc index dbe37d7..2d6b9f30 100644 --- a/base/test/gtest_xml_unittest_result_printer.cc +++ b/base/test/gtest_xml_unittest_result_printer.cc
@@ -48,7 +48,7 @@ if (output_file_ && !open_failed_) { fprintf(output_file_.get(), "</testsuites>\n"); fflush(output_file_); - CloseFile(output_file_); + CloseFile(output_file_.ExtractAsDangling()); } }
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h index 37bbac58..686b0af 100644 --- a/base/trace_event/builtin_categories.h +++ b/base/trace_event/builtin_categories.h
@@ -180,6 +180,7 @@ X("wakeup.flow") \ X("wayland") \ X("webaudio") \ + X("webengine.fidl") \ X("weblayer") \ X("WebCore") \ X("webrtc") \
diff --git a/build/config/compiler/pgo/BUILD.gn b/build/config/compiler/pgo/BUILD.gn index 900ae06..1ebe80c 100644 --- a/build/config/compiler/pgo/BUILD.gn +++ b/build/config/compiler/pgo/BUILD.gn
@@ -57,12 +57,6 @@ # Temporarily use mac-arm profile until Android native PGO support works. # TODO(crbug.com/1308749): fix this. _pgo_target = "mac-arm" - } else if (is_fuchsia) { - if (target_cpu == "arm64") { - _pgo_target = "mac-arm" - } else { - _pgo_target = "mac" - } } if (_pgo_target == "win64") { @@ -72,7 +66,7 @@ } else if (_pgo_target == "mac-arm") { inputs = [ "//chrome/build/mac-arm.pgo.txt" ] } else if (_pgo_target == "mac") { - inputs = [ "//chrome/build/mac.pgo.txt" ] + inputs = [ "//chrome/build/mac-arm.pgo.txt" ] } else if (_pgo_target == "linux") { inputs = [ "//chrome/build/linux.pgo.txt" ] }
diff --git a/build/config/compiler/pgo/pgo.gni b/build/config/compiler/pgo/pgo.gni index 9e9a0c5..eac98c6 100644 --- a/build/config/compiler/pgo/pgo.gni +++ b/build/config/compiler/pgo/pgo.gni
@@ -24,7 +24,7 @@ # TODO(crbug.com/1336055): Update this now-outdated condition with regard # to chromecast and determine whether chromeos_is_browser_only is # obsolete. - (is_high_end_android || is_win || is_mac || is_fuchsia || + (is_high_end_android || is_win || is_mac || (is_linux && !is_castos && !chromeos_is_browser_only))) { chrome_pgo_phase = 2 }
diff --git a/build/config/fuchsia/test/minimum.shard.test-cml b/build/config/fuchsia/test/minimum.shard.test-cml index 3f3784a..e0e36d7 100644 --- a/build/config/fuchsia/test/minimum.shard.test-cml +++ b/build/config/fuchsia/test/minimum.shard.test-cml
@@ -67,6 +67,12 @@ "fuchsia.sys.Loader", ], }, + { + protocol: [ + "fuchsia.tracing.perfetto.ProducerConnector", + ], + availability: "optional", + }, ], facets: { "fuchsia.test": {
diff --git a/build/fuchsia/test/compatible_utils.py b/build/fuchsia/test/compatible_utils.py index 39b4664..0399fd4 100644 --- a/build/fuchsia/test/compatible_utils.py +++ b/build/fuchsia/test/compatible_utils.py
@@ -36,8 +36,8 @@ When running unattended, confirmation prompts and the like are suppressed. """ - # Chromium tests only for the presence of the variable, so match that here. - return 'CHROME_HEADLESS' in os.environ + # TODO(crbug/1401387): Change to mixin based approach. + return 'SWARMING_SERVER' in os.environ def get_host_arch() -> str:
diff --git a/build/fuchsia/test/compatible_utils_unittests.py b/build/fuchsia/test/compatible_utils_unittests.py index 88c570f..109fb16 100755 --- a/build/fuchsia/test/compatible_utils_unittests.py +++ b/build/fuchsia/test/compatible_utils_unittests.py
@@ -19,7 +19,7 @@ def test_running_unattended_returns_true_if_headless_set(self) -> None: """Test |running_unattended| returns True if CHROME_HEADLESS is set.""" - with mock.patch('os.environ', {'CHROME_HEADLESS': 0}): + with mock.patch('os.environ', {'SWARMING_SERVER': 0}): self.assertTrue(compatible_utils.running_unattended()) with mock.patch('os.environ', {'FOO_HEADLESS': 0}):
diff --git a/build/fuchsia/test/flash_device_unittests.py b/build/fuchsia/test/flash_device_unittests.py index fb7e126..b6e881b 100755 --- a/build/fuchsia/test/flash_device_unittests.py +++ b/build/fuchsia/test/flash_device_unittests.py
@@ -31,15 +31,19 @@ self._sdk_hash_patcher = mock.patch('flash_device.get_sdk_hash', return_value=(_TEST_PRODUCT, _TEST_VERSION)) + self._swarming_patcher = mock.patch('flash_device.running_unattended', + return_value=False) self._check_patcher = mock.patch('flash_device.check_ssh_config_file') self._config_mock = self._config_patcher.start() self._ffx_mock = self._ffx_patcher.start() self._sdk_hash_mock = self._sdk_hash_patcher.start() self._check_patcher_mock = self._check_patcher.start() + self._swarming_mock = self._swarming_patcher.start() self.addCleanup(self._config_mock.stop) self.addCleanup(self._ffx_mock.stop) self.addCleanup(self._sdk_hash_mock.stop) self.addCleanup(self._check_patcher_mock.stop) + self.addCleanup(self._swarming_mock.stop) def test_update_required_on_ignore_returns_immediately(self) -> None: """Test |os_check|='ignore' skips all checks.""" @@ -118,10 +122,9 @@ """Test update when |os_check| is 'check' and system info does not match.""" + self._swarming_mock.return_value = True with mock.patch('os.path.exists', return_value=True), \ mock.patch('flash_device._add_exec_to_flash_binaries'), \ - mock.patch('flash_device.running_unattended', - return_value=True), \ mock.patch('flash_device.subprocess.run'): self._ffx_mock.return_value.stdout = \ '[{"title": "Build", "child": [{"value": "wrong.version"}, ' \ @@ -222,10 +225,11 @@ def test_update_raises_error_if_unattended_with_no_target(self) -> None: """Test update calls pave if specified.""" + + self._swarming_mock.return_value = True with mock.patch('time.sleep'), \ mock.patch('flash_device.pave'), \ - mock.patch('os.path.exists', return_value=True), \ - mock.patch('flash_device.running_unattended', return_value=True): + mock.patch('os.path.exists', return_value=True): self.assertRaises(AssertionError, flash_device.update, _TEST_IMAGE_DIR, @@ -236,11 +240,10 @@ def test_update_on_swarming(self) -> None: """Test update on swarming bots.""" + self._swarming_mock.return_value = True with mock.patch('time.sleep'), \ mock.patch('os.path.exists', return_value=True), \ mock.patch('flash_device._add_exec_to_flash_binaries'), \ - mock.patch('flash_device.running_unattended', - return_value = True), \ mock.patch('subprocess.run'): flash_device.update(_TEST_IMAGE_DIR, 'update',
diff --git a/build/fuchsia/test/run_test.py b/build/fuchsia/test/run_test.py index 7979024..f7cfe7bf 100755 --- a/build/fuchsia/test/run_test.py +++ b/build/fuchsia/test/run_test.py
@@ -78,8 +78,8 @@ if running_unattended(): set_ffx_isolate_dir( stack.enter_context(tempfile.TemporaryDirectory())) - stack.enter_context( - ScopedFfxConfig('repository.server.listen', '"[::]:0"')) + stack.enter_context( + ScopedFfxConfig('repository.server.listen', '"[::]:0"')) log_manager = stack.enter_context(LogManager(runner_args.logs_dir)) if runner_args.device: update(runner_args.system_image_dir, runner_args.os_check,
diff --git a/build/fuchsia/test/start_emulator.py b/build/fuchsia/test/start_emulator.py index 9c96d66..4cbb5773 100755 --- a/build/fuchsia/test/start_emulator.py +++ b/build/fuchsia/test/start_emulator.py
@@ -53,11 +53,17 @@ def main(): """Stand-alone function for starting an emulator.""" + + logging.basicConfig(level=logging.INFO) parser = argparse.ArgumentParser() register_emulator_args(parser, True) register_log_args(parser) args = parser.parse_args() - with create_emulator_from_args(args): + with create_emulator_from_args(args) as target_id: + logging.info( + 'Emulator successfully started. You can now run Chrome ' + 'Fuchsia tests with --target-id=%s to target this emulator.', + target_id) try: while True: time.sleep(10000)
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni index 249ad4f2..8fb1d584 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 = "2fc3d704672fbd3e85fad8492d39e02d49412891" + libcxx_revision = "2948540a20cbb5b2192119f791b04dd62ca7af1c" }
diff --git a/cc/paint/oop_pixeltest.cc b/cc/paint/oop_pixeltest.cc index bf212821b..dcb668c 100644 --- a/cc/paint/oop_pixeltest.cc +++ b/cc/paint/oop_pixeltest.cc
@@ -112,7 +112,7 @@ raster_context_provider_ = base::MakeRefCounted<viz::TestInProcessContextProvider>( - viz::TestContextType::kGpuRaster, /*support_locking=*/true, + viz::TestContextType::kGpuRaster, /*support_locking=*/false, &gr_shader_cache_, &activity_flags_); gpu::ContextResult result = raster_context_provider_->BindToCurrentSequence(); @@ -162,10 +162,6 @@ SkBitmap Raster(scoped_refptr<DisplayItemList> display_item_list, const RasterOptions& options) { - GURL url("https://example.com/foo"); - viz::TestInProcessContextProvider::ScopedRasterContextLock lock( - raster_context_provider_.get(), url.possibly_invalid_spec().c_str()); - absl::optional<PlaybackImageProvider::Settings> settings; settings.emplace(PlaybackImageProvider::Settings()); settings->raster_mode = options.image_provider_raster_mode;
diff --git a/cc/paint/transfer_cache_unittest.cc b/cc/paint/transfer_cache_unittest.cc index fea67a7..1b33fab 100644 --- a/cc/paint/transfer_cache_unittest.cc +++ b/cc/paint/transfer_cache_unittest.cc
@@ -10,6 +10,7 @@ #include "cc/paint/image_transfer_cache_entry.h" #include "cc/paint/raw_memory_transfer_cache_entry.h" #include "cc/paint/transfer_cache_entry.h" +#include "components/viz/test/test_gpu_memory_buffer_manager.h" #include "components/viz/test/test_gpu_service_holder.h" #include "components/viz/test/test_in_process_context_provider.h" #include "gpu/command_buffer/client/client_transfer_cache.h"
diff --git a/cc/test/layer_tree_pixel_test.cc b/cc/test/layer_tree_pixel_test.cc index 547f72a9..cd0db942 100644 --- a/cc/test/layer_tree_pixel_test.cc +++ b/cc/test/layer_tree_pixel_test.cc
@@ -24,6 +24,7 @@ #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_result.h" +#include "components/viz/common/gpu/raster_context_provider.h" #include "components/viz/service/display/software_output_device.h" #include "components/viz/service/display_embedder/skia_output_surface_dependency_impl.h" #include "components/viz/service/display_embedder/skia_output_surface_impl.h" @@ -122,6 +123,8 @@ if (!use_software_renderer()) { viz::RasterContextProvider* worker_context_provider = host_impl->layer_tree_frame_sink()->worker_context_provider(); + viz::RasterContextProvider::ScopedRasterContextLock lock( + worker_context_provider); EXPECT_EQ(use_accelerated_raster(), worker_context_provider->ContextCapabilities().gpu_rasterization); EXPECT_EQ(
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java index 44228ba1..49e3d516 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java
@@ -18,7 +18,6 @@ import static org.chromium.chrome.browser.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabTestHelper.isKeyboardAccessoryTabLayout; import android.app.Activity; -import android.os.Build.VERSION_CODES; import android.view.View; import androidx.annotation.IntDef; @@ -38,7 +37,6 @@ import org.chromium.base.test.util.CallbackHelper; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.ChromeWindow; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -204,11 +202,7 @@ @Test @MediumTest @ParameterAnnotations.UseMethodParameter(FeatureParamProvider.class) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testSelectSuggestionHidesKeyboardAccessory(@EnabledFeature int enabledFeature) + public void testSelectSuggestionHidesKeyboardAccessory(@EnabledFeature int enabledFeature) throws ExecutionException, TimeoutException { loadTestPage(FakeKeyboard::new, enabledFeature); mHelper.clickNodeAndShowKeyboard("NAME_FIRST", 1); @@ -236,8 +230,6 @@ @Test @SmallTest // clang-format off - @DisableIf.Build(hardware_is = "bullhead", sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, - sdk_is_less_than = VERSION_CODES.N, message = "https://crbug.com/1216008") public void testPressingBackButtonHidesAccessoryWithAutofillSuggestions() throws TimeoutException, ExecutionException { // clang-format on @@ -265,8 +257,6 @@ @Test @MediumTest // clang-format off - @DisableIf.Build(hardware_is = "bullhead", sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, - sdk_is_less_than = VERSION_CODES.N, message = "https://crbug.com/1216008") public void testSheetHasMinimumSizeWhenTriggeredBySuggestion() throws TimeoutException { // clang-format on MultiWindowUtils.getInstance().setIsInMultiWindowModeForTesting(true);
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java index 9e1147a..e46a04e 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java
@@ -27,7 +27,6 @@ import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabTestHelper.isKeyboardAccessoryTabLayout; -import android.os.Build.VERSION_CODES; import android.view.View; import android.view.ViewGroup; @@ -42,7 +41,6 @@ import org.chromium.base.task.PostTask; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CriteriaHelper; -import org.chromium.base.test.util.DisableIf; import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -109,11 +107,7 @@ @Test @SmallTest - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testKeyboardAccessoryDisappearsWithKeyboard() throws TimeoutException { + public void testKeyboardAccessoryDisappearsWithKeyboard() throws TimeoutException { mHelper.loadTestPage(false); // Focus the field to bring up the accessory. @@ -210,11 +204,7 @@ @Test @SmallTest @Features.DisableFeatures(ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testAccessoryHiddenAfterTappingAutoGenerationButton() throws TimeoutException { + public void testAccessoryHiddenAfterTappingAutoGenerationButton() throws TimeoutException { mHelper.loadTestPage(false); // Focus the field to bring up the accessory and add the generation button. @@ -258,11 +248,7 @@ @Test @SmallTest @Features.DisableFeatures({ChromeFeatureList.AUTOFILL_KEYBOARD_ACCESSORY}) - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testSelectingNonPasswordInputDismissesAccessory() throws TimeoutException { + public void testSelectingNonPasswordInputDismissesAccessory() throws TimeoutException { mHelper.loadTestPage(false); // Focus the password field to bring up the accessory. @@ -350,11 +336,7 @@ @Test @SmallTest - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testPressingBackButtonHidesAccessorySheet() throws TimeoutException { + public void testPressingBackButtonHidesAccessorySheet() throws TimeoutException { mHelper.loadTestPage(false); // Focus the field to bring up the accessory. @@ -420,11 +402,7 @@ @Test @SmallTest - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testInfobarStaysHiddenWhenOpeningSheet() throws TimeoutException { + public void testInfobarStaysHiddenWhenOpeningSheet() throws TimeoutException { mHelper.loadTestPage(false); // Initialize and wait for the infobar. @@ -473,11 +451,7 @@ @Test @SmallTest - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testMovesUpSnackbar() throws TimeoutException { + public void testMovesUpSnackbar() throws TimeoutException { final String kSnackbarText = "snackbar"; mHelper.loadTestPage(false); @@ -516,11 +490,7 @@ @Test @SmallTest - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testInfobarReopensOnPressingBack() throws TimeoutException { + public void testInfobarReopensOnPressingBack() throws TimeoutException { mHelper.loadTestPage(false); // Initialize and wait for the infobar.
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java index 7281b4a..4dac0fd3a 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessoryIntegrationTest.java
@@ -21,8 +21,6 @@ import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.keyboard_accessory.tab_layout_component.KeyboardAccessoryTabTestHelper.isKeyboardAccessoryTabLayout; -import android.os.Build.VERSION_CODES; - import androidx.test.filters.SmallTest; import org.junit.After; @@ -76,11 +74,7 @@ @Test @SmallTest - @DisableIf. - Build(sdk_is_greater_than = VERSION_CODES.LOLLIPOP_MR1, sdk_is_less_than = VERSION_CODES.N, - message = "Flaky on Marshmallow https://crbug.com/1102302") - public void - testPasswordSheetDisplaysProvidedItems() throws TimeoutException { + public void testPasswordSheetDisplaysProvidedItems() throws TimeoutException { mHelper.loadTestPage(false); mHelper.cacheCredentials("mayapark@gmail.com", "SomeHiddenPassword");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java index ac15ef9..011c39f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
@@ -17,7 +17,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.task.PostTask; import org.chromium.chrome.R; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.gesturenav.HistoryNavigationCoordinator; import org.chromium.chrome.browser.tab.EmptyTabObserver; import org.chromium.chrome.browser.tab.Tab; @@ -196,8 +195,7 @@ if (type == OverscrollAction.PULL_TO_REFRESH) { if (mSwipeRefreshLayout == null) initSwipeRefreshLayout(mTab.getContext()); attachSwipeRefreshLayoutIfNecessary(); - return mSwipeRefreshLayout.start(ChromeFeatureList.isEnabled( - ChromeFeatureList.OPTIMIZE_LAYOUTS_FOR_PULL_REFRESH)); + return mSwipeRefreshLayout.start(); } else if (type == OverscrollAction.HISTORY_NAVIGATION) { if (mNavigationCoordinator != null) { mNavigationCoordinator.startGesture();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java index 7717297..1e5e2e50 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/bookmarks/BookmarkFolderSelectActivity.java
@@ -299,10 +299,13 @@ private void finishActivity(List<BookmarkId> bookmarks) { // This means BookmarkFolderSelectActivity was called for a result. if (getCallingActivity() != null) { - assert bookmarks.size() == 1; - Intent result = new Intent(); - result.putExtra(INTENT_BOOKMARK_MOVE_RESULT, bookmarks.get(0).toString()); - setResult(Activity.RESULT_OK, result); + if (bookmarks.size() == 1) { + Intent result = new Intent(); + result.putExtra(INTENT_BOOKMARK_MOVE_RESULT, bookmarks.get(0).toString()); + setResult(Activity.RESULT_OK, result); + } else { + setResult(Activity.RESULT_CANCELED); + } } finish(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListFeatures.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListFeatures.java index 0b141794..3ac971e3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListFeatures.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReadingListFeatures.java
@@ -47,9 +47,7 @@ /** Returns whether the root folder should be used as the default location. */ public static boolean shouldUseRootFolderAsDefaultForReadLater() { - return isReadingListEnabled() - && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( - ChromeFeatureList.READ_LATER, "use_root_bookmark_as_default", true); + return isReadingListEnabled(); } /** @@ -75,6 +73,7 @@ } private static boolean isReadingListEnabled() { + // This feature is enabled by default in native. return FeatureList.isInitialized() && ChromeFeatureList.isEnabled(ChromeFeatureList.READ_LATER) && ChromeFeatureList.getFieldTrialParamByFeatureAsInt(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java index 5510e31..b528231f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/LayerTitleCache.java
@@ -19,6 +19,7 @@ import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabFavicon; import org.chromium.chrome.browser.tabmodel.TabModelSelector; +import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities; import org.chromium.chrome.browser.ui.favicon.FaviconHelper; import org.chromium.chrome.browser.ui.favicon.FaviconHelper.DefaultFaviconHelper; import org.chromium.chrome.browser.ui.favicon.FaviconHelper.FaviconImageCallback; @@ -134,7 +135,23 @@ title.register(); } - title.set(titleBitmapFactory.getTitleBitmap(mContext, titleString), + // Boolean determines if tab title text needs to be bolded. + boolean isBold = false; + + // Bold title text for TSR detached. + if (TabUiFeatureUtilities.isTabStripDetachedEnabled()) { + if (mTabModelSelector == null) { + return titleString; + } + + // Get currently selected tab id. + int selectedTabId = mTabModelSelector.getCurrentTabId(); + + // Selected tab title text should be bolded. + isBold = tabId == selectedTabId; + } + + title.set(titleBitmapFactory.getTitleBitmap(mContext, titleString, isBold), titleBitmapFactory.getFaviconBitmap(originalFavicon), fetchFaviconFromHistory); if (mNativeLayerTitleCache != 0) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TitleBitmapFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TitleBitmapFactory.java index 48ff0c1..0a37dd5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TitleBitmapFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TitleBitmapFactory.java
@@ -10,6 +10,7 @@ import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Paint.FontMetrics; +import android.graphics.Typeface; import android.text.Layout; import android.text.TextPaint; import android.text.TextUtils; @@ -112,13 +113,20 @@ * * @param context Android's UI context. * @param title The title of the tab. + * @param isBold Whether the tab title text should be bolded. * @return The Bitmap with the title. */ - public Bitmap getTitleBitmap(Context context, String title) { + public Bitmap getTitleBitmap(Context context, String title, boolean isBold) { try { boolean drawText = !TextUtils.isEmpty(title); int textWidth = drawText ? (int) Math.ceil(Layout.getDesiredWidth(title, mTextPaint)) : 0; + + // Bold tab title text. + if (isBold) { + mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD)); + } + // Minimum 1 width bitmap to avoid createBitmap function's IllegalArgumentException, // when textWidth == 0. Bitmap b = Bitmap.createBitmap(Math.max(Math.min(mMaxWidth, textWidth), 1), mViewHeight, @@ -128,6 +136,10 @@ c.drawText(title, 0, Math.min(MAX_NUM_TITLE_CHAR, title.length()), 0, Math.round((mViewHeight - mTextHeight) / 2.0f + mTextYOffset), mTextPaint); } + + // Set bolded tab title text back to normal. + mTextPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)); + return b; } catch (OutOfMemoryError ex) { Log.e(TAG, "OutOfMemoryError while building title texture.");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProviderTest.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProviderTest.java index dbde53c..c837a88 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProviderTest.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/PriceTrackingActionProviderTest.java
@@ -10,8 +10,6 @@ import android.os.Handler; -import com.google.common.base.Optional; - import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -37,6 +35,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * Unit tests for {@link PriceTrackingActionProvider} @@ -83,7 +82,7 @@ private void setPriceTrackingBackendResult(boolean hasProductInfo) { ProductInfo testProductInfo = - new ProductInfo(null, null, 0, 0, null, 0, null, Optional.absent()); + new ProductInfo(null, null, 0, 0, null, 0, null, Optional.empty()); Mockito.doAnswer(invocation -> { ProductInfoCallback callback = invocation.getArgument(1); callback.onResult(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java index d6004c0..5185d8c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
@@ -191,7 +191,6 @@ @Override public void onTabModelSelected(TabModel newModel, TabModel oldModel) { mIsIncognito = newModel.isIncognito(); - // When opening a new Incognito Tab from a normal Tab (or vice versa), the // status bar color is updated. However, this update is triggered after the // animation, so we update here for the duration of the new Tab animation. @@ -331,7 +330,11 @@ public void setTabModelSelector(TabModelSelector tabModelSelector) { assert mTabModelSelector == null : "mTabModelSelector should only be set once."; mTabModelSelector = tabModelSelector; - if (mTabModelSelector != null) mTabModelSelector.addObserver(mTabModelSelectorObserver); + if (mTabModelSelector != null) { + mTabModelSelector.addObserver(mTabModelSelectorObserver); + mIsIncognito = mTabModelSelector.isIncognitoSelected(); + updateStatusBarColor(); + } } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditTest.java index 9565ed7..73f92848 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkEditTest.java
@@ -257,6 +257,28 @@ mBookmarkEditActivity.getFolderTextView().getText()); } + @Test + @MediumTest + @Feature({"Bookmark"}) + public void testChangeFolderWhenBookmarkRemoved() throws ExecutionException, TimeoutException { + TestThreadUtils.runOnUiThreadBlocking( + () -> mBookmarkEditActivity.getFolderTextView().performClick()); + waitForMoveFolderActivity(); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertTrue("Expected BookmarkFolderSelectActivity.", + ApplicationStatus.getLastTrackedFocusedActivity() + instanceof BookmarkFolderSelectActivity); + mBookmarkModel.deleteBookmark(mBookmarkId); + }); + // clang-format off + CriteriaHelper.pollUiThread(() -> + !(ApplicationStatus.getLastTrackedFocusedActivity() + instanceof BookmarkFolderSelectActivity), + "Timed out waiting for BookmarkFolderSelectActivity to close"); + // clang-format on + } + private BookmarkItem getBookmarkItem(BookmarkId bookmarkId) throws ExecutionException { return TestThreadUtils.runOnUiThreadBlocking( () -> mBookmarkModel.getBookmarkById(bookmarkId));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java index edcde3b..4aa714a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/bookmarks/BookmarkTest.java
@@ -250,6 +250,19 @@ () -> mManager.getDragStateDelegate().setA11yStateForTesting(false)); } + void openRootFolder() { + TestThreadUtils.runOnUiThreadBlocking( + () -> mManager.openFolder(mBookmarkModel.getRootFolderId())); + RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); + } + + void openMobileBookmarks() { + openRootFolder(); + + onView(withText("Mobile bookmarks")).perform(click()); + InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + } + private boolean isItemPresentInBookmarkList(final String expectedTitle) { return TestThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() { @Override @@ -362,10 +375,11 @@ @Test @SmallTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testOpenBookmark() throws InterruptedException, ExecutionException { addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestPage); openBookmarkManager(); + openMobileBookmarks(); + Assert.assertTrue("Grid view does not contain added bookmark: ", isItemPresentInBookmarkList(TEST_PAGE_TITLE_GOOGLE)); final View title = getViewWithText(mItemsContainer, TEST_PAGE_TITLE_GOOGLE); @@ -398,9 +412,10 @@ @Test @SmallTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testopenBookmarkManager() throws InterruptedException { openBookmarkManager(); + openMobileBookmarks(); + BookmarkTestUtil.waitForBookmarkModelLoaded(); BookmarkDelegate delegate = getBookmarkManager(); @@ -689,13 +704,13 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testEndIconVisibilityInSearchMode() throws Exception { BookmarkId testId = addFolder(TEST_FOLDER_TITLE); addFolder(TEST_TITLE_A); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); View searchButton = mManager.getToolbarForTests().findViewById(R.id.search_menu_id); @@ -742,7 +757,6 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testSmallDrag_Up_BookmarksOnly() throws Exception { List<BookmarkId> initial = new ArrayList<>(); List<BookmarkId> expected = new ArrayList<>(); @@ -767,6 +781,7 @@ BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); // Callback occurs upon changes inside of the bookmark model. CallbackHelper modelReorderHelper = new CallbackHelper(); @@ -806,7 +821,6 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testSmallDrag_Down_FoldersOnly() throws Exception { List<BookmarkId> initial = new ArrayList<>(); List<BookmarkId> expected = new ArrayList<>(); @@ -832,6 +846,7 @@ BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); // Callback occurs upon changes inside of the bookmark model. CallbackHelper modelReorderHelper = new CallbackHelper(); @@ -872,7 +887,6 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testSmallDrag_Down_MixedFoldersAndBookmarks() throws Exception { List<BookmarkId> initial = new ArrayList<>(); List<BookmarkId> expected = new ArrayList<>(); @@ -895,6 +909,7 @@ BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); // Callback occurs upon changes inside of the bookmark model. CallbackHelper modelReorderHelper = new CallbackHelper(); @@ -934,12 +949,12 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testPromoDraggability() throws Exception { BookmarkId testId = addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); ViewHolder promo = mItemsContainer.findViewHolderForAdapterPosition(0); @@ -955,11 +970,11 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testPartnerFolderDraggability() throws Exception { BookmarkId testId = addFolderWithPartner(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); ViewHolder partner = mItemsContainer.findViewHolderForAdapterPosition(2); @@ -975,13 +990,13 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testUnselectedItemDraggability() throws Exception { BookmarkId aId = addBookmark("a", mTestUrlA); addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); ViewHolder test = mItemsContainer.findViewHolderForAdapterPosition(1); Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, @@ -1030,12 +1045,13 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testMoveUpMenuItem() throws Exception { addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestUrlA); addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); + openBookmarkManager(); + openMobileBookmarks(); View google = mItemsContainer.findViewHolderForAdapterPosition(2).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_PAGE_TITLE_GOOGLE, @@ -1057,12 +1073,12 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testMoveDownMenuItem() throws Exception { addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestUrlA); addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); View testFolder = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, @@ -1084,12 +1100,12 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testMoveDownGoneForBottomElement() throws Exception { addBookmarkWithPartner(TEST_PAGE_TITLE_GOOGLE, mTestUrlA); addFolderWithPartner(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); View google = mItemsContainer.findViewHolderForAdapterPosition(2).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_PAGE_TITLE_GOOGLE, @@ -1101,12 +1117,12 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testMoveUpGoneForTopElement() throws Exception { addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestUrlA); addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); View testFolder = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, @@ -1142,11 +1158,11 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testMoveButtonsGoneWithOneBookmark() throws Exception { addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); View testFolder = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, @@ -1241,11 +1257,11 @@ @Test @MediumTest @DisabledTest(message = "crbug.com/1369091") - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testShowInFolder_NoScroll() throws Exception { addFolder(TEST_FOLDER_TITLE); BookmarkPromoHeader.forcePromoStateForTests(SyncPromoState.PROMO_FOR_SYNC_TURNED_OFF_STATE); openBookmarkManager(); + openMobileBookmarks(); // Enter search mode. enterSearch(); @@ -1513,7 +1529,6 @@ @Test @MediumTest - @Features.EnableFeatures({ChromeFeatureList.READ_LATER + ":use_root_bookmark_as_default/false"}) public void testBookmarksDoesNotRecordLaunchMetrics() throws Throwable { Assert.assertEquals(1, RecordHistogram.getHistogramTotalCountForTesting( @@ -1521,6 +1536,7 @@ addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestPage); openBookmarkManager(); + pressBack(); BookmarkTestUtil.waitForTabbedActivity(); Assert.assertEquals(1,
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java index 9091160..52c1b88 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java
@@ -27,8 +27,6 @@ import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; -import com.google.common.base.Optional; - import org.hamcrest.Matchers; import org.junit.After; import org.junit.Assert; @@ -110,6 +108,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Optional; /** * Unit tests for {@link AppMenuPropertiesDelegateImpl}. @@ -858,7 +857,7 @@ .getBookmarksOfType(eq(PowerBookmarkType.SHOPPING)); Long clusterId = 1L; doReturn(new ShoppingService.ProductInfo( - "", new GURL(""), clusterId, 0, "", 0, "", Optional.absent())) + "", new GURL(""), clusterId, 0, "", 0, "", Optional.empty())) .when(mShoppingService) .getAvailableProductInfoForUrl(any()); PowerBookmarkMeta meta =
diff --git a/chrome/app/OWNERS b/chrome/app/OWNERS index 46750333..e542c3c 100644 --- a/chrome/app/OWNERS +++ b/chrome/app/OWNERS
@@ -40,8 +40,6 @@ per-file settings_google_chrome_strings.grdp=sauski@google.com per-file settings_strings.grdp=sauski@google.com -per-file supervised_user_error_page_strings.grdp=file://chrome/browser/supervised_user/OWNERS - per-file vr_strings.grdp=file://chrome/browser/vr/OWNERS per-file password_manager_ui_strings.grdp=file://chrome/browser/password_manager/OWNERS
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 19b282f..b1cc7c3c 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -346,11 +346,6 @@ <part file="vr_strings.grdp" /> </if> - <!-- Supervised user error page --> - <if expr="enable_supervised_users"> - <part file="supervised_user_error_page_strings.grdp" /> - </if> - <!-- TODO add all of your "string table" messages here. Remember to change nontranslateable parts of the messages into placeholders (using the <ph> element). You can also use the 'grit add' tool to help you identify
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index d7c913b..da4fa38 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3461,8 +3461,8 @@ ] deps += [ "//chrome/browser/supervised_user:jni_headers", - "//chrome/browser/supervised_user/supervised_user_error_page", - "//chrome/browser/supervised_user/supervised_user_features", + "//components/supervised_user/core/browser", + "//components/supervised_user/core/common", ] } @@ -5173,7 +5173,6 @@ "//chrome/browser/nearby_sharing/scheduling", "//chrome/browser/policy:onc", "//chrome/browser/resources/chromeos:app_icon_resources", - "//chrome/browser/supervised_user:supervised_user_unscaled_resources", "//chrome/browser/ui/ash/system_web_apps", "//chrome/browser/ui/quick_answers", "//chrome/browser/ui/webui/ash/add_supervision:mojo_bindings", @@ -7762,9 +7761,9 @@ } deps += [ "//chrome/browser/supervised_user/kids_chrome_management:proto", - "//chrome/browser/supervised_user/supervised_user_error_page", - "//chrome/browser/supervised_user/supervised_user_features", "//chrome/common:supervised_user_commands_mojom", + "//components/supervised_user/core/browser", + "//components/supervised_user/core/common", ] } if (enable_supervised_users && enable_extensions) { @@ -8072,7 +8071,6 @@ "//chrome/browser/resources/chromeos/set_time_dialog:html_wrapper_files", "//chrome/browser/resources/chromeos/smb_shares:web_components", "//chrome/browser/resources/chromeos/vm:web_components", - "//chrome/browser/supervised_user:supervised_user_unscaled_resources", "//chrome/browser/ui/webui/ash/add_supervision:mojo_bindings_js", "//chrome/browser/ui/webui/ash/crostini_installer:mojo_bindings_js", "//chrome/browser/ui/webui/ash/crostini_upgrader:mojo_bindings_js",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index dcd016c..41af8cc 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -328,7 +328,8 @@ "+components/subresource_filter/core/browser", "+components/subresource_filter/core/common", "+components/subresource_filter/core/mojom", - "+components/supervised_user_error_page", + "+components/supervised_user/core/browser", + "+components/supervised_user/core/common", "+components/sync", "+components/sync_bookmarks", "+components/sync_device_info",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index de5d0fbc..78261653 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -291,7 +291,7 @@ #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" // nogncheck +#include "components/supervised_user/core/common/features.h" // nogncheck #endif // ENABLE_SUPERVISED_USERS #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_ASH) @@ -6571,7 +6571,7 @@ #endif #if BUILDFLAG(IS_CHROMEOS_ASH) - {"cros-labs-float-window", flag_descriptions::kFloatWindow, + {"float-window", flag_descriptions::kFloatWindow, flag_descriptions::kFloatWindowDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::wm::features::kFloatWindow)}, {"cros-labs-overview-desk-navigation", @@ -9514,7 +9514,14 @@ flag_descriptions::kServiceWorkerBypassFetchHandlerForMainResourceName, flag_descriptions:: kServiceWorkerBypassFetchHandlerForMainResourceDescription, - kOsAll, FEATURE_VALUE_TYPE(features::kServiceWorkerBypassFetchHandler)} + kOsAll, FEATURE_VALUE_TYPE(features::kServiceWorkerBypassFetchHandler)}, + + {"autofill-remove-card-expiration-and-type-titles", + flag_descriptions::kAutofillRemoveCardExpirationAndTypeTitlesName, + flag_descriptions::kAutofillRemoveCardExpirationAndTypeTitlesDescription, + kOsDesktop, + FEATURE_VALUE_TYPE( + autofill::features::kAutofillRemoveCardExpirationAndTypeTitles)}, // 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 63b6e5d..37fef41 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_ash.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_ash.cc
@@ -26,12 +26,12 @@ #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/supervised_user/grit/supervised_user_unscaled_resources.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "components/account_id/account_id.h" #include "components/app_constants/constants.h" #include "components/app_restore/full_restore_save_handler.h" #include "components/app_restore/full_restore_utils.h" +#include "components/grit/components_resources.h" #include "components/services/app_service/app_service_mojom_impl.h" #include "components/services/app_service/public/cpp/app_capability_access_cache_wrapper.h" #include "components/services/app_service/public/cpp/app_registry_cache_wrapper.h"
diff --git a/chrome/browser/ash/BUILD.gn b/chrome/browser/ash/BUILD.gn index 99d19c28..a4ee918e 100644 --- a/chrome/browser/ash/BUILD.gn +++ b/chrome/browser/ash/BUILD.gn
@@ -3584,7 +3584,6 @@ "//chrome/browser/resources:component_extension_resources", "//chrome/browser/resources/chromeos:app_icon_resources", "//chrome/browser/resources/settings/chromeos:resources", - "//chrome/browser/supervised_user/supervised_user_features", "//chrome/browser/ui/ash/system_web_apps", "//chrome/browser/ui/webui/ash/cloud_upload:mojo_bindings", "//chrome/browser/ui/webui/ash/crostini_upgrader:mojo_bindings", @@ -3737,6 +3736,7 @@ "//components/spellcheck/browser", "//components/startup_metric_utils/browser", "//components/strings:components_strings", + "//components/supervised_user/core/common", "//components/sync/base", "//components/sync/chromeos", "//components/sync/engine",
diff --git a/chrome/browser/ash/app_list/app_list_client_impl.cc b/chrome/browser/ash/app_list/app_list_client_impl.cc index 23846cb..a7bc86c 100644 --- a/chrome/browser/ash/app_list/app_list_client_impl.cc +++ b/chrome/browser/ash/app_list/app_list_client_impl.cc
@@ -212,6 +212,7 @@ app_list::LaunchData launch_data; launch_data.id = result_id; launch_data.result_type = result->result_type(); + launch_data.category = result->category(); launch_data.launch_type = launch_type; launch_data.launched_from = launched_from; launch_data.suggestion_index = suggestion_index;
diff --git a/chrome/browser/ash/app_list/arc/arc_app_utils.cc b/chrome/browser/ash/app_list/arc/arc_app_utils.cc index c114ff5b5..778bdba 100644 --- a/chrome/browser/ash/app_list/arc/arc_app_utils.cc +++ b/chrome/browser/ash/app_list/arc/arc_app_utils.cc
@@ -32,6 +32,7 @@ #include "chrome/browser/ash/app_list/arc/intent.h" #include "chrome/browser/ash/app_list/search/ranking/launch_data.h" #include "chrome/browser/ash/app_list/search/search_controller.h" +#include "chrome/browser/ash/app_list/search/types.h" #include "chrome/browser/ash/arc/arc_migration_guide_notification.h" #include "chrome/browser/ash/arc/arc_util.h" #include "chrome/browser/ash/arc/boot_phase_monitor/arc_boot_phase_monitor_bridge.h" @@ -783,6 +784,7 @@ launch_data.id = ConstructArcAppShortcutUrl(arc_shelf_id.app_id(), shortcut_id), launch_data.result_type = ash::AppListSearchResultType::kArcAppShortcut; + launch_data.category = app_list::Category::kAppShortcuts; app_list_client_impl->search_controller()->Train(std::move(launch_data)); }
diff --git a/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc index 24dbe60..091bf7012 100644 --- a/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc +++ b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker.cc
@@ -41,7 +41,7 @@ ftrl_->Train(launch.id); break; case FtrlRanker::RankingKind::kCategories: - ftrl_->Train(CategoryToString(ResultTypeToCategory(launch.result_type))); + ftrl_->Train(CategoryToString(launch.category)); break; } }
diff --git a/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc index ae4cc3e..6cebeada 100644 --- a/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc +++ b/chrome/browser/ash/app_list/search/ranking/ftrl_ranker_unittest.cc
@@ -133,7 +133,7 @@ for (int i = 0; i < 10; ++i) { ranker.UpdateCategoryRanks(results, categories, ResultType::kInstalledApp); - ranker.Train(MakeLaunchData("a", ResultType::kInstalledApp)); + ranker.Train(MakeLaunchData("a", Category::kApps)); } // The weights of the FTRL optimizer should reflect that the good ranker is @@ -149,7 +149,7 @@ // particularly good job at predicting "c"'s category. for (int i = 0; i < 10; ++i) { ranker.UpdateResultRanks(results, ResultType::kInstalledApp); - ranker.Train(MakeLaunchData("c", ResultType::kFileSearch)); + ranker.Train(MakeLaunchData("c", Category::kFiles)); } // The weights of the 'bad' expert should have recovered.
diff --git a/chrome/browser/ash/app_list/search/ranking/launch_data.h b/chrome/browser/ash/app_list/search/ranking/launch_data.h index f375c73b..29a8b184 100644 --- a/chrome/browser/ash/app_list/search/ranking/launch_data.h +++ b/chrome/browser/ash/app_list/search/ranking/launch_data.h
@@ -8,6 +8,7 @@ #include <string> #include "ash/public/cpp/app_list/app_list_types.h" +#include "chrome/browser/ash/app_list/search/types.h" namespace app_list { @@ -24,6 +25,8 @@ ash::AppListSearchResultType::kUnknown; ash::AppListLaunchedFrom launched_from = ash::AppListLaunchedFrom::kLaunchedFromShelf; + // The category of the result. + Category category = Category::kUnknown; // The type of app launched. ash::AppListLaunchType launch_type = ash::AppListLaunchType::kSearchResult; // The index of the suggested app launched, if applicable.
diff --git a/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc index ce23194..1a083546 100644 --- a/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc +++ b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker.cc
@@ -101,7 +101,7 @@ ash::AppListLaunchedFrom::kLaunchedFromSearchBox) { return; } - mrfu_->Use(CategoryToString(ResultTypeToCategory(launch.result_type))); + mrfu_->Use(CategoryToString(launch.category)); } void MrfuCategoryRanker::SetDefaultCategoryScores() {
diff --git a/chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc index 54a1f086..2bba79d 100644 --- a/chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc +++ b/chrome/browser/ash/app_list/search/ranking/mrfu_ranker_unittest.cc
@@ -111,10 +111,10 @@ Wait(); // Train so that settings should be first, followed by apps. - ranker.Train(MakeLaunchData("a", ResultType::kInstalledApp)); - ranker.Train(MakeLaunchData("c", ResultType::kOsSettings)); - ranker.Train(MakeLaunchData("d", ResultType::kOsSettings)); - ranker.Train(MakeLaunchData("b", ResultType::kInstalledApp)); + ranker.Train(MakeLaunchData("a", Category::kApps)); + ranker.Train(MakeLaunchData("c", Category::kSettings)); + ranker.Train(MakeLaunchData("d", Category::kSettings)); + ranker.Train(MakeLaunchData("b", Category::kApps)); ResultsMap results; results[ResultType::kInstalledApp] =
diff --git a/chrome/browser/ash/app_list/search/ranking/util.cc b/chrome/browser/ash/app_list/search/ranking/util.cc index 1c30ae6..ad444fe18 100644 --- a/chrome/browser/ash/app_list/search/ranking/util.cc +++ b/chrome/browser/ash/app_list/search/ranking/util.cc
@@ -29,46 +29,4 @@ return static_cast<Category>(number); } -Category ResultTypeToCategory(ResultType result_type) { - switch (result_type) { - case ResultType::kInstalledApp: - case ResultType::kZeroStateApp: - case ResultType::kInstantApp: - case ResultType::kInternalApp: - case ResultType::kGames: - return Category::kApps; - case ResultType::kArcAppShortcut: - return Category::kAppShortcuts; - case ResultType::kOmnibox: - case ResultType::kAnswerCard: - case ResultType::kOpenTab: - return Category::kWeb; - case ResultType::kZeroStateFile: - case ResultType::kZeroStateDrive: - case ResultType::kFileSearch: - case ResultType::kDriveSearch: - return Category::kFiles; - case ResultType::kOsSettings: - case ResultType::kPersonalization: - return Category::kSettings; - case ResultType::kHelpApp: - case ResultType::kZeroStateHelpApp: - case ResultType::kKeyboardShortcut: - return Category::kHelp; - case ResultType::kPlayStoreReinstallApp: - case ResultType::kPlayStoreApp: - return Category::kPlayStore; - case ResultType::kAssistantText: - return Category::kSearchAndAssistant; - // Never used in the search backend. - case ResultType::kUnknown: - // Suggested content toggle fake result type. Used only in ash, not in the - // search backend. - case ResultType::kInternalPrivacyInfo: - // Deprecated. - case ResultType::kLauncher: - return Category::kUnknown; - } -} - } // namespace app_list
diff --git a/chrome/browser/ash/app_list/search/ranking/util.h b/chrome/browser/ash/app_list/search/ranking/util.h index 3373fe6..cb0815f 100644 --- a/chrome/browser/ash/app_list/search/ranking/util.h +++ b/chrome/browser/ash/app_list/search/ranking/util.h
@@ -22,13 +22,6 @@ Category StringToCategory(const std::string& value); -// TODO(crbug.com/1378862): This can be removed once LaunchData contains the -// result category. -// -// This is slightly inconsistent with the true result->category mapping, because -// Omnibox results can either be in the kWeb or kSearchAndAssistant category. -Category ResultTypeToCategory(ResultType result_type); - } // namespace app_list #endif // CHROME_BROWSER_ASH_APP_LIST_SEARCH_RANKING_UTIL_H_
diff --git a/chrome/browser/ash/app_list/search/test/ranking_test_util.cc b/chrome/browser/ash/app_list/search/test/ranking_test_util.cc index 15bb1d5a..b767edd6 100644 --- a/chrome/browser/ash/app_list/search/test/ranking_test_util.cc +++ b/chrome/browser/ash/app_list/search/test/ranking_test_util.cc
@@ -38,11 +38,11 @@ } LaunchData RankerTestBase::MakeLaunchData(const std::string& id, - ResultType result_type) { + Category category) { LaunchData launch; launch.launched_from = ash::AppListLaunchedFrom::kLaunchedFromSearchBox; launch.id = id; - launch.result_type = result_type; + launch.category = category; return launch; }
diff --git a/chrome/browser/ash/app_list/search/test/ranking_test_util.h b/chrome/browser/ash/app_list/search/test/ranking_test_util.h index 1bc01c5b..8fbdbe1e 100644 --- a/chrome/browser/ash/app_list/search/test/ranking_test_util.h +++ b/chrome/browser/ash/app_list/search/test/ranking_test_util.h
@@ -34,7 +34,7 @@ Category category = Category::kUnknown); LaunchData MakeLaunchData(const std::string& id, - ResultType result_type = ResultType::kUnknown); + Category category = Category::kUnknown); template <typename T> T ReadProtoFromDisk() {
diff --git a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc index 8c3aa682..657d683b 100644 --- a/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc +++ b/chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/ash/app_list/arc/arc_app_utils.h" #include "chrome/browser/ash/app_list/search/ranking/launch_data.h" #include "chrome/browser/ash/app_list/search/search_controller.h" +#include "chrome/browser/ash/app_list/search/types.h" #include "chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_request.h" #include "chrome/browser/profiles/profile.h" #include "ui/base/models/image_model.h" @@ -81,6 +82,7 @@ launch_data.id = ConstructArcAppShortcutUrl( app_id_, app_shortcut_items_->at(index).shortcut_id), launch_data.result_type = ash::AppListSearchResultType::kArcAppShortcut; + launch_data.category = app_list::Category::kAppShortcuts; app_list_client_impl->search_controller()->Train(std::move(launch_data)); }
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc index 3c452cb..3c65cc7 100644 --- a/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc +++ b/chrome/browser/ash/child_accounts/time_limits/app_service_wrapper_unittest.cc
@@ -150,8 +150,8 @@ } if (app_id.app_type() == apps::AppType::kChromeApp) { - scoped_refptr<extensions::Extension> ext = CreateExtension( - app_id.app_id(), app_name, url.value(), false /*is_bookmark_app*/); + scoped_refptr<extensions::Extension> ext = + CreateExtension(app_id.app_id(), app_name, url.value()); extension_service_->AddExtension(ext.get()); task_environment_.RunUntilIdle(); return; @@ -166,14 +166,6 @@ task_environment_.RunUntilIdle(); return; } - - if (app_id.app_type() == apps::AppType::kWeb) { - scoped_refptr<extensions::Extension> web_app = CreateExtension( - app_id.app_id(), app_name, url.value(), true /*is_bookmark_app*/); - extension_service_->AddExtension(web_app.get()); - task_environment_.RunUntilIdle(); - return; - } } void SimulateAppUninstalled(const AppId& app_id) {
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc index 5464ff4..89ef203 100644 --- a/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc +++ b/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc
@@ -38,8 +38,7 @@ scoped_refptr<extensions::Extension> CreateExtension( const std::string& extension_id, const std::string& name, - const std::string& url, - bool is_bookmark_app) { + const std::string& url) { base::Value::Dict manifest; manifest.Set(extensions::manifest_keys::kName, name); manifest.Set(extensions::manifest_keys::kVersion, "1"); @@ -48,8 +47,7 @@ std::string error; extensions::Extension::InitFromValueFlags flags = - is_bookmark_app ? extensions::Extension::FROM_BOOKMARK - : extensions::Extension::NO_FLAGS; + extensions::Extension::NO_FLAGS; scoped_refptr<extensions::Extension> extension = extensions::Extension::Create( base::FilePath(), extensions::mojom::ManifestLocation::kUnpacked,
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.h b/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.h index bfc9e6c3..f6e26dfd 100644 --- a/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.h +++ b/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.h
@@ -26,8 +26,7 @@ scoped_refptr<extensions::Extension> CreateExtension( const std::string& extension_id, const std::string& name, - const std::string& url, - bool is_bookmark_app = false); + const std::string& url); } // namespace app_time } // namespace ash
diff --git a/chrome/browser/ash/dbus/fusebox_service_provider.cc b/chrome/browser/ash/dbus/fusebox_service_provider.cc index 6cc4e251..7a05074 100644 --- a/chrome/browser/ash/dbus/fusebox_service_provider.cc +++ b/chrome/browser/ash/dbus/fusebox_service_provider.cc
@@ -14,14 +14,6 @@ // This file provides the "D-Bus protocol logic" half of the FuseBox server, // coupled with the "business logic" half in fusebox_server.cc. -// The "fusebox_staging" concept is described in -// chrome/browser/ash/fusebox/fusebox_staging.proto -// -// TODO(b/255520194): remove this section. -namespace fusebox_staging { -const char kStat2Method[] = "Stat2"; -} // namespace fusebox_staging - namespace ash { namespace { @@ -64,7 +56,7 @@ ExportProtoMethod(fusebox::kRead2Method, &fusebox::Server::Read2); ExportProtoMethod(fusebox::kReadDir2Method, &fusebox::Server::ReadDir2); ExportProtoMethod(fusebox::kRmDirMethod, &fusebox::Server::RmDir); - ExportProtoMethod(fusebox_staging::kStat2Method, &fusebox::Server::Stat2); + ExportProtoMethod(fusebox::kStat2Method, &fusebox::Server::Stat2); ExportProtoMethod(fusebox::kTruncateMethod, &fusebox::Server::Truncate); ExportProtoMethod(fusebox::kUnlinkMethod, &fusebox::Server::Unlink); ExportProtoMethod(fusebox::kWrite2Method, &fusebox::Server::Write2);
diff --git a/chrome/browser/ash/fusebox/fusebox_server.cc b/chrome/browser/ash/fusebox/fusebox_server.cc index 8ee5c21..f42e089 100644 --- a/chrome/browser/ash/fusebox/fusebox_server.cc +++ b/chrome/browser/ash/fusebox/fusebox_server.cc
@@ -162,7 +162,7 @@ // looks unused, but we need to keep the storage::FileSystemContext reference // alive until the callbacks are run. -void FillInDirEntryProto(fusebox_staging::DirEntryProto* dir_entry_proto, +void FillInDirEntryProto(DirEntryProto* dir_entry_proto, const base::File::Info& info, bool read_only) { dir_entry_proto->set_mode_bits( @@ -185,13 +185,13 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { std::move(on_failure).Run(); - fusebox_staging::CreateResponseProto response_proto; + CreateResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; } - fusebox_staging::CreateResponseProto response_proto; + CreateResponseProto response_proto; response_proto.set_fuse_handle(fuse_handle); FillInDirEntryProto(response_proto.mutable_stat(), info, read_only); std::move(callback).Run(response_proto); @@ -210,7 +210,7 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { std::move(on_failure).Run(); - fusebox_staging::CreateResponseProto response_proto; + CreateResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; @@ -246,13 +246,13 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::MkDirResponseProto response_proto; + MkDirResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; } - fusebox_staging::MkDirResponseProto response_proto; + MkDirResponseProto response_proto; FillInDirEntryProto(response_proto.mutable_stat(), info, read_only); std::move(callback).Run(response_proto); } @@ -267,7 +267,7 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::MkDirResponseProto response_proto; + MkDirResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; @@ -296,7 +296,7 @@ base::File::Error error_code) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - fusebox_staging::Read2ResponseProto response_proto; + Read2ResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(error_code)); std::move(callback).Run(response_proto); } @@ -306,7 +306,7 @@ int length) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - fusebox_staging::Read2ResponseProto response_proto; + Read2ResponseProto response_proto; if (length < 0) { response_proto.set_posix_error_code(NetErrorToErrno(length)); } else { @@ -325,13 +325,13 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::RmDirResponseProto response_proto; + RmDirResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; } - fusebox_staging::RmDirResponseProto response_proto; + RmDirResponseProto response_proto; std::move(callback).Run(response_proto); } @@ -345,13 +345,13 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::TruncateResponseProto response_proto; + TruncateResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; } - fusebox_staging::TruncateResponseProto response_proto; + TruncateResponseProto response_proto; FillInDirEntryProto(response_proto.mutable_stat(), info, read_only); std::move(callback).Run(response_proto); } @@ -366,7 +366,7 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::TruncateResponseProto response_proto; + TruncateResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; @@ -399,13 +399,13 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::UnlinkResponseProto response_proto; + UnlinkResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; } - fusebox_staging::UnlinkResponseProto response_proto; + UnlinkResponseProto response_proto; std::move(callback).Run(response_proto); } @@ -413,7 +413,7 @@ base::File::Error error_code) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - fusebox_staging::Write2ResponseProto response_proto; + Write2ResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(error_code)); std::move(callback).Run(response_proto); } @@ -421,7 +421,7 @@ void RunWrite2CallbackTypical(Server::Write2Callback callback, int length) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - fusebox_staging::Write2ResponseProto response_proto; + Write2ResponseProto response_proto; if (length < 0) { response_proto.set_posix_error_code(NetErrorToErrno(length)); } @@ -438,13 +438,13 @@ int posix_error_code = FileErrorToErrno(error_code); if (posix_error_code) { - fusebox_staging::Stat2ResponseProto response_proto; + Stat2ResponseProto response_proto; response_proto.set_posix_error_code(posix_error_code); std::move(callback).Run(response_proto); return; } - fusebox_staging::Stat2ResponseProto response_proto; + Stat2ResponseProto response_proto; FillInDirEntryProto(response_proto.mutable_stat(), info, read_only); std::move(callback).Run(response_proto); } @@ -613,20 +613,18 @@ Server::FuseFileMapEntry::~FuseFileMapEntry() = default; -void Server::FuseFileMapEntry::DoRead2( - const fusebox_staging::Read2RequestProto& request, - Server::Read2Callback callback) { +void Server::FuseFileMapEntry::DoRead2(const Read2RequestProto& request, + Server::Read2Callback callback) { int64_t offset = request.has_offset() ? request.offset() : 0; int64_t length = request.has_length() ? request.length() : 0; seqbnd_read_writer_.AsyncCall(&Server::ReadWriter::Read) .WithArgs(fs_context_, offset, length, std::move(callback)); } -void Server::FuseFileMapEntry::DoWrite2( - const fusebox_staging::Write2RequestProto& request, - Server::Write2Callback callback) { +void Server::FuseFileMapEntry::DoWrite2(const Write2RequestProto& request, + Server::Write2Callback callback) { if (!request.has_data() || request.data().empty()) { - fusebox_staging::Write2ResponseProto response_proto; + Write2ResponseProto response_proto; std::move(callback).Run(response_proto); return; } @@ -775,7 +773,7 @@ return base::Value(std::move(dict)); } -void Server::Close2(const fusebox_staging::Close2RequestProto& request_proto, +void Server::Close2(const Close2RequestProto& request_proto, Close2Callback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -783,7 +781,7 @@ request_proto.has_fuse_handle() ? request_proto.fuse_handle() : 0; auto iter = fuse_file_map_.find(fuse_handle); if (iter == fuse_file_map_.end()) { - fusebox_staging::Close2ResponseProto response_proto; + Close2ResponseProto response_proto; response_proto.set_posix_error_code(ENOENT); std::move(callback).Run(response_proto); return; @@ -796,18 +794,18 @@ fuse_file_map_.erase(iter); - fusebox_staging::Close2ResponseProto response_proto; + Close2ResponseProto response_proto; std::move(callback).Run(response_proto); if (!pending_reads.empty()) { - fusebox_staging::Read2ResponseProto read2_response_proto; + Read2ResponseProto read2_response_proto; read2_response_proto.set_posix_error_code(EBUSY); for (auto& pending_read : pending_reads) { std::move(pending_read.second).Run(read2_response_proto); } } if (!pending_writes.empty()) { - fusebox_staging::Write2ResponseProto write2_esponse_proto; + Write2ResponseProto write2_esponse_proto; write2_esponse_proto.set_posix_error_code(EBUSY); for (auto& pending_read : pending_writes) { std::move(pending_read.second).Run(write2_esponse_proto); @@ -815,7 +813,7 @@ } } -void Server::Create(const fusebox_staging::CreateRequestProto& request_proto, +void Server::Create(const CreateRequestProto& request_proto, CreateCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -825,12 +823,12 @@ auto common = ParseFileSystemURL(moniker_map_, prefix_map_, fs_url_as_string); if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::CreateResponseProto response_proto; + CreateResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; } else if (common.read_only) { - fusebox_staging::CreateResponseProto response_proto; + CreateResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; @@ -861,7 +859,7 @@ common.fs_url, exclusive, std::move(outer_callback))); } -void Server::MkDir(const fusebox_staging::MkDirRequestProto& request_proto, +void Server::MkDir(const MkDirRequestProto& request_proto, MkDirCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -871,12 +869,12 @@ auto common = ParseFileSystemURL(moniker_map_, prefix_map_, fs_url_as_string); if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::MkDirResponseProto response_proto; + MkDirResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; } else if (common.read_only) { - fusebox_staging::MkDirResponseProto response_proto; + MkDirResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; @@ -899,41 +897,41 @@ std::move(outer_callback))); } -void Server::Open2(const fusebox_staging::Open2RequestProto& request_proto, +void Server::Open2(const Open2RequestProto& request_proto, Open2Callback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::string fs_url_as_string = request_proto.has_file_system_url() ? request_proto.file_system_url() : std::string(); - fusebox_staging::AccessMode access_mode = - request_proto.has_access_mode() ? request_proto.access_mode() - : fusebox_staging::AccessMode::NO_ACCESS; + AccessMode access_mode = request_proto.has_access_mode() + ? request_proto.access_mode() + : AccessMode::NO_ACCESS; auto common = ParseFileSystemURL(moniker_map_, prefix_map_, fs_url_as_string); if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::Open2ResponseProto response_proto; + Open2ResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; } - bool readable = (access_mode == fusebox_staging::AccessMode::READ_ONLY) || - (access_mode == fusebox_staging::AccessMode::READ_WRITE); - bool writable = !common.read_only && - ((access_mode == fusebox_staging::AccessMode::WRITE_ONLY) || - (access_mode == fusebox_staging::AccessMode::READ_WRITE)); + bool readable = (access_mode == AccessMode::READ_ONLY) || + (access_mode == AccessMode::READ_WRITE); + bool writable = + !common.read_only && ((access_mode == AccessMode::WRITE_ONLY) || + (access_mode == AccessMode::READ_WRITE)); uint64_t fuse_handle = InsertFuseFileMapEntry( FuseFileMapEntry(std::move(common.fs_context), std::move(common.fs_url), readable, writable)); - fusebox_staging::Open2ResponseProto response_proto; + Open2ResponseProto response_proto; response_proto.set_fuse_handle(fuse_handle); std::move(callback).Run(response_proto); } -void Server::Read2(const fusebox_staging::Read2RequestProto& request_proto, +void Server::Read2(const Read2RequestProto& request_proto, Read2Callback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -941,12 +939,12 @@ request_proto.has_fuse_handle() ? request_proto.fuse_handle() : 0; auto iter = fuse_file_map_.find(fuse_handle); if (iter == fuse_file_map_.end()) { - fusebox_staging::Read2ResponseProto response_proto; + Read2ResponseProto response_proto; response_proto.set_posix_error_code(ENOENT); std::move(callback).Run(response_proto); return; } else if (!iter->second.readable_) { - fusebox_staging::Read2ResponseProto response_proto; + Read2ResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; @@ -1024,7 +1022,7 @@ common.fs_url, std::move(outer_callback))); } -void Server::RmDir(const fusebox_staging::RmDirRequestProto& request_proto, +void Server::RmDir(const RmDirRequestProto& request_proto, RmDirCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -1034,12 +1032,12 @@ auto common = ParseFileSystemURL(moniker_map_, prefix_map_, fs_url_as_string); if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::RmDirResponseProto response_proto; + RmDirResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; } else if (common.read_only) { - fusebox_staging::RmDirResponseProto response_proto; + RmDirResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; @@ -1059,7 +1057,7 @@ common.fs_url, std::move(outer_callback))); } -void Server::Stat2(const fusebox_staging::Stat2RequestProto& request_proto, +void Server::Stat2(const Stat2RequestProto& request_proto, Stat2Callback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -1071,13 +1069,13 @@ if (common.is_moniker_root) { constexpr bool is_directory = true; constexpr bool read_only = true; - fusebox_staging::Stat2ResponseProto response_proto; - fusebox_staging::DirEntryProto* stat = response_proto.mutable_stat(); + Stat2ResponseProto response_proto; + DirEntryProto* stat = response_proto.mutable_stat(); stat->set_mode_bits(Server::MakeModeBits(is_directory, read_only)); std::move(callback).Run(response_proto); return; } else if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::Stat2ResponseProto response_proto; + Stat2ResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; @@ -1102,9 +1100,8 @@ common.fs_url, metadata_fields, std::move(outer_callback))); } -void Server::Truncate( - const fusebox_staging::TruncateRequestProto& request_proto, - TruncateCallback callback) { +void Server::Truncate(const TruncateRequestProto& request_proto, + TruncateCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); std::string fs_url_as_string = request_proto.has_file_system_url() @@ -1113,12 +1110,12 @@ auto common = ParseFileSystemURL(moniker_map_, prefix_map_, fs_url_as_string); if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::TruncateResponseProto response_proto; + TruncateResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; } else if (common.read_only) { - fusebox_staging::TruncateResponseProto response_proto; + TruncateResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; @@ -1140,7 +1137,7 @@ std::move(outer_callback))); } -void Server::Unlink(const fusebox_staging::UnlinkRequestProto& request_proto, +void Server::Unlink(const UnlinkRequestProto& request_proto, UnlinkCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -1150,12 +1147,12 @@ auto common = ParseFileSystemURL(moniker_map_, prefix_map_, fs_url_as_string); if (common.error_code != base::File::Error::FILE_OK) { - fusebox_staging::UnlinkResponseProto response_proto; + UnlinkResponseProto response_proto; response_proto.set_posix_error_code(FileErrorToErrno(common.error_code)); std::move(callback).Run(response_proto); return; } else if (common.read_only) { - fusebox_staging::UnlinkResponseProto response_proto; + UnlinkResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; @@ -1175,7 +1172,7 @@ common.fs_url, std::move(outer_callback))); } -void Server::Write2(const fusebox_staging::Write2RequestProto& request_proto, +void Server::Write2(const Write2RequestProto& request_proto, Write2Callback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -1183,18 +1180,18 @@ request_proto.has_fuse_handle() ? request_proto.fuse_handle() : 0; auto iter = fuse_file_map_.find(fuse_handle); if (iter == fuse_file_map_.end()) { - fusebox_staging::Write2ResponseProto response_proto; + Write2ResponseProto response_proto; response_proto.set_posix_error_code(ENOENT); std::move(callback).Run(response_proto); return; } else if (!iter->second.writable_) { - fusebox_staging::Write2ResponseProto response_proto; + Write2ResponseProto response_proto; response_proto.set_posix_error_code(EACCES); std::move(callback).Run(response_proto); return; } else if (request_proto.has_data() && (request_proto.data().size() > INT_MAX)) { - fusebox_staging::Write2ResponseProto response_proto; + Write2ResponseProto response_proto; response_proto.set_posix_error_code(EMSGSIZE); std::move(callback).Run(response_proto); return; @@ -1312,15 +1309,14 @@ std::move(scoped_temp_dir))); } -void Server::OnRead2( - uint64_t fuse_handle, - Read2Callback callback, - const fusebox_staging::Read2ResponseProto& response_proto) { +void Server::OnRead2(uint64_t fuse_handle, + Read2Callback callback, + const Read2ResponseProto& response_proto) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto iter = fuse_file_map_.find(fuse_handle); if (iter == fuse_file_map_.end()) { - fusebox_staging::Read2ResponseProto enoent_response_proto; + Read2ResponseProto enoent_response_proto; enoent_response_proto.set_posix_error_code(ENOENT); std::move(callback).Run(enoent_response_proto); return; @@ -1373,15 +1369,14 @@ } } -void Server::OnWrite2( - uint64_t fuse_handle, - Write2Callback callback, - const fusebox_staging::Write2ResponseProto& response_proto) { +void Server::OnWrite2(uint64_t fuse_handle, + Write2Callback callback, + const Write2ResponseProto& response_proto) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); auto iter = fuse_file_map_.find(fuse_handle); if (iter == fuse_file_map_.end()) { - fusebox_staging::Write2ResponseProto enoent_response_proto; + Write2ResponseProto enoent_response_proto; enoent_response_proto.set_posix_error_code(ENOENT); std::move(callback).Run(enoent_response_proto); return;
diff --git a/chrome/browser/ash/fusebox/fusebox_server.h b/chrome/browser/ash/fusebox/fusebox_server.h index 7a66406..3561260bd 100644 --- a/chrome/browser/ash/fusebox/fusebox_server.h +++ b/chrome/browser/ash/fusebox/fusebox_server.h
@@ -89,34 +89,29 @@ // storage::FileSystemURL (in string form). // Close2 closes a virtual file opened by Open2. - using Close2Callback = base::OnceCallback<void( - const fusebox_staging::Close2ResponseProto& response)>; - void Close2(const fusebox_staging::Close2RequestProto& request, - Close2Callback callback); + using Close2Callback = + base::OnceCallback<void(const Close2ResponseProto& response)>; + void Close2(const Close2RequestProto& request, Close2Callback callback); // Create creates a file (not a directory). - using CreateCallback = base::OnceCallback<void( - const fusebox_staging::CreateResponseProto& response)>; - void Create(const fusebox_staging::CreateRequestProto& request, - CreateCallback callback); + using CreateCallback = + base::OnceCallback<void(const CreateResponseProto& response)>; + void Create(const CreateRequestProto& request, CreateCallback callback); // MkDir is analogous to "/usr/bin/mkdir". - using MkDirCallback = base::OnceCallback<void( - const fusebox_staging::MkDirResponseProto& response)>; - void MkDir(const fusebox_staging::MkDirRequestProto& request, - MkDirCallback callback); + using MkDirCallback = + base::OnceCallback<void(const MkDirResponseProto& response)>; + void MkDir(const MkDirRequestProto& request, MkDirCallback callback); // Open2 opens a virtual file for reading and/or writing. - using Open2Callback = base::OnceCallback<void( - const fusebox_staging::Open2ResponseProto& response)>; - void Open2(const fusebox_staging::Open2RequestProto& request, - Open2Callback callback); + using Open2Callback = + base::OnceCallback<void(const Open2ResponseProto& response)>; + void Open2(const Open2RequestProto& request, Open2Callback callback); // Read2 reads from a virtual file opened by Open2. - using Read2Callback = base::OnceCallback<void( - const fusebox_staging::Read2ResponseProto& response)>; - void Read2(const fusebox_staging::Read2RequestProto& request, - Read2Callback callback); + using Read2Callback = + base::OnceCallback<void(const Read2ResponseProto& response)>; + void Read2(const Read2RequestProto& request, Read2Callback callback); // ReadDir2 lists the directory's children. The results will be sent back in // the responses of one or more request-response RPC pairs. The first request @@ -133,34 +128,29 @@ void ReadDir2(const ReadDir2RequestProto& request, ReadDir2Callback callback); // RmDir is analogous to "/usr/bin/rmdir". - using RmDirCallback = base::OnceCallback<void( - const fusebox_staging::RmDirResponseProto& response)>; - void RmDir(const fusebox_staging::RmDirRequestProto& request, - RmDirCallback callback); + using RmDirCallback = + base::OnceCallback<void(const RmDirResponseProto& response)>; + void RmDir(const RmDirRequestProto& request, RmDirCallback callback); // Stat2 returns the file or directory's metadata. - using Stat2Callback = base::OnceCallback<void( - const fusebox_staging::Stat2ResponseProto& response)>; - void Stat2(const fusebox_staging::Stat2RequestProto& request, - Stat2Callback callback); + using Stat2Callback = + base::OnceCallback<void(const Stat2ResponseProto& response)>; + void Stat2(const Stat2RequestProto& request, Stat2Callback callback); // Truncate sets a file's size. - using TruncateCallback = base::OnceCallback<void( - const fusebox_staging::TruncateResponseProto& response)>; - void Truncate(const fusebox_staging::TruncateRequestProto& request, - TruncateCallback callback); + using TruncateCallback = + base::OnceCallback<void(const TruncateResponseProto& response)>; + void Truncate(const TruncateRequestProto& request, TruncateCallback callback); // Unlink deletes a file. - using UnlinkCallback = base::OnceCallback<void( - const fusebox_staging::UnlinkResponseProto& response)>; - void Unlink(const fusebox_staging::UnlinkRequestProto& request, - UnlinkCallback callback); + using UnlinkCallback = + base::OnceCallback<void(const UnlinkResponseProto& response)>; + void Unlink(const UnlinkRequestProto& request, UnlinkCallback callback); // Write2 writes to a virtual file opened by Open2. - using Write2Callback = base::OnceCallback<void( - const fusebox_staging::Write2ResponseProto& response)>; - void Write2(const fusebox_staging::Write2RequestProto& request, - Write2Callback callback); + using Write2Callback = + base::OnceCallback<void(const Write2ResponseProto& response)>; + void Write2(const Write2RequestProto& request, Write2Callback callback); // File operation D-Bus methods above. Meta D-Bus methods below, which do not // map 1:1 to FUSE or C standard library file operations. @@ -206,10 +196,8 @@ // ---- - using PendingRead2 = - std::pair<fusebox_staging::Read2RequestProto, Read2Callback>; - using PendingWrite2 = - std::pair<fusebox_staging::Write2RequestProto, Write2Callback>; + using PendingRead2 = std::pair<Read2RequestProto, Read2Callback>; + using PendingWrite2 = std::pair<Write2RequestProto, Write2Callback>; // Lives entirely on the I/O thread, as enforced by base::SequenceBound. struct ReadWriter { @@ -262,10 +250,8 @@ FuseFileMapEntry(FuseFileMapEntry&&); ~FuseFileMapEntry(); - void DoRead2(const fusebox_staging::Read2RequestProto& request, - Read2Callback callback); - void DoWrite2(const fusebox_staging::Write2RequestProto& request, - Write2Callback callback); + void DoRead2(const Read2RequestProto& request, Read2Callback callback); + void DoWrite2(const Write2RequestProto& request, Write2Callback callback); const scoped_refptr<storage::FileSystemContext> fs_context_; const bool readable_; @@ -343,7 +329,7 @@ void OnRead2(uint64_t fuse_handle, Read2Callback callback, - const fusebox_staging::Read2ResponseProto& response); + const Read2ResponseProto& response); void OnReadDirectory(scoped_refptr<storage::FileSystemContext> fs_context, bool read_only, @@ -354,7 +340,7 @@ void OnWrite2(uint64_t fuse_handle, Write2Callback callback, - const fusebox_staging::Write2ResponseProto& response); + const Write2ResponseProto& response); // Removes the entry (if present) for the given map key. void EraseFuseFileMapEntry(uint64_t fuse_handle);
diff --git a/chrome/browser/ash/fusebox/fusebox_staging.proto b/chrome/browser/ash/fusebox/fusebox_staging.proto index fa60976d..5a5e864 100644 --- a/chrome/browser/ash/fusebox/fusebox_staging.proto +++ b/chrome/browser/ash/fusebox/fusebox_staging.proto
@@ -19,162 +19,5 @@ package fusebox_staging; -enum AccessMode { - NO_ACCESS = 0; - READ_ONLY = 1; - WRITE_ONLY = 2; - READ_WRITE = 3; -} - -message DirEntryProto { - // Entry name. - optional string name = 2; - // POSIX style (S_IFREG | rwxr-x---) bits. - optional uint32 mode_bits = 3; - // File size in bytes. - optional int64 size = 4; - // Modification time (microseconds since the Windows epoch, like base::Time). - optional int64 mtime = 5; - // Access time (microseconds since the Windows epoch, like base::Time). - optional int64 atime = 6; - // Creation time (microseconds since the Windows epoch, like base::Time). - optional int64 ctime = 7; -} - -// Close2 closes a fuse_handle previously returned by Open2. - -message Close2RequestProto { - optional uint64 fuse_handle = 2; -} - -message Close2ResponseProto { - optional int32 posix_error_code = 1; -} - -// Create creates and opens (in the Open2 sense) a file. It is exclusive (it -// fails if the name already exists). -// -// There are no mode_bits in the request proto, as there's no mode_bits arg to -// the storage::FileSystemOperationRunner::CreateFile method. - -message CreateRequestProto { - optional string file_system_url = 3; -} - -message CreateResponseProto { - optional int32 posix_error_code = 1; - optional uint64 fuse_handle = 2; - optional DirEntryProto stat = 3; -} - -// MkDir is exclusive (it fails if the name already exists) and non-recursive -// (it's plain "mkdir", not "mkdir -p"). -// -// There are no mode_bits in the request proto, as there's no mode_bits arg to -// the storage::FileSystemOperationRunner::CreateDirectory method. - -message MkDirRequestProto { - optional string file_system_url = 3; -} - -message MkDirResponseProto { - optional int32 posix_error_code = 1; - optional DirEntryProto stat = 3; -} - -// Open2 opens a virtual file for reading and/or writing. It returns a -// fuse_handle, which is like a file descriptor but for the file server side, -// not the file client side. -// -// The "2" suffix is because the subsequent Read2 / Write2 / Close2 calls pass -// a number (fuse_handle) instead of a string (a name / path / URL) as used by -// the "version 1" Read / Write / Close methods. The same file can be opened -// multiple times concurrently, producing multiple different handles that share -// the same file_system_url. -// -// The fuse_handle uint64 numbers are generated by the Fusebox server. They are -// not guaranteed to be sequential or increasing. Zero is an invalid value. The -// high bit (also known as the 1<<63 bit) is also always zero for valid values, -// so that the Fusebox client (which is itself a FUSE server) can re-purpose -// large uint64 values (e.g. for tracking FUSE requests that do not need a -// round-trip to the Fusebox server). - -message Open2RequestProto { - optional string file_system_url = 3; - optional AccessMode access_mode = 4; -} - -message Open2ResponseProto { - optional int32 posix_error_code = 1; - optional uint64 fuse_handle = 2; -} - -// Read2 reads from a fuse_handle previously returned by Open2. - -message Read2RequestProto { - optional uint64 fuse_handle = 2; - optional int64 offset = 4; - optional int64 length = 5; -} - -message Read2ResponseProto { - optional int32 posix_error_code = 1; - optional bytes data = 3; -} - -// RmDir truly deletes (it does not "move to trash", an undo-able operation) -// and it is non-recursive (it's plain "rmdir", not "rmdir -p" or "rm -r"). - -message RmDirRequestProto { - optional string file_system_url = 3; -} - -message RmDirResponseProto { - optional int32 posix_error_code = 1; -} - -// Stat2 returns file state. - -message Stat2RequestProto { - optional string file_system_url = 3; -} - -message Stat2ResponseProto { - optional int32 posix_error_code = 1; - optional DirEntryProto stat = 3; -} - -// Truncate sets a file's size. - -message TruncateRequestProto { - optional string file_system_url = 3; - optional int64 length = 5; -} - -message TruncateResponseProto { - optional int32 posix_error_code = 1; - optional DirEntryProto stat = 3; -} - -// Unlink deletes a file, like "rm". It truly deletes (it does not "move to -// trash", an undo-able operation). - -message UnlinkRequestProto { - optional string file_system_url = 3; -} - -message UnlinkResponseProto { - optional int32 posix_error_code = 1; -} - -// Write2 writes to a fuse_handle previously returned by Open2. - -message Write2RequestProto { - optional uint64 fuse_handle = 2; - optional int64 offset = 4; - optional bytes data = 5; -} - -message Write2ResponseProto { - optional int32 posix_error_code = 1; -} +// There are no fusebox_staging definitions at this time. They're all in the +// canonical fusebox.proto file.
diff --git a/chrome/browser/ash/login/active_directory_login_browsertest.cc b/chrome/browser/ash/login/active_directory_login_browsertest.cc index 6b8a39d..767a137 100644 --- a/chrome/browser/ash/login/active_directory_login_browsertest.cc +++ b/chrome/browser/ash/login/active_directory_login_browsertest.cc
@@ -4,11 +4,13 @@ #include <string> +#include "ash/constants/ash_features.h" #include "base/base_paths.h" #include "base/environment.h" #include "base/path_service.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/ash/authpolicy/kerberos_files_handler.h" #include "chrome/browser/ash/login/test/active_directory_login_mixin.h" #include "chrome/browser/ash/login/test/device_state_mixin.h" @@ -64,7 +66,13 @@ : // Using the same realm as supervised user domain. Should be treated // as normal realm. test_realm_(user_manager::kSupervisedUserDomain), - test_user_(kTestActiveDirectoryUser + ("@" + test_realm_)) {} + test_user_(kTestActiveDirectoryUser + ("@" + test_realm_)) { + // All tests related to Active Directory login don't make sense when the + // kChromadAvailable feature is disabled. We also don't need to verify that + // the device is disabled in that case, because the Chromad disabling + // feature is already tested in `device_disabling_manager_unittest.cc`. + scoped_feature_list_.InitAndEnableFeature(features::kChromadAvailable); + } ActiveDirectoryLoginTest(const ActiveDirectoryLoginTest&) = delete; ActiveDirectoryLoginTest& operator=(const ActiveDirectoryLoginTest&) = delete; @@ -82,6 +90,9 @@ &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_ACTIVE_DIRECTORY_ENROLLED}; ActiveDirectoryLoginMixin ad_login_{&mixin_host_}; + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; class ActiveDirectoryLoginAutocompleteTest : public ActiveDirectoryLoginTest {
diff --git a/chrome/browser/ash/login/existing_user_controller_browsertest.cc b/chrome/browser/ash/login/existing_user_controller_browsertest.cc index c72b777d..869565c 100644 --- a/chrome/browser/ash/login/existing_user_controller_browsertest.cc +++ b/chrome/browser/ash/login/existing_user_controller_browsertest.cc
@@ -878,7 +878,13 @@ class ExistingUserControllerActiveDirectoryTest : public ExistingUserControllerTest { public: - ExistingUserControllerActiveDirectoryTest() = default; + ExistingUserControllerActiveDirectoryTest() { + // All tests related to Active Directory login don't make sense when the + // kChromadAvailable feature is disabled. We also don't need to verify that + // the device is disabled in that case, because the Chromad disabling + // feature is already tested in `device_disabling_manager_unittest.cc`. + scoped_feature_list_.InitAndEnableFeature(features::kChromadAvailable); + } // Overriden from ExistingUserControllerTest: void SetUp() override { @@ -1012,6 +1018,7 @@ private: testing::NiceMock<policy::MockConfigurationPolicyProvider> policy_provider_; + base::test::ScopedFeatureList scoped_feature_list_; }; class ExistingUserControllerActiveDirectoryTestCreateProfileDir
diff --git a/chrome/browser/ash/login/screens/parental_handoff_screen.cc b/chrome/browser/ash/login/screens/parental_handoff_screen.cc index 2082829..632a04e 100644 --- a/chrome/browser/ash/login/screens/parental_handoff_screen.cc +++ b/chrome/browser/ash/login/screens/parental_handoff_screen.cc
@@ -11,10 +11,10 @@ #include "chrome/browser/ash/login/wizard_context.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/ui/webui/ash/login/parental_handoff_screen_handler.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" +#include "components/supervised_user/core/common/features.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "ui/base/l10n/l10n_util.h"
diff --git a/chrome/browser/ash/login/screens/sync_consent_browsertest.cc b/chrome/browser/ash/login/screens/sync_consent_browsertest.cc index 4e94c1a9..96bd2d7 100644 --- a/chrome/browser/ash/login/screens/sync_consent_browsertest.cc +++ b/chrome/browser/ash/login/screens/sync_consent_browsertest.cc
@@ -624,6 +624,14 @@ // not use sync. class SyncConsentActiveDirectoryTest : public OobeBaseTest { public: + SyncConsentActiveDirectoryTest() { + // All tests related to Active Directory login don't make sense when the + // kChromadAvailable feature is disabled. We also don't need to verify that + // the device is disabled in that case, because the Chromad disabling + // feature is already tested in `device_disabling_manager_unittest.cc`. + scoped_feature_list_.InitAndEnableFeature(features::kChromadAvailable); + } + ~SyncConsentActiveDirectoryTest() override = default; protected: @@ -632,6 +640,9 @@ DeviceStateMixin::State::OOBE_COMPLETED_ACTIVE_DIRECTORY_ENROLLED}; ActiveDirectoryLoginMixin ad_login_{&mixin_host_}; base::HistogramTester histogram_tester_; + + private: + base::test::ScopedFeatureList scoped_feature_list_; }; IN_PROC_BROWSER_TEST_F(SyncConsentActiveDirectoryTest, LoginDoesNotStartSync) {
diff --git a/chrome/browser/banners/test_app_banner_manager_desktop.cc b/chrome/browser/banners/test_app_banner_manager_desktop.cc index 4124bc3..debb92b0 100644 --- a/chrome/browser/banners/test_app_banner_manager_desktop.cc +++ b/chrome/browser/banners/test_app_banner_manager_desktop.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/run_loop.h" +#include "base/strings/stringprintf.h" #include "base/task/single_thread_task_runner.h" #include "components/webapps/browser/installable/installable_data.h" #include "content/public/browser/web_contents.h" @@ -84,6 +85,7 @@ void TestAppBannerManagerDesktop::OnDidGetManifest( const InstallableData& result) { + debug_log_.Append("OnDidGetManifest"); AppBannerManagerDesktop::OnDidGetManifest(result); // AppBannerManagerDesktop does not call |OnDidPerformInstallableCheck| to @@ -94,6 +96,7 @@ } void TestAppBannerManagerDesktop::OnDidPerformInstallableWebAppCheck( const InstallableData& result) { + debug_log_.Append("OnDidPerformInstallableWebAppCheck"); AppBannerManagerDesktop::OnDidPerformInstallableWebAppCheck(result); SetInstallable(result.NoBlockingErrors()); } @@ -105,11 +108,13 @@ void TestAppBannerManagerDesktop::OnDidPerformWorkerCheck( const InstallableData& result) { + debug_log_.Append("OnDidPerformWorkerCheck"); AppBannerManagerDesktop::OnDidPerformWorkerCheck(result); SetPromotable(result.NoBlockingErrors()); } void TestAppBannerManagerDesktop::ResetCurrentPageData() { + debug_log_.Append("ResetCurrentPageData"); AppBannerManagerDesktop::ResetCurrentPageData(); installable_.reset(); promotable_ = false; @@ -139,6 +144,7 @@ void TestAppBannerManagerDesktop::DidFinishLoad( content::RenderFrameHost* render_frame_host, const GURL& validated_url) { + debug_log_.Append("DidFinishLoad"); if (ShouldIgnore(render_frame_host, validated_url)) { SetInstallable(false); return; @@ -148,6 +154,8 @@ } void TestAppBannerManagerDesktop::UpdateState(AppBannerManager::State state) { + debug_log_.Append( + base::StringPrintf("State updated to %d", static_cast<int>(state))); AppBannerManager::UpdateState(state); if (state == AppBannerManager::State::PENDING_ENGAGEMENT || @@ -159,13 +167,18 @@ } void TestAppBannerManagerDesktop::SetInstallable(bool installable) { - DCHECK(!installable_.has_value() || installable_ == installable); + debug_log_.Append(base::StringPrintf("SetInstallable(%d)", installable)); + DCHECK(!installable_.has_value() || installable_ == installable) + << "Cannot set installable to " << installable << ", already set to " + << installable_.value() << ". Debug log:\n" + << debug_log_.DebugString(); installable_ = installable; if (installable_quit_closure_) std::move(installable_quit_closure_).Run(); } void TestAppBannerManagerDesktop::SetPromotable(bool promotable) { + debug_log_.Append(base::StringPrintf("SetPromotable(%d)", promotable)); DCHECK(waiting_for_worker_); waiting_for_worker_ = false; promotable_ = promotable;
diff --git a/chrome/browser/banners/test_app_banner_manager_desktop.h b/chrome/browser/banners/test_app_banner_manager_desktop.h index b109aba..a9542661 100644 --- a/chrome/browser/banners/test_app_banner_manager_desktop.h +++ b/chrome/browser/banners/test_app_banner_manager_desktop.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_BANNERS_TEST_APP_BANNER_MANAGER_DESKTOP_H_ #define CHROME_BROWSER_BANNERS_TEST_APP_BANNER_MANAGER_DESKTOP_H_ +#include "base/values.h" #include "chrome/browser/banners/app_banner_manager_desktop.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -77,6 +78,7 @@ void OnFinished(); absl::optional<bool> installable_; + base::Value::List debug_log_; bool waiting_for_worker_; bool promotable_; base::OnceClosure tear_down_quit_closure_;
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd index c4de49b..7741559 100644 --- a/chrome/browser/browser_resources.grd +++ b/chrome/browser/browser_resources.grd
@@ -62,10 +62,6 @@ <include name="IDR_VIDEO_PLAYER_JS" file="resources\video_tutorials\video_player.js" type="BINDATA" /> </if> - <if expr="enable_supervised_users"> - <part file="resources/supervised_user_error_page_resources.grdp" /> - </if> - <if expr="enable_hangout_services_extension"> <!-- Hangout Services extension, included in Google Chrome builds only. --> <include name="IDR_HANGOUT_SERVICES_MANIFEST" file="resources\hangout_services\manifest.json" type="BINDATA" />
diff --git a/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc b/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc index 3e0ded92..7e29fdf4 100644 --- a/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc +++ b/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
@@ -394,9 +394,10 @@ auto page_content_annotations_service = std::make_unique<optimization_guide::PageContentAnnotationsService>( - "en-US", optimization_guide_model_providers_.at(profile).get(), - history_service, nullptr, nullptr, base::FilePath(), nullptr, - nullptr); + nullptr, "en-US", + optimization_guide_model_providers_.at(profile).get(), + history_service, nullptr, nullptr, nullptr, base::FilePath(), + nullptr, nullptr); page_content_annotations_service->OverridePageContentAnnotatorForTesting( &test_page_content_annotator_);
diff --git a/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc b/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc index eab36be9..003dd89 100644 --- a/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc +++ b/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
@@ -367,9 +367,10 @@ auto page_content_annotations_service = std::make_unique<optimization_guide::PageContentAnnotationsService>( - "en-US", optimization_guide_model_providers_.at(profile).get(), - history_service, nullptr, nullptr, base::FilePath(), nullptr, - nullptr); + nullptr, "en-US", + optimization_guide_model_providers_.at(profile).get(), + history_service, nullptr, nullptr, nullptr, base::FilePath(), + nullptr, nullptr); page_content_annotations_service->OverridePageContentAnnotatorForTesting( &test_page_content_annotator_);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 3d4e42d..4755474c 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -176,7 +176,6 @@ "//chrome/browser/resources/chromeos:app_icon_resources", "//chrome/browser/resources/chromeos/cloud_upload:resources_grit", "//chrome/browser/resources/settings:resources_grit", - "//chrome/browser/supervised_user/supervised_user_features", "//chrome/browser/ui/ash/system_web_apps", "//chrome/browser/ui/webui/ash/crostini_upgrader:mojo_bindings", "//chrome/browser/ui/webui/bluetooth_internals:mojo_bindings", @@ -467,6 +466,7 @@ "//components/spellcheck/common:spellcheck_result", "//components/storage_monitor", "//components/strings", + "//components/supervised_user/core/common", "//components/sync", "//components/sync_device_info", "//components/sync_preferences",
diff --git a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc index 2bdd7e7..b0d88480 100644 --- a/chrome/browser/devtools/chrome_devtools_manager_delegate.cc +++ b/chrome/browser/devtools/chrome_devtools_manager_delegate.cc
@@ -60,16 +60,17 @@ bool GetExtensionInfo(content::WebContents* wc, std::string* name, std::string* type) { - Profile* profile = Profile::FromBrowserContext(wc->GetBrowserContext()); - if (!profile) + auto* process_manager = + extensions::ProcessManager::Get(wc->GetBrowserContext()); + if (!process_manager) { return false; + } const extensions::Extension* extension = - extensions::ProcessManager::Get(profile)->GetExtensionForWebContents(wc); + process_manager->GetExtensionForWebContents(wc); if (!extension) return false; extensions::ExtensionHost* extension_host = - extensions::ProcessManager::Get(profile)->GetBackgroundHostForExtension( - extension->id()); + process_manager->GetBackgroundHostForExtension(extension->id()); if (extension_host && extension_host->host_contents() == wc) { *name = extension->name(); *type = ChromeDevToolsManagerDelegate::kTypeBackgroundPage; @@ -166,8 +167,11 @@ content::RenderFrameHost* rfh) { Profile* profile = Profile::FromBrowserContext(rfh->GetProcess()->GetBrowserContext()); - return AllowInspection(profile, extensions::ProcessManager::Get(profile) - ->GetExtensionForRenderFrameHost(rfh)); + auto* process_manager = extensions::ProcessManager::Get(profile); + return AllowInspection( + profile, process_manager + ? process_manager->GetExtensionForRenderFrameHost(rfh) + : nullptr); } // static @@ -176,10 +180,10 @@ content::WebContents* web_contents) { const extensions::Extension* extension = nullptr; if (web_contents) { - extension = - extensions::ProcessManager::Get( - Profile::FromBrowserContext(web_contents->GetBrowserContext())) - ->GetExtensionForWebContents(web_contents); + if (auto* process_manager = extensions::ProcessManager::Get( + web_contents->GetBrowserContext())) { + extension = process_manager->GetExtensionForWebContents(web_contents); + } } return AllowInspection(profile, extension); }
diff --git a/chrome/browser/dips/dips_bounce_detector.h b/chrome/browser/dips/dips_bounce_detector.h index 2798605..067ec05 100644 --- a/chrome/browser/dips/dips_bounce_detector.h +++ b/chrome/browser/dips/dips_bounce_detector.h
@@ -13,6 +13,7 @@ #include "base/memory/raw_ptr.h" #include "chrome/browser/dips/cookie_access_filter.h" #include "chrome/browser/dips/dips_redirect_info.h" +#include "chrome/browser/dips/dips_service.h" #include "chrome/browser/dips/dips_utils.h" #include "content/public/browser/cookie_access_details.h" #include "content/public/browser/navigation_handle.h" @@ -27,8 +28,6 @@ class TickClock; } // namespace base -class DIPSService; - // ClientBounceDetectionState is owned by the DIPSBounceDetector and stores // data needed to detect stateful client-side redirects. class ClientBounceDetectionState { @@ -208,6 +207,10 @@ void SetClockForTesting(base::Clock* clock) { detector_.SetClockForTesting(clock); + DCHECK(dips_service_); + dips_service_->storage() + ->AsyncCall(&DIPSStorage::SetClockForTesting) + .WithArgs(clock); } private:
diff --git a/chrome/browser/dips/dips_database.cc b/chrome/browser/dips/dips_database.cc index f3840da..079167d 100644 --- a/chrome/browser/dips/dips_database.cc +++ b/chrome/browser/dips/dips_database.cc
@@ -16,6 +16,7 @@ #include "base/strings/strcat.h" #include "base/threading/thread_restrictions.h" #include "base/time/time.h" +#include "chrome/browser/dips/dips_features.h" #include "chrome/browser/dips/dips_utils.h" #include "sql/database.h" #include "sql/error_delegate_util.h" @@ -43,8 +44,6 @@ // See comments at declaration of these variables in dips_database.h // for details. - -const base::TimeDelta DIPSDatabase::kMaxAge = base::Days(180); const base::TimeDelta DIPSDatabase::kMetricsInterval = base::Hours(24); DIPSDatabase::DIPSDatabase(const absl::optional<base::FilePath>& db_path) @@ -53,6 +52,7 @@ sql::DatabaseOptions{.exclusive_locking = true, .page_size = 4096, .cache_size = 32})) { + DCHECK(base::FeatureList::IsEnabled(dips::kFeature)); base::AssertLongCPUWorkAllowed(); if (db_path.has_value()) { DCHECK(!db_path->empty()) @@ -178,13 +178,13 @@ base::UmaHistogramExactLinear("Privacy.DIPS.DatabaseInit", attempts, 3); - last_health_metrics_time_ = base::Time::Now(); + last_health_metrics_time_ = clock_->Now(); ComputeDatabaseMetrics(); return status; } -void DIPSDatabase::ComputeDatabaseMetrics() const { +void DIPSDatabase::ComputeDatabaseMetrics() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); base::TimeTicks start_time = base::TimeTicks::Now(); @@ -200,14 +200,14 @@ base::TimeTicks::Now() - start_time); } -bool DIPSDatabase::CheckDBInit() const { +bool DIPSDatabase::CheckDBInit() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!db_ || !db_->is_open()) return false; // Computing these metrics may be costly, so we only do it every // |kMetricsInterval|. - base::Time now = base::Time::Now(); + base::Time now = clock_->Now(); if (now > last_health_metrics_time_ + kMetricsInterval) { last_health_metrics_time_ = now; ComputeDatabaseMetrics(); @@ -278,6 +278,15 @@ if (!statement.Step()) { return absl::nullopt; } + // If the last interaction has expired, treat this entry as not in the + // database so that callers rewrite the entry for `site` as if it was deleted. + absl::optional<base::Time> last_user_interaction = + ToOptionalTime(statement.ColumnTime(4)); + if (last_user_interaction.has_value() && + last_user_interaction.value() + dips::kInteractionTtl.Get() < + clock_->Now()) { + return absl::nullopt; + } return StateValue{TimestampRange{ToOptionalTime(statement.ColumnTime(1)), ToOptionalTime(statement.ColumnTime(2))}, @@ -289,7 +298,7 @@ ToOptionalTime(statement.ColumnTime(8))}}; } -std::vector<std::string> DIPSDatabase::GetAllSitesForTesting() const { +std::vector<std::string> DIPSDatabase::GetAllSitesForTesting() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return {}; @@ -310,12 +319,12 @@ std::vector<std::string> DIPSDatabase::GetSitesThatBounced( base::Time range_start, - base::Time last_interaction) const { + base::Time last_interaction) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return {}; + ClearRowsWithExpiredInteractions(); - DCHECK(last_interaction < range_start); static constexpr char kReadSql[] = // clang-format off "SELECT site FROM bounces " "WHERE (last_stateful_bounce_time > ? " @@ -341,12 +350,12 @@ std::vector<std::string> DIPSDatabase::GetSitesThatBouncedWithState( base::Time range_start, - base::Time last_interaction) const { + base::Time last_interaction) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return {}; + ClearRowsWithExpiredInteractions(); - DCHECK(last_interaction < range_start); static constexpr char kReadSql[] = // clang-format off "SELECT site FROM bounces " "WHERE last_stateful_bounce_time > ? AND " @@ -371,12 +380,12 @@ std::vector<std::string> DIPSDatabase::GetSitesThatUsedStorage( base::Time range_start, - base::Time last_interaction) const { + base::Time last_interaction) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return {}; + ClearRowsWithExpiredInteractions(); - DCHECK(last_interaction < range_start); static constexpr char kReadSql[] = // clang-format off "SELECT site FROM bounces " "WHERE (last_site_storage_time > ? OR " @@ -399,10 +408,34 @@ return sites; } +size_t DIPSDatabase::ClearRowsWithExpiredInteractions() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(clock_); + if (!CheckDBInit()) { + return false; + } + + static constexpr char kClearAllExpiredSql[] = + "DELETE FROM bounces WHERE last_user_interaction_time < ? AND " + "last_user_interaction_time > 0"; + + DCHECK(db_->IsSQLValid(kClearAllExpiredSql)); + sql::Statement statement( + db_->GetCachedStatement(SQL_FROM_HERE, kClearAllExpiredSql)); + + statement.BindTime(0, clock_->Now() - dips::kInteractionTtl.Get()); + if (!statement.Run()) { + return 0; + } + + return db_->GetLastChangeCount(); +} + bool DIPSDatabase::RemoveRow(const std::string& site) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return false; + ClearRowsWithExpiredInteractions(); static constexpr char kRemoveSql[] = "DELETE FROM bounces WHERE site=?"; DCHECK(db_->IsSQLValid(kRemoveSql)); @@ -440,6 +473,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return false; + ClearRowsWithExpiredInteractions(); sql::Transaction transaction(db_.get()); if (!transaction.Begin()) @@ -482,6 +516,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return false; + ClearRowsWithExpiredInteractions(); if (type == DIPSEventRemovalType::kAll) { static constexpr char kAllTypesSql[] = // clang-format off @@ -624,6 +659,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return false; + ClearRowsWithExpiredInteractions(); if ((type & DIPSEventRemovalType::kHistory) == DIPSEventRemovalType::kHistory) { @@ -700,6 +736,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return false; + ClearRowsWithExpiredInteractions(); if ((type & DIPSEventRemovalType::kHistory) == DIPSEventRemovalType::kHistory) { @@ -824,10 +861,11 @@ return s_clean.Run(); } -size_t DIPSDatabase::GetEntryCount() const { +size_t DIPSDatabase::GetEntryCount() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit()) return 0; + ClearRowsWithExpiredInteractions(); sql::Statement s_entry_count( db_->GetCachedStatement(SQL_FROM_HERE, "SELECT COUNT(*) FROM bounces")); @@ -847,7 +885,6 @@ return 0; DCHECK_GT(purge_goal, 0); - num_deleted += GarbageCollectExpired(); // If expiration did not purge enough entries, remove entries with the oldest // |MAX(last_user_interaction_time,last_site_storage_time)| values until the @@ -859,29 +896,6 @@ return num_deleted; } -size_t DIPSDatabase::GarbageCollectExpired() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (!CheckDBInit()) - return 0; - - base::Time safe_date(base::Time::Now() - kMaxAge); - - static constexpr char kExpireByInteractionSql[] = // clang-format off - "DELETE FROM bounces WHERE last_user_interaction_time<? AND " - "last_user_interaction_time>0"; - // clang-format on - DCHECK(db_->IsSQLValid(kExpireByInteractionSql)); - - sql::Statement s_expire_by_interaction( - db_->GetCachedStatement(SQL_FROM_HERE, kExpireByInteractionSql)); - s_expire_by_interaction.BindTime(0, safe_date); - - if (!s_expire_by_interaction.Run()) - return 0; - - return db_->GetLastChangeCount(); -} - size_t DIPSDatabase::GarbageCollectOldest(int purge_goal) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!CheckDBInit())
diff --git a/chrome/browser/dips/dips_database.h b/chrome/browser/dips/dips_database.h index 2904f0a..e49590c 100644 --- a/chrome/browser/dips/dips_database.h +++ b/chrome/browser/dips/dips_database.h
@@ -10,6 +10,8 @@ #include <string> #include <vector> +#include "base/time/clock.h" +#include "base/time/default_clock.h" #include "chrome/browser/dips/dips_utils.h" #include "sql/database.h" #include "sql/init_status.h" @@ -21,13 +23,6 @@ // Encapsulates an SQL database that holds DIPS info. class DIPSDatabase { public: - // The length of time since last user interaction or site storage that a - // site's entry will not be subject to garbage collection due to expiration. - // However, even with interaction or storage within this period, if there are - // more than |max_entries_| entries, an entry can still be deleted by - // |GarbageCollectOldest()|. - static const base::TimeDelta kMaxAge; - // The length of time that will be waited between emitting db health metrics. static const base::TimeDelta kMetricsInterval; @@ -52,31 +47,38 @@ absl::optional<StateValue> Read(const std::string& site); - std::vector<std::string> GetAllSitesForTesting() const; + // Note: this doesn't clear expired interactions from the database unlike the + // other database querying methods. + std::vector<std::string> GetAllSitesForTesting(); // Returns all sites that did a bounce after |range_start| with their last // interaction happening before |last_interaction|. - // - // Note: |last_interaction| must be earlier than |range_start|. - std::vector<std::string> GetSitesThatBounced( - base::Time range_start, - base::Time last_interaction) const; + std::vector<std::string> GetSitesThatBounced(base::Time range_start, + base::Time last_interaction); // Returns all sites that did a stateful bounce after |range_start| with their // last interaction happening before |last_interaction|. - // - // Note: |last_interaction| must be earlier than |range_start|. std::vector<std::string> GetSitesThatBouncedWithState( base::Time range_start, - base::Time last_interaction) const; + base::Time last_interaction); // Returns all sites that wrote to storage after |range_start| with their last // interaction happening before |last_interaction|. + std::vector<std::string> GetSitesThatUsedStorage(base::Time range_start, + base::Time last_interaction); + + // Deletes all rows in the database whose interactions have expired out. // - // Note: |last_interaction| must be earlier than |range_start|. - std::vector<std::string> GetSitesThatUsedStorage( - base::Time range_start, - base::Time last_interaction) const; + // When an interaction happens before a DIPS-triggering action or during the + // following grace-period it protects that site from its data being cleared + // by DIPS. Further interactions will prolong that protection until the last + // one reaches the `interaction_ttl`. + // + // Clearing expired interactions effectively restarts the DIPS procedure for + // determining if a site is a tracker for sites that are cleared. + // + // Returns the number of rows that are removed. + size_t ClearRowsWithExpiredInteractions(); // Delete the row from the bounces table for `site`. Returns true if query // executes successfully. @@ -95,17 +97,13 @@ const DIPSEventRemovalType type); // Returns the number of entries present in the database. - size_t GetEntryCount() const; + size_t GetEntryCount(); // If the number of entries in the database is greater than // |GetMaxEntries()|, garbage collect. Returns the number of entries deleted // (useful for debugging). size_t GarbageCollect(); - // Removes entries for sites without user interaction within |kMaxAge|. - // Returns the number of entries deleted. - size_t GarbageCollectExpired(); - // Removes the |purge_goal| entries with the oldest // |MAX(last_user_interaction_time,last_site_storage_time)| value. Returns the // number of entries deleted. @@ -117,13 +115,14 @@ } // Checks that the internal SQLite database is initialized. - bool CheckDBInit() const; + bool CheckDBInit(); size_t GetMaxEntries() const { return max_entries_; } size_t GetPurgeEntries() const { return purge_entries_; } void SetMaxEntriesForTesting(size_t entries) { max_entries_ = entries; } void SetPurgeEntriesForTesting(size_t entries) { purge_entries_ = entries; } + void SetClockForTesting(base::Clock* clock) { clock_ = clock; } protected: // Initialization functions -------------------------------------------------- @@ -148,7 +147,7 @@ const DIPSEventRemovalType type); bool RemoveEmptyRows(); - void ComputeDatabaseMetrics() const; + void ComputeDatabaseMetrics(); private: // Callback for database errors. @@ -160,6 +159,7 @@ size_t purge_entries_ = 300; const base::FilePath db_path_ GUARDED_BY_CONTEXT(sequence_checker_); std::unique_ptr<sql::Database> db_ GUARDED_BY_CONTEXT(sequence_checker_); + raw_ptr<base::Clock> clock_ = base::DefaultClock::GetInstance(); mutable base::Time last_health_metrics_time_ GUARDED_BY_CONTEXT(sequence_checker_) = base::Time::Min(); SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/dips/dips_database_unittest.cc b/chrome/browser/dips/dips_database_unittest.cc index 1fccc5a..39bd8e2b 100644 --- a/chrome/browser/dips/dips_database_unittest.cc +++ b/chrome/browser/dips/dips_database_unittest.cc
@@ -5,14 +5,17 @@ #include <optional> #include <string> +#include "base/strings/stringprintf.h" #include "base/time/time.h" #include "chrome/browser/dips/dips_database.h" #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" #include "base/strings/strcat.h" -#include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/simple_test_clock.h" +#include "chrome/browser/dips/dips_features.h" #include "chrome/browser/dips/dips_utils.h" #include "sql/sqlite_result_code_values.h" #include "sql/test/scoped_error_expecter.h" @@ -45,9 +48,11 @@ explicit DIPSDatabaseTest(bool in_memory) : in_memory_(in_memory) {} protected: + base::SimpleTestClock clock_; std::unique_ptr<TestDatabase> db_; base::ScopedTempDir temp_dir_; base::FilePath db_path_; + base::test::ScopedFeatureList features_; // Test setup. void SetUp() override { if (in_memory_) { @@ -59,6 +64,7 @@ } ASSERT_TRUE(db_->CheckDBInit()); + db_->SetClockForTesting(clock()); } void TearDown() override { @@ -69,6 +75,16 @@ ASSERT_TRUE(temp_dir_.Delete()); } + base::Time Now() { return clock_.Now(); } + + void AdvanceTimeTo(base::Time now) { + ASSERT_GE(now, clock_.Now()); + clock_.SetNow(now); + } + void AdvanceTimeBy(base::TimeDelta delta) { clock_.Advance(delta); } + + base::Clock* clock() { return &clock_; } + private: bool in_memory_; }; @@ -84,6 +100,13 @@ : DIPSDatabaseTest(std::get<0>(GetParam())), column_(std::get<1>(GetParam())) {} + void SetUp() override { + DIPSDatabaseTest::SetUp(); + // Use inf ttl to prevent interactions from expiring unintentionally. + features_.InitAndEnableFeatureWithParameters(dips::kFeature, + {{"interaction_ttl", "inf"}}); + } + protected: // Uses `times` to write to the first and last columns for `column_` in the // `site` row in `db`. This also writes the empty time stamps to all other @@ -203,6 +226,99 @@ ColumnType::kStatefulBounce, ColumnType::kStatelessBounce))); +// A test class that verifies the behavior DIPSDatabase with respect to +// interactions. +// +// Parameterized over whether the db is in memory. +class DIPSDatabaseInteractionTest : public DIPSDatabaseTest, + public testing::WithParamInterface<bool> { + public: + DIPSDatabaseInteractionTest() : DIPSDatabaseTest(GetParam()) {} + + void SetUp() override { + DIPSDatabaseTest::SetUp(); + DCHECK(db_); + db_->Write("storage-only.test", storage_times, + {interaction_for_storage, interaction_for_storage}, + /*stateful_bounce_times=*/{}, /*stateless_bounce_times=*/{}); + db_->Write( + "stateful-bounce.test", stateful_bounce_times, + {interaction_for_stateful_bounce, interaction_for_stateful_bounce}, + stateful_bounce_times, + /*stateless_bounce_times=*/{}); + db_->Write( + "stateless-bounce.test", + /*storage_times=*/{}, + {interaction_for_stateless_bounce, interaction_for_stateless_bounce}, + /*stateful_bounce_times=*/{}, stateless_bounce_times); + } + + protected: + // Used to simulate just before/after another timestamp. + base::TimeDelta tiny_delta = base::Milliseconds(1); + + base::Time storage = Time::FromDoubleT(1); + base::Time interaction_for_storage = Time::FromDoubleT(2); + + base::Time stateful_bounce = Time::FromDoubleT(3); + base::Time interaction_for_stateful_bounce = Time::FromDoubleT(5); + + base::Time stateless_bounce = Time::FromDoubleT(6); + base::Time interaction_for_stateless_bounce = Time::FromDoubleT(9); + + TimestampRange storage_times = {storage, storage}; + TimestampRange stateful_bounce_times = {stateful_bounce, stateful_bounce}; + TimestampRange stateless_bounce_times = {stateless_bounce, stateless_bounce}; +}; + +TEST_P(DIPSDatabaseInteractionTest, ClearExpiredInteractions) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeatureWithParameters(dips::kFeature, + {{"interaction_ttl", "3s"}}); + + base::TimeDelta interaction_ttl = dips::kInteractionTtl.Get(); + + ASSERT_EQ(interaction_ttl, base::Seconds(3)); + + EXPECT_THAT( + db_->GetAllSitesForTesting(), + testing::ElementsAre("stateful-bounce.test", "stateless-bounce.test", + "storage-only.test")); + AdvanceTimeTo(interaction_for_storage + interaction_ttl + tiny_delta); + EXPECT_EQ(db_->ClearRowsWithExpiredInteractions(), 1u); + EXPECT_THAT( + db_->GetAllSitesForTesting(), + testing::ElementsAre("stateful-bounce.test", "stateless-bounce.test")); + + AdvanceTimeTo(interaction_for_stateful_bounce + interaction_ttl + tiny_delta); + EXPECT_EQ(db_->ClearRowsWithExpiredInteractions(), 1u); + EXPECT_THAT(db_->GetAllSitesForTesting(), + testing::ElementsAre("stateless-bounce.test")); + + AdvanceTimeTo(interaction_for_stateless_bounce + interaction_ttl + + tiny_delta); + EXPECT_EQ(db_->ClearRowsWithExpiredInteractions(), 1u); + EXPECT_THAT(db_->GetAllSitesForTesting(), testing::IsEmpty()); +} + +TEST_P(DIPSDatabaseInteractionTest, ReadWithExpiredInteractions) { + base::test::ScopedFeatureList features; + features.InitAndEnableFeatureWithParameters(dips::kFeature, + {{"interaction_ttl", "10s"}}); + + EXPECT_TRUE(db_->Read("storage-only.test").has_value()); + EXPECT_TRUE(db_->Read("stateful-bounce.test").has_value()); + EXPECT_TRUE(db_->Read("stateless-bounce.test").has_value()); + + // Time travel to a point by which all interactions should've expired. + AdvanceTimeTo(Time::FromDoubleT(100)); + EXPECT_EQ(db_->Read("storage-only.test"), absl::nullopt); + EXPECT_EQ(db_->Read("stateful-bounce.test"), absl::nullopt); + EXPECT_EQ(db_->Read("stateless-bounce.test"), absl::nullopt); +} + +INSTANTIATE_TEST_SUITE_P(All, DIPSDatabaseInteractionTest, ::testing::Bool()); + // A test class that verifies the behavior of the methods used to query the // DIPSDatabase for information more efficiently than using DIPSDatabase::Read. // @@ -214,7 +330,9 @@ void SetUp() override { DIPSDatabaseTest::SetUp(); - + // Use inf ttl to prevent interactions from expiring unintentionally. + features_.InitAndEnableFeatureWithParameters(dips::kFeature, + {{"interaction_ttl", "inf"}}); DCHECK(db_); // Add entries to the database filling in the columns we want to test. // These test entries correspond with the following cases: @@ -222,12 +340,12 @@ // - a site redirects the user while accessing storage // - a site redirects the user (without regard to storage access) // All of these entries include a user interaction. - db_->Write("https://storage-only.test", storage_times, interaction_times, + db_->Write("storage-only.test", storage_times, interaction_times, /*stateful_bounce_times=*/{}, /*stateless_bounce_times=*/{}); - db_->Write("https://stateful-bounce.test", storage_times, interaction_times, + db_->Write("stateful-bounce.test", storage_times, interaction_times, stateful_bounce_times, /*stateless_bounce_times=*/{}); - db_->Write("https://stateless-bounce.test", + db_->Write("stateless-bounce.test", /*storage_times=*/{}, interaction_times, /*stateful_bounce_times=*/{}, stateless_bounce_times); } @@ -235,13 +353,13 @@ protected: // Rewrites the entries that were wrote in SetUp() to not have interactions. void ClearAllInteractions() { - db_->Write("https://storage-only.test", storage_times, + db_->Write("storage-only.test", storage_times, /*interaction_times=*/{}, /*stateful_bounce_times=*/{}, /*stateless_bounce_times=*/{}); - db_->Write("https://stateful-bounce.test", storage_times, + db_->Write("stateful-bounce.test", storage_times, /*interaction_times=*/{}, stateful_bounce_times, /*stateless_bounce_times=*/{}); - db_->Write("https://stateless-bounce.test", + db_->Write("stateless-bounce.test", /*storage_times=*/{}, /*interaction_times=*/{}, /*stateful_bounce_times=*/{}, stateless_bounce_times); } @@ -278,28 +396,6 @@ testing::IsEmpty()); } -TEST_P(DIPSDatabaseQueryTest, EnsureLastInteractionStrictlyBeforeRangeStart) { - // Verify that the |last_interaction| shouldn't be greater than |range_start| - // for each query method. - base::Time range_start = Time::FromDoubleT(0); - base::Time last_interaction = Time::FromDoubleT(1); - - EXPECT_DCHECK_DEATH(db_->GetSitesThatBounced(range_start, last_interaction)); - EXPECT_DCHECK_DEATH( - db_->GetSitesThatBouncedWithState(range_start, last_interaction)); - EXPECT_DCHECK_DEATH( - db_->GetSitesThatUsedStorage(range_start, last_interaction)); - - // Verify that the |last_interaction| should be strictly less than - // |range_start| for each query method. - EXPECT_DCHECK_DEATH( - db_->GetSitesThatBounced(range_start, /*last_interaction=*/range_start)); - EXPECT_DCHECK_DEATH(db_->GetSitesThatBouncedWithState( - range_start, /*last_interaction=*/range_start)); - EXPECT_DCHECK_DEATH(db_->GetSitesThatUsedStorage( - range_start, /*last_interaction=*/range_start)); -} - TEST_P(DIPSDatabaseQueryTest, GetSitesThatBounced_InteractionTest) { // All queries should be for the entire range (range_start > before_storage) // so that we can test the behavior of this method for different values of @@ -318,20 +414,20 @@ // When the last_interaction bound is `after_interaction`, both sites that // bounced are returned since they had user interaction before it. - EXPECT_THAT(db_->GetSitesThatBounced(earliest_range_start, after_interaction), - testing::ElementsAre("https://stateful-bounce.test", - "https://stateless-bounce.test")); + EXPECT_THAT( + db_->GetSitesThatBounced(earliest_range_start, after_interaction), + testing::ElementsAre("stateful-bounce.test", "stateless-bounce.test")); } TEST_P(DIPSDatabaseQueryTest, GetSitesThatBounced_RangeStartTest) { - EXPECT_THAT(db_->GetSitesThatBounced(before_storage, after_interaction), - testing::ElementsAre("https://stateful-bounce.test", - "https://stateless-bounce.test")); + EXPECT_THAT( + db_->GetSitesThatBounced(before_storage, after_interaction), + testing::ElementsAre("stateful-bounce.test", "stateless-bounce.test")); // When the range begins after the stateful bounce happened, // "stateless-bounce.test" is returned since it bounces later. EXPECT_THAT( db_->GetSitesThatBounced(after_stateful_bounce, after_interaction), - testing::ElementsAre("https://stateless-bounce.test")); + testing::ElementsAre("stateless-bounce.test")); // When the range begins after the stateless bounce happened, neither are // returned since both sites bounced before this. EXPECT_THAT( @@ -360,13 +456,13 @@ // did a stateful bounce is returned since it had user interaction before it. EXPECT_THAT(db_->GetSitesThatBouncedWithState(earliest_range_start, after_interaction), - testing::ElementsAre("https://stateful-bounce.test")); + testing::ElementsAre("stateful-bounce.test")); } TEST_P(DIPSDatabaseQueryTest, GetSitesThatBouncedWithState_RangeStartTest) { EXPECT_THAT( db_->GetSitesThatBouncedWithState(before_storage, after_interaction), - testing::ElementsAre("https://stateful-bounce.test")); + testing::ElementsAre("stateful-bounce.test")); // When the range begins after the stateful bounce happened, no other sites // are returned (since no other site did a stateful bounce after this time). EXPECT_THAT(db_->GetSitesThatBouncedWithState(after_stateful_bounce, @@ -394,20 +490,19 @@ // used storage are returned since they had user interaction before it. EXPECT_THAT( db_->GetSitesThatUsedStorage(earliest_range_start, after_interaction), - testing::ElementsAre("https://stateful-bounce.test", - "https://storage-only.test")); + testing::ElementsAre("stateful-bounce.test", "storage-only.test")); } TEST_P(DIPSDatabaseQueryTest, GetSitesThatUsedStorage_RangeStartTest) { // When the range begins at 0, both sites that used storage are returned since // they did so after t=0. - EXPECT_THAT(db_->GetSitesThatUsedStorage(before_storage, after_interaction), - testing::ElementsAre("https://stateful-bounce.test", - "https://storage-only.test")); + EXPECT_THAT( + db_->GetSitesThatUsedStorage(before_storage, after_interaction), + testing::ElementsAre("stateful-bounce.test", "storage-only.test")); // When the range begins after "storage-only.test" used storage, only // "stateful_bounce.test" is returned since it uses storage later. EXPECT_THAT(db_->GetSitesThatUsedStorage(after_storage, after_interaction), - testing::ElementsAre("https://stateful-bounce.test")); + testing::ElementsAre("stateful-bounce.test")); // When the range begins after the stateful bounce happened, no other sites // are returned (since no other site used storage after this time). EXPECT_THAT( @@ -426,14 +521,19 @@ void SetUp() override { DIPSDatabaseTest::SetUp(); + features_.InitAndEnableFeatureWithParameters( + dips::kFeature, + {{"interaction_ttl", + base::StringPrintf("%dh", base::Days(180).InHours())}}); + ASSERT_EQ(dips::kInteractionTtl.Get(), base::Days(180)); DCHECK(db_); - db_->SetMaxEntriesForTesting(200); db_->SetPurgeEntriesForTesting(20); + clock_.Advance(dips::kInteractionTtl.Get()); - recent_interaction = Time::Now(); - old_interaction = Time::Now() - DIPSDatabase::kMaxAge - base::Days(1); + recent_interaction = Now(); + old_interaction = Now() - dips::kInteractionTtl.Get() - base::Days(1); recent_interaction_times = {recent_interaction, recent_interaction}; old_interaction_times = {old_interaction, old_interaction}; @@ -443,20 +543,21 @@ DCHECK(db_); for (int i = 0; i < num_recent_entries; i++) { - db_->Write(base::StrCat({"https://recent_interaction.test", - base::NumberToString(i)}), - storage_times, recent_interaction_times, stateful_bounce_times, - stateless_bounce_times); + db_->Write( + base::StrCat({"recent_interaction.test", base::NumberToString(i)}), + storage_times, recent_interaction_times, stateful_bounce_times, + stateless_bounce_times); } for (int i = 0; i < num_old_entries; i++) { - db_->Write(base::StrCat( - {"https://old_interaction.test", base::NumberToString(i)}), - storage_times, old_interaction_times, stateful_bounce_times, - stateless_bounce_times); + db_->Write( + base::StrCat({"old_interaction.test", base::NumberToString(i)}), + storage_times, old_interaction_times, stateful_bounce_times, + stateless_bounce_times); } } + protected: base::Time recent_interaction; base::Time old_interaction; base::Time storage = Time::FromDoubleT(2); @@ -508,40 +609,28 @@ EXPECT_EQ(db_->GetEntryCount(), db_->GetMaxEntries()); } -// More than |max_entries_| entries with recent user interaction and a few with -// expired user interaction; only entries with expired user interaction should -// be garbage collected by pure expiration. -TEST_P(DIPSDatabaseGarbageCollectionTest, ExpirationPreservesRecent) { - BloatBouncesForGC(/*num_recent_entries=*/db_->GetMaxEntries() * 2, - /*num_old_entries=*/db_->GetMaxEntries() / 2); - - EXPECT_EQ(db_->GarbageCollectExpired(), db_->GetMaxEntries() / 2); - - EXPECT_EQ(db_->GetEntryCount(), db_->GetMaxEntries() * 2); -} - // The entries with the oldest interaction and storage times should be deleted // first. TEST_P(DIPSDatabaseGarbageCollectionTest, OldestEntriesRemoved) { - db_->Write("https://old_interaction.test", {}, + db_->Write("old_interaction.test", {}, /*interaction_times=*/{Time::FromDoubleT(1), Time::FromDoubleT(1)}, {}, {}); - db_->Write("https://old_storage_old_interaction.test", + db_->Write("old_storage_old_interaction.test", /*storage_times=*/{Time::FromDoubleT(1), Time::FromDoubleT(1)}, /*interaction_times=*/{Time::FromDoubleT(2), Time::FromDoubleT(2)}, {}, {}); - db_->Write("https://old_storage.test", + db_->Write("old_storage.test", /*storage_times=*/{Time::FromDoubleT(3), Time::FromDoubleT(3)}, {}, {}, {}); - db_->Write("https://old_storage_new_interaction.test", + db_->Write("old_storage_new_interaction.test", /*storage_times=*/{Time::FromDoubleT(1), Time::FromDoubleT(1)}, /*interaction_times=*/{Time::FromDoubleT(4), Time::FromDoubleT(4)}, {}, {}); - db_->Write("https://new_storage_old_interaction.test", + db_->Write("new_storage_old_interaction.test", /*storage_times=*/{Time::FromDoubleT(5), Time::FromDoubleT(5)}, /*interaction_times=*/{Time::FromDoubleT(2), Time::FromDoubleT(2)}, {}, {}); - db_->Write("https://new_storage_new_interaction.test", + db_->Write("new_storage_new_interaction.test", /*storage_times=*/{Time::FromDoubleT(6), Time::FromDoubleT(6)}, /*interaction_times=*/{Time::FromDoubleT(7), Time::FromDoubleT(7)}, {}, {}); @@ -550,9 +639,9 @@ EXPECT_EQ(db_->GetEntryCount(), static_cast<size_t>(3)); EXPECT_THAT(db_->GetAllSitesForTesting(), - testing::ElementsAre("https://new_storage_new_interaction.test", - "https://new_storage_old_interaction.test", - "https://old_storage_new_interaction.test")); + testing::ElementsAre("new_storage_new_interaction.test", + "new_storage_old_interaction.test", + "old_storage_new_interaction.test")); } INSTANTIATE_TEST_SUITE_P(All, @@ -565,6 +654,12 @@ public: DIPSDatabaseHistogramTest() : DIPSDatabaseTest(false) {} + void SetUp() override { + DIPSDatabaseTest::SetUp(); + features_.InitAndEnableFeatureWithParameters(dips::kFeature, + {{"interaction_ttl", "inf"}}); + } + const base::HistogramTester& histograms() const { return histogram_tester_; } protected: @@ -586,7 +681,7 @@ histograms().ExpectUniqueSample("Privacy.DIPS.DatabaseEntryCount", 0, 1); // Write an entry to the db. - db_->Write("https://url1.test", {}, + db_->Write("url1.test", {}, /*interaction_times=*/{Time::FromDoubleT(1), Time::FromDoubleT(1)}, {}, {}); db_->ComputeDatabaseMetricsForTesting(); @@ -612,7 +707,7 @@ histograms().ExpectUniqueSample("Privacy.DIPS.DatabaseInit", 1, 1); // Write an entry to the db. - db_->Write("https://url1.test", {}, + db_->Write("url1.test", {}, /*interaction_times=*/{Time::FromDoubleT(1), Time::FromDoubleT(1)}, {}, {}); EXPECT_EQ(db_->GetEntryCount(), static_cast<size_t>(1));
diff --git a/chrome/browser/dips/dips_features.cc b/chrome/browser/dips/dips_features.cc index 0fecc9b7..adce83a 100644 --- a/chrome/browser/dips/dips_features.cc +++ b/chrome/browser/dips/dips_features.cc
@@ -9,7 +9,9 @@ namespace dips { // Enables the DIPS (Detect Incidental Party State) feature. -BASE_FEATURE(kFeature, "DIPS", base::FEATURE_DISABLED_BY_DEFAULT); +// On by default to allow for collecting metrics. All potentially dangerous +// behavior (database persistence, DIPS deletion) will be gated by params. +BASE_FEATURE(kFeature, "DIPS", base::FEATURE_ENABLED_BY_DEFAULT); // Set whether DIPS persists its database to disk. const base::FeatureParam<bool> kPersistedDatabaseEnabled{ @@ -26,6 +28,15 @@ const base::FeatureParam<base::TimeDelta> kTimerDelay{&kFeature, "timer_delay", base::Hours(24)}; +// Set how long DIPS maintains an interaction for a site. +// +// If a site in the DIPS database has an interaction within the grace period a +// DIPS-triggering action, then that action and all ensuing actions are +// protected from DIPS clearing until the interaction "expires" as set by this +// param. +const base::FeatureParam<base::TimeDelta> kInteractionTtl{ + &kFeature, "interaction_ttl", base::Days(90)}; + // Sets the actions which will trigger DIPS clearing for a site. The default is // to set to kBounce, but can be overridden by Finch experiment groups or by // command-line flags.
diff --git a/chrome/browser/dips/dips_features.h b/chrome/browser/dips/dips_features.h index 951ef8c..eb371296 100644 --- a/chrome/browser/dips/dips_features.h +++ b/chrome/browser/dips/dips_features.h
@@ -16,6 +16,7 @@ extern const base::FeatureParam<bool> kPersistedDatabaseEnabled; extern const base::FeatureParam<base::TimeDelta> kGracePeriod; extern const base::FeatureParam<base::TimeDelta> kTimerDelay; +extern const base::FeatureParam<base::TimeDelta> kInteractionTtl; extern const base::FeatureParam<DIPSTriggeringAction> kTriggeringAction; } // namespace dips
diff --git a/chrome/browser/dips/dips_storage.h b/chrome/browser/dips/dips_storage.h index 859f5a26..eb8edb7b 100644 --- a/chrome/browser/dips/dips_storage.h +++ b/chrome/browser/dips/dips_storage.h
@@ -49,6 +49,10 @@ // Utility Methods ----------------------------------------------------------- static size_t SetPrepopulateChunkSizeForTesting(size_t size); + void SetClockForTesting(base::Clock* clock) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + db_->SetClockForTesting(clock); + } // For each site in |sites|, set the interaction and storage timestamps to // |time|. Note this may run asynchronously -- the DB is not guaranteed to be
diff --git a/chrome/browser/dips/dips_storage_unittest.cc b/chrome/browser/dips/dips_storage_unittest.cc index 5cb50f9..c2e42aa7 100644 --- a/chrome/browser/dips/dips_storage_unittest.cc +++ b/chrome/browser/dips/dips_storage_unittest.cc
@@ -5,10 +5,12 @@ #include "chrome/browser/dips/dips_storage.h" #include "base/functional/bind.h" +#include "base/metrics/field_trial_params.h" #include "base/task/thread_pool.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" -#include "base/test/test_future.h" #include "base/threading/sequence_bound.h" +#include "chrome/browser/dips/dips_features.h" #include "chrome/browser/dips/dips_state.h" #include "chrome/browser/dips/dips_utils.h" #include "content/public/browser/browsing_data_filter_builder.h" @@ -39,6 +41,17 @@ : absl::nullopt; } +class ScopedDIPSFeatureEnabledWithParams { + public: + explicit ScopedDIPSFeatureEnabledWithParams( + const base::FieldTrialParams& params) { + features_.InitAndEnableFeatureWithParameters(dips::kFeature, params); + } + + private: + base::test::ScopedFeatureList features_; +}; + } // namespace class DIPSStorageTest : public testing::Test { @@ -46,10 +59,9 @@ DIPSStorageTest() = default; protected: - TestStorage storage_; - - private: base::test::TaskEnvironment env_; + ScopedDIPSFeatureEnabledWithParams feature{{{"interaction_ttl", "inf"}}}; + TestStorage storage_; }; TEST(DirtyBit, Constructor) { @@ -494,6 +506,7 @@ protected: base::test::TaskEnvironment task_environment_; + ScopedDIPSFeatureEnabledWithParams feature{{{"interaction_ttl", "inf"}}}; base::SequenceBound<DIPSStorage> storage_; };
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc index d2b5bf59..9818f99f 100644 --- a/chrome/browser/extensions/extension_browsertest.cc +++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -663,14 +663,7 @@ // and then always pack the extension here. base::FilePath crx_path = path; if (crx_path.Extension() != FILE_PATH_LITERAL(".crx")) { - int run_flags = ExtensionCreator::kNoRunFlags; - if (creation_flags & Extension::FROM_BOOKMARK) { - run_flags = ExtensionCreator::kBookmarkApp; - if (install_source == ManifestLocation::kExternalComponent) - run_flags |= ExtensionCreator::kSystemApp; - } - - crx_path = PackExtension(path, run_flags); + crx_path = PackExtension(path, ExtensionCreator::kNoRunFlags); } if (crx_path.empty()) return nullptr;
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc index 296b14b..64051177 100644 --- a/chrome/browser/extensions/extension_service_unittest.cc +++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -6041,19 +6041,6 @@ EXPECT_EQ(0, visitor.Visit(json_data)); } - // Test is_bookmark_app. - MockProviderVisitor from_bookmark_visitor( - base_path, Extension::FROM_BOOKMARK); - json_data = - "{" - " \"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\": {" - " \"external_crx\": \"RandomExtension.crx\"," - " \"external_version\": \"1.0\"," - " \"is_bookmark_app\": true" - " }" - "}"; - EXPECT_EQ(1, from_bookmark_visitor.Visit(json_data)); - // Test is_from_webstore. MockProviderVisitor from_webstore_visitor( base_path, Extension::FROM_WEBSTORE);
diff --git a/chrome/browser/extensions/extension_sync_service.cc b/chrome/browser/extensions/extension_sync_service.cc index f931dc05..5d4c2cc 100644 --- a/chrome/browser/extensions/extension_sync_service.cc +++ b/chrome/browser/extensions/extension_sync_service.cc
@@ -180,24 +180,6 @@ } } - ExtensionRegistry* registry = ExtensionRegistry::Get(profile_); - std::unique_ptr<ExtensionSet> all_extensions = - registry->GenerateInstalledExtensionsSet(); - for (const auto& extension : *all_extensions) { - if (extension->from_deprecated_bookmark()) { - // Deleting deprecated bookmark apps. - const std::string& id = extension->id(); - std::u16string error; - bool uninstalled = extension_service()->UninstallExtension( - id, extensions::UNINSTALL_REASON_SYNC, &error); - if (!uninstalled) { - LOG(WARNING) << "Failed to uninstall bookmark apps with id '" << id - << "' : " << error; - } - base::UmaHistogramBoolean("Extensions.UninstallBookmarkApp", uninstalled); - } - } - // Now push the local state to sync. // Note: We'd like to only send out changes for extensions which have // NeedsSync set. However, we can't tell if our changes ever made it to the
diff --git a/chrome/browser/extensions/external_provider_impl.cc b/chrome/browser/extensions/external_provider_impl.cc index d1f471b..7d5d93f 100644 --- a/chrome/browser/extensions/external_provider_impl.cc +++ b/chrome/browser/extensions/external_provider_impl.cc
@@ -119,7 +119,6 @@ const char ExternalProviderImpl::kExternalCrx[] = "external_crx"; const char ExternalProviderImpl::kExternalVersion[] = "external_version"; const char ExternalProviderImpl::kExternalUpdateUrl[] = "external_update_url"; -const char ExternalProviderImpl::kIsBookmarkApp[] = "is_bookmark_app"; const char ExternalProviderImpl::kIsFromWebstore[] = "is_from_webstore"; const char ExternalProviderImpl::kKeepIfPresent[] = "keep_if_present"; const char ExternalProviderImpl::kWasInstalledByOem[] = "was_installed_by_oem"; @@ -376,11 +375,6 @@ } int creation_flags = creation_flags_; - absl::optional<bool> is_bookmark_app = - extension_dict.FindBool(kIsBookmarkApp); - if (is_bookmark_app.value_or(false)) { - creation_flags |= Extension::FROM_BOOKMARK; - } absl::optional<bool> is_from_webstore = extension_dict.FindBool(kIsFromWebstore); if (is_from_webstore.value_or(false)) {
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSwipeRefreshLayout.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSwipeRefreshLayout.java index 2262c50..b6c2794e 100644 --- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSwipeRefreshLayout.java +++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSwipeRefreshLayout.java
@@ -276,8 +276,7 @@ final float yDiff = y - mLastMotionY; if (yDiff > mTouchSlop && !mIsBeingDragged) { mIsBeingDragged = true; - // TODO(1335416): Update this to |true| if experiment is successful - start(false); + start(); } break; }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 274c5e0..589aaa6 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -574,6 +574,11 @@ "expiry_milestone": 107 }, { + "name": "autofill-remove-card-expiration-and-type-titles", + "owners": [ "qihuizhao@google.com", "jsaul@google.com" ], + "expiry_milestone": 120 + }, + { "name": "autofill-save-card-dismiss-on-navigation", "owners": [ "sczs", "bling-flags@google.com" ], "expiry_milestone": 82 @@ -1139,11 +1144,6 @@ "expiry_milestone": 114 }, { - "name": "cros-labs-float-window", - "owners": [ "shidi", "afakhry" ], - "expiry_milestone": 110 - }, - { "name": "cros-labs-overview-desk-navigation", "owners": [ "richui", "janetmac" ], "expiry_milestone": 122 @@ -3801,6 +3801,11 @@ "expiry_milestone": 111 }, { + "name": "float-window", + "owners": [ "shidi", "afakhry" ], + "expiry_milestone": 122 + }, + { "name": "focus-follows-cursor", "owners": [ "dandersson", "tclaiborne" ], "expiry_milestone": 120 @@ -5809,7 +5814,7 @@ { "name": "quick-gesture-show-launcher", "owners": [ "anasalazar", "//ash/shelf/OWNERS" ], - "expiry_milestone": 110 + "expiry_milestone": 115 }, { "name": "quick-intensive-throttling-after-loading",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 002982c..8ddb429a 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -487,6 +487,13 @@ "If enabled Autofill's popup becomes more prominent, i.e. its shadow " "becomes more emphasized, position is also updated"; +const char kAutofillRemoveCardExpirationAndTypeTitlesName[] = + "Remove expiration and type titles from Chrome Payment Settings page on " + "desktop"; +const char kAutofillRemoveCardExpirationAndTypeTitlesDescription[] = + "When enabled, expiration and type titles will be removed from the Chrome " + "Payment Settings page on desktop platforms."; + const char kAutofillUseConsistentPopupSettingsIconsName[] = "Consistent Autofill settings icon"; const char kAutofillUseConsistentPopupSettingsIconsDescription[] = @@ -5443,10 +5450,11 @@ const char kFilesTrashDescription[] = "Enable trash for My files volume in Files App."; -const char kFloatWindow[] = "CrOS Labs: Float current active window"; +const char kFloatWindow[] = "Float current active window"; const char kFloatWindowDescription[] = "Enables the accelerator (Command + Alt + F) to float current active " - "window."; + "window. You can also access this from Multitask Menu, by " + "hovering/long-pressing on the maximize button on the window frame."; const char kForceSpectreVariant2MitigationName[] = "Force Spectre variant 2 mitigagtion";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index f9369c10..8e7b949e3 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -265,6 +265,9 @@ extern const char kAutofillPreventOverridingPrefilledValuesName[]; extern const char kAutofillPreventOverridingPrefilledValuesDescription[]; +extern const char kAutofillRemoveCardExpirationAndTypeTitlesName[]; +extern const char kAutofillRemoveCardExpirationAndTypeTitlesDescription[]; + extern const char kAutofillSaveAndFillVPAName[]; extern const char kAutofillSaveAndFillVPADescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index b3aedd7..6751305f 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/push_messaging/push_messaging_features.h" #include "chrome/browser/share/share_features.h" #include "chrome/browser/signin/signin_features.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/video_tutorials/switches.h" #include "chrome/common/chrome_features.h" @@ -64,6 +63,7 @@ #include "components/shared_highlighting/core/common/shared_highlighting_features.h" #include "components/signin/public/base/signin_switches.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" +#include "components/supervised_user/core/common/features.h" #include "components/sync/base/features.h" #include "components/webapps/browser/features.h" #include "content/public/common/content_features.h" @@ -237,7 +237,6 @@ &kContextualSearchThinWebViewImplementation, &kDeferKeepScreenOnDuringGesture, &kDirectActions, - &kDuetTabStripIntegrationAndroid, &kExperimentsForAgsa, &kExploreSites, &kFocusOmniboxInIncognitoTabIntents, @@ -265,7 +264,6 @@ &kOmniboxModernizeVisualUpdate, &kOpaqueOriginForIncomingIntents, &kOptimizeGeolocationHeaderGeneration, - &kOptimizeLayoutsForPullRefresh, &kPostTaskFocusTab, &kProbabilisticCryptidRenderer, &kReachedCodeProfiler, @@ -319,7 +317,6 @@ &kTrustedWebActivityQualityEnforcement, &kTrustedWebActivityQualityEnforcementForced, &kTrustedWebActivityQualityEnforcementWarning, - &kShowExtendedPreloadingSetting, &kStartSurfaceAndroid, &kStartSurfaceReturnTime, &kStartSurfaceRefactor, @@ -736,10 +733,6 @@ "DownloadHomeForExternalApp", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kDuetTabStripIntegrationAndroid, - "DuetTabStripIntegrationAndroid", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kExperimentsForAgsa, "ExperimentsForAgsa", base::FEATURE_ENABLED_BY_DEFAULT); @@ -848,10 +841,6 @@ "OptimizeGeolocationHeaderGeneration", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kOptimizeLayoutsForPullRefresh, - "OptimizeLayoutsForPullRefresh", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kPostTaskFocusTab, "PostTaskFocusTab", base::FEATURE_ENABLED_BY_DEFAULT); @@ -1040,10 +1029,6 @@ "TrustedWebActivityQualityEnforcementWarning", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kShowExtendedPreloadingSetting, - "ShowExtendedPreloadingSetting", - base::FEATURE_ENABLED_BY_DEFAULT); - BASE_FEATURE(kStartSurfaceAndroid, "StartSurfaceAndroid", base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index f5ff5df..efb2bbc173 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -86,7 +86,6 @@ BASE_DECLARE_FEATURE(kDontPrefetchLibraries); BASE_DECLARE_FEATURE(kDownloadAutoResumptionThrottling); BASE_DECLARE_FEATURE(kDownloadHomeForExternalApp); -BASE_DECLARE_FEATURE(kDuetTabStripIntegrationAndroid); BASE_DECLARE_FEATURE(kExperimentsForAgsa); BASE_DECLARE_FEATURE(kExploreSites); BASE_DECLARE_FEATURE(kFocusOmniboxInIncognitoTabIntents); @@ -117,7 +116,6 @@ BASE_DECLARE_FEATURE(kBookmarksRefresh); BASE_DECLARE_FEATURE(kBackGestureRefactorAndroid); BASE_DECLARE_FEATURE(kOpaqueOriginForIncomingIntents); -BASE_DECLARE_FEATURE(kOptimizeLayoutsForPullRefresh); BASE_DECLARE_FEATURE(kPostTaskFocusTab); BASE_DECLARE_FEATURE(kProbabilisticCryptidRenderer); BASE_DECLARE_FEATURE(kReachedCodeProfiler); @@ -173,7 +171,6 @@ BASE_DECLARE_FEATURE(kTrustedWebActivityQualityEnforcement); BASE_DECLARE_FEATURE(kTrustedWebActivityQualityEnforcementForced); BASE_DECLARE_FEATURE(kTrustedWebActivityQualityEnforcementWarning); -BASE_DECLARE_FEATURE(kShowExtendedPreloadingSetting); BASE_DECLARE_FEATURE(kStartSurfaceAndroid); BASE_DECLARE_FEATURE(kStartSurfaceReturnTime); BASE_DECLARE_FEATURE(kStartSurfaceRefactor);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index 25be175..e93a506 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -418,7 +418,6 @@ "OptimizationGuidePushNotifications"; public static final String OPTIMIZE_GEOLOCATION_HEADER_GENERATION = "OptimizeGeolocationHeaderGeneration"; - public static final String OPTIMIZE_LAYOUTS_FOR_PULL_REFRESH = "OptimizeLayoutsForPullRefresh"; public static final String OSK_RESIZES_VISUAL_VIEWPORT = "OSKResizesVisualViewportByDefault"; public static final String OVERLAY_NEW_LAYOUT = "OverlayNewLayout"; public static final String PAGE_ANNOTATIONS_SERVICE = "PageAnnotationsService"; @@ -502,7 +501,6 @@ public static final String SHOPPING_LIST = "ShoppingList"; public static final String SHOPPING_LIST_ENABLE_DESYNC_RESOLUTION = "ShoppingListEnableDesyncResolution"; - public static final String SHOW_EXTENDED_PRELOADING_SETTING = "ShowExtendedPreloadingSetting"; public static final String SHOW_SCROLLABLE_MVT_ON_NTP_ANDROID = "ShowScrollableMVTOnNTPAndroid"; public static final String SHOW_TRUSTED_PUBLISHER_URL = "ShowTrustedPublisherURL"; public static final String SMART_SUGGESTION_FOR_LARGE_DOWNLOADS =
diff --git a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc index 9f1e485..ac94ef5 100644 --- a/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc +++ b/chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.cc
@@ -76,11 +76,11 @@ const char kPluginName[] = "name"; const char kPluginIdentifier[] = "identifier"; - base::DictionaryValue info; - info.SetStringKey(kPluginName, name); - info.SetStringKey(kPluginIdentifier, identifier); + base::Value::Dict info; + info.Set(kPluginName, name); + info.Set(kPluginIdentifier, identifier); web_view_permission_helper()->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN, info, + WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN, std::move(info), base::BindOnce( &ChromeWebViewPermissionHelperDelegate::OnPermissionResponse, weak_factory_.GetWeakPtr(), identifier), @@ -106,10 +106,10 @@ const GURL& url, const std::string& request_method, base::OnceCallback<void(bool)> callback) { - base::DictionaryValue request_info; - request_info.SetStringKey(guest_view::kUrl, url.spec()); + base::Value::Dict request_info; + request_info.Set(guest_view::kUrl, url.spec()); web_view_permission_helper()->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_DOWNLOAD, request_info, + WEB_VIEW_PERMISSION_TYPE_DOWNLOAD, std::move(request_info), base::BindOnce( &ChromeWebViewPermissionHelperDelegate::OnDownloadPermissionResponse, weak_factory_.GetWeakPtr(), std::move(callback)), @@ -127,18 +127,17 @@ bool user_gesture, bool last_unlocked_by_target, base::OnceCallback<void(bool)> callback) { - base::DictionaryValue request_info; - request_info.SetBoolKey(guest_view::kUserGesture, user_gesture); - request_info.SetBoolKey(webview::kLastUnlockedBySelf, - last_unlocked_by_target); - request_info.SetStringKey(guest_view::kUrl, web_view_permission_helper() - ->web_view_guest() - ->web_contents() - ->GetLastCommittedURL() - .spec()); + base::Value::Dict request_info; + request_info.Set(guest_view::kUserGesture, user_gesture); + request_info.Set(webview::kLastUnlockedBySelf, last_unlocked_by_target); + request_info.Set(guest_view::kUrl, web_view_permission_helper() + ->web_view_guest() + ->web_contents() + ->GetLastCommittedURL() + .spec()); web_view_permission_helper()->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK, request_info, + WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK, std::move(request_info), base::BindOnce(&ChromeWebViewPermissionHelperDelegate:: OnPointerLockPermissionResponse, weak_factory_.GetWeakPtr(), std::move(callback)), @@ -156,9 +155,9 @@ const GURL& requesting_frame, bool user_gesture, base::OnceCallback<void(bool)> callback) { - base::DictionaryValue request_info; - request_info.SetStringKey(guest_view::kUrl, requesting_frame.spec()); - request_info.SetBoolKey(guest_view::kUserGesture, user_gesture); + base::Value::Dict request_info; + request_info.Set(guest_view::kUrl, requesting_frame.spec()); + request_info.Set(guest_view::kUserGesture, user_gesture); // It is safe to hold an unretained pointer to // ChromeWebViewPermissionHelperDelegate because this callback is called from @@ -169,7 +168,7 @@ weak_factory_.GetWeakPtr(), user_gesture, base::BindOnce(&CallbackWrapper, std::move(callback))); web_view_permission_helper()->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_GEOLOCATION, request_info, + WEB_VIEW_PERMISSION_TYPE_GEOLOCATION, std::move(request_info), std::move(permission_callback), false /* allowed_by_default */); } @@ -198,10 +197,10 @@ const GURL& url, bool allowed_by_default, base::OnceCallback<void(bool)> callback) { - base::DictionaryValue request_info; - request_info.SetStringKey(guest_view::kUrl, url.spec()); + base::Value::Dict request_info; + request_info.Set(guest_view::kUrl, url.spec()); web_view_permission_helper()->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_FILESYSTEM, request_info, + WEB_VIEW_PERMISSION_TYPE_FILESYSTEM, std::move(request_info), base::BindOnce(&ChromeWebViewPermissionHelperDelegate:: OnFileSystemPermissionResponse, weak_factory_.GetWeakPtr(), std::move(callback)),
diff --git a/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc b/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc index 85a82edf..6555fdf 100644 --- a/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc +++ b/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc
@@ -4,12 +4,16 @@ #include "chrome/browser/optimization_guide/page_content_annotations_service_factory.h" +#include <memory> + #include "base/feature_list.h" #include "base/no_destructor.h" #include "base/task/sequenced_task_runner.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/browser/app_mode/app_mode_utils.h" +#include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" +#include "chrome/browser/autocomplete/zero_suggest_cache_service_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/history/history_service_factory.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h" @@ -22,6 +26,7 @@ #include "chrome/browser/search_engines/template_url_service_factory.h" #include "components/history/core/browser/history_service.h" #include "components/leveldb_proto/public/proto_database_provider.h" +#include "components/omnibox/browser/zero_suggest_cache_service.h" #include "components/optimization_guide/content/browser/page_content_annotations_service.h" #include "components/optimization_guide/core/optimization_guide_features.h" #include "components/search_engines/template_url_service.h" @@ -93,6 +98,7 @@ DependsOn(OptimizationGuideKeyedServiceFactory::GetInstance()); DependsOn(HistoryServiceFactory::GetInstance()); DependsOn(TemplateURLServiceFactory::GetInstance()); + DependsOn(ZeroSuggestCacheServiceFactory::GetInstance()); } PageContentAnnotationsServiceFactory::~PageContentAnnotationsServiceFactory() = @@ -119,11 +125,14 @@ ServiceAccessType::IMPLICIT_ACCESS); TemplateURLService* template_url_service = TemplateURLServiceFactory::GetForProfile(profile); + ZeroSuggestCacheService* zero_suggest_cache_service = + ZeroSuggestCacheServiceFactory::GetForProfile(profile); if (optimization_guide_keyed_service && history_service) { return new optimization_guide::PageContentAnnotationsService( + std::make_unique<ChromeAutocompleteProviderClient>(profile), g_browser_process->GetApplicationLocale(), optimization_guide_keyed_service, history_service, template_url_service, - proto_db_provider, profile_path, + zero_suggest_cache_service, proto_db_provider, profile_path, optimization_guide_keyed_service->GetOptimizationGuideLogger(), base::ThreadPool::CreateSequencedTaskRunner( {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
diff --git a/chrome/browser/policy/extension_policy_browsertest.cc b/chrome/browser/policy/extension_policy_browsertest.cc index 8336ab0..3cc665a 100644 --- a/chrome/browser/policy/extension_policy_browsertest.cc +++ b/chrome/browser/policy/extension_policy_browsertest.cc
@@ -30,9 +30,11 @@ #include "chrome/browser/extensions/forced_extensions/install_stage_tracker.h" #include "chrome/browser/extensions/install_verifier.h" #include "chrome/browser/extensions/load_error_waiter.h" +#include "chrome/browser/extensions/mixin_based_extension_apitest.h" #include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/extensions/updater/extension_updater.h" +#include "chrome/browser/policy/extension_force_install_mixin.h" #include "chrome/browser/policy/extension_policy_test_base.h" #include "chrome/browser/policy/policy_test_utils.h" #include "chrome/browser/policy/profile_policy_connector_builder.h" @@ -47,6 +49,7 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/common/chrome_features.h" +#include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/extension_test_util.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/test/base/ui_test_utils.h" @@ -80,6 +83,7 @@ #include "extensions/common/manifest_handlers/shared_module_info.h" #include "extensions/common/permissions/permissions_data.h" #include "extensions/common/value_builder.h" +#include "extensions/test/extension_test_message_listener.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "third_party/blink/public/common/switches.h" @@ -118,7 +122,15 @@ // {DIR_TEST_DATA}/extensions/pinning/ are used in extension pinning tests. const char kPinnedExtensionCrxId[] = "fdlpamochgodkfemfnickdlkabcfmbln"; +// A proxy test extension which is setting proxy for chromium primary profile: +const char kProxySettingExtensionId[] = "cmppkjmdihjjoenffkfoejbjdgnlgnbm"; +const char kProxySettingExtensionExtensionPath[] = + "extensions/browsertest/proxy_setting_extension/"; +const char kProxySettingExtensionPemPath[] = + "extensions/browsertest/proxy_setting_extension.pem"; + const char kGoodCrxVersion[] = "1.0.0.1"; +const char kProxyPreferencesName[] = "proxy"; const base::FilePath::CharType kGoodV1CrxName[] = FILE_PATH_LITERAL("good_v1.crx"); @@ -2588,4 +2600,152 @@ EXPECT_TRUE(app2->permissions_data()->CanAccessPage(test_url, tab_id, error)); } +class MixinBasedExtensionPolicyTest + : public extensions::MixinBasedExtensionApiTest { + public: + MixinBasedExtensionPolicyTest() = default; + + std::string GetKeyFromProxyPrefs(const PrefService::Preference* prefs, + std::string key) { + return prefs->GetValue()->FindKey(key)->GetString(); + } + + const PrefService::Preference* GetOriginalProxyPrefs() { + PrefService* prefs = browser()->profile()->GetOriginalProfile()->GetPrefs(); + return prefs->FindPreference(kProxyPreferencesName); + } + + const PrefService::Preference* GetIncognitoProxyPrefs() { + PrefService* prefs = + browser() + ->profile() + ->GetOffTheRecordProfile( + Profile::OTRProfileID::CreateUniqueForTesting(), + /*create_if_needed=*/true) + ->GetPrefs(); + return prefs->FindPreference(kProxyPreferencesName); + } + + policy::MockConfigurationPolicyProvider* policy_provider() { + return &mock_policy_provider_; + } + + ExtensionForceInstallMixin* force_mixin() { + return &extension_force_install_mixin_; + } + + base::FilePath GetTestDataDir() { + return base::PathService::CheckedGet(chrome::DIR_TEST_DATA); + } + + protected: + void SetUp() override { + extensions::ChromeContentVerifierDelegate::SetDefaultModeForTesting( + extensions::ChromeContentVerifierDelegate::VerifyInfo::Mode:: + ENFORCE_STRICT); + extensions::MixinBasedExtensionApiTest::SetUp(); + } + + void SetUpInProcessBrowserTestFixture() override { + extensions::MixinBasedExtensionApiTest::SetUpInProcessBrowserTestFixture(); + + mock_policy_provider_.SetDefaultReturns( + true /* is_initialization_complete_return */, + true /* is_first_policy_load_complete_return */); + mock_policy_provider_.SetAutoRefresh(); + BrowserPolicyConnector::SetPolicyProviderForTesting(&mock_policy_provider_); + } + + void SetUpOnMainThread() override { + extensions::MixinBasedExtensionApiTest::SetUpOnMainThread(); + extension_force_install_mixin_.InitWithMockPolicyProvider( + profile(), policy_provider()); + } + + void SetUpCommandLine(base::CommandLine* command_line) override { + extensions::MixinBasedExtensionApiTest::SetUpCommandLine(command_line); + } + + ExtensionForceInstallMixin extension_force_install_mixin_{&mixin_host_}; + + private: + testing::NiceMock<MockConfigurationPolicyProvider> mock_policy_provider_; + web_app::OsIntegrationManager::ScopedSuppressForTesting os_hooks_suppress_; +}; + +// Verifies that proxy which is configured by force-installed extensions +// will not affect incognito profile. +IN_PROC_BROWSER_TEST_F(MixinBasedExtensionPolicyTest, + ForcedProxyExtensionHasNoEffectInIncognitoMode) { +#if BUILDFLAG(IS_WIN) + // Mark as enterprise managed. + base::win::ScopedDomainStateForTesting scoped_domain(true); +#endif + + { + // Check that extension is not loaded. + EXPECT_FALSE( + force_mixin()->GetInstalledExtension(kProxySettingExtensionId)); + // Check that in main profile default proxy mode is system. + const PrefService::Preference* proxy_prefs = GetOriginalProxyPrefs(); + ASSERT_TRUE(proxy_prefs); + EXPECT_FALSE(proxy_prefs->IsExtensionControlled()); + std::string proxy_mode = GetKeyFromProxyPrefs(proxy_prefs, "mode"); + EXPECT_EQ(proxy_mode, "system"); + + // Check that in incognito profile default proxy mode is system. + const PrefService::Preference* incognito_proxy_prefs = + GetIncognitoProxyPrefs(); + ASSERT_TRUE(incognito_proxy_prefs); + EXPECT_FALSE(proxy_prefs->IsExtensionControlled()); + std::string incognito_proxy_mode = + GetKeyFromProxyPrefs(incognito_proxy_prefs, "mode"); + EXPECT_EQ(proxy_mode, "system"); + } + + // Force load extension from source dir and get back extension_id. + // As PEM file is provided, we are expecting same extension ID always. + ExtensionTestMessageListener ready_listener("ready"); + ready_listener.set_extension_id(kProxySettingExtensionId); + EXPECT_TRUE(force_mixin()->ForceInstallFromSourceDir( + GetTestDataDir().AppendASCII(kProxySettingExtensionExtensionPath), + GetTestDataDir().AppendASCII(kProxySettingExtensionPemPath), + ExtensionForceInstallMixin::WaitMode::kLoad, nullptr)); + + // Waiting for JS execution after the extension is loaded. + ASSERT_TRUE(ready_listener.WaitUntilSatisfied()); + + // Verify extension is installed and enabled. + ASSERT_TRUE(force_mixin()->GetInstalledExtension(kProxySettingExtensionId)); + EXPECT_TRUE(force_mixin()->GetEnabledExtension(kProxySettingExtensionId)); + EXPECT_EQ(force_mixin() + ->GetInstalledExtension(kProxySettingExtensionId) + ->location(), + ManifestLocation::kExternalPolicyDownload); + + { + // Verify extension has changed proxy setting for Main profile. + const PrefService::Preference* proxy_prefs = GetOriginalProxyPrefs(); + ASSERT_TRUE(proxy_prefs); + EXPECT_TRUE(proxy_prefs->IsExtensionControlled()); + std::string proxy_mode = GetKeyFromProxyPrefs(proxy_prefs, "mode"); + std::string proxy_server = GetKeyFromProxyPrefs(proxy_prefs, "server"); + std::string proxy_bypass_list = + GetKeyFromProxyPrefs(proxy_prefs, "bypass_list"); + + EXPECT_EQ(proxy_mode, "fixed_servers"); + EXPECT_EQ(proxy_server, "https=google.com:5555"); + EXPECT_EQ(proxy_bypass_list, "127.0.0.1"); + + // Verify extension has not changed proxy setting for Incognito profile. + const PrefService::Preference* incognito_proxy_prefs = + GetIncognitoProxyPrefs(); + ASSERT_TRUE(proxy_prefs); + EXPECT_FALSE(incognito_proxy_prefs->IsExtensionControlled()); + std::string incognito_proxy_mode = + GetKeyFromProxyPrefs(incognito_proxy_prefs, "mode"); + EXPECT_EQ(incognito_proxy_mode, "system"); + } +} + } // namespace policy
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java index 166d9b14a..b1890ec 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragment.java
@@ -10,7 +10,6 @@ import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate; import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher; import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; @@ -42,13 +41,6 @@ public static String getPreloadPagesSummaryString(Context context) { @PreloadPagesState int preloadPagesState = PreloadPagesSettingsBridge.getState(); - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) - && preloadPagesState == PreloadPagesState.EXTENDED_PRELOADING) { - // If the extended preloading UI setting is disabled, show "Standard - // Preloading" as a substitute. - preloadPagesState = PreloadPagesState.STANDARD_PRELOADING; - } - String preloadPagesStateString = ""; if (preloadPagesState == PreloadPagesState.EXTENDED_PRELOADING) { return context.getString(R.string.preload_pages_extended_preloading_title); }
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java index f5740cb..fe92a90 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/PreloadPagesSettingsFragmentTest.java
@@ -7,8 +7,6 @@ import static androidx.test.espresso.action.ViewActions.click; import static androidx.test.espresso.matcher.ViewMatchers.withId; -import android.view.View; - import androidx.preference.Preference; import androidx.test.filters.SmallTest; @@ -24,7 +22,6 @@ import org.chromium.base.test.util.DoNotBatch; import org.chromium.base.test.util.Feature; import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncher; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.settings.SettingsActivityTestRule; @@ -50,8 +47,6 @@ "Incorrect radio button checked state."; private static final String ASSERT_PRELOAD_PAGES_STATE_NATIVE = "Incorrect Preload Pages state from native."; - private static final String ASSERT_RADIO_BUTTON_VISIBILITY = - "Incorrect radio button visibility."; @Rule public SettingsActivityTestRule<PreloadPagesSettingsFragment> mTestRule = @@ -93,17 +88,14 @@ @Test @SmallTest @Feature({"PreloadPages"}) - @Features.EnableFeatures({ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING, - SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID}) - public void - testOnStartup_EnableHighlight() { + @Features.EnableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) + public void testOnStartup_EnableHighlight() { testOnStartupImpl(); } @Test @SmallTest @Feature({"PreloadPages"}) - @Features.EnableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) @Features.DisableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) public void testOnStartup_DisableHighlight() { testOnStartupImpl(); @@ -134,48 +126,13 @@ @SmallTest @Feature({"PreloadPages"}) @Features.EnableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) - @Features.DisableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) - public void testOnStartupExtendedPreloadingStateButNotShownInUI_EnableHighlight() { - testOnStartupExtendedPreloadingStateButNotShownInUIImpl(); - } - - @Test - @SmallTest - @Feature({"PreloadPages"}) - @Features.DisableFeatures({ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING, - SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID}) - public void - testOnStartupExtendedPreloadingStateButNotShownInUI_DisableHighlight() { - testOnStartupExtendedPreloadingStateButNotShownInUIImpl(); - } - - public void testOnStartupExtendedPreloadingStateButNotShownInUIImpl() { - launchSettingsActivity(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - PreloadPagesSettingsBridge.setState(PreloadPagesState.EXTENDED_PRELOADING); - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getExtendedPreloadingButton().getVisibility(), View.INVISIBLE); - Assert.assertTrue(getStandardPreloadingButton().isChecked()); - Assert.assertFalse(getNoPreloadingButton().isChecked()); - Assert.assertFalse(mManagedTextPreferenceLegacy.isVisible()); - Assert.assertFalse(mManagedDisclaimerText.isVisible()); - }); - } - - @Test - @SmallTest - @Feature({"PreloadPages"}) - @Features.EnableFeatures({ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING, - SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID}) - public void - testCheckRadioButtons_EnableHighlight() { + public void testCheckRadioButtons_EnableHighlight() { testCheckRadioButtonsImpl(); } @Test @SmallTest @Feature({"PreloadPages"}) - @Features.EnableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) @Features.DisableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) public void testCheckRadioButtons_DisableHighlight() { testCheckRadioButtonsImpl(); @@ -227,57 +184,6 @@ @Test @SmallTest @Feature({"PreloadPages"}) - @Features.EnableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) - @Features.DisableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) - public void testCheckRadioButtonsExtendedPreloadingHidden_EnableHighlight() { - testCheckRadioButtonsExtendedPreloadingHiddenImpl(); - } - - @Test - @SmallTest - @Feature({"PreloadPages"}) - @Features.DisableFeatures({ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING, - SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID}) - public void - testCheckRadioButtonsExtendedPreloadingHidden_DisableHighlight() { - testCheckRadioButtonsExtendedPreloadingHiddenImpl(); - } - - public void testCheckRadioButtonsExtendedPreloadingHiddenImpl() { - launchSettingsActivity(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - Assert.assertFalse(mManagedTextPreferenceLegacy.isVisible()); - Assert.assertFalse(mManagedDisclaimerText.isVisible()); - // Click the Standard Preloading button. - getStandardPreloadingButton().onClick(null); - Assert.assertEquals(ASSERT_PRELOAD_PAGES_STATE_RADIO_BUTTON_GROUP, - PreloadPagesState.STANDARD_PRELOADING, getPreloadPagesState()); - Assert.assertFalse( - ASSERT_RADIO_BUTTON_CHECKED, getExtendedPreloadingButton().isChecked()); - Assert.assertTrue( - ASSERT_RADIO_BUTTON_CHECKED, getStandardPreloadingButton().isChecked()); - Assert.assertFalse(ASSERT_RADIO_BUTTON_CHECKED, getNoPreloadingButton().isChecked()); - Assert.assertEquals(ASSERT_PRELOAD_PAGES_STATE_NATIVE, - PreloadPagesState.STANDARD_PRELOADING, PreloadPagesSettingsBridge.getState()); - - // Click the No Preloading button. - getNoPreloadingButton().onClick(null); - Assert.assertEquals(ASSERT_PRELOAD_PAGES_STATE_RADIO_BUTTON_GROUP, - PreloadPagesState.NO_PRELOADING, getPreloadPagesState()); - Assert.assertFalse( - ASSERT_RADIO_BUTTON_CHECKED, getExtendedPreloadingButton().isChecked()); - Assert.assertFalse( - ASSERT_RADIO_BUTTON_CHECKED, getStandardPreloadingButton().isChecked()); - Assert.assertTrue(ASSERT_RADIO_BUTTON_CHECKED, getNoPreloadingButton().isChecked()); - Assert.assertEquals(ASSERT_PRELOAD_PAGES_STATE_NATIVE, PreloadPagesState.NO_PRELOADING, - PreloadPagesSettingsBridge.getState()); - }); - } - - @Test - @SmallTest - @Feature({"PreloadPages"}) - @Features.EnableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) public void testExtendedPreloadingAuxButtonClicked() { launchSettingsActivity(); TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -306,8 +212,7 @@ @Test @SmallTest @Feature({"PreloadPages"}) - @Features.EnableFeatures({ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING, - SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID}) + @Features.EnableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) @Policies.Add({ @Policies.Item(key = "NetworkPredictionOptions", string = "2" /* NetworkPredictionOptions::kDisabled */) @@ -320,7 +225,6 @@ @Test @SmallTest @Feature({"PreloadPages"}) - @Features.EnableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) @Features.DisableFeatures(SettingsFeatureList.HIGHLIGHT_MANAGED_PREF_DISCLAIMER_ANDROID) @Policies.Add({ @Policies.Item(key = "NetworkPredictionOptions", @@ -370,38 +274,6 @@ }); } - @Test - @SmallTest - @Feature({"PreloadPages"}) - @Features.DisableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) - public void testExtendedPreloadingHiddenViaFinch() { - launchSettingsActivity(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getExtendedPreloadingButton().getVisibility(), View.INVISIBLE); - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getStandardPreloadingButton().getVisibility(), View.VISIBLE); - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getNoPreloadingButton().getVisibility(), View.VISIBLE); - }); - } - - @Test - @SmallTest - @Feature({"PreloadPages"}) - @Features.EnableFeatures(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) - public void testExtendedPreloadingShownViaFinch() { - launchSettingsActivity(); - TestThreadUtils.runOnUiThreadBlocking(() -> { - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getExtendedPreloadingButton().getVisibility(), View.VISIBLE); - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getStandardPreloadingButton().getVisibility(), View.VISIBLE); - Assert.assertEquals(ASSERT_RADIO_BUTTON_VISIBILITY, - getNoPreloadingButton().getVisibility(), View.VISIBLE); - }); - } - private @PreloadPagesState int getPreloadPagesState() { return mPreloadPagesPreference.getPreloadPagesStateForTesting(); }
diff --git a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/RadioButtonGroupPreloadPagesSettings.java b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/RadioButtonGroupPreloadPagesSettings.java index ef31fa4..c26f287 100644 --- a/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/RadioButtonGroupPreloadPagesSettings.java +++ b/chrome/browser/prefetch/android/java/src/org/chromium/chrome/browser/prefetch/settings/RadioButtonGroupPreloadPagesSettings.java
@@ -6,14 +6,12 @@ import android.content.Context; import android.util.AttributeSet; -import android.view.View; import android.widget.RadioGroup; import androidx.annotation.VisibleForTesting; import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; -import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate; import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils; import org.chromium.components.browser_ui.widget.RadioButtonWithDescription; @@ -76,11 +74,7 @@ super.onBindViewHolder(holder); mExtendedPreloading = (RadioButtonWithDescriptionAndAuxButton) holder.findViewById( R.id.extended_preloading); - if (ChromeFeatureList.isEnabled(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING)) { - mExtendedPreloading.setAuxButtonClickedListener(this); - } else { - mExtendedPreloading.setVisibility(View.INVISIBLE); - } + mExtendedPreloading.setAuxButtonClickedListener(this); mStandardPreloading = (RadioButtonWithDescriptionAndAuxButton) holder.findViewById( R.id.standard_preloading); mStandardPreloading.setAuxButtonClickedListener(this); @@ -137,12 +131,6 @@ * buttons of other states to unchecked. */ public void setCheckedState(@PreloadPagesState int checkedState) { - if (!ChromeFeatureList.isEnabled(ChromeFeatureList.SHOW_EXTENDED_PRELOADING_SETTING) - && checkedState == PreloadPagesState.EXTENDED_PRELOADING) { - // If the extended preloading UI setting is disabled, show "Standard - // Preloading" as a substitute. - checkedState = PreloadPagesState.STANDARD_PRELOADING; - } mPreloadPagesState = checkedState; mExtendedPreloading.setChecked(checkedState == PreloadPagesState.EXTENDED_PRELOADING); mStandardPreloading.setChecked(checkedState == PreloadPagesState.STANDARD_PRELOADING);
diff --git a/chrome/browser/profiles/profile_keyed_service_browsertest.cc b/chrome/browser/profiles/profile_keyed_service_browsertest.cc index fa98de34..c36ba0d5 100644 --- a/chrome/browser/profiles/profile_keyed_service_browsertest.cc +++ b/chrome/browser/profiles/profile_keyed_service_browsertest.cc
@@ -490,7 +490,8 @@ "WebRtcEventLogManagerKeyedService", "WebrtcAudioPrivateEventService", "feedback::FeedbackUploaderChrome", - "sct_reporting::Factory" + "sct_reporting::Factory", + "ZeroSuggestCacheServiceFactory", }; // clang-format on
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js index 63b6e2b..18007fc 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager.js
@@ -5,36 +5,29 @@ import {RectUtil} from '../common/rect_util.js'; import {MenuManager} from './menu_manager.js'; -import {SAChildNode, SARootNode} from './nodes/switch_access_node.js'; +import {SAChildNode, SANode, SARootNode} from './nodes/switch_access_node.js'; import {SwitchAccess} from './switch_access.js'; import {SAConstants} from './switch_access_constants.js'; -/** - * Class to handle focus rings. - */ +const FocusRingInfo = chrome.accessibilityPrivate.FocusRingInfo; +const FocusType = chrome.accessibilityPrivate.FocusType; + + +/** Class to handle focus rings. */ export class FocusRingManager { /** @private */ constructor() { /** * A map of all the focus rings. - * @private {!Map<SAConstants.Focus.ID, - * chrome.accessibilityPrivate.FocusRingInfo>} + * @private {!Object<SAConstants.Focus.ID, FocusRingInfo>} */ - this.rings_ = this.createMap_(); + this.rings_ = this.createRings_(); - /** @private {!Map<SAConstants.Focus.ID, SAChildNode>} */ - this.ringNodesForTesting_ = new Map([ - [SAConstants.Focus.ID.PRIMARY, null], - [SAConstants.Focus.ID.PREVIEW, null], - ]); - - /** - * Regex pattern to verify valid colors. Checks that the first character - * is '#', followed by 3, 4, 6, or 8 valid hex characters, and no other - * characters (ignoring case). - * @private - */ - this.colorPattern_ = /^#([0-9A-F]{3,4}|[0-9A-F]{6}|[0-9A-F]{8})$/i; + /** @private {!Object<SAConstants.Focus.ID, ?SANode>} */ + this.ringNodesForTesting_ = { + [SAConstants.Focus.ID.PRIMARY]: null, + [SAConstants.Focus.ID.PREVIEW]: null, + }; } static get instance() { @@ -49,42 +42,23 @@ * @param {!string} color */ static setColor(color) { - const manager = FocusRingManager.instance; - - if (manager.colorPattern_.test(color) !== true) { + if (!FocusRingManager.colorPattern_.test(color)) { console.error(SwitchAccess.error( SAConstants.ErrorType.INVALID_COLOR, 'Problem setting focus ring color: ' + color + ' is not' + 'a valid CSS color string.')); return; } - manager.rings_.forEach(ring => ring.color = color); + FocusRingManager.instance.setColorValidated_(color); } /** - * Sets the primary and preview focus rings based on the current primary and - * group nodes used for navigation. + * Sets the primary and preview focus rings based on the provided node. * @param {!SAChildNode} node */ static setFocusedNode(node) { - const manager = FocusRingManager.instance; - if (node.ignoreWhenComputingUnionOfBoundingBoxes()) { - // Nodes of this type, e.g. the back button node, handles setting its own - // focus, as it has special requirements (a round focus ring that has no - // gap with the edges of the view). - manager.rings_.get(SAConstants.Focus.ID.PRIMARY).rects = []; - // Clear the dashed ring between transitions, as the animation is - // distracting. - manager.rings_.get(SAConstants.Focus.ID.PREVIEW).rects = []; - manager.updateFocusRings_(node, null); - - // The dashed focus ring should not be shown around the menu when exiting. - if (!MenuManager.isMenuOpen()) { - manager.rings_.get(SAConstants.Focus.ID.PREVIEW).rects = - [node.group.location]; - manager.updateFocusRings_(node, null); - } + FocusRingManager.instance.setFocusedNodeIgnorePrimary_(node); return; } @@ -99,38 +73,16 @@ // focus. if (node.isGroup()) { const firstChild = node.asRootNode().firstChild; - - // Clear the dashed ring between transitions, as the animation is - // distracting. - manager.rings_.get(SAConstants.Focus.ID.PREVIEW).rects = []; - - let focusRect = node.location; - const childRect = firstChild ? firstChild.location : null; - if (childRect) { - // If the current element is not specialized in location handling, e.g. - // the back button, the focus rect should expand to contain the child - // rect. - focusRect = RectUtil.expandToFitWithPadding( - SAConstants.Focus.GROUP_BUFFER, focusRect, childRect); - manager.rings_.get(SAConstants.Focus.ID.PREVIEW).rects = [childRect]; - } - manager.rings_.get(SAConstants.Focus.ID.PRIMARY).rects = [focusRect]; - manager.updateFocusRings_(node, firstChild); + FocusRingManager.instance.setFocusedNodeGroup_(node, firstChild); return; } - manager.rings_.get(SAConstants.Focus.ID.PRIMARY).rects = [node.location]; - manager.rings_.get(SAConstants.Focus.ID.PREVIEW).rects = []; - manager.updateFocusRings_(node, null); + FocusRingManager.instance.setFocusedNodeLeaf_(node); } /** Clears all focus rings. */ static clearAll() { - const manager = FocusRingManager.instance; - manager.rings_.forEach(ring => { - ring.rects = []; - }); - manager.updateFocusRings_(null, null); + FocusRingManager.instance.clearAll_(); } /** @@ -138,23 +90,31 @@ * are updated. It will be called with two arguments: the node for * the primary ring, and the node for the preview ring. Either may * be null. - * @param {function(SAChildNode, SAChildNode)} observer + * @param {function(?SANode, ?SANode)} observer */ static setObserver(observer) { FocusRingManager.instance.observer_ = observer; } + // ======== Private methods ======== + + /** @private */ + clearAll_() { + this.forEachRing_(ring => ring.rects = []); + this.updateNodesForTesting_(null, null); + this.updateFocusRings_(); + } + /** * Creates the map of focus rings. - * @return {!Map<SAConstants.Focus.ID, - * chrome.accessibilityPrivate.FocusRingInfo>} + * @return {!Object<SAConstants.Focus.ID, FocusRingInfo>} * @private */ - createMap_() { + createRings_() { const primaryRing = { id: SAConstants.Focus.ID.PRIMARY, rects: [], - type: chrome.accessibilityPrivate.FocusType.SOLID, + type: FocusType.SOLID, color: SAConstants.Focus.PRIMARY_COLOR, secondaryColor: SAConstants.Focus.OUTER_COLOR, }; @@ -162,46 +122,138 @@ const previewRing = { id: SAConstants.Focus.ID.PREVIEW, rects: [], - type: chrome.accessibilityPrivate.FocusType.DASHED, + type: FocusType.DASHED, color: SAConstants.Focus.PREVIEW_COLOR, secondaryColor: SAConstants.Focus.OUTER_COLOR, }; - return new Map([ - [SAConstants.Focus.ID.PRIMARY, primaryRing], - [SAConstants.Focus.ID.PREVIEW, previewRing], - ]); + return { + [SAConstants.Focus.ID.PRIMARY]: primaryRing, + [SAConstants.Focus.ID.PREVIEW]: previewRing, + }; } + /** + * Calls a function for each focus ring. + * @param {!function(!FocusRingInfo)} callback + * @private + */ + forEachRing_(callback) { + Object.values(this.rings_).forEach(ring => callback(ring)); + } + + /** + * Sets the focus ring color. Assumes the color has already been validated. + * @param {!string} color + * @private + */ + setColorValidated_(color) { + this.forEachRing_(ring => ring.color = color); + } + + /** + * Sets the primary focus ring to |node|, and the preview focus ring to + * |firstChild|. + * @param {!SAChildNode} group + * @param {!SAChildNode} firstChild + * @private + */ + setFocusedNodeGroup_(group, firstChild) { + // Clear the dashed ring between transitions, as the animation is + // distracting. + this.rings_[SAConstants.Focus.ID.PREVIEW].rects = []; + + let focusRect = group.location; + const childRect = firstChild ? firstChild.location : null; + if (childRect) { + // If the current element is not specialized in location handling, e.g. + // the back button, the focus rect should expand to contain the child + // rect. + focusRect = RectUtil.expandToFitWithPadding( + SAConstants.Focus.GROUP_BUFFER, focusRect, childRect); + this.rings_[SAConstants.Focus.ID.PREVIEW].rects = [childRect]; + } + this.rings_[SAConstants.Focus.ID.PRIMARY].rects = [focusRect]; + this.updateNodesForTesting_(group, firstChild); + this.updateFocusRings_(); + } + + /** + * Clears the primary focus ring and sets the preview focus ring based on the + * provided node. + * @param {!SAChildNode} node + * @private + */ + setFocusedNodeIgnorePrimary_(node) { + // Nodes of this type, e.g. the back button node, handles setting its own + // focus, as it has special requirements (a round focus ring that has no + // gap with the edges of the view). + this.rings_[SAConstants.Focus.ID.PRIMARY].rects = []; + // Clear the dashed ring between transitions, as the animation is + // distracting. + this.rings_[SAConstants.Focus.ID.PREVIEW].rects = []; + this.updateFocusRings_(); + + // Show the preview focus ring unless the menu is open (it has a custom exit + // button). + if (!MenuManager.isMenuOpen()) { + this.rings_[SAConstants.Focus.ID.PREVIEW].rects = [node.group.location]; + } + this.updateNodesForTesting_(node, node.group); + this.updateFocusRings_(); + } + + /** + * Sets the primary focus to |node| and clears the secondary focus. + * @param {!SAChildNode} node + * @private + */ + setFocusedNodeLeaf_(node) { + this.rings_[SAConstants.Focus.ID.PRIMARY].rects = [node.location]; + this.rings_[SAConstants.Focus.ID.PREVIEW].rects = []; + this.updateNodesForTesting_(node, null); + this.updateFocusRings_(); + } /** * Updates all focus rings to reflect new location, color, style, or other * changes. Enables observers to monitor what's focused. - * @param {SAChildNode} primaryRingNode - * @param {SAChildNode} previewRingNode * @private */ - updateFocusRings_(primaryRingNode, previewRingNode) { + updateFocusRings_() { if (SwitchAccess.mode === SAConstants.Mode.POINT_SCAN && !MenuManager.isMenuOpen()) { return; } - const focusRings = []; - this.rings_.forEach(ring => focusRings.push(ring)); + const focusRings = Object.values(this.rings_); chrome.accessibilityPrivate.setFocusRings(focusRings); + } + /** + * Saves the primary/preview focus for testing. + * @param {?SANode} primary + * @param {?SANode} preview + * @private + */ + updateNodesForTesting_(primary, preview) { // Keep track of the nodes associated with each focus ring for testing // purposes, since focus ring locations are not guaranteed to exactly match // node locations. - this.ringNodesForTesting_.set( - SAConstants.Focus.ID.PRIMARY, primaryRingNode); - this.ringNodesForTesting_.set( - SAConstants.Focus.ID.PREVIEW, previewRingNode); + this.ringNodesForTesting_[SAConstants.Focus.ID.PRIMARY] = primary; + this.ringNodesForTesting_[SAConstants.Focus.ID.PREVIEW] = preview; const observer = FocusRingManager.instance.observer_; if (observer) { - observer(primaryRingNode, previewRingNode); + observer(primary, preview); } } } + +/** + * Regex pattern to verify valid colors. Checks that the first character + * is '#', followed by 3, 4, 6, or 8 valid hex characters, and no other + * characters (ignoring case). + * @private {RegExp} + */ +FocusRingManager.colorPattern_ = /^#([0-9A-F]{3,4}|[0-9A-F]{6}|[0-9A-F]{8})$/i;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js index bd5d90f..5fcbb9bb 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/focus_ring_manager_test.js
@@ -39,8 +39,8 @@ 'Third node should be a BackButtonNode'); const rings = FocusRingManager.instance.rings_; - const primary = rings.get(SAConstants.Focus.ID.PRIMARY); - const preview = rings.get(SAConstants.Focus.ID.PREVIEW); + const primary = rings[SAConstants.Focus.ID.PRIMARY]; + const preview = rings[SAConstants.Focus.ID.PREVIEW]; assertEquals(SAConstants.Focus.ID.PRIMARY, primary.id); assertEquals(SAConstants.Focus.ID.PREVIEW, preview.id); assertEquals('solid', primary.type); @@ -74,8 +74,8 @@ } const rings = FocusRingManager.instance.rings_; - const primary = rings.get(SAConstants.Focus.ID.PRIMARY); - const preview = rings.get(SAConstants.Focus.ID.PREVIEW); + const primary = rings[SAConstants.Focus.ID.PRIMARY]; + const preview = rings[SAConstants.Focus.ID.PREVIEW]; // Primary and preview focus should be empty. assertEquals(0, primary.rects.length); assertEquals(0, preview.rects.length); @@ -88,8 +88,8 @@ Navigator.byItem.moveTo_(button); const rings = FocusRingManager.instance.rings_; - const primary = rings.get(SAConstants.Focus.ID.PRIMARY); - const preview = rings.get(SAConstants.Focus.ID.PREVIEW); + const primary = rings[SAConstants.Focus.ID.PRIMARY]; + const preview = rings[SAConstants.Focus.ID.PREVIEW]; assertEquals(1, primary.rects.length); assertEquals(0, preview.rects.length); // Primary focus should be on the button. @@ -115,17 +115,15 @@ // Verify the number of rings. const rings = FocusRingManager.instance.rings_; - const primary = rings.get(SAConstants.Focus.ID.PRIMARY); - const preview = rings.get(SAConstants.Focus.ID.PREVIEW); + const primary = rings[SAConstants.Focus.ID.PRIMARY]; + const preview = rings[SAConstants.Focus.ID.PREVIEW]; assertEquals(1, primary.rects.length); assertEquals(1, preview.rects.length); // Use ringNodesForTesting_ to verify the underlying nodes. const ringNodes = FocusRingManager.instance.ringNodesForTesting_; - const primaryNode = - ringNodes.get(SAConstants.Focus.ID.PRIMARY).automationNode; - const previewNode = - ringNodes.get(SAConstants.Focus.ID.PREVIEW).automationNode; + const primaryNode = ringNodes[SAConstants.Focus.ID.PRIMARY].automationNode; + const previewNode = ringNodes[SAConstants.Focus.ID.PREVIEW].automationNode; assertEquals( menu, primaryNode, 'primary focus should be around the group (the menu)');
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js index 932a4c1..39656b9 100644 --- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js +++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/switch_access_node.js
@@ -7,7 +7,6 @@ import {SwitchAccess} from '../switch_access.js'; import {SAConstants, SwitchAccessMenuAction} from '../switch_access_constants.js'; - const AutomationNode = chrome.automation.AutomationNode; /** @@ -479,3 +478,6 @@ } } } + +/** @typedef {!SAChildNode|!SARootNode} */ +export let SANode;
diff --git a/chrome/browser/resources/chromeos/drive_internals.html b/chrome/browser/resources/chromeos/drive_internals.html index 2597f04..abd997f 100644 --- a/chrome/browser/resources/chromeos/drive_internals.html +++ b/chrome/browser/resources/chromeos/drive_internals.html
@@ -122,6 +122,10 @@ <td id="bulk-pinning-setup-stage">Unknown</td> </tr> <tr> + <td>Setup Stage Error</td> + <td id="bulk-pinning-setup-stage-error">Unknown</td> + </tr> + <tr> <td>Available Disk Space:</td> <td id="bulk-pinning-available-disk-space">Unknown</td> </tr>
diff --git a/chrome/browser/resources/chromeos/drive_internals.js b/chrome/browser/resources/chromeos/drive_internals.js index aa4a97c..1842470 100644 --- a/chrome/browser/resources/chromeos/drive_internals.js +++ b/chrome/browser/resources/chromeos/drive_internals.js
@@ -106,6 +106,7 @@ return; } $('bulk-pinning-setup-stage').innerText = 'Unknown'; + $('bulk-pinning-setup-stage-error').innerText = 'Unknown'; $('bulk-pinning-available-disk-space').innerText = 'Unknown'; $('bulk-pinning-required-disk-space').innerText = 'Unknown'; $('bulk-pinning-pinned-disk-space').innerText = 'Unknown'; @@ -119,6 +120,9 @@ return; } $('bulk-pinning-setup-stage').innerText = progress.stage; + if (progress.setupError) { + $('bulk-pinning-setup-stage-error').innerText = progress.setupError; + } $('bulk-pinning-available-disk-space').innerText = progress.availableDiskSpace; $('bulk-pinning-required-disk-space').innerText = progress.requiredDiskSpace;
diff --git a/chrome/browser/resources/history/history_toolbar.ts b/chrome/browser/resources/history/history_toolbar.ts index 4ba20eb..64875bf 100644 --- a/chrome/browser/resources/history/history_toolbar.ts +++ b/chrome/browser/resources/history/history_toolbar.ts
@@ -5,7 +5,7 @@ import './shared_style.css.js'; import './strings.m.js'; import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js'; -import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js'; +import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_selection_overlay.js'; import {CrToolbarElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js'; import {CrToolbarSearchFieldElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.js';
diff --git a/chrome/browser/resources/settings/chromeos/device_page/audio.html b/chrome/browser/resources/settings/chromeos/device_page/audio.html index bede8fc..343e3d4 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/audio.html +++ b/chrome/browser/resources/settings/chromeos/device_page/audio.html
@@ -151,6 +151,10 @@ </cr-slider> </div> </div> + <div id="audioInputNoiseCancellationSubsection"> + <div id="audioInputNoiseCancellationLabel">Noise Cancellation</div> + <cr-toggle id="audioInputNoiseCancellationToggle"></cr-toggle> + </div> </div> </div> </div>
diff --git a/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts b/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts index 22dba36..9a90da4d 100644 --- a/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts +++ b/chrome/browser/resources/settings/chromeos/device_page/fake_cros_audio_config.ts
@@ -58,6 +58,7 @@ export interface AudioSystemProperties extends AudioSystemPropertiesMojom { inputDevices: AudioDevice[]; inputMuteState: MuteState; + inputVolumePercent: number; } export interface FakePropertiesObserverInterface { @@ -70,6 +71,7 @@ outputMuteState: MuteState.kNotMuted, inputDevices: [fakeInternalFrontMic, fakeBluetoothMic], inputMuteState: MuteState.kNotMuted, + inputVolumePercent: 57, }; /** Creates an audio device based on provided device and isActive override. */ @@ -83,6 +85,7 @@ setActiveDevice(outputDevice: AudioDevice): void; setOutputMuted(muted: boolean): void; setInputMuted(muted: boolean): void; + setInputVolumePercent(percent: number): void; } export class FakeCrosAudioConfig implements FakeCrosAudioConfigInterface { @@ -150,6 +153,16 @@ } /** + * Sets the `inputVolumePercent` to the desired volume and notifies + * observers. + */ + setInputVolumePercent(volume: number): void { + assert(volume >= 0 && volume <= 100); + this.audioSystemProperties.inputVolumePercent = volume; + this.notifyAudioSystemPropertiesUpdated(); + } + + /** * Sets the `outputVolumePercent` to the desired volume and notifies * observers. */
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn index acec84f..8ad05f8 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/internet_page/BUILD.gn
@@ -21,10 +21,6 @@ ":internet_page", ":internet_page_browser_proxy", ":internet_subpage", - ":network_always_on_vpn", - ":network_proxy_section", - ":network_summary", - ":network_summary_item", ] } @@ -97,7 +93,6 @@ js_library("internet_detail_page") { deps = [ ":internet_page_browser_proxy", - ":network_proxy_section", "//ash/webui/common/resources:assert", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources:web_ui_listener_behavior", @@ -129,6 +124,7 @@ ] externs_list = [ "../settings_controls_types.js", + "$externs_path/settings_private.js", "//ui/webui/resources/cr_elements/cr_button/cr_button_externs.js", "//ui/webui/resources/cr_elements/cr_toggle/cr_toggle_externs.js", "//ui/webui/resources/cr_elements/policy/cr_policy_indicator_externs.js", @@ -163,7 +159,6 @@ ":internet_known_networks_page", ":internet_page_browser_proxy", ":internet_subpage", - ":network_summary", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources:web_ui_listener_behavior", "//ash/webui/common/resources/cellular_setup:cellular_types", @@ -183,6 +178,7 @@ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", ] externs_list = [ + "../settings_controls_types.js", "//ui/webui/resources/cr_elements/cr_toast/cr_toast_externs.js", "//ui/webui/resources/cr_elements/policy/cr_policy_indicator_externs.js", ] @@ -194,7 +190,6 @@ js_library("internet_subpage") { deps = [ ":internet_page_browser_proxy", - ":network_always_on_vpn", "//ash/webui/common/resources:i18n_behavior", "//ash/webui/common/resources/cellular_setup:cellular_types", "//ash/webui/common/resources/network:cr_policy_network_behavior_mojo", @@ -224,65 +219,6 @@ externs_list = [] } -js_library("network_always_on_vpn") { - deps = [ - "//ash/webui/common/resources:assert", - "//ash/webui/common/resources:i18n_behavior", - "//ash/webui/common/resources/network:onc_mojo", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("network_proxy_section") { - deps = [ - "//ash/webui/common/resources:i18n_behavior", - "//ash/webui/common/resources/network:cr_policy_network_behavior_mojo", - "//ash/webui/common/resources/network:cr_policy_network_indicator_mojo", - "//ash/webui/common/resources/network:network_proxy", - "//chrome/browser/resources/settings/chromeos:os_route", - "//chrome/browser/resources/settings/chromeos:prefs_behavior", - "//chrome/browser/resources/settings/chromeos:route_observer_behavior", - "//chrome/browser/resources/settings/chromeos:router", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] - externs_list = [ - "../settings_controls_types.js", - "//ui/webui/resources/cr_elements/cr_button/cr_button_externs.js", - "//ui/webui/resources/cr_elements/cr_dialog/cr_dialog_externs.js", - ] -} - -js_library("network_summary") { - deps = [ - ":hotspot_summary_item", - ":network_summary_item", - "//ash/webui/common/resources/network:mojo_interface_provider", - "//ash/webui/common/resources/network:network_listener_behavior", - "//ash/webui/common/resources/network:onc_mojo", - "//chromeos/ash/services/hotspot_config/public/mojom:mojom_webui_js", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] -} - -js_library("network_summary_item") { - deps = [ - "//ash/webui/common/resources:assert", - "//ash/webui/common/resources:cr_policy_indicator_behavior", - "//ash/webui/common/resources:i18n_behavior", - "//ash/webui/common/resources/network:cellular_utils", - "//ash/webui/common/resources/network:cr_policy_network_behavior_mojo", - "//ash/webui/common/resources/network:network_icon", - "//ash/webui/common/resources/network:network_siminfo", - "//ash/webui/common/resources/network:onc_mojo", - "//ash/webui/common/resources/traffic_counters:traffic_counters", - "//third_party/polymer/v3_0/components-chromium/iron-flex-layout:iron-flex-layout-classes", - "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", - ] - externs_list = - [ "//ui/webui/resources/cr_elements/cr_toggle/cr_toggle_externs.js" ] -} - html_to_js("web_components") { js_files = [ "apn_subpage.js", @@ -294,9 +230,5 @@ "internet_known_networks_page.js", "internet_page.js", "internet_subpage.js", - "network_always_on_vpn.js", - "network_proxy_section.js", - "network_summary_item.js", - "network_summary.js", ] }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js index 93c2fcd..50542b9 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js
@@ -59,14 +59,13 @@ import {InternetPageBrowserProxy, InternetPageBrowserProxyImpl} from './internet_page_browser_proxy.js'; +// TODO(crbug/1315757) The following type definitions are only needed for +// Closure compiler and can be removed when this file is converted to TS. /** - * TODO(crbug/1315757) The following type definitions are only needed for - * Closure compiler and can be removed when this file is converted to TS. - * * @constructor * @extends {HTMLElement} */ -export function CellularRoamingToggleButtonElement() {} +function CellularRoamingToggleButtonElement() {} /** @return {?CrToggleElement} */ CellularRoamingToggleButtonElement.prototype.getCellularRoamingToggle = function() {}; @@ -75,12 +74,20 @@ * @constructor * @extends {HTMLElement} */ -export function TetherConnectionDialogElement() {} +function TetherConnectionDialogElement() {} TetherConnectionDialogElement.prototype.open = function() {}; TetherConnectionDialogElement.prototype.close = function() {}; /** * @constructor + * @extends {HTMLElement} + */ +function NetworkProxySectionElement() {} +/** @return {?CrToggleElement} */ +NetworkProxySectionElement.prototype.getAllowSharedToggle = function() {}; + +/** + * @constructor * @extends {PolymerElement} * @implements {NetworkListenerBehaviorInterface} * @implements {CrPolicyNetworkBehaviorMojoInterface} @@ -571,7 +578,8 @@ this.proxyExpanded_ = true; this.afterRenderShowDeepLink( settingId, - () => this.shadowRoot.querySelector('network-proxy-section') + () => /** @type {NetworkProxySectionElement} */ ( + this.shadowRoot.querySelector('network-proxy-section')) .getAllowSharedToggle()); return false; }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js index f3616b2d..7f0b0c8a 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_page.js
@@ -56,6 +56,27 @@ import {InternetConfigElement} from './internet_config.js'; import {InternetPageBrowserProxy, InternetPageBrowserProxyImpl} from './internet_page_browser_proxy.js'; +// TODO(crbug/1315757) The following type definitions are only needed for +// Closure compiler and can be removed when this file is converted to TS. +/** + * @constructor + * @extends {HTMLElement} + */ +function NetworkSummaryItemElement() {} +/** @return {?CrToggleElement} */ +NetworkSummaryItemElement.prototype.getDeviceEnabledToggle = function() {}; + +/** + * @constructor + * @extends {HTMLElement} + */ +function NetworkSummaryElement() {} +/** + * @param {?NetworkType} networkType + * @return {?NetworkSummaryItemElement} + */ +NetworkSummaryElement.prototype.getNetworkRow = function(networkType) {}; + /** @type {number} */ const ESIM_PROFILE_LIMIT = 5; @@ -426,11 +447,15 @@ } afterNextRender(this, () => { - const networkRow = this.shadowRoot.querySelector('network-summary') + const networkRow = /** @type {NetworkSummaryElement} */ ( + this.shadowRoot.querySelector('network-summary')) .getNetworkRow(networkType); - if (networkRow && networkRow.getDeviceEnabledToggle()) { - this.showDeepLinkElement(networkRow.getDeviceEnabledToggle()); - return; + if (networkRow) { + const toggleEl = networkRow.getDeviceEnabledToggle(); + if (toggleEl) { + this.showDeepLinkElement(toggleEl); + return; + } } console.warn(`Element with deep link id ${settingId} not focusable.`); }); @@ -506,8 +531,10 @@ element = subPage.shadowRoot.querySelector('#networkList'); } } else if (this.detailType_ !== undefined) { - const rowForDetailType = this.shadowRoot.querySelector('network-summary') - .getNetworkRow(this.detailType_); + const rowForDetailType = + /** @type {NetworkSummaryElement} */ ( + this.shadowRoot.querySelector('network-summary')) + .getNetworkRow(this.detailType_); // Note: It is possible that the row is no longer present in the DOM // (e.g., when a Cellular dongle is unplugged or when Instant Tethering
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_always_on_vpn.js b/chrome/browser/resources/settings/chromeos/internet_page/network_always_on_vpn.ts similarity index 63% rename from chrome/browser/resources/settings/chromeos/internet_page/network_always_on_vpn.js rename to chrome/browser/resources/settings/chromeos/internet_page/network_always_on_vpn.ts index 282d8c973..705cdd5 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_always_on_vpn.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_always_on_vpn.ts
@@ -11,39 +11,41 @@ import 'chrome://resources/ash/common/network/network_shared.css.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; +import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; +import {I18nMixin} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {AlwaysOnVpnMode} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {I18nBehaviorInterface} - */ -const NetworkAlwaysOnVpnElementBase = - mixinBehaviors([I18nBehavior], PolymerElement); +import {cast} from '../assert_extras.js'; -/** @polymer */ +import {getTemplate} from './network_always_on_vpn.html.js'; + +interface VpnServiceOption { + name: string; + value: string; + selected: boolean; +} + +const NetworkAlwaysOnVpnElementBase = I18nMixin(PolymerElement); + class NetworkAlwaysOnVpnElement extends NetworkAlwaysOnVpnElementBase { static get is() { - return 'network-always-on-vpn'; + return 'network-always-on-vpn' as const; } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() { return { /** * List of all always-on VPN compatible network states. - * @type {!Array<!OncMojo.NetworkStateProperties>} */ networks: Array, /** * Always-on VPN operating mode. - * @type {!AlwaysOnVpnMode|undefined} */ mode: { type: Number, @@ -52,7 +54,6 @@ /** * Always-on VPN service automatically started on login. - * @type {string|undefined} */ service: { type: String, @@ -61,44 +62,41 @@ }; } + mode: AlwaysOnVpnMode|undefined; + networks: OncMojo.NetworkStateProperties[]; + service: string|undefined; + /** * Tells whether the always-on VPN main toggle is disabled or not. The toggle * is disabled when there's no compatible VPN networks available. - * @return {boolean} - * @private */ - shouldDisableAlwaysOnVpn_() { + private shouldDisableAlwaysOnVpn_(): boolean { return this.networks.length === 0; } /** * Computes the visibility of always-on VPN networks list and lockdown toggle. * These settings are visible when always-on VPN is enabled. - * @return {boolean} - * @private */ - shouldShowAlwaysOnVpnOptions_() { + private shouldShowAlwaysOnVpnOptions_(): boolean { return !this.shouldDisableAlwaysOnVpn_() && this.mode !== AlwaysOnVpnMode.kOff; } /** * Computes the checked value for the always-on VPN enabled toggle. - * @returns {boolean} - * @private */ - computeAlwaysOnVpnEnabled_() { + private computeAlwaysOnVpnEnabled_(): boolean { return !this.shouldDisableAlwaysOnVpn_() && this.mode !== AlwaysOnVpnMode.kOff; } /** * Handles a state change on always-on VPN enable toggle. - * @param {!Event} event - * @private */ - onAlwaysOnEnableChanged_(event) { - if (!event.target.checked) { + private onAlwaysOnEnableChanged_(event: Event): void { + const toggleEl = cast(event.target, CrToggleElement); + if (!toggleEl.checked) { this.mode = AlwaysOnVpnMode.kOff; return; } @@ -107,27 +105,24 @@ /** * Deduces the lockdown state from the always-on VPN mode. - * @return {boolean} - * @private */ - computeAlwaysOnVpnLockdown_() { + private computeAlwaysOnVpnLockdown_(): boolean { return this.mode === AlwaysOnVpnMode.kStrict; } /** * Handles a lockdown toggle state change. It reflects the change on the * current always-on VPN mode. - * @param {!Event} event - * @private */ - onAlwaysOnVpnLockdownChanged_(event) { + private onAlwaysOnVpnLockdownChanged_(event: Event): void { if (this.mode === AlwaysOnVpnMode.kOff) { // The event should not be fired when always-on VPN is disabled (the // enable toggle is disabled). return; } - this.mode = event.target.checked ? AlwaysOnVpnMode.kStrict : - AlwaysOnVpnMode.kBestEffort; + const toggleEl = cast(event.target, CrToggleElement); + this.mode = toggleEl.checked ? AlwaysOnVpnMode.kStrict : + AlwaysOnVpnMode.kBestEffort; } /** @@ -136,12 +131,9 @@ * @return {!Array<{name: string, value: string, selected: boolean}>} * @private */ - getAlwaysOnVpnListOptions_() { - /** @type {!Array<{name: string, value: string, selected: boolean}>} */ - const options = []; - /** @type {string} */ - const currentService = /** @type {string} */ (this.service); - /** @type {boolean} */ + private getAlwaysOnVpnListOptions_(): VpnServiceOption[] { + const options: VpnServiceOption[] = []; + const currentService = this.service; let serviceIsInList = false; if (!this.networks) { @@ -155,10 +147,10 @@ value: state.guid, selected: currentService === state.guid, }); - serviceIsInList |= (currentService === state.guid); + serviceIsInList = serviceIsInList || (currentService === state.guid); }); - // The current always-on VPN service is not in the VPN network list, it + // If the current always-on VPN service is not in the VPN network list, it // needs a placeholder. if (!serviceIsInList) { options.unshift({ @@ -171,12 +163,15 @@ return options; } - /** - * @param {!Event} event - * @private - */ - onAlwaysOnVpnServiceChanged_(event) { - this.service = /** @type {string} */ (event.target.value); + private onAlwaysOnVpnServiceChanged_(event: Event): void { + const selectEl = cast(event.target, HTMLSelectElement); + this.service = selectEl.value; + } +} + +declare global { + interface HTMLElementTagNameMap { + [NetworkAlwaysOnVpnElement.is]: NetworkAlwaysOnVpnElement; } }
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js b/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.ts similarity index 63% rename from chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js rename to chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.ts index a9cec8b..1d097a0 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_proxy_section.ts
@@ -13,56 +13,62 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import 'chrome://resources/cr_elements/cr_hidden_style.css.js'; +import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; import '../../controls/extension_controlled_indicator.js'; import '../../settings_vars.css.js'; import './internet_shared.css.js'; import '../../controls/settings_toggle_button.js'; -import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from 'chrome://resources/ash/common/network/cr_policy_network_behavior_mojo.js'; +import {NetworkProxyElement} from 'chrome://resources/ash/common/network/network_proxy.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; +import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; +import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; import {ManagedProperties, ManagedString} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {OncSource} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {SettingsToggleButtonElement} from '../../controls/settings_toggle_button.js'; +import {PrefsMixin, PrefsMixinInterface} from '../../prefs/prefs_mixin.js'; import {routes} from '../os_route.js'; -import {PrefsBehavior, PrefsBehaviorInterface} from '../prefs_behavior.js'; -import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {RouteObserverMixin, RouteObserverMixinInterface} from '../route_observer_mixin.js'; +import {Route} from '../router.js'; -/** - * @typedef {{name: (string|undefined), - * id: (string|undefined), - * canBeDisabled: (boolean|undefined)}} - */ -let ExtensionInfo; +import {getTemplate} from './network_proxy_section.html.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {CrPolicyNetworkBehaviorMojoInterface} - * @implements {I18nBehaviorInterface} - * @implements {PrefsBehaviorInterface} - * @implements {RouteObserverBehaviorInterface} - */ -const NetworkProxySectionElementBase = mixinBehaviors( - [ - CrPolicyNetworkBehaviorMojo, - I18nBehavior, - PrefsBehavior, - RouteObserverBehavior, - ], - PolymerElement); +interface ExtensionInfo { + name: string|undefined; + id: string|undefined; + canBeDisabled: boolean|undefined; +} -/** @polymer */ +interface NetworkProxySectionElement { + $: { + allowShared: SettingsToggleButtonElement, + confirmAllowSharedDialog: CrDialogElement, + }; +} + +const NetworkProxySectionElementBase = + mixinBehaviors( + [ + CrPolicyNetworkBehaviorMojo, + ], + PrefsMixin(RouteObserverMixin(I18nMixin(PolymerElement)))) as { + new (): PolymerElement & I18nMixinInterface & + RouteObserverMixinInterface & PrefsMixinInterface & + CrPolicyNetworkBehaviorMojoInterface, + }; + class NetworkProxySectionElement extends NetworkProxySectionElementBase { static get is() { - return 'network-proxy-section'; + return 'network-proxy-section' as const; } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() { @@ -72,19 +78,16 @@ value: false, }, - /** @type {!ManagedProperties|undefined} */ managedProperties: Object, /** * Reflects prefs.settings.use_shared_proxies for data binding. - * @private */ useSharedProxies_: Boolean, /** * Indicates if the proxy if set by an extension in the Lacros primary * profile. - * @private */ isProxySetByLacrosExtension_: Boolean, @@ -92,8 +95,6 @@ * Information about the extension in the Ash or Lacros browser which * controlling the proxy. Can be null is the proxy is not controlled by an * extension. - * @type {!ExtensionInfo|undefined} - * @private */ extensionInfo_: Object, }; @@ -106,32 +107,32 @@ ]; } + disabled: boolean; + managedProperties: ManagedProperties|undefined; + private extensionInfo_: ExtensionInfo|undefined; + private isProxySetByLacrosExtension_: boolean; + private useSharedProxies_: boolean; + /** * Returns the allow shared CrToggleElement. - * @return {?CrToggleElement} */ - getAllowSharedToggle() { - return /** @type {?CrToggleElement} */ ( - this.shadowRoot.querySelector('#allowShared')); + getAllowSharedToggle(): CrToggleElement|null { + return this.shadowRoot!.querySelector<CrToggleElement>('#allowShared'); } - /** @protected RouteObserverBehavior */ - currentRouteChanged(newRoute) { + override currentRouteChanged(newRoute: Route): void { if (newRoute === routes.NETWORK_DETAIL) { - /** @type {NetworkProxyElement} */ ( - this.shadowRoot.querySelector('network-proxy')) - .reset(); + this.shadowRoot!.querySelector<NetworkProxyElement>( + 'network-proxy')!.reset(); } } - /** @private */ - useSharedProxiesChanged_() { + private useSharedProxiesChanged_(): void { const pref = this.getPref('settings.use_shared_proxies'); this.useSharedProxies_ = !!pref && !!pref.value; } - /** @private */ - extensionProxyChanged_() { + private extensionProxyChanged_(): void { if (this.proxySetByAshExtension_()) { return; } @@ -147,11 +148,7 @@ } } - /** - * @return {boolean} - * @private - */ - proxySetByAshExtension_() { + private proxySetByAshExtension_(): boolean { const property = this.getProxySettingsTypeProperty_(); if (!property || !this.isExtensionControlled(property)) { return false; @@ -167,27 +164,17 @@ /** * Return true if the proxy is controlled by an extension in the Ash Browser * or in the Lacros Browser. - * @returns {boolean} - * @private */ - isProxySetByExtension_() { + private isProxySetByExtension_(): boolean { return this.proxySetByAshExtension_() || this.isProxySetByLacrosExtension_; } - /** - * @return {boolean} - * @private - */ - isShared_() { - return this.managedProperties.source === OncSource.kDevice || - this.managedProperties.source === OncSource.kDevicePolicy; + private isShared_(): boolean { + return this.managedProperties!.source === OncSource.kDevice || + this.managedProperties!.source === OncSource.kDevicePolicy; } - /** - * @return {!ManagedString|undefined} - * @private - */ - getProxySettingsTypeProperty_() { + private getProxySettingsTypeProperty_(): ManagedString|undefined { if (!this.managedProperties) { return undefined; } @@ -195,34 +182,20 @@ return proxySettings ? proxySettings.type : undefined; } - /** - * @param {boolean} allowShared - * @return {string} - * @private - */ - getAllowSharedDialogTitle_(allowShared) { + private getAllowSharedDialogTitle_(allowShared: boolean): string { if (allowShared) { return this.i18n('networkProxyAllowSharedDisableWarningTitle'); } return this.i18n('networkProxyAllowSharedEnableWarningTitle'); } - /** - * @return {boolean} - * @private - */ - shouldShowNetworkPolicyIndicator_() { + private shouldShowNetworkPolicyIndicator_(): boolean { const property = this.getProxySettingsTypeProperty_(); return !!property && !this.isProxySetByExtension_() && this.isNetworkPolicyEnforced(property); } - /** - * @param {!OncMojo.ManagedProperty} property - * @return {boolean} - * @private - */ - shouldShowAllowShared_(property) { + private shouldShowAllowShared_(_property: OncMojo.ManagedProperty): boolean { if (!this.isShared_()) { return false; } @@ -235,39 +208,38 @@ /** * Handles the change event for the shared proxy checkbox. Shows a * confirmation dialog. - * @param {!Event} event - * @private */ - onAllowSharedProxiesChange_(event) { + private onAllowSharedProxiesChange_(): void { this.$.confirmAllowSharedDialog.showModal(); } /** * Handles the shared proxy confirmation dialog 'Confirm' button. - * @private */ - onAllowSharedDialogConfirm_() { - /** @type {!SettingsToggleButtonElement} */ (this.$.allowShared) - .sendPrefChange(); + private onAllowSharedDialogConfirm_(): void { + this.$.allowShared.sendPrefChange(); this.$.confirmAllowSharedDialog.close(); } /** * Handles the shared proxy confirmation dialog 'Cancel' button or a cancel * event. - * @private */ - onAllowSharedDialogCancel_() { - /** @type {!SettingsToggleButtonElement} */ (this.$.allowShared) - .resetToPrefValue(); + private onAllowSharedDialogCancel_(): void { + this.$.allowShared.resetToPrefValue(); this.$.confirmAllowSharedDialog.close(); } - /** @private */ - onAllowSharedDialogClose_() { + private onAllowSharedDialogClose_(): void { this.$.allowShared.focus(); } } +declare global { + interface HTMLElementTagNameMap { + [NetworkProxySectionElement.is]: NetworkProxySectionElement; + } +} + customElements.define( NetworkProxySectionElement.is, NetworkProxySectionElement);
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary.js b/chrome/browser/resources/settings/chromeos/internet_page/network_summary.ts similarity index 68% rename from chrome/browser/resources/settings/chromeos/internet_page/network_summary.js rename to chrome/browser/resources/settings/chromeos/internet_page/network_summary.ts index a097ef0..52a65ee 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary.ts
@@ -11,33 +11,32 @@ import './network_summary_item.js'; import {getHotspotConfig} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.js'; -import {MojoInterfaceProvider, MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js'; +import {CrosHotspotConfigInterface, CrosHotspotConfigObserverReceiver, HotspotAllowStatus, HotspotInfo} from 'chrome://resources/ash/common/hotspot/cros_hotspot_config.mojom-webui.js'; +import {MojoInterfaceProviderImpl} from 'chrome://resources/ash/common/network/mojo_interface_provider.js'; import {NetworkListenerBehavior, NetworkListenerBehaviorInterface} from 'chrome://resources/ash/common/network/network_listener_behavior.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; -import {CrosHotspotConfigInterface, CrosHotspotConfigObserverInterface, CrosHotspotConfigObserverReceiver, HotspotAllowStatus, HotspotInfo, HotspotState} from 'chrome://resources/mojo/chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom-webui.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {CrosNetworkConfigRemote, FilterType, GlobalPolicy, NO_LIMIT} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {DeviceStateType, NetworkType, OncSource} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {castExists} from '../assert_extras.js'; + +import {getTemplate} from './network_summary.html.js'; import {NetworkSummaryItemElement} from './network_summary_item.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {NetworkListenerBehaviorInterface} - */ const NetworkSummaryElementBase = - mixinBehaviors([NetworkListenerBehavior], PolymerElement); + mixinBehaviors([NetworkListenerBehavior], PolymerElement) as { + new (): PolymerElement & NetworkListenerBehaviorInterface, + }; -/** @polymer */ class NetworkSummaryElement extends NetworkSummaryElementBase { static get is() { - return 'network-summary'; + return 'network-summary' as const; } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() { @@ -45,7 +44,6 @@ /** * Highest priority connected network or null. Set here to update * internet-page which updates internet-subpage and internet-detail-page. - * @type {?OncMojo.NetworkStateProperties} */ defaultNetwork: { type: Object, @@ -57,17 +55,16 @@ * The device state for each network device type. We initialize this to * include a disabled WiFi type since WiFi is always present. This reduces * the amount of visual change on first load. - * @private {!Object<!OncMojo.DeviceStateProperties>} */ deviceStates: { type: Object, value() { - const result = {}; - result[NetworkType.kWiFi] = { - deviceState: DeviceStateType.kDisabled, - type: NetworkType.kWiFi, + return { + [NetworkType.kWiFi]: { + deviceState: DeviceStateType.kDisabled, + type: NetworkType.kWiFi, + }, }; - return result; }, notify: true, }, @@ -75,7 +72,6 @@ /** * Array of active network states, one per device type. Initialized to * include a default WiFi state (see deviceStates comment). - * @private {!Array<!OncMojo.NetworkStateProperties>} */ activeNetworkStates_: { type: Array, @@ -86,26 +82,22 @@ /** * List of network state data for each network type. - * @private {!Object<!Array<!OncMojo.NetworkStateProperties>>} */ networkStateLists_: { type: Object, value() { - const result = {}; - result[NetworkType.kWiFi] = []; - return result; + return { + [NetworkType.kWiFi]: [], + }; }, }, - /** @private {!GlobalPolicy|undefined} */ globalPolicy_: Object, - /** @private {!HotspotInfo} */ hotspotInfo_: Object, /** * Return true if hotspot feature flag is enabled. - * @private */ isHotspotFeatureEnabled_: { type: Boolean, @@ -117,47 +109,47 @@ }; } - /** @override */ + defaultNetwork: OncMojo.NetworkStateProperties|null; + deviceStates: Record<NetworkType, OncMojo.DeviceStateProperties>; + private activeNetworkIds_: Set<string>|null; + private activeNetworkStates_: OncMojo.NetworkStateProperties[]; + private crosHotspotConfig_: CrosHotspotConfigInterface; + private crosHotspotConfigObserverReceiver_: CrosHotspotConfigObserverReceiver; + private globalPolicy_: GlobalPolicy|undefined; + private hotspotInfo_: HotspotInfo; + private isHotspotFeatureEnabled_: boolean; + private networkConfig_: CrosNetworkConfigRemote; + private networkStateLists_: + Record<NetworkType, OncMojo.NetworkStateProperties[]>; + constructor() { super(); /** * Set of GUIDs identifying active networks, one for each type. - * @private {?Set<string>} */ this.activeNetworkIds_ = null; - /** @private {!CrosNetworkConfigRemote} */ this.networkConfig_ = MojoInterfaceProviderImpl.getInstance().getMojoServiceRemote(); if (this.isHotspotFeatureEnabled_) { - /** @private {!CrosHotspotConfigInterface} */ this.crosHotspotConfig_ = getHotspotConfig(); - - /** - * @private {!CrosHotspotConfigObserverReceiver} - */ this.crosHotspotConfigObserverReceiver_ = - new CrosHotspotConfigObserverReceiver( - /** - * @type {!CrosHotspotConfigObserverInterface} - */ - (this)); + new CrosHotspotConfigObserverReceiver(this); } } - /** @override */ - ready() { + override ready(): void { super.ready(); + if (this.isHotspotFeatureEnabled_) { this.crosHotspotConfig_.addObserver( this.crosHotspotConfigObserverReceiver_.$.bindNewPipeAndPassRemote()); } } - /** @override */ - connectedCallback() { + override connectedCallback(): void { super.connectedCallback(); this.getNetworkLists_(); @@ -170,30 +162,26 @@ } } - /** override */ - onHotspotInfoChanged() { - this.crosHotspotConfig_.getHotspotInfo().then(response => { - this.hotspotInfo_ = response.hotspotInfo; - }); + async onHotspotInfoChanged(): Promise<void> { + const response = await this.crosHotspotConfig_.getHotspotInfo(); + this.hotspotInfo_ = response.hotspotInfo; } /** * CrosNetworkConfigObserver impl - * @param {!string} userhash */ - onPoliciesApplied(userhash) { - this.networkConfig_.getGlobalPolicy().then(response => { - this.globalPolicy_ = response.result; - }); + override async onPoliciesApplied(_userhash: string): Promise<void> { + const response = await this.networkConfig_.getGlobalPolicy(); + this.globalPolicy_ = response.result; } /** * CrosNetworkConfigObserver impl * Updates any matching existing active networks. Note: newly active networks * will trigger onNetworkStateListChanged which triggers getNetworkLists_. - * @param {!Array<OncMojo.NetworkStateProperties>} networks */ - onActiveNetworksChanged(networks) { + override onActiveNetworksChanged(networks: OncMojo.NetworkStateProperties[]): + void { if (!this.activeNetworkIds_) { // Initial list of networks not received yet. return; @@ -208,68 +196,60 @@ } /** CrosNetworkConfigObserver impl */ - onNetworkStateListChanged() { + override onNetworkStateListChanged(): void { this.getNetworkLists_(); } /** CrosNetworkConfigObserver impl */ - onDeviceStateListChanged() { + override onDeviceStateListChanged(): void { this.getNetworkLists_(); } /** * Returns the network-summary-item element corresponding to the * |networkType|. - * @param {!NetworkType} networkType - * @return {?NetworkSummaryItemElement} */ - getNetworkRow(networkType) { + getNetworkRow(networkType: NetworkType): NetworkSummaryItemElement|null { const networkTypeString = OncMojo.getNetworkTypeString(networkType); - return /** @type {NetworkSummaryItemElement} */ ( - this.shadowRoot.querySelector(`#${networkTypeString}`)); + return this.shadowRoot!.querySelector<NetworkSummaryItemElement>( + `#${networkTypeString}`); } /** * Requests the list of device states and network states from Chrome. * Updates deviceStates, activeNetworkStates, and networkStateLists once the * results are returned from Chrome. - * @private */ - getNetworkLists_() { + private async getNetworkLists_(): Promise<void> { // First get the device states. - this.networkConfig_.getDeviceStateList().then(response => { - // Second get the network states. - this.getNetworkStates_(response.result); - }); + const response = await this.networkConfig_.getDeviceStateList(); + // Second get the network states. + this.getNetworkStates_(response.result); } /** * Requests the list of network states from Chrome. Updates * activeNetworkStates and networkStateLists once the results are returned * from Chrome. - * @param {!Array<!OncMojo.DeviceStateProperties>} deviceStateList - * @private */ - getNetworkStates_(deviceStateList) { + private async getNetworkStates_( + deviceStateList: OncMojo.DeviceStateProperties[]): Promise<void> { const filter = { filter: FilterType.kVisible, limit: NO_LIMIT, networkType: NetworkType.kAll, }; - this.networkConfig_.getNetworkStateList(filter).then(response => { - this.updateNetworkStates_(response.result, deviceStateList); - }); + const response = await this.networkConfig_.getNetworkStateList(filter); + this.updateNetworkStates_(response.result, deviceStateList); } /** * Called after network states are received from getNetworks. - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStates The state - * properties for all visible networks. - * @param {!Array<!OncMojo.DeviceStateProperties>} deviceStateList - * @private */ - updateNetworkStates_(networkStates, deviceStateList) { - const newDeviceStates = {}; + private updateNetworkStates_( + networkStates: OncMojo.NetworkStateProperties[], + deviceStateList: OncMojo.DeviceStateProperties[]): void { + const newDeviceStates: Record<string, OncMojo.DeviceStateProperties> = {}; for (const device of deviceStateList) { newDeviceStates[device.type] = device; } @@ -284,17 +264,17 @@ // Clear any current networks. const activeNetworkStatesByType = - /** @type {!Map<NetworkType, !OncMojo.NetworkStateProperties>} */ - (new Map()); + new Map<NetworkType, OncMojo.NetworkStateProperties>(); // Complete list of states by type. - const newNetworkStateLists = {}; + const newNetworkStateLists: + Record<string, OncMojo.NetworkStateProperties[]> = {}; for (const type of orderedNetworkTypes) { newNetworkStateLists[type] = []; } - let firstConnectedNetwork = null; - networkStates.forEach(function(networkState) { + let firstConnectedNetwork: OncMojo.NetworkStateProperties|null = null; + networkStates.forEach((networkState) => { const type = networkState.type; if (!activeNetworkStatesByType.has(type)) { activeNetworkStatesByType.set(type, networkState); @@ -311,7 +291,7 @@ // Push the active networks onto newActiveNetworkStates in order based on // device priority, creating an empty state for devices with no networks. - const newActiveNetworkStates = []; + const newActiveNetworkStates: OncMojo.NetworkStateProperties[] = []; this.activeNetworkIds_ = new Set(); for (const type of orderedNetworkTypes) { const device = newDeviceStates[type]; @@ -340,8 +320,8 @@ // Note: The active state for 'Cellular' may be a Tether network if both // types are enabled but no Cellular network exists (edge case). - const networkState = - this.getActiveStateForType_(activeNetworkStatesByType, type); + const networkState = castExists( + this.getActiveStateForType_(activeNetworkStatesByType, type)); if (networkState.source === OncSource.kNone && device.deviceState === DeviceStateType.kProhibited) { // Prohibited technologies are enforced by the device policy. @@ -364,13 +344,10 @@ * Returns the active network state for |type| or a default network state. * If there is no 'Cellular' network, return the active 'Tether' network if * any since the two types are represented by the same section / subpage. - * @param {!Map<NetworkType, !OncMojo.NetworkStateProperties>} - * activeStatesByType - * @param {!NetworkType} type - * @return {!OncMojo.NetworkStateProperties|undefined} - * @private */ - getActiveStateForType_(activeStatesByType, type) { + private getActiveStateForType_( + activeStatesByType: Map<NetworkType, OncMojo.NetworkStateProperties>, + type: NetworkType): OncMojo.NetworkStateProperties|undefined { let activeState = activeStatesByType.get(type); if (!activeState && type === NetworkType.kCellular) { activeState = activeStatesByType.get(NetworkType.kTether); @@ -380,30 +357,21 @@ /** * Provides an id string for summary items. Used in tests. - * @param {!OncMojo.NetworkStateProperties} network - * @return {string} - * @private */ - getTypeString_(network) { + private getTypeString_(network: OncMojo.NetworkStateProperties): string { return OncMojo.getNetworkTypeString(network.type); } - /** - * @param {!Object<!OncMojo.DeviceStateProperties>} deviceStates - * @return {!OncMojo.DeviceStateProperties|undefined} - * @private - */ - getTetherDeviceState_(deviceStates) { - return this.deviceStates[NetworkType.kTether]; + private getTetherDeviceState_( + deviceStates: Record<NetworkType, OncMojo.DeviceStateProperties>): + OncMojo.DeviceStateProperties|undefined { + return deviceStates[NetworkType.kTether]; } /** * Return whether hotspot row should be shown in network summary. - * - * @return {boolean} - * @private */ - shouldShowHotspotSummary_() { + private shouldShowHotspotSummary_(): boolean { if (!this.isHotspotFeatureEnabled_ || !this.hotspotInfo_) { return false; } @@ -415,4 +383,10 @@ } } +declare global { + interface HTMLElementTagNameMap { + [NetworkSummaryElement.is]: NetworkSummaryElement; + } +} + customElements.define(NetworkSummaryElement.is, NetworkSummaryElement);
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts similarity index 70% rename from chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js rename to chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts index ea14c5c4..b0ad7d8e 100644 --- a/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.js +++ b/chrome/browser/resources/settings/chromeos/internet_page/network_summary_item.ts
@@ -16,36 +16,35 @@ import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; +import {CrPolicyIndicatorType} from 'chrome://resources/ash/common/cr_policy_indicator_behavior.js'; import {getSimSlotCount} from 'chrome://resources/ash/common/network/cellular_utils.js'; import {CrPolicyNetworkBehaviorMojo, CrPolicyNetworkBehaviorMojoInterface} from 'chrome://resources/ash/common/network/cr_policy_network_behavior_mojo.js'; import {OncMojo} from 'chrome://resources/ash/common/network/onc_mojo.js'; -import {I18nBehavior, I18nBehaviorInterface} from 'chrome://resources/ash/common/i18n_behavior.js'; -import {CrPolicyIndicatorType} from 'chrome://resources/ash/common/cr_policy_indicator_behavior.js'; -import {assert, assertNotReached} from 'chrome://resources/ash/common/assert.js'; -import {loadTimeData} from 'chrome://resources/ash/common/load_time_data.m.js'; +import {CrToggleElement} from 'chrome://resources/cr_elements/cr_toggle/cr_toggle.js'; +import {I18nMixin, I18nMixinInterface} from 'chrome://resources/cr_elements/i18n_mixin.js'; +import {assert, assertNotReached} from 'chrome://resources/js/assert_ts.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {GlobalPolicy, VpnType} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/cros_network_config.mojom-webui.js'; import {ConnectionStateType, DeviceStateType, NetworkType, OncSource, PortalState} from 'chrome://resources/mojo/chromeos/services/network_config/public/mojom/network_types.mojom-webui.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {InternetPageBrowserProxy, InternetPageBrowserProxyImpl} from './internet_page_browser_proxy.js'; +import {getTemplate} from './network_summary_item.html.js'; -/** - * @constructor - * @extends {PolymerElement} - * @implements {CrPolicyNetworkBehaviorMojoInterface} - * @implements {I18nBehaviorInterface} - */ const NetworkSummaryItemElementBase = - mixinBehaviors([CrPolicyNetworkBehaviorMojo, I18nBehavior], PolymerElement); + mixinBehaviors([CrPolicyNetworkBehaviorMojo], I18nMixin(PolymerElement)) as + { + new (): PolymerElement & I18nMixinInterface & + CrPolicyNetworkBehaviorMojoInterface, + }; -/** @polymer */ export class NetworkSummaryItemElement extends NetworkSummaryItemElementBase { static get is() { - return 'network-summary-item'; + return 'network-summary-item' as const; } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() { @@ -53,7 +52,6 @@ /** * Device state for the network type. This might briefly be undefined if * a device becomes unavailable. - * @type {!OncMojo.DeviceStateProperties|undefined} */ deviceState: { type: Object, @@ -63,19 +61,16 @@ /** * If both Cellular and Tether technologies exist, we combine the * sections and set this to the device state for Tether. - * @type {!OncMojo.DeviceStateProperties|undefined} */ tetherDeviceState: Object, /** * Network state for the active network. - * @type {!OncMojo.NetworkStateProperties|undefined} */ activeNetworkState: Object, /** * List of all network state data for the network type. - * @type {!Array<!OncMojo.NetworkStateProperties>} */ networkStateList: { type: Array, @@ -87,13 +82,11 @@ /** * Title line describing the network type to appear in the row's top * line. If it is undefined, the title text is set to a default value. - * @type {string|undefined} */ networkTitleText: String, /** * Whether to show technology badge on mobile network icon. - * @private */ showTechnologyBadge_: { type: Boolean, @@ -105,7 +98,6 @@ /** * Return true if captivePortalUI2022 feature flag is enabled. - * @private */ isCaptivePortalUI2022Enabled_: { type: Boolean, @@ -115,31 +107,32 @@ }, }, - /** @private {!GlobalPolicy|undefined} */ globalPolicy: Object, }; } + activeNetworkState: OncMojo.NetworkStateProperties|undefined; + deviceState: OncMojo.DeviceStateProperties|undefined; + globalPolicy: GlobalPolicy|undefined; + networkStateList: OncMojo.NetworkStateProperties[]; + networkTitleText: string|undefined; + tetherDeviceState: OncMojo.DeviceStateProperties|undefined; + private browserProxy_: InternetPageBrowserProxy; + private isCaptivePortalUI2022Enabled_: boolean; + private showTechnologyBadge_: boolean; + constructor() { super(); - /** @private {!InternetPageBrowserProxy} */ this.browserProxy_ = InternetPageBrowserProxyImpl.getInstance(); } - /* - * Returns the device enabled toggle element. - * @return {?CrToggleElement} - */ - getDeviceEnabledToggle() { - return this.shadowRoot.querySelector('#deviceEnabledButton'); + getDeviceEnabledToggle(): CrToggleElement|null { + return this.shadowRoot!.querySelector<CrToggleElement>( + '#deviceEnabledButton'); } - /** - * @return {string} - * @private - */ - getNetworkStateText_() { + private getNetworkStateText_(): string { // If SIM Locked, show warning message instead of connection state. if (this.shouldShowLockedWarningMessage_(this.deviceState)) { return this.i18n('networkSimLockedSubtitle'); @@ -149,7 +142,7 @@ } if (this.isCaptivePortalUI2022Enabled_ && - this.isPortalState_(this.activeNetworkState.portalState)) { + this.isPortalState_(this.activeNetworkState!.portalState)) { return this.i18n('networkListItemSignIn'); } @@ -181,12 +174,8 @@ return this.i18n('deviceOff'); } - /** - * @param {!OncMojo.NetworkStateProperties|undefined} networkState - * @return {string} - * @private - */ - getConnectionStateText_(networkState) { + private getConnectionStateText_(networkState: OncMojo.NetworkStateProperties| + undefined): string { if (!networkState || !networkState.guid) { return ''; } @@ -207,12 +196,8 @@ return this.i18n('networkListItemNotConnected'); } - /** - * @param {!OncMojo.NetworkStateProperties} activeNetworkState - * @return {boolean} - * @private - */ - showPolicyIndicator_(activeNetworkState) { + private showPolicyIndicator_(activeNetworkState: + OncMojo.NetworkStateProperties): boolean { return (activeNetworkState !== undefined && OncMojo.connectionStateIsConnected( activeNetworkState.connectionState)) || @@ -221,30 +206,26 @@ } /** - * @param {!OncMojo.NetworkStateProperties} activeNetworkState - * @return {!CrPolicyIndicatorType} Device policy indicator for VPN when + * @return Device policy indicator for VPN when * disabled by policy and an indicator corresponding to the source of the * active network state otherwise. - * @private */ - getPolicyIndicatorType_(activeNetworkState) { + private getPolicyIndicatorType_(activeNetworkState: + OncMojo.NetworkStateProperties): + CrPolicyIndicatorType { if (this.isProhibitedVpn_()) { return this.getIndicatorTypeForSource(OncSource.kDevicePolicy); } return this.getIndicatorTypeForSource(activeNetworkState.source); } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} - * @private - */ - showSimInfo_(deviceState) { + private showSimInfo_(deviceState: OncMojo.DeviceStateProperties| + undefined): boolean { if (!deviceState || deviceState.type !== NetworkType.kCellular) { return false; } - const {pSimSlots, eSimSlots} = getSimSlotCount(deviceState); + const {eSimSlots} = getSimSlotCount(deviceState); if (eSimSlots > 0) { // Do not show simInfo if we are using an eSIM enabled device. return false; @@ -252,27 +233,20 @@ return this.simLocked_(deviceState); } - /** - * @param {!OncMojo.NetworkStateProperties|undefined} activeNetworkState - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {string} - * @private - */ - getNetworkStateClass_(activeNetworkState, deviceState) { + private getNetworkStateClass_( + activeNetworkState: OncMojo.NetworkStateProperties|undefined, + deviceState: OncMojo.DeviceStateProperties|undefined): string { if ((this.isCaptivePortalUI2022Enabled_ && - this.isPortalState_(activeNetworkState.portalState)) || + this.isPortalState_(activeNetworkState!.portalState)) || this.shouldShowLockedWarningMessage_(deviceState)) { return 'warning-message'; } return 'network-state'; } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} - * @private - */ - shouldShowLockedWarningMessage_(deviceState) { + private shouldShowLockedWarningMessage_(deviceState: + OncMojo.DeviceStateProperties| + undefined): boolean { if (!deviceState || deviceState.type !== NetworkType.kCellular || !deviceState.simLockStatus) { return false; @@ -287,12 +261,8 @@ return !!deviceState.simLockStatus.lockType; } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} - * @private - */ - simLocked_(deviceState) { + private simLocked_(deviceState: OncMojo.DeviceStateProperties| + undefined): boolean { if (!deviceState) { return false; } @@ -304,28 +274,23 @@ } /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} True if the device is enabled or if it is a VPN or if + * @return True if the device is enabled or if it is a VPN or if * we are in the state of inhibited. Note: * This function will always return true for VPNs because VPNs can be * disabled by policy only for built-in VPNs (OpenVPN & L2TP), but always * enabled for other VPN providers. To know whether built-in VPNs are * disabled, use builtInVpnProhibited_() instead. - * @private */ - deviceIsEnabled_(deviceState) { + private deviceIsEnabled_(deviceState: OncMojo.DeviceStateProperties| + undefined): boolean { return !!deviceState && (deviceState.type === NetworkType.kVPN || deviceState.deviceState === DeviceStateType.kEnabled || OncMojo.deviceIsInhibited(deviceState)); } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} - * @private - */ - enableToggleIsVisible_(deviceState) { + private enableToggleIsVisible_(deviceState: OncMojo.DeviceStateProperties| + undefined): boolean { if (!deviceState) { return false; } @@ -333,48 +298,35 @@ case NetworkType.kEthernet: case NetworkType.kVPN: return false; - case NetworkType.kTether: return true; - case NetworkType.kWiFi: return deviceState.deviceState !== DeviceStateType.kUninitialized; - case NetworkType.kCellular: if (deviceState.deviceState === DeviceStateType.kUninitialized) { return false; } - // Toggle should be shown as long as we are not also showing the UI for // unlocking the SIM. return !this.showSimInfo_(deviceState); } assertNotReached(); - return false; } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} - * @private - */ - enableToggleIsEnabled_(deviceState) { + private enableToggleIsEnabled_(deviceState: OncMojo.DeviceStateProperties| + undefined): boolean { return this.enableToggleIsVisible_(deviceState) && - deviceState.deviceState !== DeviceStateType.kProhibited && + deviceState!.deviceState !== DeviceStateType.kProhibited && !OncMojo.deviceIsInhibited(deviceState) && - !OncMojo.deviceStateIsIntermediate(deviceState.deviceState); + !OncMojo.deviceStateIsIntermediate(deviceState!.deviceState); } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {string} - * @private - */ - getToggleA11yString_(deviceState) { + private getToggleA11yString_(deviceState: OncMojo.DeviceStateProperties| + undefined): string { if (!this.enableToggleIsVisible_(deviceState)) { return ''; } - switch (deviceState.type) { + switch (deviceState!.type) { case NetworkType.kTether: case NetworkType.kCellular: return this.i18n('internetToggleMobileA11yLabel'); @@ -382,103 +334,80 @@ return this.i18n('internetToggleWiFiA11yLabel'); } assertNotReached(); - return ''; } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {string} - * @private - */ - getToggleA11yDescribedBy_(deviceState) { + private getToggleA11yDescribedBy_(deviceState: OncMojo.DeviceStateProperties| + undefined): string { // Use network state text to describe toggle for uninitialized tether // device. This announces details about enabling bluetooth. if (this.enableToggleIsVisible_(deviceState) && - deviceState.type === NetworkType.kTether && - deviceState.deviceState === DeviceStateType.kUninitialized) { + deviceState!.type === NetworkType.kTether && + deviceState!.deviceState === DeviceStateType.kUninitialized) { return 'networkState'; } return ''; } /** - * @return {boolean} True if VPNs are disabled by policy and the current - * device is VPN. - * @private + * @return True if VPNs are disabled by policy and the current device is VPN. */ - isProhibitedVpn_() { + private isProhibitedVpn_(): boolean { return !!this.deviceState && this.deviceState.type === NetworkType.kVPN && this.builtInVpnProhibited_(this.deviceState); } - /** - * @param {!VpnType} vpnType - * @return {boolean} - * @private - */ - isBuiltInVpnType_(vpnType) { + private isBuiltInVpnType_(vpnType: VpnType): boolean { return vpnType === VpnType.kL2TPIPsec || vpnType === VpnType.kOpenVPN; } /** - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStateList - * @return {boolean} True if at least one non-native VPN is configured. - * @private + * @return True if at least one non-native VPN is configured. */ - hasNonBuiltInVpn_(networkStateList) { + private hasNonBuiltInVpn_(networkStateList: OncMojo.NetworkStateProperties[]): + boolean { const nonBuiltInVpnIndex = networkStateList.findIndex((networkState) => { - return !this.isBuiltInVpnType_(networkState.typeState.vpn.type); + return !this.isBuiltInVpnType_(networkState.typeState.vpn!.type); }); return nonBuiltInVpnIndex !== -1; } /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @return {boolean} True if the built-in VPNs are disabled by policy. - * @private + * @return True if the built-in VPNs are disabled by policy. */ - builtInVpnProhibited_(deviceState) { + private builtInVpnProhibited_(deviceState: OncMojo.DeviceStateProperties| + undefined): boolean { return !!deviceState && deviceState.deviceState === DeviceStateType.kProhibited; } /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStateList - * @return {boolean} True if there is any configured VPN for a non-disabled + * @return True if there is any configured VPN for a non-disabled * VPN provider. Note: Only built-in VPN providers can be disabled by * policy at the moment. - * @private */ - anyVpnExists_(deviceState, networkStateList) { + private anyVpnExists_( + deviceState: OncMojo.DeviceStateProperties|undefined, + networkStateList: OncMojo.NetworkStateProperties[]): boolean { return this.hasNonBuiltInVpn_(networkStateList) || (!this.builtInVpnProhibited_(deviceState) && networkStateList.length > 0); } - /** - * @param {!OncMojo.NetworkStateProperties|undefined} activeNetworkState - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStateList - * @return {boolean} - * @private - */ - shouldShowDetails_(activeNetworkState, deviceState, networkStateList) { + private shouldShowDetails_( + activeNetworkState: OncMojo.NetworkStateProperties|undefined, + deviceState: OncMojo.DeviceStateProperties|undefined, + networkStateList: OncMojo.NetworkStateProperties[]): boolean { if (!!deviceState && deviceState.type === NetworkType.kVPN) { return this.anyVpnExists_(deviceState, networkStateList); } return this.deviceIsEnabled_(deviceState) && - (!!activeNetworkState.guid || networkStateList.length > 0); + (!!activeNetworkState!.guid || networkStateList.length > 0); } - /** - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStateList - * @return {boolean} - * @private - */ - shouldShowSubpage_(deviceState, networkStateList) { + private shouldShowSubpage_( + deviceState: OncMojo.DeviceStateProperties|undefined, + networkStateList: OncMojo.NetworkStateProperties[]): boolean { if (!deviceState) { return false; } @@ -509,7 +438,7 @@ return this.anyVpnExists_(deviceState, networkStateList); } - let minlen; + let minlen: number; if (type === NetworkType.kWiFi) { // WiFi subpage includes 'Known Networks' so always show, even if the // technology is still enabling / scanning, or none are visible. @@ -526,13 +455,11 @@ * lead to toggling device enablement or showing the corresponding networks * list or showing details about a network or doing nothing based on the * device and networks states. - * @param {!Event} event The enable button event. - * @private */ - onShowDetailsTap_(event) { + private onShowDetailsTap_(event: Event): void { if (!this.deviceIsEnabled_(this.deviceState)) { if (this.enableToggleIsEnabled_(this.deviceState)) { - const type = this.deviceState.type; + const type = this.deviceState!.type; const deviceEnabledToggledEvent = new CustomEvent('device-enabled-toggled', { bubbles: true, @@ -543,20 +470,20 @@ } } else if ( this.isCaptivePortalUI2022Enabled_ && - this.isPortalState_(this.activeNetworkState.portalState)) { - this.browserProxy_.showPortalSignin(this.activeNetworkState.guid); + this.isPortalState_(this.activeNetworkState!.portalState)) { + this.browserProxy_.showPortalSignin(this.activeNetworkState!.guid); } else if (this.shouldShowSubpage_( this.deviceState, this.networkStateList)) { const showNetworksEvent = new CustomEvent('show-networks', { bubbles: true, composed: true, - detail: this.deviceState.type, + detail: this.deviceState!.type, }); this.dispatchEvent(showNetworksEvent); } else if (this.shouldShowDetails_( this.activeNetworkState, this.deviceState, this.networkStateList)) { - if (this.activeNetworkState.guid) { + if (this.activeNetworkState!.guid) { const showDetailEvent = new CustomEvent('show-detail', { bubbles: true, composed: true, @@ -581,21 +508,19 @@ * a network or doing nothing based on the device and networks states. * TODO(b/253326370) Cleanup duplicate functionality between this * function and `onShowDetailsTap_`. - * @param {!Event} event The enable button event. - * @private */ - onShowDetailsArrowTap_(event) { + private onShowDetailsArrowTap_(event: Event): void { if (this.shouldShowSubpage_(this.deviceState, this.networkStateList)) { const showNetworksEvent = new CustomEvent('show-networks', { bubbles: true, composed: true, - detail: this.deviceState.type, + detail: this.deviceState!.type, }); this.dispatchEvent(showNetworksEvent); } else if (this.shouldShowDetails_( this.activeNetworkState, this.deviceState, this.networkStateList)) { - if (this.activeNetworkState.guid) { + if (this.activeNetworkState!.guid) { const showDetailEvent = new CustomEvent('show-detail', { bubbles: true, composed: true, @@ -614,14 +539,10 @@ event.stopPropagation(); } - /** - * @param {!OncMojo.NetworkStateProperties} activeNetworkState - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStateList - * @return {boolean} - * @private - */ - isItemActionable_(activeNetworkState, deviceState, networkStateList) { + private isItemActionable_( + activeNetworkState: OncMojo.NetworkStateProperties, + deviceState: OncMojo.DeviceStateProperties|undefined, + networkStateList: OncMojo.NetworkStateProperties[]): boolean { // The boolean logic here matches onShowDetailsTap_ method that handles the // item click event. @@ -633,7 +554,7 @@ // Item is actionable if tapping should show the user to the portal signin. if (this.isCaptivePortalUI2022Enabled_ && - this.isPortalState_(this.activeNetworkState.portalState)) { + this.isPortalState_(this.activeNetworkState!.portalState)) { return true; } @@ -644,14 +565,10 @@ activeNetworkState, deviceState, networkStateList); } - /** - * @param {!OncMojo.NetworkStateProperties} activeNetworkState - * @param {!OncMojo.DeviceStateProperties|undefined} deviceState - * @param {!Array<!OncMojo.NetworkStateProperties>} networkStateList - * @return {boolean} - * @private - */ - showArrowButton_(activeNetworkState, deviceState, networkStateList) { + private showArrowButton_( + activeNetworkState: OncMojo.NetworkStateProperties, + deviceState: OncMojo.DeviceStateProperties|undefined, + networkStateList: OncMojo.NetworkStateProperties[]): boolean { // If SIM info is shown on the right side of the item, no arrow should be // shown. if (this.showSimInfo_(deviceState)) { @@ -667,10 +584,8 @@ /** * Event triggered when the enable button is toggled. - * @param {!Event} event - * @private */ - onDeviceEnabledChange_(event) { + private onDeviceEnabledChange_(): void { assert(this.deviceState); const deviceIsEnabled = this.deviceIsEnabled_(this.deviceState); const deviceEnabledToggledEvent = @@ -687,39 +602,28 @@ DeviceStateType.kEnabling; } - /** - * @return {string} - * @private - */ - getTitleText_() { + private getTitleText_(): string { if (this.networkTitleText) { return this.networkTitleText; } if (this.isCaptivePortalUI2022Enabled_ && - this.isPortalState_(this.activeNetworkState.portalState)) { + this.isPortalState_(this.activeNetworkState!.portalState)) { const stateText = this.getConnectionStateText_(this.activeNetworkState); if (stateText) { return stateText; } } - return this.getNetworkTypeString_(this.activeNetworkState.type); + return this.getNetworkTypeString_(this.activeNetworkState!.type); } /** * Make sure events in embedded components do not propagate to onDetailsTap_. - * @param {!Event} event - * @private */ - doNothing_(event) { + private doNothing_(event: Event): void { event.stopPropagation(); } - /** - * @param {!NetworkType} type - * @return {string} - * @private - */ - getNetworkTypeString_(type) { + private getNetworkTypeString_(type: NetworkType): string { // The shared Cellular/Tether subpage is referred to as "Mobile". // TODO(khorimoto): Remove once Cellular/Tether are split into their own // sections. @@ -731,14 +635,17 @@ /** * Return true if portalState is either kPortal or kProxyAuthRequired. - * @param {!PortalState} portalState - * @return {boolean} - * @private */ - isPortalState_(portalState) { + private isPortalState_(portalState: PortalState): boolean { return portalState === PortalState.kPortal || portalState === PortalState.kProxyAuthRequired; } } +declare global { + interface HTMLElementTagNameMap { + [NetworkSummaryItemElement.is]: NetworkSummaryItemElement; + } +} + customElements.define(NetworkSummaryItemElement.is, NetworkSummaryItemElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 278f7bd..5b296ab7 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -62,6 +62,10 @@ "chromeos/internet_page/esim_install_error_dialog.ts", "chromeos/internet_page/esim_remove_profile_dialog.ts", "chromeos/internet_page/esim_rename_dialog.ts", + "chromeos/internet_page/network_always_on_vpn.ts", + "chromeos/internet_page/network_proxy_section.ts", + "chromeos/internet_page/network_summary_item.ts", + "chromeos/internet_page/network_summary.ts", "chromeos/internet_page/settings_traffic_counters.ts", "chromeos/internet_page/tether_connection_dialog.ts", "chromeos/kerberos_page/kerberos_accounts.ts", @@ -355,10 +359,6 @@ "chromeos/internet_page/internet_known_networks_page.js", "chromeos/internet_page/internet_page.js", "chromeos/internet_page/internet_subpage.js", - "chromeos/internet_page/network_always_on_vpn.js", - "chromeos/internet_page/network_proxy_section.js", - "chromeos/internet_page/network_summary.js", - "chromeos/internet_page/network_summary_item.js", "chromeos/multidevice_page/multidevice_combined_setup_item.js", "chromeos/multidevice_page/multidevice_feature_item.js", "chromeos/multidevice_page/multidevice_feature_toggle.js",
diff --git a/chrome/browser/resources/settings/settings.ts b/chrome/browser/resources/settings/settings.ts index 9f33a751..3db81111 100644 --- a/chrome/browser/resources/settings/settings.ts +++ b/chrome/browser/resources/settings/settings.ts
@@ -49,7 +49,7 @@ export {SettingsStartupUrlsPageElement} from './on_startup_page/startup_urls_page.js'; export {StartupUrlsPageBrowserProxy, StartupUrlsPageBrowserProxyImpl} from './on_startup_page/startup_urls_page_browser_proxy.js'; export {OpenWindowProxy, OpenWindowProxyImpl} from './open_window_proxy.js'; -export {pageVisibility, setPageVisibilityForTesting} from './page_visibility.js'; +export {pageVisibility, PrivacyPageVisibility, setPageVisibilityForTesting} from './page_visibility.js'; // <if expr="chromeos_ash"> export {AccountManagerBrowserProxy, AccountManagerBrowserProxyImpl} from './people_page/account_manager_browser_proxy.js'; // </if> @@ -75,7 +75,7 @@ export {ResetBrowserProxy, ResetBrowserProxyImpl} from './reset_page/reset_browser_proxy.js'; export {SettingsResetProfileBannerElement} from './reset_page/reset_profile_banner.js'; export {buildRouter, routes} from './route.js'; -export {SettingsRoutes, Route, Router} from './router.js'; +export {Route, Router, SettingsRoutes} from './router.js'; export {SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckChromeCleanerStatus, SafetyCheckExtensionsStatus, SafetyCheckParentStatus, SafetyCheckPasswordsStatus, SafetyCheckSafeBrowsingStatus, SafetyCheckUpdatesStatus} from './safety_check_page/safety_check_browser_proxy.js'; export {SafetyCheckIconStatus, SettingsSafetyCheckChildElement} from './safety_check_page/safety_check_child.js'; // <if expr="_google_chrome and is_win">
diff --git a/chrome/browser/resources/side_panel/customize_chrome/categories.html b/chrome/browser/resources/side_panel/customize_chrome/categories.html index 28f60e2..15a60a9 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/categories.html +++ b/chrome/browser/resources/side_panel/customize_chrome/categories.html
@@ -115,7 +115,8 @@ <!-- TODO(crbug.com/1399596): use i18n for label --> <div class="label">Classic Chrome</div> </div> - <div class="tile" tabindex="0" role="button"> + <div class="tile" tabindex="0" id="uploadImageTile" + role="button" on-click="onUploadImageClick_"> <div class="image-container"></div> <!-- TODO(crbug.com/1399596): use i18n for label --> <div class="label">Upload Image</div>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/categories.ts b/chrome/browser/resources/side_panel/customize_chrome/categories.ts index 9b83f56..9a5270b4 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/categories.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/categories.ts
@@ -17,6 +17,7 @@ $: { backButton: HTMLElement, classicChromeTile: HTMLElement, + uploadImageTile: HTMLElement, }; } @@ -52,6 +53,13 @@ this.dispatchEvent(new Event('theme-select')); } + private async onUploadImageClick_() { + const {success} = await this.pageHandler_.chooseLocalCustomBackground(); + if (success) { + this.dispatchEvent(new Event('theme-select')); + } + } + private onCollectionClick_(e: DomRepeatEvent<BackgroundCollection>) { this.dispatchEvent(new CustomEvent<BackgroundCollection>( 'collection-select', {detail: e.model.item}));
diff --git a/chrome/browser/resources/supervised_user_error_page_resources.grdp b/chrome/browser/resources/supervised_user_error_page_resources.grdp deleted file mode 100644 index da3164e0..0000000 --- a/chrome/browser/resources/supervised_user_error_page_resources.grdp +++ /dev/null
@@ -1,5 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<grit-part> - <include name="IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_HTML" file="supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.html" flattenhtml="true" type="BINDATA" compress="brotli" /> - <include name="IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_V2_HTML" file="supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.html" flattenhtml="true" type="BINDATA" compress="brotli" /> -</grit-part>
diff --git a/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor.cc b/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor.cc index db995406..f68dd26c 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service.h" #include "chrome/browser/safe_browsing/extension_telemetry/password_reuse_signal.h" #include "chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal.h" +#include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/proto/csd.pb.h" #include "crypto/sha2.h" @@ -28,6 +29,10 @@ const ExtensionSignal& signal) { DCHECK(signal.GetType() == ExtensionSignalType::kRemoteHostContacted || signal.GetType() == ExtensionSignalType::kPasswordReuse); + if (!base::FeatureList::IsEnabled( + safe_browsing::kExtensionTelemetryPotentialPasswordTheft)) { + return; + } base::Time signal_creation_time = base::Time::NowFromSystemTime(); extensions::ExtensionId extension_id; // Process remote host contacted signal.
diff --git a/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor_unittest.cc b/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor_unittest.cc index bfec3ab6..c5c5da2 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor_unittest.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor_unittest.cc
@@ -3,9 +3,11 @@ // found in the LICENSE file. #include "chrome/browser/safe_browsing/extension_telemetry/potential_password_theft_signal_processor.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/safe_browsing/extension_telemetry/password_reuse_signal.h" #include "chrome/browser/safe_browsing/extension_telemetry/remote_host_contacted_signal.h" #include "components/safe_browsing/content/browser/password_protection/password_protection_service.h" +#include "components/safe_browsing/core/common/features.h" #include "components/safe_browsing/core/common/proto/csd.pb.h" #include "content/public/test/browser_task_environment.h" #include "extensions/common/extension_id.h" @@ -66,6 +68,7 @@ return reused_password_account_type; } + base::test::ScopedFeatureList scoped_feature_list; PotentialPasswordTheftSignalProcessor processor_; content::BrowserTaskEnvironment task_environment_; @@ -84,6 +87,8 @@ auto pw_reuse_signal = PasswordReuseSignal(kExtensionId[0], pw_reuse_event_0); auto remote_host_signal = RemoteHostContactedSignal( kExtensionId[0], GURL(host_urls[0]), kProtocolType); + scoped_feature_list.InitAndEnableFeature( + kExtensionTelemetryPotentialPasswordTheft); processor_.ProcessSignal(pw_reuse_signal); EXPECT_FALSE(processor_.IsPasswordQueueEmptyForTest()); @@ -119,6 +124,8 @@ kExtensionId[0], GURL(host_urls[0]), kProtocolType); auto remote_host_signal_1 = RemoteHostContactedSignal( kExtensionId[0], GURL(host_urls[1]), kProtocolType); + scoped_feature_list.InitAndEnableFeature( + kExtensionTelemetryPotentialPasswordTheft); processor_.ProcessSignal(remote_host_signal_0); task_environment_.FastForwardBy(base::Milliseconds(100)); processor_.ProcessSignal(remote_host_signal_1); @@ -156,6 +163,8 @@ auto remote_host_signal_3 = RemoteHostContactedSignal( kExtensionId[0], GURL(host_urls[3]), kProtocolType); + scoped_feature_list.InitAndEnableFeature( + kExtensionTelemetryPotentialPasswordTheft); processor_.ProcessSignal(pw_reuse_signal_0); task_environment_.FastForwardBy(base::Milliseconds(50)); processor_.ProcessSignal(pw_reuse_signal_1);
diff --git a/chrome/browser/search/background/ntp_custom_background_service.h b/chrome/browser/search/background/ntp_custom_background_service.h index 39061396..25c73bae 100644 --- a/chrome/browser/search/background/ntp_custom_background_service.h +++ b/chrome/browser/search/background/ntp_custom_background_service.h
@@ -65,7 +65,8 @@ const std::string& collection_id); // Invoked when a user selected the "Upload an image" option on the NTP. - void SelectLocalBackgroundImage(const base::FilePath& path); + // Virtual for testing. + virtual void SelectLocalBackgroundImage(const base::FilePath& path); // Virtual for testing. virtual void RefreshBackgroundIfNeeded();
diff --git a/chrome/browser/sessions/closed_tab_cache_browsertest.cc b/chrome/browser/sessions/closed_tab_cache_browsertest.cc index 8279e8e..7f45b04 100644 --- a/chrome/browser/sessions/closed_tab_cache_browsertest.cc +++ b/chrome/browser/sessions/closed_tab_cache_browsertest.cc
@@ -192,6 +192,9 @@ // Restore an entry that is in the cache. IN_PROC_BROWSER_TEST_F(ClosedTabCacheBrowserTest, RestoreEntryWhenFound) { + base::HistogramTester histogram_tester; + const char kTabRestored[] = "Tab.RestoreClosedTab"; + ASSERT_TRUE(embedded_test_server()->Start()); NavigateToURL(browser(), "a.com"); @@ -208,6 +211,12 @@ EXPECT_EQ(closed_tab_cache().EntriesCount(), 0U); ASSERT_EQ(browser()->tab_strip_model()->count(), 2); EXPECT_EQ(browser()->tab_strip_model()->GetWebContentsAt(1), wc); + + // We should store histogram kTabRestored when a tab is restored from + // ClosedTabCache with value 1. + EXPECT_EQ(histogram_tester.GetAllSamples(kTabRestored).size(), 1U); + EXPECT_THAT(histogram_tester.GetAllSamples(kTabRestored), + testing::ElementsAre(base::Bucket(1, 1))); } // Evict an entry after timeout.
diff --git a/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc b/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc index a66d9ce..4e87cf75 100644 --- a/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc +++ b/chrome/browser/storage_access_api/storage_access_grant_permission_context_unittest.cc
@@ -4,8 +4,11 @@ #include "chrome/browser/storage_access_api/storage_access_grant_permission_context.h" +#include "base/barrier_callback.h" +#include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/content_settings/core/common/content_settings.h" #include "components/permissions/permission_request_id.h" @@ -41,12 +44,6 @@ base::NumberToString(dummy_id) + ".com"); } -void SaveResult(ContentSetting* content_setting_result, - ContentSetting content_setting) { - DCHECK(content_setting_result); - *content_setting_result = content_setting; -} - } // namespace class StorageAccessGrantPermissionContextTest @@ -100,17 +97,22 @@ permissions::PermissionRequestManager* manager = permissions::PermissionRequestManager::FromWebContents(web_contents()); DCHECK(manager); - for (int grant_id = 0; - grant_id < net::features::kStorageAccessAPIDefaultImplicitGrantLimit; - grant_id++) { - ContentSetting result = CONTENT_SETTING_DEFAULT; + const int implicit_grant_limit = + net::features::kStorageAccessAPIDefaultImplicitGrantLimit; + base::RunLoop run_loop; + auto barrier = base::BarrierCallback<ContentSetting>( + implicit_grant_limit, + base::BindLambdaForTesting( + [&](const std::vector<ContentSetting> results) { + run_loop.Quit(); + })); + for (int grant_id = 0; grant_id < implicit_grant_limit; grant_id++) { permission_context.DecidePermissionForTesting( fake_id, requesting_origin, GetDummyEmbeddingUrl(grant_id), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); - base::RunLoop().RunUntilIdle(); - - EXPECT_FALSE(manager->IsRequestInProgress()); + /*user_gesture=*/true, barrier); } + run_loop.Run(); + EXPECT_FALSE(manager->IsRequestInProgress()); } permissions::PermissionRequestID CreateFakeID() { @@ -150,11 +152,11 @@ StorageAccessGrantPermissionContext permission_context(profile()); permissions::PermissionRequestID fake_id = CreateFakeID(); - ContentSetting result = CONTENT_SETTING_DEFAULT; + base::test::TestFuture<ContentSetting> future; permission_context.DecidePermissionForTesting( fake_id, GetRequesterURL(), GetTopLevelURL(), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); - EXPECT_EQ(CONTENT_SETTING_BLOCK, result); + /*user_gesture=*/true, future.GetCallback()); + EXPECT_EQ(CONTENT_SETTING_BLOCK, future.Get()); } class StorageAccessGrantPermissionContextAPIEnabledTest @@ -177,10 +179,12 @@ ExhaustImplicitGrants(GetRequesterURL(), permission_context); - ContentSetting result = CONTENT_SETTING_DEFAULT; + base::test::TestFuture<ContentSetting> future; permission_context.DecidePermissionForTesting( fake_id, GetRequesterURL(), GetTopLevelURL(), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); + /*user_gesture=*/true, future.GetCallback()); + + // Run until the prompt is ready. base::RunLoop().RunUntilIdle(); permissions::PermissionRequestManager* manager = @@ -196,8 +200,7 @@ EXPECT_EQ(GetTopLevelURL(), manager->GetEmbeddingOrigin()); manager->Dismiss(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CONTENT_SETTING_ASK, result); + EXPECT_EQ(CONTENT_SETTING_ASK, future.Get()); EXPECT_EQ(histogram_tester().GetBucketCount(kRequestOutcomeHistogram, RequestOutcome::kDismissedByUser), 1); @@ -209,11 +212,11 @@ StorageAccessGrantPermissionContext permission_context(profile()); permissions::PermissionRequestID fake_id = CreateFakeID(); - ContentSetting result = CONTENT_SETTING_DEFAULT; + base::test::TestFuture<ContentSetting> future; permission_context.DecidePermissionForTesting( fake_id, GetRequesterURL(), GetTopLevelURL(), - /*user_gesture=*/false, base::BindOnce(&SaveResult, &result)); - EXPECT_EQ(CONTENT_SETTING_BLOCK, result); + /*user_gesture=*/false, future.GetCallback()); + EXPECT_EQ(CONTENT_SETTING_BLOCK, future.Get()); EXPECT_EQ( histogram_tester().GetBucketCount(kRequestOutcomeHistogram, RequestOutcome::kDeniedByPrerequisites), @@ -258,23 +261,26 @@ EXPECT_EQ(histogram_tester().GetBucketCount( kRequestOutcomeHistogram, RequestOutcome::kGrantedByAllowance), 5); - - ContentSetting result = CONTENT_SETTING_DEFAULT; - permission_context.DecidePermissionForTesting( - fake_id, GetRequesterURL(), GetTopLevelURL(), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); - base::RunLoop().RunUntilIdle(); - permissions::PermissionRequestManager* manager = permissions::PermissionRequestManager::FromWebContents(web_contents()); ASSERT_TRUE(manager); - ASSERT_TRUE(manager->IsRequestInProgress()); - // Close the prompt and validate we get the expected setting back in our - // callback. - manager->Dismiss(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CONTENT_SETTING_ASK, result); + { + base::test::TestFuture<ContentSetting> future; + permission_context.DecidePermissionForTesting( + fake_id, GetRequesterURL(), GetTopLevelURL(), + /*user_gesture=*/true, future.GetCallback()); + + // Run until the prompt is ready. + base::RunLoop().RunUntilIdle(); + + ASSERT_TRUE(manager->IsRequestInProgress()); + + // Close the prompt and validate we get the expected setting back in our + // callback. + manager->Dismiss(); + EXPECT_EQ(CONTENT_SETTING_ASK, future.Get()); + } EXPECT_EQ(histogram_tester().GetBucketCount(kRequestOutcomeHistogram, RequestOutcome::kDismissedByUser), 1); @@ -291,15 +297,14 @@ // However now if a different requesting origin makes a request we should see // it gets auto-granted as the limit has not been reached for it yet. - result = CONTENT_SETTING_DEFAULT; + base::test::TestFuture<ContentSetting> future; permission_context.DecidePermissionForTesting( fake_id, alternate_requester_url, GetTopLevelURL(), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); - base::RunLoop().RunUntilIdle(); + /*user_gesture=*/true, future.GetCallback()); // We should have no prompts still and our latest result should be an allow. + EXPECT_EQ(CONTENT_SETTING_ALLOW, future.Get()); EXPECT_FALSE(manager->IsRequestInProgress()); - EXPECT_EQ(CONTENT_SETTING_ALLOW, result); EXPECT_EQ(histogram_tester().GetBucketCount( kRequestOutcomeHistogram, RequestOutcome::kGrantedByAllowance), 6); @@ -323,7 +328,6 @@ permissions::PermissionRequestManager* manager = permissions::PermissionRequestManager::FromWebContents(web_contents()); - ContentSetting result = CONTENT_SETTING_DEFAULT; content::WebContentsTester::For(web_contents()) ->NavigateAndCommit(GetDummyEmbeddingUrlWithSubdomain()); @@ -332,16 +336,16 @@ // that is same site with an existing grant should still be auto-granted. The // call is to `RequestPermission`, which checks for existing grants, while // `DecidePermission` does not. + base::test::TestFuture<ContentSetting> future; permission_context.RequestPermission(CreateFakeID(), GetRequesterURL(), true, - base::BindOnce(&SaveResult, &result)); - base::RunLoop().RunUntilIdle(); + future.GetCallback()); int implicit_grant_limit = net::features::kStorageAccessAPIDefaultImplicitGrantLimit; // We should have no prompts still and our latest result should be an allow. + EXPECT_EQ(CONTENT_SETTING_ALLOW, future.Get()); EXPECT_FALSE(manager->IsRequestInProgress()); - EXPECT_EQ(CONTENT_SETTING_ALLOW, result); EXPECT_EQ(histogram_tester().GetBucketCount( kRequestOutcomeHistogram, RequestOutcome::kGrantedByAllowance), implicit_grant_limit); @@ -364,10 +368,12 @@ histogram_tester().ExpectBucketCount(kGrantIsImplicitHistogram, /*sample=*/true, 5); - ContentSetting result = CONTENT_SETTING_DEFAULT; + base::test::TestFuture<ContentSetting> future; permission_context.DecidePermissionForTesting( fake_id, GetRequesterURL(), GetTopLevelURL(), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); + /*user_gesture=*/true, future.GetCallback()); + + // Run until the prompt is ready. base::RunLoop().RunUntilIdle(); permissions::PermissionRequestManager* manager = @@ -378,8 +384,7 @@ // Deny the prompt and validate we get the expected setting back in our // callback. manager->Deny(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CONTENT_SETTING_BLOCK, result); + EXPECT_EQ(CONTENT_SETTING_BLOCK, future.Get()); histogram_tester().ExpectTotalCount(kGrantIsImplicitHistogram, 5); histogram_tester().ExpectBucketCount(kGrantIsImplicitHistogram, @@ -405,10 +410,12 @@ histogram_tester().ExpectBucketCount(kGrantIsImplicitHistogram, /*sample=*/true, 5); - ContentSetting result = CONTENT_SETTING_DEFAULT; + base::test::TestFuture<ContentSetting> future; permission_context.DecidePermissionForTesting( fake_id, GetRequesterURL(), GetTopLevelURL(), - /*user_gesture=*/true, base::BindOnce(&SaveResult, &result)); + /*user_gesture=*/true, future.GetCallback()); + + // Run until the prompt is ready. base::RunLoop().RunUntilIdle(); permissions::PermissionRequestManager* manager = @@ -419,8 +426,7 @@ // Accept the prompt and validate we get the expected setting back in our // callback. manager->Accept(); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(CONTENT_SETTING_ALLOW, result); + EXPECT_EQ(CONTENT_SETTING_ALLOW, future.Get()); histogram_tester().ExpectTotalCount(kGrantIsImplicitHistogram, 6); histogram_tester().ExpectBucketCount(kGrantIsImplicitHistogram,
diff --git a/chrome/browser/supervised_user/OWNERS b/chrome/browser/supervised_user/OWNERS index a8ae8ed..faa42f3a 100644 --- a/chrome/browser/supervised_user/OWNERS +++ b/chrome/browser/supervised_user/OWNERS
@@ -1,19 +1 @@ -# Note: Unless you want a specific reviewer's expertise, please send CLs to -# chrome-family-kids-reviews@google.com rather than to specific individuals. -# -# These CLs will be automatically reassigned to a reviewer within -# about 5 minutes. This approach helps our team to load-balance incoming -# reviews. Googlers can read more about this at go/gwsq-gerrit. - -# ChromeOS -agawronska@chromium.org -danan@chromium.org -llin@chromium.org - -# Chrome Browser -fernandex@chromium.org -ljjlee@google.com -tju@google.com - -# Previous owner, feel free to add for any questions or historical context: -# treib@chromium.org +file://components/supervised_user/OWNERS
diff --git a/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc b/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc index 09ea57c..5a65bcd 100644 --- a/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc +++ b/chrome/browser/supervised_user/child_accounts/child_account_service_impl.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/supervised_user/kids_chrome_management/kids_profile_manager.h" #include "chrome/browser/supervised_user/kids_chrome_management/kidschromemanagement_messages.pb.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" @@ -37,6 +36,7 @@ #include "components/signin/public/identity_manager/account_info.h" #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h" #include "components/signin/public/identity_manager/tribool.h" +#include "components/supervised_user/core/common/features.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h"
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn b/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn deleted file mode 100644 index 0dd9626..0000000 --- a/chrome/browser/supervised_user/supervised_user_error_page/BUILD.gn +++ /dev/null
@@ -1,40 +0,0 @@ -# Copyright 2014 The Chromium Authors -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -if (is_android) { - import("//build/config/android/rules.gni") -} - -static_library("supervised_user_error_page") { - sources = [ - "supervised_user_error_page.cc", - "supervised_user_error_page.h", - ] - - deps = [ - "//base", - "//chrome/app:generated_resources", - "//chrome/browser:resources_grit", - "//chrome/browser/supervised_user/supervised_user_features", - "//components/signin/public/base", - "//ui/base", - "//url", - ] -} - -source_set("unit_tests") { - testonly = true - sources = [ "supervised_user_error_page_unittest.cc" ] - deps = [ - ":supervised_user_error_page", - "//base", - "//base/test:test_support", - "//chrome/app:generated_resources", - "//chrome/browser:resources_grit", - "//chrome/browser/supervised_user/supervised_user_features", - "//testing/gmock", - "//testing/gtest", - "//ui/base", - ] -}
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/DEPS b/chrome/browser/supervised_user/supervised_user_error_page/DEPS deleted file mode 100644 index 2b85ef17a..0000000 --- a/chrome/browser/supervised_user/supervised_user_error_page/DEPS +++ /dev/null
@@ -1,8 +0,0 @@ -include_rules = [ - "+chrome/app:generated_resources", - "+chrome/browser:resources_grit", - "+content/public/renderer", - "+third_party/blink", - "+url", - "+v8", -]
diff --git a/chrome/browser/supervised_user/supervised_user_features/BUILD.gn b/chrome/browser/supervised_user/supervised_user_features/BUILD.gn deleted file mode 100644 index 4c4f99a..0000000 --- a/chrome/browser/supervised_user/supervised_user_features/BUILD.gn +++ /dev/null
@@ -1,23 +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. - -static_library("supervised_user_features") { - sources = [ - "supervised_user_features.cc", - "supervised_user_features.h", - ] - - deps = [ "//base" ] -} - -source_set("unit_tests") { - testonly = true - sources = [ "supervised_user_features_unittest.cc" ] - deps = [ - ":supervised_user_features", - "//base", - "//base/test:test_support", - "//testing/gtest", - ] -}
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.cc b/chrome/browser/supervised_user/supervised_user_interstitial.cc index abbd20c..e8b9a22 100644 --- a/chrome/browser/supervised_user/supervised_user_interstitial.cc +++ b/chrome/browser/supervised_user/supervised_user_interstitial.cc
@@ -18,7 +18,6 @@ #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" @@ -29,6 +28,7 @@ #include "components/infobars/core/infobar.h" #include "components/infobars/core/infobar_delegate.h" #include "components/prefs/pref_service.h" +#include "components/supervised_user/core/common/features.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h"
diff --git a/chrome/browser/supervised_user/supervised_user_interstitial.h b/chrome/browser/supervised_user/supervised_user_interstitial.h index 158d12be..d64d2d9 100644 --- a/chrome/browser/supervised_user/supervised_user_interstitial.h +++ b/chrome/browser/supervised_user/supervised_user_interstitial.h
@@ -11,7 +11,7 @@ #include "base/callback_forward.h" #include "base/memory/raw_ptr.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include "url/gurl.h" namespace content {
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_observer.h b/chrome/browser/supervised_user/supervised_user_navigation_observer.h index d0dccaa1..ac4045a 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_observer.h +++ b/chrome/browser/supervised_user/supervised_user_navigation_observer.h
@@ -11,13 +11,13 @@ #include <vector> #include "base/memory/raw_ptr.h" -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" #include "chrome/browser/supervised_user/supervised_user_navigation_throttle.h" #include "chrome/browser/supervised_user/supervised_user_service_observer.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" #include "chrome/browser/supervised_user/supervised_users.h" #include "chrome/common/supervised_user_commands.mojom.h" #include "components/sessions/core/serialized_navigation_entry.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include "content/public/browser/render_frame_host_receiver_set.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h"
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.h b/chrome/browser/supervised_user/supervised_user_navigation_throttle.h index bfd722d..f85b819 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.h +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.h
@@ -9,9 +9,9 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" #include "chrome/browser/supervised_user/supervised_users.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include "content/public/browser/navigation_throttle.h" class SupervisedUserNavigationThrottle : public content::NavigationThrottle {
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc index 0375a28..5c4f013 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -24,7 +24,6 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/permission_request_creator_mock.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_interstitial.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_service.h" @@ -36,6 +35,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/supervised_user/core/common/features.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h"
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store.cc b/chrome/browser/supervised_user/supervised_user_pref_store.cc index e586a84..f9d188e 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" #include "chrome/common/chrome_switches.h" @@ -29,6 +28,7 @@ #include "components/prefs/pref_value_map.h" #include "components/signin/public/base/signin_pref_names.h" #include "components/signin/public/base/signin_switches.h" +#include "components/supervised_user/core/common/features.h" #include "extensions/buildflags/buildflags.h" namespace {
diff --git a/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc b/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc index e86e186..3ef30d4 100644 --- a/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc +++ b/chrome/browser/supervised_user/supervised_user_pref_store_unittest.cc
@@ -11,12 +11,12 @@ #include "base/values.h" #include "chrome/browser/prefs/incognito_mode_prefs.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_pref_store.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/common/net/safe_search_util.h" #include "chrome/common/pref_names.h" #include "components/prefs/testing_pref_store.h" +#include "components/supervised_user/core/common/features.h" #include "extensions/buildflags/buildflags.h" #include "testing/gmock/include/gmock/gmock-matchers.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/supervised_user/supervised_user_service.cc b/chrome/browser/supervised_user/supervised_user_service.cc index 3cb99ba..182c23d 100644 --- a/chrome/browser/supervised_user/supervised_user_service.cc +++ b/chrome/browser/supervised_user/supervised_user_service.cc
@@ -31,7 +31,6 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/supervised_user/permission_request_creator.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_observer.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" @@ -43,6 +42,7 @@ #include "chrome/grit/generated_resources.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" +#include "components/supervised_user/core/common/features.h" #include "components/sync/driver/sync_service.h" #include "components/sync/driver/sync_user_settings.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd b/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd index ac16af79..6fa6fb6 100644 --- a/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd +++ b/chrome/browser/supervised_user/supervised_user_unscaled_resources.grd
@@ -1,4 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- +This file is deprecated following the move of supervised user resources to //components. +TODO(b/262703607): Remove the file once the resource ID conflicts from Grit settings +have been resolved. +--> <grit latest_public_release="0" current_release="1" output_all_resource_defines="false"> <outputs> <output filename="grit/supervised_user_unscaled_resources.h" type="rc_header" > @@ -6,9 +11,4 @@ </output> <output filename="supervised_user_unscaled_resources.pak" type="data_package" /> </outputs> - <release seq="1"> - <includes> - <include name="IDR_SUPERVISED_USER_ICON" file="resources/supervised_user_icon.png" type="BINDATA" /> - </includes> - </release> </grit>
diff --git a/chrome/browser/supervised_user/supervised_user_url_filter.h b/chrome/browser/supervised_user/supervised_user_url_filter.h index 749b2be..1cbf4ae 100644 --- a/chrome/browser/supervised_user/supervised_user_url_filter.h +++ b/chrome/browser/supervised_user/supervised_user_url_filter.h
@@ -15,9 +15,9 @@ #include "base/observer_list.h" #include "base/sequence_checker.h" #include "build/chromeos_buildflags.h" -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" #include "chrome/browser/supervised_user/supervised_users.h" #include "components/safe_search_api/url_checker.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" class GURL; class SupervisedUserDenylist;
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 932388c..52066213 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1925,8 +1925,8 @@ "webui/family_link_user_internals/family_link_user_internals_ui.h", ] deps += [ - "//chrome/browser/supervised_user/supervised_user_error_page", - "//chrome/browser/supervised_user/supervised_user_features", + "//components/supervised_user/core/browser", + "//components/supervised_user/core/common", ] }
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc index 70cf647..116b6eb 100644 --- a/chrome/browser/ui/browser_live_tab_context.cc +++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/feature_list.h" +#include "base/metrics/histogram_macros.h" #include "base/token.h" #include "base/values.h" #include "chrome/browser/apps/app_service/web_contents_app_id_utils.h" @@ -219,6 +220,10 @@ user_agent_override, extra_data, false /* from_session_restore */); } + // Record the metrics for restoring closed tabs. Set to true when the tab is + // restored from closed tab cache and false otherwise. + UMA_HISTOGRAM_BOOLEAN("Tab.RestoreClosedTab", restored_from_closed_tab_cache); + // Only update the metadata if the group doesn't already exist since the // existing group has the latest metadata, which may have changed from the // time the tab was closed.
diff --git a/chrome/browser/ui/extensions/hosted_app_browsertest.cc b/chrome/browser/ui/extensions/hosted_app_browsertest.cc index 70a53ba..6fdfeebf 100644 --- a/chrome/browser/ui/extensions/hosted_app_browsertest.cc +++ b/chrome/browser/ui/extensions/hosted_app_browsertest.cc
@@ -237,9 +237,7 @@ DCHECK_EQ(GetParam(), AppType::HOSTED_APP); const Extension* app = InstallExtensionWithSourceAndFlags( app_folder, 1, extensions::mojom::ManifestLocation::kInternal, - app_type_ == AppType::HOSTED_APP - ? extensions::Extension::NO_FLAGS - : extensions::Extension::FROM_BOOKMARK); + extensions::Extension::NO_FLAGS); ASSERT_TRUE(app); app_id_ = app->id();
diff --git a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc index bbeeba0..34664c46 100644 --- a/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc +++ b/chrome/browser/ui/views/intent_picker_bubble_view_browsertest.cc
@@ -269,10 +269,18 @@ EXPECT_TRUE(intent_picker_icon->GetVisible()); } +// TODO(crbug.com/1399441): This test is flaky. Re-enable this test. // Tests that the intent picker icon is not visible if the navigation redirects // to a URL that doesn't have an installed PWA. +#if BUILDFLAG(IS_MAC) +#define MAYBE_DoesNotShowIntentPickerWhenRedirectedOutOfScope \ + DISABLED_DoesNotShowIntentPickerWhenRedirectedOutOfScope +#else +#define MAYBE_DoesNotShowIntentPickerWhenRedirectedOutOfScope \ + DoesNotShowIntentPickerWhenRedirectedOutOfScope +#endif IN_PROC_BROWSER_TEST_P(IntentPickerBubbleViewBrowserTest, - DoesNotShowIntentPickerWhenRedirectedOutOfScope) { + MAYBE_DoesNotShowIntentPickerWhenRedirectedOutOfScope) { InstallTestWebApp(GetOtherAppUrlHost(), /*app_scope=*/"/"); const GURL out_of_scope_url =
diff --git a/chrome/browser/ui/views/tabs/tab_strip_layout_helper.h b/chrome/browser/ui/views/tabs/tab_strip_layout_helper.h index 57017498..d996b86 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_layout_helper.h +++ b/chrome/browser/ui/views/tabs/tab_strip_layout_helper.h
@@ -138,11 +138,6 @@ // in |slots_|. int GetSlotIndexForGroupHeader(tab_groups::TabGroupId group) const; - // Compares |cached_slots_| to the TabAnimations in |animator_| and DCHECKs if - // the TabAnimation::ViewType do not match. Prevents bugs that could cause the - // wrong callback being run when a tab or group is deleted. - void VerifyAnimationsMatchTabSlots() const; - // Updates the value of either |active_tab_width_| or |inactive_tab_width_|, // as appropriate. void UpdateCachedTabWidth(int tab_index, int tab_width, bool active);
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc index d8cdb0c..b086d85 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler.cc +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler.cc
@@ -93,7 +93,8 @@ web_app_provider_(web_app::WebAppProvider::GetForWebApps(profile)), extension_service_( extensions::ExtensionSystem::Get(profile)->extension_service()) { - web_app_registrar_observation_.Observe(&web_app_provider_->registrar()); + web_app_registrar_observation_.Observe( + &web_app_provider_->registrar_unsafe()); install_manager_observation_.Observe(&web_app_provider_->install_manager()); ExtensionRegistry::Get(profile)->AddObserver(this); } @@ -200,7 +201,7 @@ app_home::mojom::AppInfoPtr AppHomePageHandler::CreateAppInfoPtrFromWebApp( const web_app::AppId& app_id) { - auto& registrar = web_app_provider_->registrar(); + auto& registrar = web_app_provider_->registrar_unsafe(); auto app_info = app_home::mojom::AppInfo::New(); @@ -251,7 +252,7 @@ void AppHomePageHandler::FillWebAppInfoList( std::vector<app_home::mojom::AppInfoPtr>* result) { - web_app::WebAppRegistrar& registrar = web_app_provider_->registrar(); + web_app::WebAppRegistrar& registrar = web_app_provider_->registrar_unsafe(); for (const web_app::AppId& web_app_id : registrar.GetAppIds()) { if (IsYoutubeExtension(web_app_id)) @@ -454,7 +455,7 @@ if (extension_dialog_prompting_) return; - if (web_app_provider_->registrar().IsInstalled(app_id) && + if (web_app_provider_->registrar_unsafe().IsInstalled(app_id) && !IsYoutubeExtension(app_id)) { UninstallWebApp(app_id); return; @@ -469,7 +470,7 @@ } void AppHomePageHandler::ShowAppSettings(const std::string& app_id) { - if (web_app_provider_->registrar().IsInstalled(app_id) && + if (web_app_provider_->registrar_unsafe().IsInstalled(app_id) && !IsYoutubeExtension(app_id)) { ShowWebAppSettings(app_id); return; @@ -488,7 +489,7 @@ void AppHomePageHandler::CreateAppShortcut(const std::string& app_id, CreateAppShortcutCallback callback) { - if (web_app_provider_->registrar().IsInstalled(app_id) && + if (web_app_provider_->registrar_unsafe().IsInstalled(app_id) && !IsYoutubeExtension(app_id)) { CreateWebAppShortcut(app_id, std::move(callback)); return; @@ -514,7 +515,7 @@ GURL full_launch_url; apps::LaunchContainer launch_container; - web_app::WebAppRegistrar& registrar = web_app_provider_->registrar(); + web_app::WebAppRegistrar& registrar = web_app_provider_->registrar_unsafe(); if (registrar.IsInstalled(app_id) && !IsYoutubeExtension(app_id)) { type = extensions::Manifest::Type::TYPE_HOSTED_APP; full_launch_url = registrar.GetAppStartUrl(app_id);
diff --git a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc index 01283fb9..d2f138f 100644 --- a/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc +++ b/chrome/browser/ui/webui/app_home/app_home_page_handler_browsertest.cc
@@ -466,7 +466,7 @@ loop.Run(); EXPECT_EQ(web_app::RunOnOsLoginMode::kWindowed, web_app::WebAppProvider::GetForWebApps(profile()) - ->registrar() + ->registrar_unsafe() .GetAppRunOnOsLoginMode(installed_app_id) .value); }
diff --git a/chrome/browser/ui/webui/ash/drive_internals_ui.cc b/chrome/browser/ui/webui/ash/drive_internals_ui.cc index 072df69..68b6ed5 100644 --- a/chrome/browser/ui/webui/ash/drive_internals_ui.cc +++ b/chrome/browser/ui/webui/ash/drive_internals_ui.cc
@@ -93,6 +93,56 @@ } } +std::string BulkPinSetupStageToString(drivefs::pinning::SetupStage stage) { + using drivefs::pinning::SetupStage; + switch (stage) { + case SetupStage::kFinishedSetup: + return "kFinishedSetup"; + case SetupStage::kFinishedSetupWithError: + return "kFinishedSetupWithError"; + case SetupStage::kCalculatedFreeLocalDiskSpace: + return "kCalculatedFreeLocalDiskSpace"; + case SetupStage::kCalculatedRequiredDiskSpace: + return "kCalculatedRequiredDiskSpace"; + case SetupStage::kNotStarted: + return "kNotStarted"; + case SetupStage::kStarted: + return "kStarted"; + default: + return "SetupStage(Unknown)"; + } +} + +std::string BulkPinSetupErrorToString(drivefs::pinning::SetupError error) { + using drivefs::pinning::SetupError; + switch (error) { + case SetupError::kSuccess: + return "kSuccess"; + case SetupError::kManagerDisabled: + return "kManagerDisabled"; + case SetupError::kErrorCalculatingFreeDiskSpace: + return "kErrorCalculatingFreeDiskSpace"; + case SetupError::kErrorRetrievingSearchResults: + return "kErrorRetrievingSearchResults"; + case SetupError::kErrorResultsReturnedInvalid: + return "kErrorResultsReturnedInvalid"; + case SetupError::kErrorNotEnoughFreeSpace: + return "kErrorNotEnoughFreeSpace"; + case SetupError::kErrorRetrievingSearchResultsForPinning: + return "kErrorRetrievingSearchResultsForPinning"; + case SetupError::kErrorResultsReturnedInvalidForPinning: + return "kErrorResultsReturnedInvalidForPinning"; + case SetupError::kErrorFailedToPinItem: + return "kErrorFailedToPinItem"; + case SetupError::kErrorSearchQueryNotBound: + return "kErrorSearchQueryNotBound"; + case SetupError::kErrorManagerStopped: + return "kErrorManagerStopped"; + default: + return "SetupError(Unknown)"; + } +} + // Gets metadata of all files and directories in |root_path| // recursively. Stores the result as a list of dictionaries like: // @@ -608,8 +658,12 @@ void OnSetupProgress( const drivefs::pinning::SetupProgress& progress) override { base::Value::Dict setup_progress; - setup_progress.Set("stage", - base::NumberToString(static_cast<int>(progress.stage))); + setup_progress.Set("stage", BulkPinSetupStageToString(progress.stage)); + if (progress.stage == + drivefs::pinning::SetupStage::kFinishedSetupWithError) { + setup_progress.Set("setupError", + BulkPinSetupErrorToString(progress.error)); + } setup_progress.Set("availableDiskSpace", base::NumberToString(progress.available_disk_space)); setup_progress.Set("requiredDiskSpace",
diff --git a/chrome/browser/ui/webui/extensions/extensions_internals_source.cc b/chrome/browser/ui/webui/extensions/extensions_internals_source.cc index 05816ec0b..55885da 100644 --- a/chrome/browser/ui/webui/extensions/extensions_internals_source.cc +++ b/chrome/browser/ui/webui/extensions/extensions_internals_source.cc
@@ -105,8 +105,6 @@ flags_value.Append("ALLOW_FILE_ACCESS"); if (creation_flags & extensions::Extension::FROM_WEBSTORE) flags_value.Append("FROM_WEBSTORE"); - if (creation_flags & extensions::Extension::FROM_BOOKMARK) - flags_value.Append("FROM_BOOKMARK"); if (creation_flags & extensions::Extension::FOLLOW_SYMLINKS_ANYWHERE) flags_value.Append("FOLLOW_SYMLINKS_ANYWHERE"); if (creation_flags & extensions::Extension::ERROR_ON_PRIVATE_KEY) @@ -127,29 +125,47 @@ } base::Value::List DisableReasonsToList(int disable_reasons) { + static_assert(extensions::disable_reason::DISABLE_REASON_LAST == 1 << 22, + "Please add your new disable reason here."); + base::Value::List disable_reasons_value; + if (disable_reasons & extensions::disable_reason::DISABLE_USER_ACTION) { + disable_reasons_value.Append("DISABLE_USER_ACTION"); + } if (disable_reasons & extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE) { disable_reasons_value.Append("DISABLE_PERMISSIONS_INCREASE"); } - if (disable_reasons & extensions::disable_reason::DISABLE_RELOAD) + if (disable_reasons & extensions::disable_reason::DISABLE_RELOAD) { disable_reasons_value.Append("DISABLE_RELOAD"); + } if (disable_reasons & extensions::disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT) { disable_reasons_value.Append("DISABLE_UNSUPPORTED_REQUIREMENT"); } - if (disable_reasons & extensions::disable_reason::DISABLE_SIDELOAD_WIPEOUT) + if (disable_reasons & extensions::disable_reason::DISABLE_SIDELOAD_WIPEOUT) { disable_reasons_value.Append("DISABLE_SIDELOAD_WIPEOUT"); - if (disable_reasons & extensions::disable_reason::DISABLE_NOT_VERIFIED) + } + if (disable_reasons & + extensions::disable_reason::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC) { + disable_reasons_value.Append("DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC"); + } + if (disable_reasons & extensions::disable_reason::DISABLE_NOT_VERIFIED) { disable_reasons_value.Append("DISABLE_NOT_VERIFIED"); - if (disable_reasons & extensions::disable_reason::DISABLE_GREYLIST) + } + if (disable_reasons & extensions::disable_reason::DISABLE_GREYLIST) { disable_reasons_value.Append("DISABLE_GREYLIST"); - if (disable_reasons & extensions::disable_reason::DISABLE_CORRUPTED) + } + if (disable_reasons & extensions::disable_reason::DISABLE_CORRUPTED) { disable_reasons_value.Append("DISABLE_CORRUPTED"); - if (disable_reasons & extensions::disable_reason::DISABLE_REMOTE_INSTALL) + } + if (disable_reasons & extensions::disable_reason::DISABLE_REMOTE_INSTALL) { disable_reasons_value.Append("DISABLE_REMOTE_INSTALL"); - if (disable_reasons & extensions::disable_reason::DISABLE_EXTERNAL_EXTENSION) + } + if (disable_reasons & + extensions::disable_reason::DISABLE_EXTERNAL_EXTENSION) { disable_reasons_value.Append("DISABLE_EXTERNAL_EXTENSION"); + } if (disable_reasons & extensions::disable_reason::DISABLE_UPDATE_REQUIRED_BY_POLICY) { disable_reasons_value.Append("DISABLE_UPDATE_REQUIRED_BY_POLICY"); @@ -158,10 +174,23 @@ extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED) { disable_reasons_value.Append("DISABLE_CUSTODIAN_APPROVAL_REQUIRED"); } - if (disable_reasons & extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY) + if (disable_reasons & extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY) { disable_reasons_value.Append("DISABLE_BLOCKED_BY_POLICY"); + } + if (disable_reasons & extensions::disable_reason::DISABLE_REINSTALL) { + disable_reasons_value.Append("DISABLE_REINSTALL"); + } + if (disable_reasons & extensions::disable_reason::DISABLE_NOT_ALLOWLISTED) { + disable_reasons_value.Append("DISABLE_NOT_ALLOWLISTED"); + } + if (disable_reasons & + extensions::disable_reason::DISABLE_NOT_ASH_KEEPLISTED) { + disable_reasons_value.Append("DISABLE_NOT_ASH_KEEPLISTED"); + } + return disable_reasons_value; } + // The JSON we generate looks like this: // Note: // - tab_specific permissions can have 0 or more DICT entries with each tab id
diff --git a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc index 7903f5d..a5d13f8 100644 --- a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc +++ b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/child_accounts/child_account_service.h" -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/supervised_user/supervised_user_settings_service.h" #include "chrome/browser/supervised_user/supervised_user_settings_service_factory.h" @@ -23,6 +22,7 @@ #include "chrome/common/channel_info.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/tribool.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include "components/url_formatter/url_fixer.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h"
diff --git a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h index df72d37a..073be2b 100644 --- a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h +++ b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h
@@ -8,10 +8,10 @@ #include "base/callback_list.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_observer.h" #include "chrome/browser/supervised_user/supervised_user_url_filter.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include "content/public/browser/web_ui_message_handler.h" // The implementation for the chrome://family-link-user-internals page.
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index 8a25a75..010554f 100644 --- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -67,8 +67,8 @@ #endif #if BUILDFLAG(ENABLE_SUPERVISED_USERS) -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" // nogncheck #include "chrome/browser/supervised_user/supervised_user_interstitial.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" // nogncheck #endif using security_interstitials::TestSafeBrowsingBlockingPageQuiet;
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom index 183df02..bb5ca13f 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom
@@ -83,6 +83,9 @@ // Sets theme to default classic chrome. SetClassicChromeDefaultTheme(); + + // Choose custom background from local file system. + ChooseLocalCustomBackground() => (bool success); }; // WebUI-side handler for requests from the browser.
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc index 9a9b5107..0bc2111 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/chrome_select_file_policy.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_colors.h" @@ -49,6 +50,9 @@ CustomizeChromePageHandler::~CustomizeChromePageHandler() { ntp_background_service_->RemoveObserver(this); + if (select_file_dialog_) { + select_file_dialog_->ListenerDestroyed(); + } } void CustomizeChromePageHandler::SetMostVisitedSettings( @@ -138,6 +142,34 @@ theme_service_->UseDefaultTheme(); } +void CustomizeChromePageHandler::ChooseLocalCustomBackground( + ChooseLocalCustomBackgroundCallback callback) { + // Early return if the select file dialog is already active. + if (select_file_dialog_) { + std::move(callback).Run(false); + return; + } + + select_file_dialog_ = ui::SelectFileDialog::Create( + this, std::make_unique<ChromeSelectFilePolicy>(web_contents_)); + ui::SelectFileDialog::FileTypeInfo file_types; + file_types.allowed_paths = ui::SelectFileDialog::FileTypeInfo::NATIVE_PATH; + file_types.extensions.resize(1); + file_types.extensions[0].push_back(FILE_PATH_LITERAL("jpg")); + file_types.extensions[0].push_back(FILE_PATH_LITERAL("jpeg")); + file_types.extensions[0].push_back(FILE_PATH_LITERAL("png")); + file_types.extensions[0].push_back(FILE_PATH_LITERAL("gif")); + file_types.extension_description_overrides.push_back( + l10n_util::GetStringUTF16(IDS_UPLOAD_IMAGE_FORMAT)); + DCHECK(!choose_local_custom_background_callback_); + choose_local_custom_background_callback_ = std::move(callback); + select_file_dialog_->SelectFile( + ui::SelectFileDialog::SELECT_OPEN_FILE, std::u16string(), + profile_->last_selected_directory(), &file_types, 0, + base::FilePath::StringType(), web_contents_->GetTopLevelNativeWindow(), + nullptr); +} + void CustomizeChromePageHandler::OnNativeThemeUpdated( ui::NativeTheme* observed_theme) { UpdateTheme(); @@ -194,3 +226,23 @@ ntp_background_service_->RemoveObserver(this); ntp_background_service_ = nullptr; } + +void CustomizeChromePageHandler::FileSelected(const base::FilePath& path, + int index, + void* params) { + DCHECK(choose_local_custom_background_callback_); + if (ntp_custom_background_service_) { + profile_->set_last_selected_directory(path.DirName()); + ntp_custom_background_service_->SelectLocalBackgroundImage(path); + } + + select_file_dialog_ = nullptr; + std::move(choose_local_custom_background_callback_).Run(true); +} + +void CustomizeChromePageHandler::FileSelectionCanceled(void* params) { + DCHECK(choose_local_custom_background_callback_); + select_file_dialog_ = nullptr; + + std::move(choose_local_custom_background_callback_).Run(false); +}
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h index 1a5b1d78..9fea65eb6 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h
@@ -18,6 +18,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "ui/native_theme/native_theme.h" #include "ui/native_theme/native_theme_observer.h" +#include "ui/shell_dialogs/select_file_dialog.h" namespace content { class WebContents; @@ -29,7 +30,8 @@ : public side_panel::mojom::CustomizeChromePageHandler, public NtpBackgroundServiceObserver, public ui::NativeThemeObserver, - public ThemeServiceObserver { + public ThemeServiceObserver, + public ui::SelectFileDialog::Listener { public: CustomizeChromePageHandler( mojo::PendingReceiver<side_panel::mojom::CustomizeChromePageHandler> @@ -54,6 +56,8 @@ void SetDefaultColor() override; void SetForegroundColor(SkColor foreground_color) override; void SetClassicChromeDefaultTheme() override; + void ChooseLocalCustomBackground( + ChooseLocalCustomBackgroundCallback callback) override; private: // ui::NativeThemeObserver: @@ -71,8 +75,16 @@ void OnNextCollectionImageAvailable() override; void OnNtpBackgroundServiceShuttingDown() override; + // SelectFileDialog::Listener: + void FileSelected(const base::FilePath& path, + int index, + void* params) override; + void FileSelectionCanceled(void* params) override; + + ChooseLocalCustomBackgroundCallback choose_local_custom_background_callback_; raw_ptr<NtpCustomBackgroundService> ntp_custom_background_service_; raw_ptr<Profile> profile_; + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; raw_ptr<content::WebContents> web_contents_; raw_ptr<NtpBackgroundService> ntp_background_service_; GetBackgroundCollectionsCallback background_collections_callback_;
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc index df9063e..1a06c9e02 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/themes/theme_service.h" #include "chrome/browser/themes/theme_service_factory.h" +#include "chrome/browser/ui/chrome_select_file_policy.h" #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom.h" @@ -38,6 +39,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/color/color_provider.h" #include "ui/native_theme/native_theme.h" +#include "ui/shell_dialogs/select_file_dialog_factory.h" namespace content { class BrowserContext; @@ -47,6 +49,77 @@ using testing::_; +// A test SelectFileDialog to go straight to calling the listener. +class TestSelectFileDialog : public ui::SelectFileDialog { + public: + TestSelectFileDialog(Listener* listener, + std::unique_ptr<ui::SelectFilePolicy> policy, + const bool auto_cancel) + : ui::SelectFileDialog(listener, std::move(policy)), + auto_cancel_(auto_cancel) {} + + TestSelectFileDialog(const TestSelectFileDialog&) = delete; + TestSelectFileDialog& operator=(const TestSelectFileDialog&) = delete; + + protected: + ~TestSelectFileDialog() override = default; + + void SelectFileImpl(Type type, + const std::u16string& title, + const base::FilePath& default_path, + const FileTypeInfo* file_types, + int file_type_index, + const base::FilePath::StringType& default_extension, + gfx::NativeWindow owning_window, + void* params, + const GURL* caller) override { + if (auto_cancel_) { + listener_->FileSelectionCanceled(params); + } else { + listener_->FileSelected(base::FilePath(FILE_PATH_LITERAL("/test/path")), + file_type_index, params); + } + } + // Pure virtual methods that need to be implemented. + bool IsRunning(gfx::NativeWindow owning_window) const override { + return false; + } + void ListenerDestroyed() override {} + bool HasMultipleFileTypeChoicesImpl() override { return false; } + + private: + bool auto_cancel_; +}; + +class TestSelectFilePolicy : public ui::SelectFilePolicy { + public: + TestSelectFilePolicy& operator=(const TestSelectFilePolicy&) = delete; + + // Pure virtual methods that need to be implemented. + bool CanOpenSelectFileDialog() override { return true; } + void SelectFileDenied() override {} +}; + +// A test SelectFileDialogFactory so that the TestSelectFileDialog is used. +class TestSelectFileDialogFactory : public ui::SelectFileDialogFactory { + public: + explicit TestSelectFileDialogFactory(bool auto_cancel) + : auto_cancel_(auto_cancel) {} + + TestSelectFileDialogFactory& operator=(const TestSelectFileDialogFactory&) = + delete; + + ui::SelectFileDialog* Create( + ui::SelectFileDialog::Listener* listener, + std::unique_ptr<ui::SelectFilePolicy> policy) override { + return new TestSelectFileDialog( + listener, std::make_unique<TestSelectFilePolicy>(), auto_cancel_); + } + + private: + bool auto_cancel_; +}; + class MockPage : public side_panel::mojom::CustomizeChromePage { public: MockPage() = default; @@ -71,6 +144,7 @@ : NtpCustomBackgroundService(profile) {} MOCK_METHOD0(GetCustomBackground, absl::optional<CustomBackground>()); MOCK_METHOD0(ResetCustomBackgroundInfo, void()); + MOCK_METHOD1(SelectLocalBackgroundImage, void(const base::FilePath&)); }; class MockNtpBackgroundService : public NtpBackgroundService { @@ -385,3 +459,33 @@ handler().SetClassicChromeDefaultTheme(); } + +TEST_F(CustomizeChromePageHandlerTest, ChooseLocalCustomBackgroundSuccess) { + bool success; + base::MockCallback< + CustomizeChromePageHandler::ChooseLocalCustomBackgroundCallback> + callback; + ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory(false)); + EXPECT_CALL(callback, Run(testing::_)) + .Times(1) + .WillOnce(testing::Invoke( + [&success](bool success_arg) { success = std::move(success_arg); })); + EXPECT_CALL(mock_ntp_custom_background_service_, SelectLocalBackgroundImage) + .Times(1); + handler().ChooseLocalCustomBackground(callback.Get()); + EXPECT_TRUE(success); +} + +TEST_F(CustomizeChromePageHandlerTest, ChooseLocalCustomBackgroundCancel) { + bool success; + base::MockCallback< + CustomizeChromePageHandler::ChooseLocalCustomBackgroundCallback> + callback; + ui::SelectFileDialog::SetFactory(new TestSelectFileDialogFactory(true)); + EXPECT_CALL(callback, Run(testing::_)) + .Times(1) + .WillOnce(testing::Invoke( + [&success](bool success_arg) { success = std::move(success_arg); })); + handler().ChooseLocalCustomBackground(callback.Get()); + EXPECT_TRUE(!success); +}
diff --git a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc index 54e98d5..359dfd6a 100644 --- a/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc +++ b/chrome/browser/web_applications/extensions/web_app_policy_manager_unittest.cc
@@ -16,6 +16,7 @@ #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" #include "base/values.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -519,6 +520,13 @@ unhashed_app_id); } + void WaitForAppsToSynchronize() { + base::RunLoop loop; + policy_manager().SetOnAppsSynchronizedCompletedCallbackForTesting( + loop.QuitClosure()); + loop.Run(); + } + private: webapps::InstallResultCode install_result_code_ = webapps::InstallResultCode::kSuccessNewInstall; @@ -537,8 +545,6 @@ if (ShouldSkipPWASpecificTest()) return; - base::RunLoop().RunUntilIdle(); - const auto& install_requests = externally_managed_app_manager().install_requests(); EXPECT_TRUE(install_requests.empty()); @@ -551,7 +557,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, base::Value::List()); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -686,7 +692,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -706,7 +712,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -726,7 +732,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -747,7 +753,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -769,7 +775,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -789,7 +795,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -809,7 +815,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -829,7 +835,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -854,7 +860,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); } - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); // Change custom name { base::Value::List list; @@ -862,7 +868,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); } - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -895,7 +901,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(first_list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -910,7 +916,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(second_list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); expected_install_options_list.push_back(GetTabbedInstallOptions()); @@ -935,7 +941,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(first_list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); // We should only try to install the app in the policy. std::vector<ExternalInstallOptions> expected_install_options_list; @@ -953,7 +959,6 @@ TEST_P(WebAppPolicyManagerTest, UninstallAppInstalledInCurrentSession) { if (ShouldSkipPWASpecificTest()) return; - base::RunLoop().RunUntilIdle(); // Add two sites, one that opens in a window and one that opens in a tab. base::Value::List first_list; @@ -961,7 +966,7 @@ first_list.Append(GetTabbedItem()); profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(first_list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -977,7 +982,7 @@ second_list.Append(GetWindowedItem()); profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(second_list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); // We'll try to install the app again but ExternallyManagedAppManager will // handle not re-installing the app. @@ -998,7 +1003,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); std::vector<ExternalInstallOptions> expected_options_list; expected_options_list.push_back(GetWindowedInstallOptions()); @@ -1008,8 +1013,13 @@ EXPECT_EQ(expected_options_list, install_options_list); MakeInstalledAppPlaceholder(GURL(kWindowedUrl)); - policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl)); - base::RunLoop().RunUntilIdle(); + base::test::TestFuture<const GURL&, + ExternallyManagedAppManager::InstallResult> + future; + policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl), + future.GetCallback()); + EXPECT_EQ(future.Get<1>().code, + webapps::InstallResultCode::kSuccessNewInstall); auto reinstall_options = GetWindowedInstallOptions(); reinstall_options.install_placeholder = false; @@ -1028,7 +1038,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); std::vector<ExternalInstallOptions> expected_options_list; expected_options_list.push_back(GetWindowedInstallOptions()); @@ -1038,8 +1048,13 @@ EXPECT_EQ(expected_options_list, install_options_list); // By default, the app being installed is not a placeholder app. - policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl)); - base::RunLoop().RunUntilIdle(); + base::test::TestFuture<const GURL&, + ExternallyManagedAppManager::InstallResult> + future; + policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl), + future.GetCallback()); + EXPECT_EQ(future.Get<1>().code, + webapps::InstallResultCode::kFailedPlaceholderUninstall); // No other options are added to list as the app is currently not // installed as a placeholder app. @@ -1056,7 +1071,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); std::vector<ExternalInstallOptions> expected_options_list; expected_options_list.push_back(GetFallbackAppNameInstallOptions()); @@ -1066,8 +1081,13 @@ EXPECT_EQ(expected_options_list, install_options_list); MakeInstalledAppPlaceholder(GURL(kWindowedUrl)); - policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl)); - base::RunLoop().RunUntilIdle(); + base::test::TestFuture<const GURL&, + ExternallyManagedAppManager::InstallResult> + future; + policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kWindowedUrl), + future.GetCallback()); + EXPECT_EQ(future.Get<1>().code, + webapps::InstallResultCode::kSuccessNewInstall); auto reinstall_options = GetFallbackAppNameInstallOptions(); reinstall_options.install_placeholder = false; @@ -1086,7 +1106,7 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); std::vector<ExternalInstallOptions> expected_options_list; expected_options_list.push_back(GetWindowedInstallOptions()); @@ -1095,9 +1115,14 @@ externally_managed_app_manager().install_requests(); EXPECT_EQ(expected_options_list, install_options_list); + base::test::TestFuture<const GURL&, + ExternallyManagedAppManager::InstallResult> + future; // Try to reinstall for app not installed by policy. - policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kTabbedUrl)); - base::RunLoop().RunUntilIdle(); + policy_manager().ReinstallPlaceholderAppIfNecessary(GURL(kTabbedUrl), + future.GetCallback()); + EXPECT_EQ(future.Get<1>().code, + webapps::InstallResultCode::kFailedPlaceholderUninstall); EXPECT_EQ(expected_options_list, install_options_list); } @@ -1105,7 +1130,6 @@ TEST_P(WebAppPolicyManagerTest, SayRefreshTwoTimesQuickly) { if (ShouldSkipPWASpecificTest()) return; - base::RunLoop().RunUntilIdle(); // Add an app. { base::Value::List list; @@ -1120,7 +1144,10 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); } - base::RunLoop().RunUntilIdle(); + + // `OnAppsSynchronized` should be triggered twice. + WaitForAppsToSynchronize(); + WaitForAppsToSynchronize(); // Both apps should have been installed. std::vector<ExternalInstallOptions> expected_options_list; @@ -1156,7 +1183,7 @@ histograms.ExpectTotalCount( WebAppPolicyManager::kInstallResultHistogramName, 0); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); histograms.ExpectTotalCount( WebAppPolicyManager::kInstallResultHistogramName, 1); @@ -1174,7 +1201,8 @@ profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - base::RunLoop().RunUntilIdle(); + WaitForAppsToSynchronize(); + histograms.ExpectTotalCount( WebAppPolicyManager::kInstallResultHistogramName, 3); histograms.ExpectBucketCount( @@ -1185,8 +1213,6 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) TEST_P(WebAppPolicyManagerTest, DisableSystemWebApps) { - base::RunLoop().RunUntilIdle(); - auto disabled_apps = policy_manager().GetDisabledSystemWebApps(); EXPECT_TRUE(disabled_apps.empty()); @@ -1262,12 +1288,9 @@ list.Append(GetWindowedItem()); list.Append(GetTabbedItem()); - base::RunLoop loop; - policy_manager().SetOnAppsSynchronizedCompletedCallbackForTesting( - loop.QuitClosure()); profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - loop.Run(); + WaitForAppsToSynchronize(); const auto& install_requests = externally_managed_app_manager().install_requests(); @@ -1322,12 +1345,9 @@ list.Append(GetWindowedItem()); list.Append(GetTabbedItem()); - base::RunLoop force_install_loop; - policy_manager().SetOnAppsSynchronizedCompletedCallbackForTesting( - force_install_loop.QuitClosure()); profile()->GetPrefs()->SetList(prefs::kWebAppInstallForceList, std::move(list)); - force_install_loop.Run(); + WaitForAppsToSynchronize(); provider()->command_manager().AwaitAllCommandsCompleteForTesting();
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.cc b/chrome/browser/web_applications/policy/web_app_policy_manager.cc index 83ccc9a..4ac2bff 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.cc +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.cc
@@ -118,7 +118,10 @@ system_web_apps_delegate_map_ = system_web_apps_delegate_map; } -void WebAppPolicyManager::Start(base::OnceClosure on_done) { +void WebAppPolicyManager::Start(base::OnceClosure initialization_complete) { + DCHECK(initialization_complete_.is_null()); + + initialization_complete_ = std::move(initialization_complete); // When Lacros is enabled, don't run PWA-specific logic in Ash. // TODO(crbug.com/1251491): Consider factoring out logic that should only run // in Ash into a separate class. This way, when running in Ash, we won't need @@ -131,11 +134,12 @@ ->PostTask(FROM_HERE, base::BindOnce( &WebAppPolicyManager::InitChangeRegistrarAndRefreshPolicy, - weak_ptr_factory_.GetWeakPtr(), enable_pwa_support) - .Then(std::move(on_done))); + weak_ptr_factory_.GetWeakPtr(), enable_pwa_support)); } -void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary(const GURL& url) { +void WebAppPolicyManager::ReinstallPlaceholderAppIfNecessary( + const GURL& url, + ExternallyManagedAppManager::OnceInstallCallback on_complete) { const base::Value::List& web_apps = pref_service_->GetList(prefs::kWebAppInstallForceList); const auto& web_apps_list = web_apps; @@ -149,13 +153,21 @@ app_registrar_->LookupPlaceholderAppId(url, WebAppManagement::kPolicy) .has_value(); - if (it == web_apps_list.end() || !is_placeholder_url) + if (it == web_apps_list.end() || !is_placeholder_url) { + std::move(on_complete) + .Run(url, ExternallyManagedAppManager::InstallResult( + webapps::InstallResultCode::kFailedPlaceholderUninstall)); return; + } ExternalInstallOptions install_options = ParseInstallPolicyEntry(*it); - if (!install_options.install_url.is_valid()) + if (!install_options.install_url.is_valid()) { + std::move(on_complete) + .Run(url, ExternallyManagedAppManager::InstallResult( + webapps::InstallResultCode::kInstallURLInvalid)); return; + } // No need to install a placeholder because there should be one already. install_options.wait_for_windows_closed = true; @@ -164,7 +176,7 @@ // If the app is not a placeholder app, ExternallyManagedAppManager will // ignore the request. externally_managed_app_manager_->InstallNow(std::move(install_options), - base::DoNothing()); + std::move(on_complete)); } // static @@ -204,6 +216,10 @@ weak_ptr_factory_.GetWeakPtr())); RefreshPolicyInstalledIsolatedWebApps(); #endif + } else { + if (initialization_complete_) { + std::move(initialization_complete_).Run(); + } } ObserveDisabledSystemFeaturesPolicy(); } @@ -538,7 +554,7 @@ void WebAppPolicyManager::SetOnAppsSynchronizedCompletedCallbackForTesting( base::OnceClosure callback) { - on_apps_synchronized_ = std::move(callback); + on_apps_synchronized_for_testing_ = std::move(callback); } void WebAppPolicyManager::SetRefreshPolicySettingsCompletedCallbackForTesting( @@ -631,8 +647,13 @@ url_and_result.second.code); } - if (on_apps_synchronized_) - std::move(on_apps_synchronized_).Run(); + if (on_apps_synchronized_for_testing_) { + std::move(on_apps_synchronized_for_testing_).Run(); + } + + if (initialization_complete_) { + std::move(initialization_complete_).Run(); + } } WebAppPolicyManager::WebAppSetting::WebAppSetting() {
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager.h b/chrome/browser/web_applications/policy/web_app_policy_manager.h index 6ea29f7..f37be5a 100644 --- a/chrome/browser/web_applications/policy/web_app_policy_manager.h +++ b/chrome/browser/web_applications/policy/web_app_policy_manager.h
@@ -65,9 +65,13 @@ void SetSystemWebAppDelegateMap( const ash::SystemWebAppDelegateMap* system_web_apps_delegate_map); + // `initialization_complete` waits for the first `SynchronizeInstalledApps` to + // finish if it's triggered on `Start`. void Start(base::OnceClosure initialization_complete); - void ReinstallPlaceholderAppIfNecessary(const GURL& url); + void ReinstallPlaceholderAppIfNecessary( + const GURL& url, + ExternallyManagedAppManager::OnceInstallCallback on_complete); static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); @@ -190,7 +194,7 @@ // Testing callbacks base::OnceClosure refresh_policy_settings_completed_; - base::OnceClosure on_apps_synchronized_; + base::OnceClosure on_apps_synchronized_for_testing_; bool is_refreshing_ = false; bool needs_refresh_ = false; @@ -200,6 +204,9 @@ std::unique_ptr<WebAppSetting> default_settings_; ExternallyInstalledWebAppPrefs externally_installed_app_prefs_; + + base::OnceClosure initialization_complete_; + #if BUILDFLAG(IS_CHROMEOS) std::unique_ptr<IsolatedWebAppPolicyManager> iwa_policy_manager_; #endif
diff --git a/chrome/browser/web_applications/web_app_tab_helper.cc b/chrome/browser/web_applications/web_app_tab_helper.cc index 3a2e469..2160a8b3 100644 --- a/chrome/browser/web_applications/web_app_tab_helper.cc +++ b/chrome/browser/web_applications/web_app_tab_helper.cc
@@ -178,7 +178,8 @@ } void WebAppTabHelper::ReinstallPlaceholderAppIfNecessary(const GURL& url) { - provider_->policy_manager().ReinstallPlaceholderAppIfNecessary(url); + provider_->policy_manager().ReinstallPlaceholderAppIfNecessary( + url, base::DoNothing()); } absl::optional<AppId> WebAppTabHelper::FindAppWithUrlInScope(
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index db2d98f7..e51cd9c 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1671105478-9542d88baf5f95c811a54a0ffc94796550dcf945.profdata +chrome-mac-main-1671126672-5755c38cfe13133153d6cf92cbf51e9ce23f7e3c.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 641e4359c..162402e 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1671105478-28a3831c720731c59eb6652e09a8362932ca8c4e.profdata +chrome-win32-main-1671116308-c3a4e361c490d4de9eb7abe31d561d478d8d8ae7.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 6b478cb..35fe22a6 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -262,7 +262,6 @@ "$root_gen_dir/chrome/assistant_optin_resources.pak", "$root_gen_dir/chrome/audio_resources.pak", "$root_gen_dir/chrome/bluetooth_pairing_dialog_resources.pak", - "$root_gen_dir/chrome/browser/supervised_user/supervised_user_unscaled_resources.pak", "$root_gen_dir/chrome/cloud_upload_resources.pak", "$root_gen_dir/chrome/desk_api_resources.pak", "$root_gen_dir/chrome/emoji_picker_resources.pak", @@ -354,7 +353,6 @@ "//chrome/browser/resources/nearby_internals:resources", "//chrome/browser/resources/nearby_share:resources", "//chrome/browser/resources/settings/chromeos:resources", - "//chrome/browser/supervised_user:supervised_user_unscaled_resources", "//chromeos/ash/resources", "//chromeos/resources", "//ui/file_manager:file_manager_gen_resources",
diff --git a/chrome/common/features.gni b/chrome/common/features.gni index 7aa0949..d2036b2 100644 --- a/chrome/common/features.gni +++ b/chrome/common/features.gni
@@ -11,6 +11,7 @@ import("//components/nacl/features.gni") import("//components/safe_browsing/buildflags.gni") import("//components/signin/features.gni") +import("//components/supervised_user/buildflags.gni") import("//crypto/features.gni") import("//device/vr/buildflags/buildflags.gni") import("//extensions/buildflags/buildflags.gni") @@ -85,10 +86,6 @@ assert(!chrome_enable_logging_by_default || !is_official_build, "Logging must be disabled by default in Official builds") -# Enables supervision for Family Link users. -# Supervision is only supported on Chrome OS and Android. -enable_supervised_users = is_chromeos || is_android - # Use brlapi from brltty for braille display support. use_brlapi = is_chromeos_ash
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index c4ce03f..f3ce22c 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3618,9 +3618,9 @@ ] } deps += [ + "//components/supervised_user/core/common", "//chrome/browser/supervised_user:test_support", "//chrome/browser/supervised_user/kids_chrome_management:proto", - "//chrome/browser/supervised_user/supervised_user_features", ] } @@ -9073,9 +9073,7 @@ deps += [ "//chrome/browser/supervised_user:test_support", "//chrome/browser/supervised_user/kids_chrome_management:proto", - "//chrome/browser/supervised_user/supervised_user_error_page:unit_tests", - "//chrome/browser/supervised_user/supervised_user_features", - "//chrome/browser/supervised_user/supervised_user_features:unit_tests", + "//components/supervised_user/core/common", ] } if (safe_browsing_mode == 1 && enable_extensions) {
diff --git a/chrome/test/data/extensions/browsertest/proxy_setting_extension.pem b/chrome/test/data/extensions/browsertest/proxy_setting_extension.pem new file mode 100644 index 0000000..b63f6a1 --- /dev/null +++ b/chrome/test/data/extensions/browsertest/proxy_setting_extension.pem
@@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCmyYDVyB24tYXx +SmwI8G6InnE1vT6LBPOLGNcyBX8E/tBWgYZwr/gRMco9S40djNEAiGvpBLMyezWS +FnYHW11DYmzlW7VZ6E+MYAYY/G1P+xDL2AA1jVxjqC68JVdU91Eub11anQDlLu8c +gwSGwy0Sg/nfMUFV7gylFahZ9EbfZ8vMsPlS8RFEf7TG7vZb4aQrh8d7npPrpJI3 +llkVQooQ0V/C56L5tmv2XdyWA0KjFiw5eE/wU0ZkQQjcJTtQHtH8DPqItmG57xXr +XYgnU5WNrA9m4FouhOL3JCN+6W0VwEkQ+WMJGlisF4wJJgQLznfDxCcwBvRk33FT +roAV9nmLAgMBAAECggEAMtLTZhGpcOgrrSfa/OxbGlmBsPj+bnlvR1Ml/DGtj5Wg +YcPtdjhBFOhBsuTrVvZal9l6XJLYkkj2PZKHm91M8aQz/74u6HtAhkuagBGns8gT +SbKD+c2eOiX9O8r7LkKA4+/+mAagx7XCGkOYZQJjoTFDOq51NNyp0MJlPygPUrL9 +9cmQ4SS9Tz6GOxjR+SJcHeJGrt6Sy0cSIuL3Ve1xNVpId+t8xxSQ1qoow36VkjK8 +lB302fgvelY75AYGAfoa8kIoEFlNq8zCtQ6rnwGOHkS67Jp/1lS/sroinxmEkcrL +lx914c5nJ8gf2xRJFdBJ3860LQ0Qlzqa9ztJCbcEAQKBgQDR/MR7eYzz4knTcO0U +R0A2ATfntkDianxqnVddd7SC0gU43LzsHjxMoYEMWqE3zpyBahNiUo38BuDBWGkw +zwJQPUsr+mAw4ue63+zAqXCjMHyoYF9xO7duBQQCsyN86A832fv/fFiOCYklWjh0 +yxV9u+IDwProRKcYAoO04/5tiwKBgQDLVWto0tA+LLM3qC0H2iI2V5vm9eOAXx4z +sPj+xS/y1xlZhlb0yoAae6Vsf7dTXln7U9uk/eFEt72CI3jYCu6xafv7OTH4f+FY +9SF8UcSaUC0I7ir3Ynx3ch/avNZer7JEbw15/gi2b7nHTZ/N7FZaHRqjUX8Tdf7N +ZPTSmsGkAQKBgFChm5zCDsKzOJ/tM8velCRokVvzGrUWKJITurFUPscg+ApekFim +P4c5WMEyp8czGduDrM/LXWPSDEmRtkqcoonHD29io78B0fNq+pD8PxkajDNnVh63 +zHZ9jI2w1canoPhURrRSvfpEZRonq5gFR0pRc7b3SiEYA4Vvqb0y8saDAoGAPAtQ +eZbvabzXe5MNISl4OuXqIuzvrqPoDkmvbcSbITIFyVsTaJw38hobQowAffz5w28D +CJj0Ic/EhZ6l+95WmEt83rYIHKLez98rcUPQM+WDNwTl6UHLEZbA814aS8HEedL1 +ftXWitE5YjJ5A11MLrYzfJD/XqbUhKDQbzTGBAECgYAHPnCl6tB21INnlDEw2E4+ +/l6BsgkVX4hfN9ohWToYPfQtY4mzSSAGEx09xODAMDOkWM5n6Kjifhh8VxDnCljl +0YktosZzYBwtnLFOYGfT1QCTOuSuesemdOb8ySMARJhve8IOe5Y2oVJG6pnGzu6R +LtrfJylDDN9kzzIOO6onbg== +-----END PRIVATE KEY-----
diff --git a/chrome/test/data/extensions/browsertest/proxy_setting_extension/background.js b/chrome/test/data/extensions/browsertest/proxy_setting_extension/background.js new file mode 100644 index 0000000..5ed2567 --- /dev/null +++ b/chrome/test/data/extensions/browsertest/proxy_setting_extension/background.js
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +chrome.runtime.onInstalled.addListener(() => { + var config = { + mode: "fixed_servers", + rules: { + proxyForHttps: {scheme: "http", host: "google.com", port: 5555}, + bypassList: ["127.0.0.1"] + } + }; + chrome.proxy.settings.set( + { 'value': config, 'scope': 'regular' }, + () => { + chrome.test.sendMessage('ready'); + } + ); + } +)
diff --git a/chrome/test/data/extensions/browsertest/proxy_setting_extension/manifest.json b/chrome/test/data/extensions/browsertest/proxy_setting_extension/manifest.json new file mode 100644 index 0000000..95aebbf --- /dev/null +++ b/chrome/test/data/extensions/browsertest/proxy_setting_extension/manifest.json
@@ -0,0 +1,12 @@ +{ + "manifest_version": 3, + "name": "Proxy extension for testing", + "version": "1.0.2", + "background": { + "service_worker": "background.js" + }, + "permissions": [ + "proxy", "tabs" + ], + "incognito": "spanning" +}
diff --git a/chrome/test/data/webui/bookmarks/BUILD.gn b/chrome/test/data/webui/bookmarks/BUILD.gn index b295b8f9..1dfbe6a 100644 --- a/chrome/test/data/webui/bookmarks/BUILD.gn +++ b/chrome/test/data/webui/bookmarks/BUILD.gn
@@ -10,9 +10,9 @@ out_dir = "$target_gen_dir/tsc" tsconfig_base = "tsconfig_base.json" path_mappings = [ - "chrome://bookmarks/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/bookmarks/tsc/*", - target_gen_dir), + "chrome://bookmarks/bookmarks.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/bookmarks/tsc/bookmarks.d.ts", + target_gen_dir), "chrome://webui-test/*|" + rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*", target_gen_dir),
diff --git a/chrome/test/data/webui/downloads/BUILD.gn b/chrome/test/data/webui/downloads/BUILD.gn index 9981c28..0133a76 100644 --- a/chrome/test/data/webui/downloads/BUILD.gn +++ b/chrome/test/data/webui/downloads/BUILD.gn
@@ -15,9 +15,8 @@ "toolbar_tests.ts", ] - ts_path_mappings = - [ "chrome://downloads/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/downloads/tsc/*", - target_gen_dir) ] + ts_path_mappings = [ "chrome://downloads/downloads.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/downloads/tsc/downloads.d.ts", + target_gen_dir) ] ts_deps = [ "//chrome/browser/resources/downloads:build_ts" ] }
diff --git a/chrome/test/data/webui/extensions/BUILD.gn b/chrome/test/data/webui/extensions/BUILD.gn index 5837083..b15e4fd1 100644 --- a/chrome/test/data/webui/extensions/BUILD.gn +++ b/chrome/test/data/webui/extensions/BUILD.gn
@@ -60,10 +60,9 @@ ] } - ts_path_mappings = - [ "chrome://extensions/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/extensions/tsc/*", - target_gen_dir) ] + ts_path_mappings = [ "chrome://extensions/extensions.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/extensions/tsc/extensions.d.ts", + target_gen_dir) ] ts_deps = [ "//chrome/browser/resources/extensions:build_ts" ] ts_definitions = [
diff --git a/chrome/test/data/webui/history/BUILD.gn b/chrome/test/data/webui/history/BUILD.gn index 2575c77..4b25236 100644 --- a/chrome/test/data/webui/history/BUILD.gn +++ b/chrome/test/data/webui/history/BUILD.gn
@@ -29,9 +29,15 @@ "test_util.ts", ] - ts_path_mappings = - [ "chrome://history/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/history/tsc/*", - target_gen_dir) ] + ts_path_mappings = [ + "chrome://history/history.js|" + + rebase_path( + "$root_gen_dir/chrome/browser/resources/history/tsc/history.d.ts", + target_gen_dir), + "chrome://history/lazy_load.ts|" + + rebase_path( + "$root_gen_dir/chrome/browser/resources/history/tsc/lazy_load.d.ts", + target_gen_dir), + ] ts_deps = [ "//chrome/browser/resources/history:build_ts" ] }
diff --git a/chrome/test/data/webui/print_preview/BUILD.gn b/chrome/test/data/webui/print_preview/BUILD.gn index e607512..685e00c 100644 --- a/chrome/test/data/webui/print_preview/BUILD.gn +++ b/chrome/test/data/webui/print_preview/BUILD.gn
@@ -81,8 +81,8 @@ } ts_path_mappings = [ - "chrome://print/*|" + rebase_path( - "$root_gen_dir/chrome/browser/resources/print_preview/tsc/*", + "chrome://print/print_preview.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/print_preview/tsc/print_preview.d.ts", target_gen_dir), "chrome://print/pdf/*|" + rebase_path("$root_gen_dir/chrome/browser/resources/pdf/tsc/*",
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn index a26e155..008781ec 100644 --- a/chrome/test/data/webui/settings/BUILD.gn +++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -188,10 +188,20 @@ ] } - ts_path_mappings = - [ "chrome://settings/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/settings/tsc/*", - target_gen_dir) ] + ts_path_mappings = [ + # Settings tests should only be importing from one of the URLs below, so + # that tests work both in optimize_webui=true/false modes. + "chrome://settings/privacy_sandbox/*|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/settings/tsc/privacy_sandbox/*", + target_gen_dir), + "chrome://settings/settings.js|" + + rebase_path( + "$root_gen_dir/chrome/browser/resources/settings/tsc/settings.d.ts", + target_gen_dir), + "chrome://settings/lazy_load.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/settings/tsc/lazy_load.d.ts", + target_gen_dir), + ] ts_definitions = [ "//tools/typescript/definitions/autofill_private.d.ts",
diff --git a/chrome/test/data/webui/settings/chromeos/device_page_tests.js b/chrome/test/data/webui/settings/chromeos/device_page_tests.js index 30d57f2a..6a5bbf4 100644 --- a/chrome/test/data/webui/settings/chromeos/device_page_tests.js +++ b/chrome/test/data/webui/settings/chromeos/device_page_tests.js
@@ -587,6 +587,15 @@ const inputVolumeSlider = audioPage.shadowRoot.querySelector('#audioInputGainVolumeSlider'); assertTrue(isVisible(inputVolumeSlider), 'audioInputGainVolumeSlider'); + const noiseCancellationSubsectionHeader = + audioPage.shadowRoot.querySelector( + '#audioInputNoiseCancellationLabel'); + assertTrue(isVisible(noiseCancellationSubsectionHeader)); + assertEquals( + 'Noise Cancellation', noiseCancellationSubsectionHeader.textContent); + const noiseCancellationToggle = audioPage.shadowRoot.querySelector( + '#audioInputNoiseCancellationToggle'); + assertTrue(isVisible(noiseCancellationToggle)); }); });
diff --git a/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js b/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js index 7177b4d4..cc96e0da 100644 --- a/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js +++ b/chrome/test/data/webui/settings/chromeos/fake_cros_audio_config_test.js
@@ -166,4 +166,17 @@ crosAudioConfigMojomWebui.MuteState.kNotMuted, onPropertiesUpdated.calls_[2][0].inputMuteState); }); + + test('VerifySetInputVolumeTriggersMatchingPropertyUpdate', () => { + const expectedVolumePercent = 32; + /** @type {AudioSystemProperties} */ + const updatedProperties = { + ...defaultProperties, + inputVolumePercent: expectedVolumePercent, + }; + onPropertiesUpdated.addExpectation(updatedProperties); + crosAudioConfig.setInputVolumePercent(expectedVolumePercent); + + mockController.verifyMocks(); + }); });
diff --git a/chrome/test/data/webui/settings/personalization_options_test.ts b/chrome/test/data/webui/settings/personalization_options_test.ts index 2b82f2c..0a74e17 100644 --- a/chrome/test/data/webui/settings/personalization_options_test.ts +++ b/chrome/test/data/webui/settings/personalization_options_test.ts
@@ -7,8 +7,7 @@ import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SettingsPersonalizationOptionsElement} from 'chrome://settings/lazy_load.js'; -import {PrivacyPageVisibility} from 'chrome://settings/page_visibility.js'; -import {loadTimeData, PrivacyPageBrowserProxyImpl, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; +import {loadTimeData, PrivacyPageVisibility, PrivacyPageBrowserProxyImpl, StatusAction, SyncBrowserProxyImpl} from 'chrome://settings/settings.js'; import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; // <if expr="not is_chromeos"> import {eventToPromise, isVisible} from 'chrome://webui-test/test_util.js';
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts index b70fbecd..2da7b20 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/categories_test.ts
@@ -97,4 +97,17 @@ assertTrue(!!event); assertEquals(1, handler.getCallCount('setClassicChromeDefaultTheme')); }); + + test('clicking upload image creates dialog and sends event', async () => { + await setInitialSettings(0); + handler.setResultFor('chooseLocalCustomBackground', Promise.resolve({ + success: true, + })); + + const eventPromise = eventToPromise('theme-select', categoriesElement); + categoriesElement.$.uploadImageTile.click(); + const event = await eventPromise; + assertTrue(!!event); + assertEquals(1, handler.getCallCount('chooseLocalCustomBackground')); + }); });
diff --git a/chrome/test/data/webui/side_panel/side_panel_browsertest.js b/chrome/test/data/webui/side_panel/side_panel_browsertest.js index 8fde73b..a21341d 100644 --- a/chrome/test/data/webui/side_panel/side_panel_browsertest.js +++ b/chrome/test/data/webui/side_panel/side_panel_browsertest.js
@@ -55,6 +55,12 @@ mocha.run(); }); +// TODO(crbug.com/1396268): Flaky on Mac. Re-enable this test. +GEN('#if BUILDFLAG(IS_MAC)'); +GEN('#define MAYBE_All DISABLED_All'); +GEN('#else'); +GEN('#define MAYBE_All All'); +GEN('#endif'); var ShoppingListTest = class extends SidePanelBrowserTest { /** @override */ @@ -63,7 +69,7 @@ } }; -TEST_F('ShoppingListTest', 'All', function() { +TEST_F('ShoppingListTest', 'MAYBE_All', function() { mocha.run(); });
diff --git a/chrome/test/data/webui/signin/BUILD.gn b/chrome/test/data/webui/signin/BUILD.gn index b462206..2d98a3e 100644 --- a/chrome/test/data/webui/signin/BUILD.gn +++ b/chrome/test/data/webui/signin/BUILD.gn
@@ -64,8 +64,11 @@ out_dir = "$target_gen_dir/tsc" tsconfig_base = "tsconfig_base.json" path_mappings = [ - "chrome://profile-picker/*|" + rebase_path( - "$root_gen_dir/chrome/browser/resources/signin/profile_picker/tsc/*", + "chrome://profile-picker/profile_picker.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/signin/profile_picker/tsc/profile_picker.d.ts", + target_gen_dir), + "chrome://profile-picker/lazy_load.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/signin/profile_picker/tsc/lazy_load.d.ts", target_gen_dir), "chrome://signin-dice-web-intercept/*|" + rebase_path( "$root_gen_dir/chrome/browser/resources/signin/tsc/dice_web_signin_intercept/*",
diff --git a/chrome/test/data/webui/tab_search/BUILD.gn b/chrome/test/data/webui/tab_search/BUILD.gn index 0dd30984..e8e2327 100644 --- a/chrome/test/data/webui/tab_search/BUILD.gn +++ b/chrome/test/data/webui/tab_search/BUILD.gn
@@ -21,9 +21,9 @@ ] ts_path_mappings = [ - "chrome://tab-search.top-chrome/*|" + - rebase_path("$root_gen_dir/chrome/browser/resources/tab_search/tsc/*", - target_gen_dir), + "chrome://tab-search.top-chrome/tab_search.js|" + rebase_path( + "$root_gen_dir/chrome/browser/resources/tab_search/tsc/tab_search.d.ts", + target_gen_dir), "chrome://webui-test/metrics_reporter/*|" + rebase_path( "$root_gen_dir/chrome/test/data/webui/metrics_reporter/tsc/*",
diff --git a/chrome/updater/test/integration_test_commands.h b/chrome/updater/test/integration_test_commands.h index 6071841..7a81612a 100644 --- a/chrome/updater/test/integration_test_commands.h +++ b/chrome/updater/test/integration_test_commands.h
@@ -46,6 +46,11 @@ const std::string& install_data_index, const base::Version& from_version, const base::Version& to_version) const = 0; + virtual void ExpectInstallSequence(ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + const base::Version& from_version, + const base::Version& to_version) const = 0; virtual void ExpectVersionActive(const std::string& version) const = 0; virtual void ExpectVersionNotActive(const std::string& version) const = 0; virtual void Uninstall() const = 0; @@ -90,6 +95,7 @@ virtual void RunUninstallCmdLine() const = 0; virtual void SetUpTestService() const = 0; virtual void TearDownTestService() const = 0; + virtual void RunHandoff(const std::string& app_id) const = 0; #endif // BUILDFLAG(IS_WIN) virtual void StressUpdateService() const = 0; virtual void CallServiceUpdate(const std::string& app_id,
diff --git a/chrome/updater/test/integration_test_commands_system.cc b/chrome/updater/test/integration_test_commands_system.cc index a62cb61..27d95ef 100644 --- a/chrome/updater/test/integration_test_commands_system.cc +++ b/chrome/updater/test/integration_test_commands_system.cc
@@ -102,6 +102,16 @@ to_version); } + void ExpectInstallSequence(ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + const base::Version& from_version, + const base::Version& to_version) const override { + updater::test::ExpectInstallSequence(updater_scope_, test_server, app_id, + install_data_index, from_version, + to_version); + } + void ExpectVersionActive(const std::string& version) const override { RunCommand("expect_version_active", {Param("version", version)}); } @@ -251,6 +261,10 @@ void TearDownTestService() const override { updater::test::RunTestServiceCommand("teardown"); } + + void RunHandoff(const std::string& app_id) const override { + RunCommand("run_handoff", {Param("app_id", app_id)}); + } #endif // BUILDFLAG(IS_WIN) base::FilePath GetDifferentUserPath() const override {
diff --git a/chrome/updater/test/integration_test_commands_user.cc b/chrome/updater/test/integration_test_commands_user.cc index 453e1dd..0db12bda 100644 --- a/chrome/updater/test/integration_test_commands_user.cc +++ b/chrome/updater/test/integration_test_commands_user.cc
@@ -83,6 +83,16 @@ to_version); } + void ExpectInstallSequence(ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + const base::Version& from_version, + const base::Version& to_version) const override { + updater::test::ExpectInstallSequence(updater_scope_, test_server, app_id, + install_data_index, from_version, + to_version); + } + void ExpectVersionActive(const std::string& version) const override { updater::test::ExpectVersionActive(updater_scope_, version); } @@ -218,6 +228,10 @@ void SetUpTestService() const override {} void TearDownTestService() const override {} + + void RunHandoff(const std::string& app_id) const override { + updater::test::RunHandoff(updater_scope_, app_id); + } #endif // BUILDFLAG(IS_WIN) base::FilePath GetDifferentUserPath() const override {
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc index 58f2a80..5fb89f9 100644 --- a/chrome/updater/test/integration_tests.cc +++ b/chrome/updater/test/integration_tests.cc
@@ -194,6 +194,10 @@ } void RunUninstallCmdLine() { test_commands_->RunUninstallCmdLine(); } + + void RunHandoff(const std::string& app_id) { + test_commands_->RunHandoff(app_id); + } #endif // BUILDFLAG(IS_WIN) void SetupFakeUpdaterHigherVersion() { @@ -308,14 +312,13 @@ test_commands_->ExpectSelfUpdateSequence(test_server); } - void ExpectInstallEvent(ScopedServer* test_server, - const std::string& app_id) { - test_server->ExpectOnce( - {base::BindRepeating( - RequestMatcherRegex, - base::StrCat({R"(.*"appid":")", app_id, R"(","enabled":true,")", - R"(event":\[{"eventresult":1,"eventtype":2,.*)"}))}, - ""); + void ExpectInstallSequence(ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + const base::Version& from_version, + const base::Version& to_version) { + test_commands_->ExpectInstallSequence( + test_server, app_id, install_data_index, from_version, to_version); } void StressUpdateService() { test_commands_->StressUpdateService(); } @@ -369,7 +372,7 @@ TEST_F(IntegrationTest, DoNothing) {} TEST_F(IntegrationTest, Install) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); EXPECT_TRUE(WaitForUpdaterExit()); ExpectInstalled(); ExpectVersionActive(kUpdaterVersion); @@ -393,7 +396,7 @@ // A new version hands off installation to the old version, and doesn't // change the active version of the updater. - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); EXPECT_TRUE(WaitForUpdaterExit()); ExpectVersionNotActive(kUpdaterVersion); @@ -407,7 +410,7 @@ // Since the old version is not working, the new version should install and // become active. - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); EXPECT_TRUE(WaitForUpdaterExit()); ExpectVersionActive(kUpdaterVersion); @@ -416,7 +419,7 @@ #endif // !BUILDFLAG(IS_LINUX) TEST_F(IntegrationTest, SelfUninstallOutdatedUpdater) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); EXPECT_TRUE(WaitForUpdaterExit()); SetupFakeUpdaterHigherVersion(); @@ -443,7 +446,7 @@ TEST_F(IntegrationTest, QualifyUpdater) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); EXPECT_TRUE(WaitForUpdaterExit()); SetupFakeUpdaterLowerVersion(); @@ -470,7 +473,7 @@ TEST_F(IntegrationTest, SelfUpdate) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); base::Version next_version(base::StringPrintf("%s1", kUpdaterVersion)); ExpectUpdateSequence(&test_server, kUpdaterAppId, "", @@ -485,7 +488,7 @@ TEST_F(IntegrationTest, SelfUpdateWithWakeAll) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); base::Version next_version(base::StringPrintf("%s1", kUpdaterVersion)); ExpectUpdateSequence(&test_server, kUpdaterAppId, "", @@ -508,7 +511,7 @@ TestTimeouts::action_timeout()); ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); // Register apps test1 and test2. Expect pings for each. @@ -540,7 +543,7 @@ TEST_F(IntegrationTest, UpdateApp) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); const std::string kAppId("test"); InstallApp(kAppId); @@ -561,9 +564,24 @@ } #if BUILDFLAG(IS_WIN) +TEST_F(IntegrationTest, Handoff) { + ScopedServer test_server(test_commands_); + ASSERT_NO_FATAL_FAILURE(Install()); + + const std::string kAppId("test"); + const base::Version v1("1"); + ExpectInstallSequence(&test_server, kAppId, "", base::Version({0, 0, 0, 0}), + v1); + RunHandoff(kAppId); + EXPECT_TRUE(WaitForUpdaterExit()); + ExpectAppVersion(kAppId, v1); + + Uninstall(); +} + TEST_F(IntegrationTest, ForceInstallApp) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); base::Value::Dict group_policies; group_policies.Set("Installtest1", IsSystemInstall(GetTestScope()) @@ -588,7 +606,7 @@ TEST_F(IntegrationTest, MultipleWakesOneNetRequest) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); // Only one sequence visible to the server despite multiple wakes. ExpectNoUpdateSequence(&test_server, kUpdaterAppId); @@ -600,7 +618,7 @@ TEST_F(IntegrationTest, MultipleUpdateAllsMultipleNetRequests) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectNoUpdateSequence(&test_server, kUpdaterAppId); UpdateAll(); @@ -612,14 +630,14 @@ #if BUILDFLAG(IS_WIN) TEST_F(IntegrationTest, MarshalInterface) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectMarshalInterfaceSucceeds(); Uninstall(); } TEST_F(IntegrationTest, LegacyUpdate3Web) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); const char kAppId[] = "test1"; InstallApp(kAppId); @@ -648,13 +666,13 @@ } TEST_F(IntegrationTest, LegacyProcessLauncher) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectLegacyProcessLauncherSucceeds(); Uninstall(); } TEST_F(IntegrationTest, LegacyAppCommandWeb) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); const char kAppId[] = "test1"; InstallApp(kAppId); @@ -668,7 +686,7 @@ TEST_F(IntegrationTest, LegacyPolicyStatus) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); const std::string kAppId("test"); InstallApp(kAppId); @@ -683,7 +701,7 @@ } TEST_F(IntegrationTest, UninstallCmdLine) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); ExpectVersionActive(kUpdaterVersion); ExpectActiveUpdater(); @@ -703,7 +721,7 @@ #endif // BUILDFLAG(IS_WIN) TEST_F(IntegrationTest, UnregisterUninstalledApp) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); InstallApp("test1"); InstallApp("test2"); @@ -724,7 +742,7 @@ } TEST_F(IntegrationTest, UninstallIfMaxServerWakesBeforeRegistrationExceeded) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); EXPECT_TRUE(WaitForUpdaterExit()); ExpectInstalled(); SetServerStarts(24); @@ -733,7 +751,7 @@ } TEST_F(IntegrationTest, UninstallUpdaterWhenAllAppsUninstalled) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); InstallApp("test1"); ExpectInstalled(); EXPECT_TRUE(WaitForUpdaterExit()); @@ -750,7 +768,7 @@ } TEST_F(IntegrationTest, RotateLog) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); EXPECT_TRUE(WaitForUpdaterExit()); FillLog(); RunWake(0); @@ -763,7 +781,7 @@ // test need not run on Windows. #if BUILDFLAG(IS_MAC) TEST_F(IntegrationTest, UnregisterUnownedApp) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); ExpectVersionActive(kUpdaterVersion); ExpectActiveUpdater(); @@ -837,7 +855,7 @@ #endif TEST_F(IntegrationTest, UpdateServiceStress) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); StressUpdateService(); Uninstall(); @@ -845,7 +863,7 @@ TEST_F(IntegrationTest, SameVersionUpdate) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); const std::string app_id = "test-appid"; @@ -885,7 +903,7 @@ TEST_F(IntegrationTest, InstallDataIndex) { ScopedServer test_server(test_commands_); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); const std::string app_id = "test-appid"; @@ -925,7 +943,7 @@ TEST_F(IntegrationTest, MigrateLegacyUpdater) { SetupFakeLegacyUpdaterData(); - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); ExpectLegacyUpdaterDataMigrated(); Uninstall(); @@ -943,21 +961,21 @@ } TEST_F(IntegrationTest, OfflineInstall) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); RunOfflineInstall(/*is_legacy_install=*/false, /*is_silent_install=*/false); Uninstall(); } TEST_F(IntegrationTest, SilentOfflineInstall) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); RunOfflineInstall(/*is_legacy_install=*/false, /*is_silent_install=*/true); Uninstall(); } TEST_F(IntegrationTest, LegacySilentOfflineInstall) { - Install(); + ASSERT_NO_FATAL_FAILURE(Install()); ExpectInstalled(); RunOfflineInstall(/*is_legacy_install=*/true, /*is_silent_install=*/true); Uninstall();
diff --git a/chrome/updater/test/integration_tests_helper.cc b/chrome/updater/test/integration_tests_helper.cc index 7ca630d..c887368 100644 --- a/chrome/updater/test/integration_tests_helper.cc +++ b/chrome/updater/test/integration_tests_helper.cc
@@ -273,6 +273,7 @@ {"expect_legacy_policy_status_succeeds", WithSystemScope(Wrap(&ExpectLegacyPolicyStatusSucceeds))}, {"run_uninstall_cmd_line", WithSystemScope(Wrap(&RunUninstallCmdLine))}, + {"run_handoff", WithSwitch("app_id", WithSystemScope(Wrap(&RunHandoff)))}, #endif // BUILDFLAG(IS_WIN) {"expect_version_active", WithSwitch("version", WithSystemScope(Wrap(&ExpectVersionActive)))},
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc index 0cf5453..c407f92 100644 --- a/chrome/updater/test/integration_tests_impl.cc +++ b/chrome/updater/test/integration_tests_impl.cc
@@ -194,6 +194,57 @@ EXPECT_EQ(exit_code, expected_exit_code); } +void ExpectSequence(UpdaterScope scope, + ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + int event_type, + const base::Version& from_version, + const base::Version& to_version) { + base::FilePath test_data_path; + ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_path)); + base::FilePath crx_path = test_data_path.Append(FILE_PATH_LITERAL("updater")) + .AppendASCII(kDoNothingCRXName); + ASSERT_TRUE(base::PathExists(crx_path)); + + // First request: update check. + test_server->ExpectOnce( + {base::BindRepeating( + RequestMatcherRegex, + base::StringPrintf(R"(.*"appid":"%s".*)", app_id.c_str())), + base::BindRepeating( + RequestMatcherRegex, + base::StringPrintf( + R"(.*%s)", + !install_data_index.empty() + ? base::StringPrintf( + R"("data":\[{"index":"%s","name":"install"}],.*)", + install_data_index.c_str()) + .c_str() + : "")), + GetScopePredicate(scope)}, + GetUpdateResponse(app_id, install_data_index, + test_server->base_url().spec(), to_version, crx_path, + kDoNothingCRXRun, {})); + + // Second request: update download. + std::string crx_bytes; + base::ReadFileToString(crx_path, &crx_bytes); + test_server->ExpectOnce({base::BindRepeating(RequestMatcherRegex, "")}, + crx_bytes); + + // Third request: event ping. + test_server->ExpectOnce( + {base::BindRepeating( + RequestMatcherRegex, + base::StringPrintf(R"(.*"eventresult":1,"eventtype":%d,)" + R"("nextversion":"%s","previousversion":"%s".*)", + event_type, to_version.GetString().c_str(), + from_version.GetString().c_str())), + GetScopePredicate(scope)}, + ")]}'\n"); +} + } // namespace void ExitTestMode(UpdaterScope scope) { @@ -544,48 +595,18 @@ const std::string& install_data_index, const base::Version& from_version, const base::Version& to_version) { - base::FilePath test_data_path; - ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_path)); - base::FilePath crx_path = test_data_path.Append(FILE_PATH_LITERAL("updater")) - .AppendASCII(kDoNothingCRXName); - ASSERT_TRUE(base::PathExists(crx_path)); + ExpectSequence(scope, test_server, app_id, install_data_index, 3, + from_version, to_version); +} - // First request: update check. - test_server->ExpectOnce( - {base::BindRepeating( - RequestMatcherRegex, - base::StringPrintf(R"(.*"appid":"%s".*)", app_id.c_str())), - base::BindRepeating( - RequestMatcherRegex, - base::StringPrintf( - R"(.*%s)", - !install_data_index.empty() - ? base::StringPrintf( - R"("data":\[{"index":"%s","name":"install"}],.*)", - install_data_index.c_str()) - .c_str() - : "")), - GetScopePredicate(scope)}, - GetUpdateResponse(app_id, install_data_index, - test_server->base_url().spec(), to_version, crx_path, - kDoNothingCRXRun, {})); - - // Second request: update download. - std::string crx_bytes; - base::ReadFileToString(crx_path, &crx_bytes); - test_server->ExpectOnce({base::BindRepeating(RequestMatcherRegex, "")}, - crx_bytes); - - // Third request: event ping. - test_server->ExpectOnce( - {base::BindRepeating( - RequestMatcherRegex, - base::StringPrintf(R"(.*"eventresult":1,"eventtype":3,)" - R"("nextversion":"%s","previousversion":"%s".*)", - to_version.GetString().c_str(), - from_version.GetString().c_str())), - GetScopePredicate(scope)}, - ")]}'\n"); +void ExpectInstallSequence(UpdaterScope scope, + ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + const base::Version& from_version, + const base::Version& to_version) { + ExpectSequence(scope, test_server, app_id, install_data_index, 2, + from_version, to_version); } // Runs multiple cycles of instantiating the update service, calling
diff --git a/chrome/updater/test/integration_tests_impl.h b/chrome/updater/test/integration_tests_impl.h index 061a92abc..e6d3c68 100644 --- a/chrome/updater/test/integration_tests_impl.h +++ b/chrome/updater/test/integration_tests_impl.h
@@ -215,6 +215,7 @@ const base::Value::Dict& arguments); void RunUninstallCmdLine(UpdaterScope scope); +void RunHandoff(UpdaterScope scope, const std::string& app_id); #endif // BUILDFLAG(IS_WIN) // Returns the number of files in the directory, not including directories, @@ -234,6 +235,13 @@ const base::Version& from_version, const base::Version& to_version); +void ExpectInstallSequence(UpdaterScope scope, + ScopedServer* test_server, + const std::string& app_id, + const std::string& install_data_index, + const base::Version& from_version, + const base::Version& to_version); + void StressUpdateService(UpdaterScope scope); void CallServiceUpdate(UpdaterScope updater_scope, @@ -259,7 +267,6 @@ void RunOfflineInstall(UpdaterScope scope, bool is_legacy_install, bool is_silent_install); - } // namespace updater::test #endif // CHROME_UPDATER_TEST_INTEGRATION_TESTS_IMPL_H_
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc index ce9df3e..65ea452 100644 --- a/chrome/updater/test/integration_tests_win.cc +++ b/chrome/updater/test/integration_tests_win.cc
@@ -1410,6 +1410,27 @@ EXPECT_EQ(0, exit_code); } +void RunHandoff(UpdaterScope scope, const std::string& app_id) { + const absl::optional<base::FilePath> installed_executable_path = + GetInstalledExecutablePath(scope); + ASSERT_TRUE(installed_executable_path); + ASSERT_TRUE(base::PathExists(*installed_executable_path)); + + base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait_process; + const std::wstring command_line(base::StrCat( + {installed_executable_path->value(), L" /handoff \"appguid=", + base::ASCIIToWide(app_id), L"&needsadmin=", + IsSystemInstall(scope) ? L"Prefers" : L"False", L"\" /silent"})); + VLOG(0) << " RunHandoff: " << command_line; + const base::Process process = base::LaunchProcess(command_line, {}); + ASSERT_TRUE(process.IsValid()); + + int exit_code = 0; + ASSERT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(), + &exit_code)); + ASSERT_EQ(exit_code, 0); +} + void SetupFakeLegacyUpdaterData(UpdaterScope scope) { const HKEY root = UpdaterScopeToHKeyRoot(scope);
diff --git a/chrome/updater/updater_scope.cc b/chrome/updater/updater_scope.cc index 1d1314b..0d02a500 100644 --- a/chrome/updater/updater_scope.cc +++ b/chrome/updater/updater_scope.cc
@@ -8,11 +8,11 @@ #include "base/command_line.h" #include "build/build_config.h" #include "chrome/updater/constants.h" +#include "chrome/updater/util/util.h" #include "third_party/abseil-cpp/absl/types/optional.h" #if BUILDFLAG(IS_WIN) #include "chrome/updater/tag.h" -#include "chrome/updater/util/util.h" #include "chrome/updater/util/win_util.h" #endif @@ -73,7 +73,7 @@ } UpdaterScope GetUpdaterScope() { - return GetUpdaterScopeForCommandLine(*base::CommandLine::ForCurrentProcess()); + return GetUpdaterScopeForCommandLine(GetCommandLineLegacyCompatible()); } bool IsSystemInstall() {
diff --git a/chromeos/ash/components/audio/cros_audio_config_impl.cc b/chromeos/ash/components/audio/cros_audio_config_impl.cc index 1fd8962..278d5e8 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl.cc +++ b/chromeos/ash/components/audio/cros_audio_config_impl.cc
@@ -56,34 +56,42 @@ return mojo_device; } -CrosAudioConfigImpl::CrosAudioConfigImpl() { - CrasAudioHandler::Get()->AddAudioObserver(this); +CrosAudioConfigImpl::CrosAudioConfigImpl() + : audio_handler_{CrasAudioHandler::Get()} { + DCHECK(audio_handler_); + audio_handler_->AddAudioObserver(this); } CrosAudioConfigImpl::~CrosAudioConfigImpl() { - if (CrasAudioHandler::Get()) - CrasAudioHandler::Get()->RemoveAudioObserver(this); + if (audio_handler_) { + audio_handler_->RemoveAudioObserver(this); + } } uint8_t CrosAudioConfigImpl::GetOutputVolumePercent() const { - return CrasAudioHandler::Get()->GetOutputVolumePercent(); + DCHECK(audio_handler_); + return audio_handler_->GetOutputVolumePercent(); } mojom::MuteState CrosAudioConfigImpl::GetOutputMuteState() const { + DCHECK(audio_handler_); // TODO(crbug.com/1092970): Add kMutedExternally. - if (CrasAudioHandler::Get()->IsOutputMutedByPolicy()) + if (audio_handler_->IsOutputMutedByPolicy()) { return mojom::MuteState::kMutedByPolicy; + } - if (CrasAudioHandler::Get()->IsOutputMuted()) + if (audio_handler_->IsOutputMuted()) { return mojom::MuteState::kMutedByUser; + } return mojom::MuteState::kNotMuted; } void CrosAudioConfigImpl::GetAudioDevices( std::vector<mojom::AudioDevicePtr>* output_devices_out) const { + DCHECK(audio_handler_); AudioDeviceList audio_devices_list; - CrasAudioHandler::Get()->GetAudioDevices(&audio_devices_list); + audio_handler_->GetAudioDevices(&audio_devices_list); for (const auto& device : audio_devices_list) { if (!device.is_for_simple_usage()) { continue; @@ -97,13 +105,13 @@ } void CrosAudioConfigImpl::SetOutputVolumePercent(int8_t volume) { - CrasAudioHandler* audio_handler = CrasAudioHandler::Get(); - audio_handler->SetOutputVolumePercent(volume); + DCHECK(audio_handler_); + audio_handler_->SetOutputVolumePercent(volume); // If the volume is above certain level and it's muted, it should be unmuted. - if (audio_handler->IsOutputMuted() && - volume > audio_handler->GetOutputDefaultVolumeMuteThreshold()) { - audio_handler->SetOutputMute(false); + if (audio_handler_->IsOutputMuted() && + volume > audio_handler_->GetOutputDefaultVolumeMuteThreshold()) { + audio_handler_->SetOutputMute(false); } }
diff --git a/chromeos/ash/components/audio/cros_audio_config_impl.h b/chromeos/ash/components/audio/cros_audio_config_impl.h index a67a734..1583d73 100644 --- a/chromeos/ash/components/audio/cros_audio_config_impl.h +++ b/chromeos/ash/components/audio/cros_audio_config_impl.h
@@ -6,6 +6,7 @@ #define CHROMEOS_ASH_COMPONENTS_AUDIO_CROS_AUDIO_CONFIG_IMPL_H_ #include "base/component_export.h" +#include "base/memory/raw_ptr.h" #include "chromeos/ash/components/audio/cras_audio_handler.h" #include "chromeos/ash/components/audio/cros_audio_config.h" @@ -30,6 +31,8 @@ void OnOutputNodeVolumeChanged(uint64_t node_id, int volume) override; void OnOutputMuteChanged(bool mute_on) override; void OnAudioNodesChanged() override; + + base::raw_ptr<CrasAudioHandler> audio_handler_; }; } // namespace ash::audio_config
diff --git a/chromeos/ash/components/network/network_state.cc b/chromeos/ash/components/network/network_state.cc index b69f724..d2da45ed 100644 --- a/chromeos/ash/components/network/network_state.cc +++ b/chromeos/ash/components/network/network_state.cc
@@ -650,6 +650,13 @@ } void NetworkState::UpdateCaptivePortalState(const base::Value& properties) { + if (!IsConnectedState()) { + // Unconnected networks are in an unknown portal state and should not + // update histograms. + shill_portal_state_ = PortalState::kUnknown; + return; + } + int status_code = properties.FindIntKey(shill::kPortalDetectionFailedStatusCodeProperty) .value_or(0);
diff --git a/chromeos/ash/components/network/network_state.h b/chromeos/ash/components/network/network_state.h index 4d29fc3..8f64ae17 100644 --- a/chromeos/ash/components/network/network_state.h +++ b/chromeos/ash/components/network/network_state.h
@@ -27,6 +27,7 @@ class DeviceState; class NetworkStateHandler; +class NetworkStateTest; // Simple class to provide network state information about a network service. // This class should always be passed as a const* and should never be held @@ -292,6 +293,7 @@ private: friend class MobileActivatorTest; friend class NetworkStateHandler; + friend class NetworkStateTest; // Updates |name_| from the 'WiFi.HexSSID' entry in |properties|, which must // be of type DICTIONARY, if the key exists, and validates |name_|. Returns
diff --git a/chromeos/ash/components/network/network_state_handler.cc b/chromeos/ash/components/network/network_state_handler.cc index 336dbd93..8a80c0ed 100644 --- a/chromeos/ash/components/network/network_state_handler.cc +++ b/chromeos/ash/components/network/network_state_handler.cc
@@ -2152,10 +2152,12 @@ void NetworkStateHandler::SendPortalHistogramTimes(base::TimeDelta elapsed) { switch (default_network_portal_state_) { case NetworkState::PortalState::kPortal: - base::UmaHistogramTimes("Network.RedirectFoundToOnlineTime", elapsed); + base::UmaHistogramMediumTimes("Network.RedirectFoundToOnlineTime", + elapsed); break; case NetworkState::PortalState::kPortalSuspected: - base::UmaHistogramTimes("Network.PortalSuspectedToOnlineTime", elapsed); + base::UmaHistogramMediumTimes("Network.PortalSuspectedToOnlineTime", + elapsed); break; default: // Previous state was not portalled, no times to report.
diff --git a/chromeos/ash/components/network/network_state_unittest.cc b/chromeos/ash/components/network/network_state_unittest.cc index 0ef0468..3a2af70 100644 --- a/chromeos/ash/components/network/network_state_unittest.cc +++ b/chromeos/ash/components/network/network_state_unittest.cc
@@ -17,6 +17,7 @@ #include "chromeos/ash/components/network/network_state_handler.h" #include "chromeos/ash/components/network/network_state_test_helper.h" #include "chromeos/ash/components/network/tether_constants.h" +#include "net/http/http_status_code.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -29,15 +30,22 @@ const char kTestCellularDevicePath[] = "cellular_path"; const char kTestCellularDeviceName[] = "cellular_name"; +} // namespace + class NetworkStateTest : public testing::Test { public: - NetworkStateTest() : network_state_("test_path") {} + NetworkStateTest() = default; NetworkStateTest(const NetworkStateTest&) = delete; NetworkStateTest& operator=(const NetworkStateTest&) = delete; // testing::Test: - void SetUp() override { AddCellularDevice(); } + void SetUp() override { + network_state_ = std::make_unique<NetworkState>("test_path"); + AddCellularDevice(); + } + + void TearDown() override { network_state_.reset(); } protected: const DeviceState* GetCellularDevice() { @@ -46,7 +54,7 @@ } bool SetProperty(const std::string& key, base::Value value) { - const bool result = network_state_.PropertyChanged(key, value); + const bool result = network_state_->PropertyChanged(key, value); properties_.SetKey(key, std::move(value)); return result; } @@ -56,10 +64,22 @@ } bool SignalInitialPropertiesReceived() { - return network_state_.InitialPropertiesReceived(properties_); + return network_state_->InitialPropertiesReceived(properties_); } - NetworkState network_state_; + void SetConnectionState(const std::string& connection_state) { + network_state_->SetConnectionState(connection_state); + } + + void UpdateCaptivePortalState(const base::Value& properties) { + network_state_->UpdateCaptivePortalState(properties); + } + + NetworkState::PortalState GetShillPortalState() { + return network_state_->shill_portal_state_; + } + + std::unique_ptr<NetworkState> network_state_; private: void AddCellularDevice() { @@ -74,8 +94,6 @@ base::Value properties_{base::Value::Type::DICTIONARY}; }; -} // namespace - // Setting kNameProperty should set network name after call to // InitialPropertiesReceived(). TEST_F(NetworkStateTest, NameAscii) { @@ -84,7 +102,7 @@ std::string network_setname = "Name TEST"; EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_setname)); EXPECT_FALSE(SignalInitialPropertiesReceived()); - EXPECT_EQ(network_state_.name(), network_setname); + EXPECT_EQ(network_state_->name(), network_setname); } TEST_F(NetworkStateTest, NameAsciiWithNull) { @@ -94,7 +112,7 @@ std::string network_setname_result = "Name TEST"; EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_setname)); EXPECT_FALSE(SignalInitialPropertiesReceived()); - EXPECT_EQ(network_state_.name(), network_setname_result); + EXPECT_EQ(network_state_->name(), network_setname_result); } // Truncates invalid UTF-8. base::Value has a DCHECK against invalid UTF-8 @@ -107,7 +125,7 @@ std::string network_setname_result = "SSID TEST \xEF\xBF\xBD\xEF\xBF\xBD!"; EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_setname)); EXPECT_TRUE(SignalInitialPropertiesReceived()); - EXPECT_EQ(network_state_.name(), network_setname_result); + EXPECT_EQ(network_state_->name(), network_setname_result); } #endif @@ -119,7 +137,7 @@ std::string wifi_utf8_result = "UTF-8 \xE3\x81\x82\xE3\x81\x84\xE3\x81\x86"; EXPECT_TRUE(SetStringProperty(shill::kNameProperty, wifi_utf8)); EXPECT_FALSE(SignalInitialPropertiesReceived()); - EXPECT_EQ(network_state_.name(), wifi_utf8_result); + EXPECT_EQ(network_state_->name(), wifi_utf8_result); } // latin1 SSID -> UTF8 SSID (Hex) @@ -132,7 +150,7 @@ std::string wifi_latin1_result = "latin-1 T\xc3\xa9\x6c\xc3\xa9\x63om"; EXPECT_TRUE(SetStringProperty(shill::kWifiHexSsid, wifi_latin1_hex)); EXPECT_TRUE(SignalInitialPropertiesReceived()); - EXPECT_EQ(network_state_.name(), wifi_latin1_result); + EXPECT_EQ(network_state_->name(), wifi_latin1_result); } // Hex SSID @@ -144,11 +162,11 @@ base::HexEncode(wifi_hex_result.c_str(), wifi_hex_result.length()); EXPECT_TRUE(SetStringProperty(shill::kWifiHexSsid, wifi_hex)); EXPECT_TRUE(SignalInitialPropertiesReceived()); - EXPECT_EQ(wifi_hex_result, network_state_.name()); + EXPECT_EQ(wifi_hex_result, network_state_->name()); // Check HexSSID via network state dictionary. base::Value dictionary(base::Value::Type::DICTIONARY); - network_state_.GetStateProperties(&dictionary); + network_state_->GetStateProperties(&dictionary); std::string* value = dictionary.FindStringKey(shill::kWifiHexSsid); EXPECT_NE(nullptr, value); EXPECT_EQ(wifi_hex, *value); @@ -168,7 +186,7 @@ base::HexEncode(non_utf8_ssid.data(), non_utf8_ssid.size()); EXPECT_TRUE(SetStringProperty(shill::kWifiHexSsid, wifi_hex)); EXPECT_TRUE(SignalInitialPropertiesReceived()); - EXPECT_EQ(network_state_.raw_ssid(), non_utf8_ssid_bytes); + EXPECT_EQ(network_state_->raw_ssid(), non_utf8_ssid_bytes); } // Multiple updates for Hex SSID should work fine. @@ -184,6 +202,8 @@ TEST_F(NetworkStateTest, CaptivePortalState) { std::string network_name = "test"; + network_state_->set_visible(true); + EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeWifi)); EXPECT_TRUE(SetStringProperty(shill::kNameProperty, network_name)); std::string hex_ssid = @@ -193,34 +213,34 @@ // State != portal or online -> portal_state() == kUnknown EXPECT_TRUE(SetStringProperty(shill::kStateProperty, shill::kStateReady)); SignalInitialPropertiesReceived(); - EXPECT_EQ(network_state_.GetPortalState(), + EXPECT_EQ(network_state_->GetPortalState(), NetworkState::PortalState::kUnknown); // State == online -> portal_state() == kOnline EXPECT_TRUE(SetStringProperty(shill::kStateProperty, shill::kStateOnline)); SignalInitialPropertiesReceived(); - EXPECT_EQ(network_state_.GetPortalState(), + EXPECT_EQ(network_state_->GetPortalState(), NetworkState::PortalState::kOnline); // State == redirect-found -> portal_state() == kPortal EXPECT_TRUE( SetStringProperty(shill::kStateProperty, shill::kStateRedirectFound)); SignalInitialPropertiesReceived(); - EXPECT_EQ(network_state_.GetPortalState(), + EXPECT_EQ(network_state_->GetPortalState(), NetworkState::PortalState::kPortal); // State == portal-suspected -> portal_state() == kPortalSuspected EXPECT_TRUE( SetStringProperty(shill::kStateProperty, shill::kStatePortalSuspected)); SignalInitialPropertiesReceived(); - EXPECT_EQ(network_state_.GetPortalState(), + EXPECT_EQ(network_state_->GetPortalState(), NetworkState::PortalState::kPortalSuspected); // State == no-connectivity -> portal_state() == kOffline EXPECT_TRUE( SetStringProperty(shill::kStateProperty, shill::kStateNoConnectivity)); SignalInitialPropertiesReceived(); - EXPECT_EQ(network_state_.GetPortalState(), + EXPECT_EQ(network_state_->GetPortalState(), NetworkState::PortalState::kNoInternet); } @@ -236,9 +256,10 @@ base::Value("third-party-vpn-provider-extension-id")); EXPECT_TRUE(SetProperty(shill::kProviderProperty, std::move(provider))); SignalInitialPropertiesReceived(); - ASSERT_TRUE(network_state_.vpn_provider()); - EXPECT_EQ(network_state_.vpn_provider()->type, shill::kProviderThirdPartyVpn); - EXPECT_EQ(network_state_.vpn_provider()->id, + ASSERT_TRUE(network_state_->vpn_provider()); + EXPECT_EQ(network_state_->vpn_provider()->type, + shill::kProviderThirdPartyVpn); + EXPECT_EQ(network_state_->vpn_provider()->id, "third-party-vpn-provider-extension-id"); } @@ -252,114 +273,114 @@ provider.SetKey(shill::kHostProperty, base::Value("package.name.foo")); EXPECT_TRUE(SetProperty(shill::kProviderProperty, std::move(provider))); SignalInitialPropertiesReceived(); - ASSERT_TRUE(network_state_.vpn_provider()); - EXPECT_EQ(network_state_.vpn_provider()->type, shill::kProviderArcVpn); - EXPECT_EQ(network_state_.vpn_provider()->id, "package.name.foo"); + ASSERT_TRUE(network_state_->vpn_provider()); + EXPECT_EQ(network_state_->vpn_provider()->type, shill::kProviderArcVpn); + EXPECT_EQ(network_state_->vpn_provider()->id, "package.name.foo"); } TEST_F(NetworkStateTest, AllowRoaming) { - EXPECT_FALSE(network_state_.allow_roaming()); + EXPECT_FALSE(network_state_->allow_roaming()); EXPECT_TRUE( SetProperty(shill::kCellularAllowRoamingProperty, base::Value(true))); - EXPECT_TRUE(network_state_.allow_roaming()); + EXPECT_TRUE(network_state_->allow_roaming()); } TEST_F(NetworkStateTest, Visible) { - EXPECT_FALSE(network_state_.visible()); + EXPECT_FALSE(network_state_->visible()); - network_state_.set_visible(true); - EXPECT_TRUE(network_state_.visible()); + network_state_->set_visible(true); + EXPECT_TRUE(network_state_->visible()); - network_state_.set_visible(false); - EXPECT_FALSE(network_state_.visible()); + network_state_->set_visible(false); + EXPECT_FALSE(network_state_->visible()); } TEST_F(NetworkStateTest, ConnectionState) { - network_state_.set_visible(true); + network_state_->set_visible(true); - network_state_.SetConnectionState(shill::kStateConfiguration); - EXPECT_EQ(network_state_.connection_state(), shill::kStateConfiguration); - EXPECT_TRUE(network_state_.IsConnectingState()); - EXPECT_TRUE(network_state_.IsConnectingOrConnected()); - EXPECT_TRUE(network_state_.IsActive()); + network_state_->SetConnectionState(shill::kStateConfiguration); + EXPECT_EQ(network_state_->connection_state(), shill::kStateConfiguration); + EXPECT_TRUE(network_state_->IsConnectingState()); + EXPECT_TRUE(network_state_->IsConnectingOrConnected()); + EXPECT_TRUE(network_state_->IsActive()); // State change to configuration from idle should not set connect_requested // unless explicitly set by the UI. - EXPECT_FALSE(network_state_.connect_requested()); + EXPECT_FALSE(network_state_->connect_requested()); - network_state_.SetConnectionState(shill::kStateOnline); - EXPECT_EQ(network_state_.connection_state(), shill::kStateOnline); - EXPECT_TRUE(network_state_.IsConnectedState()); - EXPECT_TRUE(network_state_.IsConnectingOrConnected()); - EXPECT_TRUE(network_state_.IsActive()); + network_state_->SetConnectionState(shill::kStateOnline); + EXPECT_EQ(network_state_->connection_state(), shill::kStateOnline); + EXPECT_TRUE(network_state_->IsConnectedState()); + EXPECT_TRUE(network_state_->IsConnectingOrConnected()); + EXPECT_TRUE(network_state_->IsActive()); - network_state_.SetConnectionState(shill::kStateConfiguration); - EXPECT_EQ(network_state_.connection_state(), shill::kStateConfiguration); - EXPECT_TRUE(network_state_.IsConnectingState()); + network_state_->SetConnectionState(shill::kStateConfiguration); + EXPECT_EQ(network_state_->connection_state(), shill::kStateConfiguration); + EXPECT_TRUE(network_state_->IsConnectingState()); // State change to configuration from a connected state should set // connect_requested. - EXPECT_TRUE(network_state_.connect_requested()); + EXPECT_TRUE(network_state_->connect_requested()); - network_state_.SetConnectionState(shill::kStateOnline); - EXPECT_TRUE(network_state_.IsConnectedState()); + network_state_->SetConnectionState(shill::kStateOnline); + EXPECT_TRUE(network_state_->IsConnectedState()); // State change to connected should clear connect_requested. - EXPECT_FALSE(network_state_.connect_requested()); + EXPECT_FALSE(network_state_->connect_requested()); - network_state_.SetConnectionState(shill::kStateIdle); - EXPECT_EQ(network_state_.connection_state(), shill::kStateIdle); - EXPECT_FALSE(network_state_.IsConnectedState()); - EXPECT_FALSE(network_state_.IsConnectingState()); - EXPECT_FALSE(network_state_.IsConnectingOrConnected()); - EXPECT_FALSE(network_state_.IsActive()); + network_state_->SetConnectionState(shill::kStateIdle); + EXPECT_EQ(network_state_->connection_state(), shill::kStateIdle); + EXPECT_FALSE(network_state_->IsConnectedState()); + EXPECT_FALSE(network_state_->IsConnectingState()); + EXPECT_FALSE(network_state_->IsConnectingOrConnected()); + EXPECT_FALSE(network_state_->IsActive()); EXPECT_TRUE(SetStringProperty(shill::kActivationStateProperty, shill::kActivationStateActivating)); - EXPECT_FALSE(network_state_.IsConnectedState()); - EXPECT_FALSE(network_state_.IsConnectingState()); - EXPECT_FALSE(network_state_.IsConnectingOrConnected()); - EXPECT_TRUE(network_state_.IsActive()); + EXPECT_FALSE(network_state_->IsConnectedState()); + EXPECT_FALSE(network_state_->IsConnectingState()); + EXPECT_FALSE(network_state_->IsConnectingOrConnected()); + EXPECT_TRUE(network_state_->IsActive()); } TEST_F(NetworkStateTest, ConnectRequested) { - network_state_.set_visible(true); + network_state_->set_visible(true); - network_state_.SetConnectionState(shill::kStateIdle); + network_state_->SetConnectionState(shill::kStateIdle); - network_state_.set_connect_requested_for_testing(true); - EXPECT_EQ(network_state_.connection_state(), shill::kStateIdle); - EXPECT_FALSE(network_state_.IsConnectedState()); - EXPECT_TRUE(network_state_.IsConnectingState()); - EXPECT_TRUE(network_state_.IsConnectingOrConnected()); + network_state_->set_connect_requested_for_testing(true); + EXPECT_EQ(network_state_->connection_state(), shill::kStateIdle); + EXPECT_FALSE(network_state_->IsConnectedState()); + EXPECT_TRUE(network_state_->IsConnectingState()); + EXPECT_TRUE(network_state_->IsConnectingOrConnected()); - network_state_.SetConnectionState(shill::kStateOnline); - EXPECT_TRUE(network_state_.IsConnectedState()); - EXPECT_FALSE(network_state_.IsConnectingState()); + network_state_->SetConnectionState(shill::kStateOnline); + EXPECT_TRUE(network_state_->IsConnectedState()); + EXPECT_FALSE(network_state_->IsConnectingState()); } TEST_F(NetworkStateTest, ConnectionStateNotVisible) { - network_state_.set_visible(false); + network_state_->set_visible(false); - network_state_.SetConnectionState(shill::kStateConfiguration); - EXPECT_EQ(network_state_.connection_state(), shill::kStateIdle); - EXPECT_FALSE(network_state_.IsConnectingState()); + network_state_->SetConnectionState(shill::kStateConfiguration); + EXPECT_EQ(network_state_->connection_state(), shill::kStateIdle); + EXPECT_FALSE(network_state_->IsConnectingState()); - network_state_.SetConnectionState(shill::kStateOnline); - EXPECT_EQ(network_state_.connection_state(), shill::kStateIdle); - EXPECT_FALSE(network_state_.IsConnectedState()); + network_state_->SetConnectionState(shill::kStateOnline); + EXPECT_EQ(network_state_->connection_state(), shill::kStateIdle); + EXPECT_FALSE(network_state_->IsConnectedState()); - network_state_.SetConnectionState(shill::kStateConfiguration); - EXPECT_EQ(network_state_.connection_state(), shill::kStateIdle); - EXPECT_FALSE(network_state_.IsConnectingState()); + network_state_->SetConnectionState(shill::kStateConfiguration); + EXPECT_EQ(network_state_->connection_state(), shill::kStateIdle); + EXPECT_FALSE(network_state_->IsConnectingState()); } TEST_F(NetworkStateTest, TetherProperties) { - network_state_.set_type_for_testing(kTypeTether); - network_state_.set_tether_carrier("Project Fi"); - network_state_.set_battery_percentage(85); - network_state_.set_tether_has_connected_to_host(true); - network_state_.set_signal_strength(75); + network_state_->set_type_for_testing(kTypeTether); + network_state_->set_tether_carrier("Project Fi"); + network_state_->set_battery_percentage(85); + network_state_->set_tether_has_connected_to_host(true); + network_state_->set_signal_strength(75); base::Value dictionary(base::Value::Type::DICTIONARY); - network_state_.GetStateProperties(&dictionary); + network_state_->GetStateProperties(&dictionary); absl::optional<int> signal_strength = dictionary.FindIntKey(kTetherSignalStrength); @@ -402,14 +423,14 @@ SetProperty(shill::kPaymentPortalProperty, std::move(payment_portal))); SignalInitialPropertiesReceived(); - EXPECT_EQ("Test Cellular", network_state_.name()); + EXPECT_EQ("Test Cellular", network_state_->name()); EXPECT_EQ(shill::kNetworkTechnologyLteAdvanced, - network_state_.network_technology()); - EXPECT_EQ(shill::kActivationTypeOTA, network_state_.activation_type()); + network_state_->network_technology()); + EXPECT_EQ(shill::kActivationTypeOTA, network_state_->activation_type()); EXPECT_EQ(shill::kActivationStateActivated, - network_state_.activation_state()); - EXPECT_EQ("http://test-portal.com", network_state_.payment_url()); - EXPECT_EQ("fake_data", network_state_.payment_post_data()); + network_state_->activation_state()); + EXPECT_EQ("http://test-portal.com", network_state_->payment_url()); + EXPECT_EQ("fake_data", network_state_->payment_post_data()); } TEST_F(NetworkStateTest, CelularPaymentPortalGet) { @@ -433,14 +454,14 @@ SignalInitialPropertiesReceived(); - EXPECT_EQ("Test Cellular", network_state_.name()); + EXPECT_EQ("Test Cellular", network_state_->name()); EXPECT_EQ(shill::kNetworkTechnologyLteAdvanced, - network_state_.network_technology()); - EXPECT_EQ(shill::kActivationTypeOTA, network_state_.activation_type()); + network_state_->network_technology()); + EXPECT_EQ(shill::kActivationTypeOTA, network_state_->activation_type()); EXPECT_EQ(shill::kActivationStateActivated, - network_state_.activation_state()); - EXPECT_EQ("http://test-portal.com", network_state_.payment_url()); - EXPECT_EQ("", network_state_.payment_post_data()); + network_state_->activation_state()); + EXPECT_EQ("http://test-portal.com", network_state_->payment_url()); + EXPECT_EQ("", network_state_->payment_post_data()); } TEST_F(NetworkStateTest, CellularSpecifier) { @@ -450,14 +471,14 @@ EXPECT_TRUE(SetStringProperty(shill::kTypeProperty, shill::kTypeCellular)); EXPECT_TRUE( SetStringProperty(shill::kNameProperty, kTestCellularNetworkName)); - network_state_.set_update_received(); + network_state_->set_update_received(); // Verify that cellular network state with same name but different iccid // produce different specifier values. EXPECT_TRUE(SetStringProperty(shill::kIccidProperty, kTestIccid1)); - std::string specifier1 = network_state_.GetSpecifier(); + std::string specifier1 = network_state_->GetSpecifier(); EXPECT_TRUE(SetStringProperty(shill::kIccidProperty, kTestIccid2)); - std::string specifier2 = network_state_.GetSpecifier(); + std::string specifier2 = network_state_->GetSpecifier(); EXPECT_NE(specifier1, specifier2); } @@ -495,4 +516,38 @@ EXPECT_EQ(kTestGuid, *dictionary.FindStringKey(shill::kGuidProperty)); } +TEST_F(NetworkStateTest, UpdateCaptivePortalState) { + base::Value shill_properties(base::Value::Type::DICT); + + network_state_->set_visible(true); + EXPECT_EQ(GetShillPortalState(), NetworkState::PortalState::kUnknown); + + SetConnectionState(shill::kStateIdle); + UpdateCaptivePortalState(shill_properties); + EXPECT_EQ(GetShillPortalState(), NetworkState::PortalState::kUnknown); + + SetConnectionState(shill::kStateNoConnectivity); + UpdateCaptivePortalState(shill_properties); + EXPECT_EQ(GetShillPortalState(), NetworkState::PortalState::kNoInternet); + + SetConnectionState(shill::kStateRedirectFound); + UpdateCaptivePortalState(shill_properties); + EXPECT_EQ(GetShillPortalState(), NetworkState::PortalState::kPortal); + + SetConnectionState(shill::kStatePortalSuspected); + UpdateCaptivePortalState(shill_properties); + EXPECT_EQ(GetShillPortalState(), NetworkState::PortalState::kPortalSuspected); + + shill_properties.GetDict().Set( + shill::kPortalDetectionFailedStatusCodeProperty, + net::HTTP_PROXY_AUTHENTICATION_REQUIRED); + UpdateCaptivePortalState(shill_properties); + EXPECT_EQ(GetShillPortalState(), + NetworkState::PortalState::kProxyAuthRequired); + + SetConnectionState(shill::kStateOnline); + UpdateCaptivePortalState(shill_properties); + EXPECT_EQ(GetShillPortalState(), NetworkState::PortalState::kOnline); +} + } // namespace ash
diff --git a/chromeos/ash/components/phonehub/notification_manager_impl.h b/chromeos/ash/components/phonehub/notification_manager_impl.h index 427e3d7..f74bfbf 100644 --- a/chromeos/ash/components/phonehub/notification_manager_impl.h +++ b/chromeos/ash/components/phonehub/notification_manager_impl.h
@@ -9,6 +9,7 @@ #include "chromeos/ash/components/phonehub/notification_manager.h" #include "chromeos/ash/services/multidevice_setup/public/cpp/multidevice_setup_client.h" #include "chromeos/ash/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace ash { namespace phonehub { @@ -40,7 +41,8 @@ MessageSender* message_sender_; UserActionRecorder* user_action_recorder_; multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; - multidevice_setup::mojom::FeatureState notifications_feature_status_; + absl::optional<multidevice_setup::mojom::FeatureState> + notifications_feature_status_; }; } // namespace phonehub
diff --git a/chromeos/ash/services/assistant/assistant_manager_service.h b/chromeos/ash/services/assistant/assistant_manager_service.h index 9e75eb1..6f75b66 100644 --- a/chromeos/ash/services/assistant/assistant_manager_service.h +++ b/chromeos/ash/services/assistant/assistant_manager_service.h
@@ -34,6 +34,8 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. + // If any value is added, please update enums.xml + // `AssistantServiceState`. // Enumeration of possible assistant manager service states. enum State { // Initial state, the service is created but not started yet.
diff --git a/chromeos/ash/services/device_sync/device_sync_impl.cc b/chromeos/ash/services/device_sync/device_sync_impl.cc index afbde9b..b47a0b43 100644 --- a/chromeos/ash/services/device_sync/device_sync_impl.cc +++ b/chromeos/ash/services/device_sync/device_sync_impl.cc
@@ -35,6 +35,7 @@ #include "chromeos/ash/services/device_sync/cryptauth_v2_device_manager_impl.h" #include "chromeos/ash/services/device_sync/cryptauth_v2_enrollment_manager_impl.h" #include "chromeos/ash/services/device_sync/device_sync_type_converters.h" +#include "chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_api.pb.h" #include "chromeos/ash/services/device_sync/proto/device_classifier_util.h" #include "chromeos/ash/services/device_sync/public/cpp/gcm_device_info_provider.h" @@ -488,6 +489,43 @@ ForceCryptAuthOperationResult::kSuccess /* result */); } +void DeviceSyncImpl::GetGroupPrivateKeyStatus( + GetGroupPrivateKeyStatusCallback callback) { + DCHECK(features::ShouldUseV2DeviceSync); + + if (status_ != InitializationStatus::kReady) { + PA_LOG(WARNING) << "DeviceSyncImpl::GetGroupPrivateKeyStatus() invoked " + "before initialization was complete. Cannot return " + "group private key status."; + std::move(callback).Run( + GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized); + return; + } + + std::move(callback).Run( + cryptauth_v2_device_manager_->GetDeviceSyncerGroupPrivateKeyStatus()); +} + +void DeviceSyncImpl::GetBetterTogetherMetadataStatus( + GetBetterTogetherMetadataStatusCallback callback) { + DCHECK(features::ShouldUseV2DeviceSync); + + if (status_ != InitializationStatus::kReady) { + PA_LOG(WARNING) + << "DeviceSyncImpl::GetBetterTogetherMetadataStatus() invoked " + "before initialization was complete. Cannot return " + "better together metadata status."; + std::move(callback).Run( + BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized); + return; + } + + std::move(callback).Run(cryptauth_v2_device_manager_ + ->GetDeviceSyncerBetterTogetherMetadataStatus()); +} + void DeviceSyncImpl::GetLocalDeviceMetadata( GetLocalDeviceMetadataCallback callback) { if (status_ != InitializationStatus::kReady) {
diff --git a/chromeos/ash/services/device_sync/device_sync_impl.h b/chromeos/ash/services/device_sync/device_sync_impl.h index 2dbd3c2..893ccd5e4 100644 --- a/chromeos/ash/services/device_sync/device_sync_impl.h +++ b/chromeos/ash/services/device_sync/device_sync_impl.h
@@ -116,6 +116,10 @@ // device_sync::mojom::DeviceSync: void ForceEnrollmentNow(ForceEnrollmentNowCallback callback) override; void ForceSyncNow(ForceSyncNowCallback callback) override; + void GetGroupPrivateKeyStatus( + GetGroupPrivateKeyStatusCallback callback) override; + void GetBetterTogetherMetadataStatus( + GetBetterTogetherMetadataStatusCallback callback) override; void GetLocalDeviceMetadata(GetLocalDeviceMetadataCallback callback) override; void GetSyncedDevices(GetSyncedDevicesCallback callback) override; void SetSoftwareFeatureState(
diff --git a/chromeos/ash/services/device_sync/device_sync_service_unittest.cc b/chromeos/ash/services/device_sync/device_sync_service_unittest.cc index 4db30a87..7ee01a89 100644 --- a/chromeos/ash/services/device_sync/device_sync_service_unittest.cc +++ b/chromeos/ash/services/device_sync/device_sync_service_unittest.cc
@@ -46,6 +46,7 @@ #include "chromeos/ash/services/device_sync/fake_device_sync_observer.h" #include "chromeos/ash/services/device_sync/fake_remote_device_provider.h" #include "chromeos/ash/services/device_sync/fake_software_feature_manager.h" +#include "chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_client_app_metadata.pb.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_common.pb.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_v2_test_util.h" @@ -1178,6 +1179,15 @@ // initialization. EXPECT_FALSE(CallGetLocalDeviceMetadata()); + // GetGroupPrivateKeyStatus() and GetBetterTogetherMetadataStatus() both + // should return kStatusUnavailableBecauseDeviceSyncIsNotInitialized. + EXPECT_EQ(GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + CallGetGroupPrivateKeyStatus()); + EXPECT_EQ(BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + CallGetBetterTogetherMetadataStatus()); + if (features::ShouldUseV1DeviceSync()) { // SetSoftwareFeatureState() should return a struct with the special // kErrorNotInitialized error code. @@ -1286,6 +1296,24 @@ return last_force_sync_now_result_; } + GroupPrivateKeyStatus CallGetGroupPrivateKeyStatus() { + base::RunLoop run_loop; + device_sync_->GetGroupPrivateKeyStatus(base::BindOnce( + &DeviceSyncServiceTest::OnGetGroupPrivateKeyStatusCompleted, + base::Unretained(this), run_loop.QuitClosure())); + run_loop.Run(); + return last_group_private_key_status_result_; + } + + BetterTogetherMetadataStatus CallGetBetterTogetherMetadataStatus() { + base::RunLoop run_loop; + device_sync_->GetBetterTogetherMetadataStatus(base::BindOnce( + &DeviceSyncServiceTest::OnGetBetterTogetherMetadataStatusCompleted, + base::Unretained(this), run_loop.QuitClosure())); + run_loop.Run(); + return last_better_together_metadata_status_result_; + } + const absl::optional<multidevice::RemoteDevice>& CallGetLocalDeviceMetadata() { base::RunLoop run_loop; @@ -1503,6 +1531,19 @@ std::move(quit_closure).Run(); } + void OnGetGroupPrivateKeyStatusCompleted(base::OnceClosure quit_closure, + GroupPrivateKeyStatus status) { + last_group_private_key_status_result_ = status; + std::move(quit_closure).Run(); + } + + void OnGetBetterTogetherMetadataStatusCompleted( + base::OnceClosure quit_closure, + BetterTogetherMetadataStatus status) { + last_better_together_metadata_status_result_ = status; + std::move(quit_closure).Run(); + } + void OnGetLocalDeviceMetadataCompleted( base::OnceClosure quit_closure, const absl::optional<multidevice::RemoteDevice>& local_device_metadata) { @@ -1625,6 +1666,8 @@ bool device_already_enrolled_in_cryptauth_; bool last_force_enrollment_now_result_; bool last_force_sync_now_result_; + GroupPrivateKeyStatus last_group_private_key_status_result_; + BetterTogetherMetadataStatus last_better_together_metadata_status_result_; absl::optional<multidevice::RemoteDeviceList> last_synced_devices_result_; absl::optional<multidevice::RemoteDevice> last_local_device_metadata_result_; std::unique_ptr<mojom::NetworkRequestResult> @@ -1835,6 +1878,24 @@ EXPECT_EQ(1u, fake_device_sync_observer()->num_enrollment_events()); } +TEST_P(DeviceSyncServiceTest, GetGroupPrivateKeyStatus) { + if (!features::ShouldUseV2DeviceSync()) + return; + + InitializeServiceSuccessfully(); + EXPECT_EQ(GroupPrivateKeyStatus::kWaitingForGroupPrivateKey, + CallGetGroupPrivateKeyStatus()); +} + +TEST_P(DeviceSyncServiceTest, GetBetterTogetherMetadataStatus) { + if (!features::ShouldUseV2DeviceSync()) + return; + + InitializeServiceSuccessfully(); + EXPECT_EQ(BetterTogetherMetadataStatus::kWaitingToProcessDeviceMetadata, + CallGetBetterTogetherMetadataStatus()); +} + TEST_P(DeviceSyncServiceTest, GetLocalDeviceMetadata) { InitializeServiceSuccessfully();
diff --git a/chromeos/ash/services/device_sync/fake_device_sync.cc b/chromeos/ash/services/device_sync/fake_device_sync.cc index 3b9e840..7889aec 100644 --- a/chromeos/ash/services/device_sync/fake_device_sync.cc +++ b/chromeos/ash/services/device_sync/fake_device_sync.cc
@@ -18,6 +18,19 @@ FakeDeviceSync::~FakeDeviceSync() = default; +void FakeDeviceSync::InvokePendingGetGroupPrivateKeyStatusCallback( + GroupPrivateKeyStatus status) { + std::move(get_group_private_key_status_callback_queue_.front()).Run(status); + get_group_private_key_status_callback_queue_.pop(); +} + +void FakeDeviceSync::InvokePendingGetBetterTogetherMetadataStatusCallback( + BetterTogetherMetadataStatus status) { + std::move(get_better_together_metadata_status_callback_queue_.front()) + .Run(status); + get_better_together_metadata_status_callback_queue_.pop(); +} + void FakeDeviceSync::InvokePendingGetLocalDeviceMetadataCallback( const absl::optional<multidevice::RemoteDevice>& local_device_metadata) { std::move(get_local_device_metadata_callback_queue_.front()) @@ -83,6 +96,16 @@ std::move(callback).Run(force_sync_now_completed_success_); } +void FakeDeviceSync::GetGroupPrivateKeyStatus( + GetGroupPrivateKeyStatusCallback callback) { + get_group_private_key_status_callback_queue_.push(std::move(callback)); +} + +void FakeDeviceSync::GetBetterTogetherMetadataStatus( + GetBetterTogetherMetadataStatusCallback callback) { + get_better_together_metadata_status_callback_queue_.push(std::move(callback)); +} + void FakeDeviceSync::GetLocalDeviceMetadata( GetLocalDeviceMetadataCallback callback) { get_local_device_metadata_callback_queue_.push(std::move(callback));
diff --git a/chromeos/ash/services/device_sync/fake_device_sync.h b/chromeos/ash/services/device_sync/fake_device_sync.h index 338dc63..76bbcf9 100644 --- a/chromeos/ash/services/device_sync/fake_device_sync.h +++ b/chromeos/ash/services/device_sync/fake_device_sync.h
@@ -37,6 +37,10 @@ force_sync_now_completed_success_ = force_sync_now_completed_success; } + void InvokePendingGetGroupPrivateKeyStatusCallback( + GroupPrivateKeyStatus status); + void InvokePendingGetBetterTogetherMetadataStatusCallback( + BetterTogetherMetadataStatus status); void InvokePendingGetLocalDeviceMetadataCallback( const absl::optional<multidevice::RemoteDevice>& local_device_metadata); void InvokePendingGetSyncedDevicesCallback( @@ -61,6 +65,10 @@ // device_sync::mojom::DeviceSync: void ForceEnrollmentNow(ForceEnrollmentNowCallback callback) override; void ForceSyncNow(ForceSyncNowCallback callback) override; + void GetGroupPrivateKeyStatus( + GetGroupPrivateKeyStatusCallback callback) override; + void GetBetterTogetherMetadataStatus( + GetBetterTogetherMetadataStatusCallback callback) override; void GetLocalDeviceMetadata(GetLocalDeviceMetadataCallback callback) override; void GetSyncedDevices(GetSyncedDevicesCallback callback) override; void SetSoftwareFeatureState( @@ -87,6 +95,10 @@ bool force_enrollment_now_completed_success_ = true; bool force_sync_now_completed_success_ = true; + std::queue<GetGroupPrivateKeyStatusCallback> + get_group_private_key_status_callback_queue_; + std::queue<GetBetterTogetherMetadataStatusCallback> + get_better_together_metadata_status_callback_queue_; std::queue<GetLocalDeviceMetadataCallback> get_local_device_metadata_callback_queue_; std::queue<GetSyncedDevicesCallback> get_synced_devices_callback_queue_;
diff --git a/chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h b/chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h index c05abcc..0f0f838a 100644 --- a/chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h +++ b/chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h
@@ -11,6 +11,10 @@ // CryptAuthDeviceSyncer. These enums are declared in their own module so they // can be consumed by mojom::DeviceSync and avoid a dependency cycle. enum class GroupPrivateKeyStatus { + // When Device Sync is not initialized, it cannot access the group private key + // status and will return this value. + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + // The CryptAuth SyncMetadata response that includes the encrypted group // private key hasn't been received yet. kWaitingForGroupPrivateKey, @@ -33,10 +37,14 @@ // The group private key was successfully decrypted. This is the expected // final state of this flow. - kGroupPrivateKeySuccessfullyDecrypted + kGroupPrivateKeySuccessfullyDecrypted, }; enum class BetterTogetherMetadataStatus { + // When Device Sync is not initialized, it cannot access the better together + // metadata status and will return this value. + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + // The attempt to process the encrypted device metadata hasn't started yet. // If the device sync attempt finishes and this is still the metadata // status, clients can inspect GroupPrivateKeyStatus to understand why.
diff --git a/chromeos/ash/services/device_sync/public/mojom/BUILD.gn b/chromeos/ash/services/device_sync/public/mojom/BUILD.gn index 5b00270..e9501a98 100644 --- a/chromeos/ash/services/device_sync/public/mojom/BUILD.gn +++ b/chromeos/ash/services/device_sync/public/mojom/BUILD.gn
@@ -33,11 +33,20 @@ mojom = "ash.device_sync.mojom.CryptAuthService" cpp = "cryptauthv2::TargetService" }, + { + mojom = "ash.device_sync.mojom.GroupPrivateKeyStatus" + cpp = "ash::device_sync::GroupPrivateKeyStatus" + }, + { + mojom = "ash.device_sync.mojom.BetterTogetherMetadataStatus" + cpp = "ash::device_sync::BetterTogetherMetadataStatus" + }, ] traits_headers = [ "device_sync_mojom_traits.h" ] traits_sources = [ "device_sync_mojom_traits.cc" ] traits_public_deps = [ "//chromeos/ash/services/device_sync:feature_status_change", + "//chromeos/ash/services/device_sync:group_private_key_and_better_together_metadata_status", "//chromeos/ash/services/device_sync/proto", ] },
diff --git a/chromeos/ash/services/device_sync/public/mojom/device_sync.mojom b/chromeos/ash/services/device_sync/public/mojom/device_sync.mojom index 2398b2de..af4316b 100644 --- a/chromeos/ash/services/device_sync/public/mojom/device_sync.mojom +++ b/chromeos/ash/services/device_sync/public/mojom/device_sync.mojom
@@ -73,6 +73,62 @@ kUnknownConnectivity }; +// Describes the status of the encrypted group private key received in the +// SyncMetadataResponse. +enum GroupPrivateKeyStatus { + // When Device Sync is not initialized, it cannot access the group private key + // status and will return this value. + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + + // The CryptAuth SyncMetadata response that includes the encrypted group + // private key hasn't been received yet. + kWaitingForGroupPrivateKey, + + // The SyncMetadata response was been received, but doesn't include any + // encrypted group private key. This is expected when no other user device + // uploaded the key or if we already own the key. + kNoEncryptedGroupPrivateKeyReceived, + + // The SyncMetadata response was received, but the included encrypted group + // private key is empty. + kEncryptedGroupPrivateKeyEmpty, + + // This device's CryptAuthKeyBundle::Name::kDeviceSyncBetterTogether key is + // missing, so the encrypted group private key cannot be decrypted. + kLocalDeviceSyncBetterTogetherKeyMissing, + + // An error occurred when decrypting the group private key. + kGroupPrivateKeyDecryptionFailed, + + // The group private key was successfully decrypted. This is the expected + // final state of this flow. + kGroupPrivateKeySuccessfullyDecrypted +}; + +// Describes the status of the better together remote device metadata. +enum BetterTogetherMetadataStatus { + // When Device Sync is not initialized, it cannot access the better together + // metadata status and will return this value. + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + + // The attempt to process the encrypted device metadata hasn't started yet. + // If the device sync attempt finishes and this is still the metadata + // status, clients can inspect GroupPrivateKeyStatus to understand why. + kWaitingToProcessDeviceMetadata, + + // The group private key required to decrypt the metadata is missing. + // Clients can inspect GroupPrivateKeyStatus to understand why the group + // private key is missing. + kGroupPrivateKeyMissing, + + // CryptAuth didn't send any encrypted metadata. + kEncryptedMetadataEmpty, + + // Device metadata was decrypted. This is the expected final state of this + // flow. + kMetadataDecrypted +}; + struct FindEligibleDevicesResponse { array<ash.multidevice.mojom.RemoteDevice> eligible_devices; array<ash.multidevice.mojom.RemoteDevice> ineligible_devices; @@ -136,6 +192,13 @@ [Sync] ForceSyncNow() => (bool success); + // Returns the status of the encrypted group private key received in the + // SyncMetadataResponse. + GetGroupPrivateKeyStatus() => (GroupPrivateKeyStatus status); + + // Returns the status of the better together remote device metadata. + GetBetterTogetherMetadataStatus() => (BetterTogetherMetadataStatus status); + // Returns all synced devices associated with the primary account. If this // device has not yet registered with the back-end, no list is provided. GetSyncedDevices() =>
diff --git a/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.cc b/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.cc index d57709f..856bac2 100644 --- a/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.cc +++ b/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.cc
@@ -46,6 +46,157 @@ return false; } +ash::device_sync::mojom::GroupPrivateKeyStatus +EnumTraits<ash::device_sync::mojom::GroupPrivateKeyStatus, + ash::device_sync::GroupPrivateKeyStatus>:: + ToMojom(ash::device_sync::GroupPrivateKeyStatus input) { + switch (input) { + case ash::device_sync::GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized; + case ash::device_sync::GroupPrivateKeyStatus::kWaitingForGroupPrivateKey: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kWaitingForGroupPrivateKey; + case ash::device_sync::GroupPrivateKeyStatus:: + kNoEncryptedGroupPrivateKeyReceived: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kNoEncryptedGroupPrivateKeyReceived; + case ash::device_sync::GroupPrivateKeyStatus:: + kEncryptedGroupPrivateKeyEmpty: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kEncryptedGroupPrivateKeyEmpty; + case ash::device_sync::GroupPrivateKeyStatus:: + kLocalDeviceSyncBetterTogetherKeyMissing: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kLocalDeviceSyncBetterTogetherKeyMissing; + case ash::device_sync::GroupPrivateKeyStatus:: + kGroupPrivateKeyDecryptionFailed: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kGroupPrivateKeyDecryptionFailed; + case ash::device_sync::GroupPrivateKeyStatus:: + kGroupPrivateKeySuccessfullyDecrypted: + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kGroupPrivateKeySuccessfullyDecrypted; + } + + NOTREACHED(); + return ash::device_sync::mojom::GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized; +} + +bool EnumTraits<ash::device_sync::mojom::GroupPrivateKeyStatus, + ash::device_sync::GroupPrivateKeyStatus>:: + FromMojom(ash::device_sync::mojom::GroupPrivateKeyStatus input, + ash::device_sync::GroupPrivateKeyStatus* out) { + switch (input) { + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized: + *out = ash::device_sync::GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized; + return true; + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kWaitingForGroupPrivateKey: + *out = + ash::device_sync::GroupPrivateKeyStatus::kWaitingForGroupPrivateKey; + return true; + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kNoEncryptedGroupPrivateKeyReceived: + *out = ash::device_sync::GroupPrivateKeyStatus:: + kNoEncryptedGroupPrivateKeyReceived; + return true; + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kEncryptedGroupPrivateKeyEmpty: + *out = ash::device_sync::GroupPrivateKeyStatus:: + kEncryptedGroupPrivateKeyEmpty; + return true; + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kLocalDeviceSyncBetterTogetherKeyMissing: + *out = ash::device_sync::GroupPrivateKeyStatus:: + kLocalDeviceSyncBetterTogetherKeyMissing; + return true; + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kGroupPrivateKeyDecryptionFailed: + *out = ash::device_sync::GroupPrivateKeyStatus:: + kGroupPrivateKeyDecryptionFailed; + return true; + case ash::device_sync::mojom::GroupPrivateKeyStatus:: + kGroupPrivateKeySuccessfullyDecrypted: + *out = ash::device_sync::GroupPrivateKeyStatus:: + kGroupPrivateKeySuccessfullyDecrypted; + return true; + } + + NOTREACHED(); + return false; +} + +ash::device_sync::mojom::BetterTogetherMetadataStatus +EnumTraits<ash::device_sync::mojom::BetterTogetherMetadataStatus, + ash::device_sync::BetterTogetherMetadataStatus>:: + ToMojom(ash::device_sync::BetterTogetherMetadataStatus input) { + switch (input) { + case ash::device_sync::BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized: + return ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized; + case ash::device_sync::BetterTogetherMetadataStatus:: + kWaitingToProcessDeviceMetadata: + return ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kWaitingToProcessDeviceMetadata; + case ash::device_sync::BetterTogetherMetadataStatus:: + kGroupPrivateKeyMissing: + return ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kGroupPrivateKeyMissing; + case ash::device_sync::BetterTogetherMetadataStatus:: + kEncryptedMetadataEmpty: + return ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kEncryptedMetadataEmpty; + case ash::device_sync::BetterTogetherMetadataStatus::kMetadataDecrypted: + return ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kMetadataDecrypted; + } + + NOTREACHED(); + return ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized; +} + +bool EnumTraits<ash::device_sync::mojom::BetterTogetherMetadataStatus, + ash::device_sync::BetterTogetherMetadataStatus>:: + FromMojom(ash::device_sync::mojom::BetterTogetherMetadataStatus input, + ash::device_sync::BetterTogetherMetadataStatus* out) { + switch (input) { + case ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized: + *out = ash::device_sync::BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized; + return true; + case ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kWaitingToProcessDeviceMetadata: + *out = ash::device_sync::BetterTogetherMetadataStatus:: + kWaitingToProcessDeviceMetadata; + return true; + case ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kGroupPrivateKeyMissing: + *out = ash::device_sync::BetterTogetherMetadataStatus:: + kGroupPrivateKeyMissing; + return true; + case ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kEncryptedMetadataEmpty: + *out = ash::device_sync::BetterTogetherMetadataStatus:: + kEncryptedMetadataEmpty; + return true; + case ash::device_sync::mojom::BetterTogetherMetadataStatus:: + kMetadataDecrypted: + *out = ash::device_sync::BetterTogetherMetadataStatus::kMetadataDecrypted; + return true; + } + + NOTREACHED(); + return false; +} + ash::device_sync::mojom::FeatureStatusChange EnumTraits<ash::device_sync::mojom::FeatureStatusChange, ash::device_sync::FeatureStatusChange>::
diff --git a/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.h b/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.h index 82589ae..b604f25 100644 --- a/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.h +++ b/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.h
@@ -6,6 +6,7 @@ #define CHROMEOS_ASH_SERVICES_DEVICE_SYNC_PUBLIC_MOJOM_DEVICE_SYNC_MOJOM_TRAITS_H_ #include "chromeos/ash/services/device_sync/feature_status_change.h" +#include "chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_common.pb.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_devicesync.pb.h" #include "chromeos/ash/services/device_sync/public/mojom/device_sync.mojom-shared.h" @@ -24,6 +25,27 @@ }; template <> +class EnumTraits<ash::device_sync::mojom::GroupPrivateKeyStatus, + ash::device_sync::GroupPrivateKeyStatus> { + public: + static ash::device_sync::mojom::GroupPrivateKeyStatus ToMojom( + ash::device_sync::GroupPrivateKeyStatus input); + static bool FromMojom(ash::device_sync::mojom::GroupPrivateKeyStatus input, + ash::device_sync::GroupPrivateKeyStatus* out); +}; + +template <> +class EnumTraits<ash::device_sync::mojom::BetterTogetherMetadataStatus, + ash::device_sync::BetterTogetherMetadataStatus> { + public: + static ash::device_sync::mojom::BetterTogetherMetadataStatus ToMojom( + ash::device_sync::BetterTogetherMetadataStatus input); + static bool FromMojom( + ash::device_sync::mojom::BetterTogetherMetadataStatus input, + ash::device_sync::BetterTogetherMetadataStatus* out); +}; + +template <> class EnumTraits<ash::device_sync::mojom::FeatureStatusChange, ash::device_sync::FeatureStatusChange> { public:
diff --git a/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc b/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc index df9a3d2..552874ed 100644 --- a/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc +++ b/chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits_unittest.cc
@@ -5,6 +5,7 @@ #include "chromeos/ash/services/device_sync/public/mojom/device_sync_mojom_traits.h" #include "chromeos/ash/services/device_sync/feature_status_change.h" +#include "chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h" #include "chromeos/ash/services/device_sync/proto/cryptauth_devicesync.pb.h" #include "chromeos/ash/services/device_sync/public/mojom/device_sync.mojom.h" #include "mojo/public/cpp/test_support/test_utils.h" @@ -29,6 +30,66 @@ } } +TEST(DeviceSyncMojomTraitsTest, GroupPrivateKeyStatus) { + static constexpr ash::device_sync::GroupPrivateKeyStatus + kTestGroupPrivateKeyStatuses[] = { + ash::device_sync::GroupPrivateKeyStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + ash::device_sync::GroupPrivateKeyStatus::kWaitingForGroupPrivateKey, + ash::device_sync::GroupPrivateKeyStatus:: + kNoEncryptedGroupPrivateKeyReceived, + ash::device_sync::GroupPrivateKeyStatus:: + kEncryptedGroupPrivateKeyEmpty, + ash::device_sync::GroupPrivateKeyStatus:: + kLocalDeviceSyncBetterTogetherKeyMissing, + ash::device_sync::GroupPrivateKeyStatus:: + kGroupPrivateKeyDecryptionFailed, + ash::device_sync::GroupPrivateKeyStatus:: + kGroupPrivateKeySuccessfullyDecrypted}; + + for (auto status_in : kTestGroupPrivateKeyStatuses) { + ash::device_sync::GroupPrivateKeyStatus status_out; + + ash::device_sync::mojom::GroupPrivateKeyStatus serialized_status = + mojo::EnumTraits< + ash::device_sync::mojom::GroupPrivateKeyStatus, + ash::device_sync::GroupPrivateKeyStatus>::ToMojom(status_in); + ASSERT_TRUE( + (mojo::EnumTraits<ash::device_sync::mojom::GroupPrivateKeyStatus, + ash::device_sync::GroupPrivateKeyStatus>:: + FromMojom(serialized_status, &status_out))); + EXPECT_EQ(status_in, status_out); + } +} + +TEST(DeviceSyncMojomTraitsTest, BetterTogetherMetadataStatus) { + static constexpr ash::device_sync::BetterTogetherMetadataStatus + kTestBetterTogetherMetadataStatuses[] = { + ash::device_sync::BetterTogetherMetadataStatus:: + kStatusUnavailableBecauseDeviceSyncIsNotInitialized, + ash::device_sync::BetterTogetherMetadataStatus:: + kWaitingToProcessDeviceMetadata, + ash::device_sync::BetterTogetherMetadataStatus:: + kGroupPrivateKeyMissing, + ash::device_sync::BetterTogetherMetadataStatus:: + kEncryptedMetadataEmpty, + ash::device_sync::BetterTogetherMetadataStatus::kMetadataDecrypted}; + + for (auto status_in : kTestBetterTogetherMetadataStatuses) { + ash::device_sync::BetterTogetherMetadataStatus status_out; + + ash::device_sync::mojom::BetterTogetherMetadataStatus serialized_status = + mojo::EnumTraits< + ash::device_sync::mojom::BetterTogetherMetadataStatus, + ash::device_sync::BetterTogetherMetadataStatus>::ToMojom(status_in); + ASSERT_TRUE( + (mojo::EnumTraits<ash::device_sync::mojom::BetterTogetherMetadataStatus, + ash::device_sync::BetterTogetherMetadataStatus>:: + FromMojom(serialized_status, &status_out))); + EXPECT_EQ(status_in, status_out); + } +} + TEST(DeviceSyncMojomTraitsTest, FeatureStatusChange) { static constexpr ash::device_sync::FeatureStatusChange kTestFeatureStatusChanges[] = {
diff --git a/chromeos/ash/services/device_sync/stub_device_sync.cc b/chromeos/ash/services/device_sync/stub_device_sync.cc index a6e8797..5b93ffb 100644 --- a/chromeos/ash/services/device_sync/stub_device_sync.cc +++ b/chromeos/ash/services/device_sync/stub_device_sync.cc
@@ -15,6 +15,7 @@ #include "chromeos/ash/components/multidevice/stub_multidevice_util.h" #include "chromeos/ash/services/device_sync/device_sync_base.h" #include "chromeos/ash/services/device_sync/device_sync_impl.h" +#include "chromeos/ash/services/device_sync/group_private_key_and_better_together_metadata_status.h" #include "chromeos/ash/services/device_sync/public/mojom/device_sync.mojom.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -82,6 +83,18 @@ std::move(callback).Run(/*success=*/true); } + void GetBetterTogetherMetadataStatus( + GetBetterTogetherMetadataStatusCallback callback) override { + std::move(callback).Run(/*result=*/BetterTogetherMetadataStatus:: + kWaitingToProcessDeviceMetadata); + } + + void GetGroupPrivateKeyStatus( + GetGroupPrivateKeyStatusCallback callback) override { + std::move(callback).Run( + /*result=*/GroupPrivateKeyStatus::kWaitingForGroupPrivateKey); + } + void GetLocalDeviceMetadata( GetLocalDeviceMetadataCallback callback) override { std::move(callback).Run(local_device_metadata_);
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 996ce6c1..a8bc9e6f 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -3673,6 +3673,11 @@ <message name="IDS_SHORTCUT_CUSTOMIZATION_SUBCATEGORY_GENERAL" desc="Subcategory named 'General' shown within main shortcuts section" translateable="false">General</message> <message name="IDS_SHORTCUT_CUSTOMIZATION_SUBCATEGORY_SYSTEM_APPS" desc="Subcategory named 'System Apps' shown within main shortcuts section" translateable="false">System Apps</message> <message name="IDS_SHORTCUT_CUSTOMIZATION_SUBCATEGORY_SYSTEM_CONTROLS" desc="Subcategory named 'System Controls' shown within main shortcuts section" translateable="false">System Controls</message> + <message name="IDS_SHORTCUT_CUSTOMIZATION_KEY_SPACE" desc="Lowercase name of the keyboard key 'Space'" translateable="false">space</message> + <message name="IDS_SHORTCUT_CUSTOMIZATION_KEY_TAB" desc="Lowercase name of the keyboard key 'Tab'" translateable="false">tab</message> + <message name="IDS_SHORTCUT_CUSTOMIZATION_KEY_ESCAPE" desc="Lowercase name of the keyboard key 'Escape', abbreviated if possible" translateable="false">esc</message> + <message name="IDS_SHORTCUT_CUSTOMIZATION_KEY_RETURN" desc="Lowercase name of the keyboard key 'Enter'" translateable="false">enter</message> + <message name="IDS_SHORTCUT_CUSTOMIZATION_KEY_BACKSPACE" desc="Lowercase name of the keyboard key 'Backspace'" translateable="false">backspace</message> <!-- End of Shortcut Customization --> <!-- APN -->
diff --git a/chromeos/crosapi/mojom/web_app_types.mojom b/chromeos/crosapi/mojom/web_app_types.mojom index 2103c606..a54194a 100644 --- a/chromeos/crosapi/mojom/web_app_types.mojom +++ b/chromeos/crosapi/mojom/web_app_types.mojom
@@ -37,6 +37,7 @@ kUpdateTaskFailed, [MinVersion=1] kAppNotInRegistrarAfterCommit, [MinVersion=2] kHaltedBySyncUninstall, + [MinVersion=3] kInstallURLInvalid, }; // See |webapps::UninstallResultCode|.
diff --git a/chromeos/crosapi/mojom/web_app_types_mojom_traits.cc b/chromeos/crosapi/mojom/web_app_types_mojom_traits.cc index a2a05edc..2f6a19c 100644 --- a/chromeos/crosapi/mojom/web_app_types_mojom_traits.cc +++ b/chromeos/crosapi/mojom/web_app_types_mojom_traits.cc
@@ -71,6 +71,8 @@ kAppNotInRegistrarAfterCommit; case webapps::InstallResultCode::kHaltedBySyncUninstall: return crosapi::mojom::WebAppInstallResultCode::kHaltedBySyncUninstall; + case webapps::InstallResultCode::kInstallURLInvalid: + return crosapi::mojom::WebAppInstallResultCode::kInstallURLInvalid; }; } @@ -157,6 +159,9 @@ case crosapi::mojom::WebAppInstallResultCode::kHaltedBySyncUninstall: *output = webapps::InstallResultCode::kHaltedBySyncUninstall; return true; + case crosapi::mojom::WebAppInstallResultCode::kInstallURLInvalid: + *output = webapps::InstallResultCode::kInstallURLInvalid; + return true; }; NOTREACHED();
diff --git a/chromeos/ui/wm/features.cc b/chromeos/ui/wm/features.cc index dae87381..9d3ef8e 100644 --- a/chromeos/ui/wm/features.cc +++ b/chromeos/ui/wm/features.cc
@@ -12,9 +12,7 @@ // Enables a window to float. // https://crbug.com/1240411 -BASE_FEATURE(kFloatWindow, - "CrOSLabsFloatWindow", - base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kFloatWindow, "FloatWindow", base::FEATURE_DISABLED_BY_DEFAULT); BASE_FEATURE(kPartialSplit, "PartialSplit", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/BUILD.gn b/components/BUILD.gn index 5bddc33..c0838c7 100644 --- a/components/BUILD.gn +++ b/components/BUILD.gn
@@ -10,6 +10,7 @@ import("//components/optimization_guide/features.gni") import("//components/safe_browsing/buildflags.gni") import("//components/services/screen_ai/buildflags/features.gni") +import("//components/supervised_user/buildflags.gni") import("//extensions/buildflags/buildflags.gni") import("//media/media_options.gni") import("//pdf/features.gni") @@ -230,6 +231,7 @@ "//components/subresource_filter/core/browser:unit_tests", "//components/subresource_filter/core/common:unit_tests", "//components/subresource_filter/tools:unit_tests", + "//components/supervised_user/core/common:unit_tests", "//components/sync:unit_tests", "//components/sync_bookmarks:unit_tests", "//components/sync_device_info:unit_tests", @@ -258,6 +260,10 @@ "//components/webdata_services:unit_tests", ] + if (enable_supervised_users) { + deps += [ "//components/supervised_user/core/browser:unit_tests" ] + } + if (!is_ios) { deps += [ "//components/file_access:unit_tests" ] }
diff --git a/components/autofill/core/common/autofill_payments_features.cc b/components/autofill/core/common/autofill_payments_features.cc index 39dcdc7a..8f117ce 100644 --- a/components/autofill/core/common/autofill_payments_features.cc +++ b/components/autofill/core/common/autofill_payments_features.cc
@@ -188,6 +188,12 @@ "AutofillParseVcnCardOnFileStandaloneCvcFields", base::FEATURE_DISABLED_BY_DEFAULT); +// When enabled, Expiration and Type titles will be removed from Chrome +// payment settings page. +BASE_FEATURE(kAutofillRemoveCardExpirationAndTypeTitles, + "AutofillRemoveCardExpirationAndTypeTitles", + base::FEATURE_ENABLED_BY_DEFAULT); + // When enabled, the Save Card infobar will be dismissed by a user initiated // navigation other than one caused by submitted form. BASE_FEATURE(kAutofillSaveCardDismissOnNavigation,
diff --git a/components/autofill/core/common/autofill_payments_features.h b/components/autofill/core/common/autofill_payments_features.h index 159798b0..fd39956 100644 --- a/components/autofill/core/common/autofill_payments_features.h +++ b/components/autofill/core/common/autofill_payments_features.h
@@ -38,6 +38,7 @@ BASE_DECLARE_FEATURE(kAutofillFillMerchantPromoCodeFields); BASE_DECLARE_FEATURE(kAutofillParseIBANFields); BASE_DECLARE_FEATURE(kAutofillParseVcnCardOnFileStandaloneCvcFields); +BASE_DECLARE_FEATURE(kAutofillRemoveCardExpirationAndTypeTitles); BASE_DECLARE_FEATURE(kAutofillSaveCardDismissOnNavigation); BASE_DECLARE_FEATURE(kAutofillSaveCardInfobarEditSupport); BASE_DECLARE_FEATURE(kAutofillSaveCardUiExperiment);
diff --git a/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc b/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc index 4a9416c9..ecf68e2 100644 --- a/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc +++ b/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc
@@ -211,12 +211,9 @@ if (!CheckForFileConsent() || pending_breadcrumbs_.empty()) return; - // Make a copy of |pending_breadcrumbs_| to pass to the DoWriteEventsToFile() - // callback, since |pending_breadcrumbs_| is about to be cleared. - const std::string pending_breadcrumbs = pending_breadcrumbs_; task_runner_->PostTask( FROM_HERE, base::BindOnce(&DoWriteEventsToFile, breadcrumbs_file_path_, - file_position_.value(), pending_breadcrumbs, + file_position_.value(), pending_breadcrumbs_, /*append=*/true, write_counter_, write_counter_at_last_full_rewrite_));
diff --git a/components/browsing_topics/browsing_topics_calculator_unittest.cc b/components/browsing_topics/browsing_topics_calculator_unittest.cc index eef2d1c..b15d81f 100644 --- a/components/browsing_topics/browsing_topics_calculator_unittest.cc +++ b/components/browsing_topics/browsing_topics_calculator_unittest.cc
@@ -87,9 +87,9 @@ optimization_guide::TestOptimizationGuideModelProvider>(); page_content_annotations_service_ = std::make_unique<optimization_guide::PageContentAnnotationsService>( - "en-US", optimization_guide_model_provider_.get(), - history_service_.get(), nullptr, nullptr, base::FilePath(), nullptr, - nullptr); + nullptr, "en-US", optimization_guide_model_provider_.get(), + history_service_.get(), nullptr, nullptr, nullptr, base::FilePath(), + nullptr, nullptr); page_content_annotations_service_->OverridePageContentAnnotatorForTesting( &test_page_content_annotator_);
diff --git a/components/browsing_topics/browsing_topics_service_impl_unittest.cc b/components/browsing_topics/browsing_topics_service_impl_unittest.cc index 40a2f0fb..2293057 100644 --- a/components/browsing_topics/browsing_topics_service_impl_unittest.cc +++ b/components/browsing_topics/browsing_topics_service_impl_unittest.cc
@@ -211,9 +211,9 @@ optimization_guide::TestOptimizationGuideModelProvider>(); page_content_annotations_service_ = std::make_unique<optimization_guide::PageContentAnnotationsService>( - "en-US", optimization_guide_model_provider_.get(), - history_service_.get(), nullptr, nullptr, base::FilePath(), nullptr, - nullptr); + nullptr, "en-US", optimization_guide_model_provider_.get(), + history_service_.get(), nullptr, nullptr, nullptr, base::FilePath(), + nullptr, nullptr); page_content_annotations_service_->OverridePageContentAnnotatorForTesting( &test_page_content_annotator_);
diff --git a/components/commerce/core/android/BUILD.gn b/components/commerce/core/android/BUILD.gn index 3f7251e..c9a9621 100644 --- a/components/commerce/core/android/BUILD.gn +++ b/components/commerce/core/android/BUILD.gn
@@ -12,7 +12,6 @@ deps = [ "//base:jni_java", "//build/android:build_java", - "//third_party/android_deps:guava_android_java", "//third_party/androidx:androidx_annotation_annotation_java", "//url:gurl_java", ]
diff --git a/components/commerce/core/android/java/src/org/chromium/components/commerce/core/ShoppingService.java b/components/commerce/core/android/java/src/org/chromium/components/commerce/core/ShoppingService.java index 89ce899..6df1dc12 100644 --- a/components/commerce/core/android/java/src/org/chromium/components/commerce/core/ShoppingService.java +++ b/components/commerce/core/android/java/src/org/chromium/components/commerce/core/ShoppingService.java
@@ -6,14 +6,14 @@ import androidx.annotation.VisibleForTesting; -import com.google.common.base.Optional; - import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.NativeMethods; import org.chromium.url.GURL; -/** A central hub for accessing shopping and product infomration. */ +import java.util.Optional; + +/** A central hub for accessing shopping and product information. */ @JNINamespace("commerce") public class ShoppingService { /** A data container for product info provided by the shopping service. */ @@ -167,7 +167,7 @@ boolean hasPreviousPrice, long previousAmountMicros) { Optional<Long> previousPrice; if (hasPreviousPrice) { - previousPrice = Optional.absent(); + previousPrice = Optional.empty(); } else { previousPrice = Optional.of(previousAmountMicros); }
diff --git a/components/components_strings.grd b/components/components_strings.grd index e3e64ee..21a34cf 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -329,6 +329,7 @@ <part file="soda_strings.grdp" /> <part file="ssl_errors_strings.grdp" /> <part file="subresource_filter_strings.grdp" /> + <part file="supervised_user_strings.grdp" /> <part file="sync_ui_strings.grdp" /> <part file="translate_strings.grdp" /> <part file="tab_groups_strings.grdp" />
diff --git a/components/history_clusters/core/config.cc b/components/history_clusters/core/config.cc index c7c61df..ab66bc3e 100644 --- a/components/history_clusters/core/config.cc +++ b/components/history_clusters/core/config.cc
@@ -176,6 +176,18 @@ "omnibox_history_cluster_provider_score", omnibox_history_cluster_provider_score); + omnibox_history_cluster_provider_inherit_search_match_score = + base::GetFieldTrialParamByFeatureAsBool( + internal::kOmniboxHistoryClusterProvider, + "omnibox_history_cluster_provider_inherit_search_match_score", + omnibox_history_cluster_provider_inherit_search_match_score); + + omnibox_history_cluster_provider_rank_above_searches = + base::GetFieldTrialParamByFeatureAsBool( + internal::kOmniboxHistoryClusterProvider, + "omnibox_history_cluster_provider_rank_above_searches", + omnibox_history_cluster_provider_rank_above_searches); + omnibox_history_cluster_provider_shortcuts = base::GetFieldTrialParamByFeatureAsBool( internal::kOmniboxHistoryClusterProvider, @@ -200,12 +212,6 @@ internal::kOmniboxHistoryClusterProvider, "omnibox_history_cluster_provider_on_navigation_intents", omnibox_history_cluster_provider_on_navigation_intents); - - omnibox_history_cluster_provider_free_ranking = - base::GetFieldTrialParamByFeatureAsBool( - internal::kOmniboxHistoryClusterProvider, - "omnibox_history_cluster_provider_free_ranking", - omnibox_history_cluster_provider_free_ranking); } // The `kOnDeviceClusteringKeywordFiltering` feature and child params.
diff --git a/components/history_clusters/core/config.h b/components/history_clusters/core/config.h index 69edc4e..57d9d481 100644 --- a/components/history_clusters/core/config.h +++ b/components/history_clusters/core/config.h
@@ -190,6 +190,20 @@ // aren't too many strong navigation matches. int omnibox_history_cluster_provider_score = 900; + // If enabled, will inherit the score from the matched search suggestion. This + // tries to emulate the ranking of chips, though remains slightly more + // conservative in that chips will be shown if the match query is at least the + // 8th top scored suggestion, while rows will be shown if the matched query is + // at least the 7th top scored suggestion. If enabled, + // `omnibox_history_cluster_provider_score` becomes a no-op. + bool omnibox_history_cluster_provider_inherit_search_match_score = false; + + // If enabled, ranks the suggestion row below the default suggestion, but + // above the searches. Though whether it appears or not will depend on scores. + // Otherwise, ranks the suggestion among the search group; the exact position + // will depend on scores. + bool omnibox_history_cluster_provider_rank_above_searches = false; + // Whether Journey suggestions from the `HistoryClusterProvider` can be // surfaced from the shortcuts' provider. They will be scored according to the // shortcuts' provider's scoring, which is more aggressive than the default @@ -219,10 +233,6 @@ // `omnibox_history_cluster_provider` is disabled. bool omnibox_history_cluster_provider_on_navigation_intents = false; - // If enabled, allows the suggestion row to be ranked in any position; - // otherwise, always ranked last. - bool omnibox_history_cluster_provider_free_ranking = false; - // The `kOnDeviceClusteringKeywordFiltering` feature and child params. // If enabled, adds the keywords of aliases for detected entity names to a
diff --git a/components/navigation_metrics/navigation_metrics.cc b/components/navigation_metrics/navigation_metrics.cc index 2e65b1c..3934eb3b 100644 --- a/components/navigation_metrics/navigation_metrics.cc +++ b/components/navigation_metrics/navigation_metrics.cc
@@ -20,6 +20,7 @@ #include "net/base/url_util.h" #include "url/gurl.h" #include "url/url_canon.h" +#include "url/url_features.h" namespace navigation_metrics { @@ -36,11 +37,6 @@ namespace { -// Kill switch for crbug.com/1362507. -BASE_FEATURE(kStopRecordingIDNA2008Metrics, - "StopRecordingIDNA2008Metrics", - base::FEATURE_DISABLED_BY_DEFAULT); - const char* const kSchemeNames[] = { "unknown", url::kHttpScheme, @@ -176,7 +172,7 @@ IDNA2008DeviationCharacter RecordIDNA2008Metrics( const std::u16string& hostname16) { - if (base::FeatureList::IsEnabled(kStopRecordingIDNA2008Metrics)) { + if (!url::IsRecordingIDNA2008Metrics()) { return IDNA2008DeviationCharacter::kNone; } if (hostname16.empty()) {
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc index b42a1b57..9fac07da 100644 --- a/components/omnibox/browser/autocomplete_result.cc +++ b/components/omnibox/browser/autocomplete_result.cc
@@ -25,6 +25,7 @@ #include "base/trace_event/memory_usage_estimator.h" #include "base/trace_event/typed_macros.h" #include "build/build_config.h" +#include "components/history_clusters/core/config.h" #include "components/omnibox/browser/actions/omnibox_pedal.h" #include "components/omnibox/browser/actions/omnibox_pedal_provider.h" #include "components/omnibox/browser/autocomplete_input.h" @@ -1278,12 +1279,15 @@ base::ranges::stable_sort(begin, end, {}, [](const auto& m) { if (AutocompleteMatch::IsStarterPackType(m.type)) return 0; - // Group history cluster suggestions with searches. If the - // `omnibox_history_cluster_provider_free_ranking` feature is disabled, - // they'll be pushed back to last position, and grouping here will have - // no effect. - if (m.type == AutocompleteMatchType::HISTORY_CLUSTER) - return 0; +#if !BUILDFLAG(IS_IOS) + // Group history cluster suggestions above or with searches. + if (m.type == AutocompleteMatchType::HISTORY_CLUSTER) { + return history_clusters::GetConfig() + .omnibox_history_cluster_provider_rank_above_searches + ? 0 + : 1; + } +#endif // !BUILDFLAG(IS_IOS) if (AutocompleteMatch::IsSearchType(m.type)) return 1; return 2;
diff --git a/components/omnibox/browser/history_cluster_provider.cc b/components/omnibox/browser/history_cluster_provider.cc index 8268f96..d3cfbe7 100644 --- a/components/omnibox/browser/history_cluster_provider.cc +++ b/components/omnibox/browser/history_cluster_provider.cc
@@ -17,7 +17,6 @@ #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/strings/grit/components_strings.h" -#include "third_party/omnibox_proto/groups.pb.h" #include "ui/base/l10n/l10n_util.h" HistoryClusterProvider::HistoryClusterProvider( @@ -44,18 +43,8 @@ void HistoryClusterProvider::CompleteHistoryClustersMatch( const std::string& matching_text, history::ClusterKeywordData matched_keyword_data, - AutocompleteMatch* match, - omnibox::GroupConfigMap* provider_suggestion_group_maps) { + AutocompleteMatch* match) { DCHECK(match); - DCHECK(provider_suggestion_group_maps); - - if (!history_clusters::GetConfig() - .omnibox_history_cluster_provider_free_ranking) { - match->suggestion_group_id = omnibox::GROUP_HISTORY_CLUSTER; - // Insert a corresponding omnibox::GroupConfig with default values in the - // suggestion groups map; otherwise the group ID will get dropped. - (*provider_suggestion_group_maps)[omnibox::GROUP_HISTORY_CLUSTER]; - } // It's fine to unconditionally attach this takeover action, as the action // itself checks the flag to redirect the user to either the Side Panel or @@ -145,8 +134,8 @@ OmniboxTriggeredFeatureService::Feature::kHistoryClusterSuggestion); if (!history_clusters::GetConfig() .omnibox_history_cluster_provider_counterfactual) { - matches_.push_back(CreateMatch( - search_match.contents, std::move(matched_keyword_data.value()))); + matches_.push_back( + CreateMatch(search_match, std::move(matched_keyword_data.value()))); } return true; } @@ -155,7 +144,7 @@ } AutocompleteMatch HistoryClusterProvider::CreateMatch( - std::u16string text, + const AutocompleteMatch& search_match, history::ClusterKeywordData matched_keyword_data) { AutocompleteMatch match; match.provider = this; @@ -167,7 +156,13 @@ // Ideally, relevance would depend on how many keywords matched, how // significant the keywords were, how significant their clusters were etc. match.relevance = - history_clusters::GetConfig().omnibox_history_cluster_provider_score; + history_clusters::GetConfig() + .omnibox_history_cluster_provider_inherit_search_match_score + ? search_match.relevance - 1 + : history_clusters::GetConfig() + .omnibox_history_cluster_provider_score; + + const auto& text = search_match.contents; match.destination_url = GURL(base::UTF8ToUTF16(base::StringPrintf( "chrome://history/journeys?q=%s", @@ -186,8 +181,7 @@ match.contents_class = {{0, ACMatchClassification::DIM}}; CompleteHistoryClustersMatch(base::UTF16ToUTF8(text), - std::move(matched_keyword_data), &match, - &suggestion_groups_map_); + std::move(matched_keyword_data), &match); return match; }
diff --git a/components/omnibox/browser/history_cluster_provider.h b/components/omnibox/browser/history_cluster_provider.h index 29a536e1..17fc5305 100644 --- a/components/omnibox/browser/history_cluster_provider.h +++ b/components/omnibox/browser/history_cluster_provider.h
@@ -35,8 +35,7 @@ static void CompleteHistoryClustersMatch( const std::string& matching_text, history::ClusterKeywordData matched_keyword_data, - AutocompleteMatch* match, - omnibox::GroupConfigMap* provider_suggestion_groups_map); + AutocompleteMatch* match); // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; @@ -59,7 +58,7 @@ // Creates a `AutocompleteMatch`. AutocompleteMatch CreateMatch( - std::u16string text, + const AutocompleteMatch& search_match, history::ClusterKeywordData matched_keyword_data); // The `AutocompleteInput` passed to `Start()`.
diff --git a/components/omnibox/browser/history_cluster_provider_unittest.cc b/components/omnibox/browser/history_cluster_provider_unittest.cc index 951748e..ca878e0 100644 --- a/components/omnibox/browser/history_cluster_provider_unittest.cc +++ b/components/omnibox/browser/history_cluster_provider_unittest.cc
@@ -446,25 +446,8 @@ VerifyFeatureTriggered(true); } -TEST_F(HistoryClustersProviderTest, Grouping) { - // By default, should have groups. - AutocompleteInput input; - input.set_omit_asynchronous_matches(false); - search_provider_->matches_ = {CreateMatch(u"keyword")}; - search_provider_->done_ = true; - - provider_->Start(input, false); - ASSERT_EQ(provider_->matches().size(), 1u); - EXPECT_EQ(provider_->matches()[0].suggestion_group_id, - omnibox::GROUP_HISTORY_CLUSTER); -} - -TEST_F(HistoryClustersProviderTest, Grouping_FreeRanking) { - // When `omnibox_history_cluster_provider_free_ranking` is enabled, should not - // have groups. - config_.omnibox_history_cluster_provider_free_ranking = true; - history_clusters::SetConfigForTesting(config_); - +TEST_F(HistoryClustersProviderTest, Grouping_Ranking) { + // Should not have groups. AutocompleteInput input; input.set_omit_asynchronous_matches(false); search_provider_->matches_ = {CreateMatch(u"keyword")};
diff --git a/components/omnibox/browser/shortcuts_provider.cc b/components/omnibox/browser/shortcuts_provider.cc index a9887240..566b50a0 100644 --- a/components/omnibox/browser/shortcuts_provider.cc +++ b/components/omnibox/browser/shortcuts_provider.cc
@@ -364,8 +364,7 @@ // Shortcut-generated HC matches have empty `ClusterKeywordData()`s, // because it wasn't generated via an entity match in the first place. HistoryClusterProvider::CompleteHistoryClustersMatch( - matching_string, history::ClusterKeywordData(), &match, - &suggestion_groups_map_); + matching_string, history::ClusterKeywordData(), &match); #endif // !BUILDFLAG(IS_IOS) return match;
diff --git a/components/omnibox/browser/shortcuts_provider_unittest.cc b/components/omnibox/browser/shortcuts_provider_unittest.cc index 4b45d38f..112f27f 100644 --- a/components/omnibox/browser/shortcuts_provider_unittest.cc +++ b/components/omnibox/browser/shortcuts_provider_unittest.cc
@@ -901,26 +901,14 @@ EXPECT_EQ(matches[5].relevance, matches[0].relevance); EXPECT_EQ(matches[6].relevance, matches[0].relevance); - // Expect cluster matches to have grouping. + // Expect cluster matches to not have grouping. EXPECT_EQ(matches[0].suggestion_group_id, absl::nullopt); EXPECT_EQ(matches[1].suggestion_group_id, absl::nullopt); EXPECT_EQ(matches[2].suggestion_group_id, absl::nullopt); - EXPECT_EQ(matches[3].suggestion_group_id, omnibox::GROUP_HISTORY_CLUSTER); - EXPECT_EQ(matches[4].suggestion_group_id, omnibox::GROUP_HISTORY_CLUSTER); - EXPECT_EQ(matches[5].suggestion_group_id, omnibox::GROUP_HISTORY_CLUSTER); - EXPECT_EQ(matches[6].suggestion_group_id, omnibox::GROUP_HISTORY_CLUSTER); - - // With `omnibox_history_cluster_provider_free_ranking`, should not have - // groups. - config.omnibox_history_cluster_provider_free_ranking = true; - history_clusters::SetConfigForTesting(config); - provider_->Start(input, false); - const auto matches_with_free_ranking = provider_->matches(); - ASSERT_EQ(matches_with_free_ranking.size(), matches.size()); - for (size_t i = 0; i < matches.size(); ++i) { - EXPECT_EQ(matches_with_free_ranking[i].contents, matches[i].contents); - EXPECT_EQ(matches_with_free_ranking[i].suggestion_group_id, absl::nullopt); - } + EXPECT_EQ(matches[3].suggestion_group_id, absl::nullopt); + EXPECT_EQ(matches[4].suggestion_group_id, absl::nullopt); + EXPECT_EQ(matches[5].suggestion_group_id, absl::nullopt); + EXPECT_EQ(matches[6].suggestion_group_id, absl::nullopt); // With `omnibox_history_cluster_provider_allow_default`, should be allowed // default.
diff --git a/components/omnibox/browser/zero_suggest_cache_service.cc b/components/omnibox/browser/zero_suggest_cache_service.cc index 4835e3f..7d556de 100644 --- a/components/omnibox/browser/zero_suggest_cache_service.cc +++ b/components/omnibox/browser/zero_suggest_cache_service.cc
@@ -6,6 +6,9 @@ #include "base/metrics/histogram_functions.h" #include "base/trace_event/memory_usage_estimator.h" +#include "components/omnibox/browser/autocomplete_input.h" +#include "components/omnibox/browser/autocomplete_provider_client.h" +#include "components/omnibox/browser/search_suggestion_parser.h" using CacheEntry = ZeroSuggestCacheService::CacheEntry; @@ -57,6 +60,27 @@ CacheEntry::~CacheEntry() = default; +SearchSuggestionParser::SuggestResults CacheEntry::GetSuggestResults( + const AutocompleteInput& input, + const AutocompleteProviderClient& client) const { + SearchSuggestionParser::Results results; + + auto response_data = + SearchSuggestionParser::DeserializeJsonData(response_json); + if (!response_data) { + return results.suggest_results; + } + + if (!SearchSuggestionParser::ParseSuggestResults( + *response_data, input, client.GetSchemeClassifier(), + /*default_result_relevance=*/100, /*is_keyword_result=*/false, + &results)) { + return results.suggest_results; + } + + return results.suggest_results; +} + size_t CacheEntry::EstimateMemoryUsage() const { return base::trace_event::EstimateMemoryUsage(response_json); }
diff --git a/components/omnibox/browser/zero_suggest_cache_service.h b/components/omnibox/browser/zero_suggest_cache_service.h index a8af960..812346c 100644 --- a/components/omnibox/browser/zero_suggest_cache_service.h +++ b/components/omnibox/browser/zero_suggest_cache_service.h
@@ -12,6 +12,9 @@ #include "base/observer_list_types.h" #include "build/build_config.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/omnibox/browser/autocomplete_input.h" +#include "components/omnibox/browser/autocomplete_provider_client.h" +#include "components/omnibox/browser/search_suggestion_parser.h" class ZeroSuggestCacheService : public KeyedService { public: @@ -27,6 +30,14 @@ // JSON response received from the remote Suggest service. std::string response_json; + // Parses the stored JSON response in order to extract the list of + // suggestions received from the remote Suggest service. + // For memory efficiency reasons, CacheEntry does not store the + // deserialized SuggestResults object as a data member. + SearchSuggestionParser::SuggestResults GetSuggestResults( + const AutocompleteInput& input, + const AutocompleteProviderClient& client) const; + // Estimates dynamic memory usage. // See base/trace_event/memory_usage_estimator.h for more info. size_t EstimateMemoryUsage() const;
diff --git a/components/optimization_guide/content/browser/BUILD.gn b/components/optimization_guide/content/browser/BUILD.gn index 3ea5ddf..82c0a51 100644 --- a/components/optimization_guide/content/browser/BUILD.gn +++ b/components/optimization_guide/content/browser/BUILD.gn
@@ -39,6 +39,7 @@ "//components/history/core/browser", "//components/keyed_service/core", "//components/no_state_prefetch/browser", + "//components/omnibox/browser", "//components/optimization_guide:machine_learning_tflite_buildflags", "//components/optimization_guide:optimization_guide_buildflags", "//components/optimization_guide/content/mojom:mojo_interfaces", @@ -50,6 +51,7 @@ "//services/metrics/public/cpp:metrics_cpp", "//services/metrics/public/cpp:ukm_builders", "//services/network/public/cpp", + "//third_party/omnibox_proto", ] if (build_with_tflite_lib) { public_deps += [
diff --git a/components/optimization_guide/content/browser/DEPS b/components/optimization_guide/content/browser/DEPS index e4c9a2d..9da827c4 100644 --- a/components/optimization_guide/content/browser/DEPS +++ b/components/optimization_guide/content/browser/DEPS
@@ -5,6 +5,7 @@ "+components/history/core/browser", "+components/keyed_service/core", "+components/no_state_prefetch/browser", + "+components/omnibox/browser", "+components/optimization_guide/core", "+components/optimization_guide/proto", "+components/search_engines", @@ -15,4 +16,5 @@ "+services/metrics/public", "+services/service_manager/public", "+third_party/blink/public", + "+third_party/omnibox_proto", ]
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.cc b/components/optimization_guide/content/browser/page_content_annotations_service.cc index dcb6c609..40e200b 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_service.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_service.cc
@@ -4,6 +4,9 @@ #include "components/optimization_guide/content/browser/page_content_annotations_service.h" +#include <algorithm> +#include <utility> + #include "base/barrier_closure.h" #include "base/containers/adapters.h" #include "base/metrics/histogram_functions.h" @@ -14,6 +17,8 @@ #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" #include "components/leveldb_proto/public/proto_database_provider.h" +#include "components/omnibox/browser/autocomplete_input.h" +#include "components/omnibox/browser/search_suggestion_parser.h" #include "components/optimization_guide/content/browser/page_content_annotations_validator.h" #include "components/optimization_guide/core/entity_metadata.h" #include "components/optimization_guide/core/local_page_entities_metadata_provider.h" @@ -30,6 +35,7 @@ #include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/cpp/ukm_source.h" #include "services/metrics/public/cpp/ukm_source_id.h" +#include "third_party/omnibox_proto/types.pb.h" #if BUILDFLAG(BUILD_WITH_TFLITE_LIB) #include "components/optimization_guide/content/browser/page_content_annotations_model_manager.h" @@ -111,18 +117,22 @@ } // namespace PageContentAnnotationsService::PageContentAnnotationsService( + std::unique_ptr<AutocompleteProviderClient> autocomplete_provider_client, const std::string& application_locale, OptimizationGuideModelProvider* optimization_guide_model_provider, history::HistoryService* history_service, TemplateURLService* template_url_service, + ZeroSuggestCacheService* zero_suggest_cache_service, leveldb_proto::ProtoDatabaseProvider* database_provider, const base::FilePath& database_dir, OptimizationGuideLogger* optimization_guide_logger, scoped_refptr<base::SequencedTaskRunner> background_task_runner) - : min_page_category_score_to_persist_( + : autocomplete_provider_client_(std::move(autocomplete_provider_client)), + min_page_category_score_to_persist_( features::GetMinimumPageCategoryScoreToPersist()), history_service_(history_service), template_url_service_(template_url_service), + zero_suggest_cache_service_(zero_suggest_cache_service), last_annotated_history_visits_( features::MaxContentAnnotationRequestsCached()), annotated_text_cache_(features::MaxVisitAnnotationCacheSize()), @@ -130,6 +140,10 @@ DCHECK(optimization_guide_model_provider); DCHECK(history_service_); history_service_observation_.Observe(history_service_); + if (zero_suggest_cache_service_) { + zero_suggest_cache_service_observation_.Observe( + zero_suggest_cache_service_); + } #if BUILDFLAG(BUILD_WITH_TFLITE_LIB) model_manager_ = std::make_unique<PageContentAnnotationsModelManager>( optimization_guide_model_provider); @@ -377,6 +391,10 @@ void PageContentAnnotationsService::ExtractRelatedSearches( const HistoryVisit& visit, content::WebContents* web_contents) { + if (ShouldExtractRelatedSearchesFromZPSCache()) { + return; + } + search_result_extractor_client_.RequestData( web_contents, {continuous_search::mojom::ResultType::kRelatedSearches}, base::BindOnce(&PageContentAnnotationsService::OnRelatedSearchesExtracted, @@ -428,6 +446,64 @@ } #endif +bool PageContentAnnotationsService::ShouldExtractRelatedSearchesFromZPSCache() { + return base::FeatureList::IsEnabled( + features::kExtractRelatedSearchesFromPrefetchedZPSResponse) && + autocomplete_provider_client_ && zero_suggest_cache_service_; +} + +void PageContentAnnotationsService::OnZeroSuggestResponseUpdated( + const std::string& page_url, + const ZeroSuggestCacheService::CacheEntry& response) { + if (!ShouldExtractRelatedSearchesFromZPSCache()) { + return; + } + + if (page_url.empty() || !google_util::IsGoogleSearchUrl(GURL(page_url))) { + return; + } + + history_service_->QueryURL( + GURL(page_url), /*want_visits=*/true, + base::BindOnce(&PageContentAnnotationsService:: + ExtractRelatedSearchesFromZeroSuggestResponse, + weak_ptr_factory_.GetWeakPtr(), response), + &history_service_task_tracker_); +} + +void PageContentAnnotationsService:: + ExtractRelatedSearchesFromZeroSuggestResponse( + const ZeroSuggestCacheService::CacheEntry& response, + history::QueryURLResult url_result) { + if (url_result.visits.empty()) { + return; + } + + AutocompleteInput input(u"", metrics::OmniboxEventProto::JOURNEYS, + autocomplete_provider_client_->GetSchemeClassifier()); + auto suggest_results = + response.GetSuggestResults(input, *autocomplete_provider_client_); + + std::vector<std::string> related_searches; + for (const auto& result : suggest_results) { + const auto subtypes = result.subtypes(); + // Suggestions with HIVEMIND subtype are considered "related searches". + auto it = std::find(subtypes.begin(), subtypes.end(), + omnibox::SuggestSubtype::SUBTYPE_HIVEMIND); + if (it != subtypes.end()) { + related_searches.push_back(base::UTF16ToUTF8( + base::CollapseWhitespace(result.suggestion(), true))); + } + } + + if (related_searches.empty()) { + return; + } + + auto visit_id = url_result.visits.front().visit_id; + history_service_->AddRelatedSearchesForVisit(related_searches, visit_id); +} + void PageContentAnnotationsService::OnRelatedSearchesExtracted( const HistoryVisit& visit, continuous_search::SearchResultExtractorClientStatus status,
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.h b/components/optimization_guide/content/browser/page_content_annotations_service.h index c4e97c37..b25fb62e 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_service.h +++ b/components/optimization_guide/content/browser/page_content_annotations_service.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_CONTENT_ANNOTATIONS_SERVICE_H_ #define COMPONENTS_OPTIMIZATION_GUIDE_CONTENT_BROWSER_PAGE_CONTENT_ANNOTATIONS_SERVICE_H_ +#include <memory> #include <string> #include <vector> @@ -25,6 +26,8 @@ #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/url_row.h" #include "components/keyed_service/core/keyed_service.h" +#include "components/omnibox/browser/autocomplete_provider_client.h" +#include "components/omnibox/browser/zero_suggest_cache_service.h" #include "components/optimization_guide/content/browser/page_content_annotator.h" #include "components/optimization_guide/core/entity_metadata_provider.h" #include "components/optimization_guide/core/model_info.h" @@ -96,13 +99,16 @@ // A KeyedService that annotates page content. class PageContentAnnotationsService : public KeyedService, public EntityMetadataProvider, - public history::HistoryServiceObserver { + public history::HistoryServiceObserver, + public ZeroSuggestCacheService::Observer { public: PageContentAnnotationsService( + std::unique_ptr<AutocompleteProviderClient> autocomplete_provider_client, const std::string& application_locale, OptimizationGuideModelProvider* optimization_guide_model_provider, history::HistoryService* history_service, TemplateURLService* template_url_service, + ZeroSuggestCacheService* zero_suggest_cache_service, leveldb_proto::ProtoDatabaseProvider* database_provider, const base::FilePath& database_dir, OptimizationGuideLogger* optimization_guide_logger, @@ -146,6 +152,20 @@ // test_page_content_annotator.h for an implementation designed for testing. void OverridePageContentAnnotatorForTesting(PageContentAnnotator* annotator); + // Specifies whether PageContentAnnotationsService should extract "related + // searches" data from the ZPS response cache. + bool ShouldExtractRelatedSearchesFromZPSCache(); + + // ZeroSuggestCacheService::Observer: + void OnZeroSuggestResponseUpdated( + const std::string& page_url, + const ZeroSuggestCacheService::CacheEntry& response) override; + + // Callback used to extract "related searches" data from cached ZPS responses. + void ExtractRelatedSearchesFromZeroSuggestResponse( + const ZeroSuggestCacheService::CacheEntry& response, + history::QueryURLResult url_result); + OptimizationGuideLogger* optimization_guide_logger() const { return optimization_guide_logger_; } @@ -258,6 +278,9 @@ PageContentAnnotationsType annotation_type, history::QueryURLResult url_result); + // Provider client instance used when parsing cached ZPS response data. + std::unique_ptr<AutocompleteProviderClient> autocomplete_provider_client_; + // The minimum score that an allowlisted page category must have for it to be // persisted. const int min_page_category_score_to_persist_; @@ -280,6 +303,12 @@ history_service_observation_{this}; // The task tracker to keep track of tasks to query |history_service|. base::CancelableTaskTracker history_service_task_tracker_; + // The zero suggest cache service used to fetch cached ZPS response data. + const raw_ptr<ZeroSuggestCacheService> zero_suggest_cache_service_; + // The scoped observation to the ZeroSuggestCacheService. + base::ScopedObservation<ZeroSuggestCacheService, + PageContentAnnotationsService> + zero_suggest_cache_service_observation_{this}; // The client of continuous_search::mojom::SearchResultExtractor interface // used for extracting data from the main frame of Google SRP |web_contents|. continuous_search::SearchResultExtractorClient
diff --git a/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc b/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc index 2cc0ae5..1af63838 100644 --- a/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc +++ b/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc
@@ -83,11 +83,13 @@ explicit FakePageContentAnnotationsService( OptimizationGuideModelProvider* optimization_guide_model_provider, history::HistoryService* history_service) - : PageContentAnnotationsService("en-US", + : PageContentAnnotationsService(nullptr, + "en-US", optimization_guide_model_provider, history_service, nullptr, nullptr, + nullptr, base::FilePath(), nullptr, nullptr) {}
diff --git a/components/optimization_guide/core/prediction_model_store.cc b/components/optimization_guide/core/prediction_model_store.cc index 69f548a..57506cd 100644 --- a/components/optimization_guide/core/prediction_model_store.cc +++ b/components/optimization_guide/core/prediction_model_store.cc
@@ -4,9 +4,11 @@ #include "components/optimization_guide/core/prediction_model_store.h" +#include "base/files/file_enumerator.h" #include "base/files/file_util.h" #include "base/guid.h" #include "base/memory/ptr_util.h" +#include "base/metrics/histogram_functions.h" #include "base/rand_util.h" #include "base/task/thread_pool.h" #include "components/optimization_guide/core/model_store_metadata_entry.h" @@ -19,6 +21,8 @@ namespace { +constexpr size_t kBytesPerMegabyte = 1024 * 1024; + // Returns the model info parsed from |model_info_path|. absl::optional<proto::ModelInfo> ParseModelInfoFromFile( const base::FilePath& model_info_path) { @@ -55,6 +59,50 @@ return model_file_paths; } +// Parses the OptimizationTarget from the string. +proto::OptimizationTarget ParseOptimizationTargetFromString( + const std::string& optimization_target_str) { + int optimization_target; + if (!base::StringToInt(optimization_target_str, &optimization_target)) { + return proto::OPTIMIZATION_TARGET_UNKNOWN; + } + if (!proto::OptimizationTarget_IsValid(optimization_target)) { + return proto::OPTIMIZATION_TARGET_UNKNOWN; + } + return static_cast<proto::OptimizationTarget>(optimization_target); +} + +void RecordModelStorageMetrics(const base::FilePath& base_store_dir) { + base::FileEnumerator enumerator(base_store_dir, false, + base::FileEnumerator::DIRECTORIES); + for (base::FilePath optimization_target_dir = enumerator.Next(); + !optimization_target_dir.empty(); + optimization_target_dir = enumerator.Next()) { + proto::OptimizationTarget optimization_target = + ParseOptimizationTargetFromString( + optimization_target_dir.BaseName().AsUTF8Unsafe()); + if (optimization_target == proto::OPTIMIZATION_TARGET_UNKNOWN) { + continue; + } + size_t total_models = 0; + base::FileEnumerator models_enumerator(optimization_target_dir, false, + base::FileEnumerator::DIRECTORIES); + for (base::FilePath model_dir = models_enumerator.Next(); + !model_dir.empty(); model_dir = models_enumerator.Next()) { + total_models++; + } + base::UmaHistogramCounts100( + "OptimizationGuide.PredictionModelStore.ModelCount." + + GetStringNameForOptimizationTarget(optimization_target), + total_models); + base::UmaHistogramMemoryMB( + "OptimizationGuide.PredictionModelStore.TotalDirectorySize." + + GetStringNameForOptimizationTarget(optimization_target), + base::ComputeDirectorySize(optimization_target_dir) / + kBytesPerMegabyte); + } +} + } // namespace // static @@ -83,6 +131,9 @@ local_state_ = local_state; base_store_dir_ = base_store_dir; + + background_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&RecordModelStorageMetrics, base_store_dir_)); } // static
diff --git a/components/optimization_guide/core/prediction_model_store_unittest.cc b/components/optimization_guide/core/prediction_model_store_unittest.cc index 227847fe..b6df191d 100644 --- a/components/optimization_guide/core/prediction_model_store_unittest.cc +++ b/components/optimization_guide/core/prediction_model_store_unittest.cc
@@ -9,6 +9,7 @@ #include "base/guid.h" #include "base/rand_util.h" #include "base/task/thread_pool.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "components/optimization_guide/core/model_store_metadata_entry.h" @@ -244,4 +245,52 @@ EXPECT_TRUE(metadata_entry->GetKeepBeyondValidDuration()); } +TEST_F(PredictionModelStoreTest, ModelStorageMetrics) { + RunUntilIdle(); + base::HistogramTester histogram_tester; + + auto model_cache_key = CreateModelCacheKey(kTestLocaleFoo); + auto model_detail = + CreateTestModelFiles(kTestOptimizationTargetFoo, model_cache_key, {}); + prediction_model_store_->UpdateModel( + kTestOptimizationTargetFoo, model_cache_key, model_detail.model_info, + model_detail.base_model_dir, base::DoNothing()); + RunUntilIdle(); + model_detail = + CreateTestModelFiles(kTestOptimizationTargetBar, model_cache_key, {}); + prediction_model_store_->UpdateModel( + kTestOptimizationTargetBar, model_cache_key, model_detail.model_info, + model_detail.base_model_dir, base::DoNothing()); + RunUntilIdle(); + + // Recreate the model store, and that should record model storage metrics. + prediction_model_store_ = + PredictionModelStore::CreatePredictionModelStoreForTesting( + local_state_prefs_.get(), temp_models_dir_.GetPath()); + RunUntilIdle(); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PredictionModelStore.ModelCount.PainfulPageLoad", 1, + 1); + histogram_tester.ExpectTotalCount( + "OptimizationGuide.PredictionModelStore.TotalDirectorySize." + "PainfulPageLoad", + 1); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PredictionModelStore.ModelCount.ModelValidation", 1, + 1); + histogram_tester.ExpectTotalCount( + "OptimizationGuide.PredictionModelStore.TotalDirectorySize." + "ModelValidation", + 1); + EXPECT_EQ(2U, histogram_tester + .GetTotalCountsForPrefix( + "OptimizationGuide.PredictionModelStore.ModelCount.") + .size()); + EXPECT_EQ( + 2U, histogram_tester + .GetTotalCountsForPrefix( + "OptimizationGuide.PredictionModelStore.TotalDirectorySize.") + .size()); +} + } // namespace optimization_guide
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerSwipeRefreshHandler.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerSwipeRefreshHandler.java index b2279f9..ff079046 100644 --- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerSwipeRefreshHandler.java +++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/PlayerSwipeRefreshHandler.java
@@ -67,8 +67,7 @@ @Override public boolean start() { - // TODO(1335416): Update this to |true| if experiment is successful - return mSwipeRefreshLayout.start(false); + return mSwipeRefreshLayout.start(); } @Override
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn index 2a80cbf..a5e43ac 100644 --- a/components/resources/BUILD.gn +++ b/components/resources/BUILD.gn
@@ -4,6 +4,7 @@ import("//build/config/android/config.gni") import("//components/safe_browsing/buildflags.gni") +import("//components/supervised_user/buildflags.gni") import("//printing/buildflags/buildflags.gni") import("//tools/grit/grit_rule.gni") @@ -42,6 +43,7 @@ defines = [ "enable_printing=$enable_printing", "enable_print_preview=$enable_print_preview", + "enable_supervised_users=$enable_supervised_users", "safe_browsing_mode=$safe_browsing_mode", "is_fuchsia=$is_fuchsia", ]
diff --git a/components/resources/components_resources.grd b/components/resources/components_resources.grd index 03e7665..0e9f7458 100644 --- a/components/resources/components_resources.grd +++ b/components/resources/components_resources.grd
@@ -30,6 +30,9 @@ <if expr="is_android"> <part file="android_system_error_page_resources.grdp" /> </if> + <if expr="enable_supervised_users"> + <part file="supervised_user_resources.grdp" /> + </if> </includes> </release> </grit>
diff --git a/components/resources/supervised_user_resources.grdp b/components/resources/supervised_user_resources.grdp new file mode 100644 index 0000000..cc8c8aa --- /dev/null +++ b/components/resources/supervised_user_resources.grdp
@@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <include name="IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_HTML" file="../supervised_user/core/browser/resources/supervised_user_block_interstitial.html" flattenhtml="true" type="BINDATA" compress="brotli" /> + <include name="IDR_SUPERVISED_USER_BLOCK_INTERSTITIAL_V2_HTML" file="../supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.html" flattenhtml="true" type="BINDATA" compress="brotli" /> + <include name="IDR_SUPERVISED_USER_ICON" file="../supervised_user/core/browser/resources/supervised_user_icon.png" type="BINDATA" /> +</grit-part>
diff --git a/components/segmentation_platform/internal/execution/model_executor_impl.cc b/components/segmentation_platform/internal/execution/model_executor_impl.cc index d8ee45e..1a4e8d9 100644 --- a/components/segmentation_platform/internal/execution/model_executor_impl.cc +++ b/components/segmentation_platform/internal/execution/model_executor_impl.cc
@@ -30,8 +30,8 @@ const ModelExecutorImpl::ExecutionState& state); ~ModelExecutionTraceEvent(); - const raw_ref<const ModelExecutorImpl::ExecutionState, DanglingUntriaged> - state; + // Which track to add this trace event to. + perfetto::Track track; }; struct ModelExecutorImpl::ExecutionState { @@ -71,14 +71,13 @@ ModelExecutorImpl::ModelExecutionTraceEvent::ModelExecutionTraceEvent( const char* event_name, const ModelExecutorImpl::ExecutionState& state) - : state(state) { + : track(perfetto::Track::FromPointer(&state)) { TRACE_EVENT_BEGIN("segmentation_platform", perfetto::StaticString(event_name), - perfetto::Track::FromPointer(&state)); + track); } ModelExecutorImpl::ModelExecutionTraceEvent::~ModelExecutionTraceEvent() { - TRACE_EVENT_END("segmentation_platform", - perfetto::Track::FromPointer(&*state)); + TRACE_EVENT_END("segmentation_platform", track); } ModelExecutorImpl::ModelExecutorImpl( @@ -109,7 +108,7 @@ *state); if (!state->model_provider || !state->model_provider->ModelAvailable()) { - RunModelExecutionCallback(std::move(state), + RunModelExecutionCallback(*state, std::move(state->callback), std::make_unique<ModelExecutionResult>( ModelExecutionStatus::kSkippedModelNotReady)); return; @@ -119,8 +118,9 @@ if (metadata_utils::ValidateSegmentInfo(segment_info) != metadata_utils::ValidationResult::kValidationSuccess) { RunModelExecutionCallback( - std::move(state), std::make_unique<ModelExecutionResult>( - ModelExecutionStatus::kSkippedInvalidMetadata)); + *state, std::move(state->callback), + std::make_unique<ModelExecutionResult>( + ModelExecutionStatus::kSkippedInvalidMetadata)); return; } @@ -141,8 +141,9 @@ if (error) { // Validation error occurred on model's metadata. RunModelExecutionCallback( - std::move(state), std::make_unique<ModelExecutionResult>( - ModelExecutionStatus::kSkippedInvalidMetadata)); + *state, std::move(state->callback), + std::make_unique<ModelExecutionResult>( + ModelExecutionStatus::kSkippedInvalidMetadata)); return; } state->input_tensor.insert(state->input_tensor.end(), input_tensor.begin(), @@ -205,28 +206,29 @@ } } ModelProvider::Request input_tensor = state->input_tensor; - RunModelExecutionCallback(std::move(state), + RunModelExecutionCallback(*state, std::move(state->callback), std::make_unique<ModelExecutionResult>( std::move(input_tensor), *result)); } else { VLOG(1) << "Segmentation model returned no result for segment " << proto::SegmentId_Name(state->segment_info.segment_id()); - RunModelExecutionCallback(std::move(state), + RunModelExecutionCallback(*state, std::move(state->callback), std::make_unique<ModelExecutionResult>( ModelExecutionStatus::kExecutionError)); } } void ModelExecutorImpl::RunModelExecutionCallback( - std::unique_ptr<ExecutionState> state, + const ExecutionState& state, + ModelExecutionCallback callback, std::unique_ptr<ModelExecutionResult> result) { stats::RecordModelExecutionDurationTotal( - state->segment_info.segment_id(), result->status, - clock_->Now() - state->total_execution_start_time); - stats::RecordModelExecutionStatus(state->segment_info.segment_id(), - state->record_metrics_for_default, + state.segment_info.segment_id(), result->status, + clock_->Now() - state.total_execution_start_time); + stats::RecordModelExecutionStatus(state.segment_info.segment_id(), + state.record_metrics_for_default, result->status); - std::move(state->callback).Run(std::move(result)); + std::move(callback).Run(std::move(result)); } } // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/execution/model_executor_impl.h b/components/segmentation_platform/internal/execution/model_executor_impl.h index 8417f59f..069b778a 100644 --- a/components/segmentation_platform/internal/execution/model_executor_impl.h +++ b/components/segmentation_platform/internal/execution/model_executor_impl.h
@@ -67,8 +67,11 @@ const absl::optional<ModelProvider::Response>& result); // Helper function for synchronously invoking the callback with the given - // result and status. - void RunModelExecutionCallback(std::unique_ptr<ExecutionState> state, + // result and status. Before invoking this, it is required to move the + // ExecutionState::callback out as a separate parameter, e.g.: + // `RunModelExecutionCallback(*state, std::move(state->callback), ...)`. + void RunModelExecutionCallback(const ExecutionState& state, + ModelExecutionCallback callback, std::unique_ptr<ModelExecutionResult> result); const raw_ptr<base::Clock> clock_;
diff --git a/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc b/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc index 609c2ee7..6633e6b 100644 --- a/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc +++ b/components/segmentation_platform/internal/execution/model_executor_impl_unittest.cc
@@ -34,6 +34,7 @@ #include "components/segmentation_platform/public/proto/types.pb.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" using ::base::test::RunOnceCallback; using segmentation_platform::processing::FeatureListQueryProcessor; @@ -54,6 +55,10 @@ ~ModelExecutorTest() override = default; void SetUp() override { + // TODO(khokhlov): Replace with a test environment for tracing after the + // SDK migration + perfetto::internal::TrackRegistry::InitializeInstance(); + signal_database_ = std::make_unique<MockSignalDatabase>(); clock_.SetNow(base::Time::Now()); }
diff --git a/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc b/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc index 70f40ad2..ac5d814 100644 --- a/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc +++ b/components/segmentation_platform/internal/segmentation_platform_service_impl_unittest.cc
@@ -30,6 +30,7 @@ #include "components/ukm/test_ukm_recorder.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" using base::test::RunOnceCallback; using ::testing::_; @@ -83,6 +84,10 @@ base::SetRecordActionTaskRunner( task_environment_.GetMainThreadTaskRunner()); + // TODO(khokhlov): Replace with a test environment for tracing after the + // SDK migration + perfetto::internal::TrackRegistry::InitializeInstance(); + // Setup model provider data for default model for supporting on demand // execution. model_provider_data_.segments_supporting_default_model = {
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc b/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc index f790814b..1ffd645 100644 --- a/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc +++ b/components/segmentation_platform/internal/selection/segment_result_provider_unittest.cc
@@ -24,6 +24,7 @@ #include "components/segmentation_platform/public/segmentation_platform_service.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/perfetto/include/perfetto/tracing/track.h" namespace segmentation_platform { namespace { @@ -81,6 +82,10 @@ ~SegmentResultProviderTest() override = default; void SetUp() override { + // TODO(khokhlov): Replace with a test environment for tracing after the + // SDK migration + perfetto::internal::TrackRegistry::InitializeInstance(); + default_manager_ = std::make_unique<DefaultModelManager>( &provider_factory_, std::vector<SegmentId>({kTestSegment, kTestSegment2}));
diff --git a/components/supervised_user/COMMON_METADATA b/components/supervised_user/COMMON_METADATA new file mode 100644 index 0000000..b2bd8d8 --- /dev/null +++ b/components/supervised_user/COMMON_METADATA
@@ -0,0 +1,5 @@ +# Chrome Kids team +monorail { + component: "FamilyExperiences > Browser" +} +team_email: "chrome-kids-eng@google.com"
diff --git a/components/supervised_user/DEPS b/components/supervised_user/DEPS new file mode 100644 index 0000000..d3410bb --- /dev/null +++ b/components/supervised_user/DEPS
@@ -0,0 +1,6 @@ +include_rules = [ + "+components/grit", + "+components/strings/grit", + "+components/signin", + "+ui/base", +]
diff --git a/components/supervised_user/OWNERS b/components/supervised_user/OWNERS new file mode 100644 index 0000000..a8ae8ed --- /dev/null +++ b/components/supervised_user/OWNERS
@@ -0,0 +1,19 @@ +# Note: Unless you want a specific reviewer's expertise, please send CLs to +# chrome-family-kids-reviews@google.com rather than to specific individuals. +# +# These CLs will be automatically reassigned to a reviewer within +# about 5 minutes. This approach helps our team to load-balance incoming +# reviews. Googlers can read more about this at go/gwsq-gerrit. + +# ChromeOS +agawronska@chromium.org +danan@chromium.org +llin@chromium.org + +# Chrome Browser +fernandex@chromium.org +ljjlee@google.com +tju@google.com + +# Previous owner, feel free to add for any questions or historical context: +# treib@chromium.org
diff --git a/components/supervised_user/README.md b/components/supervised_user/README.md new file mode 100644 index 0000000..1fe7bcb8 --- /dev/null +++ b/components/supervised_user/README.md
@@ -0,0 +1,10 @@ +Supervised User is a multiprocess [layered +component](https://sites.google.com/a/chromium.org/dev/developers/design-documents/layered-components-design) that supports cross-platform access to services and +features that target supervised users in Chrome, including metrics +collection, application of parental controls, and the enforcement of browser +protections. + +It has the following structure: +- [`core/`](https://source.chromium.org/chromium/chromium/src/+/main:components/supervised_user/core): Code shared by `content/` and `ios/`. + - [`browser/`](https://source.chromium.org/chromium/chromium/src/+/main:components/supervised_user/core/browser): Browser process code. + - [`common/`](https://source.chromium.org/chromium/chromium/src/+/main:components/supervised_user/core/common): Code shared by the browser and the renderer.
diff --git a/components/supervised_user/buildflags.gni b/components/supervised_user/buildflags.gni new file mode 100644 index 0000000..d672775 --- /dev/null +++ b/components/supervised_user/buildflags.gni
@@ -0,0 +1,9 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +declare_args() { + # Enables supervision for Family Link users. + # Supervision is only supported on Chrome OS and Android. + enable_supervised_users = is_chromeos || is_android +}
diff --git a/components/supervised_user/core/browser/BUILD.gn b/components/supervised_user/core/browser/BUILD.gn new file mode 100644 index 0000000..1fbd454 --- /dev/null +++ b/components/supervised_user/core/browser/BUILD.gn
@@ -0,0 +1,36 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +static_library("browser") { + sources = [ + "supervised_user_error_page.cc", + "supervised_user_error_page.h", + ] + + deps = [ + "//base", + "//components/resources:components_resources", + "//components/signin/public/base", + "//components/strings:components_strings_grit", + "//components/supervised_user/core/common", + "//ui/base", + "//url", + ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "supervised_user_error_page_unittest.cc" ] + deps = [ + ":browser", + "//base", + "//base/test:test_support", + "//components/resources:components_resources", + "//components/strings:components_strings_grit", + "//components/supervised_user/core/common", + "//testing/gmock", + "//testing/gtest", + "//ui/base", + ] +}
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/OWNERS b/components/supervised_user/core/browser/resources/OWNERS similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/OWNERS rename to components/supervised_user/core/browser/resources/OWNERS
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/default_100_percent/logo_avatar_circle_blue_color.png b/components/supervised_user/core/browser/resources/default_100_percent/logo_avatar_circle_blue_color.png similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/default_100_percent/logo_avatar_circle_blue_color.png rename to components/supervised_user/core/browser/resources/default_100_percent/logo_avatar_circle_blue_color.png Binary files differ
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/default_200_percent/logo_avatar_circle_blue_color.png b/components/supervised_user/core/browser/resources/default_200_percent/logo_avatar_circle_blue_color.png similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/default_200_percent/logo_avatar_circle_blue_color.png rename to components/supervised_user/core/browser/resources/default_200_percent/logo_avatar_circle_blue_color.png Binary files differ
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/error_page_illustration_dark_theme.svg b/components/supervised_user/core/browser/resources/error_page_illustration_dark_theme.svg similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/error_page_illustration_dark_theme.svg rename to components/supervised_user/core/browser/resources/error_page_illustration_dark_theme.svg
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/error_page_illustration_light_theme.svg b/components/supervised_user/core/browser/resources/error_page_illustration_light_theme.svg similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/error_page_illustration_light_theme.svg rename to components/supervised_user/core/browser/resources/error_page_illustration_light_theme.svg
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.css b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial.css similarity index 97% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.css rename to components/supervised_user/core/browser/resources/supervised_user_block_interstitial.css index ae76a42..4c308b9a 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.css +++ b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial.css
@@ -106,7 +106,7 @@ } #family-link-kite { - content: -webkit-image-set(url(../../resources/supervised_user_icon.png) 1x); + content: -webkit-image-set(url(../resources/supervised_user_icon.png) 1x); height: 72px; width: 72px; }
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.html b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial.html similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.html rename to components/supervised_user/core/browser/resources/supervised_user_block_interstitial.html
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial.js similarity index 98% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js rename to components/supervised_user/core/browser/resources/supervised_user_block_interstitial.js index 64bcdf9..13b92ee 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial.js +++ b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial.js
@@ -124,7 +124,6 @@ * frame. */ function setRequestStatus(isSuccessful, isMainFrame) { - console.log('setRequestStatus(' + isSuccessful + ')'); requestCreated(isSuccessful, isMainFrame); }
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.css b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.css similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.css rename to components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.css
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.html b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.html similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.html rename to components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.html
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.js b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.js similarity index 98% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.js rename to components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.js index 2d3cdfb..5d8c416 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/resources/supervised_user_block_interstitial_v2.js +++ b/components/supervised_user/core/browser/resources/supervised_user_block_interstitial_v2.js
@@ -140,7 +140,6 @@ * frame. */ function setRequestStatus(isSuccessful, isMainFrame) { - console.log('setRequestStatus(' + isSuccessful + ')'); requestCreated(isSuccessful, isMainFrame); }
diff --git a/chrome/browser/supervised_user/resources/supervised_user_icon.png b/components/supervised_user/core/browser/resources/supervised_user_icon.png similarity index 100% rename from chrome/browser/supervised_user/resources/supervised_user_icon.png rename to components/supervised_user/core/browser/resources/supervised_user_icon.png Binary files differ
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/waiting_for_approval_dark_theme.svg b/components/supervised_user/core/browser/resources/waiting_for_approval_dark_theme.svg similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/waiting_for_approval_dark_theme.svg rename to components/supervised_user/core/browser/resources/waiting_for_approval_dark_theme.svg
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/resources/waiting_for_approval_light_theme.svg b/components/supervised_user/core/browser/resources/waiting_for_approval_light_theme.svg similarity index 100% rename from chrome/browser/supervised_user/supervised_user_error_page/resources/waiting_for_approval_light_theme.svg rename to components/supervised_user/core/browser/resources/waiting_for_approval_light_theme.svg
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc b/components/supervised_user/core/browser/supervised_user_error_page.cc similarity index 96% rename from chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc rename to components/supervised_user/core/browser/supervised_user_error_page.cc index 68b6ab9..54482757 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.cc +++ b/components/supervised_user/core/browser/supervised_user_error_page.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include <string> @@ -11,10 +11,10 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" -#include "chrome/grit/browser_resources.h" -#include "chrome/grit/generated_resources.h" +#include "components/grit/components_resources.h" #include "components/signin/public/base/avatar_icon_util.h" +#include "components/strings/grit/components_strings.h" +#include "components/supervised_user/core/common/features.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h"
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h b/components/supervised_user/core/browser/supervised_user_error_page.h similarity index 78% rename from chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h rename to components/supervised_user/core/browser/supervised_user_error_page.h index d236aa1..88b8128 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h +++ b/components/supervised_user/core/browser/supervised_user_error_page.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_ERROR_PAGE_SUPERVISED_USER_ERROR_PAGE_H_ -#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_ERROR_PAGE_SUPERVISED_USER_ERROR_PAGE_H_ +#ifndef COMPONENTS_SUPERVISED_USER_CORE_BROWSER_SUPERVISED_USER_ERROR_PAGE_H_ +#define COMPONENTS_SUPERVISED_USER_CORE_BROWSER_SUPERVISED_USER_ERROR_PAGE_H_ #include <string> @@ -36,4 +36,4 @@ } // namespace supervised_user_error_page -#endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_ERROR_PAGE_SUPERVISED_USER_ERROR_PAGE_H_ +#endif // COMPONENTS_SUPERVISED_USER_CORE_BROWSER_SUPERVISED_USER_ERROR_PAGE_H_
diff --git a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page_unittest.cc b/components/supervised_user/core/browser/supervised_user_error_page_unittest.cc similarity index 97% rename from chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page_unittest.cc rename to components/supervised_user/core/browser/supervised_user_error_page_unittest.cc index a534019..43655ed 100644 --- a/chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page_unittest.cc +++ b/components/supervised_user/core/browser/supervised_user_error_page_unittest.cc
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/supervised_user/supervised_user_error_page/supervised_user_error_page.h" +#include "components/supervised_user/core/browser/supervised_user_error_page.h" #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" -#include "chrome/grit/browser_resources.h" -#include "chrome/grit/generated_resources.h" +#include "components/grit/components_resources.h" +#include "components/strings/grit/components_strings.h" +#include "components/supervised_user/core/common/features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest-param-test.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/supervised_user/core/common/BUILD.gn b/components/supervised_user/core/common/BUILD.gn new file mode 100644 index 0000000..eefeda45 --- /dev/null +++ b/components/supervised_user/core/common/BUILD.gn
@@ -0,0 +1,22 @@ +# Copyright 2022 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +static_library("common") { + sources = [ + "features.cc", + "features.h", + ] + deps = [ "//base" ] +} + +source_set("unit_tests") { + testonly = true + sources = [ "features_unittest.cc" ] + deps = [ + ":common", + "//base", + "//base/test:test_support", + "//testing/gtest", + ] +}
diff --git a/chrome/browser/supervised_user/supervised_user_features/supervised_user_features.cc b/components/supervised_user/core/common/features.cc similarity index 96% rename from chrome/browser/supervised_user/supervised_user_features/supervised_user_features.cc rename to components/supervised_user/core/common/features.cc index 1c165a8..27b4247 100644 --- a/chrome/browser/supervised_user/supervised_user_features/supervised_user_features.cc +++ b/components/supervised_user/core/common/features.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" +#include "components/supervised_user/core/common/features.h" #include <string> #include "base/check.h"
diff --git a/chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h b/components/supervised_user/core/common/features.h similarity index 80% rename from chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h rename to components/supervised_user/core/common/features.h index f4ccdce..b3b11a1 100644 --- a/chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h +++ b/components/supervised_user/core/common/features.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_FEATURES_SUPERVISED_USER_FEATURES_H_ -#define CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_FEATURES_SUPERVISED_USER_FEATURES_H_ +#ifndef COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_H_ +#define COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_H_ #include "base/feature_list.h" @@ -37,4 +37,4 @@ } // namespace supervised_users -#endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_FEATURES_SUPERVISED_USER_FEATURES_H_ +#endif // COMPONENTS_SUPERVISED_USER_CORE_COMMON_FEATURES_H_
diff --git a/chrome/browser/supervised_user/supervised_user_features/supervised_user_features_unittest.cc b/components/supervised_user/core/common/features_unittest.cc similarity index 82% rename from chrome/browser/supervised_user/supervised_user_features/supervised_user_features_unittest.cc rename to components/supervised_user/core/common/features_unittest.cc index 699b2b6..3777b187 100644 --- a/chrome/browser/supervised_user/supervised_user_features/supervised_user_features_unittest.cc +++ b/components/supervised_user/core/common/features_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/supervised_user/supervised_user_features/supervised_user_features.h" +#include "components/supervised_user/core/common/features.h" #include "base/dcheck_is_on.h" #include "base/feature_list.h" @@ -12,20 +12,19 @@ namespace supervised_users { // Tests supervised user features configurations. -class SupervisedUserFeaturesTest : public testing::Test { +class FeaturesTest : public testing::Test { protected: - SupervisedUserFeaturesTest() = default; - SupervisedUserFeaturesTest(const SupervisedUserFeaturesTest&) = delete; - SupervisedUserFeaturesTest& operator=(const SupervisedUserFeaturesTest&) = - delete; - ~SupervisedUserFeaturesTest() override = default; + FeaturesTest() = default; + FeaturesTest(const FeaturesTest&) = delete; + FeaturesTest& operator=(const FeaturesTest&) = delete; + ~FeaturesTest() override = default; base::test::ScopedFeatureList scoped_feature_list_; }; // Tests `kWebFilterInterstitialRefresh` and `kLocalWebApproval`features // configuration. -using LocalWebApprovalsFeatureTest = SupervisedUserFeaturesTest; +using LocalWebApprovalsFeatureTest = FeaturesTest; TEST_F(LocalWebApprovalsFeatureTest, InterstitialRefreshDisabledAndLocalApprovalsDisabled) {
diff --git a/chrome/app/supervised_user_error_page_strings.grdp b/components/supervised_user_strings.grdp similarity index 100% rename from chrome/app/supervised_user_error_page_strings.grdp rename to components/supervised_user_strings.grdp
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BACK_BUTTON.png.sha1 b/components/supervised_user_strings_grdp/IDS_BACK_BUTTON.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BACK_BUTTON.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BACK_BUTTON.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_BUTTON.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_BUTTON.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_BUTTON.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_BUTTON.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_INSTEAD_BUTTON.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_INSTEAD_BUTTON.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_INSTEAD_BUTTON.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_ASK_IN_PERSON_INSTEAD_BUTTON.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_ACCESS_REQUESTS_DISABLED.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_NOT_SIGNED_IN.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_NOT_SIGNED_IN.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_NOT_SIGNED_IN.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_HEADER_NOT_SIGNED_IN.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_HIDE_DETAILS.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_HIDE_DETAILS.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_HIDE_DETAILS.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_HIDE_DETAILS.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_REQUEST_ACCESS_BUTTON.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_FEEDBACK.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_FEEDBACK.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_FEEDBACK.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_FEEDBACK.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_MESSAGE_BUTTON.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_MESSAGE_BUTTON.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_MESSAGE_BUTTON.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_SEND_MESSAGE_BUTTON.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_SHOW_DETAILS.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_SHOW_DETAILS.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_SHOW_DETAILS.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_SHOW_DETAILS.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_TITLE.png.sha1 b/components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_TITLE.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_BLOCK_INTERSTITIAL_TITLE.png.sha1 rename to components/supervised_user_strings_grdp/IDS_BLOCK_INTERSTITIAL_TITLE.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_HEADER.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_HEADER.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_HEADER.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_HEADER.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE_V2.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE_V2.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE_V2.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_MESSAGE_V2.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_MULTI_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_FAILED_MESSAGE_SINGLE_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_MULTI_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_REQUEST_SENT_MESSAGE_SINGLE_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_MULTI_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_MULTI_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_MULTI_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_MULTI_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_SINGLE_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_SINGLE_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_SINGLE_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_DESCRIPTION_SINGLE_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_MESSAGE.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_MESSAGE.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_MESSAGE.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_INTERSTITIAL_WAITING_APPROVAL_MESSAGE.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_MULTI_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_DEFAULT_SINGLE_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_MULTI_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT.png.sha1 b/components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT.png.sha1 rename to components/supervised_user_strings_grdp/IDS_CHILD_BLOCK_MESSAGE_MANUAL_SINGLE_PARENT.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_GENERIC_SITE_BLOCK_HEADER.png.sha1 b/components/supervised_user_strings_grdp/IDS_GENERIC_SITE_BLOCK_HEADER.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_GENERIC_SITE_BLOCK_HEADER.png.sha1 rename to components/supervised_user_strings_grdp/IDS_GENERIC_SITE_BLOCK_HEADER.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_REQUEST_SENT_OK.png.sha1 b/components/supervised_user_strings_grdp/IDS_REQUEST_SENT_OK.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_REQUEST_SENT_OK.png.sha1 rename to components/supervised_user_strings_grdp/IDS_REQUEST_SENT_OK.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_SUPERVISED_USER_BLOCK_HEADER.png.sha1 b/components/supervised_user_strings_grdp/IDS_SUPERVISED_USER_BLOCK_HEADER.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_SUPERVISED_USER_BLOCK_HEADER.png.sha1 rename to components/supervised_user_strings_grdp/IDS_SUPERVISED_USER_BLOCK_HEADER.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES.png.sha1 b/components/supervised_user_strings_grdp/IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES.png.sha1 rename to components/supervised_user_strings_grdp/IDS_SUPERVISED_USER_BLOCK_MESSAGE_SAFE_SITES.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/IDS_SUPERVISED_USER_NOT_SIGNED_IN.png.sha1 b/components/supervised_user_strings_grdp/IDS_SUPERVISED_USER_NOT_SIGNED_IN.png.sha1 similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/IDS_SUPERVISED_USER_NOT_SIGNED_IN.png.sha1 rename to components/supervised_user_strings_grdp/IDS_SUPERVISED_USER_NOT_SIGNED_IN.png.sha1
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/OWNERS b/components/supervised_user_strings_grdp/OWNERS similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/OWNERS rename to components/supervised_user_strings_grdp/OWNERS
diff --git a/chrome/app/supervised_user_error_page_strings_grdp/README.md b/components/supervised_user_strings_grdp/README.md similarity index 100% rename from chrome/app/supervised_user_error_page_strings_grdp/README.md rename to components/supervised_user_strings_grdp/README.md
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc index 758daae0..63b4f52 100644 --- a/components/variations/service/variations_field_trial_creator.cc +++ b/components/variations/service/variations_field_trial_creator.cc
@@ -324,7 +324,7 @@ if (base::FeatureList::IsEnabled(kForceFieldTrialSetupCrashForTesting)) { // We log a recognizable token for the crash condition, to allow tests to // recognize the crash location in the test output. See: - // TEST_P(FieldTrialTest, ExtendedSafeModeEndToEnd) + // VariationsSafeModeEndToEndBrowserTest.ExtendedSafeSeedEndToEnd LOG(ERROR) << "crash_for_testing"; abort(); }
diff --git a/components/variations/variations_crash_keys.cc b/components/variations/variations_crash_keys.cc index d6e4c00..1b6dbdd 100644 --- a/components/variations/variations_crash_keys.cc +++ b/components/variations/variations_crash_keys.cc
@@ -7,6 +7,7 @@ #include <string> #include "base/debug/leak_annotations.h" +#include "base/metrics/histogram_macros.h" #include "base/sequence_checker.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" @@ -28,14 +29,19 @@ namespace { -// Size of the "num-experiments" crash key in bytes. 4096 bytes should be able -// to hold about 227 entries, given each entry is 18 bytes long (due to being +// Size of the "num-experiments" crash key in bytes. 1024*6 bytes should be able +// to hold about 341 entries, given each entry is 18 bytes long (due to being // of the form "8e7abfb0-c16397b7,"). #if BUILDFLAG(LARGE_VARIATION_KEY_SIZE) -constexpr size_t kVariationsKeySize = 8192; +constexpr size_t kVariationsKeySize = 1024 * 8; +constexpr char kVariationKeySizeHistogram[] = + "Variations.Limits.VariationKeySize.Large"; #else -constexpr size_t kVariationsKeySize = 6144; +constexpr size_t kVariationsKeySize = 1024 * 6; +constexpr char kVariationKeySizeHistogram[] = + "Variations.Limits.VariationKeySize.Default"; #endif +constexpr size_t kVariationsKeySizeNumBuckets = 16; // Crash key reporting the number of experiments. 8 is the size of the crash key // in bytes, which is used to hold an int as a string. @@ -180,13 +186,14 @@ ExperimentListInfo info = GetExperimentListInfo(); g_num_variations_crash_key.Set(base::NumberToString(info.num_experiments)); + const size_t count_of_kbs = info.experiment_list.size() / 1024; + UMA_HISTOGRAM_EXACT_LINEAR(kVariationKeySizeHistogram, count_of_kbs, + kVariationsKeySizeNumBuckets); if (info.experiment_list.size() > kVariationsKeySize) { // If size exceeded, truncate to the last full entry. int comma_index = info.experiment_list.substr(0, kVariationsKeySize).rfind(','); info.experiment_list.resize(comma_index + 1); - // NOTREACHED() will let us know of the problem and adjust the limit. - NOTREACHED(); } g_variations_crash_key.Set(info.experiment_list);
diff --git a/components/viz/test/test_in_process_context_provider.cc b/components/viz/test/test_in_process_context_provider.cc index b54d3580..f0825d1 100644 --- a/components/viz/test/test_in_process_context_provider.cc +++ b/components/viz/test/test_in_process_context_provider.cc
@@ -9,45 +9,47 @@ #include <memory> #include <utility> -#include "base/lazy_instance.h" #include "base/task/single_thread_task_runner.h" #include "base/types/optional_util.h" #include "components/viz/common/gpu/context_cache_controller.h" -#include "components/viz/common/resources/platform_color.h" -#include "components/viz/service/display/display_compositor_memory_and_task_controller.h" #include "components/viz/service/gl/gpu_service_impl.h" #include "components/viz/test/test_gpu_service_holder.h" -#include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/gles2_implementation.h" #include "gpu/command_buffer/client/raster_implementation_gles.h" #include "gpu/command_buffer/client/shared_memory_limits.h" #include "gpu/command_buffer/common/context_creation_attribs.h" -#include "gpu/command_buffer/service/gpu_task_scheduler_helper.h" #include "gpu/config/skia_limits.h" #include "gpu/ipc/gl_in_process_context.h" #include "gpu/ipc/raster_in_process_context.h" -#include "gpu/ipc/test_gpu_thread_holder.h" #include "gpu/skia_bindings/grcontext_for_gles2_interface.h" -#include "third_party/khronos/GLES2/gl2.h" -#include "third_party/khronos/GLES2/gl2ext.h" #include "third_party/skia/include/gpu/GrDirectContext.h" -#include "third_party/skia/include/gpu/gl/GrGLInterface.h" -#include "ui/gfx/native_widget_types.h" namespace viz { namespace { -std::unique_ptr<gpu::GLInProcessContext> CreateGLInProcessContext() { +gpu::ContextCreationAttribs GetAttributes(bool enable_gles2, + bool enable_raster, + bool enable_oopr) { gpu::ContextCreationAttribs attribs; - attribs.alpha_size = -1; - attribs.depth_size = 24; + attribs.alpha_size = 8; + attribs.blue_size = 8; + attribs.green_size = 8; + attribs.red_size = 8; + attribs.depth_size = 0; attribs.stencil_size = 8; attribs.samples = 0; attribs.sample_buffers = 0; - attribs.fail_if_major_perf_caveat = false; attribs.bind_generates_resource = false; - attribs.enable_oop_rasterization = false; + attribs.enable_gles2_interface = enable_gles2; + attribs.enable_raster_interface = enable_raster; + attribs.enable_oop_rasterization = enable_oopr; + return attribs; +} + +std::unique_ptr<gpu::GLInProcessContext> CreateGLInProcessContext() { + gpu::ContextCreationAttribs attribs = GetAttributes( + /*enable_gles2=*/true, /*enable_raster=*/false, /*enable_oopr=*/false); auto context = std::make_unique<gpu::GLInProcessContext>(); auto result = @@ -70,11 +72,18 @@ gpu::raster::GrShaderCache* gr_shader_cache, gpu::GpuProcessActivityFlags* activity_flags) : type_(type), activity_flags_(activity_flags) { - if (support_locking) + DCHECK(main_thread_checker_.CalledOnValidThread()); + context_thread_checker_.DetachFromThread(); + + if (support_locking) { context_lock_.emplace(); + } } -TestInProcessContextProvider::~TestInProcessContextProvider() = default; +TestInProcessContextProvider::~TestInProcessContextProvider() { + DCHECK(main_thread_checker_.CalledOnValidThread() || + context_thread_checker_.CalledOnValidThread()); +} void TestInProcessContextProvider::AddRef() const { base::RefCountedThreadSafe<TestInProcessContextProvider>::AddRef(); @@ -85,6 +94,8 @@ } gpu::ContextResult TestInProcessContextProvider::BindToCurrentSequence() { + DCHECK(context_thread_checker_.CalledOnValidThread()); + auto* holder = TestGpuServiceHolder::GetInstance(); if (type_ == TestContextType::kGLES2) { @@ -94,11 +105,8 @@ } else { bool is_gpu_raster = type_ == TestContextType::kGpuRaster; - gpu::ContextCreationAttribs attribs; - attribs.bind_generates_resource = false; - attribs.enable_oop_rasterization = is_gpu_raster; - attribs.enable_raster_interface = true; - attribs.enable_gles2_interface = false; + gpu::ContextCreationAttribs attribs = GetAttributes( + /*enable_gles2=*/false, /*enable_raster=*/true, is_gpu_raster); raster_context_ = std::make_unique<gpu::RasterInProcessContext>(); auto result = raster_context_->Initialize( @@ -122,11 +130,13 @@ } gpu::gles2::GLES2Interface* TestInProcessContextProvider::ContextGL() { + CheckValidThreadOrLockAcquired(); DCHECK_EQ(type_, TestContextType::kGLES2); return gles2_context_->GetImplementation(); } gpu::raster::RasterInterface* TestInProcessContextProvider::RasterInterface() { + CheckValidThreadOrLockAcquired(); DCHECK_NE(type_, TestContextType::kGLES2); return raster_context_->GetImplementation(); } @@ -140,6 +150,7 @@ } class GrDirectContext* TestInProcessContextProvider::GrContext() { + CheckValidThreadOrLockAcquired(); if (gr_context_) return gr_context_->get(); @@ -168,6 +179,7 @@ } ContextCacheController* TestInProcessContextProvider::CacheController() { + CheckValidThreadOrLockAcquired(); return cache_controller_.get(); } @@ -177,14 +189,30 @@ const gpu::Capabilities& TestInProcessContextProvider::ContextCapabilities() const { + CheckValidThreadOrLockAcquired(); return caps_; } const gpu::GpuFeatureInfo& TestInProcessContextProvider::GetGpuFeatureInfo() const { + CheckValidThreadOrLockAcquired(); return gpu_feature_info_; } +void TestInProcessContextProvider::AddObserver(ContextLostObserver* obs) { + observers_.AddObserver(obs); +} + +void TestInProcessContextProvider::RemoveObserver(ContextLostObserver* obs) { + observers_.RemoveObserver(obs); +} + +void TestInProcessContextProvider::SendOnContextLost() { + for (auto& observer : observers_) { + observer.OnContextLost(); + } +} + void TestInProcessContextProvider::ExecuteOnGpuThread(base::OnceClosure task) { DCHECK(raster_context_); raster_context_->GetCommandBufferForTest() @@ -192,4 +220,14 @@ ->ScheduleOutOfOrderTask(std::move(task)); } +void TestInProcessContextProvider::CheckValidThreadOrLockAcquired() const { +#if DCHECK_IS_ON() + if (context_lock_) { + context_lock_->AssertAcquired(); + } else { + DCHECK(context_thread_checker_.CalledOnValidThread()); + } +#endif +} + } // namespace viz
diff --git a/components/viz/test/test_in_process_context_provider.h b/components/viz/test/test_in_process_context_provider.h index afc94df..ebf8d64 100644 --- a/components/viz/test/test_in_process_context_provider.h +++ b/components/viz/test/test_in_process_context_provider.h
@@ -10,11 +10,11 @@ #include <memory> #include "base/memory/raw_ptr.h" +#include "base/observer_list.h" #include "base/synchronization/lock.h" -#include "base/task/single_thread_task_runner.h" +#include "base/threading/thread_checker.h" #include "components/viz/common/gpu/context_provider.h" #include "components/viz/common/gpu/raster_context_provider.h" -#include "components/viz/test/test_gpu_memory_buffer_manager.h" #include "gpu/config/gpu_feature_info.h" class GrDirectContext; @@ -67,8 +67,11 @@ base::Lock* GetLock() override; const gpu::Capabilities& ContextCapabilities() const override; const gpu::GpuFeatureInfo& GetGpuFeatureInfo() const override; - void AddObserver(ContextLostObserver* obs) override {} - void RemoveObserver(ContextLostObserver* obs) override {} + void AddObserver(ContextLostObserver* obs) override; + void RemoveObserver(ContextLostObserver* obs) override; + + // Calls OnContextLost() on all observers. This doesn't modify the context. + void SendOnContextLost(); void ExecuteOnGpuThread(base::OnceClosure task); @@ -77,10 +80,15 @@ ~TestInProcessContextProvider() override; private: + void CheckValidThreadOrLockAcquired() const; + const TestContextType type_; raw_ptr<gpu::raster::GrShaderCache> gr_shader_cache_ = nullptr; raw_ptr<gpu::GpuProcessActivityFlags> activity_flags_ = nullptr; + base::ThreadChecker main_thread_checker_; + base::ThreadChecker context_thread_checker_; + gpu::Capabilities caps_; // Used for GLES2 contexts only. @@ -93,6 +101,8 @@ std::unique_ptr<ContextCacheController> cache_controller_; absl::optional<base::Lock> context_lock_; gpu::GpuFeatureInfo gpu_feature_info_; + + base::ObserverList<ContextLostObserver>::Unchecked observers_; }; } // namespace viz
diff --git a/components/webapps/browser/install_result_code.cc b/components/webapps/browser/install_result_code.cc index eed3793b..9fce22a 100644 --- a/components/webapps/browser/install_result_code.cc +++ b/components/webapps/browser/install_result_code.cc
@@ -79,6 +79,8 @@ return os << "kAppNotInRegistrarAfterCommit"; case InstallResultCode::kHaltedBySyncUninstall: return os << "kHaltedBySyncUninstall"; + case InstallResultCode::kInstallURLInvalid: + return os << "kInstallURLInvalid"; } }
diff --git a/components/webapps/browser/install_result_code.h b/components/webapps/browser/install_result_code.h index b791da5..4c1f38db 100644 --- a/components/webapps/browser/install_result_code.h +++ b/components/webapps/browser/install_result_code.h
@@ -83,7 +83,10 @@ // The installation stopped due to an uninstall from sync being scheduled. kHaltedBySyncUninstall = 28, - kMaxValue = kHaltedBySyncUninstall, + // Invalid install URL for externally managed apps. + kInstallURLInvalid = 29, + + kMaxValue = kInstallURLInvalid, }; // Checks if InstallResultCode is not a failure.
diff --git a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm index d89c11d6..fd4c01dd 100644 --- a/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm +++ b/content/app_shim_remote_cocoa/render_widget_host_view_cocoa.mm
@@ -26,6 +26,7 @@ #import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h" #import "content/public/browser/render_widget_host_view_mac_delegate.h" #include "content/public/common/content_features.h" +#include "skia/ext/skia_utils_mac.h" #include "third_party/blink/public/mojom/input/input_handler.mojom.h" #include "third_party/blink/public/platform/web_text_input_type.h" #include "ui/accessibility/platform/ax_platform_node.h" @@ -75,7 +76,7 @@ // functions. class DummyHostHelper : public RenderWidgetHostNSViewHostHelper { public: - explicit DummyHostHelper() {} + explicit DummyHostHelper() = default; DummyHostHelper(const DummyHostHelper&) = delete; DummyHostHelper& operator=(const DummyHostHelper&) = delete; @@ -117,37 +118,32 @@ return content::GetSystemHotkeyMap()->IsEventReserved(event); } -// TODO(suzhe): Upstream this function. -SkColor SkColorFromNSColor(NSColor* color) { - CGFloat r, g, b, a; - [color getRed:&r green:&g blue:&b alpha:&a]; - - return base::clamp(static_cast<int>(lroundf(255.0f * a)), 0, 255) << 24 | - base::clamp(static_cast<int>(lroundf(255.0f * r)), 0, 255) << 16 | - base::clamp(static_cast<int>(lroundf(255.0f * g)), 0, 255) << 8 | - base::clamp(static_cast<int>(lroundf(255.0f * b)), 0, 255); -} - -// Extract underline information from an attributed string. Mostly copied from -// third_party/WebKit/Source/WebKit/mac/WebView/WebHTMLView.mm +// Extract underline information from an attributed string. Inspired by +// `extractUnderlines` in +// https://github.com/WebKit/WebKit/blob/main/Source/WebKitLegacy/mac/WebView/WebHTMLView.mm void ExtractUnderlines(NSAttributedString* string, std::vector<ui::ImeTextSpan>* ime_text_spans) { - int length = [[string string] length]; - int i = 0; + NSUInteger length = string.length; + NSUInteger i = 0; while (i < length) { NSRange range; NSDictionary* attrs = [string attributesAtIndex:i longestEffectiveRange:&range inRange:NSMakeRange(i, length - i)]; - if (NSNumber* style = attrs[NSUnderlineStyleAttributeName]) { + if (NSNumber* style_attr = attrs[NSUnderlineStyleAttributeName]) { SkColor color = SK_ColorBLACK; - if (NSColor* colorAttr = attrs[NSUnderlineColorAttributeName]) { - color = SkColorFromNSColor( - [colorAttr colorUsingColorSpaceName:NSDeviceRGBColorSpace]); + if (NSColor* color_attr = attrs[NSUnderlineColorAttributeName]) { + color = skia::NSDeviceColorToSkColor( + [color_attr colorUsingColorSpace:NSColorSpace.deviceRGBColorSpace]); } + + // `NSUnderlineStyle` is the combination of a type enum with a pattern + // style in the higher bits. Fold anything more complicated than a single + // unstyled underline down to "thick" rather than "thin". ui::ImeTextSpan::Thickness thickness = - [style intValue] > 1 ? ui::ImeTextSpan::Thickness::kThick - : ui::ImeTextSpan::Thickness::kThin; + style_attr.intValue > NSUnderlineStyleSingle + ? ui::ImeTextSpan::Thickness::kThick + : ui::ImeTextSpan::Thickness::kThin; ui::ImeTextSpan ui_ime_text_span = ui::ImeTextSpan( ui::ImeTextSpan::Type::kComposition, range.location, NSMaxRange(range), thickness, ui::ImeTextSpan::UnderlineStyle::kSolid, @@ -155,7 +151,7 @@ ui_ime_text_span.underline_color = color; ime_text_spans->push_back(ui_ime_text_span); } - i = range.location + range.length; + i = NSMaxRange(range); } } @@ -2056,10 +2052,10 @@ ExtractUnderlines(string, &_ime_text_spans); } else { // Use a thin black underline by default. - _ime_text_spans.push_back(ui::ImeTextSpan( - ui::ImeTextSpan::Type::kComposition, 0, length, - ui::ImeTextSpan::Thickness::kThin, - ui::ImeTextSpan::UnderlineStyle::kSolid, SK_ColorTRANSPARENT)); + _ime_text_spans.emplace_back(ui::ImeTextSpan::Type::kComposition, 0, length, + ui::ImeTextSpan::Thickness::kThin, + ui::ImeTextSpan::UnderlineStyle::kSolid, + SK_ColorTRANSPARENT); } // If we are handling a key down event and the reconversion is not triggered,
diff --git a/content/browser/attribution_reporting/attribution_debug_report.cc b/content/browser/attribution_reporting/attribution_debug_report.cc index 27fbbb63..b7e7e9a 100644 --- a/content/browser/attribution_reporting/attribution_debug_report.cc +++ b/content/browser/attribution_reporting/attribution_debug_report.cc
@@ -29,6 +29,8 @@ using EventLevelResult = ::content::AttributionTrigger::EventLevelResult; using AggregatableResult = ::content::AttributionTrigger::AggregatableResult; +constexpr char kAttributionDestination[] = "attribution_destination"; + absl::optional<DebugDataType> DataTypeIfCookieSet(DebugDataType data_type, bool is_debug_cookie_set) { return is_debug_cookie_set ? absl::make_optional(data_type) : absl::nullopt; @@ -205,11 +207,6 @@ } } -void SetAttributionDestination(base::Value::Dict& data_body, - const net::SchemefulSite& destination) { - data_body.Set("attribution_destination", destination.Serialize()); -} - template <typename T> void SetLimit(base::Value::Dict& data_body, absl::optional<T> limit) { DCHECK(limit.has_value()); @@ -224,7 +221,8 @@ const CommonSourceInfo& common_info = source.common_info(); base::Value::Dict data_body; - SetAttributionDestination(data_body, common_info.DestinationSite()); + data_body.Set(kAttributionDestination, + common_info.SerializeDestinationSites()); SetSourceData(data_body, common_info); switch (data_type) { @@ -266,8 +264,8 @@ const AttributionTrigger& trigger, const CreateReportResult& result) { base::Value::Dict data_body; - SetAttributionDestination(data_body, - net::SchemefulSite(trigger.destination_origin())); + data_body.Set(kAttributionDestination, + net::SchemefulSite(trigger.destination_origin()).Serialize()); if (absl::optional<uint64_t> debug_key = trigger.registration().debug_key) data_body.Set("trigger_debug_key", base::NumberToString(*debug_key));
diff --git a/content/browser/attribution_reporting/attribution_debug_report_unittest.cc b/content/browser/attribution_reporting/attribution_debug_report_unittest.cc index 811b210..10e3a11 100644 --- a/content/browser/attribution_reporting/attribution_debug_report_unittest.cc +++ b/content/browser/attribution_reporting/attribution_debug_report_unittest.cc
@@ -7,6 +7,7 @@ #include <stdint.h> #include "base/test/values_test_util.h" +#include "components/attribution_reporting/suitable_origin.h" #include "content/browser/attribution_reporting/attribution_observer_types.h" #include "content/browser/attribution_reporting/attribution_storage.h" #include "content/browser/attribution_reporting/attribution_test_utils.h" @@ -19,6 +20,8 @@ namespace content { namespace { +using ::attribution_reporting::SuitableOrigin; + using EventLevelResult = ::content::AttributionTrigger::EventLevelResult; using AggregatableResult = ::content::AttributionTrigger::AggregatableResult; @@ -223,6 +226,39 @@ } } } + + // Multiple destinations + { + absl::optional<AttributionDebugReport> report = + AttributionDebugReport::Create( + SourceBuilder() + .SetDebugReporting(true) + .SetDestinationOrigins({ + *SuitableOrigin::Create(GURL("https://a.c.test")), + *SuitableOrigin::Create(GURL("https://b.c.test")), + *SuitableOrigin::Create(GURL("https://d.test")), + }) + .Build(), + /*is_debug_cookie_set=*/true, + AttributionStorage::StoreSourceResult( + StorableSource::Result::kSuccessNoised, + /*min_fake_report_time=*/absl::nullopt, + /*max_destinations_per_source_site_reporting_origin=*/ + absl::nullopt, + /*max_sources_per_origin=*/absl::nullopt)); + + EXPECT_EQ(report->ReportBody(), base::test::ParseJson(R"json([{ + "body": { + "attribution_destination": [ + "https://c.test", + "https://d.test" + ], + "source_event_id": "123", + "source_site": "https://impression.test" + }, + "type": "source-noised" + }])json")); + } } TEST(AttributionDebugReportTest, TriggerDebugging) {
diff --git a/content/browser/attribution_reporting/attribution_input_event_tracker_android.cc b/content/browser/attribution_reporting/attribution_input_event_tracker_android.cc index cbb0e9d4..b09d5ea 100644 --- a/content/browser/attribution_reporting/attribution_input_event_tracker_android.cc +++ b/content/browser/attribution_reporting/attribution_input_event_tracker_android.cc
@@ -9,8 +9,6 @@ #include <tuple> #include "base/android/scoped_java_ref.h" -#include "base/bind.h" -#include "base/callback.h" #include "base/check.h" #include "base/time/time.h" #include "content/browser/web_contents/web_contents_android.h" @@ -21,18 +19,8 @@ namespace content { -namespace { - -bool IsEventValid(const ui::MotionEventAndroid& event) { - // TODO(crbug.com/1378617): Apply Android's event policy. - return true; -} - -} // namespace - AttributionInputEventTrackerAndroid::AttributionInputEventTrackerAndroid( - WebContents* web_contents) - : event_filter_(base::BindRepeating(&IsEventValid)) { + WebContents* web_contents) { DCHECK(web_contents); // Lazy initialization @@ -52,14 +40,11 @@ void AttributionInputEventTrackerAndroid::OnTouchEvent( const ui::MotionEventAndroid& event) { - PushEventIfValid(event); + PushEvent(event); } -void AttributionInputEventTrackerAndroid::PushEventIfValid( +void AttributionInputEventTrackerAndroid::PushEvent( const ui::MotionEventAndroid& event) { - if (!event_filter_.Run(event)) - return; - most_recent_event_ = base::android::ScopedJavaGlobalRef<jobject>(event.GetJavaObject()); most_recent_event_cache_time_ = base::TimeTicks::Now();
diff --git a/content/browser/attribution_reporting/attribution_input_event_tracker_android.h b/content/browser/attribution_reporting/attribution_input_event_tracker_android.h index 36ee114..776d6a3 100644 --- a/content/browser/attribution_reporting/attribution_input_event_tracker_android.h +++ b/content/browser/attribution_reporting/attribution_input_event_tracker_android.h
@@ -7,10 +7,6 @@ #include <jni.h> -#include <utility> - -#include "base/callback.h" -#include "base/check.h" #include "base/time/time.h" #include "content/common/content_export.h" #include "ui/android/event_forwarder.h" @@ -59,20 +55,10 @@ private: friend class AttributionInputEventTrackerAndroidTest; - using EventFilterFunction = - base::RepeatingCallback<bool(const ui::MotionEventAndroid&)>; - // ui::EventForwarder::Observer: void OnTouchEvent(const ui::MotionEventAndroid& event) override; - void PushEventIfValid(const ui::MotionEventAndroid& event); - - void set_event_filter_for_testing(EventFilterFunction event_filter) { - DCHECK(!event_filter.is_null()); - event_filter_ = std::move(event_filter); - } - - EventFilterFunction event_filter_; + void PushEvent(const ui::MotionEventAndroid& event); base::android::ScopedJavaGlobalRef<jobject> most_recent_event_;
diff --git a/content/browser/attribution_reporting/attribution_input_event_tracker_android_unittest.cc b/content/browser/attribution_reporting/attribution_input_event_tracker_android_unittest.cc index 58956ea..f0a021c 100644 --- a/content/browser/attribution_reporting/attribution_input_event_tracker_android_unittest.cc +++ b/content/browser/attribution_reporting/attribution_input_event_tracker_android_unittest.cc
@@ -7,15 +7,12 @@ #include <jni.h> #include <memory> -#include <utility> #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" -#include "base/bind.h" #include "base/memory/raw_ptr.h" #include "base/strings/string_piece.h" -#include "base/test/bind.h" #include "base/time/time.h" #include "content/public/browser/web_contents.h" #include "content/public/test/browser_task_environment.h" @@ -56,19 +53,12 @@ input_event_tracker_ = std::make_unique<AttributionInputEventTrackerAndroid>(web_contents()); - SetEventFilter(base::BindRepeating( - [](const ui::MotionEventAndroid&) { return true; })); } void OnTouchEvent(const ui::MotionEventAndroid& event) { input_event_tracker_->OnTouchEvent(event); } - void SetEventFilter( - AttributionInputEventTrackerAndroid::EventFilterFunction event_filter) { - input_event_tracker_->set_event_filter_for_testing(std::move(event_filter)); - } - protected: // The Java strings are used as standins for the input events. base::android::ScopedJavaLocalRef<jstring> GetJavaString( @@ -86,22 +76,6 @@ std::unique_ptr<AttributionInputEventTrackerAndroid> input_event_tracker_; }; -TEST_F(AttributionInputEventTrackerAndroidTest, EventFilterApplied) { - base::android::ScopedJavaLocalRef<jstring> str1 = GetJavaString("str1"); - base::android::ScopedJavaLocalRef<jstring> str2 = GetJavaString("str2"); - - SetEventFilter( - base::BindLambdaForTesting([&](const ui::MotionEventAndroid& event) { - return IsSameObject(event.GetJavaObject(), str2); - })); - - OnTouchEvent(CreateTouchEventAt(100.f, 100.f, str1.obj())); - EXPECT_TRUE(input_event_tracker_->GetMostRecentEvent().is_null()); - - OnTouchEvent(CreateTouchEventAt(100.f, 100.f, str2.obj())); - EXPECT_TRUE(IsSameObject(input_event_tracker_->GetMostRecentEvent(), str2)); -} - TEST_F(AttributionInputEventTrackerAndroidTest, EventExpiryApplied) { EXPECT_TRUE(input_event_tracker_->GetMostRecentEvent().is_null());
diff --git a/content/browser/attribution_reporting/attribution_report.cc b/content/browser/attribution_reporting/attribution_report.cc index 3756faed..c3c20f2 100644 --- a/content/browser/attribution_reporting/attribution_report.cc +++ b/content/browser/attribution_reporting/attribution_report.cc
@@ -10,7 +10,6 @@ #include "base/check.h" #include "base/check_op.h" -#include "base/containers/flat_set.h" #include "base/functional/overloaded.h" #include "base/memory/raw_ptr.h" #include "base/strings/strcat.h" @@ -19,7 +18,6 @@ #include "components/attribution_reporting/suitable_origin.h" #include "content/browser/attribution_reporting/attribution_source_type.h" #include "content/browser/attribution_reporting/common_source_info.h" -#include "net/base/schemeful_site.h" #include "third_party/abseil-cpp/absl/types/variant.h" #include "url/gurl.h" #include "url/origin.h" @@ -27,32 +25,6 @@ namespace content { -namespace { - -base::Value SerializeDestinations( - const base::flat_set<attribution_reporting::SuitableOrigin>& destinations) { - DCHECK(!destinations.empty()); - - base::flat_set<net::SchemefulSite> sites; - for (const auto& destination : destinations) { - sites.insert(net::SchemefulSite(destination)); - } - - if (sites.size() == 1) - return base::Value(sites.begin()->Serialize()); - - base::Value::List list; - list.reserve(sites.size()); - - for (const auto& site : sites) { - list.Append(site.Serialize()); - } - - return base::Value(std::move(list)); -} - -} // namespace - AttributionReport::EventLevelData::EventLevelData( uint64_t trigger_data, int64_t priority, @@ -177,8 +149,7 @@ this->attribution_info().source.common_info(); dict.Set("attribution_destination", - SerializeDestinations( - common_source_info.destination_origins())); + common_source_info.SerializeDestinationSites()); // The API denotes these values as strings; a `uint64_t` cannot be // put in a dict as an integer in order to be opaque to various API
diff --git a/content/browser/attribution_reporting/common_source_info.cc b/content/browser/attribution_reporting/common_source_info.cc index 6f862f0..1dbe130 100644 --- a/content/browser/attribution_reporting/common_source_info.cc +++ b/content/browser/attribution_reporting/common_source_info.cc
@@ -10,6 +10,7 @@ #include "base/check_op.h" #include "base/containers/flat_set.h" #include "base/cxx17_backports.h" +#include "base/values.h" #include "components/attribution_reporting/suitable_origin.h" #include "net/base/schemeful_site.h" @@ -149,4 +150,24 @@ return net::SchemefulSite(source_origin_); } +base::Value CommonSourceInfo::SerializeDestinationSites() const { + base::flat_set<net::SchemefulSite> sites; + for (const auto& destination : destination_origins_) { + sites.insert(net::SchemefulSite(destination)); + } + + if (sites.size() == 1) { + return base::Value(sites.begin()->Serialize()); + } + + base::Value::List list; + list.reserve(sites.size()); + + for (const auto& site : sites) { + list.Append(site.Serialize()); + } + + return base::Value(std::move(list)); +} + } // namespace content
diff --git a/content/browser/attribution_reporting/common_source_info.h b/content/browser/attribution_reporting/common_source_info.h index 3350469..77925ff 100644 --- a/content/browser/attribution_reporting/common_source_info.h +++ b/content/browser/attribution_reporting/common_source_info.h
@@ -17,6 +17,10 @@ #include "content/common/content_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" +namespace base { +class Value; +} // namespace base + namespace net { class SchemefulSite; } // namespace net @@ -132,6 +136,11 @@ // that we avoid unnecessary copies of |source_origin_|. net::SchemefulSite SourceSite() const; + // Serializes the source's destination origins as a set of sites. If the set + // has a single element, returns the string directly. Otherwise, returns a + // list of strings. + base::Value SerializeDestinationSites() const; + private: uint64_t source_event_id_; attribution_reporting::SuitableOrigin source_origin_;
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index 6cbdb791..2a180c7a 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -214,11 +214,14 @@ "ConnectionInfo enum is stable"); static_assert(net::HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 == 40, "ConnectionInfo enum is stable"); -static_assert(net::HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1 == 41, +static_assert( + net::HttpResponseInfo::CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1 == 41, + "ConnectionInfo enum is stable"); +static_assert(net::HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_8 == 42, "ConnectionInfo enum is stable"); // The following assert needs to be changed every time a new value is added. // It exists to prevent us from forgetting to add new values above. -static_assert(net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS == 42, +static_assert(net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS == 43, "Please add new values above and update this assert"); // Copy headers out of a cache entry and into a protobuf. The callback is
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc index 12805d2..909604f 100644 --- a/content/browser/child_process_security_policy_unittest.cc +++ b/content/browser/child_process_security_policy_unittest.cc
@@ -130,6 +130,14 @@ } void TearDown() override { + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + { + base::AutoLock lock(policy->lock_); + EXPECT_EQ(0u, policy->security_state_.size()) + << "ChildProcessSecurityPolicy should not be tracking any processes " + << "at test shutdown. Did you forget to call Remove() at the end of " + << "a test?"; + } test_browser_client_.ClearSchemes(); SetBrowserClientForTesting(old_browser_client_); }
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc index 70d70bc..dcfa80f 100644 --- a/content/browser/devtools/protocol/network_handler.cc +++ b/content/browser/devtools/protocol/network_handler.cc
@@ -3160,6 +3160,9 @@ case network::mojom::TrustTokenOperationStatus::kUnavailable: return protocol::Network::TrustTokenOperationDone::StatusEnum:: Unavailable; + case network::mojom::TrustTokenOperationStatus::kUnauthorized: + return protocol::Network::TrustTokenOperationDone::StatusEnum:: + Unauthorized; case network::mojom::TrustTokenOperationStatus::kBadResponse: return protocol::Network::TrustTokenOperationDone::StatusEnum:: BadResponse;
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc index 1f2540ff..6e083c9 100644 --- a/content/browser/loader/navigation_url_loader_impl_unittest.cc +++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -117,6 +117,7 @@ nullptr /* keepalive_statistics_recorder */, nullptr /* trust_token_helper */, mojo::NullRemote() /* cookie_observer */, + mojo::NullRemote() /* trust_token_observer */, mojo::NullRemote() /* url_loader_network_observer */, /*devtools_observer=*/mojo::NullRemote(), /*accept_ch_frame_observer=*/mojo::NullRemote(),
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc index 5228eca..4436627 100644 --- a/content/browser/renderer_host/clipboard_host_impl.cc +++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -49,22 +49,11 @@ namespace content { -namespace { -bool IsRendererPasteAllowed(RenderFrameHost& render_frame_host) { - ContentBrowserClient* browser_client = GetContentClient()->browser(); - return browser_client->IsClipboardPasteAllowed(&render_frame_host); -} -} // namespace - -// 5 mins is based on the timeout in BinaryUploadService. This scanning timeout -// of 5 mins means no paste will be held back longer before being allowed or -// blocked, so matching this timeout with the threshold for a paste being too -// old ensures scans that: -// - Scans that timeout can be retried without waiting -// - Scans that succeed will apply their verdicts without the risk that their -// associated IsPasteContentAllowedRequest is already too old. -const base::TimeDelta ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld = - base::Minutes(5); +// The amount of time that the result of a content allow request is cached +// and reused for the same clipboard `seqno`. +constexpr base::TimeDelta + ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld = + base::Milliseconds(500); ClipboardHostImpl::IsPasteContentAllowedRequest:: IsPasteContentAllowedRequest() = default; @@ -88,16 +77,19 @@ void ClipboardHostImpl::IsPasteContentAllowedRequest::Complete( IsClipboardPasteContentAllowedCallbackArgType data) { + completed_time_ = base::Time::Now(); data_ = std::move(data); InvokeCallbacks(); } bool ClipboardHostImpl::IsPasteContentAllowedRequest::IsObsolete( base::Time now) { - // If the request is old and no longer has any registered callbacks it is - // obsolete. - return (now - time_) > kIsPasteContentAllowedRequestTooOld && - callbacks_.empty(); + return (now - completed_time_) > kIsPasteContentAllowedRequestTooOld; +} + +base::Time ClipboardHostImpl::IsPasteContentAllowedRequest::completed_time() { + DCHECK(is_complete()); + return completed_time_; } void ClipboardHostImpl::IsPasteContentAllowedRequest::InvokeCallbacks() { @@ -206,7 +198,7 @@ void ClipboardHostImpl::ReadText(ui::ClipboardBuffer clipboard_buffer, ReadTextCallback callback) { - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(std::u16string()); return; } @@ -243,7 +235,7 @@ void ClipboardHostImpl::ReadHtml(ui::ClipboardBuffer clipboard_buffer, ReadHtmlCallback callback) { - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(std::u16string(), GURL(), 0, 0); return; } @@ -275,7 +267,7 @@ void ClipboardHostImpl::ReadSvg(ui::ClipboardBuffer clipboard_buffer, ReadSvgCallback callback) { - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(std::u16string()); return; } @@ -298,7 +290,7 @@ void ClipboardHostImpl::ReadRtf(ui::ClipboardBuffer clipboard_buffer, ReadRtfCallback callback) { - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(std::string()); return; } @@ -322,7 +314,7 @@ void ClipboardHostImpl::ReadPng(ui::ClipboardBuffer clipboard_buffer, ReadPngCallback callback) { - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(mojo_base::BigBuffer()); return; } @@ -356,7 +348,7 @@ void ClipboardHostImpl::ReadFiles(ui::ClipboardBuffer clipboard_buffer, ReadFilesCallback callback) { blink::mojom::ClipboardFilesPtr result = blink::mojom::ClipboardFiles::New(); - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(std::move(result)); return; } @@ -435,7 +427,7 @@ void ClipboardHostImpl::ReadCustomData(ui::ClipboardBuffer clipboard_buffer, const std::u16string& type, ReadCustomDataCallback callback) { - if (!IsRendererPasteAllowed(render_frame_host())) { + if (!IsRendererPasteAllowed(clipboard_buffer, render_frame_host())) { std::move(callback).Run(std::u16string()); return; } @@ -503,6 +495,21 @@ ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint()); } +bool ClipboardHostImpl::IsRendererPasteAllowed( + ui::ClipboardBuffer clipboard_buffer, + RenderFrameHost& render_frame_host) { + auto it = is_allowed_requests_.find( + ui::Clipboard::GetForCurrentThread()->GetSequenceNumber( + clipboard_buffer)); + if (it != is_allowed_requests_.end() && it->second.is_complete() && + !it->second.IsObsolete(base::Time::Now())) { + return true; + } + + return GetContentClient()->browser()->IsClipboardPasteAllowed( + &render_frame_host); +} + bool ClipboardHostImpl::IsUnsanitizedCustomFormatContentAllowed() { if (!base::FeatureList::IsEnabled(blink::features::kClipboardCustomFormats)) { mojo::ReportBadMessage("Custom format read/write is not enabled.");
diff --git a/content/browser/renderer_host/clipboard_host_impl.h b/content/browser/renderer_host/clipboard_host_impl.h index 363b90fb..8205fe2 100644 --- a/content/browser/renderer_host/clipboard_host_impl.h +++ b/content/browser/renderer_host/clipboard_host_impl.h
@@ -75,6 +75,9 @@ // Invoke all callbacks now. void Complete(IsClipboardPasteContentAllowedCallbackArgType data); + // Returns true if the request has completed. + bool is_complete() const { return data_.has_value(); } + // Returns true if this request is obsolete. An obsolete request // is one that is completed, all registered callbacks have been // called, and is considered old. @@ -82,15 +85,18 @@ // |now| represents the current time. It is an argument to ease testing. bool IsObsolete(base::Time now); - // Returns the time at which this request was created. - base::Time time() { return time_; } + // Returns the time at which this request was completed. If called + // before the request is completed the return value is undefined. + base::Time completed_time(); private: // Calls all the callbacks in |callbacks_| with the current value of // |allowed_|. |allowed_| must not be empty. void InvokeCallbacks(); - base::Time time_{base::Time::Now()}; + // The time at which the request was completed. Before completion this + // value is undefined. + base::Time completed_time_; // The data argument to pass to the IsClipboardPasteContentAllowedCallback. // This member is null until Complete() is called. @@ -201,6 +207,11 @@ void WriteStringToFindPboard(const std::u16string& text) override; #endif + // Checks if the renderer allows pasting. This check is skipped if called + // soon after a successful content allowed request. + bool IsRendererPasteAllowed(ui::ClipboardBuffer clipboard_buffer, + RenderFrameHost& render_frame_host); + // Returns true if custom format is allowed to be read/written from/to the // clipboard, else, fails. bool IsUnsanitizedCustomFormatContentAllowed();
diff --git a/content/browser/renderer_host/clipboard_host_impl_unittest.cc b/content/browser/renderer_host/clipboard_host_impl_unittest.cc index 6865a7ea67..e3d747a3 100644 --- a/content/browser/renderer_host/clipboard_host_impl_unittest.cc +++ b/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -221,23 +221,12 @@ TEST_F(ClipboardHostImplTest, IsPasteContentAllowedRequest_IsObsolete) { ClipboardHostImpl::IsPasteContentAllowedRequest request; - // A request that is not too old is not obsolete, even if it has no callbacks. - EXPECT_FALSE(request.IsObsolete( - request.time() + - ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld / 2)); - - // A request that still has callbacks is not obsolete, even if older than - // "too old". - request.AddCallback(base::DoNothing()); - EXPECT_FALSE(request.IsObsolete( - request.time() + ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld + - base::Microseconds(1))); - - // A request is obsolete once it is too old and has no callbacks. + // A request is obsolete once it is too old and completed. // Whether paste is allowed or not is not important. request.Complete("data"); EXPECT_TRUE(request.IsObsolete( - request.time() + ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld + + request.completed_time() + + ClipboardHostImpl::kIsPasteContentAllowedRequestTooOld + base::Microseconds(1))); }
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 8dcc8499..5ba4614 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -2456,9 +2456,20 @@ policy_container_builder_->FinalPolicies().cross_origin_opener_policy, origin, net::NetworkAnonymizationKey(site, site)); - // Select an appropriate RenderFrameHost. - render_frame_host_ = - frame_tree_node_->render_manager()->GetFrameHostForNavigation(this); + if (auto result = + frame_tree_node_->render_manager()->GetFrameHostForNavigation( + this); + result.has_value()) { + render_frame_host_ = result.value(); + } else { + switch (result.error()) { + case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame: + // TODO(https://crbug.com/1400535): This was unhandled before and + // remains explicitly unhandled. This branch may be removed in the + // future. + break; + } + } CHECK(Navigator::CheckWebUIRendererDoesNotDisplayNormalURL( render_frame_host_, GetUrlInfo(), @@ -3913,8 +3924,19 @@ // TODO(https://crbug.com/1181712): Handle the cases when the prerender is // cancelled and RFH is destroyed while NavigationRequest is alive. } else if (response_should_be_rendered_) { - render_frame_host_ = - frame_tree_node_->render_manager()->GetFrameHostForNavigation(this); + if (auto result = + frame_tree_node_->render_manager()->GetFrameHostForNavigation(this); + result.has_value()) { + render_frame_host_ = result.value(); + } else { + switch (result.error()) { + case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame: + // TODO(https://crbug.com/1400535): This was unhandled before and + // remains explicitly unhandled. This branch may be removed in the + // future. + break; + } + } // Update the associated RenderFrameHost type, which could have changed // due to redirects during navigation. @@ -4150,9 +4172,16 @@ // The CrossOriginRedirectAfterEarlyHints variant of // Navigation.MainFrame.TimeToReadyToCommit2 histogram tracks the performance // impacts. - RenderProcessHost* process = frame_tree_node_->render_manager() - ->GetFrameHostForNavigation(this) - ->GetProcess(); + auto result = + frame_tree_node_->render_manager()->GetFrameHostForNavigation(this); + + // Early hints is an optimization; if it is not possible to get a suitable + // RenderFrameHost for any reason, just bail out. + if (!result.has_value()) { + return absl::nullopt; + } + + RenderProcessHost* process = result.value()->GetProcess(); // The process is shutting down. if (!process->GetBrowserContext()) @@ -4267,8 +4296,20 @@ // https://crbug.com/1125106. common_params_->navigation_type = ConvertToCrossDocumentType(common_params_->navigation_type); - render_frame_host = - frame_tree_node_->render_manager()->GetFrameHostForNavigation(this); + if (auto result = + frame_tree_node_->render_manager()->GetFrameHostForNavigation( + this); + result.has_value()) { + render_frame_host = result.value(); + } else { + switch (result.error()) { + case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame: + // TODO(https://crbug.com/1400535): This was unhandled + // before and remains explicitly unhandled. This branch may be + // removed in the future. + break; + } + } break; } // Sanity check that we haven't changed the RenderFrameHost picked for the
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index 0ee4d43..3aa703c 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -25,6 +25,7 @@ #include "base/trace_event/base_tracing.h" #include "base/trace_event/trace_event.h" #include "base/trace_event/typed_macros.h" +#include "base/types/expected.h" #include "build/build_config.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/network/cross_origin_opener_policy_reporter.h" @@ -1114,18 +1115,20 @@ request->SetAssociatedRFHType( NavigationRequest::AssociatedRenderFrameHostType::CURRENT); } else { - RenderFrameHostImpl* dest_rfh = GetFrameHostForNavigation(request); - DCHECK(dest_rfh); - request->SetAssociatedRFHType( - dest_rfh == render_frame_host_.get() - ? NavigationRequest::AssociatedRenderFrameHostType::CURRENT - : NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE); + auto result = GetFrameHostForNavigation(request); + if (result.has_value()) { + DCHECK(result.value()); + request->SetAssociatedRFHType( + result.value() == render_frame_host_.get() + ? NavigationRequest::AssociatedRenderFrameHostType::CURRENT + : NavigationRequest::AssociatedRenderFrameHostType::SPECULATIVE); + } } } -RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation( - NavigationRequest* request, - std::string* reason) { +base::expected<RenderFrameHostImpl*, GetFrameHostForNavigationFailed> +RenderFrameHostManager::GetFrameHostForNavigation(NavigationRequest* request, + std::string* reason) { TRACE_EVENT("navigation", "RenderFrameHostManager::GetFrameHostForNavigation", ChromeTrackEvent::kFrameTreeNodeInfo, *frame_tree_node_); @@ -1385,8 +1388,10 @@ // before. if (!navigation_rfh->IsRenderFrameLive()) { DCHECK(!frame_tree_node_->parent()); - if (!ReinitializeMainRenderFrame(navigation_rfh)) - return nullptr; + if (!ReinitializeMainRenderFrame(navigation_rfh)) { + return base::unexpected( + GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame); + } notify_webui_of_rf_creation = true;
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h index e79044e..77001a65 100644 --- a/content/browser/renderer_host/render_frame_host_manager.h +++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -16,6 +16,7 @@ #include "base/containers/unique_ptr_adapters.h" #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/types/expected.h" #include "content/browser/renderer_host/browsing_context_state.h" #include "content/browser/renderer_host/navigation_discard_reason.h" #include "content/browser/renderer_host/render_frame_host_impl.h" @@ -62,6 +63,14 @@ using RemoteFramesBroadcastMethodCallback = base::RepeatingCallback<void(RenderFrameProxyHost*)>; +// Reasons that `GetFrameHostForNavigation()` might fail. +enum class GetFrameHostForNavigationFailed { + // Failed to reinitialize the main frame, for whatever reason. + // TODO(https://crbug.com/1400535): This adds a tremendous amount of failure + // plumbing *everywhere* and might be unnecessary. + kCouldNotReinitializeMainFrame, +}; + // Manages RenderFrameHosts for a FrameTreeNode. It maintains a // current_frame_host() which is the content currently visible to the user. When // a frame is told to navigate to a different web site (as determined by @@ -388,16 +397,22 @@ void DidCreateNavigationRequest(NavigationRequest* request); // Called (possibly several times) during a navigation to select or create an - // appropriate RenderFrameHost for the provided URL. The returned pointer will - // be for the current or the speculative RenderFrameHost and the instance is - // owned by this manager. + // appropriate RenderFrameHost for the provided URL. // - // |reason| is an optional out-parameter that will be populated with + // On success, returns a non-null pointer to a RenderFrameHost to use for the + // navigation. The returned pointer always refers to either the current or the + // speculative RenderFrameHost owned by `this`. + // + // Otherwise, on failure, returns an enum value denoting the reason for + // failure. + // + // `reason` is an optional out-parameter that will be populated with // engineer-readable information describing the reason for the method - // behavior. The returned |reason| should fit into + // behavior. The returned `reason` should fit into // base::debug::CrashKeySize::Size256. - RenderFrameHostImpl* GetFrameHostForNavigation(NavigationRequest* request, - std::string* reason = nullptr); + base::expected<RenderFrameHostImpl*, GetFrameHostForNavigationFailed> + GetFrameHostForNavigation(NavigationRequest* request, + std::string* reason = nullptr); // Discards `speculative_render_frame_host_` if it exists, even if there are // NavigationRequests associated with it, including pending commit
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc index be3e2e4..022929d6 100644 --- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc +++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -446,7 +446,7 @@ // And also simulates the 2nd and final call to GetFrameHostForNavigation // that determines the final frame that will commit the navigation. TestRenderFrameHost* frame_host = static_cast<TestRenderFrameHost*>( - manager->GetFrameHostForNavigation(navigation_request.get())); + manager->GetFrameHostForNavigation(navigation_request.get()).value()); CHECK(frame_host); frame_host->SetPolicyContainerHost(
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 3d43d94..0b462411 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1017,6 +1017,11 @@ if (commit_params.http_response_code != -1) navigation_params->http_status_code = commit_params.http_response_code; + // Copy the modified runtime features from `commit_params` to send to the + // Blink renderer class WebLocalFrameImpl. + navigation_params->modified_runtime_features = + commit_params.modified_runtime_features; + // Populate the arrays of non-current entries for the window.navigation API. auto& entry_arrays = commit_params.navigation_api_history_entry_arrays; navigation_params->navigation_api_back_entries.reserve(
diff --git a/content/test/data/gpu/pixel_offscreenCanvas_transferToImageBitmap_main.html b/content/test/data/gpu/pixel_offscreenCanvas_transferToImageBitmap_main.html index a8d34b23..9ab1ec97 100644 --- a/content/test/data/gpu/pixel_offscreenCanvas_transferToImageBitmap_main.html +++ b/content/test/data/gpu/pixel_offscreenCanvas_transferToImageBitmap_main.html
@@ -8,7 +8,7 @@ <html> <head> -<title>OffscreenCanvas transferToImageBitmap on main thread: green and blue squares on white background.</title> +<title>OffscreenCanvas transferToImageBitmap on main thread: RGB squares and on large blue square on white background.</title> <style type="text/css"> .nomargin { margin: 0px auto; @@ -29,8 +29,18 @@ var height = 100; var aCanvas = new OffscreenCanvas(width, height); var gl = aCanvas.getContext('webgl'); - gl.clearColor(0.0, 1.0, 0.0, 1.0); + gl.enable(gl.SCISSOR_TEST); + gl.scissor(0, 50, 50, 50); + gl.clearColor(1, 0, 0, 1); gl.clear(gl.COLOR_BUFFER_BIT); + gl.scissor(50, 50, 100, 50); + gl.clearColor(0, 1, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.scissor(0, 0, 50, 50); + gl.clearColor(0, 0, 1, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.disable(gl.SCISSOR_TEST); + var image1 = aCanvas.transferToImageBitmap(); gl.clearColor(0.0, 0.0, 1.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT);
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 56a02b47..c1b37d5 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -633,6 +633,12 @@ base_name + '_OffscreenCanvasTransferToImageBitmap', test_rect=[0, 0, 300, 300], browser_args=browser_args), + PixelTestPage( + 'pixel_offscreenCanvas_transferToImageBitmap_main.html', + base_name + + '_OffscreenCanvasTransferToImageBitmapSoftwareCompositing', + test_rect=[0, 0, 300, 300], + browser_args=browser_args + unaccelerated_args), PixelTestPage('pixel_offscreenCanvas_transferToImageBitmap_worker.html', base_name + '_OffscreenCanvasTransferToImageBitmapWorker', test_rect=[0, 0, 300, 300],
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index b60b641b..8799d9d 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -83,6 +83,7 @@ [ android ] Pixel_RepeatedWebGLTo2D_SoftwareCompositing [ Skip ] [ android ] Pixel_Canvas2DTabSwitch_SoftwareCompositing [ Skip ] [ android ] Pixel_WebGLReadPixelsTabSwitch_SoftwareCompositing [ Skip ] +[ android ] Pixel_OffscreenCanvasTransferToImageBitmapSoftwareCompositing [ Skip ] [ chromeos ] Pixel_OffscreenCanvasUnaccelerated2D [ Skip ] [ chromeos ] Pixel_OffscreenCanvasUnaccelerated2DWorker [ Skip ] [ chromeos ] Pixel_OffscreenCanvasUnaccelerated2DGPUCompositing [ Skip ] @@ -95,6 +96,7 @@ [ chromeos ] Pixel_RepeatedWebGLTo2D_SoftwareCompositing [ Skip ] [ chromeos ] Pixel_Canvas2DTabSwitch_SoftwareCompositing [ Skip ] [ chromeos ] Pixel_WebGLReadPixelsTabSwitch_SoftwareCompositing [ Skip ] +[ chromeos ] Pixel_OffscreenCanvasTransferToImageBitmapSoftwareCompositing [ Skip ] [ fuchsia ] Pixel_OffscreenCanvasUnaccelerated2D [ Skip ] [ fuchsia ] Pixel_OffscreenCanvasUnaccelerated2DWorker [ Skip ] [ fuchsia ] Pixel_OffscreenCanvasUnaccelerated2DGPUCompositing [ Skip ] @@ -107,6 +109,7 @@ [ fuchsia ] Pixel_RepeatedWebGLTo2D_SoftwareCompositing [ Skip ] [ fuchsia ] Pixel_Canvas2DTabSwitch_SoftwareCompositing [ Skip ] [ fuchsia ] Pixel_WebGLReadPixelsTabSwitch_SoftwareCompositing [ Skip ] +[ fuchsia ] Pixel_OffscreenCanvasTransferToImageBitmapSoftwareCompositing [ Skip ] # Skip tab switching tests on Android webview and Fuchsia since they don't have tabs [ android android-webview-instrumentation ] Pixel_Canvas2DTabSwitch [ Skip ]
diff --git a/device/bluetooth/test/bluetooth_test_cast.cc b/device/bluetooth/test/bluetooth_test_cast.cc index 50f7b63..d67254e34 100644 --- a/device/bluetooth/test/bluetooth_test_cast.cc +++ b/device/bluetooth/test/bluetooth_test_cast.cc
@@ -130,16 +130,16 @@ } // Add service_uuids. - std::vector<uint8_t> data; + std::vector<uint8_t> parsed_uuids; for (const auto& uuid_str : service_uuids) { chromecast::bluetooth_v2_shlib::Uuid uuid; ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(uuid_str, &uuid)); - data.insert(data.end(), uuid.rbegin(), uuid.rend()); + parsed_uuids.insert(parsed_uuids.end(), uuid.rbegin(), uuid.rend()); } result .type_to_data [chromecast::bluetooth::LeScanResult::kGapComplete128BitServiceUuids] - .push_back(std::move(data)); + .push_back(std::move(parsed_uuids)); // Add service data. for (const auto& it : service_data) { @@ -155,7 +155,8 @@ // Add manufacturer data. for (const auto& it : manufacturer_data) { - std::vector<uint8_t> data({(it.first & 0xFF), ((it.first >> 8) & 0xFF)}); + std::vector<uint8_t> data{{static_cast<uint8_t>(it.first & 0xFF), + static_cast<uint8_t>((it.first >> 8) & 0xFF)}}; data.insert(data.end(), it.second.begin(), it.second.end()); result .type_to_data[chromecast::bluetooth::LeScanResult::kGapManufacturerData]
diff --git a/docs/fuchsia/build_instructions.md b/docs/fuchsia/build_instructions.md index 4b823ca..abb2ed3 100644 --- a/docs/fuchsia/build_instructions.md +++ b/docs/fuchsia/build_instructions.md
@@ -259,6 +259,9 @@ ### Running test suites +A description of how our testing scripts work can be found +[here](test_scripts.md). + There are three types of tests available to run on Fuchsia: 1. [Gtests](gtests.md) @@ -276,7 +279,7 @@ directory in Fuchsia. For instance. `/path/to/src/fuchsia/out/qemu-x64`. This will automatically add the `--fuchsia-out-dir` flag to wrapper scripts. * `default_fuchsia_device_node_name`. Set this to a Fuchsia device node name. - This will automatically add the `--node-name` flag to most wrapper scripts. + This will automatically add the `--target-id` flag to most wrapper scripts. * Finally, use the `-d` flag when running the <test_target_name> wrappers to execute them on an already running device or emulator, rather than starting an ephemeral emulator instance. This speeds up subsequent runs since the runner
diff --git a/docs/fuchsia/gtests.md b/docs/fuchsia/gtests.md index 67c56da..267b6e4 100644 --- a/docs/fuchsia/gtests.md +++ b/docs/fuchsia/gtests.md
@@ -3,13 +3,9 @@ [TOC] Fuchsia gtest binaries are deployed and executed via scripts that are -automatically generated by the `test()` GN target. For each test, three wrapper -scripts are created: - -1. deploy_<test_target_name>, for deploying the Fuchsia package onto a device -2. run_<test_target_name>, for running the Fuchsia package on the device - -These executables are found in `${OUTPUT_DIR}/bin`. +automatically generated by the `test()` GN target. For each test, a wrapper +scripts is created named `run_<test_target_name>` for running the Fuchsia +package on the device. These executables are found in `${OUTPUT_DIR}/bin`. The aforementioned devices can be either emulators started by the scripts themselves, an existing emulator instance, or a physical device. To build a @@ -31,12 +27,13 @@ `--custom-image=workstation.qemu-x64-release` would run the test on a workstation image. -## Run on a persistent emulated device from the Chromium three +## Run on a persistent device -You can start a persistent emulator from the Chromium tree by running this command: +You can also run tests on physical devices or start a persistent emulator +from the Chromium tree. To start a persistent emulator, run: ```bash -$ ./build/fuchsia/start_emulator.py +$ ./build/fuchsia/test/start_emulator.py ``` Part of the output should be: @@ -44,19 +41,18 @@ ``` 2022-05-31 22:55:13,011:INFO:root:Emulator successfully started.\ You can now run Chrome Fuchsia tests with\ - "-d --node-name fuchsia-5254-0063-5e7a" to target this emulator. + "--target-id fuchsia-emulator-198" to target this emulator. ``` -Once the emulator is running, you can run tests on this emulator instance by -adding the command line arguments indicated above: +You can run tests on persistent devices by adding the command line +arguments indicated above. For example, to run `base_unittests` you +would run the following command: ```bash -$ out/fuchsia/bin/run_base_unittests -d --node-name fuchsia-5254-0063-5e7a +$ out/fuchsia/bin/run_base_unittests --target-id fuchsia-emulator-198 ``` -## Run on an physical device - -Note the `-d` flag, which is an alias for `--device`. +If only one Fuchsia device is connected, you can also simply use ```bash $ out/fuchsia/bin/run_base_unittests -d @@ -68,47 +64,17 @@ the architecture of the Fuchsia output directory (x64==x64, arm64==arm64, etc.). ```bash -$ out/fuchsia/bin/run_base_unittests -d ---fuchsia-out-dir=/path/to/fuchsia/outdir +$ out/fuchsia/bin/run_base_unittests -d --repo [FUCHSIA_OUT_DIR]/amber-files \ +--no-repo-init ``` -If you are frequently deploying to Fuchsia built from source, you might want to -add the following entry to your `args.gn`: - -``` -default_fuchsia_build_dir_for_installation = "/path/to/fuchsia/outdir" -``` - -With this flag in place, the `--fuchsia-out-dir` flag will automatically be -used whenever you use the wrapper scripts to run or deploy Fuchsia packages, -making your command lines much shorter: - -```bash -$ out/fuchsia/bin/run_base_unittests -d -``` - -## Install on a device running Fuchsia built from source - -```bash -$ out/fuchsia/bin/deploy_base_unittests ---fuchsia-out-dir=/path/to/fuchsia/outdir -``` - -You will need to run the package manually on your device. In this case, run the -following from your Fuchsia directory: - -``` -$ fx shell run fuchsia-pkg://fuchsia.com/base_unittests#meta/base_unittests.cmx -``` +Note that you should not have `fx serve` running as Chromium will handle serving +the repository. ## Run on a device the host is connected to remotely via ssh -Note the `--ssh-config` flag, which should point to the config file used to set -up the connection between the host and the remote device. - ```bash -$ out/fuchsia/bin/run_base_unittests -d \ - --host=::1 --port=8022 --ssh-config=/path/to/ssh/config +$ out/fuchsia/bin/run_base_unittests --target-id=[::1]:8022 ``` ## Troubleshooting a test
diff --git a/docs/fuchsia/test_scripts.md b/docs/fuchsia/test_scripts.md index 0c2985fa..aed02ef 100644 --- a/docs/fuchsia/test_scripts.md +++ b/docs/fuchsia/test_scripts.md
@@ -11,33 +11,6 @@ To build Fuchsia gtest binaries follow [build instructions](build_instructions.md). -### Run on a transient emulated device - -The test script brings up an emulator, runs the tests on it, and -shuts the emulator down when finished. -```bash -$ ./build/fuchsia/test/run_test.py [TEST_BINARY] -C [OUTPUT_DIR] -``` - -### Run on a persistent emulated device from the Chromium tree - -You can start a persistent emulator from the Chromium tree by running this -command: - -```bash -$ ./build/fuchsia/test/start_emulator.py -``` - -Note that running this command for the first time will download a Fuchsia -product bundle and will take around a minute. Part of the output should be: - -``` -Logging to \ - "$HOME/.local/share/Fuchsia/ffx/emu/instances/[EMULATOR_NAME]/emulator.log" -``` - -Record the [EMULATOR_NAME] value as it will be used in subsequent commands. - #### E2E Testing Script Once the emulator is running, you can run tests on this emulator instance by
diff --git a/docs/updater/test_plan.md b/docs/updater/test_plan.md index 0edd5b4..25fc243 100644 --- a/docs/updater/test_plan.md +++ b/docs/updater/test_plan.md
@@ -70,6 +70,10 @@ that it is immediately active after installation, and then can be cleanly uninstalled. +IntegrationTest.Handoff tests that the updater can be installed on a clean OS, +that it can install an app via a "/handoff" command line, and then can be +cleanly uninstalled. + Overinstall cases are tested by IntegrationTest.OverinstallWorking and IntegrationTest.OverinstallBroken, to ensure that the updater can be installed on an unclean OS, and as a post-condition of installation, the system has a
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md index 7c02b13..a783f93 100644 --- a/docs/webui_explainer.md +++ b/docs/webui_explainer.md
@@ -408,9 +408,310 @@ * Setting the resource to load for the empty path. * Adding all resources from a GritResourceMap. -## Browser (C++) → Renderer (JS) +## Browser (C++) and Renderer (JS) communication -### WebUIMessageHandler::AllowJavascript() +### Mojo + +[Mojo](https://chromium.googlesource.com/chromium/src/+/master/mojo/README.md) +is used for IPC throughout Chromium, and should generally be used for new +WebUIs to communicate between the browser (C++) and the renderer (JS/TS). To +use Mojo, you will need to: + +* Write an interface definition for the JS/C++ interface in a mojom file +* Add a build target in the BUILD.gn file to autogenerate C++ and TypeScript + code ("bindings"). +* Bind the interface on the C++ side and implement any methods to send or + receive information from TypeScript. +* Add the TypeScript bindings file to your WebUI's <code>ts_library()</code> + and use them in your TypeScript code. + +#### Mojo Interface Definition +Mojo interfaces are declared in mojom files. For WebUIs, these normally live +alongside the C++ code in chrome/browser/ui/webui. For example: + +**chrome/browser/ui/webui/donuts/donuts.mojom** +``` +module donuts.mojom; + +interface PageHandlerFactory { + CreatePageHandler(pending_remote<Page> page, + pending_receiver<PageHandler> handler); +}; + +// Called from TS side of chrome://donuts (Renderer -> Browser) +interface PageHandler { + StartPilotLight(); + + BakeDonuts(uint32 num_donuts); + + // Expects a response from the browser. + GetNumberOfDonuts() => (uint32 num_donuts); +} + +// Called from C++ side of chrome://donuts. (Browser -> Renderer) +interface Page { + DonutsBaked(uint32 num_donuts); +} +``` + +#### BUILD.gn mojo target +mojom() is the build rule used to generate mojo bindings. It can be set up as +follows: + +**chrome/browser/ui/webui/donuts/BUILD.gn** +``` +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojo_bindings") { + sources = [ "donuts.mojom" ] + webui_module_path = "/" + use_typescript_sources = true +} +``` + +#### Setting up C++ bindings +The WebUIController class should inherit from ui::MojoWebUIController and +from the PageHandlerFactory class defined in the mojom file. + +**chrome/browser/ui/webui/donuts/donuts_ui.h** +```c++ +class DonutsPageHandler; + +class DonutsUI : public ui::MojoWebUIController, + public donuts::mojom::PageHandlerFactory { + public: + explicit DonutsUI(content::WebUI* web_ui); + + DonutsUI(const DonutsUI&) = delete; + DonutsUI& operator=(const DonutsUI&) = delete; + + ~DonutsUI() override; + + // Instantiates the implementor of the mojom::PageHandlerFactory mojo + // interface passing the pending receiver that will be internally bound. + void BindInterface( + mojo::PendingReceiver<donuts::mojom::PageHandlerFactory> receiver); + + private: + // donuts::mojom::PageHandlerFactory: + void CreatePageHandler( + mojo::PendingRemote<donuts::mojom::Page> page, + mojo::PendingReceiver<donuts::mojom::PageHandler> receiver) override; + + std::unique_ptr<DonutsPageHandler> page_handler_; + + mojo::Receiver<donuts::mojom::PageHandlerFactory> page_factory_receiver_{ + this}; + + WEB_UI_CONTROLLER_TYPE_DECL(); +}; +``` + +**chrome/browser/ui/webui/donuts/donuts_ui.cc** +```c++ +DonutsUI::DonutsUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui, true) { + // Normal constructor steps (e.g. setting up data source) go here. +} + +WEB_UI_CONTROLLER_TYPE_IMPL(DonutsUI) + +DonutsUI::~DonutsUI() = default; + +void DonutsUI::BindInterface( + mojo::PendingReceiver<donuts::mojom::PageHandlerFactory> receiver) { + page_factory_receiver_.reset(); + page_factory_receiver_.Bind(std::move(receiver)); +} + +void DonutsUI::CreatePageHandler( + mojo::PendingRemote<donuts::mojom::Page> page, + mojo::PendingReceiver<donuts::mojom::PageHandler> receiver) { + DCHECK(page); + page_handler_ = std::make_unique<DonutsPageHandler>( + std::move(receiver), std::move(page)); +} +``` + +You also need to register the PageHandlerFactory to your controller in +**chrome/browser/chrome_browser_interface_binders.cc**: +```c++ +RegisterWebUIControllerInterfaceBinder<donuts::mojom::PageHandlerFactory, + DonutsUI>(map); +``` + +#### Using C++ bindings for communication +The WebUI message handler should inherit from the Mojo PageHandler class. + +**chrome/browser/ui/webui/donuts/donuts_page_handler.h** +```c++ +#include "chrome/browser/ui/webui/donuts/donuts.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" + +class DonutsPageHandler : public donuts::mojom::PageHandler { + public: + DonutsPageHandler( + mojo::PendingReceiver<donuts::mojom::PageHandler> receiver, + mojo::PendingRemote<donuts::mojom::Page> page); + + DonutsPageHandler(const DonutsPageHandler&) = delete; + DonutsPageHandler& operator=(const DonutsPageHandler&) = delete; + + ~DonutsPageHandler() override; + + // Triggered by some outside event + void DonutsPageHandler::OnBakingDonutsFinished(uint32_t num_donuts); + + // donuts::mojom::PageHandler: + void StartPilotLight() override; + void BakeDonuts(uint32_t num_donuts) override; + void GetNumberOfDonuts(GetNumberOfDonutsCallback callback) override; +} +``` + +The message handler needs to implement all the methods on the PageHandler +interface. + +**chrome/browser/ui/webui/donuts/donuts_page_handler.cc** +```c++ +DonutsPageHandler::DonutsPageHandler( + mojo::PendingReceiver<donuts::mojom::PageHandler> receiver, + mojo::PendingRemote<donuts::mojom::Page> page) + : receiver_(this, std::move(receiver)), + page_(std::move(page)) { +} + +DonutsPageHandler::~DonutsPageHandler() { + GetOven()->TurnOffGas(); +} + +// Triggered by outside asynchronous event; sends information to the renderer. +void DonutsPageHandler::OnBakingDonutsFinished(uint32_t num_donuts) { + page_->DonutsBaked(num_donuts); +} + +// Triggered by startPilotLight() call in TS. +void DonutsPageHandler::StartPilotLight() { + GetOven()->StartPilotLight(); +} + +// Triggered by bakeDonuts() call in TS. +void DonutsPageHandler::BakeDonuts(int32_t num_donuts) { + GetOven()->BakeDonuts(); +} + +// Triggered by getNumberOfDonuts() call in TS; sends a response back to the +// renderer. +void DonutsPageHandler::GetNumberOfDonuts(GetNumberOfDonutsCallback callback) { + uint32_t result = GetOven()->GetNumberOfDonuts(); + std::move(callback).Run(result); +} +``` + +#### Setting Up TypeScript bindings + +For WebUIs using the `build_webui()` rule, the TypeScript mojo bindings can be +added to the build and served from the root (e.g. +`chrome://donuts/donuts.mojom-webui.js`) by adding the following arguments to +`build_webui()`: + +**chrome/browser/resources/donuts/BUILD.gn** +``` +build_webui("build") { + # ... Other arguments go here + mojo_files_deps = + [ "//chrome/browser/ui/webui/donuts:mojo_bindings_ts__generator" ] + mojo_files = [ + "$root_gen_dir/chrome/browser/ui/webui/donuts/donuts.mojom-webui.ts", + ] + # ... Other arguments can go here +} +``` + +It is often helpful to wrap the TypeScript side of Mojo setup in a BrowserProxy +class: + +**chrome/browser/resources/donuts/browser_proxy.ts** +```js +import {PageCallbackRouter, PageHandlerFactory, PageHandlerInterface, PageHandlerRemote} from './donuts.mojom-webui.js'; + +class BrowserProxy { + callbackRouter: PageCallbackRouter; + handler: PageHandlerInterface; + + constructor() { + this.callbackRouter = new PageCallbackRouter(); + + this.handler = new PageHandlerRemote(); + + const factory = PageHandlerFactory.getRemote(); + factory.createPageHandler( + this.callbackRouter.$.bindNewPipeAndPassRemote(), + (this.handler as PageHandlerRemote).$.bindNewPipeAndPassReceiver()); + } + + static getInstance(): BrowserProxy { + return instance || (instance = new BrowserProxy()); + } + + static setInstance(obj: BrowserProxy) { + instance = obj; + } +} + +let instance: BrowserProxy|null = null; +``` + +#### Using TypeScript bindings for communication +The `callbackRouter` (`PageCallbackRouter`) can be used to add listeners for +asynchronous events sent from the browser. + +The `handler` (`PageHandlerRemote`) can be used to send messages from the +renderer to the browser. For interface methods that require a browser response, +calling the method returns a promise. The promise will be resolved with the +response from the browser. + +**chrome/browser/resources/donuts/donuts.ts** +```js +import {BrowserProxy} from './browser_proxy.js'; + +let numDonutsBaked: number = 0; + +window.onload = function() { + // Other page initialization steps go here + const proxy = BrowserProxy.getInstance(); + // Tells the browser to start the pilot light. + proxy.handler.startPilotLight(); + // Adds a listener for the asynchronous "donutsBaked" event. + proxy.callbackRouter.donutsBaked.addListener( + (numDonuts: number) => { + numDonutsBaked += numDonuts; + }); +}; + +function CheckNumberOfDonuts() { + // Requests the number of donuts from the browser, and alerts with the + // response. + BrowserProxy.getInstance().handler.getNumberOfDonuts().then( + (numDonuts: number) => { + alert('Yay, there are ' + numDonuts + ' delicious donuts left!'); + }); +} + +function BakeDonuts(numDonuts: number) { + // Tells the browser to bake |numDonuts| donuts. + BrowserProxy.getInstance().handler.bakeDonuts(numDonuts); +} +``` + +### Pre-Mojo alternative: chrome.send()/WebUIMessageHandler +Most Chrome WebUIs were added before the introduction of Mojo, and use the +older style WebUIMessageHandler + chrome.send() pattern. The following sections +detail the methods in WebUIMessageHandler and the corresponding communication +methods in TypeScript/JavaScript and how to use them. + +#### WebUIMessageHandler::AllowJavascript() A tab that has been used for settings UI may be reloaded, or may navigate to an external origin. In both cases, one does not want callbacks from C++ to @@ -474,7 +775,7 @@ custom <code>'initialized'</code> message is often necessary. </div> -### WebUIMessageHandler::CallJavascriptFunction() +#### WebUIMessageHandler::CallJavascriptFunction() When the browser process needs to tell the renderer/JS of an event or otherwise execute code, it can use `CallJavascriptFunction()`. @@ -519,7 +820,7 @@ when Javascript requires a response to an inquiry about C++-canonical state (i.e. "Is Autofill enabled?", "Is the user incognito?") -### WebUIMessageHandler::FireWebUIListener() +#### WebUIMessageHandler::FireWebUIListener() `FireWebUIListener()` is used to notify a registered set of listeners that an event has occurred. This is generally used for events that are not guaranteed to @@ -547,7 +848,7 @@ [`sendWithPromise()`](#sendWithPromise) and [`ResolveJavascriptCallback`](#ResolveJavascriptCallback). -### WebUIMessageHandler::OnJavascriptAllowed() +#### WebUIMessageHandler::OnJavascriptAllowed() `OnJavascriptDisallowed()` is a lifecycle method called in response to [`AllowJavascript()`](#AllowJavascript). It is a good place to register @@ -589,7 +890,7 @@ document has loaded enough to signal to the C++ that it's ready to respond to messages. -### WebUIMessageHandler::OnJavascriptDisallowed() +#### WebUIMessageHandler::OnJavascriptDisallowed() `OnJavascriptDisallowed` is a lifecycle method called when it's unclear whether it's safe to send JavaScript messsages to the renderer. @@ -623,7 +924,7 @@ scoped observer that automatically unsubscribes on destruction but can also imperatively unsubscribe in `OnJavascriptDisallowed()`. -### WebUIMessageHandler::RejectJavascriptCallback() +#### WebUIMessageHandler::RejectJavascriptCallback() This method is called in response to [`sendWithPromise()`](#sendWithPromise) to reject the issued Promise. This @@ -654,7 +955,7 @@ See also: [`ResolveJavascriptCallback`](#ResolveJavascriptCallback) -### WebUIMessageHandler::ResolveJavascriptCallback() +#### WebUIMessageHandler::ResolveJavascriptCallback() This method is called in response to [`sendWithPromise()`](#sendWithPromise) to fulfill an issued Promise, @@ -666,7 +967,7 @@ So, given this TypeScript code: ```js -sendWithPromise('bakeDonuts').then(function(numDonutsBaked: number) { +sendWithPromise('bakeDonuts', [5]).then(function(numDonutsBaked: number) { shop.donuts += numDonutsBaked; }); ``` @@ -681,9 +982,7 @@ } ``` -## Renderer (JS) → Browser (C++) - -### chrome.send() +#### chrome.send() When the JavaScript `window` object is created, a renderer is checked for [WebUI bindings](#bindings). @@ -734,7 +1033,7 @@ message_callbacks_.find(message)->second.Run(&args); ``` -### addWebUiListener() +#### addWebUiListener() WebUI listeners are a convenient way for C++ to inform JavaScript of events. @@ -747,7 +1046,7 @@ Adding WebUI listeners creates and inserts a unique ID into a map in JavaScript, just like [sendWithPromise()](#sendWithPromise). -addWebUiListener can be imported from 'chrome://resources/js/cr.m.js'. +addWebUiListener can be imported from 'chrome://resources/js/cr.js'. ```js // addWebUiListener(): @@ -785,7 +1084,7 @@ }); ``` -### sendWithPromise() +#### sendWithPromise() `sendWithPromise()` is a wrapper around `chrome.send()`. It's used when triggering a message requires a response:
diff --git a/extensions/browser/event_router_unittest.cc b/extensions/browser/event_router_unittest.cc index 7fed31b..81b12c6ae 100644 --- a/extensions/browser/event_router_unittest.cc +++ b/extensions/browser/event_router_unittest.cc
@@ -27,7 +27,6 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-blink-forward.h" -using base::DictionaryValue; using base::Value; namespace extensions { @@ -118,13 +117,12 @@ scoped_refptr<const Extension> CreateExtension(bool component, bool persistent) { ExtensionBuilder builder; - std::unique_ptr<base::DictionaryValue> manifest = - std::make_unique<base::DictionaryValue>(); - manifest->SetStringKey("name", "foo"); - manifest->SetStringKey("version", "1.0.0"); - manifest->SetIntKey("manifest_version", 2); - manifest->SetStringPath("background.page", "background.html"); - manifest->SetBoolPath("background.persistent", persistent); + base::Value::Dict manifest; + manifest.Set("name", "foo"); + manifest.Set("version", "1.0.0"); + manifest.Set("manifest_version", 2); + manifest.SetByDottedPath("background.page", "background.html"); + manifest.SetByDottedPath("background.persistent", persistent); builder.SetManifest(std::move(manifest)); if (component) builder.SetLocation(mojom::ManifestLocation::kComponent); @@ -134,11 +132,11 @@ scoped_refptr<const Extension> CreateServiceWorkerExtension() { ExtensionBuilder builder; - auto manifest = std::make_unique<base::DictionaryValue>(); - manifest->SetStringKey("name", "foo"); - manifest->SetStringKey("version", "1.0.0"); - manifest->SetIntKey("manifest_version", 2); - manifest->SetStringPath("background.service_worker", "worker.js"); + base::Value::Dict manifest; + manifest.Set("name", "foo"); + manifest.Set("version", "1.0.0"); + manifest.Set("manifest_version", 2); + manifest.SetByDottedPath("background.service_worker", "worker.js"); builder.SetManifest(std::move(manifest)); return builder.Build(); } @@ -607,7 +605,7 @@ .Set("name", "Test app") .Set("version", "1.0") .Set("manifest_version", 2) - .Build()) + .BuildDict()) .Build(); ExtensionRegistry::Get(browser_context())->AddEnabled(extension); };
diff --git a/extensions/browser/events/lazy_event_dispatch_util.cc b/extensions/browser/events/lazy_event_dispatch_util.cc index d97f2fd..6e289f4f 100644 --- a/extensions/browser/events/lazy_event_dispatch_util.cc +++ b/extensions/browser/events/lazy_event_dispatch_util.cc
@@ -107,16 +107,16 @@ // |pending_on_install_info| currently only contains a version string. Instead // of making the pref hold a plain string, we store it as a dictionary value // so that we can add more stuff to it in the future if necessary. - auto pending_on_install_info = std::make_unique<base::DictionaryValue>(); + base::Value::Dict pending_on_install_info; base::Version previous_version = ExtensionRegistry::Get(browser_context_) ->GetStoredVersion(extension->id()); - pending_on_install_info->SetStringKey(kPrefPreviousVersion, - previous_version.IsValid() - ? previous_version.GetString() - : std::string()); - prefs->UpdateExtensionPref(extension->id(), - kPrefPendingOnInstalledEventDispatchInfo, - std::move(pending_on_install_info)); + pending_on_install_info.Set(kPrefPreviousVersion, + previous_version.IsValid() + ? previous_version.GetString() + : std::string()); + prefs->UpdateExtensionPref( + extension->id(), kPrefPendingOnInstalledEventDispatchInfo, + std::make_unique<base::Value>(std::move(pending_on_install_info))); } } // namespace extensions
diff --git a/extensions/browser/extension_action_manager_unittest.cc b/extensions/browser/extension_action_manager_unittest.cc index d4b96ba..bd64547 100644 --- a/extensions/browser/extension_action_manager_unittest.cc +++ b/extensions/browser/extension_action_manager_unittest.cc
@@ -62,9 +62,9 @@ .SetManifestKey("icons", DictionaryBuilder() .Set("48", "icon48.png") .Set("128", "icon128.png") - .Build()) + .BuildDict()) .SetManifestKey(ActionInfo::GetManifestKeyForActionType(GetParam()), - std::make_unique<base::DictionaryValue>()) + base::Value::Dict()) .Build(); ASSERT_TRUE(extension); @@ -84,7 +84,7 @@ scoped_refptr<const Extension> extension = ExtensionBuilder("Test Extension") .SetManifestKey(ActionInfo::GetManifestKeyForActionType(GetParam()), - std::make_unique<base::DictionaryValue>()) + base::Value::Dict()) .Build(); ASSERT_TRUE(extension); @@ -102,15 +102,15 @@ TEST_P(ExtensionActionManagerTest, TestDontOverrideIfDefaultsProvided) { scoped_refptr<const Extension> extension = ExtensionBuilder("Test Extension") - .SetManifestKey("icons", - DictionaryBuilder().Set("24", "icon24.png").Build()) + .SetManifestKey( + "icons", DictionaryBuilder().Set("24", "icon24.png").BuildDict()) .SetManifestKey( ActionInfo::GetManifestKeyForActionType(GetParam()), DictionaryBuilder() .Set("default_icon", - DictionaryBuilder().Set("19", "icon19.png").Build()) + DictionaryBuilder().Set("19", "icon19.png").BuildDict()) .Set("default_title", "Action!") - .Build()) + .BuildDict()) .Build(); ASSERT_TRUE(extension);
diff --git a/extensions/browser/extension_creator.cc b/extensions/browser/extension_creator.cc index de7b816..7cfe286 100644 --- a/extensions/browser/extension_creator.cc +++ b/extensions/browser/extension_creator.cc
@@ -107,9 +107,6 @@ if (run_flags & kRequireModernManifestVersion) create_flags |= Extension::REQUIRE_MODERN_MANIFEST_VERSION; - if (run_flags & kBookmarkApp) - create_flags |= Extension::FROM_BOOKMARK; - scoped_refptr<Extension> extension(file_util::LoadExtension( extension_dir, extension_id, run_flags & kSystemApp ? mojom::ManifestLocation::kExternalComponent
diff --git a/extensions/browser/extension_creator.h b/extensions/browser/extension_creator.h index afc95f4..234a2392 100644 --- a/extensions/browser/extension_creator.h +++ b/extensions/browser/extension_creator.h
@@ -40,7 +40,8 @@ kNoRunFlags = 0, kOverwriteCRX = 1 << 0, kRequireModernManifestVersion = 1 << 1, - kBookmarkApp = 1 << 2, + // DEPRECATED. + // kBookmarkApp = 1 << 2, kSystemApp = 1 << 3, };
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index 9bdacd5..a151352 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -2180,8 +2180,6 @@ MigrateToNewExternalUninstallPref(); - MigrateYoutubeOffBookmarkApps(); - MigrateDeprecatedDisableReasons(); } @@ -2518,23 +2516,6 @@ } } -void ExtensionPrefs::MigrateYoutubeOffBookmarkApps() { - const base::Value::Dict& extensions_dictionary = - prefs_->GetDict(pref_names::kExtensions); - const base::Value::Dict* youtube_dictionary = - extensions_dictionary.FindDict(extension_misc::kYoutubeAppId); - if (!youtube_dictionary) { - return; - } - int creation_flags = - youtube_dictionary->FindInt(kPrefCreationFlags).value_or(0); - if ((creation_flags & Extension::FROM_BOOKMARK) == 0) - return; - ScopedExtensionPrefUpdate update(prefs_, extension_misc::kYoutubeAppId); - creation_flags &= ~Extension::FROM_BOOKMARK; - update->SetInteger(kPrefCreationFlags, creation_flags); -} - void ExtensionPrefs::MigrateObsoleteExtensionPrefs() { const base::Value::Dict& extensions_dictionary = prefs_->GetDict(pref_names::kExtensions);
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h index 77059027..dfca56a 100644 --- a/extensions/browser/extension_prefs.h +++ b/extensions/browser/extension_prefs.h
@@ -752,11 +752,6 @@ // TODO(archanasimha): Remove this around M89. void MigrateDeprecatedDisableReasons(); - // Looks to see if the Youtube extension is installed, and removes the - // FROM_BOOKMARK flag from it's creation flags. - // TODO(dmurph): Remove this in m90. - void MigrateYoutubeOffBookmarkApps(); - // Iterates over the extension pref entries and removes any obsolete keys. We // need to do this here specially (rather than in // MigrateObsoleteProfilePrefs()) because these entries are subkeys of the
diff --git a/extensions/browser/file_highlighter.cc b/extensions/browser/file_highlighter.cc index c4dc097..d31e6621 100644 --- a/extensions/browser/file_highlighter.cc +++ b/extensions/browser/file_highlighter.cc
@@ -6,17 +6,11 @@ #include "base/check_op.h" #include "base/containers/stack.h" -#include "base/values.h" namespace extensions { namespace { -// Keys for a highlighted dictionary. -const char kBeforeHighlightKey[] = "beforeHighlight"; -const char kHighlightKey[] = "highlight"; -const char kAfterHighlightKey[] = "afterHighlight"; - // Increment |index| to the position of the next quote ('"') in |str|, skipping // over any escaped quotes. If no next quote is found, |index| is set to // std::string::npos. Assumes |index| currently points to a quote. @@ -113,20 +107,6 @@ return contents_.substr(end_); } -void FileHighlighter::SetHighlightedRegions(base::DictionaryValue* dict) const { - std::string before_feature = GetBeforeFeature(); - if (!before_feature.empty()) - dict->SetStringKey(kBeforeHighlightKey, before_feature); - - std::string feature = GetFeature(); - if (!feature.empty()) - dict->SetStringKey(kHighlightKey, feature); - - std::string after_feature = GetAfterFeature(); - if (!after_feature.empty()) - dict->SetStringKey(kAfterHighlightKey, after_feature); -} - ManifestHighlighter::ManifestHighlighter(const std::string& manifest, const std::string& key, const std::string& specific)
diff --git a/extensions/browser/file_highlighter.h b/extensions/browser/file_highlighter.h index b7c39c8..bfd2e4baf 100644 --- a/extensions/browser/file_highlighter.h +++ b/extensions/browser/file_highlighter.h
@@ -9,10 +9,6 @@ #include <string> -namespace base { -class DictionaryValue; -} - namespace extensions { // The FileHighlighter class is used in order to isolate and highlight a portion @@ -39,10 +35,6 @@ // after the feature. std::string GetAfterFeature() const; - // Populate a DictionaryValue with the highlighted portions (in UTF16) of the - // source file. - void SetHighlightedRegions(base::DictionaryValue* dict) const; - protected: explicit FileHighlighter(const std::string& contents);
diff --git a/extensions/browser/file_highlighter_fuzzer.cc b/extensions/browser/file_highlighter_fuzzer.cc index 10d2223..a95b316c 100644 --- a/extensions/browser/file_highlighter_fuzzer.cc +++ b/extensions/browser/file_highlighter_fuzzer.cc
@@ -34,11 +34,6 @@ CHECK_EQ(highlighter->GetBeforeFeature() + highlighter->GetFeature() + highlighter->GetAfterFeature(), contents); - if (base::IsStringUTF8(contents)) { - // `base::Value` only supports valid UTF-8 strings. - base::DictionaryValue dict; - highlighter->SetHighlightedRegions(&dict); - } return 0; }
diff --git a/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc b/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc index f72bdeb..ae215773 100644 --- a/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc +++ b/extensions/browser/guest_view/web_view/javascript_dialog_helper.cc
@@ -51,18 +51,18 @@ const std::u16string& default_prompt_text, DialogClosedCallback callback, bool* did_suppress_message) { - base::DictionaryValue request_info; - request_info.SetStringKey(webview::kDefaultPromptText, default_prompt_text); - request_info.SetStringKey(webview::kMessageText, message_text); - request_info.SetStringKey(webview::kMessageType, - JavaScriptDialogTypeToString(dialog_type)); - request_info.SetStringKey(guest_view::kUrl, - render_frame_host->GetLastCommittedURL().spec()); + base::Value::Dict request_info; + request_info.Set(webview::kDefaultPromptText, default_prompt_text); + request_info.Set(webview::kMessageText, message_text); + request_info.Set(webview::kMessageType, + JavaScriptDialogTypeToString(dialog_type)); + request_info.Set(guest_view::kUrl, + render_frame_host->GetLastCommittedURL().spec()); WebViewPermissionHelper* web_view_permission_helper = web_view_guest_->web_view_permission_helper(); web_view_permission_helper->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG, request_info, + WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG, std::move(request_info), base::BindOnce(&JavaScriptDialogHelper::OnPermissionResponse, weak_factory_.GetWeakPtr(), std::move(callback)), false /* allowed_by_default */);
diff --git a/extensions/browser/guest_view/web_view/web_view_guest.cc b/extensions/browser/guest_view/web_view/web_view_guest.cc index 2ab1953e..91d5e3cb 100644 --- a/extensions/browser/guest_view/web_view/web_view_guest.cc +++ b/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -1431,12 +1431,12 @@ content::RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) { // Ask the embedder for permission. - base::DictionaryValue request_info; + base::Value::Dict request_info; const GURL& origin = requesting_frame->GetLastCommittedURL().DeprecatedGetOriginAsURL(); - request_info.SetStringKey(webview::kOrigin, origin.spec()); + request_info.Set(webview::kOrigin, origin.spec()); web_view_permission_helper_->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_FULLSCREEN, request_info, + WEB_VIEW_PERMISSION_TYPE_FULLSCREEN, std::move(request_info), base::BindOnce(&WebViewGuest::OnFullscreenPermissionDecided, weak_ptr_factory_.GetWeakPtr()), false /* allowed_by_default */); @@ -1540,23 +1540,23 @@ const int guest_instance_id = new_guest->guest_instance_id(); - base::DictionaryValue request_info; - request_info.SetIntKey(webview::kInitialHeight, initial_bounds.height()); - request_info.SetIntKey(webview::kInitialWidth, initial_bounds.width()); - request_info.SetStringKey(webview::kTargetURL, new_window_info.url.spec()); - request_info.SetStringKey(webview::kName, new_window_info.name); - request_info.SetIntKey(webview::kWindowID, guest_instance_id); + base::Value::Dict request_info; + request_info.Set(webview::kInitialHeight, initial_bounds.height()); + request_info.Set(webview::kInitialWidth, initial_bounds.width()); + request_info.Set(webview::kTargetURL, new_window_info.url.spec()); + request_info.Set(webview::kName, new_window_info.name); + request_info.Set(webview::kWindowID, guest_instance_id); // We pass in partition info so that window-s created through newwindow // API can use it to set their partition attribute. - request_info.SetStringKey(webview::kStoragePartitionId, storage_partition_id); - request_info.SetStringKey(webview::kWindowOpenDisposition, - WindowOpenDispositionToString(disposition)); + request_info.Set(webview::kStoragePartitionId, storage_partition_id); + request_info.Set(webview::kWindowOpenDisposition, + WindowOpenDispositionToString(disposition)); GuestViewManager::FromBrowserContext(browser_context()) ->ManageOwnership(std::move(new_guest)); web_view_permission_helper_->RequestPermission( - WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW, request_info, + WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW, std::move(request_info), base::BindOnce(&WebViewGuest::OnWebViewNewWindowResponse, weak_ptr_factory_.GetWeakPtr(), guest_instance_id), false /* allowed_by_default */);
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc index 8fd08e8..55b5d03 100644 --- a/extensions/browser/guest_view/web_view/web_view_permission_helper.cc +++ b/extensions/browser/guest_view/web_view/web_view_permission_helper.cc
@@ -179,10 +179,10 @@ content::WebContents* source, const content::MediaStreamRequest& request, content::MediaResponseCallback callback) { - base::DictionaryValue request_info; - request_info.SetStringKey(guest_view::kUrl, request.security_origin.spec()); + base::Value::Dict request_info; + request_info.Set(guest_view::kUrl, request.security_origin.spec()); RequestPermission( - WEB_VIEW_PERMISSION_TYPE_MEDIA, request_info, + WEB_VIEW_PERMISSION_TYPE_MEDIA, std::move(request_info), base::BindOnce(&WebViewPermissionHelper::OnMediaPermissionResponse, weak_factory_.GetWeakPtr(), request, std::move(callback)), default_media_access_permission_); @@ -266,7 +266,7 @@ int WebViewPermissionHelper::RequestPermission( WebViewPermissionType permission_type, - const base::DictionaryValue& request_info, + base::Value::Dict request_info, PermissionResponseCallback callback, bool allowed_by_default) { // If there are too many pending permission requests then reject this request. @@ -286,7 +286,7 @@ pending_permission_requests_[request_id] = PermissionResponseInfo( std::move(callback), permission_type, allowed_by_default); base::Value::Dict args; - args.Set(webview::kRequestInfo, request_info.Clone()); + args.Set(webview::kRequestInfo, std::move(request_info)); args.Set(webview::kRequestId, request_id); switch (permission_type) { case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW: {
diff --git a/extensions/browser/guest_view/web_view/web_view_permission_helper.h b/extensions/browser/guest_view/web_view/web_view_permission_helper.h index 98d2e40..2c08f89 100644 --- a/extensions/browser/guest_view/web_view/web_view_permission_helper.h +++ b/extensions/browser/guest_view/web_view/web_view_permission_helper.h
@@ -10,6 +10,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/values.h" #include "components/guest_view/common/guest_view_constants.h" #include "content/public/browser/media_stream_request.h" #include "content/public/browser/web_contents.h" @@ -17,10 +18,6 @@ #include "ppapi/buildflags/buildflags.h" #include "third_party/blink/public/common/mediastream/media_stream_request.h" -namespace base { -class DictionaryValue; -} - namespace extensions { class WebViewGuest; @@ -58,7 +55,7 @@ using RequestMap = std::map<int, PermissionResponseInfo>; int RequestPermission(WebViewPermissionType permission_type, - const base::DictionaryValue& request_info, + base::Value::Dict request_info, PermissionResponseCallback callback, bool allowed_by_default);
diff --git a/extensions/browser/renderer_startup_helper_unittest.cc b/extensions/browser/renderer_startup_helper_unittest.cc index 76b629c..9c9a036 100644 --- a/extensions/browser/renderer_startup_helper_unittest.cc +++ b/extensions/browser/renderer_startup_helper_unittest.cc
@@ -206,44 +206,43 @@ } scoped_refptr<const Extension> CreateExtension(const std::string& id_input) { - std::unique_ptr<base::DictionaryValue> manifest = - DictionaryBuilder() - .Set("name", "extension") - .Set("description", "an extension") - .Set("manifest_version", 2) - .Set("version", "0.1") - .Build(); + base::Value::Dict manifest = DictionaryBuilder() + .Set("name", "extension") + .Set("description", "an extension") + .Set("manifest_version", 2) + .Set("version", "0.1") + .BuildDict(); return CreateExtension(id_input, std::move(manifest)); } scoped_refptr<const Extension> CreateTheme(const std::string& id_input) { - std::unique_ptr<base::DictionaryValue> manifest = + base::Value::Dict manifest = DictionaryBuilder() .Set("name", "theme") .Set("description", "a theme") - .Set("theme", DictionaryBuilder().Build()) + .Set("theme", DictionaryBuilder().BuildDict()) .Set("manifest_version", 2) .Set("version", "0.1") - .Build(); + .BuildDict(); return CreateExtension(id_input, std::move(manifest)); } scoped_refptr<const Extension> CreatePlatformApp( const std::string& id_input) { - std::unique_ptr<base::Value> background = + base::Value::Dict background = DictionaryBuilder() - .Set("scripts", ListBuilder().Append("background.js").Build()) - .Build(); - std::unique_ptr<base::DictionaryValue> manifest = + .Set("scripts", ListBuilder().Append("background.js").BuildList()) + .BuildDict(); + base::Value::Dict manifest = DictionaryBuilder() .Set("name", "platform_app") .Set("description", "a platform app") .Set("app", DictionaryBuilder() .Set("background", std::move(background)) - .Build()) + .BuildDict()) .Set("manifest_version", 2) .Set("version", "0.1") - .Build(); + .BuildDict(); return CreateExtension(id_input, std::move(manifest)); } @@ -284,9 +283,8 @@ scoped_refptr<const Extension> extension_; private: - scoped_refptr<const Extension> CreateExtension( - const std::string& id_input, - std::unique_ptr<base::DictionaryValue> manifest) { + scoped_refptr<const Extension> CreateExtension(const std::string& id_input, + base::Value::Dict manifest) { return ExtensionBuilder() .SetManifest(std::move(manifest)) .SetID(crx_file::id_util::GenerateId(id_input))
diff --git a/extensions/browser/service_worker_task_queue.cc b/extensions/browser/service_worker_task_queue.cc index dc7c77b..32ee2d7 100644 --- a/extensions/browser/service_worker_task_queue.cc +++ b/extensions/browser/service_worker_task_queue.cc
@@ -602,11 +602,11 @@ if (browser_context_->IsOffTheRecord()) { off_the_record_registrations_[extension_id] = version; } else { - auto info = std::make_unique<base::DictionaryValue>(); - info->SetStringKey(kServiceWorkerVersion, version.GetString()); + base::Value::Dict info; + info.Set(kServiceWorkerVersion, version.GetString()); ExtensionPrefs::Get(browser_context_) ->UpdateExtensionPref(extension_id, kPrefServiceWorkerRegistrationInfo, - std::move(info)); + std::make_unique<base::Value>(std::move(info))); } }
diff --git a/extensions/common/api/bluetooth/bluetooth_manifest_data.cc b/extensions/common/api/bluetooth/bluetooth_manifest_data.cc index e88b9f1..fc76abf 100644 --- a/extensions/common/api/bluetooth/bluetooth_manifest_data.cc +++ b/extensions/common/api/bluetooth/bluetooth_manifest_data.cc
@@ -18,7 +18,7 @@ DCHECK(permission_); } -BluetoothManifestData::~BluetoothManifestData() {} +BluetoothManifestData::~BluetoothManifestData() = default; // static BluetoothManifestData* BluetoothManifestData::Get(const Extension* extension) { @@ -72,6 +72,6 @@ const std::string& uuid) : uuid(uuid) {} -BluetoothPermissionRequest::~BluetoothPermissionRequest() {} +BluetoothPermissionRequest::~BluetoothPermissionRequest() = default; } // namespace extensions
diff --git a/extensions/common/api/extension_action/action_info.cc b/extensions/common/api/extension_action/action_info.cc index 1c629a72a..dfdf0656 100644 --- a/extensions/common/api/extension_action/action_info.cc +++ b/extensions/common/api/extension_action/action_info.cc
@@ -37,7 +37,7 @@ ActionInfoData::ActionInfoData(std::unique_ptr<ActionInfo> info) : action_info(std::move(info)) {} -ActionInfoData::~ActionInfoData() {} +ActionInfoData::~ActionInfoData() = default; } // namespace
diff --git a/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc b/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc index c4c2110c..648fe24 100644 --- a/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc +++ b/extensions/common/api/printer_provider/usb_printer_manifest_unittest.cc
@@ -4,15 +4,14 @@ #include "extensions/common/api/printer_provider/usb_printer_manifest_data.h" #include "extensions/common/manifest_test.h" -#include "extensions/common/value_builder.h" #include "services/device/public/mojom/usb_enumeration_options.mojom.h" namespace extensions { class UsbPrinterManifestTest : public ManifestTest { public: - UsbPrinterManifestTest() {} - ~UsbPrinterManifestTest() override {} + UsbPrinterManifestTest() = default; + ~UsbPrinterManifestTest() override = default; }; TEST_F(UsbPrinterManifestTest, Filters) {
diff --git a/extensions/common/api/sockets/sockets_manifest_handler.cc b/extensions/common/api/sockets/sockets_manifest_handler.cc index 4a57436d..fa18aa4 100644 --- a/extensions/common/api/sockets/sockets_manifest_handler.cc +++ b/extensions/common/api/sockets/sockets_manifest_handler.cc
@@ -11,9 +11,9 @@ namespace extensions { -SocketsManifestHandler::SocketsManifestHandler() {} +SocketsManifestHandler::SocketsManifestHandler() = default; -SocketsManifestHandler::~SocketsManifestHandler() {} +SocketsManifestHandler::~SocketsManifestHandler() = default; bool SocketsManifestHandler::Parse(Extension* extension, std::u16string* error) {
diff --git a/extensions/common/command.cc b/extensions/common/command.cc index 08dcb30..df15399 100644 --- a/extensions/common/command.cc +++ b/extensions/common/command.cc
@@ -270,7 +270,7 @@ Command::Command(const Command& other) = default; -Command::~Command() {} +Command::~Command() = default; // static std::string Command::CommandPlatform() {
diff --git a/extensions/common/core_extensions_api_provider.cc b/extensions/common/core_extensions_api_provider.cc index 3f58613..ccead91 100644 --- a/extensions/common/core_extensions_api_provider.cc +++ b/extensions/common/core_extensions_api_provider.cc
@@ -17,7 +17,7 @@ namespace extensions { -CoreExtensionsAPIProvider::CoreExtensionsAPIProvider() {} +CoreExtensionsAPIProvider::CoreExtensionsAPIProvider() = default; CoreExtensionsAPIProvider::~CoreExtensionsAPIProvider() = default; void CoreExtensionsAPIProvider::AddAPIFeatures(FeatureProvider* provider) {
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index df8bc5b..48f57d8 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc
@@ -254,12 +254,6 @@ return nullptr; } - if ((flags & FROM_BOOKMARK) != 0) { - // Extension-based bookmark apps are no longer supported. - // They have been replaced by web apps. - return nullptr; - } - std::unique_ptr<extensions::Manifest> manifest; if (flags & FOR_LOGIN_SCREEN) { manifest = Manifest::CreateManifestForLoginScreen(location, value.Clone(), @@ -864,6 +858,6 @@ extension_manifest = std::make_unique<base::Value::Dict>(manifest->Clone()); } -ExtensionInfo::~ExtensionInfo() {} +ExtensionInfo::~ExtensionInfo() = default; } // namespace extensions
diff --git a/extensions/common/extension.h b/extensions/common/extension.h index 91698320..e4d1e08 100644 --- a/extensions/common/extension.h +++ b/extensions/common/extension.h
@@ -95,10 +95,11 @@ // Chrome Web Store. FROM_WEBSTORE = 1 << 3, - // |FROM_BOOKMARK| indicates the extension is a bookmark app which has been - // generated from a web page. Bookmark apps have no permissions or extent - // and launch the web page they are created from when run. - FROM_BOOKMARK = 1 << 4, + // DEPRECATED - |FROM_BOOKMARK| indicates the extension is a bookmark app + // which has been generated from a web page. Bookmark apps have no + // permissions or extent and launch the web page they are created from when + // run. + // FROM_BOOKMARK = 1 << 4, // |FOLLOW_SYMLINKS_ANYWHERE| means that resources can be symlinks to // anywhere in the filesystem, rather than being restricted to the @@ -311,11 +312,6 @@ } int creation_flags() const { return creation_flags_; } bool from_webstore() const { return (creation_flags_ & FROM_WEBSTORE) != 0; } - // TODO(crbug.com/1065748): Retire this function when there are no old - // entries. - bool from_deprecated_bookmark() const { - return (creation_flags_ & FROM_BOOKMARK) != 0; - } bool may_be_untrusted() const { return (creation_flags_ & MAY_BE_UNTRUSTED) != 0; }
diff --git a/extensions/common/extension_builder.cc b/extensions/common/extension_builder.cc index bc9b698..3ef1ddf 100644 --- a/extensions/common/extension_builder.cc +++ b/extensions/common/extension_builder.cc
@@ -131,7 +131,7 @@ manifest_data_->type = type; } -ExtensionBuilder::~ExtensionBuilder() {} +ExtensionBuilder::~ExtensionBuilder() = default; ExtensionBuilder::ExtensionBuilder(ExtensionBuilder&& other) = default; ExtensionBuilder& ExtensionBuilder::operator=(ExtensionBuilder&& other) =
diff --git a/extensions/common/extension_icon_set.cc b/extensions/common/extension_icon_set.cc index e5dcaef..5bf4ccd 100644 --- a/extensions/common/extension_icon_set.cc +++ b/extensions/common/extension_icon_set.cc
@@ -10,11 +10,11 @@ #include "base/files/file_path.h" #include "base/strings/string_util.h" -ExtensionIconSet::ExtensionIconSet() {} +ExtensionIconSet::ExtensionIconSet() = default; ExtensionIconSet::ExtensionIconSet(const ExtensionIconSet& other) = default; -ExtensionIconSet::~ExtensionIconSet() {} +ExtensionIconSet::~ExtensionIconSet() = default; void ExtensionIconSet::Clear() { map_.clear();
diff --git a/extensions/common/features/feature.cc b/extensions/common/features/feature.cc index 47b67bd..0a5be7d 100644 --- a/extensions/common/features/feature.cc +++ b/extensions/common/features/feature.cc
@@ -48,7 +48,7 @@ Feature::Feature() : no_parent_(false) {} -Feature::~Feature() {} +Feature::~Feature() = default; void Feature::set_name(base::StringPiece name) { name_ = std::string(name);
diff --git a/extensions/common/manifest_handlers/extension_action_handler.cc b/extensions/common/manifest_handlers/extension_action_handler.cc index aa0dee4..7f052a8 100644 --- a/extensions/common/manifest_handlers/extension_action_handler.cc +++ b/extensions/common/manifest_handlers/extension_action_handler.cc
@@ -45,7 +45,7 @@ ExtensionActionHandler::ExtensionActionHandler() = default; -ExtensionActionHandler::~ExtensionActionHandler() {} +ExtensionActionHandler::~ExtensionActionHandler() = default; bool ExtensionActionHandler::Parse(Extension* extension, std::u16string* error) {
diff --git a/extensions/common/manifest_handlers/extension_action_handler_unittest.cc b/extensions/common/manifest_handlers/extension_action_handler_unittest.cc index f0b7d45b..c710e49 100644 --- a/extensions/common/manifest_handlers/extension_action_handler_unittest.cc +++ b/extensions/common/manifest_handlers/extension_action_handler_unittest.cc
@@ -140,13 +140,13 @@ : public ManifestTest, public testing::WithParamInterface<ActionInfo::Type> { public: - ExtensionActionManifestTest() {} + ExtensionActionManifestTest() = default; ExtensionActionManifestTest(const ExtensionActionManifestTest&) = delete; ExtensionActionManifestTest& operator=(const ExtensionActionManifestTest&) = delete; - ~ExtensionActionManifestTest() override {} + ~ExtensionActionManifestTest() override = default; // Constructs and returns a ManifestData object with the provided // |action_spec|.
diff --git a/extensions/common/manifest_handlers/externally_connectable_unittest.cc b/extensions/common/manifest_handlers/externally_connectable_unittest.cc index 2312964..c45559a 100644 --- a/extensions/common/manifest_handlers/externally_connectable_unittest.cc +++ b/extensions/common/manifest_handlers/externally_connectable_unittest.cc
@@ -23,8 +23,8 @@ class ExternallyConnectableTest : public ManifestTest { public: - ExternallyConnectableTest() {} - ~ExternallyConnectableTest() override {} + ExternallyConnectableTest() = default; + ~ExternallyConnectableTest() override = default; protected: ExternallyConnectableInfo* GetExternallyConnectableInfo(
diff --git a/extensions/common/manifest_test.cc b/extensions/common/manifest_test.cc index 74a8527..b0ea918 100644 --- a/extensions/common/manifest_test.cc +++ b/extensions/common/manifest_test.cc
@@ -69,8 +69,7 @@ : enable_apps_(true) { } -ManifestTest::~ManifestTest() { -} +ManifestTest::~ManifestTest() = default; // Helper class that simplifies creating methods that take either a filename // to a manifest or the manifest itself. @@ -82,6 +81,14 @@ : name_(name), manifest_(std::move(manifest)) { CHECK(manifest_.is_dict()) << "Manifest must be a dictionary. " << name_; } + +ManifestTest::ManifestData::ManifestData(base::Value::Dict manifest, + base::StringPiece name) + : ManifestData(base::Value(std::move(manifest)), std::move(name)) {} + +ManifestTest::ManifestData::ManifestData(base::Value::Dict manifest) + : ManifestData(base::Value(std::move(manifest))) {} + ManifestTest::ManifestData::ManifestData(base::Value manifest) : name_(GetNameFromManifest(manifest)), manifest_(std::move(manifest)) { CHECK(manifest_.is_dict()) << "Manifest must be a dictionary.";
diff --git a/extensions/common/manifest_test.h b/extensions/common/manifest_test.h index eff2c07..02c8c6cb5 100644 --- a/extensions/common/manifest_test.h +++ b/extensions/common/manifest_test.h
@@ -39,8 +39,12 @@ class ManifestData { public: explicit ManifestData(base::StringPiece name); + // This is deprecated. Use the constructor that accepts base::Value::Dict. explicit ManifestData(base::Value manifest); + explicit ManifestData(base::Value::Dict manifest); + // This is deprecated. Use the constructor that accepts base::Value::Dict. ManifestData(base::Value manifest, base::StringPiece name); + ManifestData(base::Value::Dict manifest, base::StringPiece name); ManifestData(ManifestData&& other); ~ManifestData();
diff --git a/extensions/common/mojom/permission_set_mojom_traits_unittest.cc b/extensions/common/mojom/permission_set_mojom_traits_unittest.cc index a75a2e4..dbc240d 100644 --- a/extensions/common/mojom/permission_set_mojom_traits_unittest.cc +++ b/extensions/common/mojom/permission_set_mojom_traits_unittest.cc
@@ -19,10 +19,10 @@ class MockManifestHandler : public ManifestHandler { public: - MockManifestHandler() {} + MockManifestHandler() = default; MockManifestHandler(const MockManifestHandler&) = delete; MockManifestHandler& operator=(const MockManifestHandler&) = delete; - ~MockManifestHandler() override {} + ~MockManifestHandler() override = default; bool Parse(Extension* extension, std::u16string* error) override { return true;
diff --git a/extensions/common/permissions/manifest_permission.cc b/extensions/common/permissions/manifest_permission.cc index 0e69e351..e54e7ba 100644 --- a/extensions/common/permissions/manifest_permission.cc +++ b/extensions/common/permissions/manifest_permission.cc
@@ -6,9 +6,9 @@ namespace extensions { -ManifestPermission::ManifestPermission() {} +ManifestPermission::ManifestPermission() = default; -ManifestPermission::~ManifestPermission() { } +ManifestPermission::~ManifestPermission() = default; std::unique_ptr<ManifestPermission> ManifestPermission::Clone() const { return Union(this);
diff --git a/extensions/common/permissions/permission_set.cc b/extensions/common/permissions/permission_set.cc index 9deb51b..5ecd79e 100644 --- a/extensions/common/permissions/permission_set.cc +++ b/extensions/common/permissions/permission_set.cc
@@ -17,7 +17,7 @@ namespace extensions { -PermissionSet::PermissionSet() {} +PermissionSet::PermissionSet() = default; PermissionSet::PermissionSet(APIPermissionSet apis, ManifestPermissionSet manifest_permissions, URLPatternSet explicit_hosts,
diff --git a/extensions/common/permissions/usb_device_permission_data.cc b/extensions/common/permissions/usb_device_permission_data.cc index 8e7a669cf..337b2f8 100644 --- a/extensions/common/permissions/usb_device_permission_data.cc +++ b/extensions/common/permissions/usb_device_permission_data.cc
@@ -46,7 +46,7 @@ } // namespace -UsbDevicePermissionData::UsbDevicePermissionData() {} +UsbDevicePermissionData::UsbDevicePermissionData() = default; UsbDevicePermissionData::UsbDevicePermissionData(int vendor_id, int product_id,
diff --git a/extensions/common/user_script.cc b/extensions/common/user_script.cc index c7d8d91..2b54cba 100644 --- a/extensions/common/user_script.cc +++ b/extensions/common/user_script.cc
@@ -26,9 +26,10 @@ bool UrlMatchesGlobs(const std::vector<std::string>* globs, const GURL& url) { - for (auto glob = globs->cbegin(); glob != globs->cend(); ++glob) { - if (base::MatchPattern(url.spec(), *glob)) + for (const auto& glob : *globs) { + if (base::MatchPattern(url.spec(), glob)) { return true; + } } return false; @@ -91,7 +92,7 @@ url_(url) { } -UserScript::File::File() {} +UserScript::File::File() = default; // File content is not copied. UserScript::File::File(const File& other)
diff --git a/fuchsia_web/webengine/BUILD.gn b/fuchsia_web/webengine/BUILD.gn index 82203c4..85adb8d9 100644 --- a/fuchsia_web/webengine/BUILD.gn +++ b/fuchsia_web/webengine/BUILD.gn
@@ -317,6 +317,7 @@ "browser/navigation_policy_throttle.h", "browser/theme_manager.cc", "browser/theme_manager.h", + "browser/trace_event.h", "browser/url_request_rewrite_type_converters.cc", "browser/url_request_rewrite_type_converters.h", "browser/web_engine_browser_context.cc",
diff --git a/fuchsia_web/webengine/browser/context_impl.cc b/fuchsia_web/webengine/browser/context_impl.cc index cd63412..921a47f 100644 --- a/fuchsia_web/webengine/browser/context_impl.cc +++ b/fuchsia_web/webengine/browser/context_impl.cc
@@ -15,15 +15,19 @@ #include "base/fuchsia/koid.h" #include "base/fuchsia/mem_buffer_util.h" #include "base/strings/stringprintf.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/typed_macros.h" #include "build/chromecast_buildflags.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "fuchsia_web/webengine/browser/frame_impl.h" +#include "fuchsia_web/webengine/browser/trace_event.h" #include "fuchsia_web/webengine/browser/web_engine_devtools_controller.h" #include "third_party/blink/public/common/web_preferences/web_preferences.h" #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h" +#include "third_party/perfetto/include/perfetto/tracing/track_event_args.h" #if BUILDFLAG(ENABLE_CAST_RECEIVER) #include "components/cast_streaming/browser/public/network_context_getter.h" // nogncheck @@ -40,9 +44,15 @@ base::Unretained(this))) { DCHECK(browser_context_); DCHECK(devtools_controller_); + + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Context created", + perfetto::Flow::FromPointer(this)); } -ContextImpl::~ContextImpl() = default; +ContextImpl::~ContextImpl() { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Context destroyed", + perfetto::TerminatingFlow::FromPointer(this)); +} void ContextImpl::DestroyFrame(FrameImpl* frame) { auto iter = frames_.find(frame); @@ -64,12 +74,21 @@ void ContextImpl::CreateFrame( fidl::InterfaceRequest<fuchsia::web::Frame> frame) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Context.CreateFrame", + perfetto::Flow::FromPointer(this)); + CreateFrameWithParams(fuchsia::web::CreateFrameParams(), std::move(frame)); } void ContextImpl::CreateFrameWithParams( fuchsia::web::CreateFrameParams params, fidl::InterfaceRequest<fuchsia::web::Frame> frame) { + if (!params.IsEmpty()) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Context.CreateFrameWithParams", + perfetto::Flow::FromPointer(this)); + } + // FrameImpl clones the params used to create it when creating popup Frames. // Ensure the params can be cloned to avoid problems when handling popups. // TODO(fxbug.dev/65750): Consider removing this restriction if clients @@ -155,11 +174,18 @@ void ContextImpl::GetCookieManager( fidl::InterfaceRequest<fuchsia::web::CookieManager> request) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Context.GetCookieManager", + perfetto::Flow::FromPointer(this)); + cookie_manager_bindings_.AddBinding(&cookie_manager_, std::move(request)); } void ContextImpl::GetRemoteDebuggingPort( GetRemoteDebuggingPortCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Context.GetRemoteDebuggingPort", + perfetto::Flow::FromPointer(this)); + devtools_controller_->GetDevToolsPort(base::BindOnce( [](GetRemoteDebuggingPortCallback callback, uint16_t port) { if (port == 0) {
diff --git a/fuchsia_web/webengine/browser/frame_impl.cc b/fuchsia_web/webengine/browser/frame_impl.cc index 0cb90a5..1d5e4398 100644 --- a/fuchsia_web/webengine/browser/frame_impl.cc +++ b/fuchsia_web/webengine/browser/frame_impl.cc
@@ -26,6 +26,7 @@ #include "base/task/single_thread_task_runner.h" #include "base/thread_annotations.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "build/chromecast_buildflags.h" #include "content/public/browser/audio_stream_broker.h" #include "content/public/browser/browser_accessibility_state.h" @@ -51,6 +52,7 @@ #include "fuchsia_web/webengine/browser/media_player_impl.h" #include "fuchsia_web/webengine/browser/message_port.h" #include "fuchsia_web/webengine/browser/navigation_policy_handler.h" +#include "fuchsia_web/webengine/browser/trace_event.h" #include "fuchsia_web/webengine/browser/url_request_rewrite_type_converters.h" #include "fuchsia_web/webengine/browser/web_engine_devtools_controller.h" #include "media/mojo/mojom/audio_processing.mojom.h" @@ -66,6 +68,7 @@ #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "third_party/blink/public/mojom/navigation/was_activated_option.mojom.h" +#include "third_party/perfetto/include/perfetto/tracing/track_event_args.h" #include "ui/aura/window.h" #include "ui/compositor/compositor.h" #include "ui/gfx/switches.h" @@ -418,7 +421,7 @@ console_log_tag_(params.has_debug_name() ? params.debug_name() : std::string()), params_for_popups_(std::move(params)), - navigation_controller_(web_contents_.get()), + navigation_controller_(web_contents_.get(), this), permission_controller_(web_contents_.get()), binding_(this, std::move(frame_request)), media_blocker_(web_contents_.get()), @@ -432,6 +435,10 @@ params_for_popups_.debug_name()) : inspect::StringProperty()) { DCHECK(!WebContentsToFrameImplMap()[web_contents_.get()]); + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame created", + perfetto::Flow::FromPointer(context_), + perfetto::Flow::FromPointer(this)); + WebContentsToFrameImplMap()[web_contents_.get()] = this; web_contents_->SetDelegate(this); @@ -451,6 +458,9 @@ } FrameImpl::~FrameImpl() { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame destroyed", + perfetto::TerminatingFlow::FromPointer(this)); + DestroyWindowTreeHost(); context_->devtools_controller()->OnFrameDestroyed(web_contents_.get()); @@ -788,16 +798,28 @@ } void FrameImpl::CreateView(fuchsia::ui::views::ViewToken view_token) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.CreateView", + perfetto::Flow::FromPointer(this)); + auto view_ref_pair = scenic::ViewRefPair::New(); - CreateViewWithViewRef(std::move(view_token), - std::move(view_ref_pair.control_ref), - std::move(view_ref_pair.view_ref)); + CreateViewImpl(std::move(view_token), std::move(view_ref_pair.control_ref), + std::move(view_ref_pair.view_ref)); } void FrameImpl::CreateViewWithViewRef( fuchsia::ui::views::ViewToken view_token, fuchsia::ui::views::ViewRefControl control_ref, fuchsia::ui::views::ViewRef view_ref) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.CreateViewWithViewRef", + perfetto::Flow::FromPointer(this)); + + CreateViewImpl(std::move(view_token), std::move(control_ref), + std::move(view_ref)); +} + +void FrameImpl::CreateViewImpl(fuchsia::ui::views::ViewToken view_token, + fuchsia::ui::views::ViewRefControl control_ref, + fuchsia::ui::views::ViewRef view_ref) { if (IsHeadless()) { LOG(WARNING) << "CreateView() called on a HEADLESS Context."; CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS); @@ -822,6 +844,9 @@ } void FrameImpl::CreateView2(fuchsia::web::CreateView2Args view_args) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.CreateView2", + perfetto::Flow::FromPointer(this)); + if (IsHeadless()) { LOG(WARNING) << "CreateView2() called on a HEADLESS Context."; CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS); @@ -847,6 +872,9 @@ void FrameImpl::GetMediaPlayer( fidl::InterfaceRequest<fuchsia::media::sessions2::Player> player) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.GetMediaPlayer", + perfetto::Flow::FromPointer(this)); + media_player_ = std::make_unique<MediaPlayerImpl>( content::MediaSession::Get(web_contents_.get()), std::move(player), base::BindOnce(&FrameImpl::OnMediaPlayerDisconnect, @@ -855,12 +883,19 @@ void FrameImpl::GetNavigationController( fidl::InterfaceRequest<fuchsia::web::NavigationController> controller) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.GetNavigationController", + perfetto::Flow::FromPointer(this)); + navigation_controller_.AddBinding(std::move(controller)); } void FrameImpl::ExecuteJavaScript(std::vector<std::string> origins, fuchsia::mem::Buffer script, ExecuteJavaScriptCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.ExecuteJavaScript", + perfetto::Flow::FromPointer(this)); + ExecuteJavaScriptInternal(std::move(origins), std::move(script), std::move(callback), true); } @@ -869,6 +904,10 @@ std::vector<std::string> origins, fuchsia::mem::Buffer script, ExecuteJavaScriptNoResultCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.ExecuteJavaScriptNoResult", + perfetto::Flow::FromPointer(this)); + ExecuteJavaScriptInternal( std::move(origins), std::move(script), [callback = std::move(callback)]( @@ -887,6 +926,10 @@ std::vector<std::string> origins, fuchsia::mem::Buffer script, AddBeforeLoadJavaScriptCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.AddBeforeLoadJavaScript", + perfetto::Flow::FromPointer(this)); + if (!context_->IsJavaScriptInjectionAllowed()) { callback(fpromise::error(fuchsia::web::FrameError::INTERNAL_ERROR)); return; @@ -921,12 +964,19 @@ } void FrameImpl::RemoveBeforeLoadJavaScript(uint64_t id) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.RemoveBeforeLoadJavaScript", + perfetto::Flow::FromPointer(this)); + script_injector_.RemoveScript(id); } void FrameImpl::PostMessage(std::string origin, fuchsia::web::WebMessage message, PostMessageCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.PostMessage", + perfetto::Flow::FromPointer(this)); + #if BUILDFLAG(ENABLE_CAST_RECEIVER) if (MaybeHandleCastStreamingMessage(&origin, &message, &callback)) return; @@ -991,14 +1041,24 @@ void FrameImpl::SetNavigationEventListener2( fidl::InterfaceHandle<fuchsia::web::NavigationEventListener> listener, fuchsia::web::NavigationEventListenerFlags flags) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.SetNavigationEventListener", + perfetto::Flow::FromPointer(this)); + navigation_controller_.SetEventListener(std::move(listener), flags); } void FrameImpl::SetJavaScriptLogLevel(fuchsia::web::ConsoleLogLevel level) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.SetJavaScriptLogLevel", + perfetto::Flow::FromPointer(this)); + log_level_ = FuchsiaWebConsoleLogLevelToFxLogSeverity(level); } void FrameImpl::SetConsoleLogSink(fuchsia::logger::LogSinkHandle sink) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.SetConsoleLogSink", + perfetto::Flow::FromPointer(this)); + if (sink) { console_logger_ = base::ScopedFxLogger::CreateFromLogSink( std::move(sink), {console_log_tag_}); @@ -1009,11 +1069,18 @@ void FrameImpl::ConfigureInputTypes(fuchsia::web::InputTypes types, fuchsia::web::AllowInputState allow) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.ConfigureInputTypes", + perfetto::Flow::FromPointer(this)); + event_filter_.ConfigureInputTypes(types, allow); } void FrameImpl::SetPopupFrameCreationListener( fidl::InterfaceHandle<fuchsia::web::PopupFrameCreationListener> listener) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.SetPopupFrameCreationListener", + perfetto::Flow::FromPointer(this)); + popup_listener_ = listener.Bind(); popup_listener_.set_error_handler( fit::bind_member(this, &FrameImpl::OnPopupListenerDisconnected)); @@ -1022,6 +1089,10 @@ void FrameImpl::SetUrlRequestRewriteRules( std::vector<fuchsia::web::UrlRequestRewriteRule> rules, SetUrlRequestRewriteRulesCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.SetUrlRequestRewriteRules", + perfetto::Flow::FromPointer(this)); + auto mojom_rules = mojo::ConvertTo<url_rewrite::mojom::UrlRequestRewriteRulesPtr>( std::move(rules)); @@ -1034,6 +1105,10 @@ } void FrameImpl::EnableHeadlessRendering() { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.EnableHeadlessRendering", + perfetto::Flow::FromPointer(this)); + if (!IsHeadless()) { LOG(ERROR) << "EnableHeadlessRendering() on non-HEADLESS Context."; CloseAndDestroyFrame(ZX_ERR_INVALID_ARGS); @@ -1059,6 +1134,10 @@ } void FrameImpl::DisableHeadlessRendering() { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.DisableHeadlessRendering", + perfetto::Flow::FromPointer(this)); + if (!IsHeadless()) { LOG(ERROR) << "Attempted to disable headless rendering on non-HEADLESS Context."; @@ -1124,6 +1203,9 @@ void FrameImpl::SetMediaSettings( fuchsia::web::FrameMediaSettings media_settings) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.SetMediaSettings", + perfetto::Flow::FromPointer(this)); + media_settings_ = std::move(media_settings); if (media_settings.has_renderer_usage() && set_audio_output_usage_callback_) set_audio_output_usage_callback_.Run(media_settings.renderer_usage()); @@ -1131,6 +1213,10 @@ void FrameImpl::ForceContentDimensions( std::unique_ptr<fuchsia::ui::gfx::vec2> web_dips) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.ForceContentDimensions", + perfetto::Flow::FromPointer(this)); + if (!web_dips) { render_size_override_ = {}; if (layout_manager_) @@ -1154,6 +1240,9 @@ fuchsia::web::PermissionDescriptor fidl_permission, std::string web_origin_string, fuchsia::web::PermissionState fidl_state) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.SetPermissionState", + perfetto::Flow::FromPointer(this)); + if (!fidl_permission.has_type()) { LOG(ERROR) << "PermissionDescriptor.type is not specified in " "SetPermissionState()."; @@ -1190,6 +1279,9 @@ } void FrameImpl::GetPrivateMemorySize(GetPrivateMemorySizeCallback callback) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.GetPrivateMemorySize", + perfetto::Flow::FromPointer(this)); + if (!web_contents_->GetPrimaryMainFrame()->GetProcess()->IsReady()) { // Renderer process is not yet started. callback(0); @@ -1214,12 +1306,20 @@ void FrameImpl::SetNavigationPolicyProvider( fuchsia::web::NavigationPolicyProviderParams params, fidl::InterfaceHandle<fuchsia::web::NavigationPolicyProvider> provider) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.SetNavigationPolicyProvider", + perfetto::Flow::FromPointer(this)); + navigation_policy_handler_ = std::make_unique<NavigationPolicyHandler>( std::move(params), std::move(provider)); } void FrameImpl::SetContentAreaSettings( fuchsia::web::ContentAreaSettings settings) { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.SetContentAreaSettings", + perfetto::Flow::FromPointer(this)); + if (settings.has_hide_scrollbars()) content_area_settings_.set_hide_scrollbars(settings.hide_scrollbars()); if (settings.has_autoplay_policy()) @@ -1245,6 +1345,10 @@ } void FrameImpl::ResetContentAreaSettings() { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/Frame.ResetContentAreaSettings", + perfetto::Flow::FromPointer(this)); + content_area_settings_ = fuchsia::web::ContentAreaSettings(); web_contents_->OnWebPreferencesChanged(); UpdateRenderFrameZoomLevel(web_contents_->GetPrimaryMainFrame()); @@ -1291,6 +1395,9 @@ } void FrameImpl::SetBlockMediaLoading(bool blocked) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/Frame.SetBlockMediaLoading", + perfetto::Flow::FromPointer(this)); + media_blocker_.BlockMediaLoading(blocked); }
diff --git a/fuchsia_web/webengine/browser/frame_impl.h b/fuchsia_web/webengine/browser/frame_impl.h index 8bd7e95..69e45b7 100644 --- a/fuchsia_web/webengine/browser/frame_impl.h +++ b/fuchsia_web/webengine/browser/frame_impl.h
@@ -221,6 +221,11 @@ // |accessibility_bridge_|. void ConnectToAccessibilityBridge(); + // Shared implementation of CreateView and CreateViewWithViewRef. + void CreateViewImpl(fuchsia::ui::views::ViewToken view_token, + fuchsia::ui::views::ViewRefControl control_ref, + fuchsia::ui::views::ViewRef view_ref); + // fuchsia::web::Frame implementation. void CreateView(fuchsia::ui::views::ViewToken view_token) override; void CreateViewWithViewRef(fuchsia::ui::views::ViewToken view_token,
diff --git a/fuchsia_web/webengine/browser/navigation_controller_impl.cc b/fuchsia_web/webengine/browser/navigation_controller_impl.cc index b495690..d83978a 100644 --- a/fuchsia_web/webengine/browser/navigation_controller_impl.cc +++ b/fuchsia_web/webengine/browser/navigation_controller_impl.cc
@@ -13,15 +13,19 @@ #include "base/strings/strcat.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" +#include "base/trace_event/trace_event.h" +#include "base/trace_event/typed_macros.h" #include "components/favicon/content/content_favicon_driver.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "fuchsia_web/common/string_util.h" +#include "fuchsia_web/webengine/browser/trace_event.h" #include "net/base/net_errors.h" #include "net/http/http_util.h" #include "third_party/blink/public/mojom/navigation/was_activated_option.mojom.h" +#include "third_party/perfetto/include/perfetto/tracing/track_event_args.h" #include "third_party/skia/include/core/SkBitmap.h" #include "ui/base/page_transition_types.h" #include "ui/gfx/image/image.h" @@ -132,8 +136,13 @@ } // namespace NavigationControllerImpl::NavigationControllerImpl( - content::WebContents* web_contents) - : web_contents_(web_contents), weak_factory_(this) { + content::WebContents* web_contents, + void* parent_for_trace_flow) + : parent_for_trace_flow_(parent_for_trace_flow), + web_contents_(web_contents), + weak_factory_(this) { + DCHECK(parent_for_trace_flow_); + Observe(web_contents_); } @@ -253,6 +262,14 @@ waiting_for_navigation_event_ack_ = true; + // Note that the events is logged to the parent Frame's flow. + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/NavigationEventListener.OnNavigationStateChanged", + perfetto::Flow::FromPointer(parent_for_trace_flow_), "url", + previous_navigation_state_.url(), "title", + previous_navigation_state_.title().data(), "is_loaded", + is_main_document_loaded_); + // Send the event to the observer and, upon acknowledgement, revisit this // function to send another update. navigation_listener_->OnNavigationStateChanged( @@ -267,6 +284,11 @@ void NavigationControllerImpl::LoadUrl(std::string url, fuchsia::web::LoadUrlParams params, LoadUrlCallback callback) { + // Note that the event is logged to the parent Frame's flow. + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/NavigationController.LoadUrl", + perfetto::Flow::FromPointer(parent_for_trace_flow_), "url", url); + GURL validated_url(url); if (!validated_url.is_valid()) { callback( @@ -310,20 +332,33 @@ } void NavigationControllerImpl::GoBack() { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/NavigationController.GoBack", + perfetto::Flow::FromPointer(parent_for_trace_flow_)); + if (web_contents_->GetController().CanGoBack()) web_contents_->GetController().GoBack(); } void NavigationControllerImpl::GoForward() { + TRACE_EVENT(kWebEngineFidlCategory, + "fuchsia.web/NavigationController.GoForward", + perfetto::Flow::FromPointer(parent_for_trace_flow_)); + if (web_contents_->GetController().CanGoForward()) web_contents_->GetController().GoForward(); } void NavigationControllerImpl::Stop() { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/NavigationController.Stop", + perfetto::Flow::FromPointer(parent_for_trace_flow_)); + web_contents_->Stop(); } void NavigationControllerImpl::Reload(fuchsia::web::ReloadType type) { + TRACE_EVENT(kWebEngineFidlCategory, "fuchsia.web/NavigationController.Reload", + perfetto::Flow::FromPointer(parent_for_trace_flow_)); + content::ReloadType internal_reload_type; switch (type) { case fuchsia::web::ReloadType::PARTIAL_CACHE:
diff --git a/fuchsia_web/webengine/browser/navigation_controller_impl.h b/fuchsia_web/webengine/browser/navigation_controller_impl.h index 996c96f..6c1d99d1 100644 --- a/fuchsia_web/webengine/browser/navigation_controller_impl.h +++ b/fuchsia_web/webengine/browser/navigation_controller_impl.h
@@ -25,7 +25,8 @@ public content::WebContentsObserver, public favicon::FaviconDriverObserver { public: - explicit NavigationControllerImpl(content::WebContents* web_contents); + NavigationControllerImpl(content::WebContents* web_contents, + void* parent_for_trace_flow); NavigationControllerImpl(const NavigationControllerImpl&) = delete; NavigationControllerImpl& operator=(const NavigationControllerImpl&) = delete; @@ -81,6 +82,7 @@ bool icon_url_changed, const gfx::Image& image) override; + const raw_ptr<void> parent_for_trace_flow_; content::WebContents* const web_contents_; // NavigationController client bindings.
diff --git a/fuchsia_web/webengine/browser/trace_event.h b/fuchsia_web/webengine/browser/trace_event.h new file mode 100644 index 0000000..b1785cb --- /dev/null +++ b/fuchsia_web/webengine/browser/trace_event.h
@@ -0,0 +1,13 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FUCHSIA_WEB_WEBENGINE_BROWSER_TRACE_EVENT_H_ +#define FUCHSIA_WEB_WEBENGINE_BROWSER_TRACE_EVENT_H_ + +// The category to use for WebEngine FIDL events. +// The event names should use the convention `namespace`/`interface`.`method`, +// e.g. "fuchsia.web/Frame.CreateView". +inline constexpr char kWebEngineFidlCategory[] = "webengine.fidl"; + +#endif // FUCHSIA_WEB_WEBENGINE_BROWSER_TRACE_EVENT_H_
diff --git a/fuchsia_web/webinstance_host/web_instance_host_internal.cc b/fuchsia_web/webinstance_host/web_instance_host_internal.cc index 94c76ff..58e556b8 100644 --- a/fuchsia_web/webinstance_host/web_instance_host_internal.cc +++ b/fuchsia_web/webinstance_host/web_instance_host_internal.cc
@@ -333,6 +333,10 @@ } #if BUILDFLAG(ENABLE_CAST_RECEIVER) + // Use a constexpr instead of the media::IsClearKey() helper, because of the + // additional dependencies required. + static constexpr char kClearKeyKeySystem[] = "org.w3.clearkey"; + if (enable_playready) { const std::string& key_system = params.playready_key_system(); if (key_system == kWidevineKeySystem || key_system == kClearKeyKeySystem) {
diff --git a/gin/gin_features.cc b/gin/gin_features.cc index 6a90e38..035dfdb 100644 --- a/gin/gin_features.cc +++ b/gin/gin_features.cc
@@ -150,6 +150,10 @@ const base::FeatureParam<base::TimeDelta> kV8MemoryReducerStartDelay{ &kV8DelayMemoryReducer, "delay", base::Seconds(30)}; +BASE_FEATURE(kV8UseLibmTrigFunctions, + "V8UseLibmTrigFunctions", + base::FEATURE_ENABLED_BY_DEFAULT); + // JavaScript language features. // Enables the Symbols-as-WeakMap-keys proposal.
diff --git a/gin/gin_features.h b/gin/gin_features.h index f3b1b52..45f01f7 100644 --- a/gin/gin_features.h +++ b/gin/gin_features.h
@@ -46,6 +46,7 @@ GIN_EXPORT BASE_DECLARE_FEATURE(kV8SparkplugNeedsShortBuiltinCalls); GIN_EXPORT BASE_DECLARE_FEATURE(kV8TurboFastApiCalls); GIN_EXPORT BASE_DECLARE_FEATURE(kV8DelayMemoryReducer); +GIN_EXPORT BASE_DECLARE_FEATURE(kV8UseLibmTrigFunctions); GIN_EXPORT extern const base::FeatureParam<base::TimeDelta> kV8MemoryReducerStartDelay; GIN_EXPORT BASE_DECLARE_FEATURE(kJavaScriptSymbolAsWeakMapKey);
diff --git a/gin/v8_initializer.cc b/gin/v8_initializer.cc index 10b8bfa..8820680 100644 --- a/gin/v8_initializer.cc +++ b/gin/v8_initializer.cc
@@ -356,6 +356,10 @@ SetV8Flags("--use_strict"); } + SetV8FlagsIfOverridden(features::kV8UseLibmTrigFunctions, + "--use-libm-trig-functions", + "--no-use-libm-trig-functions"); + if (js_command_line_flags.empty()) return;
diff --git a/gpu/command_buffer/service/scheduler_dfs.cc b/gpu/command_buffer/service/scheduler_dfs.cc index d21e69ee..d181581 100644 --- a/gpu/command_buffer/service/scheduler_dfs.cc +++ b/gpu/command_buffer/service/scheduler_dfs.cc
@@ -576,11 +576,13 @@ << " (order_num: " << fence_iter->first.order_num << ")."; Sequence* release_sequence = GetSequence(fence_iter->first.release_sequence_id); - // Sanity check to make sure we're not processing a sequence on another - // thread that's past - DCHECK(!(release_sequence && release_sequence->HasTasks() && - release_sequence->tasks_.front().order_num >= - fence_iter->first.order_num)); + // ShouldYield might be calling this function, and a dependency might depend + // on the calling sequence, which might have not released its fences yet. + if (release_sequence && release_sequence->HasTasks() && + release_sequence->tasks_.front().order_num >= + fence_iter->first.order_num) { + continue; + } if (Sequence* result = FindNextTaskFromRoot(release_sequence); result != nullptr) { return result; @@ -617,7 +619,7 @@ // dependency tied to another thread. for (const SchedulingState& state : sorted_sequences) { Sequence* root_sequence = GetSequence(state.sequence_id); - DVLOG(10) << "RunNextTask: Calling FindNextTask on sequence " + DVLOG(10) << "FindNextTask: Calling FindNextTaskFromRoot on sequence " << root_sequence->sequence_id().value(); if (Sequence* sequence = FindNextTaskFromRoot(root_sequence); sequence != nullptr) { @@ -767,9 +769,7 @@ total_blocked_time_ += blocked_time; // Reset pointers after reaquiring the lock. - thread_state = &per_thread_state_map_[task_runner]; sequence = GetSequence(sequence_id); - if (sequence) { sequence->FinishTask(); }
diff --git a/gpu/command_buffer/service/scheduler_dfs_unittest.cc b/gpu/command_buffer/service/scheduler_dfs_unittest.cc index ec9eda6..1bb1828 100644 --- a/gpu/command_buffer/service/scheduler_dfs_unittest.cc +++ b/gpu/command_buffer/service/scheduler_dfs_unittest.cc
@@ -15,7 +15,6 @@ #include "base/functional/bind.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" -#include "base/test/test_simple_task_runner.h" #include "base/time/time.h" #include "gpu/command_buffer/service/scheduler.h" #include "gpu/command_buffer/service/sync_point_manager.h" @@ -171,9 +170,9 @@ sync_point_manager()->CreateSyncPointClientState( kNamespaceId, command_buffer_id, sequence_id); - sequence_info_.emplace(std::make_pair( + sequence_info_.emplace( sequence_key, - SequenceInfo(sequence_id, command_buffer_id, release_state))); + SequenceInfo(sequence_id, command_buffer_id, release_state)); } void CreateExternalSequence(int sequence_key) { @@ -182,9 +181,9 @@ auto release_state = sync_point_manager()->CreateSyncPointClientState( kNamespaceId, command_buffer_id, order_data->sequence_id()); - sequence_info_.emplace(std::make_pair( + sequence_info_.emplace( sequence_key, - SequenceInfo(std::move(order_data), command_buffer_id, release_state))); + SequenceInfo(std::move(order_data), command_buffer_id, release_state)); } void DestroySequence(int sequence_key) { @@ -205,9 +204,9 @@ ASSERT_TRUE(info_it != sequence_info_.end()); uint64_t release = release_sync + 1; - sync_tokens_.emplace(std::make_pair( + sync_tokens_.emplace( release_sync, - SyncToken(kNamespaceId, info_it->second.command_buffer_id, release))); + SyncToken(kNamespaceId, info_it->second.command_buffer_id, release)); } static void RunExternalTask(base::OnceClosure task, @@ -605,6 +604,56 @@ scheduler()->DestroySequence(sequence_id2); } +// Tests a situation where a sequence's WaitFence has an order number less than +// the sequence's first order number, because the sequence is currently running, +// and called ShouldYield before release the WaitFence. +TEST_F(SchedulerDfsTest, ShouldYieldIsValidWhenSequenceReleaseIsPending) { + SequenceId sequence_id1 = + scheduler()->CreateSequenceForTesting(SchedulingPriority::kHigh); + CommandBufferNamespace namespace_id = CommandBufferNamespace::GPU_IO; + CommandBufferId command_buffer_id1 = CommandBufferId::FromUnsafeValue(1); + scoped_refptr<SyncPointClientState> release_state1 = + sync_point_manager()->CreateSyncPointClientState( + namespace_id, command_buffer_id1, sequence_id1); + + SequenceId sequence_id2 = + scheduler()->CreateSequenceForTesting(SchedulingPriority::kNormal); + CommandBufferId command_buffer_id2 = CommandBufferId::FromUnsafeValue(2); + scoped_refptr<SyncPointClientState> release_state2 = + sync_point_manager()->CreateSyncPointClientState( + namespace_id, command_buffer_id2, sequence_id2); + + SyncToken sync_token1(namespace_id, command_buffer_id1, 1); + SyncToken sync_token2(namespace_id, command_buffer_id2, 2); + + // Job 1.1 doesn't depend on anything. + scheduler()->ScheduleTask( + Scheduler::Task(sequence_id1, GetClosure([&] { + EXPECT_FALSE(scheduler()->ShouldYield(sequence_id1)); + release_state1->ReleaseFenceSync(1); + }), + {})); + + // Job 2.1 depends on Job 1.1. + scheduler()->ScheduleTask(Scheduler::Task(sequence_id2, GetClosure([&] { + release_state2->ReleaseFenceSync( + sync_token2.release_count()); + }), + {sync_token1})); + + // Job 1.2 depends on Job 2.1. + scheduler()->ScheduleTask( + Scheduler::Task(sequence_id1, GetClosure([&] {}), {sync_token2})); + + RunAllPendingTasks(); + + release_state1->Destroy(); + release_state2->Destroy(); + + scheduler()->DestroySequence(sequence_id1); + scheduler()->DestroySequence(sequence_id2); +} + TEST_F(SchedulerDfsTest, ReentrantEnableSequenceShouldNotDeadlock) { SequenceId sequence_id1 = scheduler()->CreateSequenceForTesting(SchedulingPriority::kHigh);
diff --git a/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc b/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc index 3d14b16..1948267b 100644 --- a/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc +++ b/gpu/vulkan/init/gr_vk_memory_allocator_impl.cc
@@ -195,16 +195,11 @@ return vma::InvalidateAllocation(allocator_, allocation, offset, size); } - uint64_t totalUsedMemory() const override { + std::pair<uint64_t, uint64_t> totalAllocatedAndUsedMemory() const override { VmaStats stats; vma::CalculateStats(allocator_, &stats); - return stats.total.usedBytes; - } - - uint64_t totalAllocatedMemory() const override { - VmaStats stats; - vma::CalculateStats(allocator_, &stats); - return stats.total.usedBytes + stats.total.unusedBytes; + return {stats.total.usedBytes + stats.total.unusedBytes, + stats.total.usedBytes}; } const VmaAllocator allocator_;
diff --git a/infra/config/generated/builders/ci/linux-wpt-content-shell-asan-fyi-rel/properties.json b/infra/config/generated/builders/ci/linux-wpt-content-shell-asan-fyi-rel/properties.json new file mode 100644 index 0000000..b8f8bb3 --- /dev/null +++ b/infra/config/generated/builders/ci/linux-wpt-content-shell-asan-fyi-rel/properties.json
@@ -0,0 +1,54 @@ +{ + "$build/chromium_tests_builder_config": { + "builder_config": { + "builder_db": { + "entries": [ + { + "builder_id": { + "bucket": "ci", + "builder": "linux-wpt-content-shell-asan-fyi-rel", + "project": "chromium" + }, + "builder_spec": { + "build_gs_bucket": "chromium-fyi-archive", + "builder_group": "chromium.fyi", + "execution_mode": "COMPILE_AND_TEST", + "legacy_chromium_config": { + "apply_configs": [ + "mb" + ], + "build_config": "Release", + "config": "chromium", + "target_bits": 64 + }, + "legacy_gclient_config": { + "config": "chromium" + } + } + } + ] + }, + "builder_ids": [ + { + "bucket": "ci", + "builder": "linux-wpt-content-shell-asan-fyi-rel", + "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.fyi", + "recipe": "chromium" +} \ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index 8e0cd11..5f3b01e 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -41204,6 +41204,96 @@ } } builders { + name: "linux-wpt-content-shell-asan-fyi-rel" + swarming_host: "chromium-swarm.appspot.com" + dimensions: "builderless:1" + dimensions: "cores:8" + dimensions: "cpu:x86-64" + dimensions: "free_space:standard" + dimensions: "os:Ubuntu-18.04" + dimensions: "pool:luci.chromium.ci" + dimensions: "ssd:0" + exe { + cipd_package: "infra/chromium/bootstrapper/${platform}" + cipd_version: "latest" + cmd: "bootstrapper" + } + properties: + '{' + ' "$bootstrap/exe": {' + ' "exe": {' + ' "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",' + ' "cipd_version": "refs/heads/main",' + ' "cmd": [' + ' "luciexe"' + ' ]' + ' }' + ' },' + ' "$bootstrap/properties": {' + ' "properties_file": "infra/config/generated/builders/ci/linux-wpt-content-shell-asan-fyi-rel/properties.json",' + ' "top_level_project": {' + ' "ref": "refs/heads/main",' + ' "repo": {' + ' "host": "chromium.googlesource.com",' + ' "project": "chromium/src"' + ' }' + ' }' + ' },' + ' "builder_group": "chromium.fyi",' + ' "led_builder_is_bootstrapped": true,' + ' "recipe": "chromium"' + '}' + priority: 35 + execution_timeout_secs: 36000 + build_numbers: YES + service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" + experimental: YES + experiments { + key: "chromium_swarming.expose_merge_script_failures" + value: 100 + } + experiments { + key: "luci.buildbucket.omit_python2" + value: 100 + } + experiments { + key: "luci.recipes.use_python3" + value: 100 + } + resultdb { + enable: true + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "ci_test_results" + test_results {} + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "gpu_ci_test_results" + test_results { + predicate { + test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+" + } + } + } + bq_exports { + project: "chrome-luci-data" + dataset: "chromium" + table: "blink_web_tests_ci_test_results" + test_results { + predicate { + test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)" + } + } + } + history_options { + use_invocation_timestamp: true + } + } + } + builders { name: "linux-wpt-content-shell-fyi-rel" swarming_host: "chromium-swarm.appspot.com" dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg index d4f42827..ac609cc7 100644 --- a/infra/config/generated/luci/luci-milo.cfg +++ b/infra/config/generated/luci/luci-milo.cfg
@@ -8862,6 +8862,10 @@ category: "linux" } builders { + name: "buildbucket/luci.chromium.ci/linux-wpt-content-shell-asan-fyi-rel" + category: "linux" + } + builders { name: "buildbucket/luci.chromium.ci/linux-wpt-content-shell-fyi-rel" category: "linux" }
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg index 9fb6e243..b97b6cd0 100644 --- a/infra/config/generated/luci/luci-scheduler.cfg +++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -5099,6 +5099,15 @@ } } job { + id: "linux-wpt-content-shell-asan-fyi-rel" + realm: "ci" + buildbucket { + server: "cr-buildbucket.appspot.com" + bucket: "ci" + builder: "linux-wpt-content-shell-asan-fyi-rel" + } +} +job { id: "linux-wpt-content-shell-fyi-rel" realm: "ci" buildbucket { @@ -6276,6 +6285,7 @@ triggers: "linux-ubsan-vptr" triggers: "linux-upload-perfetto" triggers: "linux-win_cross-rel" + triggers: "linux-wpt-content-shell-asan-fyi-rel" triggers: "linux-wpt-content-shell-fyi-rel" triggers: "linux-wpt-fyi-rel" triggers: "linux-wpt-identity-fyi-rel"
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star index 6a696067..1794c46 100644 --- a/infra/config/subprojects/chromium/ci/chromium.fyi.star +++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -806,6 +806,27 @@ ) ci.builder( + name = "linux-wpt-content-shell-asan-fyi-rel", + builder_spec = builder_config.builder_spec( + gclient_config = builder_config.gclient_config( + config = "chromium", + ), + chromium_config = builder_config.chromium_config( + config = "chromium", + apply_configs = ["mb"], + build_config = builder_config.build_config.RELEASE, + target_bits = 64, + ), + build_gs_bucket = "chromium-fyi-archive", + ), + os = os.LINUX_DEFAULT, + console_view_entry = consoles.console_view_entry( + category = "linux", + ), + experimental = True, +) + +ci.builder( name = "linux-wpt-identity-fyi-rel", builder_spec = builder_config.builder_spec( gclient_config = builder_config.gclient_config(config = "chromium"),
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index 9e0789e..76f4a2d 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -446,14 +446,17 @@ // Tests that the tap gesture recognizer that dismisses the keyboard and // defocuses the omnibox works. - (void)testDefocusOmniboxTapWorks { - // TODO(crbug.com/1394749): Test fails on iPad. - if ([ChromeEarlGrey isIPadIdiom]) { - EARL_GREY_TEST_DISABLED(@"Fails on iPad."); - } - [self focusFakebox]; - [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPCollectionView()] - performAction:grey_tap()]; + if ([ChromeEarlGrey isIPadIdiom]) { + // Tap on a space in the collectionView that is not a Feed card. + [[EarlGrey selectElementWithMatcher: + grey_accessibilityID( + ntp_home::DiscoverHeaderTitleAccessibilityID())] + performAction:grey_tap()]; + } else { + [[EarlGrey selectElementWithMatcher:chrome_test_util::NTPCollectionView()] + performAction:grey_tap()]; + } [ChromeEarlGreyUI waitForAppToIdle]; // Check the fake omnibox is displayed again at the same position.
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm index 42b1555..88d3f5b 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_table_view_controller.mm
@@ -576,8 +576,13 @@ } } +// TODO(crbug.com/1359392): Remove this override when kPasswordsGrouping flag is +// removed. - (BOOL)shouldHideToolbar { - return !self.editing; + // When credentials are grouped, each credential section has its own Delete + // button displayed on editing mode, hence showing the toolbar with the Delete + // button is not necessary. + return IsPasswordGroupingEnabled() || !self.editing; } #pragma mark - Private
diff --git a/ios/chrome/browser/variations/variations_safe_mode_end_to_end_egtest.mm b/ios/chrome/browser/variations/variations_safe_mode_end_to_end_egtest.mm index 141a6d9..21588f6 100644 --- a/ios/chrome/browser/variations/variations_safe_mode_end_to_end_egtest.mm +++ b/ios/chrome/browser/variations/variations_safe_mode_end_to_end_egtest.mm
@@ -129,7 +129,7 @@ // Tests that three seed-driven crashes trigger variations safe mode. // -// Corresponds to VariationsSafeModeEndToEndBrowserTest.ExtendedSafeModeEndToEnd +// Corresponds to VariationsSafeModeEndToEndBrowserTest.ExtendedSafeSeedEndToEnd // in variations_safe_mode_browsertest.cc. - (void)testVariationsSafeModeEndToEnd { #if !TARGET_OS_SIMULATOR
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index 1a8af95..835b0ef 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -890,13 +890,14 @@ (src_frame.format() == PIXEL_FORMAT_I420 || src_frame.format() == PIXEL_FORMAT_I420A)) { if (dst_frame.format() == PIXEL_FORMAT_I420A) { - libyuv::ScalePlane( - src_frame.visible_data(VideoFrame::kAPlane), - src_frame.stride(VideoFrame::kAPlane), - src_frame.visible_rect().width(), src_frame.visible_rect().height(), - dst_frame.writable_data(VideoFrame::kAPlane), // TODO: Is this right? - dst_frame.stride(VideoFrame::kAPlane), dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane(src_frame.visible_data(VideoFrame::kAPlane), + src_frame.stride(VideoFrame::kAPlane), + src_frame.visible_rect().width(), + src_frame.visible_rect().height(), + dst_frame.GetWritableVisibleData(VideoFrame::kAPlane), + dst_frame.stride(VideoFrame::kAPlane), + dst_frame.visible_rect().width(), + dst_frame.visible_rect().height(), kDefaultFiltering); } int error = libyuv::I420Scale( src_frame.visible_data(VideoFrame::kYPlane), @@ -924,14 +925,14 @@ (src_frame.format() == PIXEL_FORMAT_NV12 || src_frame.format() == PIXEL_FORMAT_NV12A)) { if (dst_frame.format() == PIXEL_FORMAT_NV12A) { - libyuv::ScalePlane(src_frame.visible_data(VideoFrame::kAPlaneTriPlanar), - src_frame.stride(VideoFrame::kAPlaneTriPlanar), - src_frame.visible_rect().width(), - src_frame.visible_rect().height(), - dst_frame.writable_data(VideoFrame::kAPlaneTriPlanar), - dst_frame.stride(VideoFrame::kAPlaneTriPlanar), - dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane( + src_frame.visible_data(VideoFrame::kAPlaneTriPlanar), + src_frame.stride(VideoFrame::kAPlaneTriPlanar), + src_frame.visible_rect().width(), src_frame.visible_rect().height(), + dst_frame.GetWritableVisibleData(VideoFrame::kAPlaneTriPlanar), + dst_frame.stride(VideoFrame::kAPlaneTriPlanar), + dst_frame.visible_rect().width(), dst_frame.visible_rect().height(), + kDefaultFiltering); } int error = libyuv::NV12Scale( src_frame.visible_data(VideoFrame::kYPlane), @@ -1031,13 +1032,14 @@ if (error) return EncoderStatus::Codes::kFormatConversionError; // Convert alpha channel separately. - libyuv::ScalePlane( - src_frame.visible_data(VideoFrame::kAPlaneTriPlanar), - src_frame.stride(VideoFrame::kAPlaneTriPlanar), - src_frame.visible_rect().width(), src_frame.visible_rect().height(), - dst_frame.writable_data(VideoFrame::kAPlane), - dst_frame.stride(VideoFrame::kAPlane), dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane(src_frame.visible_data(VideoFrame::kAPlaneTriPlanar), + src_frame.stride(VideoFrame::kAPlaneTriPlanar), + src_frame.visible_rect().width(), + src_frame.visible_rect().height(), + dst_frame.GetWritableVisibleData(VideoFrame::kAPlane), + dst_frame.stride(VideoFrame::kAPlane), + dst_frame.visible_rect().width(), + dst_frame.visible_rect().height(), kDefaultFiltering); return OkStatus(); } else { // Both resize and NV12-to-I420 conversion are required. @@ -1077,13 +1079,14 @@ if (error) return EncoderStatus::Codes::kScalingError; // Convert alpha channel separately. - libyuv::ScalePlane( - src_frame.visible_data(VideoFrame::kAPlaneTriPlanar), - src_frame.stride(VideoFrame::kAPlaneTriPlanar), - src_frame.visible_rect().width(), src_frame.visible_rect().height(), - dst_frame.writable_data(VideoFrame::kAPlane), - dst_frame.stride(VideoFrame::kAPlane), dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane(src_frame.visible_data(VideoFrame::kAPlaneTriPlanar), + src_frame.stride(VideoFrame::kAPlaneTriPlanar), + src_frame.visible_rect().width(), + src_frame.visible_rect().height(), + dst_frame.GetWritableVisibleData(VideoFrame::kAPlane), + dst_frame.stride(VideoFrame::kAPlane), + dst_frame.visible_rect().width(), + dst_frame.visible_rect().height(), kDefaultFiltering); return OkStatus(); } } @@ -1166,14 +1169,14 @@ if (error) return EncoderStatus::Codes::kFormatConversionError; // Convert alpha channel separately. - libyuv::ScalePlane(src_frame.visible_data(VideoFrame::kAPlane), - src_frame.stride(VideoFrame::kAPlane), - src_frame.visible_rect().width(), - src_frame.visible_rect().height(), - dst_frame.writable_data(VideoFrame::kAPlaneTriPlanar), - dst_frame.stride(VideoFrame::kAPlaneTriPlanar), - dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane( + src_frame.visible_data(VideoFrame::kAPlane), + src_frame.stride(VideoFrame::kAPlane), + src_frame.visible_rect().width(), src_frame.visible_rect().height(), + dst_frame.GetWritableVisibleData(VideoFrame::kAPlaneTriPlanar), + dst_frame.stride(VideoFrame::kAPlaneTriPlanar), + dst_frame.visible_rect().width(), dst_frame.visible_rect().height(), + kDefaultFiltering); return OkStatus(); } else { // Both resize and I420-to-NV12 conversion are required. @@ -1210,14 +1213,14 @@ if (error) return EncoderStatus::Codes::kScalingError; // Convert alpha channel separately. - libyuv::ScalePlane(src_frame.visible_data(VideoFrame::kAPlane), - src_frame.stride(VideoFrame::kAPlane), - src_frame.visible_rect().width(), - src_frame.visible_rect().height(), - dst_frame.writable_data(VideoFrame::kAPlaneTriPlanar), - dst_frame.stride(VideoFrame::kAPlaneTriPlanar), - dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane( + src_frame.visible_data(VideoFrame::kAPlane), + src_frame.stride(VideoFrame::kAPlane), + src_frame.visible_rect().width(), src_frame.visible_rect().height(), + dst_frame.GetWritableVisibleData(VideoFrame::kAPlaneTriPlanar), + dst_frame.stride(VideoFrame::kAPlaneTriPlanar), + dst_frame.visible_rect().width(), dst_frame.visible_rect().height(), + kDefaultFiltering); return OkStatus(); } }
diff --git a/media/gpu/v4l2/test/v4l2_ioctl_shim.cc b/media/gpu/v4l2/test/v4l2_ioctl_shim.cc index b785b78c..d0dd1bbcb 100644 --- a/media/gpu/v4l2/test/v4l2_ioctl_shim.cc +++ b/media/gpu/v4l2/test/v4l2_ioctl_shim.cc
@@ -52,6 +52,7 @@ V4L2_REQUEST_CODE_AND_STRING(VIDIOC_QBUF), V4L2_REQUEST_CODE_AND_STRING(VIDIOC_DQBUF), V4L2_REQUEST_CODE_AND_STRING(VIDIOC_STREAMON), + V4L2_REQUEST_CODE_AND_STRING(VIDIOC_STREAMOFF), V4L2_REQUEST_CODE_AND_STRING(VIDIOC_S_EXT_CTRLS), V4L2_REQUEST_CODE_AND_STRING(MEDIA_IOC_REQUEST_ALLOC), V4L2_REQUEST_CODE_AND_STRING(MEDIA_REQUEST_IOC_QUEUE), @@ -267,6 +268,7 @@ template <> bool V4L2IoctlShim::Ioctl(int request_code, int* arg) const { DCHECK(request_code == static_cast<int>(VIDIOC_STREAMON) || + request_code == static_cast<int>(VIDIOC_STREAMOFF) || request_code == static_cast<int>(MEDIA_IOC_REQUEST_ALLOC)); LOG_ASSERT(arg != nullptr) << "|arg| check failed."; @@ -401,6 +403,30 @@ return ret; } +bool V4L2IoctlShim::ReqBufsWithCount(std::unique_ptr<V4L2Queue>& queue, + uint32_t count) const { + struct v4l2_requestbuffers reqbuf; + + memset(&reqbuf, 0, sizeof(reqbuf)); + reqbuf.count = count; + reqbuf.type = queue->type(); + reqbuf.memory = queue->memory(); + + const bool ret = Ioctl(VIDIOC_REQBUFS, &reqbuf); + + queue->set_num_buffers(reqbuf.count); + + if (count == 0) { + LOG(INFO) << "Requested to free all buffers in " << queue->type() + << "with a buffer count of 0."; + } else { + LOG(INFO) << queue->num_buffers() << " buffers requested, " << reqbuf.count + << " buffers returned for " << queue->type() << "."; + } + + return ret; +} + bool V4L2IoctlShim::QBuf(const std::unique_ptr<V4L2Queue>& queue, const uint32_t index) const { LOG_ASSERT(queue->memory() == V4L2_MEMORY_MMAP) @@ -501,6 +527,12 @@ return Ioctl(VIDIOC_STREAMON, &arg); } +bool V4L2IoctlShim::StreamOff(const enum v4l2_buf_type type) const { + int arg = static_cast<int>(type); + + return Ioctl(VIDIOC_STREAMOFF, &arg); +} + bool V4L2IoctlShim::SetExtCtrls(const std::unique_ptr<V4L2Queue>& queue, v4l2_ext_controls* ext_ctrls) const { // TODO(b/230021497): add compressed header probability related change @@ -626,4 +658,4 @@ } } // namespace v4l2_test -} // namespace media \ No newline at end of file +} // namespace media
diff --git a/media/gpu/v4l2/test/v4l2_ioctl_shim.h b/media/gpu/v4l2/test/v4l2_ioctl_shim.h index 331ba675..25f244fa 100644 --- a/media/gpu/v4l2/test/v4l2_ioctl_shim.h +++ b/media/gpu/v4l2/test/v4l2_ioctl_shim.h
@@ -92,7 +92,12 @@ enum v4l2_buf_type type() const { return type_; } uint32_t fourcc() const { return fourcc_; } + gfx::Size display_size() const { return display_size_; } + void set_display_size(gfx::Size display_size) { + display_size_ = display_size; + } + enum v4l2_memory memory() const { return memory_; } void set_buffers(MmapedBuffers& buffers) { buffers_ = buffers; } @@ -132,13 +137,15 @@ queued_buffer_indexes_.erase(index); } + void DequeueAllBufferIndexes() { queued_buffer_indexes_.clear(); } + private: const enum v4l2_buf_type type_; const uint32_t fourcc_; MmapedBuffers buffers_; uint32_t num_buffers_; // The size of the image on the screen. - const gfx::Size display_size_; + gfx::Size display_size_; // The size of the encoded frame. Usually has an alignment of 16, 32 // depending on codec. gfx::Size coded_size_; @@ -189,6 +196,10 @@ // Allocates buffers via VIDIOC_REQBUFS for |queue|. [[nodiscard]] bool ReqBufs(std::unique_ptr<V4L2Queue>& queue) const; + // Allocates buffers via VIDIOC_REQBUFS for |queue| with a buffer count. + [[nodiscard]] bool ReqBufsWithCount(std::unique_ptr<V4L2Queue>& queue, + uint32_t count) const; + // Enqueues an empty (capturing) or filled (output) buffer // in the driver's incoming |queue|. [[nodiscard]] bool QBuf(const std::unique_ptr<V4L2Queue>& queue, @@ -202,6 +213,9 @@ // Starts streaming |queue| (via VIDIOC_STREAMON). [[nodiscard]] bool StreamOn(const enum v4l2_buf_type type) const; + // Stops streaming |queue| (via VIDIOC_STREAMOFF). + [[nodiscard]] bool StreamOff(const enum v4l2_buf_type type) const; + // Sets the value of controls which specify decoding parameters // for each frame. [[nodiscard]] bool SetExtCtrls(const std::unique_ptr<V4L2Queue>& queue,
diff --git a/media/gpu/v4l2/test/video_decoder.cc b/media/gpu/v4l2/test/video_decoder.cc index 5d8ee81..c9f7640 100644 --- a/media/gpu/v4l2/test/video_decoder.cc +++ b/media/gpu/v4l2/test/video_decoder.cc
@@ -50,10 +50,10 @@ // 4:2:0 subsampled, but UV are interlaced). This function converts a single // MM21 plane into its equivalent NV12 plane. void DetilePlane(std::vector<char>& dest, - gfx::Size dest_size, + const gfx::Size& dest_size, char* src, - gfx::Size src_size, - gfx::Size tile_size) { + const gfx::Size& src_size, + const gfx::Size& tile_size) { // Tile size in bytes. const int tile_len = tile_size.GetArea(); // |width| rounded down to the nearest multiple of |tile_width|. @@ -166,11 +166,15 @@ if (!v4l2_ioctl_->SetFmt(CAPTURE_queue_)) LOG(FATAL) << "SetFmt for CAPTURE queue failed."; - if (!v4l2_ioctl_->ReqBufs(OUTPUT_queue_)) - LOG(FATAL) << "ReqBufs for OUTPUT queue failed."; + // If there is a dynamic resolution change, the Initialization sequence will + // be performed again, minus the allocation of OUTPUT queue buffers. + if (!IsResolutionChanged()) { + if (!v4l2_ioctl_->ReqBufs(OUTPUT_queue_)) + LOG(FATAL) << "ReqBufs for OUTPUT queue failed."; - if (!v4l2_ioctl_->QueryAndMmapQueueBuffers(OUTPUT_queue_)) - LOG(FATAL) << "QueryAndMmapQueueBuffers for OUTPUT queue failed"; + if (!v4l2_ioctl_->QueryAndMmapQueueBuffers(OUTPUT_queue_)) + LOG(FATAL) << "QueryAndMmapQueueBuffers for OUTPUT queue failed"; + } if (!v4l2_ioctl_->ReqBufs(CAPTURE_queue_)) LOG(FATAL) << "ReqBufs for CAPTURE queue failed."; @@ -196,15 +200,52 @@ LOG(FATAL) << "StreamOn for CAPTURE queue failed."; } +// Follows the dynamic resolution change sequence described in +// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/dev-stateless-decoder.html#dynamic-resolution-change +VideoDecoder::Result VideoDecoder::HandleDynamicResolutionChange( + const gfx::Size& new_resolution) { + // Call VIDIOC_STREAMOFF() on both the OUTPUT and CAPTURE queues. + if (!v4l2_ioctl_->StreamOff(OUTPUT_queue_->type())) + LOG(FATAL) << "StreamOff for OUTPUT queue failed."; + + if (!v4l2_ioctl_->StreamOff(CAPTURE_queue_->type())) + LOG(FATAL) << "StreamOff for CAPTURE queue failed."; + + // Free all CAPTURE buffers from the driver side by calling VIDIOC_REQBUFS() + // on the CAPTURE queue with a buffer count of zero. + if (!v4l2_ioctl_->ReqBufsWithCount(CAPTURE_queue_, 0)) + LOG(FATAL) << "Failed to free all buffers for CAPTURE queue"; + + // Free queued CAPTURE buffer indexes that are tracked by the client side. + CAPTURE_queue_->DequeueAllBufferIndexes(); + + // Set the new resolution on OUTPUT queue. The driver will then pick up + // the new resolution to be set on the coded size for CAPTURE queue. + OUTPUT_queue_->set_display_size(new_resolution); + OUTPUT_queue_->set_coded_size(new_resolution); + + if (!v4l2_ioctl_->ReqBufsWithCount(CAPTURE_queue_, + number_of_buffers_in_capture_queue_)) { + LOG(FATAL) << "ReqBufs for CAPTURE queue failed."; + } + CAPTURE_queue_->set_display_size(new_resolution); + + // Perform the initialization sequence again + Initialize(); + is_resolution_changed_ = false; + + return VideoDecoder::kOk; +} + // Unpacks NV12 to I420 and optionally trims padding from source. // This expects a contiguous NV12 buffer, as specified by // V4L2_PIX_FMT_NV12. void VideoDecoder::ConvertNV12ToYUV(std::vector<char>& dest_y, std::vector<char>& dest_u, std::vector<char>& dest_v, - gfx::Size dest_size, + const gfx::Size& dest_size, const char* src, - gfx::Size src_size) { + const gfx::Size& src_size) { CHECK(dest_size.width() <= src_size.width()); CHECK(dest_size.height() <= src_size.height()); @@ -246,10 +287,10 @@ void VideoDecoder::ConvertMM21ToYUV(std::vector<char>& dest_y, std::vector<char>& dest_u, std::vector<char>& dest_v, - gfx::Size dest_size, + const gfx::Size& dest_size, char* src_y, char* src_uv, - gfx::Size src_size) { + const gfx::Size& src_size) { constexpr int kMM21TileWidth = 16; constexpr int kMM21TileHeight = 32;
diff --git a/media/gpu/v4l2/test/video_decoder.h b/media/gpu/v4l2/test/video_decoder.h index 3e27fc4..3afadd7 100644 --- a/media/gpu/v4l2/test/video_decoder.h +++ b/media/gpu/v4l2/test/video_decoder.h
@@ -46,26 +46,34 @@ gfx::Size& size, const int frame_number) = 0; + // Handles dynamic resolution change with new resolution parsed from frame + // header. + VideoDecoder::Result HandleDynamicResolutionChange( + const gfx::Size& new_resolution); + // Returns whether the last decoded frame was visible. bool LastDecodedFrameVisible() const { return last_decoded_frame_visible_; } + // Return whether there is a dynamic resolytion change. + bool IsResolutionChanged() const { return is_resolution_changed_; } + protected: // Helper method for converting NV12 frames to I420. static void ConvertNV12ToYUV(std::vector<char>& dest_y, std::vector<char>& dest_u, std::vector<char>& dest_v, - gfx::Size dest_size, + const gfx::Size& dest_size, const char* src, - gfx::Size src_size); + const gfx::Size& src_size); // Helper method for converting MM21 frames to I420. static void ConvertMM21ToYUV(std::vector<char>& dest_y, std::vector<char>& dest_u, std::vector<char>& dest_v, - gfx::Size dest_size, + const gfx::Size& dest_size, char* src_y, char* src_uv, - gfx::Size src_size); + const gfx::Size& src_size); // Wrapper for V4L2 ioctl requests. const std::unique_ptr<V4L2IoctlShim> v4l2_ioctl_; @@ -78,6 +86,12 @@ // Whether the last decoded frame was visible. bool last_decoded_frame_visible_ = false; + + // Whether there is a dynamic support change. + bool is_resolution_changed_ = false; + + // Number of buffers in CAPTURE queue varied by different codecs. + uint32_t number_of_buffers_in_capture_queue_; }; } // namespace v4l2_test
diff --git a/media/gpu/v4l2/test/vp8_decoder.cc b/media/gpu/v4l2/test/vp8_decoder.cc index 144209d..64bbcccc 100644 --- a/media/gpu/v4l2/test/vp8_decoder.cc +++ b/media/gpu/v4l2/test/vp8_decoder.cc
@@ -38,6 +38,37 @@ base::strict_cast<TypeOfVp8RefType>(media::VP8_FRAME_ALTREF), "Invalid index value for Altref reference frame"); +// The resolution encoded in the bitstream is required for queue creation. Note +// that parsing ivf file and parsing the first frame VP8 parser happen +// again later in the code. This is intentionally duplicated. +const gfx::Size GetResolutionFromBitstream( + const base::MemoryMappedFile& stream) { + media::IvfParser ivf_parser{}; + media::IvfFileHeader ivf_file_header{}; + + if (!ivf_parser.Initialize(stream.data(), stream.length(), + &ivf_file_header)) { + LOG(FATAL) << "Couldn't initialize IVF parser."; + } + + media::IvfFrameHeader ivf_frame_header{}; + const uint8_t* ivf_frame_data; + + if (!ivf_parser.ParseNextFrame(&ivf_frame_header, &ivf_frame_data)) { + LOG(FATAL) << "Failed to parse the first frame with IVF parser."; + } + + VLOG(2) << "Ivf file header: " << ivf_file_header.width << " x " + << ivf_file_header.height; + + media::Vp8Parser vp8_parser; + media::Vp8FrameHeader vp8_frame_header; + vp8_parser.ParseFrame(ivf_frame_data, ivf_frame_header.frame_size, + &vp8_frame_header); + + return gfx::Size(vp8_frame_header.width, vp8_frame_header.height); +} + // Section 9.4. Loop filter type and levels syntax in VP8 specs. // https://datatracker.ietf.org/doc/rfc6386/ struct v4l2_vp8_loop_filter FillV4L2VP8LoopFilterHeader( @@ -227,6 +258,7 @@ DCHECK(v4l2_ioctl_->QueryCtrl(V4L2_CID_STATELESS_VP8_FRAME)); std::fill(ref_frames_.begin(), ref_frames_.end(), nullptr); + number_of_buffers_in_capture_queue_ = kNumberOfBuffersInCaptureQueue; } Vp8Decoder::~Vp8Decoder() = default; @@ -278,20 +310,22 @@ LOG(INFO) << "Ivf file header: " << file_header.width << " x " << file_header.height; + const gfx::Size bitstream_coded_size = GetResolutionFromBitstream(stream); + // TODO(b/256251694): might need to consider using more than 1 file descriptor // (fd) & buffer with the output queue for 4K60 requirement. // https://buganizer.corp.google.com/issues/202214561#comment31 auto OUTPUT_queue = std::make_unique<V4L2Queue>( V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, kDriverCodecFourcc, - gfx::Size(file_header.width, file_header.height), /*num_planes=*/1, - V4L2_MEMORY_MMAP, /*num_buffers=*/kNumberOfBuffersInOutputQueue); + bitstream_coded_size, /*num_planes=*/1, V4L2_MEMORY_MMAP, + /*num_buffers=*/kNumberOfBuffersInOutputQueue); // TODO(b/256543928): enable V4L2_MEMORY_DMABUF memory for CAPTURE queue. // |num_planes| represents separate memory buffers, not planes for Y, U, V. // https://www.kernel.org/doc/html/v5.10/userspace-api/media/v4l/pixfmt-v4l2-mplane.html#c.V4L.v4l2_plane_pix_format auto CAPTURE_queue = std::make_unique<V4L2Queue>( V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, uncompressed_fourcc, - gfx::Size(file_header.width, file_header.height), + bitstream_coded_size, /*num_planes=*/num_planes, V4L2_MEMORY_MMAP, /*num_buffers=*/kNumberOfBuffersInCaptureQueue); @@ -534,6 +568,23 @@ break; } + if (frame_hdr.IsKeyframe()) { + is_resolution_changed_ = + frame_hdr.width != OUTPUT_queue_->coded_size().width() || + frame_hdr.height != OUTPUT_queue_->coded_size().height(); + } else { + frame_hdr.width = OUTPUT_queue_->coded_size().width(); + frame_hdr.height = OUTPUT_queue_->coded_size().height(); + } + + if (IsResolutionChanged()) { + const gfx::Size new_resolution(frame_hdr.width, frame_hdr.height); + LOG_ASSERT(!new_resolution.IsEmpty()) + << "New key frame resolution is empty."; + + HandleDynamicResolutionChange(new_resolution); + } + VLOG_IF(2, !frame_hdr.show_frame) << "Not displaying frame"; last_decoded_frame_visible_ = frame_hdr.show_frame;
diff --git a/media/video/video_encode_accelerator_adapter.cc b/media/video/video_encode_accelerator_adapter.cc index 61cf5e4..6a050c9a 100644 --- a/media/video/video_encode_accelerator_adapter.cc +++ b/media/video/video_encode_accelerator_adapter.cc
@@ -160,23 +160,23 @@ : public base::RefCountedThreadSafe<GpuMemoryBufferVideoFramePool> { public: GpuMemoryBufferVideoFramePool(GpuVideoAcceleratorFactories* gpu_factories, - const gfx::Size& size) - : gpu_factories_(gpu_factories), size_(size) {} + const gfx::Size& coded_size) + : gpu_factories_(gpu_factories), coded_size_(coded_size) {} GpuMemoryBufferVideoFramePool(const GpuMemoryBufferVideoFramePool&) = delete; GpuMemoryBufferVideoFramePool& operator=( const GpuMemoryBufferVideoFramePool&) = delete; - scoped_refptr<VideoFrame> MaybeCreateVideoFrame(const gfx::Size& size) { + scoped_refptr<VideoFrame> MaybeCreateVideoFrame( + const gfx::Size& visible_size) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (size_ != size) - return nullptr; + DCHECK(gfx::Rect(coded_size_).Contains(gfx::Rect(visible_size))); if (available_gmbs_.empty()) { constexpr auto kBufferFormat = gfx::BufferFormat::YUV_420_BIPLANAR; constexpr auto kBufferUsage = gfx::BufferUsage::VEA_READ_CAMERA_AND_CPU_READ_WRITE; - auto gmb = gpu_factories_->CreateGpuMemoryBuffer(size_, kBufferFormat, - kBufferUsage); + auto gmb = gpu_factories_->CreateGpuMemoryBuffer( + coded_size_, kBufferFormat, kBufferUsage); if (!gmb) return nullptr; @@ -191,7 +191,7 @@ const gpu::MailboxHolder kEmptyMailBoxes[media::VideoFrame::kMaxPlanes] = {}; return VideoFrame::WrapExternalGpuMemoryBuffer( - gfx::Rect(size_), size_, std::move(gmb), kEmptyMailBoxes, + gfx::Rect(visible_size), visible_size, std::move(gmb), kEmptyMailBoxes, std::move(reuse_cb), base::TimeDelta()); } @@ -208,7 +208,7 @@ } const raw_ptr<GpuVideoAcceleratorFactories> gpu_factories_; - const gfx::Size size_; + const gfx::Size coded_size_; std::vector<std::unique_ptr<gfx::GpuMemoryBuffer>> available_gmbs_; @@ -522,7 +522,8 @@ } const bool frame_needs_resizing = - frame->visible_rect().size() != options_.frame_size; + frame->visible_rect().size() != options_.frame_size || + frame->coded_size() != input_coded_size_; // Try using a frame with GPU buffer both are true: // 1. the frame already has GPU buffer @@ -539,9 +540,9 @@ EncoderStatus::Or<scoped_refptr<VideoFrame>> result(nullptr); if (use_gpu_buffer) - result = PrepareGpuFrame(input_coded_size_, frame); + result = PrepareGpuFrame(frame); else - result = PrepareCpuFrame(input_coded_size_, frame); + result = PrepareCpuFrame(frame); if (!result.has_value()) { std::move(done_cb).Run( @@ -946,25 +947,27 @@ // frames can I420, NV12, or RGB -- they'll be converted to I420 if needed. EncoderStatus::Or<scoped_refptr<VideoFrame>> VideoEncodeAcceleratorAdapter::PrepareCpuFrame( - const gfx::Size& size, scoped_refptr<VideoFrame> src_frame) { TRACE_EVENT0("media", "VideoEncodeAcceleratorAdapter::PrepareCpuFrame"); + const auto dest_coded_size = input_coded_size_; + const auto dest_visible_rect = gfx::Rect(options_.frame_size); + // The frame whose storage type is STORAGE_OWNED_MEMORY and // STORAGE_UNOWNED_MEMORY is copied here, not in mojo_video_frame_traits. // It is because VEAAdapter recycles the SharedMemoryRegion, but // mojo_video_frame_traits doesn't. if (src_frame->storage_type() == VideoFrame::STORAGE_SHMEM && src_frame->format() == PIXEL_FORMAT_I420 && - src_frame->visible_rect().size() == size && - src_frame->visible_rect().origin().IsOrigin()) { + src_frame->visible_rect() == dest_visible_rect && + src_frame->coded_size() == dest_coded_size) { // Nothing to do here, the input frame is already what we need. return src_frame; } if (!input_pool_) { const size_t input_buffer_size = - VideoFrame::AllocationSize(PIXEL_FORMAT_I420, size); + VideoFrame::AllocationSize(PIXEL_FORMAT_I420, dest_coded_size); input_pool_ = base::MakeRefCounted<ReadOnlyRegionPool>(input_buffer_size); } @@ -978,9 +981,9 @@ ? ConvertToMemoryMappedFrame(src_frame) : src_frame; auto shared_frame = VideoFrame::WrapExternalData( - PIXEL_FORMAT_I420, size, gfx::Rect(size), size, - static_cast<uint8_t*>(mapping->memory()), mapping->size(), - src_frame->timestamp()); + PIXEL_FORMAT_I420, dest_coded_size, dest_visible_rect, + dest_visible_rect.size(), static_cast<uint8_t*>(mapping->memory()), + mapping->size(), src_frame->timestamp()); if (!shared_frame || !mapped_src_frame) return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode); @@ -1001,24 +1004,28 @@ // can I420, NV12, or RGB -- they'll be converted to NV12 if needed. EncoderStatus::Or<scoped_refptr<VideoFrame>> VideoEncodeAcceleratorAdapter::PrepareGpuFrame( - const gfx::Size& size, scoped_refptr<VideoFrame> src_frame) { TRACE_EVENT0("media", "VideoEncodeAcceleratorAdapter::PrepareGpuFrame"); DCHECK_CALLED_ON_VALID_SEQUENCE(accelerator_sequence_checker_); DCHECK(src_frame); + + const auto dest_coded_size = input_coded_size_; + const auto dest_visible_rect = gfx::Rect(options_.frame_size); + if (src_frame->HasGpuMemoryBuffer() && src_frame->format() == PIXEL_FORMAT_NV12 && - (gpu_resize_supported_ || src_frame->visible_rect().size() == size)) { + (gpu_resize_supported_ || src_frame->coded_size() == dest_coded_size)) { // Nothing to do here, the input frame is already what we need return src_frame; } if (!gmb_frame_pool_) { gmb_frame_pool_ = base::MakeRefCounted<GpuMemoryBufferVideoFramePool>( - gpu_factories_, size); + gpu_factories_, dest_coded_size); } - auto gpu_frame = gmb_frame_pool_->MaybeCreateVideoFrame(size); + auto gpu_frame = + gmb_frame_pool_->MaybeCreateVideoFrame(dest_visible_rect.size()); if (!gpu_frame) return EncoderStatus(EncoderStatus::Codes::kEncoderFailedEncode);
diff --git a/media/video/video_encode_accelerator_adapter.h b/media/video/video_encode_accelerator_adapter.h index ead17024..4cf209fb0 100644 --- a/media/video/video_encode_accelerator_adapter.h +++ b/media/video/video_encode_accelerator_adapter.h
@@ -123,10 +123,8 @@ template <class T> T WrapCallback(T cb); EncoderStatus::Or<scoped_refptr<VideoFrame>> PrepareGpuFrame( - const gfx::Size& size, scoped_refptr<VideoFrame> src_frame); EncoderStatus::Or<scoped_refptr<VideoFrame>> PrepareCpuFrame( - const gfx::Size& size, scoped_refptr<VideoFrame> src_frame); scoped_refptr<ReadOnlyRegionPool> input_pool_;
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index 72b007a..4c637b4 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc
@@ -180,7 +180,8 @@ case CONNECTION_INFO_QUIC_DRAFT_29: case CONNECTION_INFO_QUIC_T051: case CONNECTION_INFO_QUIC_RFC_V1: - case CONNECTION_INFO_QUIC_2_DRAFT_1: + case CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1: + case CONNECTION_INFO_QUIC_2_DRAFT_8: return CONNECTION_INFO_COARSE_QUIC; case CONNECTION_INFO_UNKNOWN: @@ -553,7 +554,8 @@ case CONNECTION_INFO_QUIC_DRAFT_29: case CONNECTION_INFO_QUIC_T051: case CONNECTION_INFO_QUIC_RFC_V1: - case CONNECTION_INFO_QUIC_2_DRAFT_1: + case CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1: + case CONNECTION_INFO_QUIC_2_DRAFT_8: return true; case NUM_OF_CONNECTION_INFOS: NOTREACHED(); @@ -652,8 +654,10 @@ return "h3-T051"; case CONNECTION_INFO_QUIC_RFC_V1: return "h3"; - case CONNECTION_INFO_QUIC_2_DRAFT_1: + case CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1: return "h3/quic2draft01"; + case CONNECTION_INFO_QUIC_2_DRAFT_8: + return "h3/quic2draft08"; case NUM_OF_CONNECTION_INFOS: break; }
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index f8b39a7..1455d37 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h
@@ -78,7 +78,8 @@ CONNECTION_INFO_QUIC_DRAFT_29 = 38, CONNECTION_INFO_QUIC_T051 = 39, CONNECTION_INFO_QUIC_RFC_V1 = 40, - CONNECTION_INFO_QUIC_2_DRAFT_1 = 41, + CONNECTION_INFO_DEPRECATED_QUIC_2_DRAFT_1 = 41, + CONNECTION_INFO_QUIC_2_DRAFT_8 = 42, NUM_OF_CONNECTION_INFOS, };
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index 790c7b9..eb7a639 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -90,9 +90,9 @@ return HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1; case quic::QUIC_VERSION_RESERVED_FOR_NEGOTIATION: return HttpResponseInfo::CONNECTION_INFO_QUIC_999; - case quic::QUIC_VERSION_IETF_2_DRAFT_01: + case quic::QUIC_VERSION_IETF_2_DRAFT_08: DCHECK(quic_version.UsesTls()); - return HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1; + return HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_8; } NOTREACHED(); return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index aa63e952..d2873b2c 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -690,11 +690,11 @@ // QUIC v1 and QUIC v2 are considered a match, because they have the same // ALPN token. if ((connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 || - connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1) && + connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_8) && (response->connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 || response->connection_info == - HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1)) { + HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_8)) { return; }
diff --git a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc index b8ec997c..d85f940 100644 --- a/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc +++ b/sandbox/linux/integration_tests/seccomp_broker_process_unittest.cc
@@ -4,6 +4,7 @@ #include <errno.h> #include <fcntl.h> +#include <sys/inotify.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -15,13 +16,19 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/files/file.h" #include "base/files/file_path.h" +#include "base/files/file_path_watcher.h" +#include "base/files/file_path_watcher_inotify.h" +#include "base/files/file_util.h" #include "base/files/scoped_file.h" #include "base/files/scoped_temp_dir.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/posix/eintr_wrapper.h" +#include "base/run_loop.h" #include "base/test/bind.h" +#include "base/test/task_environment.h" #include "build/build_config.h" #include "sandbox/linux/bpf_dsl/bpf_dsl.h" #include "sandbox/linux/bpf_dsl/policy.h" @@ -261,6 +268,7 @@ virtual int Mkdir(const char* pathname, mode_t mode) = 0; virtual int Rmdir(const char* path) = 0; virtual int Unlink(const char* path) = 0; + virtual int InotifyAddWatch(int fd, const char* path, uint32_t mask) = 0; }; class IPCSyscaller : public Syscaller { @@ -307,6 +315,11 @@ return broker_->GetBrokerClientSignalBased()->Unlink(path); } + int InotifyAddWatch(int fd, const char* path, uint32_t mask) override { + return broker_->GetBrokerClientSignalBased()->InotifyAddWatch(fd, path, + mask); + } + private: raw_ptr<BrokerProcess> broker_; }; @@ -385,6 +398,13 @@ return -errno; return ret; } + + int InotifyAddWatch(int fd, const char* path, uint32_t mask) override { + int ret = syscall(__NR_inotify_add_watch, fd, path, mask); + if (ret < 0) + return -errno; + return ret; + } }; #endif // defined(DIRECT_SYSCALLER_ENABLED) @@ -448,9 +468,21 @@ return -errno; return ret; } + + int InotifyAddWatch(int fd, const char* path, uint32_t mask) override { + int ret = inotify_add_watch(fd, path, mask); + if (ret < 0) + return -errno; + return ret; + } }; -enum class SyscallerType { IPCSyscaller = 0, DirectSyscaller, LibcSyscaller }; +enum class SyscallerType { + IPCSyscaller = 0, + DirectSyscaller, + LibcSyscaller, + NoSyscaller +}; // The testing infrastructure for the broker integration tests is built on the // same infrastructure that BPF_TEST or SANDBOX_TEST uses. Each individual test @@ -599,6 +631,9 @@ case SyscallerType::LibcSyscaller: syscaller_ = std::make_unique<LibcSyscaller>(); break; + case SyscallerType::NoSyscaller: + syscaller_ = nullptr; + break; } } @@ -1125,7 +1160,7 @@ // Create a conflict for the temp filename. base::ScopedFD fd( open(existing_temp_file_str_.c_str(), O_RDWR | O_CREAT, 0600)); - BPF_ASSERT_GE(fd.get(), 0); + ASSERT_GE(fd.get(), 0); } BrokerParams ChildSetUpPreSandbox() override { @@ -2535,5 +2570,276 @@ RunAllBrokerTests<UnlinkFileRWCPermissionsDelegate>(); } +// Parent class for the inotify_add_watch() tests. +class InotifyAddWatchDelegate : public BrokerTestDelegate { + public: + const uint32_t kBadMask = + IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_ONLYDIR; + const uint32_t kGoodMask = kBadMask | IN_ATTRIB; + + static constexpr char kNestedTempDirName[] = "nested_temp_dir"; + static constexpr char kBadPrefixName[] = "nested_t"; + + void ParentSetUp() override { + // Create two nested temp dirs. + ASSERT_TRUE(temp_dir_.CreateUniqueTempDirUnderPath( + base::FilePath(kTempDirForTests))); + temp_dir_str_ = temp_dir_.GetPath().MaybeAsASCII(); + ASSERT_FALSE(temp_dir_str_.empty()); + + ASSERT_TRUE(nested_temp_dir_.Set( + temp_dir_.GetPath().AppendASCII(kNestedTempDirName))); + nested_temp_dir_str_ = nested_temp_dir_.GetPath().MaybeAsASCII(); + ASSERT_FALSE(nested_temp_dir_str_.empty()); + + temp_file_ = base::CreateAndOpenTemporaryFileInDir( + nested_temp_dir_.GetPath(), &temp_file_path_); + temp_file_path_str_ = temp_file_path_.MaybeAsASCII(); + ASSERT_FALSE(temp_file_path_str_.empty()); + } + + protected: + // Parent temp directory. + base::ScopedTempDir temp_dir_; + std::string temp_dir_str_; + + // A directory nested under |temp_dir_|. + base::ScopedTempDir nested_temp_dir_; + std::string nested_temp_dir_str_; + + // In |nested_temp_dir_|. + base::FilePath temp_file_path_; + std::string temp_file_path_str_; + base::File temp_file_; +}; + +// Try inotify_add_watch() without the relevant broker command. +class InotifyAddWatchNoCommandDelegate final : public InotifyAddWatchDelegate { + public: + BrokerParams ChildSetUpPreSandbox() override { + BrokerParams params; + params.allowed_command_set = syscall_broker::MakeBrokerCommandSet({}); + params.permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + temp_file_path_str_), + BrokerFilePermission::ReadWriteCreateRecursive(nested_temp_dir_str_ + + "/")}; + return params; + } + + void RunTestInSandboxedChild(Syscaller* syscaller) override { + base::ScopedFD inotify_instance(inotify_init()); + BPF_ASSERT(inotify_instance.is_valid()); + BPF_ASSERT_EQ( + -kFakeErrnoSentinel, + syscaller->InotifyAddWatch(inotify_instance.get(), + nested_temp_dir_str_.c_str(), kGoodMask)); + } +}; + +TEST(BrokerProcessIntegrationTest, InotifyAddWatchNoCommand) { + RunAllBrokerTests<InotifyAddWatchNoCommandDelegate>(); +} + +// Try inotify_add_watch() without the relevant permissions. +class InotifyAddWatchNoPermissionsDelegate final + : public InotifyAddWatchDelegate { + public: + BrokerParams ChildSetUpPreSandbox() override { + BrokerParams params; + params.allowed_command_set = syscall_broker::MakeBrokerCommandSet( + {syscall_broker::COMMAND_INOTIFY_ADD_WATCH}); + params.permissions = {}; + return params; + } + + void RunTestInSandboxedChild(Syscaller* syscaller) override { + base::ScopedFD inotify_instance(inotify_init()); + BPF_ASSERT(inotify_instance.is_valid()); + BPF_ASSERT_EQ( + -kFakeErrnoSentinel, + syscaller->InotifyAddWatch(inotify_instance.get(), + nested_temp_dir_str_.c_str(), kGoodMask)); + } +}; + +TEST(BrokerProcessIntegrationTest, InotifyAddWatchNoPermissions) { + RunAllBrokerTests<InotifyAddWatchNoPermissionsDelegate>(); +} + +// Try inotify_add_watch() with a variety of bad arguments. +class InotifyAddWatchBadArgumentsDelegate final + : public InotifyAddWatchDelegate { + public: + void ParentSetUp() override { + InotifyAddWatchDelegate::ParentSetUp(); + + ASSERT_TRUE( + other_temp_dir_.Set(temp_dir_.GetPath().AppendASCII("other_temp_dir"))); + other_temp_dir_str_ = other_temp_dir_.GetPath().MaybeAsASCII(); + ASSERT_FALSE(other_temp_dir_str_.empty()); + + base::FilePath bad_prefix = temp_dir_.GetPath().AppendASCII(kBadPrefixName); + bad_prefix_str_ = bad_prefix.MaybeAsASCII(); + ASSERT_FALSE(bad_prefix_str_.empty()); + } + + BrokerParams ChildSetUpPreSandbox() override { + BrokerParams params; + params.allowed_command_set = syscall_broker::MakeBrokerCommandSet( + {syscall_broker::COMMAND_INOTIFY_ADD_WATCH}); + params.permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + temp_file_path_str_)}; + return params; + } + + void RunTestInSandboxedChild(Syscaller* syscaller) override { + base::ScopedFD inotify_instance(inotify_init()); + BPF_ASSERT(inotify_instance.is_valid()); + // Watch the correct directory with bad flags. + BPF_ASSERT_EQ( + -kFakeErrnoSentinel, + syscaller->InotifyAddWatch(inotify_instance.get(), + nested_temp_dir_str_.c_str(), kBadMask)); + + // Try to watch an unintended directory, should fail. + BPF_ASSERT_EQ( + -kFakeErrnoSentinel, + syscaller->InotifyAddWatch(inotify_instance.get(), + other_temp_dir_str_.c_str(), kGoodMask)); + + // Try to access a prefix that isn't a full directory. + BPF_ASSERT_EQ(-kFakeErrnoSentinel, syscaller->InotifyAddWatch( + inotify_instance.get(), + bad_prefix_str_.c_str(), kGoodMask)); + } + + protected: + // Another directory nested under |temp_dir_| with no sandbox permissions. + base::ScopedTempDir other_temp_dir_; + std::string other_temp_dir_str_; + + // A prefix of |nested_temp_dir_| that doesn't match a valid directory. + std::string bad_prefix_str_; +}; + +TEST(BrokerProcessIntegrationTest, InotifyAddWatchBadArguments) { + RunAllBrokerTests<InotifyAddWatchBadArgumentsDelegate>(); +} + +// Use inottify_add_watch() successfully and verify it actually works. +class InotifyAddWatchSuccessDelegate final : public InotifyAddWatchDelegate { + public: + BrokerParams ChildSetUpPreSandbox() override { + BrokerParams params; + params.allowed_command_set = syscall_broker::MakeBrokerCommandSet( + {syscall_broker::COMMAND_INOTIFY_ADD_WATCH, + syscall_broker::COMMAND_UNLINK}); + params.permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + temp_file_path_str_), + BrokerFilePermission::ReadWriteCreateRecursive(nested_temp_dir_str_ + + "/")}; + return params; + } + + void RunTestInSandboxedChild(Syscaller* syscaller) override { + base::ScopedFD inotify_instance(inotify_init()); + BPF_ASSERT(inotify_instance.is_valid()); + // This inotify_add_watch() call should succeed. + int wd = syscaller->InotifyAddWatch( + inotify_instance.get(), nested_temp_dir_str_.c_str(), kGoodMask); + BPF_ASSERT_GE(wd, 0); + + // Unlinking the file generates an inotify notification. + BPF_ASSERT_GE(unlink(temp_file_path_str_.c_str()), 0); + + // Read one inotify message and verify it names the correct watch descriptor + // |wd|. The test will timeout if no inotify notifications are ever + // generated. + std::vector<char> buf(4096); + BPF_ASSERT_GE(read(inotify_instance.get(), buf.data(), buf.size()), 0); + struct inotify_event* event = + reinterpret_cast<struct inotify_event*>(buf.data()); + BPF_ASSERT_EQ(event->wd, wd); + + // Removing the watch should succeed. + BPF_ASSERT_GE(inotify_rm_watch(inotify_instance.get(), wd), 0); + } +}; + +TEST(BrokerProcessIntegrationTest, InotifyAddWatchSuccess) { + RunAllBrokerTests<InotifyAddWatchSuccessDelegate>(); +} + +// Tests base::FilePathWatcher which uses inotify on Linux. +// This is used in the network service sandbox. +class BaseFilePathWatcherDelegate final : public InotifyAddWatchDelegate { + public: + BrokerParams ChildSetUpPreSandbox() override { + // Prewarm file accesses. + base::GetMaxNumberOfInotifyWatches(); + + BrokerParams params; + params.allowed_command_set = syscall_broker::MakeBrokerCommandSet( + {syscall_broker::COMMAND_INOTIFY_ADD_WATCH, + syscall_broker::COMMAND_OPEN}); + params.permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + temp_file_path_str_), + BrokerFilePermission::ReadWriteCreateRecursive(nested_temp_dir_str_ + + "/")}; + return params; + } + + void RunTestInSandboxedChild(Syscaller* syscaller) override { + base::test::SingleThreadTaskEnvironment task_environment( + base::test::TaskEnvironment::MainThreadType::IO); + + // Watch the file and wait for a notification about that file from + // FilePathWatcher. + base::RunLoop run_loop; + base::FilePathWatcher file_watcher_; + BPF_ASSERT(file_watcher_.Watch( + temp_file_path_, base::FilePathWatcher::Type::kNonRecursive, + base::BindLambdaForTesting([&](const base::FilePath& path, bool error) { + BPF_ASSERT_EQ(temp_file_path_, path); + run_loop.Quit(); + }))); + + // Our inotify file path watcher requires a file to be opened for writing + // *after* adding the watch, and then closed, in order to generate a + // notification. The actual call to Write() isn't even strictly necessary. + // Another way to generate a notification is + // base::DeleteFile(temp_file_path_). + base::File temp_file_again(temp_file_path_, base::File::FLAG_OPEN | + base::File::FLAG_READ | + base::File::FLAG_WRITE); + char buf2[] = "a"; + BPF_ASSERT_EQ(temp_file_again.Write(0, buf2, sizeof(buf2)), sizeof(buf2)); + temp_file_again.Flush(); + temp_file_again.Close(); + // Wait until we receive a notification about the file modification. + // Failure results in a test timeout. + run_loop.Run(); + } +}; + +TEST(BrokerProcessIntegrationTest, BaseFilePathWatcherInotifyTest) { + const std::vector<BrokerTestConfiguration> inotify_test_configs = { + {"FastCheckInClient_NoSyscaller", true, SyscallerType::NoSyscaller, + BrokerType::SIGNAL_BASED}, + {"NoFastCheckInClient_NoSyscaller", false, SyscallerType::NoSyscaller, + BrokerType::SIGNAL_BASED}, + }; + + for (const BrokerTestConfiguration& test_config : inotify_test_configs) { + SCOPED_TRACE(test_config.test_name); + auto test_delegate = std::make_unique<BaseFilePathWatcherDelegate>(); + RunSingleBrokerTest(test_delegate.get(), test_config); + } +} + #endif // !defined(THREAD_SANITIZER) } // namespace sandbox
diff --git a/sandbox/linux/syscall_broker/broker_client.cc b/sandbox/linux/syscall_broker/broker_client.cc index 05d99ba5..0aace79 100644 --- a/sandbox/linux/syscall_broker/broker_client.cc +++ b/sandbox/linux/syscall_broker/broker_client.cc
@@ -207,6 +207,38 @@ return PathOnlySyscall(COMMAND_UNLINK, path); } +int BrokerClient::InotifyAddWatch(int fd, + const char* pathname, + uint32_t mask) const { + if (!pathname) + return -EFAULT; + + if (fast_check_in_client_ && + !CommandInotifyAddWatchIsSafe(policy_->allowed_command_set, + *policy_->file_permissions, pathname, mask, + nullptr)) { + return -policy_->file_permissions->denied_errno(); + } + + BrokerSimpleMessage message; + RAW_CHECK(message.AddIntToMessage(COMMAND_INOTIFY_ADD_WATCH)); + RAW_CHECK(message.AddStringToMessage(pathname)); + RAW_CHECK(message.AddIntToMessage(mask)); + + BrokerSimpleMessage reply; + ssize_t msg_len = message.SendRecvMsgWithFlagsMultipleFds( + ipc_channel_.get(), 0, base::span<const int>(&fd, 1), {}, &reply); + + if (msg_len < 0) + return msg_len; + + int return_value = -1; + if (!reply.ReadInt(&return_value)) + return -ENOMEM; + + return return_value; +} + int BrokerClient::PathOnlySyscall(BrokerCommand syscall_type, const char* pathname) const { BrokerSimpleMessage message;
diff --git a/sandbox/linux/syscall_broker/broker_client.h b/sandbox/linux/syscall_broker/broker_client.h index f96e77e..9d0fdee 100644 --- a/sandbox/linux/syscall_broker/broker_client.h +++ b/sandbox/linux/syscall_broker/broker_client.h
@@ -68,6 +68,9 @@ bool follow_links, struct kernel_stat64* sb) const override; int Unlink(const char* unlink) const override; + int InotifyAddWatch(int fd, + const char* pathname, + uint32_t mask) const override; const BrokerSandboxConfig& policy() const { return *policy_; }
diff --git a/sandbox/linux/syscall_broker/broker_command.cc b/sandbox/linux/syscall_broker/broker_command.cc index 340305d..79d27b0d 100644 --- a/sandbox/linux/syscall_broker/broker_command.cc +++ b/sandbox/linux/syscall_broker/broker_command.cc
@@ -95,5 +95,15 @@ filename_to_use, nullptr); } +bool CommandInotifyAddWatchIsSafe(const BrokerCommandSet& command_set, + const BrokerPermissionList& policy, + const char* requested_filename, + uint32_t mask, + const char** filename_to_use) { + return command_set.test(COMMAND_INOTIFY_ADD_WATCH) && + policy.GetFileNameIfAllowedToInotifyAddWatch(requested_filename, mask, + filename_to_use); +} + } // namespace syscall_broker } // namespace sandbox
diff --git a/sandbox/linux/syscall_broker/broker_command.h b/sandbox/linux/syscall_broker/broker_command.h index 514c5f6..468d9056 100644 --- a/sandbox/linux/syscall_broker/broker_command.h +++ b/sandbox/linux/syscall_broker/broker_command.h
@@ -42,9 +42,10 @@ COMMAND_STAT, COMMAND_STAT64, COMMAND_UNLINK, + COMMAND_INOTIFY_ADD_WATCH, // NOTE: update when adding new commands. - COMMAND_MAX = COMMAND_UNLINK + COMMAND_MAX = COMMAND_INOTIFY_ADD_WATCH }; using BrokerCommandSet = std::bitset<COMMAND_MAX + 1>; @@ -106,6 +107,12 @@ const char* requested_filename, const char** filename_to_use); +bool CommandInotifyAddWatchIsSafe(const BrokerCommandSet& command_set, + const BrokerPermissionList& policy, + const char* requested_filename, + uint32_t mask, + const char** filename_to_use); + } // namespace syscall_broker } // namespace sandbox
diff --git a/sandbox/linux/syscall_broker/broker_file_permission.cc b/sandbox/linux/syscall_broker/broker_file_permission.cc index b399455..02fbf8b6 100644 --- a/sandbox/linux/syscall_broker/broker_file_permission.cc +++ b/sandbox/linux/syscall_broker/broker_file_permission.cc
@@ -7,6 +7,7 @@ #include <fcntl.h> #include <stddef.h> #include <string.h> +#include <sys/inotify.h> #include <unistd.h> #include <ostream> @@ -206,8 +207,9 @@ return true; } -bool BrokerFilePermission::CheckStat(const char* requested_filename, - const char** file_to_access) const { +bool BrokerFilePermission::CheckStatWithIntermediates( + const char* requested_filename, + const char** file_to_access) const { if (!ValidatePath(requested_filename)) return false; @@ -219,26 +221,64 @@ if (!(allow_create() || allow_stat_with_intermediates())) return false; - // NOTE: ValidatePath proved requested_length != 0; + // |allow_stat_with_intermediates()| can match on the full path, and + // |allow_create()| only matches a leading directory. + if (!CheckIntermediates( + requested_filename, + /*can_match_full_path=*/allow_stat_with_intermediates())) + return false; + + if (file_to_access) + *file_to_access = requested_filename; + + return true; +} + +bool BrokerFilePermission::CheckInotifyAddWatchWithIntermediates( + const char* requested_filename, + uint32_t mask, + const char** file_to_inotify_add_watch) const { + if (!allow_inotify_add_watch_with_intermediates()) + return false; + + if (!ValidatePath(requested_filename)) + return false; + + // Allow only this exact mask as it is used by + // base/files/file_path_watcher_inotify.cc. + if (mask != (IN_ATTRIB | IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | + IN_ONLYDIR)) + return false; + + if (!CheckIntermediates(requested_filename, + /*can_match_full_path=*/true)) + return false; + + if (file_to_inotify_add_watch) + *file_to_inotify_add_watch = requested_filename; + + return true; +} + +bool BrokerFilePermission::CheckIntermediates(const char* requested_filename, + bool can_match_full_path) const { + // NOTE: ValidatePath proves requested_length != 0 and |requested_filename| is + // absolute. size_t requested_length = strlen(requested_filename); CHECK(requested_length); + CHECK(requested_filename[0] == '/'); // Special case for root: only one slash, otherwise must have a second // slash in the right spot to avoid substring matches. - // |allow_stat_with_intermediates()| can match on the full path, and - // |allow_create()| only matches a leading directory. - if ((requested_length == 1 && requested_filename[0] == '/') || - (allow_stat_with_intermediates() && path_ == requested_filename) || - (requested_length < path_.length() && - memcmp(path_.c_str(), requested_filename, requested_length) == 0 && - path_.c_str()[requested_length] == '/')) { - if (file_to_access) - *file_to_access = requested_filename; - - return true; - } - - return false; + return (requested_length == 1 && requested_filename[0] == '/') || + // If this permission can match the full path, compare directly to the + // requested filename. + (can_match_full_path && path_ == requested_filename) || + // Check whether |requested_filename| matches a leading directory of + // |path_|. + (requested_length < path_.length() && + memcmp(path_.c_str(), requested_filename, requested_length) == 0 && + path_.c_str()[requested_length] == '/'); } const char* BrokerFilePermission::GetErrorMessageForTests() { @@ -256,9 +296,10 @@ if (temporary_only()) CHECK(allow_create()) << GetErrorMessageForTests(); - // Recursive paths must have a trailing slash, absolutes must not. - const char last_char = *(path_.rbegin()); - if (recursive()) + // Recursive paths must have a trailing slash, absolutes must not (except + // root). + const char last_char = path_.back(); + if (recursive() || path_.length() == 1) CHECK(last_char == '/') << GetErrorMessageForTests(); else CHECK(last_char != '/') << GetErrorMessageForTests(); @@ -276,7 +317,8 @@ ReadPermission read_perm, WritePermission write_perm, CreatePermission create_perm, - StatWithIntermediatesPermission stat_perm) + StatWithIntermediatesPermission stat_perm, + InotifyAddWatchWithIntermediatesPermission inotify_perm) : path_(std::move(path)) { flags_[kRecursiveBitPos] = recurse_opt == RecursionOption::kRecursive; flags_[kTemporaryOnlyBitPos] = @@ -286,6 +328,9 @@ flags_[kAllowCreateBitPos] = create_perm == CreatePermission::kAllowCreate; flags_[kAllowStatWithIntermediatesBitPos] = stat_perm == StatWithIntermediatesPermission::kAllowStatWithIntermediates; + flags_[kAllowInotifyAddWatchWithIntermediates] = + inotify_perm == InotifyAddWatchWithIntermediatesPermission:: + kAllowInotifyAddWatchWithIntermediates; DieOnInvalidPermission(); }
diff --git a/sandbox/linux/syscall_broker/broker_file_permission.h b/sandbox/linux/syscall_broker/broker_file_permission.h index b167ffb0..a9577adf 100644 --- a/sandbox/linux/syscall_broker/broker_file_permission.h +++ b/sandbox/linux/syscall_broker/broker_file_permission.h
@@ -25,6 +25,10 @@ kBlockStatWithIntermediates = 0, kAllowStatWithIntermediates }; +enum class InotifyAddWatchWithIntermediatesPermission { + kBlockInotifyAddWatchWithIntermediates = 0, + kAllowInotifyAddWatchWithIntermediates +}; // BrokerFilePermission defines a path for allowlisting. // Pick the correct static factory method to create a permission. @@ -46,7 +50,9 @@ path, RecursionOption::kNonRecursive, PersistenceOption::kPermanent, ReadPermission::kAllowRead, WritePermission::kBlockWrite, CreatePermission::kBlockCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission ReadOnlyRecursive(const std::string& path) { @@ -54,7 +60,9 @@ path, RecursionOption::kRecursive, PersistenceOption::kPermanent, ReadPermission::kAllowRead, WritePermission::kBlockWrite, CreatePermission::kBlockCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission WriteOnly(const std::string& path) { @@ -62,7 +70,9 @@ path, RecursionOption::kNonRecursive, PersistenceOption::kPermanent, ReadPermission::kBlockRead, WritePermission::kAllowWrite, CreatePermission::kBlockCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission ReadWrite(const std::string& path) { @@ -70,7 +80,9 @@ path, RecursionOption::kNonRecursive, PersistenceOption::kPermanent, ReadPermission::kAllowRead, WritePermission::kAllowWrite, CreatePermission::kBlockCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission ReadWriteCreate(const std::string& path) { @@ -78,7 +90,9 @@ path, RecursionOption::kNonRecursive, PersistenceOption::kPermanent, ReadPermission::kAllowRead, WritePermission::kAllowWrite, CreatePermission::kAllowCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission ReadWriteCreateRecursive( @@ -87,7 +101,9 @@ path, RecursionOption::kRecursive, PersistenceOption::kPermanent, ReadPermission::kAllowRead, WritePermission::kAllowWrite, CreatePermission::kAllowCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } // Temporary files must always be newly created and do not confer rights to @@ -98,7 +114,9 @@ path, RecursionOption::kNonRecursive, PersistenceOption::kTemporaryOnly, ReadPermission::kAllowRead, WritePermission::kAllowWrite, CreatePermission::kAllowCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission ReadWriteCreateTemporaryRecursive( @@ -107,7 +125,9 @@ path, RecursionOption::kRecursive, PersistenceOption::kTemporaryOnly, ReadPermission::kAllowRead, WritePermission::kAllowWrite, CreatePermission::kAllowCreate, - StatWithIntermediatesPermission::kBlockStatWithIntermediates); + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); } static BrokerFilePermission StatOnlyWithIntermediateDirs( @@ -116,7 +136,20 @@ path, RecursionOption::kNonRecursive, PersistenceOption::kPermanent, ReadPermission::kBlockRead, WritePermission::kBlockWrite, CreatePermission::kBlockCreate, - StatWithIntermediatesPermission::kAllowStatWithIntermediates); + StatWithIntermediatesPermission::kAllowStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kBlockInotifyAddWatchWithIntermediates); + } + + static BrokerFilePermission InotifyAddWatchWithIntermediateDirs( + const std::string& path) { + return BrokerFilePermission( + path, RecursionOption::kNonRecursive, PersistenceOption::kPermanent, + ReadPermission::kBlockRead, WritePermission::kBlockWrite, + CreatePermission::kBlockCreate, + StatWithIntermediatesPermission::kBlockStatWithIntermediates, + InotifyAddWatchWithIntermediatesPermission:: + kAllowInotifyAddWatchWithIntermediates); } // Returns true if |requested_filename| is allowed to be accessed @@ -149,13 +182,29 @@ // by this permission as per stat(2). Differs from CheckAccess() // in that if create permission is granted to a file, we permit // stat() on all of its leading components. - // If |file_to_open| is not NULL, it is set to point to either + // If |file_to_access| is not NULL, it is set to point to either // the |requested_filename| in the case of a recursive match, // or a pointer to the matched path in the allowlist if an absolute // match. // Async signal safe if |file_to_access| is NULL - bool CheckStat(const char* requested_filename, - const char** file_to_access) const; + bool CheckStatWithIntermediates(const char* requested_filename, + const char** file_to_access) const; + + // Returns true if |requested_filename| is allowed by this permission to be + // added to an inotify instance's watch list by inotify_add_watch(2), with the + // specific |mask|. Differs from CheckAccess() in that if inotify_add_watch + // permission is granted to a file, we permit inotify_add_watch() on all of + // its leading components. + // + // If |file_to_inotify_add_watch| is not NULL, it is set to point to either + // the |requested_filename| in the case of a recursive match, or a pointer to + // the matched path in the allowlist if an absolute match. + // + // Async signal safe if |file_to_inotify_add_watch| is NULL + bool CheckInotifyAddWatchWithIntermediates( + const char* requested_filename, + uint32_t mask, + const char** file_to_inotify_add_watch) const; private: friend class BrokerFilePermissionTester; @@ -167,8 +216,9 @@ kAllowWriteBitPos, kAllowCreateBitPos, kAllowStatWithIntermediatesBitPos, + kAllowInotifyAddWatchWithIntermediates, - kMaxValueBitPos = kAllowStatWithIntermediatesBitPos + kMaxValueBitPos = kAllowInotifyAddWatchWithIntermediates }; // NOTE: Validates the permission and dies if invalid! @@ -178,7 +228,8 @@ ReadPermission read_perm, WritePermission write_perm, CreatePermission create_perm, - StatWithIntermediatesPermission stat_perm); + StatWithIntermediatesPermission stat_perm, + InotifyAddWatchWithIntermediatesPermission inotify_perm); // Allows construction from the raw bitset. BrokerFilePermission(std::string path, uint64_t flags); @@ -202,6 +253,10 @@ return flags_.test(kAllowStatWithIntermediatesBitPos); } + bool allow_inotify_add_watch_with_intermediates() const { + return flags_.test(kAllowInotifyAddWatchWithIntermediates); + } + // ValidatePath checks |path| and returns true if these conditions are met // * Greater than 0 length // * Is an absolute path @@ -218,6 +273,14 @@ int mode, const char** file_to_access) const; + // Helper routine for CheckStatWithIntermediates() and + // CheckInotifyAddWatchWithIntermediates() to return true if one of the + // following is true: + // 1. |requested_filename| matches a leading directory of |path_|. + // 2. |can_match_full_path| is true and |path_| == |requested_filename|. + bool CheckIntermediates(const char* requested_filename, + bool can_match_full_path) const; + // Used in by BrokerFilePermissionTester for tests. static const char* GetErrorMessageForTests();
diff --git a/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc b/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc index dd3df5a5..65d3d640 100644 --- a/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc +++ b/sandbox/linux/syscall_broker/broker_file_permission_unittest.cc
@@ -6,6 +6,7 @@ #include <fcntl.h> #include <string.h> +#include <sys/inotify.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> @@ -265,23 +266,65 @@ const char kLeading1[] = "/"; const char kLeading2[] = "/tmp"; const char kLeading3[] = "/tmp/good/path"; + const char kBadPrefix[] = "/tmp/good/pa"; const char kTrailing[] = "/tmp/good/path/bad"; BrokerFilePermission perm = BrokerFilePermission::StatOnlyWithIntermediateDirs(kPath); // No open or access permission. - ASSERT_FALSE(perm.CheckOpen(kPath, O_RDONLY, NULL, NULL)); - ASSERT_FALSE(perm.CheckOpen(kPath, O_WRONLY, NULL, NULL)); - ASSERT_FALSE(perm.CheckOpen(kPath, O_RDWR, NULL, NULL)); - ASSERT_FALSE(perm.CheckAccess(kPath, R_OK, NULL)); - ASSERT_FALSE(perm.CheckAccess(kPath, W_OK, NULL)); + ASSERT_FALSE(perm.CheckOpen(kPath, O_RDONLY, nullptr, nullptr)); + ASSERT_FALSE(perm.CheckOpen(kPath, O_WRONLY, nullptr, nullptr)); + ASSERT_FALSE(perm.CheckOpen(kPath, O_RDWR, nullptr, nullptr)); + ASSERT_FALSE(perm.CheckAccess(kPath, R_OK, nullptr)); + ASSERT_FALSE(perm.CheckAccess(kPath, W_OK, nullptr)); // Stat for all leading paths, but not trailing paths. - ASSERT_TRUE(perm.CheckStat(kPath, NULL)); - ASSERT_TRUE(perm.CheckStat(kLeading1, NULL)); - ASSERT_TRUE(perm.CheckStat(kLeading2, NULL)); - ASSERT_TRUE(perm.CheckStat(kLeading3, NULL)); - ASSERT_FALSE(perm.CheckStat(kTrailing, NULL)); + ASSERT_TRUE(perm.CheckStatWithIntermediates(kPath, nullptr)); + ASSERT_TRUE(perm.CheckStatWithIntermediates(kLeading1, nullptr)); + ASSERT_TRUE(perm.CheckStatWithIntermediates(kLeading2, nullptr)); + ASSERT_TRUE(perm.CheckStatWithIntermediates(kLeading3, nullptr)); + ASSERT_FALSE(perm.CheckStatWithIntermediates(kBadPrefix, nullptr)); + ASSERT_FALSE(perm.CheckStatWithIntermediates(kTrailing, nullptr)); +} + +TEST(BrokerFilePermission, InotifyAddWatchWithIntermediateDirs) { + const char kPath[] = "/tmp/good/path"; + const char kLeading1[] = "/"; + const char kLeading2[] = "/tmp"; + const char kLeading3[] = "/tmp/good/path"; + const char kBadPrefix[] = "/tmp/good/pa"; + const char kTrailing[] = "/tmp/good/path/bad"; + + const uint32_t kBadMask = + IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_ONLYDIR; + const uint32_t kGoodMask = kBadMask | IN_ATTRIB; + + BrokerFilePermission perm = + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(kPath); + // No open or access permission. + ASSERT_FALSE(perm.CheckOpen(kPath, O_RDONLY, nullptr, nullptr)); + ASSERT_FALSE(perm.CheckOpen(kPath, O_WRONLY, nullptr, nullptr)); + ASSERT_FALSE(perm.CheckOpen(kPath, O_RDWR, nullptr, nullptr)); + ASSERT_FALSE(perm.CheckAccess(kPath, R_OK, nullptr)); + ASSERT_FALSE(perm.CheckAccess(kPath, W_OK, nullptr)); + + // Inotify_add_watch for all leading paths, but not trailing paths. + ASSERT_TRUE( + perm.CheckInotifyAddWatchWithIntermediates(kPath, kGoodMask, nullptr)); + ASSERT_TRUE(perm.CheckInotifyAddWatchWithIntermediates(kLeading1, kGoodMask, + nullptr)); + ASSERT_TRUE(perm.CheckInotifyAddWatchWithIntermediates(kLeading2, kGoodMask, + nullptr)); + ASSERT_TRUE(perm.CheckInotifyAddWatchWithIntermediates(kLeading3, kGoodMask, + nullptr)); + ASSERT_FALSE(perm.CheckInotifyAddWatchWithIntermediates(kBadPrefix, kGoodMask, + nullptr)); + ASSERT_FALSE(perm.CheckInotifyAddWatchWithIntermediates(kTrailing, kGoodMask, + nullptr)); + + // Fails without correct mask. + ASSERT_FALSE( + perm.CheckInotifyAddWatchWithIntermediates(kPath, kBadMask, nullptr)); } TEST(BrokerFilePermission, ValidatePath) {
diff --git a/sandbox/linux/syscall_broker/broker_host.cc b/sandbox/linux/syscall_broker/broker_host.cc index de86b08..99b5fa7 100644 --- a/sandbox/linux/syscall_broker/broker_host.cc +++ b/sandbox/linux/syscall_broker/broker_host.cc
@@ -8,12 +8,14 @@ #include <fcntl.h> #include <limits.h> #include <stddef.h> +#include <sys/inotify.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/syscall.h> #include <sys/types.h> #include <unistd.h> +#include <array> #include <string> #include <utility> @@ -51,12 +53,12 @@ // permission_list. Write the syscall return value (-errno) to |reply|. void AccessFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& requested_filename, + const char* requested_filename, int mode, BrokerSimpleMessage* reply) { const char* file_to_access = NULL; if (!CommandAccessIsSafe(allowed_command_set, permission_list, - requested_filename.c_str(), mode, &file_to_access)) { + requested_filename, mode, &file_to_access)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -70,16 +72,16 @@ RAW_CHECK(reply->AddIntToMessage(0)); } -// Performs mkdir(2) on |filename| with mode |mode| if allowed by our +// Performs mkdir(2) on |requested_filename| with mode |mode| if allowed by our // permission_list. Write the syscall return value (-errno) to |reply|. void MkdirFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& filename, + const char* requested_filename, int mode, BrokerSimpleMessage* reply) { const char* file_to_access = nullptr; if (!CommandMkdirIsSafe(allowed_command_set, permission_list, - filename.c_str(), &file_to_access)) { + requested_filename, &file_to_access)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -95,14 +97,14 @@ // file descriptor in the |opened_file| if relevant. void OpenFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& requested_filename, + const char* requested_filename, int flags, BrokerSimpleMessage* reply, base::ScopedFD* opened_file) { - const char* file_to_open = NULL; + const char* file_to_open = nullptr; bool unlink_after_open = false; if (!CommandOpenIsSafe(allowed_command_set, permission_list, - requested_filename.c_str(), flags, &file_to_open, + requested_filename, flags, &file_to_open, &unlink_after_open)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; @@ -125,14 +127,14 @@ // result to |return_val|. void RenameFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& old_filename, - const std::string& new_filename, + const char* old_filename, + const char* new_filename, BrokerSimpleMessage* reply) { const char* old_file_to_access = nullptr; const char* new_file_to_access = nullptr; - if (!CommandRenameIsSafe(allowed_command_set, permission_list, - old_filename.c_str(), new_filename.c_str(), - &old_file_to_access, &new_file_to_access)) { + if (!CommandRenameIsSafe(allowed_command_set, permission_list, old_filename, + new_filename, &old_file_to_access, + &new_file_to_access)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -146,11 +148,11 @@ // Perform readlink(2) on |filename| using a buffer of MAX_PATH bytes. void ReadlinkFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& filename, + const char* requested_filename, BrokerSimpleMessage* reply) { const char* file_to_access = nullptr; if (!CommandReadlinkIsSafe(allowed_command_set, permission_list, - filename.c_str(), &file_to_access)) { + requested_filename, &file_to_access)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -166,11 +168,11 @@ void RmdirFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& requested_filename, + const char* requested_filename, BrokerSimpleMessage* reply) { const char* file_to_access = nullptr; if (!CommandRmdirIsSafe(allowed_command_set, permission_list, - requested_filename.c_str(), &file_to_access)) { + requested_filename, &file_to_access)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -186,12 +188,12 @@ void StatFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, BrokerCommand command_type, - const std::string& requested_filename, + const char* requested_filename, bool follow_links, BrokerSimpleMessage* reply) { const char* file_to_access = nullptr; if (!CommandStatIsSafe(allowed_command_set, permission_list, - requested_filename.c_str(), &file_to_access)) { + requested_filename, &file_to_access)) { RAW_CHECK(reply->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -232,11 +234,11 @@ void UnlinkFileForIPC(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, - const std::string& requested_filename, + const char* requested_filename, BrokerSimpleMessage* message) { const char* file_to_access = nullptr; if (!CommandUnlinkIsSafe(allowed_command_set, permission_list, - requested_filename.c_str(), &file_to_access)) { + requested_filename, &file_to_access)) { RAW_CHECK(message->AddIntToMessage(-permission_list.denied_errno())); return; } @@ -247,11 +249,34 @@ RAW_CHECK(message->AddIntToMessage(0)); } +void InotifyAddWatchForIPC(const BrokerCommandSet& allowed_command_set, + const BrokerPermissionList& permission_list, + base::ScopedFD inotify_fd, + const char* requested_filename, + uint32_t mask, + BrokerSimpleMessage* message) { + const char* file_to_access = nullptr; + if (!CommandInotifyAddWatchIsSafe(allowed_command_set, permission_list, + requested_filename, mask, + &file_to_access)) { + RAW_CHECK(message->AddIntToMessage(-permission_list.denied_errno())); + return; + } + + int wd = inotify_add_watch(inotify_fd.get(), file_to_access, mask); + if (wd < 0) { + RAW_CHECK(message->AddIntToMessage(-errno)); + return; + } + RAW_CHECK(message->AddIntToMessage(wd)); +} + // Handle a |command_type| request contained in |iter| and write the reply // to |reply|. bool HandleRemoteCommand(const BrokerCommandSet& allowed_command_set, const BrokerPermissionList& permission_list, BrokerSimpleMessage* message, + base::span<base::ScopedFD> recv_fds, BrokerSimpleMessage* reply, base::ScopedFD* opened_file) { // Message structure: @@ -340,6 +365,20 @@ reply); break; } + case COMMAND_INOTIFY_ADD_WATCH: { + const char* requested_filename; + if (!message->ReadString(&requested_filename)) + return false; + int mask; + if (!message->ReadInt(&mask)) + return false; + if (!recv_fds[0].is_valid()) + return false; + InotifyAddWatchForIPC(allowed_command_set, permission_list, + std::move(recv_fds[0]), requested_filename, mask, + reply); + break; + } default: LOG(ERROR) << "Invalid IPC command"; return false; @@ -364,26 +403,33 @@ BrokerSimpleMessage message; errno = 0; base::ScopedFD temporary_ipc; + std::array<base::ScopedFD, 2> recv_fds_arr; + base::span<base::ScopedFD> recv_fds(recv_fds_arr); const ssize_t msg_len = - message.RecvMsgWithFlags(ipc_channel_.get(), 0, &temporary_ipc); + message.RecvMsgWithFlagsMultipleFds(ipc_channel_.get(), 0, recv_fds); if (msg_len == 0 || (msg_len == -1 && errno == ECONNRESET)) { // EOF from the client, or the client died, we should finish looping. return; } - // The client sends exactly one file descriptor, on which we - // will write the reply. - if (msg_len < 0) { + // This indicates an error occurred in IPC. For example, too many fds were + // sent along with the message. + if (msg_len < 0 || !recv_fds[0].is_valid()) { + if (!recv_fds[0].is_valid()) { + errno = EBADF; + } PLOG(ERROR) << "Error reading message from the client"; continue; } + temporary_ipc = std::move(recv_fds[0]); + BrokerSimpleMessage reply; base::ScopedFD opened_file; if (!HandleRemoteCommand(policy_->allowed_command_set, - *policy_->file_permissions, &message, &reply, - &opened_file)) { + *policy_->file_permissions, &message, + recv_fds.subspan(1), &reply, &opened_file)) { // Does not exit if we received a malformed message. LOG(ERROR) << "Received malformed message from the client"; continue;
diff --git a/sandbox/linux/syscall_broker/broker_permission_list.cc b/sandbox/linux/syscall_broker/broker_permission_list.cc index f949797..3d28d7f 100644 --- a/sandbox/linux/syscall_broker/broker_permission_list.cc +++ b/sandbox/linux/syscall_broker/broker_permission_list.cc
@@ -111,7 +111,23 @@ return false; for (size_t i = 0; i < num_of_permissions_; i++) { - if (permissions_array_[i].CheckStat(requested_filename, file_to_stat)) + if (permissions_array_[i].CheckStatWithIntermediates(requested_filename, + file_to_stat)) + return true; + } + return false; +} + +bool BrokerPermissionList::GetFileNameIfAllowedToInotifyAddWatch( + const char* requested_filename, + uint32_t mask, + const char** file_to_inotify_add_watch) const { + if (!CheckCallerArgs(file_to_inotify_add_watch)) + return false; + + for (size_t i = 0; i < num_of_permissions_; i++) { + if (permissions_array_[i].CheckInotifyAddWatchWithIntermediates( + requested_filename, mask, file_to_inotify_add_watch)) return true; } return false;
diff --git a/sandbox/linux/syscall_broker/broker_permission_list.h b/sandbox/linux/syscall_broker/broker_permission_list.h index 98580ed..8524df5 100644 --- a/sandbox/linux/syscall_broker/broker_permission_list.h +++ b/sandbox/linux/syscall_broker/broker_permission_list.h
@@ -46,11 +46,10 @@ // If |file_to_open| is not NULL, a pointer to the path will be returned. // In the case of a recursive match, this will be the requested_filename, // otherwise it will return the matching pointer from the - // allowlist. For paranoia a caller should then use |file_to_access|. See - // GetFileNameIfAllowedToOpen() for more explanation. - // return true if calling access() on this file should be allowed, false - // otherwise. - // Async signal safe if and only if |file_to_access| is NULL. + // allowlist. A caller should then use |file_to_access|. See + // GetFileNameIfAllowedToOpen() for more explanation. return true if calling + // access() on this file should be allowed, false otherwise. Async signal safe + // if and only if |file_to_access| is NULL. bool GetFileNameIfAllowedToAccess(const char* requested_filename, int requested_mode, const char** file_to_access) const; @@ -59,8 +58,8 @@ // If |file_to_open| is not NULL, a pointer to the path will be returned. // In the case of a recursive match, this will be the requested_filename, // otherwise it will return the matching pointer from the - // allowlist. For paranoia, a caller should then use |file_to_open| rather - // than |requested_filename|, so that it never attempts to open an + // allowlist. A caller should then use |file_to_open| rather than + // |requested_filename|, so that it never attempts to open an // attacker-controlled file name, even if an attacker managed to fool the // string comparison mechanism. // |unlink_after_open| if not NULL will be set to point to true if the @@ -77,11 +76,25 @@ // similar to GetFileNameIfAllowedToAccess(), except that if we have // create permission on file, we permit stat() on all its leading // components, otherwise checking for missing intermediate directories - // can't happen proplery during a base::CreateDirectory() call. - // Async signal safe if and only if |file_to_open| is NULL. + // can't happen properly during a base::CreateDirectory() call. + // Async signal safe if and only if |file_to_access| is NULL. bool GetFileNameIfAllowedToStat(const char* requested_filename, const char** file_to_access) const; + // Check if |requested_filename| can be watched with mask |mask|. + // If |file_to_inotify_add_watch| is not NULL, a pointer to the validated path + // will be returned. In the case of a recursive match, this will be the + // requested_filename, otherwise it will return the matching pointer from the + // allowlist. A caller should then use |file_to_inotify_add_watch| rather than + // |requested_filename|, so that it never attempts to open an + // attacker-controlled file name, even if an attacker managed to fool the + // string comparison mechanism. Async signal safe if and only if + // |file_to_inotify_add_watch| is NULL. + bool GetFileNameIfAllowedToInotifyAddWatch( + const char* requested_filename, + uint32_t mask, + const char** file_to_inotify_add_watch) const; + int denied_errno() const { return denied_errno_; } private:
diff --git a/sandbox/linux/syscall_broker/broker_process.cc b/sandbox/linux/syscall_broker/broker_process.cc index ed5b6f2..ab66dfed 100644 --- a/sandbox/linux/syscall_broker/broker_process.cc +++ b/sandbox/linux/syscall_broker/broker_process.cc
@@ -26,8 +26,10 @@ #include "build/build_config.h" #include "sandbox/linux/syscall_broker/broker_channel.h" #include "sandbox/linux/syscall_broker/broker_client.h" +#include "sandbox/linux/syscall_broker/broker_command.h" #include "sandbox/linux/syscall_broker/broker_host.h" #include "sandbox/linux/syscall_broker/broker_permission_list.h" +#include "sandbox/linux/system_headers/linux_syscalls.h" namespace sandbox { @@ -187,7 +189,9 @@ // If rmdir() doesn't exist, unlinkat is used with AT_REMOVEDIR. return !fast_check || policy_->allowed_command_set.test(COMMAND_RMDIR) || policy_->allowed_command_set.test(COMMAND_UNLINK); - + case __NR_inotify_add_watch: + return !fast_check || + policy_->allowed_command_set.test(COMMAND_INOTIFY_ADD_WATCH); default: return false; }
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc index 526574ec..fbe4ea31 100644 --- a/sandbox/linux/syscall_broker/broker_process_unittest.cc +++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -8,6 +8,7 @@ #include <fcntl.h> #include <poll.h> #include <stddef.h> +#include <sys/inotify.h> #include <sys/resource.h> #include <sys/stat.h> #include <sys/types.h> @@ -25,6 +26,7 @@ #include "base/containers/flat_set.h" #include "base/files/file_util.h" #include "base/files/scoped_file.h" +#include "base/files/scoped_temp_dir.h" #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/posix/unix_domain_socket.h" @@ -1748,6 +1750,169 @@ TestUnlinkHelper(false); } +void TestInotifyAddWatchHelper(bool fast_check_in_client) { + const uint32_t kBadMask = + IN_CREATE | IN_DELETE | IN_CLOSE_WRITE | IN_MOVE | IN_ONLYDIR; + const uint32_t kGoodMask = kBadMask | IN_ATTRIB; + + // Create two nested temp dirs. + base::ScopedTempDir temp_dir; + ASSERT_TRUE( + temp_dir.CreateUniqueTempDirUnderPath(base::FilePath(kTempDirForTests))); + std::string temp_dir_str = temp_dir.GetPath().MaybeAsASCII(); + ASSERT_FALSE(temp_dir_str.empty()); + + base::ScopedTempDir nested_temp_dir; + ASSERT_TRUE( + nested_temp_dir.Set(temp_dir.GetPath().AppendASCII("nested_temp_dir"))); + std::string nested_temp_dir_str = nested_temp_dir.GetPath().MaybeAsASCII(); + ASSERT_FALSE(nested_temp_dir_str.empty()); + + base::FilePath bad_prefix = temp_dir.GetPath().AppendASCII("nested_t"); + std::string bad_prefix_str = bad_prefix.MaybeAsASCII(); + ASSERT_FALSE(bad_prefix_str.empty()); + + { + // Try to watch a directory without COMMAND_INOTIFY_ADD_WATCH + std::vector<BrokerFilePermission> permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + nested_temp_dir_str)}; + auto policy = absl::make_optional<BrokerSandboxConfig>( + BrokerCommandSet(), permissions, kFakeErrnoSentinel); + BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED, + fast_check_in_client); + + ASSERT_TRUE(open_broker.Fork(base::BindOnce(&NoOpCallback))); + + base::ScopedFD inotify_instance(inotify_init()); + ASSERT_TRUE(inotify_instance.is_valid()); + EXPECT_EQ( + -kFakeErrnoSentinel, + open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), nested_temp_dir_str.c_str(), kGoodMask)); + } + + BrokerCommandSet command_set; + command_set.set(COMMAND_INOTIFY_ADD_WATCH); + + { + // Try to watch a directory with no permission. + std::vector<BrokerFilePermission> permissions; + auto policy = absl::make_optional<BrokerSandboxConfig>( + command_set, permissions, kFakeErrnoSentinel); + BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED, + fast_check_in_client); + + ASSERT_TRUE(open_broker.Fork(base::BindOnce(&NoOpCallback))); + + base::ScopedFD inotify_instance(inotify_init()); + ASSERT_TRUE(inotify_instance.is_valid()); + EXPECT_EQ( + -kFakeErrnoSentinel, + open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), nested_temp_dir_str.c_str(), kGoodMask)); + } + { + // Try to watch a directory with permission, but bad flags. + std::vector<BrokerFilePermission> permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + nested_temp_dir_str)}; + auto policy = absl::make_optional<BrokerSandboxConfig>( + command_set, permissions, kFakeErrnoSentinel); + BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED, + fast_check_in_client); + + ASSERT_TRUE(open_broker.Fork(base::BindOnce(&NoOpCallback))); + + base::ScopedFD inotify_instance(inotify_init()); + ASSERT_TRUE(inotify_instance.is_valid()); + EXPECT_EQ( + -kFakeErrnoSentinel, + open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), nested_temp_dir_str.c_str(), kBadMask)); + } + { + // Add a directory with permissions and make sure it does not give watch + // permission to uintended directories or files. + std::vector<BrokerFilePermission> permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + nested_temp_dir_str)}; + auto policy = absl::make_optional<BrokerSandboxConfig>( + command_set, permissions, kFakeErrnoSentinel); + BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED, + fast_check_in_client); + + ASSERT_TRUE(open_broker.Fork(base::BindOnce(&NoOpCallback))); + + base::ScopedTempDir other_directory; + ASSERT_TRUE( + other_directory.CreateUniqueTempDirUnderPath(temp_dir.GetPath())); + std::string other_directory_str = other_directory.GetPath().MaybeAsASCII(); + ASSERT_FALSE(other_directory_str.empty()); + + base::ScopedFD inotify_instance(inotify_init()); + ASSERT_TRUE(inotify_instance.is_valid()); + + // Try to watch an unintended directory, should fail. + ASSERT_EQ( + -kFakeErrnoSentinel, + open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), other_directory_str.c_str(), kGoodMask)); + + // Try to access a prefix that isn't a full directory. + ASSERT_EQ(-kFakeErrnoSentinel, + open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), bad_prefix_str.c_str(), kGoodMask)); + } + { + // Try to watch a directory with permission, and good flags. + std::vector<BrokerFilePermission> permissions = { + BrokerFilePermission::InotifyAddWatchWithIntermediateDirs( + nested_temp_dir_str)}; + auto policy = absl::make_optional<BrokerSandboxConfig>( + command_set, permissions, kFakeErrnoSentinel); + BrokerProcess open_broker(std::move(policy), BrokerType::SIGNAL_BASED, + fast_check_in_client); + + ASSERT_TRUE(open_broker.Fork(base::BindOnce(&NoOpCallback))); + + base::ScopedFD inotify_instance(inotify_init()); + ASSERT_TRUE(inotify_instance.is_valid()); + + // Try to watch the directory, which should succeed. + int wd = open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), nested_temp_dir_str.c_str(), kGoodMask); + // The returned watch descriptor should be valid. + ASSERT_LE(0, wd); + // Removing the watch should succeed. + ASSERT_EQ(0, inotify_rm_watch(inotify_instance.get(), wd)); + + // Now try watching a leading directory, which should succeed. + wd = open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), temp_dir_str.c_str(), kGoodMask); + // The returned watch descriptor should be valid. + ASSERT_LE(0, wd); + // Removing the watch should succeed. + ASSERT_EQ(0, inotify_rm_watch(inotify_instance.get(), wd)); + + // Watching root should succeed with any valid permission. + wd = open_broker.GetBrokerClientSignalBased()->InotifyAddWatch( + inotify_instance.get(), "/", kGoodMask); + // The returned watch descriptor should be valid. + ASSERT_LE(0, wd); + // Removing the watch should succeed. + ASSERT_EQ(0, inotify_rm_watch(inotify_instance.get(), wd)); + } +} + +TEST(BrokerProcess, InotifyAddWatchClient) { + TestInotifyAddWatchHelper(true); +} + +TEST(BrokerProcess, InotifyAddWatchHost) { + TestInotifyAddWatchHelper(false); +} + TEST(BrokerProcess, IsSyscallAllowed) { const base::flat_map<BrokerCommand, base::flat_set<int>> kSysnosForCommand = { {COMMAND_ACCESS, @@ -1815,6 +1980,12 @@ #if defined(__NR_lstat64) __NR_lstat64, #endif + }}, + {COMMAND_INOTIFY_ADD_WATCH, + { +#if defined(__NR_inotify_add_watch) + __NR_inotify_add_watch +#endif }}}; // First gather up all the syscalls numbers we want to test.
diff --git a/sandbox/linux/syscall_broker/broker_simple_message.h b/sandbox/linux/syscall_broker/broker_simple_message.h index ea0a467..91bc057e 100644 --- a/sandbox/linux/syscall_broker/broker_simple_message.h +++ b/sandbox/linux/syscall_broker/broker_simple_message.h
@@ -83,16 +83,16 @@ // This returns a pointer to the next available data buffer in |data|. The // pointer is owned by |this| class. The resulting buffer is a string and // terminated with a '\0' character. - bool ReadString(const char** string); + [[nodiscard]] bool ReadString(const char** string); // This returns a pointer to the next available data buffer in the message // in |data|, and the length of the buffer in |length|. The buffer is owned // by |this| class. - bool ReadData(const char** data, size_t* length); + [[nodiscard]] bool ReadData(const char** data, size_t* length); // This reads the next available int from the message and stores it in // |result|. - bool ReadInt(int* result); + [[nodiscard]] bool ReadInt(int* result); // The maximum length of a message in the fixed size buffer. static constexpr size_t kMaxMessageLength = 4096;
diff --git a/sandbox/linux/syscall_broker/syscall_dispatcher.cc b/sandbox/linux/syscall_broker/syscall_dispatcher.cc index 6d9782cf..1f20d42 100644 --- a/sandbox/linux/syscall_broker/syscall_dispatcher.cc +++ b/sandbox/linux/syscall_broker/syscall_dispatcher.cc
@@ -195,6 +195,12 @@ case __NR_unlinkat: return PerformUnlinkat(args); #endif // defined(__NR_unlinkat) +#if defined(__NR_inotify_add_watch) + case __NR_inotify_add_watch: + return InotifyAddWatch(static_cast<int>(args.args[0]), + reinterpret_cast<const char*>(args.args[1]), + static_cast<uint32_t>(args.args[2])); +#endif default: RAW_CHECK(false); return -ENOSYS;
diff --git a/sandbox/linux/syscall_broker/syscall_dispatcher.h b/sandbox/linux/syscall_broker/syscall_dispatcher.h index 3c5b26034..906c37d 100644 --- a/sandbox/linux/syscall_broker/syscall_dispatcher.h +++ b/sandbox/linux/syscall_broker/syscall_dispatcher.h
@@ -53,6 +53,11 @@ // Emulates unlink()/unlinkat(). virtual int Unlink(const char* unlink) const = 0; + // Emulates inotify_add_watch(). + virtual int InotifyAddWatch(int fd, + const char* pathname, + uint32_t mask) const = 0; + // Different architectures use a different syscall from the stat family by // default in glibc. E.g. 32-bit systems use *stat*64() and fill out struct // kernel_stat64, whereas 64-bit systems use *stat*() and fill out struct
diff --git a/sandbox/linux/tests/scoped_temporary_file.cc b/sandbox/linux/tests/scoped_temporary_file.cc index 35f53eb..4527a30d 100644 --- a/sandbox/linux/tests/scoped_temporary_file.cc +++ b/sandbox/linux/tests/scoped_temporary_file.cc
@@ -9,26 +9,21 @@ #include <unistd.h> #include "base/check_op.h" +#include "base/files/file_util.h" #include "base/posix/eintr_wrapper.h" #include "build/build_config.h" namespace sandbox { -ScopedTemporaryFile::ScopedTemporaryFile() : fd_(-1) { -#if BUILDFLAG(IS_ANDROID) - static const char file_template[] = "/data/local/tmp/ScopedTempFileXXXXXX"; -#else - static const char file_template[] = "/tmp/ScopedTempFileXXXXXX"; -#endif // BUILDFLAG(IS_ANDROID) - static_assert(sizeof(full_file_name_) >= sizeof(file_template), - "full_file_name is not large enough"); - memcpy(full_file_name_, file_template, sizeof(file_template)); - fd_ = mkstemp(full_file_name_); +ScopedTemporaryFile::ScopedTemporaryFile() { + static const char kFileNameTemplate[] = "ScopedTempFileXXXXXX"; + full_file_name_ = std::string(kTempDirForTests) + kFileNameTemplate; + fd_ = mkstemp(full_file_name_.data()); CHECK_LE(0, fd_); } ScopedTemporaryFile::~ScopedTemporaryFile() { - CHECK_EQ(0, unlink(full_file_name_)); + CHECK_EQ(0, unlink(full_file_name_.c_str())); CHECK_EQ(0, IGNORE_EINTR(close(fd_))); }
diff --git a/sandbox/linux/tests/scoped_temporary_file.h b/sandbox/linux/tests/scoped_temporary_file.h index 69903a1..10787b9 100644 --- a/sandbox/linux/tests/scoped_temporary_file.h +++ b/sandbox/linux/tests/scoped_temporary_file.h
@@ -5,7 +5,18 @@ #ifndef SANDBOX_LINUX_TESTS_SCOPED_TEMPORARY_FILE_H_ #define SANDBOX_LINUX_TESTS_SCOPED_TEMPORARY_FILE_H_ +#include <string> + +#include "build/build_config.h" + namespace sandbox { + +#if BUILDFLAG(IS_ANDROID) +static const char kTempDirForTests[] = "/data/local/tmp/"; +#else +static const char kTempDirForTests[] = "/tmp/"; +#endif // BUILDFLAG(IS_ANDROID) + // Creates and open a temporary file on creation and closes // and removes it on destruction. // Unlike base/ helpers, this does not require JNI on Android. @@ -19,11 +30,11 @@ ~ScopedTemporaryFile(); int fd() const { return fd_; } - const char* full_file_name() const { return full_file_name_; } + const char* full_file_name() const { return full_file_name_.c_str(); } private: - int fd_; - char full_file_name_[128]; + int fd_ = -1; + std::string full_file_name_; }; } // namespace sandbox
diff --git a/sandbox/policy/linux/bpf_broker_policy_linux.cc b/sandbox/policy/linux/bpf_broker_policy_linux.cc index 0dc454a..87a0cc1fa 100644 --- a/sandbox/policy/linux/bpf_broker_policy_linux.cc +++ b/sandbox/policy/linux/bpf_broker_policy_linux.cc
@@ -5,6 +5,7 @@ #include "sandbox/policy/linux/bpf_broker_policy_linux.h" #include "sandbox/linux/bpf_dsl/bpf_dsl.h" +#include "sandbox/linux/syscall_broker/broker_command.h" #include "sandbox/linux/system_headers/linux_syscalls.h" using sandbox::bpf_dsl::Allow; @@ -146,6 +147,14 @@ } break; #endif +#if defined(__NR_inotify_add_watch) + case __NR_inotify_add_watch: + if (allowed_command_set_.test( + syscall_broker::COMMAND_INOTIFY_ADD_WATCH)) { + return Allow(); + } + break; +#endif default: break; }
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc index 1a76284..61a74a1 100644 --- a/services/network/network_context_unittest.cc +++ b/services/network/network_context_unittest.cc
@@ -7168,7 +7168,7 @@ EXPECT_EQ(client->completion_status().error_code, net::ERR_TRUST_TOKEN_OPERATION_FAILED); EXPECT_EQ(client->completion_status().trust_token_operation_status, - mojom::TrustTokenOperationStatus::kUnavailable); + mojom::TrustTokenOperationStatus::kUnauthorized); } TEST_F(NetworkContextTest, NoAvailableTrustTokensWhenTrustTokensAreDisabled) {
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index fa107688..f06533a9 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -359,6 +359,7 @@ "source_location.mojom", "supports_loading_mode.mojom", "timing_allow_origin.mojom", + "trust_token_access_observer.mojom", "trust_tokens.mojom", "url_loader.mojom", "url_loader_completion_status.mojom", @@ -510,6 +511,7 @@ traits_private_headers = [ "//services/network/public/mojom/devtools_observer.mojom.h", "//services/network/public/mojom/cookie_access_observer.mojom.h", + "//services/network/public/mojom/trust_token_access_observer.mojom.h", ] traits_public_deps = [ "//base",
diff --git a/services/network/public/mojom/trust_token_access_observer.mojom b/services/network/public/mojom/trust_token_access_observer.mojom new file mode 100644 index 0000000..ca3710f --- /dev/null +++ b/services/network/public/mojom/trust_token_access_observer.mojom
@@ -0,0 +1,36 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module network.mojom; + +import "sandbox/policy/mojom/context.mojom"; +import "url/mojom/origin.mojom"; + +struct TrustTokenAccessDetails { + // This is the origin that is triggering a Trust Token access. If the access + // is triggered from a resource request, `origin` is the origin of the + // request; if they're being triggered by a script, it's the origin of the + // window or service worker. + url.mojom.Origin origin; + + // Whether the Trust Token operation was blocked. + bool blocked = false; +}; + +// Cloneable interface to observe trust token operations being performed in +// the NetworkService from other services (primarily the browser process). +// Users of TrustTokenAccessObserver should create a dedicated observer for +// each network request context (URLLoaderFactory) they are interested in +// observing. +[RequireContext=sandbox.mojom.Context.kBrowser] +interface TrustTokenAccessObserver { + // Called when an attempt has been made to access trust tokens by the + // NetworkService with the details about the trust token access. + OnTrustTokensAccessed(TrustTokenAccessDetails details); + + // Called to create a copy of this observer. (e.g. when cloning observers + // from ResourceRequest). + [AllowedContext=sandbox.mojom.Context.kBrowser] + Clone(pending_receiver<TrustTokenAccessObserver> listener); +};
diff --git a/services/network/public/mojom/trust_tokens.mojom b/services/network/public/mojom/trust_tokens.mojom index c41e116..3778b34 100644 --- a/services/network/public/mojom/trust_tokens.mojom +++ b/services/network/public/mojom/trust_tokens.mojom
@@ -50,6 +50,9 @@ // some other general, probably transient, manner. kUnavailable, + // The operation was unauthorized due to some sort of policy. + kUnauthorized, + // The server response was malformed or otherwise invalid. kBadResponse,
diff --git a/services/network/test/url_loader_context_for_tests.cc b/services/network/test/url_loader_context_for_tests.cc index c03a02c..c4969e1 100644 --- a/services/network/test/url_loader_context_for_tests.cc +++ b/services/network/test/url_loader_context_for_tests.cc
@@ -28,6 +28,11 @@ return nullptr; } +mojom::TrustTokenAccessObserver* +URLLoaderContextForTests::GetTrustTokenAccessObserver() const { + return nullptr; +} + mojom::CrossOriginEmbedderPolicyReporter* URLLoaderContextForTests::GetCoepReporter() const { return nullptr;
diff --git a/services/network/test/url_loader_context_for_tests.h b/services/network/test/url_loader_context_for_tests.h index def81636..d25cc252 100644 --- a/services/network/test/url_loader_context_for_tests.h +++ b/services/network/test/url_loader_context_for_tests.h
@@ -42,6 +42,7 @@ const cors::OriginAccessList& GetOriginAccessList() const override; const mojom::URLLoaderFactoryParams& GetFactoryParams() const override; mojom::CookieAccessObserver* GetCookieAccessObserver() const override; + mojom::TrustTokenAccessObserver* GetTrustTokenAccessObserver() const override; mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const override; mojom::DevToolsObserver* GetDevToolsObserver() const override; mojom::NetworkContextClient* GetNetworkContextClient() const override;
diff --git a/services/network/trust_tokens/trust_token_request_helper_factory.cc b/services/network/trust_tokens/trust_token_request_helper_factory.cc index e4e59d7..eb2389c3 100644 --- a/services/network/trust_tokens/trust_token_request_helper_factory.cc +++ b/services/network/trust_tokens/trust_token_request_helper_factory.cc
@@ -98,7 +98,7 @@ if (!authorizer_.Run()) { LogOutcome(net_log, params.type, Outcome::kRejectedByAuthorizer); - std::move(done).Run(mojom::TrustTokenOperationStatus::kUnavailable); + std::move(done).Run(mojom::TrustTokenOperationStatus::kUnauthorized); return; }
diff --git a/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc b/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc index 9a410843..4eb6faf9 100644 --- a/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc +++ b/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc
@@ -291,7 +291,7 @@ run_loop.Run(); EXPECT_EQ(obtained_result.status(), - mojom::TrustTokenOperationStatus::kUnavailable); + mojom::TrustTokenOperationStatus::kUnauthorized); histogram_tester.ExpectUniqueSample( "Net.TrustTokens.RequestHelperFactoryOutcome.Signing", Outcome::kRejectedByAuthorizer, 1);
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index 0e03522..633e750 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -484,6 +484,7 @@ base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder, std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_helper_factory, mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer, + mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer, mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver> url_loader_network_observer, mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer, @@ -532,6 +533,10 @@ cookie_observer_remote_(std::move(cookie_observer)), cookie_observer_(PtrOrFallback(cookie_observer_remote_, context.GetCookieAccessObserver())), + trust_token_observer_remote_(std::move(trust_token_observer)), + trust_token_observer_( + PtrOrFallback(trust_token_observer_remote_, + context.GetTrustTokenAccessObserver())), url_loader_network_observer_remote_( std::move(url_loader_network_observer)), url_loader_network_observer_( @@ -937,6 +942,21 @@ void URLLoader::OnDoneConstructingTrustTokenHelper( mojom::TrustTokenOperationType type, TrustTokenStatusOrRequestHelper status_or_helper) { + if (trust_token_observer_) { + const net::IsolationInfo& isolation_info = url_request_->isolation_info(); + url::Origin top_frame_origin; + if (isolation_info.top_frame_origin()) { + top_frame_origin = *isolation_info.top_frame_origin(); + } + + bool token_operation_unauthorized = + status_or_helper.status() == + mojom::TrustTokenOperationStatus::kUnauthorized; + trust_token_observer_->OnTrustTokensAccessed( + mojom::TrustTokenAccessDetails::New(top_frame_origin, + token_operation_unauthorized)); + } + if (!status_or_helper.ok()) { trust_token_status_ = status_or_helper.status();
diff --git a/services/network/url_loader.h b/services/network/url_loader.h index f3debce..ccc98aa5 100644 --- a/services/network/url_loader.h +++ b/services/network/url_loader.h
@@ -45,6 +45,7 @@ #include "services/network/public/mojom/ip_address_space.mojom-forward.h" #include "services/network/public/mojom/ip_address_space.mojom-shared.h" #include "services/network/public/mojom/network_service.mojom.h" +#include "services/network/public/mojom/trust_token_access_observer.mojom.h" #include "services/network/public/mojom/trust_tokens.mojom-shared.h" #include "services/network/public/mojom/url_loader.mojom.h" #include "services/network/resource_scheduler/resource_scheduler.h" @@ -156,6 +157,7 @@ std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_helper_factory, mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer, + mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer, mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver> url_loader_network_observer, mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer, @@ -597,6 +599,10 @@ // URLLoaderFactory). const mojo::Remote<mojom::CookieAccessObserver> cookie_observer_remote_; const raw_ptr<mojom::CookieAccessObserver> cookie_observer_ = nullptr; + const mojo::Remote<mojom::TrustTokenAccessObserver> + trust_token_observer_remote_; + const raw_ptr<mojom::TrustTokenAccessObserver> trust_token_observer_ = + nullptr; const mojo::Remote<mojom::URLLoaderNetworkServiceObserver> url_loader_network_observer_remote_; const raw_ptr<mojom::URLLoaderNetworkServiceObserver>
diff --git a/services/network/url_loader_context.h b/services/network/url_loader_context.h index 775fe41..4b61d5aa 100644 --- a/services/network/url_loader_context.h +++ b/services/network/url_loader_context.h
@@ -27,6 +27,7 @@ class DevToolsObserver; class NetworkContextClient; class TrustedURLLoaderHeaderClient; +class TrustTokenAccessObserver; class URLLoaderFactoryParams; class URLLoaderNetworkServiceObserver; } // namespace mojom @@ -39,6 +40,8 @@ virtual const cors::OriginAccessList& GetOriginAccessList() const = 0; virtual const mojom::URLLoaderFactoryParams& GetFactoryParams() const = 0; virtual mojom::CookieAccessObserver* GetCookieAccessObserver() const = 0; + virtual mojom::TrustTokenAccessObserver* GetTrustTokenAccessObserver() + const = 0; virtual mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const = 0; virtual mojom::DevToolsObserver* GetDevToolsObserver() const = 0; virtual mojom::NetworkContextClient* GetNetworkContextClient() const = 0;
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc index 1eb0584..f0f256bf 100644 --- a/services/network/url_loader_factory.cc +++ b/services/network/url_loader_factory.cc
@@ -296,6 +296,9 @@ std::move(const_cast<mojo::PendingRemote<mojom::CookieAccessObserver>&>( resource_request.trusted_params->cookie_observer)); } + // TODO(https://crbug.com/1378264): Currently Trust Token Access observer + // isn't hooked up through URLLoaderFactory. + mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer; mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver> url_loader_network_observer; if (resource_request.trusted_params && @@ -338,9 +341,10 @@ static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation), request_id, keepalive_request_size, std::move(keepalive_statistics_recorder), std::move(trust_token_factory), - std::move(cookie_observer), std::move(url_loader_network_observer), - std::move(devtools_observer), std::move(accept_ch_frame_observer), - third_party_cookies_enabled, context_->cache_transparency_settings()); + std::move(cookie_observer), std::move(trust_token_observer), + std::move(url_loader_network_observer), std::move(devtools_observer), + std::move(accept_ch_frame_observer), third_party_cookies_enabled, + context_->cache_transparency_settings()); if (context_->GetMemoryCache()) loader->SetMemoryCache(context_->GetMemoryCache()->GetWeakPtr()); @@ -360,6 +364,13 @@ return nullptr; } +mojom::TrustTokenAccessObserver* URLLoaderFactory::GetTrustTokenAccessObserver() + const { + // TODO(https://crbug.com/1378264): URLLoaderFactory support for the Trust + // Token Access Observer is currently unimplemented. + return nullptr; +} + mojom::URLLoaderNetworkServiceObserver* URLLoaderFactory::GetURLLoaderNetworkServiceObserver() const { if (url_loader_network_service_observer_)
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h index 35df8f9..fd5a0483 100644 --- a/services/network/url_loader_factory.h +++ b/services/network/url_loader_factory.h
@@ -15,6 +15,7 @@ #include "services/network/public/mojom/cookie_access_observer.mojom.h" #include "services/network/public/mojom/devtools_observer.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/trust_token_access_observer.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_loader_network_service_observer.mojom.h" #include "services/network/url_loader_context.h" @@ -71,6 +72,7 @@ const cors::OriginAccessList& GetOriginAccessList() const override; const mojom::URLLoaderFactoryParams& GetFactoryParams() const override; mojom::CookieAccessObserver* GetCookieAccessObserver() const override; + mojom::TrustTokenAccessObserver* GetTrustTokenAccessObserver() const override; mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const override; mojom::DevToolsObserver* GetDevToolsObserver() const override; mojom::NetworkContextClient* GetNetworkContextClient() const override;
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc index 5266d26..4d35671 100644 --- a/services/network/url_loader_unittest.cc +++ b/services/network/url_loader_unittest.cc
@@ -643,9 +643,9 @@ std::move(sync_url_loader_client), traffic_annotation, request_id, keepalive_request_size, std::move(keepalive_statistics_recorder), std::move(trust_token_helper_factory), std::move(cookie_observer), - std::move(url_loader_network_observer), std::move(devtools_observer), - std::move(accept_ch_frame_observer), third_party_cookies_enabled, - cache_transparency_settings); + std::move(trust_token_observer), std::move(url_loader_network_observer), + std::move(devtools_observer), std::move(accept_ch_frame_observer), + third_party_cookies_enabled, cache_transparency_settings); } int32_t options = mojom::kURLLoadOptionNone; @@ -658,6 +658,8 @@ std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_helper_factory; mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer = mojo::NullRemote(); + mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer = + mojo::NullRemote(); mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver> url_loader_network_observer = mojo::NullRemote(); mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer = @@ -3886,6 +3888,70 @@ arg, result_listener); } +class MockTrustTokenObserver : public network::mojom::TrustTokenAccessObserver { + public: + MockTrustTokenObserver() = default; + ~MockTrustTokenObserver() override = default; + + struct TrustTokenDetails { + explicit TrustTokenDetails(const mojom::TrustTokenAccessDetailsPtr& details) + : origin(details->origin), blocked(details->blocked) {} + + url::Origin origin; + bool blocked; + }; + + mojo::PendingRemote<mojom::TrustTokenAccessObserver> GetRemote() { + mojo::PendingRemote<mojom::TrustTokenAccessObserver> remote; + receivers_.Add(this, remote.InitWithNewPipeAndPassReceiver()); + return remote; + } + + void OnTrustTokensAccessed( + mojom::TrustTokenAccessDetailsPtr details) override { + observed_tokens_.emplace_back(details); + if (wait_for_token_count_ && + observed_tokens().size() >= wait_for_token_count_) { + std::move(wait_for_tokens_quit_closure_).Run(); + } + } + + void WaitForTrustTokens(size_t token_count) { + if (observed_tokens_.size() < token_count) { + wait_for_token_count_ = token_count; + base::RunLoop run_loop; + wait_for_tokens_quit_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + EXPECT_EQ(observed_tokens_.size(), token_count); + } + + void Clone(mojo::PendingReceiver<mojom::TrustTokenAccessObserver> observer) + override { + receivers_.Add(this, std::move(observer)); + } + + const std::vector<TrustTokenDetails>& observed_tokens() { + return observed_tokens_; + } + + private: + size_t wait_for_token_count_ = 0; + base::OnceClosure wait_for_tokens_quit_closure_; + std::vector<TrustTokenDetails> observed_tokens_; + mojo::ReceiverSet<mojom::TrustTokenAccessObserver> receivers_; +}; + +MATCHER_P2(MatchesTrustTokenDetails, origin, blocked, "") { + return testing::ExplainMatchResult( + testing::AllOf( + testing::Field(&MockTrustTokenObserver::TrustTokenDetails::origin, + origin), + testing::Field(&MockTrustTokenObserver::TrustTokenDetails::blocked, + blocked)), + arg, result_listener); +} + // Responds certificate request with previously set responses. class ClientCertAuthObserver : public TestURLLoaderNetworkObserver { public: @@ -5839,6 +5905,8 @@ MockTrustTokenDevToolsObserver devtools_observer; URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); url_loader_options.trust_token_helper_factory = std::make_unique<MockTrustTokenRequestHelperFactory>( mojom::TrustTokenOperationStatus::kOk /* on_begin */, @@ -5869,6 +5937,11 @@ EXPECT_EQ(ReadBody(), expected); EXPECT_FALSE(client()->response_head()->headers->raw_headers().empty()); + + trust_token_observer.WaitForTrustTokens(1u); + EXPECT_THAT(trust_token_observer.observed_tokens(), + testing::ElementsAre( + MatchesTrustTokenDetails(test_server()->GetOrigin(), false))); } // A request with an associated Trust Tokens operation whose Begin step returns @@ -5890,6 +5963,8 @@ MockTrustTokenDevToolsObserver devtools_observer; URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); url_loader_options.trust_token_helper_factory = std::make_unique<MockTrustTokenRequestHelperFactory>( mojom::TrustTokenOperationStatus::kAlreadyExists /* on_begin */, @@ -5914,6 +5989,11 @@ EXPECT_FALSE(client()->response_head()); EXPECT_FALSE(client()->response_body().is_valid()); + + trust_token_observer.WaitForTrustTokens(1u); + EXPECT_THAT(trust_token_observer.observed_tokens(), + testing::ElementsAre( + MatchesTrustTokenDetails(test_server()->GetOrigin(), false))); } // When a request's associated Trust Tokens operation's Begin step fails, the @@ -5929,6 +6009,8 @@ MockTrustTokenDevToolsObserver devtools_observer; URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); url_loader_options.trust_token_helper_factory = std::make_unique<MockTrustTokenRequestHelperFactory>( mojom::TrustTokenOperationStatus::kFailedPrecondition /* on_begin */, @@ -5953,6 +6035,11 @@ EXPECT_FALSE(client()->response_head()); EXPECT_FALSE(client()->response_body().is_valid()); + + trust_token_observer.WaitForTrustTokens(1u); + EXPECT_THAT(trust_token_observer.observed_tokens(), + testing::ElementsAre( + MatchesTrustTokenDetails(test_server()->GetOrigin(), false))); } // When a request's associated Trust Tokens operation's Begin step succeeds but @@ -5968,6 +6055,8 @@ MockTrustTokenDevToolsObserver devtools_observer; URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); url_loader_options.trust_token_helper_factory = std::make_unique<MockTrustTokenRequestHelperFactory>( mojom::TrustTokenOperationStatus::kOk /* on_begin */, @@ -5990,6 +6079,11 @@ // Verify the DevTools event was fired and it has the right status. EXPECT_EQ(devtools_observer.trust_token_operation_status(), mojom::TrustTokenOperationStatus::kBadResponse); + + trust_token_observer.WaitForTrustTokens(1u); + EXPECT_THAT(trust_token_observer.observed_tokens(), + testing::ElementsAre( + MatchesTrustTokenDetails(test_server()->GetOrigin(), false))); } // When URLLoader receives a request parameterized to perform a Trust Tokens @@ -6007,6 +6101,8 @@ MockTrustTokenDevToolsObserver devtools_observer; URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); url_loader_options.trust_token_helper_factory = std::make_unique<MockTrustTokenRequestHelperFactory>( mojom::TrustTokenOperationStatus:: @@ -6028,6 +6124,54 @@ // Verify the DevTools event was fired and it has the right status. EXPECT_EQ(devtools_observer.trust_token_operation_status(), mojom::TrustTokenOperationStatus::kInternalError); + + trust_token_observer.WaitForTrustTokens(1u); + EXPECT_THAT(trust_token_observer.observed_tokens(), + testing::ElementsAre( + MatchesTrustTokenDetails(test_server()->GetOrigin(), false))); +} + +// When URLLoader receives a request that is blocked by policy, the request +// should fail entirely and report a blocked event to the observer. +TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest, + HandlesTrustTokenRequestHelperCreationBlocked) { + ResourceRequest request = CreateTrustTokenResourceRequest(); + + base::RunLoop delete_run_loop; + mojo::PendingRemote<mojom::URLLoader> loader_remote; + std::unique_ptr<URLLoader> url_loader; + context().mutable_factory_params().process_id = mojom::kBrowserProcessId; + MockTrustTokenDevToolsObserver devtools_observer; + + URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); + url_loader_options.trust_token_helper_factory = + std::make_unique<MockTrustTokenRequestHelperFactory>( + mojom::TrustTokenOperationStatus:: + kUnauthorized /* helper_creation_error */, + GetParam()); + url_loader_options.devtools_observer = devtools_observer.Bind(); + url_loader = url_loader_options.MakeURLLoader( + context(), DeleteLoaderCallback(&delete_run_loop, &url_loader), + loader_remote.InitWithNewPipeAndPassReceiver(), request, + client()->CreateRemote()); + + client()->RunUntilComplete(); + delete_run_loop.Run(); + + EXPECT_EQ(client()->completion_status().error_code, + net::ERR_TRUST_TOKEN_OPERATION_FAILED); + EXPECT_EQ(client()->completion_status().trust_token_operation_status, + mojom::TrustTokenOperationStatus::kUnauthorized); + // Verify the DevTools event was fired and it has the right status. + EXPECT_EQ(devtools_observer.trust_token_operation_status(), + mojom::TrustTokenOperationStatus::kUnauthorized); + + trust_token_observer.WaitForTrustTokens(1u); + EXPECT_THAT(trust_token_observer.observed_tokens(), + testing::ElementsAre( + MatchesTrustTokenDetails(test_server()->GetOrigin(), true))); } TEST_F(URLLoaderTest, OnRawRequestClientSecurityStateFactory) { @@ -6049,6 +6193,8 @@ base::RunLoop delete_run_loop; mojo::PendingRemote<mojom::URLLoader> loader; URLLoaderOptions url_loader_options; + MockTrustTokenObserver trust_token_observer; + url_loader_options.trust_token_observer = trust_token_observer.GetRemote(); url_loader_options.devtools_observer = devtools_observer.Bind(); std::unique_ptr<URLLoader> url_loader = url_loader_options.MakeURLLoader( context(), DeleteLoaderCallback(&delete_run_loop, &url_loader),
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h index 50670b75..4793800 100644 --- a/skia/config/SkUserConfig.h +++ b/skia/config/SkUserConfig.h
@@ -216,10 +216,6 @@ #define SK_USE_LEGACY_MIPMAP_BUILDER -// To ensure chrome only has access to legacy vma memory query apis until all -// skia changes to implement new api is completed. -#define SK_USE_LEGACY_VMA_MEMORY_QUERY - // Temporary until web tests can be rebaselined (skbug.com/13752) #define SK_DISABLE_RASTER_PIPELINE_SAMPLING_FIXES
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index 08cd682..e252dd6 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -860,12 +860,19 @@ db_->set_histogram_tag("Quota"); - // UMA logging and don't crash on database errors in DCHECK builds. - db_->set_error_callback( - base::BindRepeating([](int sqlite_error_code, sql::Statement* statement) { + db_->set_error_callback(base::BindRepeating( + [](base::RepeatingClosure full_disk_error_callback, int sqlite_error_code, + sql::Statement* statement) { sql::UmaHistogramSqliteResult("Quota.QuotaDatabaseError", sqlite_error_code); - })); + + if (!full_disk_error_callback.is_null() && + static_cast<sql::SqliteErrorCode>(sqlite_error_code) == + sql::SqliteErrorCode::kFullDisk) { + full_disk_error_callback.Run(); + } + }, + full_disk_error_callback_)); // Migrate an existing database from the old path. if (!db_file_path_.empty() && !MoveLegacyDatabase()) { @@ -1134,4 +1141,9 @@ return result; } +void QuotaDatabase::SetOnFullDiskErrorCallback( + const base::RepeatingClosure& callback) { + full_disk_error_callback_ = callback; +} + } // namespace storage
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h index a0cca26..b89f307d 100644 --- a/storage/browser/quota/quota_database.h +++ b/storage/browser/quota/quota_database.h
@@ -209,6 +209,10 @@ // Flushes previously scheduled commits. void CommitNow(); + // The given callback will be invoked whenever the database encounters a full + // disk error. + void SetOnFullDiskErrorCallback(const base::RepeatingClosure& callback); + // Testing support for database corruption handling. // // Runs `corrupter` on the same sequence used to do database I/O, @@ -293,6 +297,8 @@ static const size_t kTableCount; static const IndexSchema kIndexes[]; static const size_t kIndexCount; + + base::RepeatingClosure full_disk_error_callback_; }; } // namespace storage
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index 1b401886..cc540a0 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -1727,6 +1727,12 @@ database_ = std::make_unique<QuotaDatabase>(is_incognito_ ? base::FilePath() : profile_path_); + // Start the storage eviction routine on a full disk error. + database_->SetOnFullDiskErrorCallback( + base::BindPostTask(base::SequencedTaskRunner::GetCurrentDefault(), + base::BindRepeating(&QuotaManagerImpl::StartEviction, + weak_factory_.GetWeakPtr()))); + temporary_usage_tracker_ = std::make_unique<UsageTracker>( this, client_types_[StorageType::kTemporary], StorageType::kTemporary, special_storage_policy_.get()); @@ -1993,12 +1999,13 @@ void QuotaManagerImpl::StartEviction() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!temporary_storage_evictor_.get()); if (eviction_disabled_) return; - temporary_storage_evictor_ = std::make_unique<QuotaTemporaryStorageEvictor>( - this, kEvictionIntervalInMilliSeconds); + if (!temporary_storage_evictor_) { + temporary_storage_evictor_ = std::make_unique<QuotaTemporaryStorageEvictor>( + this, kEvictionIntervalInMilliSeconds); + } temporary_storage_evictor_->Start(); }
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.cc b/storage/browser/quota/quota_temporary_storage_evictor.cc index 11f7d53..3486b2d 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -27,7 +27,7 @@ base::UmaHistogramCustomCounts(name, sample / kMBytes, 1, 10 * 1024 * 1024 /* 10 TB */, 100); } -} +} // namespace namespace storage { @@ -35,8 +35,7 @@ QuotaEvictionHandler* quota_eviction_handler, int64_t interval_ms) : quota_eviction_handler_(quota_eviction_handler), - interval_ms_(interval_ms), - timer_disabled_for_testing_(false) { + interval_ms_(interval_ms) { DCHECK(quota_eviction_handler); } @@ -52,8 +51,7 @@ (*statistics)["errors-on-getting-usage-and-quota"] = statistics_.num_errors_on_getting_usage_and_quota; (*statistics)["evicted-buckets"] = statistics_.num_evicted_buckets; - (*statistics)["eviction-rounds"] = - statistics_.num_eviction_rounds; + (*statistics)["eviction-rounds"] = statistics_.num_eviction_rounds; (*statistics)["skipped-eviction-rounds"] = statistics_.num_skipped_eviction_rounds; } @@ -115,6 +113,11 @@ } else { ++statistics_.num_skipped_eviction_rounds; } + + if (!on_round_finished_for_testing_.is_null()) { + on_round_finished_for_testing_.Run(); + } + // Reset stats for next round. round_statistics_ = EvictionRoundStatistics(); } @@ -122,6 +125,17 @@ void QuotaTemporaryStorageEvictor::Start() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + // Don't start while we're in a round. + if (round_statistics_.in_round) { + return; + } + + // If we already have a round scheduled, just run it now. + if (eviction_timer_.IsRunning()) { + eviction_timer_.FireNow(); + return; + } + base::AutoReset<bool> auto_reset(&timer_disabled_for_testing_, false); StartEvictionTimerWithDelay(0); @@ -183,8 +197,7 @@ current_usage - static_cast<int64_t>(settings.pool_size * kUsageRatioToStartEviction)); int64_t diskspace_shortage = - std::max(INT64_C(0), - settings.should_remain_available - available_space); + std::max(INT64_C(0), settings.should_remain_available - available_space); DCHECK(current_usage_is_complete || diskspace_shortage == 0); // If we're using so little that freeing all of it wouldn't help,
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.h b/storage/browser/quota/quota_temporary_storage_evictor.h index 1b666f4..c7d9481 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.h +++ b/storage/browser/quota/quota_temporary_storage_evictor.h
@@ -97,7 +97,8 @@ base::Time time_of_end_of_last_round_; int64_t interval_ms_; - bool timer_disabled_for_testing_; + bool timer_disabled_for_testing_ = false; + base::RepeatingClosure on_round_finished_for_testing_; base::OneShotTimer eviction_timer_; base::RepeatingTimer histogram_timer_;
diff --git a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index 8f72496..febc778 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -29,6 +29,11 @@ namespace { +struct EvictionBucket { + BucketLocator locator; + int64_t usage; +}; + class MockQuotaEvictionHandler : public QuotaEvictionHandler { public: void EvictExpiredBuckets(StatusCallback done) override { @@ -57,9 +62,11 @@ } if (!task_for_get_usage_and_quota_.is_null()) task_for_get_usage_and_quota_.Run(); - std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, settings_, - available_space_, available_space_ * 2, GetUsage(), - true); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), blink::mojom::QuotaStatusCode::kOk, + settings_, available_space_, available_space_ * 2, + GetUsage(), true)); } void GetEvictionBucket(StorageType type, @@ -119,6 +126,10 @@ buckets_[bucket.id] = usage; } + bool HasBucket(const EvictionBucket& bucket) { + return base::Contains(buckets_, bucket.locator.id); + } + private: int64_t EnsureBucketRemoved(const BucketLocator& bucket) { int64_t bucket_usage; @@ -202,6 +213,62 @@ blink::mojom::StorageType::kTemporary, is_default); } + EvictionBucket CreateEvictionBucket(const std::string& url, + int64_t usage, + bool is_default = true) { + return EvictionBucket{CreateBucket(url, is_default), usage}; + } + + EvictionBucket CreateAndAddBucket(const std::string& url, + int64_t usage, + bool is_default = true) { + EvictionBucket bucket = CreateEvictionBucket(url, usage, is_default); + quota_eviction_handler()->AddBucket(bucket.locator, bucket.usage); + return bucket; + } + + bool EvictorHasBuckets(const std::vector<EvictionBucket>& buckets) { + int64_t total_usage = 0; + for (const auto& bucket : buckets) { + if (!quota_eviction_handler_->HasBucket(bucket)) { + return false; + } + total_usage += bucket.usage; + } + return total_usage == quota_eviction_handler_->GetUsage(); + } + + void RunAnEvictionRound(bool schedule_next_round) { + temporary_storage_evictor_->timer_disabled_for_testing_ = + !schedule_next_round; + base::RunLoop run_loop; + quota_eviction_handler_->set_task_for_get_usage_and_quota( + base::BindRepeating( + [](int* num_get_usage_and_quota_for_eviction) { + (*num_get_usage_and_quota_for_eviction)++; + }, + base::Unretained(&num_get_usage_and_quota_for_eviction_))); + set_on_round_finished_callback(run_loop.QuitClosure()); + temporary_storage_evictor()->Start(); + run_loop.Run(); + } + + bool RunAnEvictionPass() { + base::RunLoop run_loop; + quota_eviction_handler_->set_task_for_get_usage_and_quota( + base::BindRepeating( + [](base::RepeatingClosure quit_closure, + int* num_get_usage_and_quota_for_eviction) { + (*num_get_usage_and_quota_for_eviction)++; + quit_closure.Run(); + }, + run_loop.QuitClosure(), + base::Unretained(&num_get_usage_and_quota_for_eviction_))); + set_on_round_finished_callback(run_loop.QuitClosure()); + run_loop.Run(); + return temporary_storage_evictor_->round_statistics_.in_round; + } + protected: MockQuotaEvictionHandler* quota_eviction_handler() const { return static_cast<MockQuotaEvictionHandler*>( @@ -220,6 +287,10 @@ temporary_storage_evictor_->timer_disabled_for_testing_ = true; } + void set_on_round_finished_callback(base::RepeatingClosure callback) { + temporary_storage_evictor_->on_round_finished_for_testing_ = callback; + } + int num_get_usage_and_quota_for_eviction() const { return num_get_usage_and_quota_for_eviction_; } @@ -446,4 +517,87 @@ EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); // FIXME? } +TEST_F(QuotaTemporaryStorageEvictorTest, CallingStartAfterEvictionScheduled) { + // After running an eviction round and letting it schedule the next one, it + // should immediately run the next one if you call Start instead of waiting + // out the timer. + quota_eviction_handler()->SetPoolSize(4000); + quota_eviction_handler()->set_available_space(1000000000); + + EvictionBucket bucket_z = CreateAndAddBucket("http://www.z.com", 20); + EvictionBucket bucket_y = CreateAndAddBucket("http://www.y.com", 2900); + EvictionBucket bucket_x = CreateAndAddBucket("http://www.x.com", 450); + EvictionBucket bucket_w = CreateAndAddBucket("http://www.w.com", 400); + EXPECT_TRUE(EvictorHasBuckets({bucket_z, bucket_y, bucket_x, bucket_w})); + + RunAnEvictionRound(/*schedule_next_round=*/true); + EXPECT_TRUE(EvictorHasBuckets({bucket_x, bucket_w})); + + EvictionBucket bucket_v = CreateAndAddBucket("http://www.v.com", 2000); + EvictionBucket bucket_u = CreateAndAddBucket("http://www.u.com", 400); + EXPECT_TRUE(EvictorHasBuckets({bucket_x, bucket_w, bucket_v, bucket_u})); + + RunAnEvictionRound(/*schedule_next_round=*/false); + EXPECT_TRUE(EvictorHasBuckets({bucket_w, bucket_v, bucket_u})); + + EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); + EXPECT_EQ(3, statistics().num_evicted_buckets); + EXPECT_EQ(2, statistics().num_eviction_rounds); + EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); + EXPECT_EQ(2U, quota_eviction_handler()->get_evict_expired_buckets_count()); +} + +TEST_F(QuotaTemporaryStorageEvictorTest, + CallingStartImmediatelyAfterEvictionScheduled) { + // After calling start to schedule an eviction round, calling start multiple + // times before the eviction round begins shouldn't cause it to run multiple + // times. + quota_eviction_handler()->SetPoolSize(4000); + quota_eviction_handler()->set_available_space(1000000000); + + EvictionBucket bucket_z = CreateAndAddBucket("http://www.z.com", 20); + EvictionBucket bucket_y = CreateAndAddBucket("http://www.y.com", 2900); + EvictionBucket bucket_x = CreateAndAddBucket("http://www.x.com", 450); + EvictionBucket bucket_w = CreateAndAddBucket("http://www.w.com", 400); + EXPECT_TRUE(EvictorHasBuckets({bucket_z, bucket_y, bucket_x, bucket_w})); + + temporary_storage_evictor()->Start(); + temporary_storage_evictor()->Start(); + RunAnEvictionRound(/*schedule_next_round=*/false); + EXPECT_TRUE(EvictorHasBuckets({bucket_x, bucket_w})); + + EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); + EXPECT_EQ(2, statistics().num_evicted_buckets); + EXPECT_EQ(1, statistics().num_eviction_rounds); + EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); + EXPECT_EQ(1U, quota_eviction_handler()->get_evict_expired_buckets_count()); +} + +TEST_F(QuotaTemporaryStorageEvictorTest, CallingStartDuringEvictionRoutine) { + // If we're in the middle of an eviction round, calling Start should do + // nothing. + quota_eviction_handler()->SetPoolSize(4000); + quota_eviction_handler()->set_available_space(1000000000); + + EvictionBucket bucket_z = CreateAndAddBucket("http://www.z.com", 20); + EvictionBucket bucket_y = CreateAndAddBucket("http://www.y.com", 2900); + EvictionBucket bucket_x = CreateAndAddBucket("http://www.x.com", 450); + EvictionBucket bucket_w = CreateAndAddBucket("http://www.w.com", 400); + EXPECT_TRUE(EvictorHasBuckets({bucket_z, bucket_y, bucket_x, bucket_w})); + + disable_timer_for_testing(); + temporary_storage_evictor()->Start(); + while (RunAnEvictionPass()) { + temporary_storage_evictor_->Start(); + } + EXPECT_TRUE(EvictorHasBuckets({bucket_x, bucket_w})); + + EXPECT_EQ(3, num_get_usage_and_quota_for_eviction()); + EXPECT_EQ(0, statistics().num_errors_on_getting_usage_and_quota); + EXPECT_EQ(2, statistics().num_evicted_buckets); + EXPECT_EQ(1, statistics().num_eviction_rounds); + EXPECT_EQ(0, statistics().num_skipped_eviction_rounds); + EXPECT_EQ(1U, quota_eviction_handler()->get_evict_expired_buckets_count()); +} + } // namespace storage
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index dffa27d..fd9af986 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -23731,7 +23731,7 @@ { "args": [ "--platform", - "iPad Pro (12.9-inch) (2nd generation)", + "iPhone 7", "--version", "14.5", "--out-dir", @@ -23748,7 +23748,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", + "name": "ios_chrome_signin_eg2tests_module iPhone 7 14.5", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -23782,7 +23782,7 @@ "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" + "variant_id": "iPhone 7 14.5" }, { "args": [ @@ -24064,7 +24064,7 @@ { "args": [ "--platform", - "iPad Pro (12.9-inch) (2nd generation)", + "iPhone 7", "--version", "14.5", "--out-dir", @@ -24081,7 +24081,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module iPad Pro (12.9-inch) (2nd generation) 14.5", + "name": "ios_chrome_ui_eg2tests_module iPhone 7 14.5", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -24115,7 +24115,7 @@ "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPad Pro (12.9-inch) (2nd generation) 14.5" + "variant_id": "iPhone 7 14.5" }, { "args": [ @@ -30432,62 +30432,6 @@ { "args": [ "--platform", - "iPhone 6s", - "--version", - "15.5", - "--output-disabled-tests", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPhone 6s 15.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_15_5", - "path": "Runtime-ios-15.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone 6s 15.5" - }, - { - "args": [ - "--platform", "iPhone 7", "--version", "15.5", @@ -30602,6 +30546,62 @@ "--platform", "iPhone X", "--version", + "15.5", + "--output-disabled-tests", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPhone X 15.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_15_5", + "path": "Runtime-ios-15.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPhone X 15.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", "16.1", "--output-disabled-tests", "--out-dir", @@ -31320,62 +31320,6 @@ { "args": [ "--platform", - "iPhone 6s", - "--version", - "15.5", - "--output-disabled-tests", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPhone 6s 15.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_15_5", - "path": "Runtime-ios-15.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone 6s 15.5" - }, - { - "args": [ - "--platform", "iPhone 7", "--version", "15.5", @@ -31490,6 +31434,62 @@ "--platform", "iPhone X", "--version", + "15.5", + "--output-disabled-tests", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPhone X 15.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_15_5", + "path": "Runtime-ios-15.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPhone X 15.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", "16.1", "--output-disabled-tests", "--out-dir", @@ -61855,6 +61855,62 @@ { "args": [ "--platform", + "iPad Air (3rd generation)", + "--version", + "16.1", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization", + "--record-video", + "failed_only" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPad Air (3rd generation) 16.1", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_16_1", + "path": "Runtime-ios-16.1" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 16.1" + }, + { + "args": [ + "--platform", "iPad Pro (12.9-inch) (3rd generation)", "--version", "16.1", @@ -62354,6 +62410,62 @@ { "args": [ "--platform", + "iPad Air (3rd generation)", + "--version", + "16.1", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization", + "--record-video", + "failed_only" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPad Air (3rd generation) 16.1", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_16_1", + "path": "Runtime-ios-16.1" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPad Air (3rd generation) 16.1" + }, + { + "args": [ + "--platform", "iPad Pro (12.9-inch) (3rd generation)", "--version", "16.1", @@ -92546,6 +92658,42 @@ } ] }, + "linux-wpt-content-shell-asan-fyi-rel": { + "isolated_scripts": [ + { + "args": [ + "--log-wptreport", + "--xvfb", + "--enable-sanitizer" + ], + "experiment_percentage": 100, + "isolate_name": "wpt_tests_isolate_content_shell", + "merge": { + "args": [ + "--verbose" + ], + "script": "//third_party/blink/tools/merge_web_test_results.py" + }, + "name": "wpt_tests_suite", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "results_handler": "layout tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 8 + }, + "test_id_prefix": "ninja://:wpt_tests_isolate_content_shell/" + } + ] + }, "linux-wpt-content-shell-fyi-rel": { "isolated_scripts": [ {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 96eb101d..9a424bd 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -8599,6 +8599,9 @@ "args": [], "script": "//testing/merge_scripts/standard_gtest_merge.py" }, + "precommit_args": [ + "--gtest_filter=-*" + ], "swarming": { "can_use_on_swarming_builders": true, "dimension_sets": [ @@ -12123,118 +12126,6 @@ { "args": [ "--platform", - "iPhone 8", - "--version", - "16.1", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPhone 8 16.1", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "mac_model": "Macmini8,1", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_16_1", - "path": "Runtime-ios-16.1" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone 8 16.1" - }, - { - "args": [ - "--platform", - "iPhone 8", - "--version", - "16.1", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPhone 8 16.1", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "mac_model": "Macmini8,1", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_16_1", - "path": "Runtime-ios-16.1" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone 8 16.1" - }, - { - "args": [ - "--platform", "iPad Air (3rd generation)", "--version", "16.1", @@ -17258,62 +17149,6 @@ { "args": [ "--platform", - "iPhone 6s", - "--version", - "15.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPhone 6s 15.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "mac_model": "Macmini8,1", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_15_5", - "path": "Runtime-ios-15.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone 6s 15.5" - }, - { - "args": [ - "--platform", "iPhone 7", "--version", "15.5", @@ -17426,6 +17261,118 @@ { "args": [ "--platform", + "iPhone X", + "--version", + "15.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPhone X 15.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "mac_model": "Macmini8,1", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_15_5", + "path": "Runtime-ios-15.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPhone X 15.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "16.1", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_signin_eg2tests_module", + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_signin_eg2tests_module iPhone X 16.1", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "mac_model": "Macmini8,1", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_16_1", + "path": "Runtime-ios-16.1" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 6 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", + "variant_id": "iPhone X 16.1" + }, + { + "args": [ + "--platform", "iPad Air (3rd generation)", "--version", "16.1", @@ -18090,62 +18037,6 @@ { "args": [ "--platform", - "iPhone 6s", - "--version", - "15.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "isolate_profile_data": true, - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPhone 6s 15.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "mac_model": "Macmini8,1", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_15_5", - "path": "Runtime-ios-15.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone 6s 15.5" - }, - { - "args": [ - "--platform", "iPhone 7", "--version", "15.5", @@ -18258,6 +18149,118 @@ { "args": [ "--platform", + "iPhone X", + "--version", + "15.5", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPhone X 15.5", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "mac_model": "Macmini8,1", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_15_5", + "path": "Runtime-ios-15.5" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPhone X 15.5" + }, + { + "args": [ + "--platform", + "iPhone X", + "--version", + "16.1", + "--out-dir", + "${ISOLATED_OUTDIR}", + "--xcode-build-version", + "14b47b", + "--xctest", + "--xcode-parallelization" + ], + "isolate_name": "ios_chrome_ui_eg2tests_module", + "isolate_profile_data": true, + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_isolated_script_merge.py" + }, + "name": "ios_chrome_ui_eg2tests_module iPhone X 16.1", + "resultdb": { + "enable": true, + "has_native_resultdb_integration": true + }, + "swarming": { + "can_use_on_swarming_builders": true, + "cipd_packages": [ + { + "cipd_package": "infra/tools/mac_toolchain/${platform}", + "location": ".", + "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" + } + ], + "dimension_sets": [ + { + "cpu": "x86-64", + "mac_model": "Macmini8,1", + "os": "Mac-12" + } + ], + "named_caches": [ + { + "name": "xcode_ios_14b47b", + "path": "Xcode.app" + }, + { + "name": "runtime_ios_16_1", + "path": "Runtime-ios-16.1" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 12 + }, + "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", + "variant_id": "iPhone X 16.1" + }, + { + "args": [ + "--platform", "iPad Air 2", "--version", "15.5", @@ -23625,62 +23628,6 @@ { "args": [ "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization", - "--record-video", - "failed_only" - ], - "isolate_name": "ios_chrome_signin_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_signin_eg2tests_module iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 6 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", "iPhone 7", "--version", "14.5", @@ -23737,7 +23684,7 @@ { "args": [ "--platform", - "iPhone SE (1st generation)", + "iPhone X", "--version", "14.5", "--out-dir", @@ -23754,7 +23701,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module iPhone SE (1st generation) 14.5", + "name": "ios_chrome_signin_eg2tests_module iPhone X 14.5", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -23788,7 +23735,7 @@ "shards": 6 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module/", - "variant_id": "iPhone SE (1st generation) 14.5" + "variant_id": "iPhone X 14.5" }, { "args": [ @@ -24125,62 +24072,6 @@ { "args": [ "--platform", - "iPhone 6s Plus", - "--version", - "14.5", - "--out-dir", - "${ISOLATED_OUTDIR}", - "--xcode-build-version", - "14b47b", - "--xctest", - "--xcode-parallelization", - "--record-video", - "failed_only" - ], - "isolate_name": "ios_chrome_ui_eg2tests_module", - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "name": "ios_chrome_ui_eg2tests_module iPhone 6s Plus 14.5", - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/mac_toolchain/${platform}", - "location": ".", - "revision": "git_revision:723fc1a6c8cdf2631a57851f5610e598db0c1de1" - } - ], - "dimension_sets": [ - { - "cpu": "x86-64", - "os": "Mac-12" - } - ], - "named_caches": [ - { - "name": "xcode_ios_14b47b", - "path": "Xcode.app" - }, - { - "name": "runtime_ios_14_5", - "path": "Runtime-ios-14.5" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 12 - }, - "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone 6s Plus 14.5" - }, - { - "args": [ - "--platform", "iPhone 7", "--version", "14.5", @@ -24237,7 +24128,7 @@ { "args": [ "--platform", - "iPhone SE (1st generation)", + "iPhone X", "--version", "14.5", "--out-dir", @@ -24254,7 +24145,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module iPhone SE (1st generation) 14.5", + "name": "ios_chrome_ui_eg2tests_module iPhone X 14.5", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -24288,7 +24179,7 @@ "shards": 12 }, "test_id_prefix": "ninja://ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module/", - "variant_id": "iPhone SE (1st generation) 14.5" + "variant_id": "iPhone X 14.5" }, { "args": [
diff --git a/testing/buildbot/chromium.perf.fyi.json b/testing/buildbot/chromium.perf.fyi.json index 9a2cbec..f0ab13e 100644 --- a/testing/buildbot/chromium.perf.fyi.json +++ b/testing/buildbot/chromium.perf.fyi.json
@@ -189,7 +189,8 @@ "fuchsia-builder-perf-x64": { "additional_compile_targets": [ "chrome_pkg", - "base_perftests" + "base_perftests", + "sync_performance_tests" ] }, "fuchsia-perf-ast": {
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl index 539eedf77..4334b9a 100644 --- a/testing/buildbot/gn_isolate_map.pyl +++ b/testing/buildbot/gn_isolate_map.pyl
@@ -1672,6 +1672,19 @@ "label": "//chrome/test:sync_integration_tests", "type": "windowed_test_launcher", }, + "sync_performance_tests": { + "args": [ + "sync_performance_tests", + "--non-telemetry=true", + "--test-launcher-print-test-stdio=always", + "--test-launcher-jobs=1", + "--test-launcher-retry-limit=0", + ], + "label": "//chrome/test:sync_performance_tests", + "skip_usage_check": True, # Used by Pinpoint: crbug.com/1042778 + "script": "//testing/scripts/run_performance_tests.py", + "type": "script", + }, "system_webview_apk": { "label": "//android_webview:system_webview_apk", "type": "additional_compile_target",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 8a4ae8b..633419bb 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -3291,6 +3291,9 @@ }, }, 'Mac12 Tests': { + 'precommit_args': [ + '--gtest_filter=-*', + ], 'swarming': { 'shards': 4, }, @@ -4068,6 +4071,14 @@ }, 'wpt_tests_suite': { 'modifications': { + 'linux-wpt-content-shell-asan-fyi-rel': { + 'args': [ + '--enable-sanitizer', + ], + 'swarming': { + 'shards': 8, + }, + }, 'win10-wpt-content-shell-fyi-rel': { 'args': [ '--target',
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index d828c17..897813a 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -3839,16 +3839,6 @@ 'shards': 8, }, }, - 'ios_chrome_signin_eg2tests_module': { - 'swarming': { - 'shards': 6, - }, - }, - 'ios_chrome_ui_eg2tests_module': { - 'swarming': { - 'shards': 12, - }, - }, 'ios_web_shell_eg2tests_module': {}, }, @@ -3859,7 +3849,17 @@ 'shards': 3, }, }, + 'ios_chrome_signin_eg2tests_module': { + 'swarming': { + 'shards': 6, + }, + }, 'ios_chrome_smoke_eg2tests_module': {}, + 'ios_chrome_ui_eg2tests_module': { + 'swarming': { + 'shards': 12, + }, + }, 'ios_chrome_web_eg2tests_module': {}, 'ios_showcase_eg2tests_module': {}, },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index a95547b..2c2323a10 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -3532,6 +3532,15 @@ }, 'use_swarming': False, }, + 'linux-wpt-content-shell-asan-fyi-rel': { + 'mixins': [ + 'has_native_resultdb_integration', + 'linux-bionic', + ], + 'test_suites': { + 'isolated_scripts': 'wpt_web_tests_content_shell', + }, + }, 'linux-wpt-content-shell-fyi-rel': { 'mixins': [ 'has_native_resultdb_integration',
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py index 2b09d2f..82af9d41 100755 --- a/testing/scripts/run_performance_tests.py +++ b/testing/scripts/run_performance_tests.py
@@ -503,7 +503,8 @@ def execute_telemetry_benchmark( - command_generator, output_paths, use_xvfb=False): + command_generator, output_paths, use_xvfb=False, + return_exit_code_zero=False): start = time.time() env = os.environ.copy() @@ -567,6 +568,10 @@ 'this as a success.' % return_code) return 0 if return_code: + if return_exit_code_zero: + print ('run_benchmark returned exit code ' + str(return_code) + + ' which indicates there were test failures in the run.') + return 0 return return_code return 0 @@ -633,6 +638,12 @@ 'replace the static shardmap file.', type=str, required=False) + parser.add_argument('--ignore-benchmark-exit-code', + help='If set, return an exit code 0 even if there' + + ' are benchmark failures', + action='store_true', + required=False + ) options, leftover_args = parser.parse_known_args(args) options.passthrough_args.extend(leftover_args) return options @@ -703,7 +714,8 @@ benchmark, options) print('\n### {folder} ###'.format(folder=benchmark)) return_code = execute_telemetry_benchmark( - command_generator, output_paths, options.xvfb) + command_generator, output_paths, options.xvfb, + options.ignore_benchmark_exit_code) overall_return_code = return_code or overall_return_code test_results_files.append(output_paths.test_results) if options.run_ref_build: @@ -773,7 +785,8 @@ story_selection_config=story_selection_config) print('\n### {folder} ###'.format(folder=benchmark)) return_code = execute_telemetry_benchmark( - command_generator, output_paths, options.xvfb) + command_generator, output_paths, options.xvfb, + options.ignore_benchmark_exit_code) overall_return_code = return_code or overall_return_code test_results_files.append(output_paths.test_results) if options.run_ref_build: @@ -790,7 +803,7 @@ # reference build. execute_telemetry_benchmark( reference_command_generator, reference_output_paths, - options.xvfb) + options.xvfb, options.ignore_benchmark_exit_code) if 'executables' in shard_configuration: names_and_configs = shard_configuration['executables'] for (name, configuration) in names_and_configs.items():
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 45683764..0482393 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -7782,21 +7782,6 @@ ] } ], - "OptimizeLayoutsForPullRefresh": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "OptimizeLayoutsForPullRefresh" - ] - } - ] - } - ], "OptimizeNetworkBuffers": [ { "platforms": [ @@ -8373,21 +8358,6 @@ ] } ], - "PasswordsGrouping": [ - { - "platforms": [ - "ios" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "PasswordsGrouping" - ] - } - ] - } - ], "Path2DPaintCache": [ { "platforms": [
diff --git a/third_party/android_swipe_refresh/README.chromium b/third_party/android_swipe_refresh/README.chromium index 1744524..e199415 100644 --- a/third_party/android_swipe_refresh/README.chromium +++ b/third_party/android_swipe_refresh/README.chromium
@@ -28,5 +28,4 @@ * All ViewCompat and MotionEventCompat dependencies removed. * Added OnResetListener interface to notify SwipeRefreshHandler to detach this view. - * Add a flag to minimze the number of z-order changes, thereby minimizing - relayouts of the UI. + * Optimization to minimize number of relayouts of the UI.
diff --git a/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java index 09d92a7..02545ad 100644 --- a/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java +++ b/third_party/android_swipe_refresh/java/src/org/chromium/third_party/android/swiperefresh/SwipeRefreshLayout.java
@@ -21,16 +21,12 @@ import android.content.res.TypedArray; import android.util.AttributeSet; import android.util.DisplayMetrics; -import android.util.Log; -import android.view.MotionEvent; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.DecelerateInterpolator; import android.view.animation.Transformation; -import android.widget.AbsListView; /** * The SwipeRefreshLayout should be used whenever the user can refresh the @@ -136,12 +132,6 @@ private boolean mNotify; - /** - * Flag used during duration of pull-refresh animation to reduce the number of calls to - * |bringToFront|, and therefore requested layouts. crbug/1335416 - */ - private boolean mOptimizeLayouts; - private int mCircleWidth; private int mCircleHeight; @@ -570,11 +560,10 @@ * is currently active, the request will be ignored. * @return whether a new pull sequence has started. */ - public boolean start(boolean optimizeLayouts) { + public boolean start() { if (!isEnabled()) return false; if (mRefreshing) return false; mCircleView.clearAnimation(); - mOptimizeLayouts = optimizeLayouts; mProgress.stop(); // See ACTION_DOWN handling in {@link #onTouchEvent(...)}. setTargetOffsetTopAndBottom(mOriginalOffsetTop - mCircleView.getTop(), true); @@ -645,7 +634,7 @@ @Override public void bringChildToFront(View child) { - if (mOptimizeLayouts && indexOfChild(child) == getChildCount() - 1) return; + if (indexOfChild(child) == getChildCount() - 1) return; super.bringChildToFront(child); }
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index 32c02cdd..feea463b 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -6408,6 +6408,7 @@ ResourceExhausted AlreadyExists Unavailable + Unauthorized BadResponse InternalError UnknownError
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 b89eabe..57866250 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
@@ -3765,6 +3765,8 @@ kDialogCloseWatcherCloseSignalClosedMultiple = 4424, kNoVarySearch = 4425, kFedCmUserInfo = 4426, + kIDNA2008DeviationCharacterInHostnameOfSubresource = 4427, + kIDNA2008DeviationCharacterInHostnameOfIFrame = 4428, // 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/web/DEPS b/third_party/blink/public/web/DEPS index c17f725..2a47463 100644 --- a/third_party/blink/public/web/DEPS +++ b/third_party/blink/public/web/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+base/containers/span.h", + "+base/containers/flat_map.h", "+base/files/file_path.h", "+base/i18n/rtl.h", "+base/observer_list_types.h",
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h index 086a171..b124fa6 100644 --- a/third_party/blink/public/web/web_navigation_params.h +++ b/third_party/blink/public/web/web_navigation_params.h
@@ -7,6 +7,7 @@ #include <memory> +#include "base/containers/flat_map.h" #include "base/containers/span.h" #include "base/time/time.h" #include "base/unguessable_token.h" @@ -27,6 +28,7 @@ #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h" #include "third_party/blink/public/mojom/frame/policy_container.mojom-forward.h" #include "third_party/blink/public/mojom/frame/triggering_event_info.mojom-shared.h" +#include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom-shared.h" #include "third_party/blink/public/platform/cross_variant_mojo_util.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_content_security_policy_struct.h" @@ -514,6 +516,12 @@ // components associated with the winning bid in an auction. absl::optional<FencedFrame::RedactedFencedFrameProperties> fenced_frame_properties; + + // Maps the blink runtime-enabled features modified in the browser process to + // their new enabled/disabled status: + // <enum_representing_runtime_enabled_feature, enabled/disabled> + base::flat_map<::blink::mojom::RuntimeFeatureState, bool> + modified_runtime_features; }; } // namespace blink
diff --git a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl index 8257d0e..1fc1ee15 100644 --- a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.cc.tmpl
@@ -6,10 +6,21 @@ #include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom-shared.h" #include "third_party/blink/renderer/platform/runtime_feature_state/runtime_feature_state_override_context.h" +#include "base/process/process.h" + namespace blink { + +void RuntimeFeatureStateOverrideContext::ApplyOverrideValuesFromParams( + const base::flat_map<mojom::RuntimeFeatureState, bool>& + values_from_params) { + for(const auto& override_value : values_from_params) { + override_values_[override_value.first] = override_value.second; + } +} + {% for feature in overridable_features %} bool RuntimeFeatureStateOverrideContext:: - Is{{feature.name}}ForceDisabled() { + Is{{feature.name}}ForceDisabled() const { auto it = override_values_.find( blink::mojom::RuntimeFeatureState::k{{feature.name}}); if (it != override_values_.end() && it->second == false) @@ -19,7 +30,7 @@ } bool RuntimeFeatureStateOverrideContext:: - Is{{feature.name}}ForceEnabled() { + Is{{feature.name}}ForceEnabled() const { auto it = override_values_.find( blink::mojom::RuntimeFeatureState::k{{feature.name}}); if(it != override_values_.end() && it->second == true)
diff --git a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.h.tmpl b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.h.tmpl index 67a087a5..08089d3 100644 --- a/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.h.tmpl +++ b/third_party/blink/renderer/build/scripts/templates/runtime_feature_state_override_context.h.tmpl
@@ -24,16 +24,25 @@ ApplyEnterprisePolicyOverrides(); } - {% for feature in overridable_features %} - bool Is{{feature.name}}ForceDisabled(); + void ApplyOverrideValuesFromParams( + const base::flat_map<mojom::RuntimeFeatureState, bool>& + values_from_params); - bool Is{{feature.name}}ForceEnabled(); + {% for feature in overridable_features %} + bool Is{{feature.name}}ForceDisabled() const; + + bool Is{{feature.name}}ForceEnabled() const; void Set{{feature.name}}ForceDisabled(); void Set{{feature.name}}ForceEnabled(); {% endfor %} + + const base::flat_map<blink::mojom::RuntimeFeatureState, bool>& GetOverrideValuesForTesting() const { + return override_values_; + } + void Trace(Visitor*) const {} private:
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc index ccdcd3c..9d3fae9 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -556,11 +556,26 @@ void DisplayLockContext::ScheduleStateChangeEventIfNeeded() { if (state_ == EContentVisibility::kAuto && - RuntimeEnabledFeatures::ContentVisibilityAutoStateChangeEventEnabled()) { - element_->EnqueueEvent( - *ContentVisibilityAutoStateChangeEvent::Create( - event_type_names::kContentvisibilityautostatechange, is_locked_), - TaskType::kMiscPlatformAPI); + RuntimeEnabledFeatures::ContentVisibilityAutoStateChangeEventEnabled() && + !state_change_task_pending_) { + document_->GetExecutionContext() + ->GetTaskRunner(TaskType::kMiscPlatformAPI) + ->PostTask( + FROM_HERE, + WTF::BindOnce(&DisplayLockContext::DispatchStateChangeEventIfNeeded, + WrapPersistent(this))); + state_change_task_pending_ = true; + } +} + +void DisplayLockContext::DispatchStateChangeEventIfNeeded() { + DCHECK(state_change_task_pending_); + state_change_task_pending_ = false; + if (!last_notified_skipped_state_ || + *last_notified_skipped_state_ != is_locked_) { + last_notified_skipped_state_ = is_locked_; + element_->DispatchEvent(*ContentVisibilityAutoStateChangeEvent::Create( + event_type_names::kContentvisibilityautostatechange, is_locked_)); } }
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h index d9d4a3a..352b5d1 100644 --- a/third_party/blink/renderer/core/display_lock/display_lock_context.h +++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -402,6 +402,7 @@ bool SubtreeHasTopLayerElement() const; void ScheduleStateChangeEventIfNeeded(); + void DispatchStateChangeEventIfNeeded(); WeakMember<Element> element_; WeakMember<Document> document_; @@ -558,9 +559,17 @@ // the next frame. bool has_pending_clear_has_top_layer_ = false; - // If ture, we need to check if this subtree has any top layer elements at the + // If true, we need to check if this subtree has any top layer elements at the // start of the next frame. bool has_pending_top_layer_check_ = false; + + // This is set to the last value for which ContentVisibilityAutoStateChange + // event has been dispatched (if any). + absl::optional<bool> last_notified_skipped_state_; + + // If true, there is a pending task that will dispatch a state change event if + // needed. + bool state_change_task_pending_ = false; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 725ad63e..e1e32d4 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -198,6 +198,7 @@ #include "third_party/blink/renderer/core/html/canvas/canvas_font_cache.h" #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h" #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" +#include "third_party/blink/renderer/core/html/collection_type.h" #include "third_party/blink/renderer/core/html/custom/custom_element.h" #include "third_party/blink/renderer/core/html/custom/custom_element_definition.h" #include "third_party/blink/renderer/core/html/custom/custom_element_descriptor.h" @@ -7102,6 +7103,10 @@ kDocumentAllNamedItems, name); } +HTMLCollection* Document::PopoverInvokers() { + return EnsureCachedCollection<HTMLCollection>(kPopoverInvokers); +} + void Document::IncrementLazyAdsFrameCount() { data_->lazy_ads_frame_count_++; }
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index a020c70..88821f69 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -264,6 +264,7 @@ kInvalidateForFormControls, kInvalidateOnHRefAttrChange, kInvalidateOnAnyAttrChange, + kInvalidateOnPopoverInvokerAttrChange, }; const int kNumNodeListInvalidationTypes = kInvalidateOnAnyAttrChange + 1; @@ -544,6 +545,7 @@ HTMLCollection* WindowNamedItems(const AtomicString& name); DocumentNameCollection* DocumentNamedItems(const AtomicString& name); HTMLCollection* DocumentAllNamedItems(const AtomicString& name); + HTMLCollection* PopoverInvokers(); // The unassociated listed elements are listed elements that are not // associated to a <form> element.
diff --git a/third_party/blink/renderer/core/dom/live_node_list_base.h b/third_party/blink/renderer/core/dom/live_node_list_base.h index 8fdd370..5620418 100644 --- a/third_party/blink/renderer/core/dom/live_node_list_base.h +++ b/third_party/blink/renderer/core/dom/live_node_list_base.h
@@ -130,6 +130,11 @@ attr_name == html_names::kTypeAttr; case kInvalidateOnHRefAttrChange: return attr_name == html_names::kHrefAttr; + case kInvalidateOnPopoverInvokerAttrChange: + return attr_name == html_names::kPopoverAttr || + attr_name == html_names::kPopovertoggletargetAttr || + attr_name == html_names::kPopoverhidetargetAttr || + attr_name == html_names::kPopovershowtargetAttr; case kDoNotInvalidateOnAttributeChanges: return false; case kInvalidateOnAnyAttrChange:
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc index 912a9721..5c47e804 100644 --- a/third_party/blink/renderer/core/frame/web_frame_test.cc +++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -200,6 +200,7 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/runtime_feature_state/runtime_feature_state_override_context.h" #include "third_party/blink/renderer/platform/scheduler/public/event_loop.h" #include "third_party/blink/renderer/platform/scheduler/public/thread.h" #include "third_party/blink/renderer/platform/testing/find_cc_layer.h" @@ -14436,4 +14437,44 @@ script_request.Complete(); } +// Verify that modified_runtime_features is correctly set in the +// RuntimeFeatureStateOverrideContext when a navigation is committed. +TEST_F(WebFrameSimTest, SetModifiedFeaturesInOverrideContext) { + frame_test_helpers::WebViewHelper web_view_helper; + web_view_helper.Initialize(); + + WebLocalFrameImpl* frame = web_view_helper.LocalMainFrame(); + + auto params = std::make_unique<WebNavigationParams>(); + // The url isn't important, just pick something. + params->url = url_test_helpers::ToKURL("http://www.example.com"); + + // Create a modified features value map and give it a value that we can check. + auto modified_features = + base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(); + modified_features[blink::mojom::RuntimeFeatureState::kTestFeature] = true; + params->modified_runtime_features = modified_features; + + // Commit the navigation + frame->CommitNavigation(std::move(params), nullptr); + + // Get the override context and compare the override values map with the + // modified features map. + RuntimeFeatureStateOverrideContext* override_context = + frame->GetFrame()->DomWindow()->GetRuntimeFeatureStateOverrideContext(); + EXPECT_EQ(override_context->GetOverrideValuesForTesting(), modified_features); + + // Do the same thing for a value of "false" + params = std::make_unique<WebNavigationParams>(); + params->url = url_test_helpers::ToKURL("http://www.example2.com"); + modified_features = + base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(); + modified_features[blink::mojom::RuntimeFeatureState::kTestFeature] = false; + params->modified_runtime_features = modified_features; + frame->CommitNavigation(std::move(params), nullptr); + override_context = + frame->GetFrame()->DomWindow()->GetRuntimeFeatureStateOverrideContext(); + EXPECT_EQ(override_context->GetOverrideValuesForTesting(), modified_features); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/collection_type.h b/third_party/blink/renderer/core/html/collection_type.h index 97468e4e..3ed2818d 100644 --- a/third_party/blink/renderer/core/html/collection_type.h +++ b/third_party/blink/renderer/core/html/collection_type.h
@@ -48,6 +48,7 @@ kDataListOptions, kMapAreas, kFormControls, + kPopoverInvokers, // Named HTMLCollection types cached in the document. kWindowNamedItems,
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc index cee7313..f47f8d6 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -332,7 +332,7 @@ // values match, the behavior is to toggle. HTMLFormControlElement::PopoverTargetElement HTMLFormControlElement::popoverTargetElement() const { - const PopoverTargetElement no_element{.element = nullptr, + const PopoverTargetElement no_element{.popover = nullptr, .action = PopoverTriggerAction::kNone, .attribute_name = g_null_name}; if (!RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( @@ -368,7 +368,7 @@ DynamicTo<HTMLElement>(GetTreeScope().getElementById(idref)); if (!popover_element || !popover_element->HasPopoverAttribute()) return no_element; - return PopoverTargetElement{.element = popover_element, + return PopoverTargetElement{.popover = popover_element, .action = action, .attribute_name = attribute_name}; } @@ -376,7 +376,7 @@ void HTMLFormControlElement::DefaultEventHandler(Event& event) { if (!IsDisabledFormControl()) { auto popover = popoverTargetElement(); - if (popover.element) { + if (popover.popover) { auto trigger_support = SupportsPopoverTriggering(); DCHECK_NE(popover.action, PopoverTriggerAction::kNone); DCHECK_NE(trigger_support, PopoverTriggerSupport::kNone); @@ -392,21 +392,21 @@ // popover and set focus to the previously focused element, then the // normal focus management code will reset focus to the clicked control. bool can_show = - popover.element->IsPopoverReady(PopoverTriggerAction::kShow) && + popover.popover->IsPopoverReady(PopoverTriggerAction::kShow) && (popover.action == PopoverTriggerAction::kToggle || popover.action == PopoverTriggerAction::kShow); bool can_hide = - popover.element->IsPopoverReady(PopoverTriggerAction::kHide) && + popover.popover->IsPopoverReady(PopoverTriggerAction::kHide) && (popover.action == PopoverTriggerAction::kToggle || popover.action == PopoverTriggerAction::kHide); if (event.type() == event_type_names::kDOMActivate && (!Form() || !IsSuccessfulSubmitButton())) { if (can_hide) { - popover.element->HidePopoverInternal( + popover.popover->HidePopoverInternal( HidePopoverFocusBehavior::kFocusPreviousElement, HidePopoverForcingLevel::kHideAfterAnimations); } else if (can_show) { - popover.element->InvokePopover(this); + popover.popover->InvokePopover(this); } } }
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.h b/third_party/blink/renderer/core/html/forms/html_form_control_element.h index c2243b1..021d9836 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.h +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.h
@@ -91,10 +91,10 @@ struct PopoverTargetElement final { public: DISALLOW_NEW(); - WeakMember<HTMLElement> element; + WeakMember<HTMLElement> popover; PopoverTriggerAction action; QualifiedName attribute_name; - void Trace(Visitor* visitor) const { visitor->Trace(element); } + void Trace(Visitor* visitor) const { visitor->Trace(popover); } }; enum class PopoverTriggerSupport {
diff --git a/third_party/blink/renderer/core/html/html_collection.cc b/third_party/blink/renderer/core/html/html_collection.cc index edfdfe69..31852f5f 100644 --- a/third_party/blink/renderer/core/html/html_collection.cc +++ b/third_party/blink/renderer/core/html/html_collection.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/dom/class_collection.h" #include "third_party/blink/renderer/core/dom/element_traversal.h" #include "third_party/blink/renderer/core/dom/node_rare_data.h" +#include "third_party/blink/renderer/core/html/collection_type.h" #include "third_party/blink/renderer/core/html/document_all_name_collection.h" #include "third_party/blink/renderer/core/html/document_name_collection.h" #include "third_party/blink/renderer/core/html/forms/html_data_list_options_collection.h" @@ -37,6 +38,7 @@ #include "third_party/blink/renderer/core/html/html_tag_collection.h" #include "third_party/blink/renderer/core/html/window_name_collection.h" #include "third_party/blink/renderer/core/html_names.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" namespace blink { @@ -64,6 +66,7 @@ case kDataListOptions: case kWindowNamedItems: case kFormControls: + case kPopoverInvokers: return false; case kNodeChildren: case kTRCells: @@ -108,6 +111,7 @@ case kSelectedOptions: case kDataListOptions: case kMapAreas: + case kPopoverInvokers: return NodeListSearchRoot::kOwnerNode; case kFormControls: if (IsA<HTMLFieldSetElement>(owner)) @@ -162,6 +166,8 @@ return kInvalidateForFormControls; case kClassCollectionType: return kInvalidateOnClassAttrChange; + case kPopoverInvokers: + return kInvalidateOnPopoverInvokerAttrChange; case kNameNodeListType: case kRadioNodeListType: case kRadioImgNodeListType: @@ -254,6 +260,11 @@ return IsA<HTMLObjectElement>(element) || IsA<HTMLFormControlElement>(element) || element.IsFormAssociatedCustomElement(); + case kPopoverInvokers: + if (auto* invoker = DynamicTo<HTMLFormControlElement>(element)) { + return invoker->popoverTargetElement().popover; + } + return false; case kClassCollectionType: case kTagCollectionType: case kTagCollectionNSType:
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc index 0d4a310..30364041 100644 --- a/third_party/blink/renderer/core/html/html_element.cc +++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -69,6 +69,7 @@ #include "third_party/blink/renderer/core/html/custom/custom_element.h" #include "third_party/blink/renderer/core/html/custom/custom_element_registry.h" #include "third_party/blink/renderer/core/html/custom/element_internals.h" +#include "third_party/blink/renderer/core/html/forms/html_form_control_element.h" #include "third_party/blink/renderer/core/html/forms/html_form_element.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/labels_node_list.h" @@ -1350,10 +1351,8 @@ auto original_type = PopoverType(); if (original_type == PopoverValueType::kAuto) { // If the new popover is a popover=auto, hide any popover above this in the - // stack. Because this popover isn't yet in the stack, we call - // NearestOpenAncestralPopover to find this popover's ancestor, if any. - const auto* auto_ancestor = - NearestOpenAncestralPopover(*this, PopoverAncestorType::kNewPopover); + // stack, if any. + const auto* auto_ancestor = FindTopmostPopoverAncestor(*this); HideAllPopoversUntil(auto_ancestor, document, HidePopoverFocusBehavior::kNone, HidePopoverForcingLevel::kHideAfterAnimations); @@ -1628,145 +1627,140 @@ doc.TopDocument().FinalizeAutofocus(); } -using PopoverPositionMap = HeapHashMap<Member<const Element>, int>; -using PopoverAnchorMap = - HeapHashMap<Member<const Element>, Member<const Element>>; -using PopoverSeenSet = HashSet<Member<const Node>>; - namespace { -const HTMLElement* NearestOpenAncestralPopoverRecursive( - const Node* node, - const PopoverPositionMap& popover_positions, - const PopoverAnchorMap& anchors_to_popovers, - int upper_bound, - PopoverSeenSet& seen) { - if (!node || seen.Contains(node)) - return nullptr; - seen.insert(node); - const HTMLElement* ancestor = nullptr; - int position = -1; - auto update = [&ancestor, &position, &popover_positions, - upper_bound](const HTMLElement* popover) { - DCHECK(popover); - if (popover->popoverOpen() && - popover->PopoverType() != PopoverValueType::kManual) { - DCHECK(popover_positions.Contains(popover)); - int new_position = popover_positions.at(popover); - if (new_position > position && new_position < upper_bound) { - ancestor = popover; - position = new_position; - } - } - }; - auto recurse_and_update = [&update, &popover_positions, upper_bound, - &anchors_to_popovers, &seen](const Node* node) { - if (auto* popover = NearestOpenAncestralPopoverRecursive( - node, popover_positions, anchors_to_popovers, upper_bound, seen)) - update(popover); - }; - - if (auto* element = DynamicTo<HTMLElement>(node)) { - // Update for this element. - update(element); - // Recursively look up the tree from this element's anchors and invokers. - if (popover_positions.Contains(element)) { - recurse_and_update(element->anchorElement()); - recurse_and_update(element->GetPopoverData()->invoker()); - } - // Include invokers that weren't used to invoke the popover. This is - // necessary to catch invoking elements that should not light dismiss a - // popover, even if they weren't used to show it. - if (auto* form_control = DynamicTo<HTMLFormControlElement>(element)) { - recurse_and_update(form_control->popoverTargetElement().element); - } - // Include the anchor elements for all showing popovers. - if (anchors_to_popovers.Contains(element)) { - recurse_and_update(anchors_to_popovers.at(element)); - } +template <typename UnaryPredicate> +const HTMLElement* NearestInclusiveMatchingAncestor(const Node* node, + UnaryPredicate predicate) { + for (; node; node = FlatTreeTraversal::Parent(*node)) { + if (auto* value = predicate(node)) + return value; } - // Also walk up the flat tree from this node. - recurse_and_update(FlatTreeTraversal::Parent(*node)); - - return ancestor; + return nullptr; } + +const HTMLElement* NearestInclusiveOpenPopover(const Node* node) { + return NearestInclusiveMatchingAncestor(node, [](const Node* test_node) { + auto* popover = DynamicTo<HTMLElement>(test_node); + return (popover && popover->popoverOpen() && + popover->PopoverType() != PopoverValueType::kManual) + ? popover + : nullptr; + }); +} + +const HTMLElement* NearestInclusiveTargetPopoverForInvoker(const Node* node) { + return NearestInclusiveMatchingAncestor(node, [](const Node* test_node) { + auto* form_element = DynamicTo<HTMLFormControlElement>(test_node); + auto target_popover = + form_element ? form_element->popoverTargetElement().popover : nullptr; + return (target_popover && target_popover->popoverOpen() && + target_popover->PopoverType() != PopoverValueType::kManual) + ? target_popover.Get() + : nullptr; + }); +} + } // namespace // static -// This function will return the popover that is highest in the popover stack -// that is an ancestral popover of the provided node. Popover ancestors are -// created by DOM flat tree parents, or through either anchor or invoker -// relationships. Anchor relationships are formed by the anchor attribute on a -// popover, pointing to another node in the tree. Invoker relationships are -// formed by invoking elements, which are HTMLFormControlElements having -// popovertoggletarget, popovershowtarget, or popoverhidetarget attributes -// pointing to a popover element. There can be multiple popovers that point to a -// single anchor element, and there can be multiple invoking elements for a -// single popover. Additionally, an anchor for one popover can be an invoker for -// a different popover. For these reasons, this function needs to do a recursive -// tree walk up from the provided node, plus all associated anchors and -// invokers, returning the highest (on the stack) popover that is found. If the -// inclusive parameter is true, the highest popover found during the tree-walk -// is included in the search. If it is false, the |node| parameter must be a -// popover, and the highest popover *below* that starting pop- up will be -// returned. -const HTMLElement* HTMLElement::NearestOpenAncestralPopover( - const Node& node, - PopoverAncestorType ancestor_type) { +// This function will return the topmost (highest in the popover stack) +// ancestral popover for the provided popover. Popovers can be related to each +// other in several ways, creating a tree of popovers. There are three paths +// through which one popover (call it the "child" popover) can have an ancestor +// popover (call it the "parent" popover): +// 1. the popovers are nested within each other in the DOM tree. In this case, +// the descendant popover is the "child" and its ancestor popover is the +// "parent". +// 2. a popover has an `anchor` attribute pointing to another element in the +// DOM. In this case, the popover is the "child", and the DOM-contained +// popover of its anchor element is the "parent". If the anchor doesn't +// point to an element, or that element isn't contained within a popover, no +// such relationship exists. +// 3. an invoking element (e.g. a <button>) has one of the invoking attributes +// (e.g. popovertoggletarget) pointing to a popover. In this case, the +// popover is the "child", and the DOM-contained popover of the invoking +// element is the "parent". As with anchor, the invoker must be in a popover +// and reference an open popover. +// In each of the relationships formed above, the parent popover must be +// strictly lower in the popover stack than the child popover, or it does not +// form a valid ancestral relationship. This eliminates non-showing popovers and +// self-pointers (e.g. a popover with an anchor attribute that points back to +// the same popover), and it allows for the construction of a well-formed tree +// from the (possibly cyclic) graph of connections. For example, if two popovers +// have anchors pointing to each other, the only valid relationship is that the +// first one to open is the "parent" and the second is the "child". Only +// popover=auto popovers are considered. +const HTMLElement* HTMLElement::FindTopmostPopoverAncestor( + const HTMLElement& new_popover) { + DCHECK(new_popover.HasPopoverAttribute() && !new_popover.popoverOpen()); + auto& document = new_popover.GetDocument(); DCHECK(RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( - node.GetDocument().GetExecutionContext())); - // popover_positions is a map from all showing (or about-to-show) popovers to - // their position in the popover stack. - PopoverPositionMap popover_positions; - // anchors_to_popovers is a map from the anchor elements of all showing - // popovers back to the popover itself. - PopoverAnchorMap anchors_to_popovers; + document.GetExecutionContext())); + + // Build a map from each open popover to its position in the stack. + HeapHashMap<Member<const HTMLElement>, int> popover_positions; int indx = 0; - for (auto popover : node.GetDocument().PopoverStack()) { + for (auto popover : document.PopoverStack()) { popover_positions.Set(popover, indx++); - if (popover->anchorElement()) - anchors_to_popovers.Set(popover->anchorElement(), popover); } - auto* element = DynamicTo<HTMLElement>(node); - if (ancestor_type == PopoverAncestorType::kNewPopover) { - DCHECK(element && element->HasPopoverAttribute() && - !element->popoverOpen()); - popover_positions.Set(element, indx++); - } - // upper_bound is one above the maximum popover stack height to accept. It is - // typically the position of the provided element. - int upper_bound = popover_positions.Contains(element) - ? popover_positions.at(element) - : INT_MAX; - if (ancestor_type == PopoverAncestorType::kInclusive) { - // For inclusive mode, we need to walk up the tree until we find an open - // popover, or an invoker for an open popover, and then modify the upper - // bound to include the highest such popover found, if any. - for (const Node* current_node = &node; current_node; - current_node = FlatTreeTraversal::Parent(*current_node)) { - if (auto* current_element = DynamicTo<HTMLElement>(current_node); - current_element && current_element->HasPopoverAttribute() && - current_element->popoverOpen() && - current_element->PopoverType() != PopoverValueType::kManual) { - upper_bound = - std::max(upper_bound, popover_positions.at(current_element) + 1); - } - if (auto* form_control = - DynamicTo<HTMLFormControlElement>(current_node)) { - if (auto target_popover = form_control->popoverTargetElement().element; - target_popover && target_popover->popoverOpen() && - target_popover->PopoverType() != PopoverValueType::kManual) { - upper_bound = - std::max(upper_bound, popover_positions.at(target_popover) + 1); - } - } + popover_positions.Set(&new_popover, indx++); + + const HTMLElement* topmost_popover_ancestor = nullptr; + auto check_ancestor = [&topmost_popover_ancestor, + &popover_positions](const Element* candidate) { + if (!candidate) + return; + auto* candidate_ancestor = NearestInclusiveOpenPopover(candidate); + if (!candidate_ancestor) + return; + int candidate_position = popover_positions.at(candidate_ancestor); + if (!topmost_popover_ancestor || + popover_positions.at(topmost_popover_ancestor) < candidate_position) { + topmost_popover_ancestor = candidate_ancestor; } + }; + // Add the three types of ancestor relationships to the map: + // 1. DOM tree ancestor. + check_ancestor(NearestInclusiveOpenPopover( + FlatTreeTraversal::ParentElement(new_popover))); + // 2. Anchor attribute. + check_ancestor(new_popover.anchorElement()); + // 3. Invoker to popover (need to consider all of them). + for (auto* invoker : *document.PopoverInvokers()) { + DCHECK(IsA<HTMLFormControlElement>(invoker)); + auto* popover = To<HTMLFormControlElement>(invoker) + ->popoverTargetElement() + .popover.Get(); + if (popover == &new_popover) + check_ancestor(invoker); } - PopoverSeenSet seen; - return NearestOpenAncestralPopoverRecursive( - &node, popover_positions, anchors_to_popovers, upper_bound, seen); + return topmost_popover_ancestor; } +namespace { +// For light dismiss, we need to find the closest popover that the user has +// clicked. That is the nearest DOM ancestor that is either a popover or the +// invoking element for a popover. It is possible both exist, in which case +// the topmost one (highest on the popover stack) is returned. +const HTMLElement* FindTopmostClickedPopover(const Node& node) { + auto& document = node.GetDocument(); + DCHECK(RuntimeEnabledFeatures::HTMLPopoverAttributeEnabled( + document.GetExecutionContext())); + // Check if we're in an invoking element or a popover, and choose + // the higher popover on the stack. + auto* clicked_popover = NearestInclusiveOpenPopover(&node); + auto* invoker_popover = NearestInclusiveTargetPopoverForInvoker(&node); + auto get_stack_position = [&document](const HTMLElement* popover) { + auto pos = document.PopoverStack().Find(popover); + return pos == kNotFound ? 0 : (pos + 1); + }; + if (get_stack_position(clicked_popover) > get_stack_position(invoker_popover)) + return clicked_popover; + return invoker_popover; +} +} // namespace + // static void HTMLElement::HandlePopoverLightDismiss(const Event& event, const Node& target_node) { @@ -1786,8 +1780,8 @@ DCHECK_EQ(Event::PhaseType::kNone, event.eventPhase()); if (event_type == event_type_names::kPointerdown) { - document.SetPopoverPointerdownTarget(NearestOpenAncestralPopover( - target_node, PopoverAncestorType::kInclusive)); + document.SetPopoverPointerdownTarget( + FindTopmostClickedPopover(target_node)); } else if (event_type == event_type_names::kPointerup) { // Hide everything up to the clicked element. We do this on pointerup, // rather than pointerdown or click, primarily for accessibility concerns. @@ -1799,8 +1793,7 @@ // a pointer-drag on a popover, and finishes off the popover (to highlight // text), the ancestral popover is stored in pointerdown and compared // here. - auto* ancestor_popover = NearestOpenAncestralPopover( - target_node, PopoverAncestorType::kInclusive); + auto* ancestor_popover = FindTopmostClickedPopover(target_node); bool same_target = ancestor_popover == document.PopoverPointerdownTarget(); document.SetPopoverPointerdownTarget(nullptr);
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h index 7593fa0..9f6781e8 100644 --- a/third_party/blink/renderer/core/html/html_element.h +++ b/third_party/blink/renderer/core/html/html_element.h
@@ -84,12 +84,6 @@ kHideImmediately, }; -enum class PopoverAncestorType { - kDefault, - kNewPopover, - kInclusive, -}; - class CORE_EXPORT HTMLElement : public Element { DEFINE_WRAPPERTYPEINFO(); @@ -229,8 +223,7 @@ void HidePopoverInternal(HidePopoverFocusBehavior focus_behavior, HidePopoverForcingLevel forcing_level); void PopoverHideFinishIfNeeded(); - static const HTMLElement* NearestOpenAncestralPopover(const Node&, - PopoverAncestorType); + static const HTMLElement* FindTopmostPopoverAncestor(const HTMLElement&); // Retrieves the element pointed to by this element's 'anchor' content // attribute, if that element exists, and if this element is a popover.
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc index 40e5526..ce984a6 100644 --- a/third_party/blink/renderer/core/layout/layout_shift_tracker.cc +++ b/third_party/blink/renderer/core/layout/layout_shift_tracker.cc
@@ -592,12 +592,12 @@ DCHECK(performance); double input_timestamp = LastInputTimestamp(); - LayoutShift* entry = LayoutShift::Create( - performance->now(), score_delta, had_recent_input, input_timestamp, - CreateAttributionList(), - PerformanceEntry::GetNavigationId(window)); // Add WPT for - // LayoutShift. See - // crbug.com/1320878. + LayoutShift* entry = + LayoutShift::Create(performance->now(), score_delta, had_recent_input, + input_timestamp, CreateAttributionList(), + PerformanceEntry::GetNavigationId(window), window); + + // Add WPT for LayoutShift. See crbug.com/1320878. performance->AddLayoutShiftEntry(entry); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc index cf115695..c9154c81 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.cc
@@ -325,15 +325,24 @@ const NGConstraintSpace& space, const NGLogicalOutOfFlowInsets& insets, const NGLogicalStaticPosition& static_position) { + return ComputeOutOfFlowAvailableRect(node, space.AvailableSize(), insets, + static_position); +} + +LogicalRect ComputeOutOfFlowAvailableRect( + const NGBlockNode& node, + const LogicalSize& available_size, + const NGLogicalOutOfFlowInsets& insets, + const NGLogicalStaticPosition& static_position) { const bool is_table = node.IsTable(); LayoutUnit inline_offset, inline_size; std::tie(inline_offset, inline_size) = ComputeAvailableSpaceInOneAxis( - space.AvailableSize().inline_size, insets.inline_start, insets.inline_end, + available_size.inline_size, insets.inline_start, insets.inline_end, static_position.offset.inline_offset, GetStaticPositionEdge(static_position.inline_edge), is_table); LayoutUnit block_offset, block_size; std::tie(block_offset, block_size) = ComputeAvailableSpaceInOneAxis( - space.AvailableSize().block_size, insets.block_start, insets.block_end, + available_size.block_size, insets.block_start, insets.block_end, static_position.offset.block_offset, GetStaticPositionEdge(static_position.block_edge), is_table); return LogicalRect(inline_offset, block_offset, inline_size, block_size);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h index b6ab2fb..4d479cc 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h +++ b/third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h
@@ -64,6 +64,11 @@ const NGConstraintSpace&, const NGLogicalOutOfFlowInsets&, const NGLogicalStaticPosition&); +CORE_EXPORT LogicalRect +ComputeOutOfFlowAvailableRect(const NGBlockNode&, + const LogicalSize& available_size, + const NGLogicalOutOfFlowInsets&, + const NGLogicalStaticPosition&); // The following routines implement the absolute size resolution algorithm. // https://www.w3.org/TR/css-position-3/#abs-non-replaced-width
diff --git a/third_party/blink/renderer/core/loader/DEPS b/third_party/blink/renderer/core/loader/DEPS index 904d7124..d9556285 100644 --- a/third_party/blink/renderer/core/loader/DEPS +++ b/third_party/blink/renderer/core/loader/DEPS
@@ -20,5 +20,7 @@ "+base/containers/flat_map.h", "+base/features.h", "+base/no_destructor.h", + "+base/strings/utf_string_conversions.h", "+services/network/public/cpp/client_hints.h", + "+url/url_features.h", ]
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc index 17e1dcf..b62b4e1 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -20,6 +20,7 @@ #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/inspector/identifiers_factory.h" #include "third_party/blink/renderer/core/loader/frame_client_hints_preferences_context.h" +#include "third_party/blink/renderer/core/loader/idna_util.h" #include "third_party/blink/renderer/core/loader/subresource_filter.h" #include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -690,6 +691,24 @@ } } + // Warn if the resource URL's hostname contains IDNA deviation characters. + // Only warn if the resource URL's origin is different than its requestor + // (we don't want to warn for <img src="faß.de/image.img"> on faß.de). + // TODO(crbug.com/1396475): Remove once Non-Transitional mode is shipped. + if (!resource_request.RequestorOrigin()->IsSameOriginWith( + SecurityOrigin::Create(url).get()) && + url.HasIDNA2008DeviationCharacter()) { + String message = GetConsoleWarningForIDNADeviationCharacters(url); + if (!message.empty()) { + AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kSecurity, + mojom::ConsoleMessageLevel::kWarning, message)); + UseCounter::Count( + GetExecutionContext(), + WebFeature::kIDNA2008DeviationCharacterInHostnameOfSubresource); + } + } + return absl::nullopt; }
diff --git a/third_party/blink/renderer/core/loader/build.gni b/third_party/blink/renderer/core/loader/build.gni index 04d9959..23600d7 100644 --- a/third_party/blink/renderer/core/loader/build.gni +++ b/third_party/blink/renderer/core/loader/build.gni
@@ -11,6 +11,8 @@ "back_forward_cache_loader_helper_impl.h", "base_fetch_context.cc", "base_fetch_context.h", + "idna_util.h", + "idna_util.cc", "beacon_data.cc", "beacon_data.h", "cookie_jar.cc",
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 30d84870..edcb94a2 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -54,6 +54,7 @@ #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h" #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h" #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h" +#include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/task_type.h" @@ -92,6 +93,7 @@ #include "third_party/blink/renderer/core/loader/form_submission.h" #include "third_party/blink/renderer/core/loader/frame_load_request.h" #include "third_party/blink/renderer/core/loader/frame_loader_types.h" +#include "third_party/blink/renderer/core/loader/idna_util.h" #include "third_party/blink/renderer/core/loader/mixed_content_checker.h" #include "third_party/blink/renderer/core/loader/progress_tracker.h" #include "third_party/blink/renderer/core/navigation_api/navigation_api.h" @@ -123,6 +125,7 @@ #include "third_party/blink/renderer/platform/network/http_parsers.h" #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" #include "third_party/blink/renderer/platform/network/network_utils.h" +#include "third_party/blink/renderer/platform/runtime_feature_state/runtime_feature_state_override_context.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/weborigin/security_policy.h" @@ -818,6 +821,25 @@ } } + // Warn if the resource URL's hostname contains IDNA deviation characters. + // Only warn if the resource URL's origin is different than its requestor + // (we don't want to warn for <img src="faß.de/image.img"> on faß.de). + // TODO(crbug.com/1396475): Remove once Non-Transitional mode is shipped. + if (resource_request.RequestorOrigin() && + !resource_request.RequestorOrigin()->IsSameOriginWith( + SecurityOrigin::Create(url).get()) && + url.HasIDNA2008DeviationCharacter()) { + String message = GetConsoleWarningForIDNADeviationCharacters(url); + if (!message.empty()) { + request.GetOriginWindow()->AddConsoleMessage( + MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kSecurity, + mojom::ConsoleMessageLevel::kWarning, message)); + origin_window->CountUse( + WebFeature::kIDNA2008DeviationCharacterInHostnameOfIFrame); + } + } + Client()->BeginNavigation( resource_request, request.GetFrameType(), origin_window, nullptr /* document_loader */, navigation_type, @@ -1164,6 +1186,10 @@ policy_container = PolicyContainer::CreateFromWebPolicyContainer( std::move(navigation_params->policy_container)); } + + base::flat_map<mojom::blink::RuntimeFeatureState, bool> override_values = + navigation_params->modified_runtime_features; + // TODO(dgozman): get rid of provisional document loader and most of the code // below. We should probably call DocumentLoader::CommitNavigation directly. DocumentLoader* new_document_loader = MakeGarbageCollected<DocumentLoader>( @@ -1175,6 +1201,14 @@ ScopedOldDocumentInfoForCommitCapturer::CurrentInfo()->history_item, commit_reason); + // Now that the RuntimeFeatureStateOverrideContext has been created, set the + // override values. + // TODO(crbug.com/1377000): Move this inside CommitNavigation() and put it + // alongside the other state initialization. + frame_->DomWindow() + ->GetRuntimeFeatureStateOverrideContext() + ->ApplyOverrideValuesFromParams(override_values); + RestoreScrollPositionAndViewState(); TakeObjectSnapshot();
diff --git a/third_party/blink/renderer/core/loader/idna_util.cc b/third_party/blink/renderer/core/loader/idna_util.cc new file mode 100644 index 0000000..87cbb505 --- /dev/null +++ b/third_party/blink/renderer/core/loader/idna_util.cc
@@ -0,0 +1,94 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/core/loader/idna_util.h" + +#include <unicode/idna.h> + +#include "base/strings/utf_string_conversions.h" +#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" +#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" +#include "url/url_features.h" + +namespace { + +// RFC5321 says the maximum total length of a domain name is 255 octets. +constexpr int32_t kMaximumDomainNameLengthForIDNADecoding = 255; + +// Unsafely decodes a punycode hostname to unicode (e.g. xn--fa-hia.de to +// faß.de). Only used for logging. Doesn't do any spoof checks on the output, +// so the output MUST NOT be used for anything else. +String UnsafeASCIIToIDNA(String hostname_ascii) { + static UIDNA* uidna = [] { + UErrorCode err = U_ZERO_ERROR; + UIDNA* value = + uidna_openUTS46(UIDNA_CHECK_BIDI | UIDNA_NONTRANSITIONAL_TO_ASCII | + UIDNA_NONTRANSITIONAL_TO_UNICODE, + &err); + if (U_FAILURE(err)) { + value = nullptr; + } + return value; + }(); + + if (!uidna) { + return String(); + } + DCHECK(hostname_ascii.ContainsOnlyASCIIOrEmpty()); + + UErrorCode status = U_ZERO_ERROR; + UIDNAInfo info = UIDNA_INFO_INITIALIZER; + Vector<char> output_utf8( + static_cast<wtf_size_t>(kMaximumDomainNameLengthForIDNADecoding), '\0'); + StringUTF8Adaptor hostname(hostname_ascii); + + // This returns the actual length required. If processing fails, info.errors + // will be nonzero. `status` indicates an error only in exceptional cases, + // such as a U_MEMORY_ALLOCATION_ERROR. + int32_t output_utf8_length = uidna_nameToUnicodeUTF8( + uidna, hostname.data(), static_cast<int32_t>(hostname.size()), + output_utf8.data(), output_utf8.size(), &info, &status); + if (U_FAILURE(status) || info.errors != 0 || + output_utf8_length > kMaximumDomainNameLengthForIDNADecoding) { + return String(); + } + return String::FromUTF8(output_utf8.data(), + static_cast<wtf_size_t>(output_utf8_length)); +} + +} // namespace + +namespace blink { + +String GetConsoleWarningForIDNADeviationCharacters(const KURL& url) { + if (!url::IsRecordingIDNA2008Metrics()) { + return String(); + } + // `url` is canonicalized to ASCII (i.e. punycode). First decode it to unicode + // then check for deviation characters. + String host = UnsafeASCIIToIDNA(url.Host()); + + if (!host.Contains(u"\u00DF") && // Sharp-s + !host.Contains(u"\u03C2") && // Greek final sigma + !host.Contains(u"\u200D") && // Zero width joiner + !host.Contains(u"\u200C")) { // Zero width non-joiner + return String(); + } + + String elided = url.ElidedString().replace( + url.HostStart(), url.HostEnd() - url.HostStart(), host); + StringBuilder message; + message.Append("The resource at "); + message.Append(elided); + message.Append( + " contains IDNA Deviation Characters. The hostname for this URL ("); + message.Append(host); + message.Append( + ") might point to a different IP address after " + "https://chromestatus.com/feature/5105856067141632. Make sure you are " + "using the correct host name."); + return message.ToString(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/core/loader/idna_util.h b/third_party/blink/renderer/core/loader/idna_util.h new file mode 100644 index 0000000..2f9c7bae --- /dev/null +++ b/third_party/blink/renderer/core/loader/idna_util.h
@@ -0,0 +1,19 @@ +// Copyright 2022 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDNA_UTIL_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_IDNA_UTIL_H_ + +#include "third_party/blink/renderer/platform/weborigin/kurl.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +// Returns a console message if the hostname of `url` contains IDNA 2008 +// deviation characters. Returns empty string otherwise. +String GetConsoleWarningForIDNADeviationCharacters(const KURL& url); + +} // namespace blink + +#endif
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc index 5c942f07..2f2e89c 100644 --- a/third_party/blink/renderer/core/page/focus_controller.cc +++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -91,7 +91,7 @@ auto* invoker = DynamicTo<HTMLFormControlElement>(node); if (!invoker) return false; - HTMLElement* popover = invoker->popoverTargetElement().element; + HTMLElement* popover = invoker->popoverTargetElement().popover; if (!popover) return false; return popover->popoverOpen(); @@ -368,7 +368,7 @@ DCHECK(IsA<HTMLFormControlElement>(invoker)); HTMLElement* popover = DynamicTo<HTMLFormControlElement>(invoker) ->popoverTargetElement() - .element; + .popover; DCHECK(IsOpenPopoverWithInvoker(popover)); return ScopedFocusNavigation(*popover, nullptr, owner_map); }
diff --git a/third_party/blink/renderer/core/timing/back_forward_cache_restoration.cc b/third_party/blink/renderer/core/timing/back_forward_cache_restoration.cc index caf882e4..f3bdd66b 100644 --- a/third_party/blink/renderer/core/timing/back_forward_cache_restoration.cc +++ b/third_party/blink/renderer/core/timing/back_forward_cache_restoration.cc
@@ -12,11 +12,13 @@ DOMHighResTimeStamp start_time, DOMHighResTimeStamp pageshow_event_start, DOMHighResTimeStamp pageshow_event_end, - uint32_t navigation_id) + uint32_t navigation_id, + DOMWindow* source) : PerformanceEntry(g_empty_atom, start_time, pageshow_event_start, - navigation_id), + navigation_id, + source), pageshow_event_start_(pageshow_event_start), pageshow_event_end_(pageshow_event_end) {} BackForwardCacheRestoration::~BackForwardCacheRestoration() = default;
diff --git a/third_party/blink/renderer/core/timing/back_forward_cache_restoration.h b/third_party/blink/renderer/core/timing/back_forward_cache_restoration.h index 762514f..f20da0b2 100644 --- a/third_party/blink/renderer/core/timing/back_forward_cache_restoration.h +++ b/third_party/blink/renderer/core/timing/back_forward_cache_restoration.h
@@ -18,7 +18,8 @@ BackForwardCacheRestoration(DOMHighResTimeStamp start_time, DOMHighResTimeStamp pageshow_event_start, DOMHighResTimeStamp pageshow_event_end, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~BackForwardCacheRestoration() override; const AtomicString& entryType() const override; PerformanceEntryType EntryTypeEnum() const override;
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.cc b/third_party/blink/renderer/core/timing/largest_contentful_paint.cc index 32f67e1..40b4a21 100644 --- a/third_party/blink/renderer/core/timing/largest_contentful_paint.cc +++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
@@ -20,8 +20,13 @@ const AtomicString& id, const String& url, Element* element, - uint32_t navigation_id) - : PerformanceEntry(g_empty_atom, start_time, start_time, navigation_id), + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(g_empty_atom, + start_time, + start_time, + navigation_id, + source), size_(size), render_time_(render_time), load_time_(load_time),
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.h b/third_party/blink/renderer/core/timing/largest_contentful_paint.h index 852141ef..c20ced0 100644 --- a/third_party/blink/renderer/core/timing/largest_contentful_paint.h +++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.h
@@ -27,7 +27,8 @@ const AtomicString& id, const String& url, Element* element, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~LargestContentfulPaint() override; const AtomicString& entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/layout_shift.cc b/third_party/blink/renderer/core/timing/layout_shift.cc index 8c9527f..847789d 100644 --- a/third_party/blink/renderer/core/timing/layout_shift.cc +++ b/third_party/blink/renderer/core/timing/layout_shift.cc
@@ -16,10 +16,11 @@ bool input_detected, double input_timestamp, AttributionList sources, - uint32_t navigation_id) { + uint32_t navigation_id, + DOMWindow* source) { return MakeGarbageCollected<LayoutShift>(start_time, value, input_detected, input_timestamp, sources, - navigation_id); + navigation_id, source); } LayoutShift::LayoutShift(double start_time, @@ -27,8 +28,13 @@ bool input_detected, double input_timestamp, AttributionList sources, - uint32_t navigation_id) - : PerformanceEntry(g_empty_atom, start_time, start_time, navigation_id), + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(g_empty_atom, + start_time, + start_time, + navigation_id, + source), value_(value), had_recent_input_(input_detected), most_recent_input_timestamp_(input_timestamp),
diff --git a/third_party/blink/renderer/core/timing/layout_shift.h b/third_party/blink/renderer/core/timing/layout_shift.h index 42fd190..6476499 100644 --- a/third_party/blink/renderer/core/timing/layout_shift.h +++ b/third_party/blink/renderer/core/timing/layout_shift.h
@@ -31,14 +31,16 @@ bool input_detected, double input_timestamp, AttributionList sources, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); explicit LayoutShift(double start_time, double value, bool input_detected, double input_timestamp, AttributionList sources, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~LayoutShift() override;
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc index 8a4990c..d6ea3167 100644 --- a/third_party/blink/renderer/core/timing/performance.cc +++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -676,7 +676,7 @@ ExecutionContext* context) { auto* entry = MakeGarbageCollected<PerformanceResourceTiming>( *info, time_origin_, cross_origin_isolated_capability_, initiator_type, - context); + context, DynamicTo<LocalDOMWindow>(context)); NotifyObserversOfEntry(*entry); // https://w3c.github.io/resource-timing/#dfn-add-a-performanceresourcetiming-entry if (CanAddResourceTimingEntry() && @@ -818,7 +818,8 @@ base::TimeTicks start_time) { PerformanceEntry* entry = MakeGarbageCollected<PerformancePaintTiming>( type, MonotonicTimeToDOMHighResTimeStamp(start_time), - PerformanceEntry::GetNavigationId(GetExecutionContext())); + PerformanceEntry::GetNavigationId(GetExecutionContext()), + DynamicTo<LocalDOMWindow>(GetExecutionContext())); DCHECK((type == PerformancePaintTiming::PaintType::kFirstPaint) || (type == PerformancePaintTiming::PaintType::kFirstContentfulPaint)); if (paint_entries_timing_.size() < kDefaultPaintEntriesBufferSize) { @@ -852,7 +853,8 @@ static_cast<int>(MonotonicTimeToDOMHighResTimeStamp(end_time) - dom_high_res_start_time), name, container_type, container_src, container_id, container_name, - PerformanceEntry::GetNavigationId(execution_context)); + PerformanceEntry::GetNavigationId(execution_context), + DynamicTo<LocalDOMWindow>(execution_context)); if (longtask_buffer_.size() < kDefaultLongTaskBufferSize) { InsertEntryIntoSortedBuffer(longtask_buffer_, *entry, kRecordSwaps); } else { @@ -875,7 +877,8 @@ MonotonicTimeToDOMHighResTimeStamp(start_time), MonotonicTimeToDOMHighResTimeStamp(pageshow_start_time), MonotonicTimeToDOMHighResTimeStamp(pageshow_end_time), - PerformanceEntry::GetNavigationId(GetExecutionContext())); + PerformanceEntry::GetNavigationId(GetExecutionContext()), + DynamicTo<LocalDOMWindow>(GetExecutionContext())); if (back_forward_cache_restoration_buffer_.size() < back_forward_cache_restoration_buffer_size_limit_) { InsertEntryIntoSortedBuffer(back_forward_cache_restoration_buffer_, *entry, @@ -1069,9 +1072,9 @@ const V8UnionDoubleOrString* end, const ScriptValue& detail, ExceptionState& exception_state) { - PerformanceMeasure* performance_measure = - GetUserTiming().Measure(script_state, measure_name, start, duration, end, - detail, exception_state); + PerformanceMeasure* performance_measure = GetUserTiming().Measure( + script_state, measure_name, start, duration, end, detail, exception_state, + LocalDOMWindow::From(script_state)); if (performance_measure) NotifyObserversOfEntry(*performance_measure); return performance_measure;
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.cc b/third_party/blink/renderer/core/timing/performance_element_timing.cc index 991e076..6e527f2 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_element_timing.cc
@@ -23,7 +23,8 @@ int naturalHeight, const AtomicString& id, Element* element, - uint32_t navigation_id) { + uint32_t navigation_id, + DOMWindow* source) { // It is possible to 'paint' images which have naturalWidth or naturalHeight // equal to 0. DCHECK_GE(naturalWidth, 0); @@ -32,7 +33,8 @@ double start_time = render_time != 0.0 ? render_time : load_time; return MakeGarbageCollected<PerformanceElementTiming>( name, start_time, url, intersection_rect, render_time, load_time, - identifier, naturalWidth, naturalHeight, id, element, navigation_id); + identifier, naturalWidth, naturalHeight, id, element, navigation_id, + source); } PerformanceElementTiming::PerformanceElementTiming( @@ -47,8 +49,9 @@ int naturalHeight, const AtomicString& id, Element* element, - uint32_t navigation_id) - : PerformanceEntry(name, start_time, start_time, navigation_id), + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(name, start_time, start_time, navigation_id, source), element_(element), intersection_rect_(DOMRectReadOnly::FromRectF(intersection_rect)), render_time_(render_time),
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.h b/third_party/blink/renderer/core/timing/performance_element_timing.h index 6e40732..3be35a42 100644 --- a/third_party/blink/renderer/core/timing/performance_element_timing.h +++ b/third_party/blink/renderer/core/timing/performance_element_timing.h
@@ -32,7 +32,8 @@ int naturalHeight, const AtomicString& id, Element*, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); PerformanceElementTiming(const AtomicString& name, DOMHighResTimeStamp start_time, const String& url, @@ -44,7 +45,8 @@ int naturalHeight, const AtomicString& id, Element*, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~PerformanceElementTiming() override;
diff --git a/third_party/blink/renderer/core/timing/performance_entry.cc b/third_party/blink/renderer/core/timing/performance_entry.cc index 1571f7327..52a9592 100644 --- a/third_party/blink/renderer/core/timing/performance_entry.cc +++ b/third_party/blink/renderer/core/timing/performance_entry.cc
@@ -48,22 +48,26 @@ PerformanceEntry::PerformanceEntry(const AtomicString& name, double start_time, double finish_time, - uint32_t navigation_id) + uint32_t navigation_id, + DOMWindow* source) : duration_(finish_time - start_time), name_(name), start_time_(start_time), index_(index_seq.GetNext()), - navigation_id_(navigation_id) {} + navigation_id_(navigation_id), + source_(source) {} PerformanceEntry::PerformanceEntry(double duration, const AtomicString& name, double start_time, - uint32_t navigation_id) + uint32_t navigation_id, + DOMWindow* source) : duration_(duration), name_(name), start_time_(start_time), index_(index_seq.GetNext()), - navigation_id_(navigation_id) { + navigation_id_(navigation_id), + source_(source) { DCHECK_GE(duration_, 0.0); } @@ -81,6 +85,10 @@ return navigation_id_; } +DOMWindow* PerformanceEntry::source() const { + return source_; +} + mojom::blink::PerformanceMarkOrMeasurePtr PerformanceEntry::ToMojoPerformanceMarkOrMeasure() { DCHECK(EntryTypeEnum() == kMark || EntryTypeEnum() == kMeasure); @@ -153,6 +161,11 @@ return local_dom_window->GetNavigationId(); } +void PerformanceEntry::Trace(Visitor* visitor) const { + visitor->Trace(source_); + ScriptWrappable::Trace(visitor); +} + ScriptValue PerformanceEntry::toJSONForBinding( ScriptState* script_state) const { V8ObjectBuilder result(script_state);
diff --git a/third_party/blink/renderer/core/timing/performance_entry.h b/third_party/blink/renderer/core/timing/performance_entry.h index 95916303..93695e7 100644 --- a/third_party/blink/renderer/core/timing/performance_entry.h +++ b/third_party/blink/renderer/core/timing/performance_entry.h
@@ -35,6 +35,7 @@ #include "third_party/blink/public/mojom/timing/performance_mark_or_measure.mojom-blink-forward.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/dom/dom_high_res_time_stamp.h" +#include "third_party/blink/renderer/core/frame/dom_window.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -79,6 +80,9 @@ const AtomicString& name() const { return name_; } DOMHighResTimeStamp startTime() const; uint32_t navigationId() const; + // source() will return null if the PerformanceEntry did not originate from a + // Window context. + DOMWindow* source() const; virtual const AtomicString& entryType() const = 0; virtual PerformanceEntryType EntryTypeEnum() const = 0; // PerformanceNavigationTiming will override this due to @@ -129,15 +133,19 @@ virtual mojom::blink::PerformanceMarkOrMeasurePtr ToMojoPerformanceMarkOrMeasure(); + void Trace(Visitor*) const override; + protected: PerformanceEntry(const AtomicString& name, double start_time, double finish_time, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); PerformanceEntry(double duration, const AtomicString& name, double start_time, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); virtual void BuildJSONValue(V8ObjectBuilder&) const; @@ -149,6 +157,9 @@ const double start_time_; const int index_; const uint32_t navigation_id_; + // source_ will be null if the PerformanceEntry did not originate from a + // Window context. + const Member<DOMWindow> source_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/timing/performance_entry.idl b/third_party/blink/renderer/core/timing/performance_entry.idl index 8c8d8bd8..a7e9ef3 100644 --- a/third_party/blink/renderer/core/timing/performance_entry.idl +++ b/third_party/blink/renderer/core/timing/performance_entry.idl
@@ -37,5 +37,6 @@ readonly attribute DOMHighResTimeStamp startTime; readonly attribute DOMHighResTimeStamp duration; [RuntimeEnabled=NavigationId] readonly attribute unsigned long navigationId; + [RuntimeEnabled=CrossFramePerformanceTimeline, Exposed=Window] readonly attribute EventTarget source; [CallWith=ScriptState, ImplementedAs=toJSONForBinding] object toJSON(); };
diff --git a/third_party/blink/renderer/core/timing/performance_event_timing.cc b/third_party/blink/renderer/core/timing/performance_event_timing.cc index ab6bb840..24259bb 100644 --- a/third_party/blink/renderer/core/timing/performance_event_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_event_timing.cc
@@ -22,13 +22,14 @@ DOMHighResTimeStamp processing_end, bool cancelable, Node* target, - uint32_t navigation_id) { + uint32_t navigation_id, + DOMWindow* source) { // TODO(npm): enable this DCHECK once https://crbug.com/852846 is fixed. // DCHECK_LE(start_time, processing_start); DCHECK_LE(processing_start, processing_end); return MakeGarbageCollected<PerformanceEventTiming>( event_type, performance_entry_names::kEvent, start_time, processing_start, - processing_end, cancelable, target, navigation_id); + processing_end, cancelable, target, navigation_id, source); } // static @@ -38,7 +39,8 @@ MakeGarbageCollected<PerformanceEventTiming>( entry->name(), performance_entry_names::kFirstInput, entry->startTime(), entry->processingStart(), entry->processingEnd(), - entry->cancelable(), entry->target(), entry->navigationId()); + entry->cancelable(), entry->target(), entry->navigationId(), + entry->source()); first_input->SetDuration(entry->duration()); return first_input; } @@ -51,8 +53,9 @@ DOMHighResTimeStamp processing_end, bool cancelable, Node* target, - uint32_t navigation_id) - : PerformanceEntry(event_type, start_time, 0.0, navigation_id), + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(event_type, start_time, 0.0, navigation_id, source), entry_type_(entry_type), processing_start_(processing_start), processing_end_(processing_end),
diff --git a/third_party/blink/renderer/core/timing/performance_event_timing.h b/third_party/blink/renderer/core/timing/performance_event_timing.h index 4f10adcc..84b44e0e 100644 --- a/third_party/blink/renderer/core/timing/performance_event_timing.h +++ b/third_party/blink/renderer/core/timing/performance_event_timing.h
@@ -24,7 +24,8 @@ DOMHighResTimeStamp processing_end, bool cancelable, Node* target, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); static PerformanceEventTiming* CreateFirstInputTiming( PerformanceEventTiming* entry); @@ -36,7 +37,8 @@ DOMHighResTimeStamp processing_end, bool cancelable, Node* target, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~PerformanceEventTiming() override; const AtomicString& entryType() const override { return entry_type_; }
diff --git a/third_party/blink/renderer/core/timing/performance_long_task_timing.cc b/third_party/blink/renderer/core/timing/performance_long_task_timing.cc index effe654..929be42f 100644 --- a/third_party/blink/renderer/core/timing/performance_long_task_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_long_task_timing.cc
@@ -20,11 +20,12 @@ const AtomicString& culprit_src, const AtomicString& culprit_id, const AtomicString& culprit_name, - const uint32_t navigation_id) - : PerformanceEntry(duration, name, start_time, navigation_id) { + const uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(duration, name, start_time, navigation_id, source) { auto* attribution_entry = MakeGarbageCollected<TaskAttributionTiming>( "unknown", culprit_type, culprit_src, culprit_id, culprit_name, - navigation_id); + navigation_id, source); attribution_.push_back(*attribution_entry); }
diff --git a/third_party/blink/renderer/core/timing/performance_long_task_timing.h b/third_party/blink/renderer/core/timing/performance_long_task_timing.h index a5292fc..85318575 100644 --- a/third_party/blink/renderer/core/timing/performance_long_task_timing.h +++ b/third_party/blink/renderer/core/timing/performance_long_task_timing.h
@@ -31,7 +31,8 @@ const AtomicString& culprit_src, const AtomicString& culprit_id, const AtomicString& culprit_name, - const uint32_t navigation_id); + const uint32_t navigation_id, + DOMWindow* source); ~PerformanceLongTaskTiming() override; const AtomicString& entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/performance_mark.cc b/third_party/blink/renderer/core/timing/performance_mark.cc index d3f1553d..7e1372a 100644 --- a/third_party/blink/renderer/core/timing/performance_mark.cc +++ b/third_party/blink/renderer/core/timing/performance_mark.cc
@@ -23,8 +23,9 @@ base::TimeTicks unsafe_time_for_traces, scoped_refptr<SerializedScriptValue> serialized_detail, ExceptionState& exception_state, - uint32_t navigation_id) - : PerformanceEntry(name, start_time, start_time, navigation_id), + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(name, start_time, start_time, navigation_id, source), serialized_detail_(std::move(serialized_detail)), unsafe_time_for_traces_(unsafe_time_for_traces) {} @@ -93,7 +94,7 @@ uint32_t navigation_id = PerformanceEntry::GetNavigationId(script_state); return MakeGarbageCollected<PerformanceMark>( mark_name, start, unsafe_start_for_traces, std::move(serialized_detail), - exception_state, navigation_id); + exception_state, navigation_id, LocalDOMWindow::From(script_state)); } const AtomicString& PerformanceMark::entryType() const {
diff --git a/third_party/blink/renderer/core/timing/performance_mark.h b/third_party/blink/renderer/core/timing/performance_mark.h index 009fd8b0..d8dd8be 100644 --- a/third_party/blink/renderer/core/timing/performance_mark.h +++ b/third_party/blink/renderer/core/timing/performance_mark.h
@@ -57,14 +57,13 @@ ExceptionState&); // This constructor is only public so that MakeGarbageCollected can call it. - PerformanceMark( - const AtomicString& name, - double start_time, - base::TimeTicks unsafe_time_for_traces, - scoped_refptr<SerializedScriptValue>, - ExceptionState& exception_state, - uint32_t navigation_count = 0); /* TODO(1273925): Remove the default value - when all callers have been updated. */ + PerformanceMark(const AtomicString& name, + double start_time, + base::TimeTicks unsafe_time_for_traces, + scoped_refptr<SerializedScriptValue>, + ExceptionState& exception_state, + uint32_t navigation_count, + DOMWindow* source); ~PerformanceMark() override = default;
diff --git a/third_party/blink/renderer/core/timing/performance_mark_test.cc b/third_party/blink/renderer/core/timing/performance_mark_test.cc index 73412ec..ddbd2352 100644 --- a/third_party/blink/renderer/core/timing/performance_mark_test.cc +++ b/third_party/blink/renderer/core/timing/performance_mark_test.cc
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_performance_mark_options.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/performance_entry_names.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" @@ -46,7 +47,7 @@ PerformanceMark* pm = MakeGarbageCollected<PerformanceMark>( "mark-name", 0, base::TimeTicks(), SerializedScriptValue::NullValue(), - exception_state, 1); + exception_state, 1, LocalDOMWindow::From(script_state)); ASSERT_EQ(pm->entryType(), performance_entry_names::kMark); ASSERT_EQ(pm->EntryTypeEnum(), PerformanceEntry::EntryType::kMark); @@ -65,7 +66,8 @@ SerializedScriptValue::Create(String("some-payload")); PerformanceMark* pm = MakeGarbageCollected<PerformanceMark>( - "mark-name", 0, base::TimeTicks(), payload_string, exception_state); + "mark-name", 0, base::TimeTicks(), payload_string, exception_state, 0, + LocalDOMWindow::From(script_state)); ASSERT_EQ(pm->entryType(), performance_entry_names::kMark); ASSERT_EQ(pm->EntryTypeEnum(), PerformanceEntry::EntryType::kMark); @@ -86,7 +88,8 @@ const AtomicString expected_entry_type = "mark"; PerformanceMark pm(expected_name, expected_start_time, base::TimeTicks(), SerializedScriptValue::NullValue(), exception_state, - expected_navigation_count); + expected_navigation_count, + LocalDOMWindow::From(script_state)); ScriptValue json_object = pm.toJSONForBinding(script_state); EXPECT_TRUE(json_object.IsObject());
diff --git a/third_party/blink/renderer/core/timing/performance_measure.cc b/third_party/blink/renderer/core/timing/performance_measure.cc index c8035df..d98397a4 100644 --- a/third_party/blink/renderer/core/timing/performance_measure.cc +++ b/third_party/blink/renderer/core/timing/performance_measure.cc
@@ -19,21 +19,23 @@ double start_time, double end_time, scoped_refptr<SerializedScriptValue> serialized_detail, - ExceptionState& exception_state) + ExceptionState& exception_state, + DOMWindow* source) : PerformanceEntry(name, start_time, end_time, - PerformanceEntry::GetNavigationId(script_state)), + PerformanceEntry::GetNavigationId(script_state), + source), serialized_detail_(serialized_detail) {} // static -PerformanceMeasure* PerformanceMeasure::Create( - ScriptState* script_state, - const AtomicString& name, - double start_time, - double end_time, - const ScriptValue& detail, - ExceptionState& exception_state) { +PerformanceMeasure* PerformanceMeasure::Create(ScriptState* script_state, + const AtomicString& name, + double start_time, + double end_time, + const ScriptValue& detail, + ExceptionState& exception_state, + DOMWindow* source) { scoped_refptr<SerializedScriptValue> serialized_detail; if (detail.IsEmpty()) { serialized_detail = nullptr; @@ -46,7 +48,7 @@ } return MakeGarbageCollected<PerformanceMeasure>( script_state, name, start_time, end_time, serialized_detail, - exception_state); + exception_state, source); } ScriptValue PerformanceMeasure::detail(ScriptState* script_state) {
diff --git a/third_party/blink/renderer/core/timing/performance_measure.h b/third_party/blink/renderer/core/timing/performance_measure.h index d74343e8..4209bbd1 100644 --- a/third_party/blink/renderer/core/timing/performance_measure.h +++ b/third_party/blink/renderer/core/timing/performance_measure.h
@@ -49,7 +49,8 @@ double start_time, double end_time, scoped_refptr<SerializedScriptValue>, - ExceptionState&); + ExceptionState&, + DOMWindow* source); ~PerformanceMeasure() override = default; static PerformanceMeasure* Create(ScriptState*, @@ -57,7 +58,8 @@ double start_time, double end_time, const ScriptValue& detail, - ExceptionState&); + ExceptionState&, + DOMWindow* source); ScriptValue detail(ScriptState*);
diff --git a/third_party/blink/renderer/core/timing/performance_navigation_timing.cc b/third_party/blink/renderer/core/timing/performance_navigation_timing.cc index e67d2c7..456afb0 100644 --- a/third_party/blink/renderer/core/timing/performance_navigation_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_navigation_timing.cc
@@ -68,7 +68,8 @@ window->Url().Protocol().Ascii()), std::move(server_timing), window, - navigation_delivery_type), + navigation_delivery_type, + window), ExecutionContextClient(window), resource_timing_info_(info) { DCHECK(window);
diff --git a/third_party/blink/renderer/core/timing/performance_observer_test.cc b/third_party/blink/renderer/core/timing/performance_observer_test.cc index e30b482..6b1b866b 100644 --- a/third_party/blink/renderer/core/timing/performance_observer_test.cc +++ b/third_party/blink/renderer/core/timing/performance_observer_test.cc
@@ -77,9 +77,9 @@ EXPECT_EQ(0, NumPerformanceEntries()); // add a layout-shift to performance so getEntries() returns it - auto* entry = - LayoutShift::Create(0.0, 1234, true, 5678, LayoutShift::AttributionList(), - /*navigation_id=*/1); + auto* entry = LayoutShift::Create( + 0.0, 1234, true, 5678, LayoutShift::AttributionList(), + /*navigation_id=*/1, LocalDOMWindow::From(scope.GetScriptState())); base_->AddLayoutShiftBuffer(*entry); // call observe with the buffered flag
diff --git a/third_party/blink/renderer/core/timing/performance_paint_timing.cc b/third_party/blink/renderer/core/timing/performance_paint_timing.cc index b6c3e66f..3c75040 100644 --- a/third_party/blink/renderer/core/timing/performance_paint_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_paint_timing.cc
@@ -32,11 +32,13 @@ PerformancePaintTiming::PerformancePaintTiming(PaintType type, double start_time, - uint32_t navigation_id) + uint32_t navigation_id, + DOMWindow* source) : PerformanceEntry(FromPaintTypeToString(type), start_time, start_time, - navigation_id) {} + navigation_id, + source) {} PerformancePaintTiming::~PerformancePaintTiming() = default;
diff --git a/third_party/blink/renderer/core/timing/performance_paint_timing.h b/third_party/blink/renderer/core/timing/performance_paint_timing.h index a1bfbd741..c640163 100644 --- a/third_party/blink/renderer/core/timing/performance_paint_timing.h +++ b/third_party/blink/renderer/core/timing/performance_paint_timing.h
@@ -16,7 +16,10 @@ public: enum class PaintType { kFirstPaint, kFirstContentfulPaint }; - PerformancePaintTiming(PaintType, double start_time, uint32_t navigation_id); + PerformancePaintTiming(PaintType, + double start_time, + uint32_t navigation_id, + DOMWindow* source); ~PerformancePaintTiming() override; const AtomicString& entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.cc b/third_party/blink/renderer/core/timing/performance_resource_timing.cc index 0ff35dff..45f7680e 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.cc
@@ -80,7 +80,8 @@ base::TimeTicks time_origin, bool cross_origin_isolated_capability, const AtomicString& initiator_type, - ExecutionContext* context) + ExecutionContext* context, + DOMWindow* source) : PerformanceEntry(AtomicString(info.name), Performance::MonotonicTimeToDOMHighResTimeStamp( time_origin, @@ -92,7 +93,8 @@ info.response_end, info.allow_negative_values, cross_origin_isolated_capability), - PerformanceEntry::GetNavigationId(context)), + PerformanceEntry::GetNavigationId(context), + source), initiator_type_(initiator_type.empty() ? fetch_initiator_type_names::kOther : initiator_type), @@ -136,8 +138,9 @@ bool is_secure_transport, HeapVector<Member<PerformanceServerTiming>> server_timing, ExecutionContext* context, - NavigationDeliveryType navigation_delivery_type) - : PerformanceEntry(name, 0.0, 0.0, kNavigationIdDefaultValue), + NavigationDeliveryType navigation_delivery_type, + DOMWindow* source) + : PerformanceEntry(name, 0.0, 0.0, kNavigationIdDefaultValue, source), delivery_type_(GetDeliveryType(navigation_delivery_type, cache_state)), time_origin_(time_origin), cross_origin_isolated_capability_(cross_origin_isolated_capability),
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing.h b/third_party/blink/renderer/core/timing/performance_resource_timing.h index 450eb6a2..8826f1fb 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing.h +++ b/third_party/blink/renderer/core/timing/performance_resource_timing.h
@@ -66,12 +66,14 @@ bool is_secure_transport, HeapVector<Member<PerformanceServerTiming>> server_timing, ExecutionContext* context, - network::mojom::NavigationDeliveryType delivery_type); + network::mojom::NavigationDeliveryType delivery_type, + DOMWindow* source); PerformanceResourceTiming(const mojom::blink::ResourceTimingInfo&, base::TimeTicks time_origin, bool cross_origin_isolated_capability, const AtomicString& initiator_type, - ExecutionContext* context); + ExecutionContext* context, + DOMWindow* source); ~PerformanceResourceTiming() override; const AtomicString& entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/performance_resource_timing_test.cc b/third_party/blink/renderer/core/timing/performance_resource_timing_test.cc index ebf03b4..bab768d 100644 --- a/third_party/blink/renderer/core/timing/performance_resource_timing_test.cc +++ b/third_party/blink/renderer/core/timing/performance_resource_timing_test.cc
@@ -5,7 +5,9 @@ #include "third_party/blink/renderer/core/timing/performance_resource_timing.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" namespace blink { @@ -31,6 +33,10 @@ connection_info); } + void Initialize(ScriptState* script_state) { script_state_ = script_state; } + + ScriptState* GetScriptState() { return script_state_; } + private: PerformanceResourceTiming* MakePerformanceResourceTiming( const mojom::blink::ResourceTimingInfo& info) { @@ -42,12 +48,18 @@ .GetExecutionContext() ->CrossOriginIsolatedCapability(), /*initiator_type=*/"", - dummy_page_holder->GetDocument().GetExecutionContext()); + dummy_page_holder->GetDocument().GetExecutionContext(), + LocalDOMWindow::From(GetScriptState())); } + + Persistent<ScriptState> script_state_; }; TEST_F(PerformanceResourceTimingTest, TestFallbackToConnectionInfoWhenALPNUnknown) { + V8TestingScope scope; + Initialize(scope.GetScriptState()); + AtomicString connection_info = "http/1.1"; AtomicString alpn_negotiated_protocol = "unknown"; EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), @@ -56,12 +68,18 @@ TEST_F(PerformanceResourceTimingTest, TestFallbackToHTTPInfoWhenALPNAndConnectionInfoUnknown) { + V8TestingScope scope; + Initialize(scope.GetScriptState()); + AtomicString connection_info = "unknown"; AtomicString alpn_negotiated_protocol = "unknown"; EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), ""); } TEST_F(PerformanceResourceTimingTest, TestNoChangeWhenContainsQuic) { + V8TestingScope scope; + Initialize(scope.GetScriptState()); + AtomicString connection_info = "http/1.1"; AtomicString alpn_negotiated_protocol = "http/2+quic/39"; EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), @@ -69,6 +87,9 @@ } TEST_F(PerformanceResourceTimingTest, TestNoChangeWhenOtherwise) { + V8TestingScope scope; + Initialize(scope.GetScriptState()); + AtomicString connection_info = "http/1.1"; AtomicString alpn_negotiated_protocol = "RandomProtocol"; EXPECT_EQ(GetNextHopProtocol(alpn_negotiated_protocol, connection_info), @@ -76,6 +97,9 @@ } TEST_F(PerformanceResourceTimingTest, TestNextHopProtocolIsGuardedByTao) { + V8TestingScope scope; + Initialize(scope.GetScriptState()); + AtomicString connection_info = "http/1.1"; AtomicString alpn_negotiated_protocol = "RandomProtocol"; EXPECT_EQ(
diff --git a/third_party/blink/renderer/core/timing/performance_test.cc b/third_party/blink/renderer/core/timing/performance_test.cc index b3292ef..bd11c511 100644 --- a/third_party/blink/renderer/core/timing/performance_test.cc +++ b/third_party/blink/renderer/core/timing/performance_test.cc
@@ -14,6 +14,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_performance_observer_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_performance_observer_init.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" +#include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/testing/null_execution_context.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/core/timing/back_forward_cache_restoration.h" @@ -33,6 +34,8 @@ constexpr int kEvent2PageshowEnd = 987; } // namespace +class LocalDOMWindow; + class TestPerformance : public Performance { public: explicit TestPerformance(ScriptState* script_state) @@ -231,8 +234,9 @@ PerformanceEntryVector test_buffer_; - PerformanceEventTiming* test_entry = - PerformanceEventTiming::Create("event", 0.0, 0.0, 0.0, false, nullptr, 0); + PerformanceEventTiming* test_entry = PerformanceEventTiming::Create( + "event", 0.0, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); base_->InsertEntryIntoSortedBuffer(test_buffer_, *test_entry, Performance::kDoNotRecordSwaps); @@ -254,12 +258,14 @@ for (int i = 0; i < 3; i++) { double tmp = 1.0; PerformanceEventTiming* entry = PerformanceEventTiming::Create( - "event", tmp * i, 0.0, 0.0, false, nullptr, 0); + "event", tmp * i, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); test_buffer_.push_back(*entry); } - PerformanceEventTiming* test_entry = - PerformanceEventTiming::Create("event", 1.0, 0.0, 0.0, false, nullptr, 0); + PerformanceEventTiming* test_entry = PerformanceEventTiming::Create( + "event", 1.0, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); // Create copy of the test_buffer_. PerformanceEntryVector sorted_buffer_ = test_buffer_; @@ -285,12 +291,14 @@ for (int i = 0; i < 3; i++) { double tmp = 1.0; PerformanceEventTiming* entry = PerformanceEventTiming::Create( - "event", tmp * i, 0.0, 0.0, false, nullptr, 0); + "event", tmp * i, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); test_buffer_.push_back(*entry); } - PerformanceEventTiming* test_entry = - PerformanceEventTiming::Create("event", 0.0, 0.0, 0.0, false, nullptr, 0); + PerformanceEventTiming* test_entry = PerformanceEventTiming::Create( + "event", 0.0, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); // Create copy of the test_buffer_. PerformanceEntryVector sorted_buffer_ = test_buffer_; @@ -306,6 +314,9 @@ } TEST_F(PerformanceTest, MergePerformanceEntryVectorsTest) { + V8TestingScope scope; + Initialize(scope.GetScriptState()); + PerformanceEntryVector first_vector; PerformanceEntryVector second_vector; @@ -314,7 +325,8 @@ for (int i = 0; i < 6; i += 2) { double tmp = 1.0; PerformanceEventTiming* entry = PerformanceEventTiming::Create( - "event", tmp * i, 0.0, 0.0, false, nullptr, 0); + "event", tmp * i, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); first_vector.push_back(*entry); test_vector.push_back(*entry); } @@ -322,7 +334,8 @@ for (int i = 1; i < 6; i += 2) { double tmp = 1.0; PerformanceEventTiming* entry = PerformanceEventTiming::Create( - "event", tmp * i, 0.0, 0.0, false, nullptr, 0); + "event", tmp * i, 0.0, 0.0, false, nullptr, 0, + LocalDOMWindow::From(scope.GetScriptState())); second_vector.push_back(*entry); test_vector.push_back(*entry); }
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.cc b/third_party/blink/renderer/core/timing/performance_user_timing.cc index de67bfbb..6a2025d 100644 --- a/third_party/blink/renderer/core/timing/performance_user_timing.cc +++ b/third_party/blink/renderer/core/timing/performance_user_timing.cc
@@ -175,7 +175,8 @@ const absl::optional<double>& duration, const V8UnionDoubleOrString* end, const ScriptValue& detail, - ExceptionState& exception_state) { + ExceptionState& exception_state, + DOMWindow* source) { double start_time = start ? GetTimeOrFindMarkTime(measure_name, start, exception_state) : 0; if (exception_state.HadException()) @@ -219,7 +220,7 @@ PerformanceMeasure* measure = PerformanceMeasure::Create(script_state, measure_name, start_time, - end_time, detail, exception_state); + end_time, detail, exception_state, source); if (!measure) return nullptr; InsertPerformanceEntry(measures_map_, measures_buffer_, *measure);
diff --git a/third_party/blink/renderer/core/timing/performance_user_timing.h b/third_party/blink/renderer/core/timing/performance_user_timing.h index fc283ce..4293c98 100644 --- a/third_party/blink/renderer/core/timing/performance_user_timing.h +++ b/third_party/blink/renderer/core/timing/performance_user_timing.h
@@ -53,7 +53,8 @@ const absl::optional<double>& duration, const V8UnionDoubleOrString* end, const ScriptValue& detail, - ExceptionState&); + ExceptionState&, + DOMWindow* source); void ClearMeasures(const AtomicString& measure_name); PerformanceEntryVector GetMarks() const;
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_entry.cc b/third_party/blink/renderer/core/timing/soft_navigation_entry.cc index ab59820..06c47c65 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_entry.cc +++ b/third_party/blink/renderer/core/timing/soft_navigation_entry.cc
@@ -11,8 +11,9 @@ SoftNavigationEntry::SoftNavigationEntry(AtomicString name, double start_time, - uint32_t navigation_id) - : PerformanceEntry(name, start_time, start_time, navigation_id) {} + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(name, start_time, start_time, navigation_id, source) {} SoftNavigationEntry::~SoftNavigationEntry() = default;
diff --git a/third_party/blink/renderer/core/timing/soft_navigation_entry.h b/third_party/blink/renderer/core/timing/soft_navigation_entry.h index 379d3809..4472ba0 100644 --- a/third_party/blink/renderer/core/timing/soft_navigation_entry.h +++ b/third_party/blink/renderer/core/timing/soft_navigation_entry.h
@@ -16,7 +16,8 @@ public: SoftNavigationEntry(AtomicString name, double start_time, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~SoftNavigationEntry() override; const AtomicString& entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/task_attribution_timing.cc b/third_party/blink/renderer/core/timing/task_attribution_timing.cc index 3df4f44..cf46dc7 100644 --- a/third_party/blink/renderer/core/timing/task_attribution_timing.cc +++ b/third_party/blink/renderer/core/timing/task_attribution_timing.cc
@@ -15,8 +15,9 @@ const AtomicString& container_src, const AtomicString& container_id, const AtomicString& container_name, - const uint32_t navigation_id) - : PerformanceEntry(name, 0.0, 0.0, navigation_id), + const uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(name, 0.0, 0.0, navigation_id, source), container_type_(container_type), container_src_(container_src), container_id_(container_id),
diff --git a/third_party/blink/renderer/core/timing/task_attribution_timing.h b/third_party/blink/renderer/core/timing/task_attribution_timing.h index 5795ab9..c1a07ad 100644 --- a/third_party/blink/renderer/core/timing/task_attribution_timing.h +++ b/third_party/blink/renderer/core/timing/task_attribution_timing.h
@@ -31,7 +31,8 @@ const AtomicString& container_src, const AtomicString& container_id, const AtomicString& container_name, - const uint32_t navigation_id); + const uint32_t navigation_id, + DOMWindow* source); ~TaskAttributionTiming() override; private:
diff --git a/third_party/blink/renderer/core/timing/visibility_state_entry.cc b/third_party/blink/renderer/core/timing/visibility_state_entry.cc index 0003027..6722d6d 100644 --- a/third_party/blink/renderer/core/timing/visibility_state_entry.cc +++ b/third_party/blink/renderer/core/timing/visibility_state_entry.cc
@@ -11,8 +11,9 @@ VisibilityStateEntry::VisibilityStateEntry(AtomicString name, double start_time, - uint32_t navigation_id) - : PerformanceEntry(name, start_time, start_time, navigation_id) {} + uint32_t navigation_id, + DOMWindow* source) + : PerformanceEntry(name, start_time, start_time, navigation_id, source) {} VisibilityStateEntry::~VisibilityStateEntry() = default;
diff --git a/third_party/blink/renderer/core/timing/visibility_state_entry.h b/third_party/blink/renderer/core/timing/visibility_state_entry.h index c02cd59..ead3b39 100644 --- a/third_party/blink/renderer/core/timing/visibility_state_entry.h +++ b/third_party/blink/renderer/core/timing/visibility_state_entry.h
@@ -16,7 +16,8 @@ public: VisibilityStateEntry(AtomicString name, double start_time, - uint32_t navigation_id); + uint32_t navigation_id, + DOMWindow* source); ~VisibilityStateEntry() override; const AtomicString& entryType() const override;
diff --git a/third_party/blink/renderer/core/timing/window_performance.cc b/third_party/blink/renderer/core/timing/window_performance.cc index 678a098..30be2b7 100644 --- a/third_party/blink/renderer/core/timing/window_performance.cc +++ b/third_party/blink/renderer/core/timing/window_performance.cc
@@ -422,9 +422,9 @@ MonotonicTimeToDOMHighResTimeStamp(processing_start), MonotonicTimeToDOMHighResTimeStamp(processing_end), event.cancelable(), event.target() ? event.target()->ToNode() : nullptr, - PerformanceEntry::GetNavigationId( - GetExecutionContext())); // TODO(haoliuk): Add WPT for Event Timing. - // See crbug.com/1320878. + PerformanceEntry::GetNavigationId(GetExecutionContext()), + DomWindow()); // TODO(haoliuk): Add WPT for Event Timing. + // See crbug.com/1320878. absl::optional<int> key_code; if (event.IsKeyboardEvent()) key_code = DynamicTo<KeyboardEvent>(event)->keyCode(); @@ -618,7 +618,7 @@ name, url, rect, MonotonicTimeToDOMHighResTimeStamp(start_time), MonotonicTimeToDOMHighResTimeStamp(load_time), identifier, intrinsic_size.width(), intrinsic_size.height(), id, element, - PerformanceEntry::GetNavigationId(GetExecutionContext())); + PerformanceEntry::GetNavigationId(GetExecutionContext()), DomWindow()); TRACE_EVENT2("loading", "PerformanceElementTiming", "data", entry->ToTracedValue(), "frame", ToTraceValue(DomWindow()->GetFrame())); @@ -657,10 +657,10 @@ VisibilityStateEntry* entry = MakeGarbageCollected<VisibilityStateEntry>( PageHiddenStateString(!is_visible), MonotonicTimeToDOMHighResTimeStamp(timestamp), - PerformanceEntry::GetNavigationId( - GetExecutionContext())); // Todo(haoliuk): Add WPT for - // VisibilityStateEntry. See - // crbug.com/1320878. + PerformanceEntry::GetNavigationId(GetExecutionContext()), + DomWindow()); // Todo(haoliuk): Add WPT for + // VisibilityStateEntry. See + // crbug.com/1320878. if (HasObserverFor(PerformanceEntry::kVisibilityState)) NotifyObserversOfEntry(*entry); @@ -676,7 +676,7 @@ } SoftNavigationEntry* entry = MakeGarbageCollected<SoftNavigationEntry>( name, MonotonicTimeToDOMHighResTimeStamp(timestamp), - PerformanceEntry::GetNavigationId(GetExecutionContext())); + PerformanceEntry::GetNavigationId(GetExecutionContext()), DomWindow()); if (HasObserverFor(PerformanceEntry::kSoftNavigation)) { UseCounter::Count(GetExecutionContext(), @@ -721,7 +721,7 @@ auto* entry = MakeGarbageCollected<LargestContentfulPaint>( start_timestamp, render_timestamp, paint_size, load_timestamp, first_animated_frame_timestamp, id, url, element, - PerformanceEntry::GetNavigationId(GetExecutionContext())); + PerformanceEntry::GetNavigationId(GetExecutionContext()), DomWindow()); if (HasObserverFor(PerformanceEntry::kLargestContentfulPaint)) NotifyObserversOfEntry(*entry); AddLargestContentfulPaint(entry);
diff --git a/third_party/blink/renderer/core/timing/window_performance_test.cc b/third_party/blink/renderer/core/timing/window_performance_test.cc index e8dd5813..daafb98 100644 --- a/third_party/blink/renderer/core/timing/window_performance_test.cc +++ b/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -133,8 +133,9 @@ PerformanceEventTiming* CreatePerformanceEventTiming( const AtomicString& name) { - return PerformanceEventTiming::Create(name, 0.0, 0.0, 0.0, false, nullptr, - 1); + return PerformanceEventTiming::Create( + name, 0.0, 0.0, 0.0, false, nullptr, 1, + LocalDOMWindow::From(GetScriptState())); } LocalFrame* GetFrame() const { return &page_holder_->GetFrame(); }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc index 52cdecd..4b50ec0 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -1880,7 +1880,7 @@ // kAuto, then set aria-expanded=false when the popover is hidden, and // aria-expanded=true when it is showing. if (auto* form_control = DynamicTo<HTMLFormControlElement>(element)) { - if (auto popover = form_control->popoverTargetElement().element; + if (auto popover = form_control->popoverTargetElement().popover; popover && popover->PopoverType() == PopoverValueType::kAuto) { return popover->popoverOpen() ? kExpandedExpanded : kExpandedCollapsed; }
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc index 444739e..9b9f292e 100644 --- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc +++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
@@ -151,6 +151,18 @@ const bool gpu_compositing = SharedGpuContext::IsGpuCompositingEnabled(); + if (!gpu_compositing) { + // Readback if needed and retain the readback in image_ to prevent future + // readbacks. + // Note: Switching to unaccelerated may change the value of + // image_->IsOriginTopLeft(), so it is important to make the switch before + // calling IsOriginTopLeft(). + image_ = image_->MakeUnaccelerated(); + if (!image_) { + return false; + } + } + const ImageOrientation origin = image_->IsOriginTopLeft() ? ImageOrientationEnum::kOriginTopLeft : ImageOrientationEnum::kOriginBottomLeft; @@ -204,12 +216,6 @@ std::move(image_for_compositor)); *out_release_callback = std::move(func); } else { - // Readback if needed and retain the readback in image_ to prevent future - // readbacks - image_ = image_->MakeUnaccelerated(); - if (!image_) - return false; - sk_sp<SkImage> sk_image = image_->PaintImageForCurrentFrame().GetSwSkImage(); if (!sk_image)
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc index 0ce1919..6b6aa02 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_error.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_error.cc
@@ -200,8 +200,10 @@ bool ResourceError::IsUnactionableTrustTokensStatus() const { return IsTrustTokenCacheHit() || (error_code_ == net::ERR_TRUST_TOKEN_OPERATION_FAILED && - trust_token_operation_error_ == - network::mojom::TrustTokenOperationStatus::kUnavailable); + (trust_token_operation_error_ == + network::mojom::TrustTokenOperationStatus::kUnavailable || + trust_token_operation_error_ == + network::mojom::TrustTokenOperationStatus::kUnauthorized)); } bool ResourceError::IsCacheMiss() const {
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 0f3495e..31c27f94 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -594,7 +594,7 @@ }, { name: "CrossFramePerformanceTimeline", - status: "test", + status: "experimental", base_feature: "CrossFramePerformanceTimeline", }, {
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.cc b/third_party/blink/renderer/platform/weborigin/kurl.cc index 5f26de2..df63fbe 100644 --- a/third_party/blink/renderer/platform/weborigin/kurl.cc +++ b/third_party/blink/renderer/platform/weborigin/kurl.cc
@@ -223,7 +223,10 @@ return GetString().Left(511) + "..." + GetString().Right(510); } -KURL::KURL() : is_valid_(false), protocol_is_in_http_family_(false) {} +KURL::KURL() + : is_valid_(false), + protocol_is_in_http_family_(false), + has_idna2008_deviation_character_(false) {} // Initializes with a string representing an absolute URL. No encoding // information is specified. This generally happens when a KURL is converted @@ -239,6 +242,7 @@ // empty string, which is what Init() will create. is_valid_ = false; protocol_is_in_http_family_ = false; + has_idna2008_deviation_character_ = false; } } @@ -267,15 +271,21 @@ bool is_valid) : is_valid_(is_valid), protocol_is_in_http_family_(false), + has_idna2008_deviation_character_(false), parsed_(parsed), string_(canonical_string) { InitProtocolMetadata(); InitInnerURL(); + // For URLs with non-ASCII hostnames canonical_string will be in punycode. + // We can't check has_idna2008_deviation_character_ without decoding punycode. + // here. } KURL::KURL(const KURL& other) : is_valid_(other.is_valid_), protocol_is_in_http_family_(other.protocol_is_in_http_family_), + has_idna2008_deviation_character_( + other.has_idna2008_deviation_character_), protocol_(other.protocol_), parsed_(other.parsed_), string_(other.string_) { @@ -288,6 +298,7 @@ KURL& KURL::operator=(const KURL& other) { is_valid_ = other.is_valid_; protocol_is_in_http_family_ = other.protocol_is_in_http_family_; + has_idna2008_deviation_character_ = other.has_idna2008_deviation_character_; protocol_ = other.protocol_; parsed_ = other.parsed_; string_ = other.string_; @@ -322,6 +333,10 @@ return protocol_is_in_http_family_; } +bool KURL::HasIDNA2008DeviationCharacter() const { + return has_idna2008_deviation_character_; +} + bool KURL::HasPath() const { // Note that http://www.google.com/" has a path, the path is "/". This can // return false only for invalid or nonstandard URLs. @@ -912,6 +927,15 @@ InitProtocolMetadata(); InitInnerURL(); DCHECK(!::blink::ProtocolIsJavaScript(string_) || ProtocolIsJavaScript()); + + // Check for deviation characters in the string. See + // https://unicode.org/reports/tr46/#Table_Deviation_Characters + has_idna2008_deviation_character_ = + base.has_idna2008_deviation_character_ || + relative.Contains(u"\u00DF") || // Sharp-s + relative.Contains(u"\u03C2") || // Greek final sigma + relative.Contains(u"\u200D") || // Zero width joiner + relative.Contains(u"\u200C"); // Zero width non-joiner } void KURL::InitInnerURL() {
diff --git a/third_party/blink/renderer/platform/weborigin/kurl.h b/third_party/blink/renderer/platform/weborigin/kurl.h index d33bb3f..479b3b5 100644 --- a/third_party/blink/renderer/platform/weborigin/kurl.h +++ b/third_party/blink/renderer/platform/weborigin/kurl.h
@@ -229,6 +229,8 @@ void WriteIntoTrace(perfetto::TracedValue context) const; + bool HasIDNA2008DeviationCharacter() const; + private: friend struct WTF::HashTraits<blink::KURL>; @@ -253,6 +255,11 @@ bool is_valid_; bool protocol_is_in_http_family_; + // Set to true if any part of the URL string contains an IDNA 2008 deviation + // character. Only used for logging. The hostname is decoded to IDN and + // checked for deviation characters again before logging. + // TODO(crbug.com/1396475): Remove once Non-Transitional mode is shipped. + bool has_idna2008_deviation_character_; // Keep a separate string for the protocol to avoid copious copies for // protocol().
diff --git a/third_party/blink/renderer/platform/weborigin/kurl_test.cc b/third_party/blink/renderer/platform/weborigin/kurl_test.cc index 283f81d..1bcca14 100644 --- a/third_party/blink/renderer/platform/weborigin/kurl_test.cc +++ b/third_party/blink/renderer/platform/weborigin/kurl_test.cc
@@ -1080,6 +1080,30 @@ EXPECT_EQ(gurl.host_piece(), "%25t%EF%BF%BD"); } +TEST(KURLTest, HasIDNA2008DeviationCharacters) { + // èxample.com: + EXPECT_FALSE( + KURL("http://\xE8xample.com/path").HasIDNA2008DeviationCharacter()); + // faß.de (contains Sharp-S): + EXPECT_TRUE(KURL(u"http://fa\u00df.de/path").HasIDNA2008DeviationCharacter()); + // βόλος.com (contains Greek Final Sigma): + EXPECT_TRUE(KURL(u"http://\u03b2\u03cc\u03bb\u03bf\u03c2.com/path") + .HasIDNA2008DeviationCharacter()); + // ශ්රී.com (contains Zero Width Joiner): + EXPECT_TRUE(KURL(u"http://\u0DC1\u0DCA\u200D\u0DBB\u0DD3.com") + .HasIDNA2008DeviationCharacter()); + // http://نامه\u200cای.com (contains Zero Width Non-Joiner): + EXPECT_TRUE(KURL(u"http://\u0646\u0627\u0645\u0647\u200C\u0627\u06CC.com") + .HasIDNA2008DeviationCharacter()); + + // Copying the URL from a canonical string presently doesn't copy the boolean. + KURL url1(u"http://\u03b2\u03cc\u03bb\u03bf\u03c2.com/path"); + std::string url_string = url1.GetString().Utf8(); + KURL url2(AtomicString::FromUTF8(url_string.data(), url_string.length()), + url1.GetParsed(), url1.IsValid()); + EXPECT_FALSE(url2.HasIDNA2008DeviationCharacter()); +} + enum class PortIsValid { // The constructor does strict checking. Ports which are considered valid by // the constructor are kAlways valid.
diff --git a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py index 8d05024..f2454aa 100755 --- a/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py +++ b/third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
@@ -1764,6 +1764,14 @@ }, { 'paths': [ + 'third_party/blink/renderer/core/loader/frame_loader.cc', + ], + 'allowed': [ + 'base::flat_map', + ] + }, + { + 'paths': [ 'third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc', ], 'allowed': [
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index ee96ab99..731b115 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2337,9 +2337,27 @@ crbug.com/876485 fast/performance/performance-measure-null-exception.html [ Failure ] -# Unprefixed image-set() not supported -crbug.com/630597 external/wpt/css/css-images/image-set/image-set-rendering.html [ Failure ] -crbug.com/630597 external/wpt/css/css-images/image-set/image-set-content-rendering.html [ Failure ] +# image-set() does not yet support default resolution +crbug.com/1400898 external/wpt/css/css-images/image-set/image-set-no-res-rendering.html [ Failure ] + +# image-set() does not yet support URLs without the url function notation +crbug.com/1400901 external/wpt/css/css-images/image-set/image-set-no-url-rendering.html [ Failure ] + +# image-set() does not yet support gradient images +crbug.com/1400902 external/wpt/css/css-images/image-set/image-set-linear-gradient-rendering.html [ Failure ] +crbug.com/1400902 external/wpt/css/css-images/image-set/image-set-radial-gradient-rendering.html [ Failure ] + +# image-set() does not yet support all resolution units +crbug.com/1400903 external/wpt/css/css-images/image-set/image-set-dppx-rendering.html [ Failure ] +crbug.com/1400903 external/wpt/css/css-images/image-set/image-set-dpi-rendering.html [ Failure ] +crbug.com/1400903 external/wpt/css/css-images/image-set/image-set-dpi-rendering-2.html [ Failure ] + +# image-set() type function not yet supported +crbug.com/1399341 external/wpt/css/css-images/image-set/image-set-type-rendering.html [ Failure ] +crbug.com/1399341 external/wpt/css/css-images/image-set/image-set-type-rendering-2.html [ Failure ] +crbug.com/1399341 external/wpt/css/css-images/image-set/image-set-type-rendering-3.html [ Failure ] +crbug.com/1399341 external/wpt/css/css-images/image-set/image-set-type-first-match-rendering.html [ Failure ] +crbug.com/1399341 external/wpt/css/css-images/image-set/image-set-type-skip-unsupported-rendering.html [ Failure ] # CSS Color 4 interpolations crbug.com/1362022 external/wpt/css/css-images/gradient/gradient-eval-004.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-auto-state-changed-first-observation.html b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-auto-state-changed-first-observation.html new file mode 100644 index 0000000..1c51851 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/content-visibility/content-visibility-auto-state-changed-first-observation.html
@@ -0,0 +1,65 @@ +<!doctype HTML> +<html> +<meta charset="utf8"> +<title>Content Visibility: ContentVisibilityAutoStateChange event.</title> +<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-contain/#content-visibility"> +<meta name="assert" content="ContentVisibilityAutoStateChange fires once when element is inserted"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<style> +.spacer { + height: 10000px; +} +</style> + +<div id=topdiv></div> +<div class=spacer></div> +<div id=bottomdiv></div> + +<script> +promise_test(t => new Promise(async (resolve, reject) => { + await new Promise((waited, _) => { + requestAnimationFrame(() => requestAnimationFrame(waited)); + }); + + let observed = false; + let div = document.createElement("div"); + div.addEventListener("contentvisibilityautostatechange", (e) => { + if (observed) + reject("already observed"); + if (e.skipped) + reject("unexpected skipped"); + observed = true; + // Wait a couple of frames to ensure no other signal comes in + requestAnimationFrame(() => requestAnimationFrame(resolve)); + }); + + div.style.contentVisibility = "auto"; + topdiv.appendChild(div); +}), "ContentVisibilityAutoStateChange fires once when added (not skipped)"); + +promise_test(t => new Promise(async (resolve, reject) => { + await new Promise((waited, _) => { + requestAnimationFrame(() => requestAnimationFrame(waited)); + }); + + let observed = false; + let div = document.createElement("div"); + div.addEventListener("contentvisibilityautostatechange", (e) => { + if (observed) + reject("already observed"); + if (!e.skipped) + reject("unexpected not skipped"); + observed = true; + // Wait a couple of frames to ensure no other signal comes in + requestAnimationFrame(() => requestAnimationFrame(resolve)); + }); + + div.style.contentVisibility = "auto"; + bottomdiv.appendChild(div); +}), "ContentVisibilityAutoStateChange fires once when added (skipped)"); +</script> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering-ref.html deleted file mode 100644 index 29316bc1..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering-ref.html +++ /dev/null
@@ -1,11 +0,0 @@ -<!doctype html> -<title>CSS Test Reference</title> -<style> - .test { - display: inline-block; - width: 100px; - height: 100px; - background: red; - } -</style> -<div class="test" style="content: url('/images/green.png')" ></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html index 9110837..f0622a89 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html
@@ -1,16 +1,15 @@ -<!doctype html> +<!DOCTYPE html> <title>Image set is supported in the content property</title> <link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> <link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> <link rel="help" href="https://drafts.csswg.org/css-content/#content-property"> -<link rel="match" href="image-set-content-rendering-ref.html"> +<link rel="match" href="reference/image-set-content-rendering-ref.html"> +<meta name="assert" content="image-set content rendering"> +<script src="resources/image-set-rendering-helper.js"></script> <style> - .test { - display: inline-block; - width: 100px; - height: 100px; - background: red; + #test { + content: image-set(url("/images/green.png") 1x); } </style> -<div class="test" style="content: image-set(url() 2x, url('/images/green.png') 100dpi)" ></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html.ini b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html.ini deleted file mode 100644 index f223f93..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-content-rendering.html.ini +++ /dev/null
@@ -1,2 +0,0 @@ -[image-set-content-rendering.html] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dpi-rendering-2.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dpi-rendering-2.html new file mode 100644 index 0000000..d7bd02e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dpi-rendering-2.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set dpi rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set dpi rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/green.png") 96dpi, + url("/images/red.png") 100dpi + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dpi-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dpi-rendering.html new file mode 100644 index 0000000..be18e85f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dpi-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set dpi rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set dpi rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(url("/images/green.png") 96dpi); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dppx-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dppx-rendering.html new file mode 100644 index 0000000..1fc2f8c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-dppx-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set dppx rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set dppx rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(url("/images/green.png") 1dppx); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-empty-url-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-empty-url-rendering.html new file mode 100644 index 0000000..0286d737 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-empty-url-rendering.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set empty url rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering when 2x url is empty"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/green.png") 1x, + url("") 2x + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-first-match-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-first-match-rendering.html new file mode 100644 index 0000000..4d5b9d7d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-first-match-rendering.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set type first match rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering picks first valid match"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/green.png") 1x, + url("/images/red.png") 1x + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering-2.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering-2.html new file mode 100644 index 0000000..88917e1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering-2.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<title>Image set invalid resolution rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering when resolution is invalid"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: url("/images/green.png"); + background-image: image-set( + url("/images/red.png") 0x, + url("/images/red.png") 2x + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering.html new file mode 100644 index 0000000..0cdcf601 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-invalid-resolution-rendering.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<title>Image set invalid resolution rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering when resolution is invalid"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: url("/images/green.png"); + background-image: image-set(url("/images/red.png") 0x); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-linear-gradient-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-linear-gradient-rendering.html new file mode 100644 index 0000000..62f41a74 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-linear-gradient-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set linear-gradient rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-linear-gradient-rendering-ref.html"> +<meta name="assert" content="image-set linear-gradient rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(linear-gradient(green, lightgreen) 1x); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-no-res-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-no-res-rendering.html new file mode 100644 index 0000000..927d4c67 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-no-res-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set no resolution rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with no resolution defined"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(url("/images/green.png")); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-no-url-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-no-url-rendering.html new file mode 100644 index 0000000..7af722d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-no-url-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set no url rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set without url functional notation rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set("/images/green.png" 1x); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-radial-gradient-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-radial-gradient-rendering.html new file mode 100644 index 0000000..7bf950a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-radial-gradient-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set radial-gradient rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-radial-gradient-rendering-ref.html"> +<meta name="assert" content="image-set radial-gradient rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(radial-gradient(green, lightgreen) 1x); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering-2.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering-2.html new file mode 100644 index 0000000..a672455 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering-2.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/green.png") 1x, + url("/images/red.png") 2x + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering-ref.html deleted file mode 100644 index 081766c..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering-ref.html +++ /dev/null
@@ -1,44 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <title>Image set rendering</title> - <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> - <link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> - <meta name="assert" content="image-set rendering"> - <style> - .test { - display: inline-block; - width: 100px; - height: 100px; - } - - main { - width: 500px; - } - </style> - </head> - <body> - <p>All images below should be lime or a lime-green gradient when devicePixelRatio is 1 - no red!.</p> - <main> - <div class="test" style="background-image: url(/images/green.png)"></div> - <div class="test" style="background-image: linear-gradient(green, lightgreen)"></div> - <div class="test" style="background-image: url('/images/green.png')" ></div> - <div class="test" style="background-image: radial-gradient(green, lightgreen)" ></div> - <div class="test" style="background-image: linear-gradient(green, lightgreen)" ></div> - <div class="test" style="background-image: url('/images/green.png')" ></div> - <div class="test" style="background-image: url('/images/green.png')" ></div> - <div class="test" style="background-image: url('/images/green.png')" ></div> - <div class="test" style="background-image: url('/images/green.png')"></div> - <div class="test" style="background-color: lime"></div> - <div class="test" style="background-color: lime"></div> - <div class="test" style="background-color: lime"></div> - <div class="test" style="background-image: url(/images/green.png)"></div> - <div class="test" style="background-image: url(/images/green.png)"></div> - <div class="test" style="background-image: url(/images/green.png)"></div> - <div class="test" style="background-image: url(/images/red.png)"></div> - <div class="test" style="background-image: url(/images/green.png)"></div> - <div class="test" style="background-image: url(/images/red.png)"></div> - <div class="test" style="background-image: url(/images/green.png)"></div> - </main> - </body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html index eb3ece96..ce4a900 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html
@@ -1,46 +1,13 @@ <!DOCTYPE html> -<html> - <head> - <title>Image set rendering</title> - <link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> - <link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> - <meta name="assert" content="image-set rendering"> - <link rel="match" href="image-set-rendering-ref.html"> - <style> - .test { - display: inline-block; - width: 100px; - height: 100px; - background: red; - } - - main { - width: 500px; - } - </style> - </head> - <body> - <p>All images below should be lime or a lime-green gradient when devicePixelRatio is 1 - no red!.</p> - <main> - <div class="test" style="background-image: image-set('/images/green.png' 1x)"></div> - <div class="test" style="background-image: image-set('/images/red.png' 20dpi, linear-gradient(green, lightgreen) 2x)"></div> - <div class="test" style="background-image: image-set(url('/images/green.png') 1x, url('/images/red.png') 2x)" ></div> - <div class="test" style="background-image: image-set(radial-gradient(green, lightgreen) 1x, linear-gradient(yellow, red) 2x)" ></div> - <div class="test" style="background-image: image-set(linear-gradient(green, lightgreen) 96dpi, '/images/red.png' 100dpi)" ></div> - <div class="test" style="background-image: image-set(radial-gradient(red, yellow) 1.3x, url('/images/green.png') 100dpi, linear-gradient(red, yellow) 2.5x)" ></div> - <div class="test" style="background-image: image-set('/images/red.png' 2x, url('/images/green.png') 1x, url('/images/yellow.png') 300dpi)" ></div> - <div class="test" style="background-color: red; background-image: image-set('' 2x, url('/images/green.png') 1x)" ></div> - <div class="test" style="background-image: image-set('/images/green.png' 1x)"></div> - <div class="test" style="background-color: red; background-image: image-set('/images/green.png')" ></div> - <div class="test" style="background-color: lime; background-image: image-set('/images/red.png' 0x)" ></div> - <div class="test" style="background-color: lime; background-image: image-set('/images/red.png' 0x, url('/images/red.png') 2x)" ></div> - <div class="test" style="background-image: image-set('/images/green.png' type('image/png') 1x)"></div> - <div class="test" style="background-image: image-set('/images/green.png' 1x type('image/png'))"></div> - <div class="test" style="background-image: image-set('/images/green.png' type('image/png'))"></div> - <div class="test" style="background-image: image-set('/images/red.png' type('image/png'), '/images/green.png' type('image/png'))"></div> - <div class="test" style="background-image: image-set('/images/red.png' type('image/unsupported'), '/images/green.png' type('image/png'))"></div> - <div class="test" style="background-image: image-set('/images/red.png' type('image/unsupported'), '/images/green.png' type('image/unsupported'))"></div> - <div class="test" style="background-image: image-set('/images/red.png' 2x type('image/png'), '/images/green.png' 1x type('image/png'))"></div> - </main> - </body> -</html> +<title>Image set rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(url("/images/green.png") 1x); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html.ini b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html.ini deleted file mode 100644 index cac31096..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-rendering.html.ini +++ /dev/null
@@ -1,2 +0,0 @@ -[image-set-rendering.html] - expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-first-match-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-first-match-rendering.html new file mode 100644 index 0000000..1283d22 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-first-match-rendering.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set type first match rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with type picks first valid match"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/green.png") 1x type('image/png'), + url("/images/red.png") 1x type('image/png') + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering-2.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering-2.html new file mode 100644 index 0000000..897118ac --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering-2.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set type rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering for images with same type but different resolutions"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/green.png") type('image/png') 1x, + url("/images/red.png") type('image/png') 2x + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering-3.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering-3.html new file mode 100644 index 0000000..51dbe2c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering-3.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set type rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with type before resolution"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(url("/images/green.png") type('image/png') 1x); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering.html new file mode 100644 index 0000000..16055db --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-rendering.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<title>Image set type rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with type"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set(url("/images/green.png") 1x type('image/png')); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-skip-unsupported-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-skip-unsupported-rendering.html new file mode 100644 index 0000000..e555633c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-skip-unsupported-rendering.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set type skip unsupported rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with type skips unsupported type"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/red.png") 1x type('image/unsupported'), + url("/images/green.png") 1x type('image/png') + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-unsupported-rendering-2.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-unsupported-rendering-2.html new file mode 100644 index 0000000..3f9fcd2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-unsupported-rendering-2.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<title>Image set type rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with all unsupported types"> +<!-- +Spec definition: +"An image-set() function contains a list of one or more <image-set-option>s, + and must select only one of them to determine what image it will represent: + First, remove any <image-set-option>s from the list that specify + an unknown or unsupported MIME type in their type() value." + +If all the values in the image set are of an unsupported type, +the set should be empty. +--> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: url("/images/green.png"); + background-image: image-set( + url("/images/red.png") 1x type('image/unsupported'), + url("/images/red.png") 1x type('image/unsupported') + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-unsupported-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-unsupported-rendering.html new file mode 100644 index 0000000..6e9e56a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-type-unsupported-rendering.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<title>Image set type rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering with unsupported type"> +<!-- +Spec definition: +"An image-set() function contains a list of one or more <image-set-option>s, + and must select only one of them to determine what image it will represent: + First, remove any <image-set-option>s from the list that specify + an unknown or unsupported MIME type in their type() value." + +If all the values in the image set are of an unsupported type, +the set should be empty. +--> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: url("/images/green.png"); + background-image: image-set(url("/images/red.png") 1x type('image/unsupported')); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-unordered-res-rendering.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-unordered-res-rendering.html new file mode 100644 index 0000000..c1063b7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/image-set-unordered-res-rendering.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Image set type unordered resolutions rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<link rel="help" href="https://drafts.csswg.org/css-images-4/#image-set-notation"> +<link rel="match" href="reference/image-set-rendering-ref.html"> +<meta name="assert" content="image-set rendering when resolutions are unordered"> +<script src="resources/image-set-rendering-helper.js"></script> +<style> + #test { + background-image: image-set( + url("/images/red.png") 2x, + url("/images/green.png") 1x + ); + } +</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-content-rendering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-content-rendering-ref.html new file mode 100644 index 0000000..c1ef6d4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-content-rendering-ref.html
@@ -0,0 +1,11 @@ +<!DOCTYPE html> +<title>Image set is supported in the content property</title> +<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io"> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<style> + #test { + content: url("/images/green.png"); + } +</style> +<script src="../resources/image-set-rendering-helper.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-linear-gradient-rendering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-linear-gradient-rendering-ref.html new file mode 100644 index 0000000..272bab9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-linear-gradient-rendering-ref.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Image set linear-gradient rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<style> + #test { + background-image: linear-gradient(green, lightgreen); + } +</style> +<script src="../resources/image-set-rendering-helper.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-radial-gradient-rendering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-radial-gradient-rendering-ref.html new file mode 100644 index 0000000..f5545af --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-radial-gradient-rendering-ref.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Image set radial-gradient rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<style> + #test { + background-image: radial-gradient(green, lightgreen); + } +</style> +<script src="../resources/image-set-rendering-helper.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-rendering-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-rendering-ref.html new file mode 100644 index 0000000..2ca6b33 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/reference/image-set-rendering-ref.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Image set rendering</title> +<link rel="author" title="Noam Rosenthal" href="mailto:noam@webkit.org"> +<link rel="author" title="Traian Captan" href="mailto:tcaptan@chromium.org"> +<style> + #test { + background-image: url("/images/green.png"); + } +</style> +<script src="../resources/image-set-rendering-helper.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/image-set/resources/image-set-rendering-helper.js b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/resources/image-set-rendering-helper.js new file mode 100644 index 0000000..7dbd50a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-images/image-set/resources/image-set-rendering-helper.js
@@ -0,0 +1,27 @@ +function setupTest() { + createPassingNotice(); + createTestDiv(); +} + +function createPassingNotice() { + const notice = document.createElement('p'); + + notice.textContent = + 'Test passes if the image below is green when devicePixelRatio is 1, not red.'; + + document.body.appendChild(notice); +} + +function createTestDiv() { + const testDiv = document.createElement('div'); + + testDiv.id = 'test'; + + testDiv.style.width = '100px'; + testDiv.style.height = '100px'; + testDiv.style.backgroundColor = 'red'; + + document.body.appendChild(testDiv); +} + +window.onload = setupTest;
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html index bdd0d12..83573c86 100644 --- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html +++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-light-dismiss.tentative.html
@@ -242,13 +242,9 @@ popover1.showPopover(); assert_true(popover1.matches(':open')); await waitForRender(); - p1HideCount = popover1HideCount; await clickOn(popover1anchor); - assert_true(popover1.matches(':open'),'popover1 not open'); - assert_equals(popover1HideCount,p1HideCount); - popover1.hidePopover(); // Cleanup - assert_false(popover1.matches(':open')); - },'Clicking on anchor element (that isn\'t an invoking element) shouldn\'t close its popover'); + assert_false(popover1.matches(':open'),'popover1 should close'); + },'Clicking on anchor element (that isn\'t an invoking element) shouldn\'t prevent its popover from being closed'); promise_test(async () => { popover1.showPopover(); @@ -273,9 +269,9 @@ <div popover id=p4>Inside popover 4</div> </button> <div popover id=p3>Inside popover 3</div> -<button id=b4 popovertoggletarget=p3>Popover 3 - button 4 - <div popover id=p5>Inside popover 5</div> -</button> +<div popover id=p5>Inside popover 5 + <button popovertoggletarget=p3>Popover 3 - button 4 - unused</button> +</div> <style> #p3 {top:100px;} #p4 {top:200px;} @@ -291,24 +287,20 @@ assert_true(popover3.matches(':open'),'invoking element should open popover'); popover4.showPopover(); assert_true(popover4.matches(':open')); - assert_true(popover3.matches(':open')); - popover3.hidePopover(); // Cleanup - assert_false(popover3.matches(':open')); + assert_false(popover3.matches(':open'),'popover3 is unrelated to popover4'); + popover4.hidePopover(); // Cleanup assert_false(popover4.matches(':open')); - },'An invoking element should be part of the ancestor chain'); + },'A popover inside an invoking element doesn\'t participate in that invoker\'s ancestor chain'); promise_test(async () => { - await clickOn(button3); - assert_true(popover3.matches(':open')); - assert_false(popover4.matches(':open')); - assert_false(popover5.matches(':open')); popover5.showPopover(); - assert_true(popover3.matches(':open')); - assert_false(popover4.matches(':open')); assert_true(popover5.matches(':open')); - popover3.hidePopover(); assert_false(popover3.matches(':open')); - assert_false(popover4.matches(':open')); + popover3.showPopover(); + assert_true(popover3.matches(':open')); + assert_true(popover5.matches(':open')); + popover5.hidePopover(); + assert_false(popover3.matches(':open')); assert_false(popover5.matches(':open')); },'An invoking element that was not used to invoke the popover can still be part of the ancestor chain'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/performance-entry-source.html b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/performance-entry-source.html new file mode 100644 index 0000000..5e51ddb --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/performance-timeline/tentative/performance-entry-source.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<head> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +</head> +<body> +</body> +<script> +promise_test(() => { + return new Promise(resolve => { + const navigationEntries = performance.getEntriesByType("navigation") + const parentEntry = navigationEntries[0] + + // Parent NavigationTiming source is current window. + assert_equals(parentEntry.source, window) + + // Create child iframe. + const childFrame = document.createElement('iframe') + childFrame.src = "../resources/child-frame.html" + document.body.appendChild(childFrame) + + childFrame.addEventListener('load', () => { + const markedEntries = performance.getEntriesByName("entry-name", undefined, true) + const childEntry = markedEntries[0] + + // Child PerformanceMark source is the child's Window. + assert_equals(childEntry.source, childFrame.contentWindow) + + resolve() + }) + }) +}, "PerformanceEntry source is equal to its respective Window") +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-expected.txt b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-expected.txt new file mode 100644 index 0000000..b96e97a --- /dev/null +++ b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-expected.txt
@@ -0,0 +1,9 @@ +CONSOLE WARNING: The resource at http://faß.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (faß.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://βόλος.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (βόλος.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://ශ්රී.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (ශ්රී.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://نامهای.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (نامهای.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://faß.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (faß.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://βόλος.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (βόλος.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://ශ්රී.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (ශ්රී.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://نامهای.test/image.jpg contains IDNA Deviation Characters. The hostname for this URL (نامهای.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. + t
diff --git a/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-iframe-expected.txt b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-iframe-expected.txt new file mode 100644 index 0000000..85e1ec21 --- /dev/null +++ b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-iframe-expected.txt
@@ -0,0 +1,5 @@ +CONSOLE WARNING: The resource at http://faß.test/ contains IDNA Deviation Characters. The hostname for this URL (faß.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://βόλος.test/ contains IDNA Deviation Characters. The hostname for this URL (βόλος.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://ශ්රී.test/ contains IDNA Deviation Characters. The hostname for this URL (ශ්රී.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +CONSOLE WARNING: The resource at http://نامهای.test/ contains IDNA Deviation Characters. The hostname for this URL (نامهای.test) might point to a different IP address after https://chromestatus.com/feature/5105856067141632. Make sure you are using the correct host name. +
diff --git a/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-iframe.html b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-iframe.html new file mode 100644 index 0000000..57216ae --- /dev/null +++ b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname-iframe.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> +<script> +if (window.testRunner) + testRunner.dumpAsText(); +</script> +</head> +<body> +<!-- Frame with a non-ASCII hostname --> +<iframe src="http://èxample.test/"></iframe> + +<!-- Frame with a hostname containing IDNA 2008 deviation character (Sharp-s) --> +<iframe src="http://faß.test"></iframe> + +<!-- Frame with a hostname containing IDNA 2008 deviation character (Greek Final Sigma). --> +<iframe src="http://βόλος.test"></iframe> + +<!-- Frame with a hostname containing IDNA 2008 deviation character (Zero Width Joiner) --> +<iframe src="http://ශ්රී.test"></iframe> + +<!-- Frame with a hostname containing IDNA 2008 deviation character (Zero Width Non-Joiner) --> +<iframe src="http://نامهای.test"></iframe> + +</body> +</html> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname.html b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname.html new file mode 100644 index 0000000..771cb48 --- /dev/null +++ b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-hostname.html
@@ -0,0 +1,26 @@ +<!DOCTYPE html> +<html> +<head> +<script> +if (window.testRunner) + testRunner.dumpAsText(); +</script> +</head> +<body> +<!-- Image with a non-ASCII hostname --> +<img src="http://èxample.test/image.jpg"> + +<!-- Image with a hostname containing IDNA 2008 deviation character (Sharp-s) --> +<img src="http://faß.test/image.jpg"> + +<!-- Image with a hostname containing IDNA 2008 deviation character (Greek Final Sigma). --> +<img src="http://βόλος.test/image.jpg"> + +<!-- Image with a hostname containing IDNA 2008 deviation character (Zero Width Joiner) --> +<img src="http://ශ්රී.test/image.jpg"> + +<!-- Image with a hostname containing IDNA 2008 deviation character (Zero Width Non-Joiner) --> +<img src="http://نامهای.test/image.jpg"> + +</body> +</html>t \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-path-expected.txt b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-path-expected.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-path-expected.txt
@@ -0,0 +1 @@ +
diff --git a/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-path.html b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-path.html new file mode 100644 index 0000000..25467e39 --- /dev/null +++ b/third_party/blink/web_tests/fast/loader/resource-with-idna-deviation-char-in-path.html
@@ -0,0 +1,13 @@ +<!DOCTYPE html> +<html> +<head> +<script> +if (window.testRunner) + testRunner.dumpAsText(); +</script> +</head> +<body> +<!-- An image containing IDNA 2008 deviation character in the path. --> +<img src="http://example.test/faß.jpg"> +</body> +</html>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 7858e2ca..3cbd744 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6616,6 +6616,7 @@ getter entryType getter name getter navigationId + getter source getter startTime method constructor method toJSON
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 0e3c9d21..3f9cb80 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -443,6 +443,7 @@ 'linux-perfetto-rel': 'perfetto_release_bot_reclient', 'linux-rel-no-external-ip': 'gpu_tests_release_bot_do_typecheck_reclient', 'linux-upload-perfetto': 'release_bot_perfetto_zlib_reclient', + 'linux-wpt-content-shell-asan-fyi-rel': 'asan_lsan_release_trybot_reclient', 'linux-wpt-content-shell-fyi-rel': 'release_trybot_minimal_symbols_reclient', 'linux-wpt-fyi-rel': 'release_trybot_minimal_symbols_reclient', 'linux-wpt-identity-fyi-rel': 'release_bot_minimal_symbols_reclient',
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json index 50b79bee..6b4bc5e 100644 --- a/tools/mb/mb_config_expectations/chromium.fyi.json +++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -1298,6 +1298,17 @@ "use_remoteexec": true } }, + "linux-wpt-content-shell-asan-fyi-rel": { + "gn_args": { + "dcheck_always_on": true, + "is_asan": true, + "is_component_build": false, + "is_debug": false, + "is_lsan": true, + "symbol_level": 1, + "use_remoteexec": true + } + }, "linux-wpt-content-shell-fyi-rel": { "gn_args": { "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 133531b..750aab7 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -5178,6 +5178,15 @@ <int value="14" label="kBloom"/> </enum> +<enum name="AssistantServiceState"> + <int value="0" label="kStopped"/> + <int value="1" label="kStarting"/> + <int value="2" label="kStarted"/> + <int value="3" label="kRunning"/> + <int value="4" label="kStopping"/> + <int value="5" label="kDisconnected"/> +</enum> + <enum name="AsyncDNSConfigParsePosix"> <obsolete> Removed 2021-01. @@ -18026,7 +18035,8 @@ <int value="38" label="HTTP/3 (draft-29)"/> <int value="39" label="HTTP/3 (T051)"/> <int value="40" label="QUIC (RFC)"/> - <int value="41" label="QUICv2 (draft-01)"/> + <int value="41" label="QUICv2 draft-01 (deprecated)"/> + <int value="42" label="QUICv2 draft-08"/> </enum> <enum name="ConnectionResult"> @@ -41655,6 +41665,8 @@ <int value="4424" label="DialogCloseWatcherCloseSignalClosedMultiple"/> <int value="4425" label="NoVarySearch"/> <int value="4426" label="FedCmUserInfo"/> + <int value="4427" label="IDNA2008DeviationCharacterInHostnameOfSubresource"/> + <int value="4428" label="IDNA2008DeviationCharacterInHostnameOfIFrame"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -57264,6 +57276,8 @@ <int value="-2008272679" label="disable-webrtc-hw-encoding"/> <int value="-2007947679" label="OmniboxMostVisitedTilesOnSrp:disabled"/> <int value="-2007377632" label="DiscoverFeedMultiColumn:enabled"/> + <int value="-2006505465" + label="AutofillRemoveCardExpirationAndTypeTitles:disabled"/> <int value="-2005089558" label="BackgroundVideoTrackOptimization:disabled"/> <int value="-2004882388" label="AutofillPruneSuggestions:enabled"/> <int value="-2004862295" label="FedCmUserInfo:disabled"/> @@ -57646,6 +57660,7 @@ <int value="-1802559277" label="RunTasksByBatches:disabled"/> <int value="-1802502753" label="enable-manual-password-generation:enabled"/> <int value="-1801515363" label="ThreadedPreloadScanner:enabled"/> + <int value="-1801349476" label="FloatWindow:enabled"/> <int value="-1799801575" label="CookieDeprecationMessages:enabled"/> <int value="-1798337879" label="enable-md-downloads"/> <int value="-1798258607" label="AdaptiveCharging:disabled"/> @@ -58325,7 +58340,6 @@ <int value="-1408288176" label="enable-account-consistency"/> <int value="-1407904527" label="OmniboxRemoveSuggestionHeaderCapitalization:disabled"/> - <int value="-1407568904" label="CrOSLabsFloatWindow:enabled"/> <int value="-1405349891" label="PictureInPictureAPI:enabled"/> <int value="-1405048637" label="OfflinePagesResourceBasedSnapshot:enabled"/> <int value="-1404469375" label="RemoteCopyProgressNotification:enabled"/> @@ -62240,6 +62254,7 @@ <int value="879992337" label="disable-pull-to-refresh-effect"/> <int value="880201245" label="NewTabPageTilesTitleWrapAround:disabled"/> <int value="880510010" label="enable-permissions-bubbles"/> + <int value="882103442" label="FloatWindow:disabled"/> <int value="882893584" label="UseOfHashAffiliationFetcher:disabled"/> <int value="883190338" label="PrintWithReducedRasterization:disabled"/> <int value="884106779" label="supervised-user-safesites"/> @@ -63860,6 +63875,8 @@ <int value="1841051176" label="WindowsScrollingPersonality:disabled"/> <int value="1841793150" label="TwoPanesStartSurfaceAndroid:enabled"/> <int value="1841976850" label="FeedLoadingPlaceholder:enabled"/> + <int value="1841993231" + label="AutofillRemoveCardExpirationAndTypeTitles:enabled"/> <int value="1842219851" label="enable-incognito-window-counter"/> <int value="1843088575" label="OutOfBlinkCors:enabled"/> <int value="1843847665" label="SyncPromoAfterSigninIntercept:disabled"/> @@ -64161,7 +64178,6 @@ label="ContextualSuggestionsAlternateCardLayout:enabled"/> <int value="2006856618" label="BiometricTouchToFill:enabled"/> <int value="2007421572" label="EapGtcWifiAuthentication:disabled"/> - <int value="2007638959" label="CrOSLabsFloatWindow:disabled"/> <int value="2008599705" label="EnableFeedbackPanel:enabled"/> <int value="2008878342" label="TouchToFillAndroid:disabled"/> <int value="2009097351" label="memlog-sampling-rate"/> @@ -89988,6 +90004,18 @@ <int value="2" label="Media app opened"/> </enum> +<enum name="ScanFailureProgress"> + <summary> + Shows which function caused a failure while scanning. These functions + correspond to function found in chromos's lorgnette.c + </summary> + <int value="1" label="StartScan"/> + <int value="2" label="GetScanCapabilities"/> + <int value="3" label="ConnectToDevice"/> + <int value="4" label="ScanLoop"/> + <int value="5" label="ListScanners"/> +</enum> + <enum name="ScanJobFailureReason"> <int value="0" label="Unknown scanner error"/> <int value="1" label="Scanner not found"/>
diff --git a/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS b/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS index 1f33dca..3745273 100644 --- a/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS +++ b/tools/metrics/histograms/metadata/METRIC_REVIEWER_OWNERS
@@ -9,6 +9,7 @@ ckitagawa@chromium.org sinansahin@google.com mvanouwerkerk@chromium.org +jinsukkim@chromium.org # apps nancylingwang@chromium.org tby@chromium.org
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml index faab4f5..6f33a81 100644 --- a/tools/metrics/histograms/metadata/arc/histograms.xml +++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -2014,7 +2014,7 @@ </histogram> <histogram name="Arc.Session.HasWebViewUsage" enum="Boolean" - expires_after="2022-12-20"> + expires_after="2023-02-01"> <owner>hungmn@google.com</owner> <owner>khmel@google.com</owner> <owner>arc-performance@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/assistant/histograms.xml b/tools/metrics/histograms/metadata/assistant/histograms.xml index 88cc8d6..b3a8746 100644 --- a/tools/metrics/histograms/metadata/assistant/histograms.xml +++ b/tools/metrics/histograms/metadata/assistant/histograms.xml
@@ -218,7 +218,7 @@ <summary>Amount of time spent in starting Assistant service.</summary> </histogram> -<histogram name="Assistant.ServiceState" enum="State" +<histogram name="Assistant.ServiceState" enum="AssistantServiceState" expires_after="2023-10-31"> <owner>wutao@chromium.org</owner> <owner>assistive-eng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml index d6eed612..d1cbd14 100644 --- a/tools/metrics/histograms/metadata/extensions/histograms.xml +++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -3078,6 +3078,9 @@ <histogram name="Extensions.UninstallBookmarkApp" enum="Boolean" expires_after="2022-12-01"> + <obsolete> + Obsolete in M110. + </obsolete> <owner>phillis@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml index 73444793..10a25036 100644 --- a/tools/metrics/histograms/metadata/network/histograms.xml +++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -1478,7 +1478,8 @@ <owner>cros-network-health@google.com</owner> <summary> Captive portal time from a portal-suspected state to an online state on - ChromeOS. + ChromeOS. NOTE: Prior to M110 this used a range that was too small so those + results are invalid. </summary> </histogram> @@ -1573,7 +1574,8 @@ <owner>cros-network-health@google.com</owner> <summary> Captive portal time from a redirect-found state to an online state on - ChromeOS. + ChromeOS. NOTE: Prior to M110 this used a range that was too small so those + results are invalid. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml index 8101c5f..9adffd9 100644 --- a/tools/metrics/histograms/metadata/optimization/histograms.xml +++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -1275,6 +1275,30 @@ </histogram> <histogram + name="OptimizationGuide.PredictionModelStore.ModelCount.{OptimizationTarget}" + units="counts" expires_after="M112"> + <owner>sophiechang@chromium.org</owner> + <owner>rajendrant@chromium.org</owner> + <summary> + The total number of model directories in the prediction model store for + {OptimizationTarget}. Recorded once at startup. + </summary> + <token key="OptimizationTarget" variants="OptimizationTarget"/> +</histogram> + +<histogram + name="OptimizationGuide.PredictionModelStore.TotalDirectorySize.{OptimizationTarget}" + units="MB" expires_after="M112"> + <owner>sophiechang@chromium.org</owner> + <owner>rajendrant@chromium.org</owner> + <summary> + The total disk usage of the prediction model store attributed to + {OptimizationTarget}. Recorded once at startup. + </summary> + <token key="OptimizationTarget" variants="OptimizationTarget"/> +</histogram> + +<histogram name="OptimizationGuide.PredictionModelUpdateVersion.{OptimizationTarget}" units="version number" expires_after="M112"> <owner>mcrouse@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index e865f30..4bc61419 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -5091,6 +5091,16 @@ </summary> </histogram> +<histogram name="DocumentScan.ScanFailureProgress" enum="ScanFailureProgress" + expires_after="2023-12-14"> + <owner>rishabhagr@google.com</owner> + <owner>project-bolton@google.com</owner> + <summary> + Chrome OS document scan metric that tracks the stage at which the scan + failed. + </summary> +</histogram> + <histogram name="DocumentScan.ScanFailureReason" enum="ScanJobFailureReason" expires_after="2023-11-30"> <owner>rishabhagr@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml index d9400b6..ffb4e4c 100644 --- a/tools/metrics/histograms/metadata/sync/histograms.xml +++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -1369,9 +1369,10 @@ <owner>mmoskvitin@google.com</owner> <component>Services>Sync</component> <summary> - Records the known degraded recoverability value when the primary account is - set. Note that the value reflects state restored from the file and recorded - before sending new request to the server. + Records the known degraded recoverability value when the degraded + recoverability handler is started. Note that the value reflects state + restored from the file and recorded before sending new request to the + server. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index 65db5f3..735849e 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -590,6 +590,18 @@ </summary> </histogram> +<histogram name="Tab.RestoreClosedTab" enum="Boolean" + expires_after="2023-11-30"> + <owner>sreejakshetty@chromium.org</owner> + <owner>chrome-brapp-loading@google.com</owner> + <summary> + [Desktop] This metric is recorded whenever a tab is restored by the user. + Set to true if the tab is restored from ClosedTabCache and false indicates + the tab is restored normally. This accounts for all types of tab restores + i.e., in a closed window, closed group also on startup tab restores. + </summary> +</histogram> + <histogram name="Tab.RestoreResult" enum="TabRestoreResult" expires_after="M88"> <owner>dtrainor@chromium.org</owner> <owner>marq@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml index 18ac0fa..8d9d826b 100644 --- a/tools/metrics/histograms/metadata/variations/histograms.xml +++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -255,6 +255,26 @@ </summary> </histogram> +<histogram name="Variations.Limits.VariationKeySize.{Size}" units="KiB" + expires_after="2023-09-22"> + <owner>dalerogerson@google.com</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + The number of kilobytes of the variations crash keys, recorded every time + crash keys are updated. Crash keys larger than kVariationKeySize will be + truncated. The size of kVariationKeySize is controlled by the preprocessor + macro LARGE_VARIATION_KEY_SIZE. {Size}; + </summary> + <token key="Size"> + <variant name="Default" + summary=""Default" is recorded when + LARGE_VARIATION_KEY_SIZE is NOT defined."/> + <variant name="Large" + summary=""Large" is used when LARGE_VARIATION_KEY_SIZE is + defined."/> + </token> +</histogram> + <histogram name="Variations.LoadPermanentConsistencyCountryResult" enum="VariationsPermanentConsistencyCountryResult" expires_after="2023-11-01">
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv index 595089ddb..e9a1cbb 100644 --- a/tools/perf/benchmark.csv +++ b/tools/perf/benchmark.csv
@@ -73,6 +73,7 @@ speedometer2-minormc,omerkatz@chromium.org,Blink>JavaScript>GarbageCollection,,all speedometer2-pcscan,tmrts@chromium.org,Blink>JavaScript,,all startup.mobile,"pasko@chromium.org, lizeb@chromium.org",Speed>Metrics>SystemHealthRegressions,, +sync_performance_tests,mastiz@chromium.org,Services>Sync,https://chromium.googlesource.com/chromium/src/+/HEAD/components/sync/README.md, system_health.common_desktop,"charliea@chromium.org, sullivan@chromium.org, tdresser@chromium.org, chrome-speed-metrics-dev@chromium.org",Speed>Metrics>SystemHealthRegressions,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,2021,accessibility,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy,keyboard_input,scroll,tabs_switching,wasm,webgl" system_health.common_mobile,"charliea@chromium.org, sullivan@chromium.org, tdresser@chromium.org, chrome-speed-metrics-dev@chromium.org",Speed>Metrics>SystemHealthRegressions,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,2021,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy" system_health.memory_desktop,"pasko@chromium.org, lizeb@chromium.org",,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,2021,accessibility,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy,keyboard_input,scroll,tabs_switching,wasm,webgl"
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index 3e75430..c1b805d 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -248,6 +248,19 @@ ['blink_perf.display_locking', 'jetstream2']) +def _sync_performance_tests(estimated_runtime=110, + path=None, + additional_flags=None): + if not additional_flags: + additional_flags = [] + flags = ['--test-launcher-jobs=1', '--test-launcher-retry-limit=0'] + flags.extend(additional_flags) + return ExecutableConfig('sync_performance_tests', + path=path, + flags=flags, + estimated_runtime=estimated_runtime) + + def _base_perftests(estimated_runtime=270, path=None, additional_flags=None): if not additional_flags: additional_flags = [] @@ -357,7 +370,10 @@ FUCHSIA_EXEC_CONFIGS[board] = frozenset([ _base_perftests(900, path='bin/run_base_perftests', - additional_flags=FUCHSIA_EXEC_ARGS[board]) + additional_flags=FUCHSIA_EXEC_ARGS[board]), + _sync_performance_tests(900, + path='bin/run_sync_performance_tests', + additional_flags=FUCHSIA_EXEC_ARGS[board]), ]) _LINUX_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 79f585a..b3e3499 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -415,7 +415,8 @@ ], }, 'fuchsia-builder-perf-x64': { - 'additional_compile_targets': ['chrome_pkg', 'base_perftests'], + 'additional_compile_targets': + ['chrome_pkg', 'base_perftests', 'sync_performance_tests'], }, } @@ -1560,6 +1561,11 @@ 'skyostil@chromium.org, gab@chromium.org', 'Internals>SequenceManager', ('https://chromium.googlesource.com/chromium/src/+/HEAD/base/' + 'README.md#performance-testing')), + 'sync_performance_tests': + BenchmarkMetadata( + 'mastiz@chromium.org', 'Services>Sync', + 'https://chromium.googlesource.com/chromium/src/+/HEAD/components/sync/README.md' + ), 'tracing_perftests': BenchmarkMetadata('eseckler@chromium.org, oysteine@chromium.org', 'Speed>Tracing'),
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 5f322b0c..b44f31e 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/v31.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "1745dfffbb9a5fa93b72ac8ea7da6ac1bfefc8bc", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/f3ce1d9b9ce6a1401be9e0cebbaa0596f1373a10/trace_processor_shell.exe" + "hash": "46be90dba011723aa14314617f8b86a10bbc984b", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/42498077f54f5e3093b865b22cf6822f14c73222/trace_processor_shell.exe" }, "linux_arm": { "hash": "6373f26144aad58f230d11d6a91efda5a09c9873", @@ -22,7 +22,7 @@ }, "linux": { "hash": "16ec80773ab59dfaf991857341533653a091a918", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/42498077f54f5e3093b865b22cf6822f14c73222/trace_processor_shell" + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/39f3c505498164c3ad9ca31a4f5924de5d6aa8d0/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/core/shard_maps/fuchsia-perf-atlas-fyi_map.json b/tools/perf/core/shard_maps/fuchsia-perf-atlas-fyi_map.json index 76cb5507..3906bec 100644 --- a/tools/perf/core/shard_maps/fuchsia-perf-atlas-fyi_map.json +++ b/tools/perf/core/shard_maps/fuchsia-perf-atlas-fyi_map.json
@@ -27,18 +27,25 @@ }, "speedometer2": { "abridged": false - }, - "system_health.common_desktop": { - "end": 24, - "abridged": false + } + }, + "executables": { + "sync_performance_tests": { + "arguments": [ + "--test-launcher-jobs=1", + "--test-launcher-retry-limit=0", + "-d", + "--os-check=check", + "--system-image-dir=workstation_eng.chromebook-x64" + ], + "path": "bin/run_sync_performance_tests" } } }, "2": { "benchmarks": { "system_health.common_desktop": { - "begin": 24, - "end": 53, + "end": 41, "abridged": false } } @@ -46,20 +53,20 @@ "3": { "benchmarks": { "system_health.common_desktop": { - "begin": 53, + "begin": 41, "abridged": false } } }, "extra_infos": { - "num_stories": 86, - "predicted_min_shard_time": 280, - "predicted_min_shard_index": 1, - "predicted_max_shard_time": 900.0, - "predicted_max_shard_index": 0, + "num_stories": 87, + "predicted_min_shard_time": 400, + "predicted_min_shard_index": 3, + "predicted_max_shard_time": 940.0, + "predicted_max_shard_index": 1, "shard #0": 900.0, - "shard #1": 280, - "shard #2": 290, - "shard #3": 280 + "shard #1": 940.0, + "shard #2": 410, + "shard #3": 400 } } \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/fuchsia-perf-nuc-fyi_map.json b/tools/perf/core/shard_maps/fuchsia-perf-nuc-fyi_map.json index 9134264..51dae71d 100644 --- a/tools/perf/core/shard_maps/fuchsia-perf-nuc-fyi_map.json +++ b/tools/perf/core/shard_maps/fuchsia-perf-nuc-fyi_map.json
@@ -27,18 +27,25 @@ }, "speedometer2": { "abridged": false - }, - "system_health.common_desktop": { - "end": 24, - "abridged": false + } + }, + "executables": { + "sync_performance_tests": { + "arguments": [ + "--test-launcher-jobs=1", + "--test-launcher-retry-limit=0", + "-d", + "--os-check=check", + "--system-image-dir=workstation_eng.x64" + ], + "path": "bin/run_sync_performance_tests" } } }, "2": { "benchmarks": { "system_health.common_desktop": { - "begin": 24, - "end": 53, + "end": 41, "abridged": false } } @@ -46,20 +53,20 @@ "3": { "benchmarks": { "system_health.common_desktop": { - "begin": 53, + "begin": 41, "abridged": false } } }, "extra_infos": { - "num_stories": 86, - "predicted_min_shard_time": 280, - "predicted_min_shard_index": 1, - "predicted_max_shard_time": 900.0, - "predicted_max_shard_index": 0, + "num_stories": 87, + "predicted_min_shard_time": 400, + "predicted_min_shard_index": 3, + "predicted_max_shard_time": 940.0, + "predicted_max_shard_index": 1, "shard #0": 900.0, - "shard #1": 280, - "shard #2": 290, - "shard #3": 280 + "shard #1": 940.0, + "shard #2": 410, + "shard #3": 400 } } \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-atlas-fyi_timing.json b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-atlas-fyi_timing.json index 4ecf637..b7976a1 100644 --- a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-atlas-fyi_timing.json +++ b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-atlas-fyi_timing.json
@@ -2,5 +2,9 @@ { "duration": "900.0", "name": "base_perftests/_gtest_" + }, + { + "duration": "900.0", + "name": "sync_performance_tests/_gtest_" } ] \ No newline at end of file
diff --git a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-nuc-fyi_timing.json b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-nuc-fyi_timing.json index 4ecf637..b7976a1 100644 --- a/tools/perf/core/shard_maps/timing_data/fuchsia-perf-nuc-fyi_timing.json +++ b/tools/perf/core/shard_maps/timing_data/fuchsia-perf-nuc-fyi_timing.json
@@ -2,5 +2,9 @@ { "duration": "900.0", "name": "base_perftests/_gtest_" + }, + { + "duration": "900.0", + "name": "sync_performance_tests/_gtest_" } ] \ No newline at end of file
diff --git a/tools/rust/build_rust.py b/tools/rust/build_rust.py index 0a424cf..ae9de42 100755 --- a/tools/rust/build_rust.py +++ b/tools/rust/build_rust.py
@@ -191,9 +191,8 @@ # A `-Clink-arg=<foo>` arg passes `foo`` to the linker invovation. RUSTENV['RUSTFLAGS_BOOTSTRAP'] = '' - if gcc_toolchain_flag: - RUSTENV['RUSTFLAGS_BOOTSTRAP'] += f' -Clink-arg={gcc_toolchain_flag} ' if gcc_toolchain_path: + RUSTENV['RUSTFLAGS_BOOTSTRAP'] += f' -Clink-arg={gcc_toolchain_flag} ' RUSTENV['RUSTFLAGS_BOOTSTRAP'] += ( f' -L native={gcc_toolchain_path}/lib64') RUSTENV['RUSTFLAGS_NOT_BOOTSTRAP'] = RUSTENV['RUSTFLAGS_BOOTSTRAP']
diff --git a/tools/rust/package_rust.py b/tools/rust/package_rust.py index ace96ef..d67f348 100755 --- a/tools/rust/package_rust.py +++ b/tools/rust/package_rust.py
@@ -5,6 +5,7 @@ import argparse import os +import platform import shutil import sys import tarfile @@ -56,11 +57,6 @@ # Share this argument with other build scripts that we execute here. BUILD_MAC_ARM = args.build_mac_arm - # Only build on Linux. Other platforms are currently unsupported. - if not (sys.platform.startswith('linux') or sys.platform == 'win32'): - print('Only Linux and Windows is supported!') - return 1 - # The gcs_platform logic copied from `//tools/clang/scripts/upload.sh`. if sys.platform == 'darwin': # The --build-mac-intel switch can be used to force the Mac build to
diff --git a/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm b/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm index 6c01505..9356415 100644 --- a/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm +++ b/ui/accelerated_widget_mac/ca_layer_tree_unittest_mac.mm
@@ -15,7 +15,6 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/mac/io_surface.h" #include "ui/gl/ca_renderer_layer_params.h" -#include "ui/gl/gl_image_io_surface.h" @interface CALayer (Private) @property BOOL wantsExtendedDynamicRangeContent; @@ -41,39 +40,34 @@ float opacity = 1.0f; float scale_factor = 1.0f; unsigned filter = GL_LINEAR; - scoped_refptr<gl::GLImageIOSurface> gl_image; + gfx::ScopedIOSurface io_surface; + gfx::ColorSpace color_space; + base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer; bool allow_av_layers = true; bool allow_solid_color_layers = true; }; -scoped_refptr<gl::GLImageIOSurface> CreateGLImage(const gfx::Size& size, - gfx::BufferFormat format, - bool video) { - scoped_refptr<gl::GLImageIOSurface> gl_image( - gl::GLImageIOSurface::Create(size)); - base::ScopedCFTypeRef<IOSurfaceRef> io_surface( - gfx::CreateIOSurface(size, format)); - if (video) { - base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer; - CVPixelBufferCreateWithIOSurface(nullptr, io_surface, nullptr, - cv_pixel_buffer.InitializeInto()); - gl_image->InitializeWithCVPixelBuffer(cv_pixel_buffer, 0, - gfx::GenericSharedMemoryId(), format, - gfx::ColorSpace::CreateREC709()); - } else { - gl_image->Initialize(io_surface, 0, gfx::GenericSharedMemoryId(), format); - } - return gl_image; +gfx::ScopedIOSurface CreateScopedIOSurface(const gfx::Size& size, + gfx::BufferFormat format) { + return gfx::ScopedIOSurface(gfx::CreateIOSurface(size, format)); +} + +base::ScopedCFTypeRef<CVPixelBufferRef> CreateCVPixelBuffer( + gfx::ScopedIOSurface io_surface) { + base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer; + CVPixelBufferCreateWithIOSurface(nullptr, io_surface, nullptr, + cv_pixel_buffer.InitializeInto()); + return cv_pixel_buffer; } bool ScheduleCALayer(ui::CARendererLayerTree* tree, CALayerProperties* properties) { gfx::ScopedIOSurface io_surface; gfx::ColorSpace io_surface_color_space; - if (properties->gl_image) { - io_surface = properties->gl_image->io_surface(); - io_surface_color_space = properties->gl_image->color_space(); + if (properties->io_surface) { + io_surface = properties->io_surface; + io_surface_color_space = properties->color_space; } return tree->ScheduleCALayer(ui::CARendererLayerParams( properties->is_clipped, properties->clip_rect, @@ -136,8 +130,8 @@ properties.background_color = SkColors::kRed; properties.edge_aa_mask = ui::CALayerEdge::kLayerEdgeLeft; properties.opacity = 0.5f; - properties.gl_image = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); + properties.io_surface = CreateScopedIOSurface(gfx::Size(256, 256), + gfx::BufferFormat::BGRA_8888); std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; CALayer* root_layer = nil; @@ -190,7 +184,7 @@ [transform_layer sublayerTransform].m42); // Validate the content layer. - EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), + EXPECT_EQ(static_cast<id>(properties.io_surface.get()), [content_layer contents]); EXPECT_EQ(properties.contents_rect, gfx::RectF([content_layer contentsRect])); @@ -299,7 +293,7 @@ // Change the contents and commit. { - properties.gl_image = nullptr; + properties.io_surface = gfx::ScopedIOSurface(); UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); // Validate the tree structure. @@ -414,8 +408,8 @@ // Add the clipping and IOSurface contents back. { properties.is_clipped = true; - properties.gl_image = CreateGLImage(gfx::Size(256, 256), - gfx::BufferFormat::BGRA_8888, false); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888); UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); // Validate the tree structure. @@ -430,7 +424,7 @@ EXPECT_EQ(content_layer, [transform_layer sublayers][0]); // Validate the content layer. - EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), + EXPECT_EQ(static_cast<id>(properties.io_surface.get()), [content_layer contents]); EXPECT_EQ(kCALayerBottomEdge, [content_layer edgeAntialiasingMask]); } @@ -484,7 +478,7 @@ [transform_layer sublayerTransform].m42); // Validate the content layer. - EXPECT_EQ(static_cast<id>(properties.gl_image->io_surface().get()), + EXPECT_EQ(static_cast<id>(properties.io_surface.get()), [content_layer contents]); EXPECT_EQ(properties.contents_rect, gfx::RectF([content_layer contentsRect])); @@ -577,10 +571,10 @@ properties.rect = gfx::Rect(0, 0, 256, 256); // We'll use the IOSurface contents to identify the content layers. - scoped_refptr<gl::GLImageIOSurface> gl_images[5]; + gfx::ScopedIOSurface io_surfaces[5]; for (size_t i = 0; i < 5; ++i) { - gl_images[i] = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); + io_surfaces[i] = CreateScopedIOSurface(gfx::Size(256, 256), + gfx::BufferFormat::BGRA_8888); } // Have 5 transforms: @@ -598,7 +592,7 @@ std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree( new ui::CARendererLayerTree(true, true)); for (size_t i = 0; i < 5; ++i) { - properties.gl_image = gl_images[i]; + properties.io_surface = io_surfaces[i]; properties.transform = transforms[i]; bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); EXPECT_TRUE(result); @@ -645,16 +639,11 @@ CALayer* content_layer_4 = [transform_layer_2_0 sublayers][1]; // Validate that the layers come out in order. - EXPECT_EQ(static_cast<id>(gl_images[0]->io_surface().get()), - [content_layer_0 contents]); - EXPECT_EQ(static_cast<id>(gl_images[1]->io_surface().get()), - [content_layer_1 contents]); - EXPECT_EQ(static_cast<id>(gl_images[2]->io_surface().get()), - [content_layer_2 contents]); - EXPECT_EQ(static_cast<id>(gl_images[3]->io_surface().get()), - [content_layer_3 contents]); - EXPECT_EQ(static_cast<id>(gl_images[4]->io_surface().get()), - [content_layer_4 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[0].get()), [content_layer_0 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[1].get()), [content_layer_1 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[2].get()), [content_layer_2 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[3].get()), [content_layer_3 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[4].get()), [content_layer_4 contents]); } // Verify that sorting contexts are allocated appropriately. @@ -665,10 +654,10 @@ properties.rect = gfx::Rect(0, 0, 256, 256); // We'll use the IOSurface contents to identify the content layers. - scoped_refptr<gl::GLImageIOSurface> gl_images[3]; + gfx::ScopedIOSurface io_surfaces[3]; for (size_t i = 0; i < 3; ++i) { - gl_images[i] = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); + io_surfaces[i] = CreateScopedIOSurface(gfx::Size(256, 256), + gfx::BufferFormat::BGRA_8888); } int sorting_context_ids[3] = {3, -1, 0}; @@ -678,7 +667,7 @@ new ui::CARendererLayerTree(true, true)); for (size_t i = 0; i < 3; ++i) { properties.sorting_context_id = sorting_context_ids[i]; - properties.gl_image = gl_images[i]; + properties.io_surface = io_surfaces[i]; bool result = ScheduleCALayer(ca_layer_tree.get(), &properties); EXPECT_TRUE(result); } @@ -715,12 +704,9 @@ CALayer* content_layer_2 = [transform_layer_2 sublayers][0]; // Validate that the layers come out in order. - EXPECT_EQ(static_cast<id>(gl_images[0]->io_surface().get()), - [content_layer_0 contents]); - EXPECT_EQ(static_cast<id>(gl_images[1]->io_surface().get()), - [content_layer_1 contents]); - EXPECT_EQ(static_cast<id>(gl_images[2]->io_surface().get()), - [content_layer_2 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[0].get()), [content_layer_0 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[1].get()), [content_layer_1 contents]); + EXPECT_EQ(static_cast<id>(io_surfaces[2].get()), [content_layer_2 contents]); } // Verify that sorting contexts must all have the same clipping properties. @@ -773,8 +759,8 @@ // Test updating each layer's properties. TEST_F(CALayerTreeTest, AVLayer) { CALayerProperties properties; - properties.gl_image = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); + properties.io_surface = + CreateScopedIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888); std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; CALayer* content_layer_old = nil; @@ -791,8 +777,8 @@ // Pass a YUV 420 frame. This will become an AVSampleBufferDisplayLayer // because it is in fullscreen low power mode. - properties.gl_image = CreateGLImage( - gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR, false); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR); { UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); content_layer_new = GetOnlyContentLayer(); @@ -803,8 +789,8 @@ content_layer_old = content_layer_new; // Pass a similar frame. Nothing should change. - properties.gl_image = CreateGLImage( - gfx::Size(256, 128), gfx::BufferFormat::YUV_420_BIPLANAR, false); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(256, 128), gfx::BufferFormat::YUV_420_BIPLANAR); { UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); content_layer_new = GetOnlyContentLayer(); @@ -828,8 +814,8 @@ // Now try a P010 frame. Because this may be HDR, we should jump back to // having an AVSampleBufferDisplayLayer. - properties.gl_image = - CreateGLImage(gfx::Size(128, 256), gfx::BufferFormat::P010, false); + properties.io_surface = + CreateScopedIOSurface(gfx::Size(128, 256), gfx::BufferFormat::P010); { UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); content_layer_new = GetOnlyContentLayer(); @@ -844,8 +830,10 @@ // Pass a frame with a CVPixelBuffer which, when scaled down, will have a // fractional dimension. - properties.gl_image = CreateGLImage( - gfx::Size(513, 512), gfx::BufferFormat::YUV_420_BIPLANAR, true); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(513, 512), gfx::BufferFormat::YUV_420_BIPLANAR); + properties.cv_pixel_buffer = CreateCVPixelBuffer(properties.io_surface); + properties.color_space = gfx::ColorSpace::CreateREC709(); { UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); content_layer_new = GetOnlyContentLayer(); @@ -860,8 +848,8 @@ // Pass a frame that is clipped. properties.contents_rect = gfx::RectF(0, 0, 1, 0.9); - properties.gl_image = CreateGLImage( - gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR, false); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR); { UpdateCALayerTree(ca_layer_tree, &properties, superlayer_); content_layer_new = GetOnlyContentLayer(); @@ -875,8 +863,8 @@ // Ensure that blocklisting AVSampleBufferDisplayLayer works. TEST_F(CALayerTreeTest, AVLayerBlocklist) { CALayerProperties properties; - properties.gl_image = CreateGLImage( - gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR, false); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR); std::unique_ptr<ui::CARendererLayerTree> ca_layer_tree; CALayer* root_layer = nil; @@ -932,8 +920,10 @@ // Test fullscreen low power detection. TEST_F(CALayerTreeTest, FullscreenLowPower) { CALayerProperties properties; - properties.gl_image = CreateGLImage( - gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR, true); + properties.io_surface = CreateScopedIOSurface( + gfx::Size(256, 256), gfx::BufferFormat::YUV_420_BIPLANAR); + properties.cv_pixel_buffer = CreateCVPixelBuffer(properties.io_surface); + properties.color_space = gfx::ColorSpace::CreateREC709(); properties.is_clipped = false; CALayerProperties properties_black; @@ -1075,18 +1065,16 @@ bool result = false; // We only copy images that have both high-bit-depth and an HDR color space. - scoped_refptr<gl::GLImageIOSurface> sdr_image = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); - scoped_refptr<gl::GLImageIOSurface> tricky_sdr_image = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888, false); - scoped_refptr<gl::GLImageIOSurface> hdr_image = - CreateGLImage(gfx::Size(256, 256), gfx::BufferFormat::RGBA_F16, false); - sdr_image->SetColorSpace(gfx::ColorSpace::CreateSRGB()); - tricky_sdr_image->SetColorSpace(gfx::ColorSpace::CreateExtendedSRGB()); - hdr_image->SetColorSpace(gfx::ColorSpace::CreateExtendedSRGB()); + auto sdr_image = + CreateScopedIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888); + auto tricky_sdr_image = + CreateScopedIOSurface(gfx::Size(256, 256), gfx::BufferFormat::BGRA_8888); + auto hdr_image = + CreateScopedIOSurface(gfx::Size(256, 256), gfx::BufferFormat::RGBA_F16); // Schedule and commit the HDR layer. - properties.gl_image = hdr_image; + properties.io_surface = hdr_image; + properties.color_space = gfx::ColorSpace::CreateExtendedSRGB(); result = ScheduleCALayer(ca_layer_trees[0].get(), &properties); EXPECT_TRUE(result); ca_layer_trees[0]->CommitScheduledCALayers( @@ -1098,7 +1086,8 @@ EXPECT_TRUE([content_layer wantsExtendedDynamicRangeContent]); // Commit the SDR layer. - properties.gl_image = sdr_image; + properties.io_surface = sdr_image; + properties.color_space = gfx::ColorSpace::CreateSRGB(); result = ScheduleCALayer(ca_layer_trees[1].get(), &properties); EXPECT_TRUE(result); ca_layer_trees[1]->CommitScheduledCALayers( @@ -1113,7 +1102,8 @@ EXPECT_FALSE([content_layer wantsExtendedDynamicRangeContent]); // Commit the tricky SDR layer. - properties.gl_image = tricky_sdr_image; + properties.io_surface = tricky_sdr_image; + properties.color_space = gfx::ColorSpace::CreateExtendedSRGB(); result = ScheduleCALayer(ca_layer_trees[2].get(), &properties); EXPECT_TRUE(result); ca_layer_trees[2]->CommitScheduledCALayers( @@ -1126,7 +1116,8 @@ EXPECT_FALSE([content_layer wantsExtendedDynamicRangeContent]); // Commit the HDR layer. - properties.gl_image = hdr_image; + properties.io_surface = hdr_image; + properties.color_space = gfx::ColorSpace::CreateExtendedSRGB(); result = ScheduleCALayer(ca_layer_trees[3].get(), &properties); EXPECT_TRUE(result); ca_layer_trees[3]->CommitScheduledCALayers(
diff --git a/ui/chromeos/styles/cros_sys_colors.json5 b/ui/chromeos/styles/cros_sys_colors.json5 index 1ce9aab..c99aed4 100644 --- a/ui/chromeos/styles/cros_sys_colors.json5 +++ b/ui/chromeos/styles/cros_sys_colors.json5
@@ -197,6 +197,7 @@ light: '$cros.ref.primary10', dark: '$cros.ref.primary10', }, + 'system-on-primary-container-disabled': 'rgba($cros.sys.system-on-primary-container.rgb, 0.38)', /* Harmonized colors */ 'on-positive-container': {
diff --git a/ui/compositor/test/in_process_context_provider.cc b/ui/compositor/test/in_process_context_provider.cc index 1828eee..3aef16e7 100644 --- a/ui/compositor/test/in_process_context_provider.cc +++ b/ui/compositor/test/in_process_context_provider.cc
@@ -193,15 +193,6 @@ observers_.RemoveObserver(obs); } -uint32_t InProcessContextProvider::GetCopyTextureInternalFormat() { - if (attribs_.alpha_size > 0) - return GL_RGBA; - DCHECK_NE(attribs_.red_size, 0); - DCHECK_NE(attribs_.green_size, 0); - DCHECK_NE(attribs_.blue_size, 0); - return GL_RGB; -} - void InProcessContextProvider::SendOnContextLost() { for (auto& observer : observers_) observer.OnContextLost();
diff --git a/ui/compositor/test/in_process_context_provider.h b/ui/compositor/test/in_process_context_provider.h index 9ec54fb..3f0a766d 100644 --- a/ui/compositor/test/in_process_context_provider.h +++ b/ui/compositor/test/in_process_context_provider.h
@@ -67,10 +67,6 @@ void AddObserver(viz::ContextLostObserver* obs) override; void RemoveObserver(viz::ContextLostObserver* obs) override; - // Gives the GL internal format that should be used for calling CopyTexImage2D - // on the default framebuffer. - uint32_t GetCopyTextureInternalFormat(); - // Calls OnContextLost() on all observers. This doesn't modify the context. void SendOnContextLost();
diff --git a/ui/gl/gl_image_io_surface.h b/ui/gl/gl_image_io_surface.h index bcad4544..6376ad4 100644 --- a/ui/gl/gl_image_io_surface.h +++ b/ui/gl/gl_image_io_surface.h
@@ -66,7 +66,6 @@ uint64_t process_tracing_id, const std::string& dump_name) override; - const gfx::ColorSpace& color_space() const { return color_space_; } gfx::BufferFormat format() const { return format_; } gfx::GenericSharedMemoryId io_surface_id() const { return io_surface_id_; } base::ScopedCFTypeRef<IOSurfaceRef> io_surface() { return io_surface_; }
diff --git a/url/url_features.cc b/url/url_features.cc index 39000c8..25132d1 100644 --- a/url/url_features.cc +++ b/url/url_features.cc
@@ -10,7 +10,17 @@ "UseIDNA2008NonTransitional", base::FEATURE_ENABLED_BY_DEFAULT); +// Kill switch for crbug.com/1362507. +BASE_FEATURE(kRecordIDNA2008Metrics, + "RecordIDNA2008Metrics", + base::FEATURE_ENABLED_BY_DEFAULT); + bool IsUsingIDNA2008NonTransitional() { return base::FeatureList::IsEnabled(kUseIDNA2008NonTransitional); } + +bool IsRecordingIDNA2008Metrics() { + return base::FeatureList::IsEnabled(kRecordIDNA2008Metrics); +} + } // namespace url
diff --git a/url/url_features.h b/url/url_features.h index 3bd283f3..9924f3d 100644 --- a/url/url_features.h +++ b/url/url_features.h
@@ -14,6 +14,10 @@ // Returns true if Chrome is using IDNA 2008 in Non-Transitional mode. COMPONENT_EXPORT(URL) bool IsUsingIDNA2008NonTransitional(); + +// Returns true if Chrome is recording IDNA 2008 related metrics. +COMPONENT_EXPORT(URL) bool IsRecordingIDNA2008Metrics(); + } // namespace url #endif // URL_URL_FEATURES_H_