diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-10-26 13:57:00 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-11-02 11:31:01 +0000 |
commit | 1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch) | |
tree | 8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/chrome/browser/ui/webui/settings | |
parent | 21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff) |
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/chrome/browser/ui/webui/settings')
132 files changed, 5754 insertions, 1952 deletions
diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.cc b/chromium/chrome/browser/ui/webui/settings/about_handler.cc index 748b410d0a6..c629f0ac055 100644 --- a/chromium/chrome/browser/ui/webui/settings/about_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/about_handler.cc @@ -66,7 +66,7 @@ #include "chrome/browser/ui/webui/help/version_updater_chromeos.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chromeos/dbus/power/power_manager_client.h" -#include "chromeos/dbus/update_engine_client.h" +#include "chromeos/dbus/update_engine/update_engine_client.h" #include "chromeos/dbus/util/version_loader.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" @@ -378,12 +378,16 @@ void AboutHandler::OnDeviceAutoUpdatePolicyChanged( const base::Value* previous_policy, const base::Value* current_policy) { bool previous_auto_update_disabled = false; - if (previous_policy) - CHECK(previous_policy->GetAsBoolean(&previous_auto_update_disabled)); + if (previous_policy) { + CHECK(previous_policy->is_bool()); + previous_auto_update_disabled = previous_policy->GetBool(); + } bool current_auto_update_disabled = false; - if (current_policy) - CHECK(current_policy->GetAsBoolean(¤t_auto_update_disabled)); + if (current_policy) { + CHECK(current_policy->is_bool()); + current_auto_update_disabled = current_policy->GetBool(); + } if (current_auto_update_disabled != previous_auto_update_disabled) { // Refresh the update status to refresh the status of the UI. diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/about_handler_unittest.cc index ad4350be337..cf7d225f416 100644 --- a/chromium/chrome/browser/ui/webui/settings/about_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/about_handler_unittest.cc @@ -8,7 +8,7 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/concierge/concierge_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_update_engine_client.h" +#include "chromeos/dbus/update_engine/fake_update_engine_client.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" #include "testing/gtest/include/gtest/gtest.h" @@ -67,9 +67,10 @@ class AboutHandlerTest : public testing::Test { std::string CallGetEndOfLifeInfoAndReturnString(bool has_eol_passed) { size_t call_data_count_before_call = web_ui_.call_data().size(); - base::ListValue args; - args.AppendString("handlerFunctionName"); - web_ui_.HandleReceivedMessage("getEndOfLifeInfo", &args); + base::Value args(base::Value::Type::LIST); + args.Append("handlerFunctionName"); + web_ui_.HandleReceivedMessage("getEndOfLifeInfo", + &base::Value::AsListValue(args)); task_environment_.RunUntilIdle(); EXPECT_EQ(call_data_count_before_call + 1u, web_ui_.call_data().size()); diff --git a/chromium/chrome/browser/ui/webui/settings/captions_handler.cc b/chromium/chrome/browser/ui/webui/settings/captions_handler.cc index 1927f1fd45f..2c32738c187 100644 --- a/chromium/chrome/browser/ui/webui/settings/captions_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/captions_handler.cc @@ -17,16 +17,26 @@ #include "media/base/media_switches.h" #include "ui/base/l10n/l10n_util.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "ash/constants/ash_features.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + #if defined(OS_WIN) || defined(OS_MAC) #include "chrome/browser/accessibility/caption_settings_dialog.h" #endif namespace settings { -CaptionsHandler::CaptionsHandler(PrefService* prefs) : prefs_(prefs) {} +CaptionsHandler::CaptionsHandler(PrefService* prefs) : prefs_(prefs) { +#if BUILDFLAG(IS_CHROMEOS_ASH) + soda_available_ = + base::FeatureList::IsEnabled(ash::features::kOnDeviceSpeechRecognition); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) +} CaptionsHandler::~CaptionsHandler() { - speech::SodaInstaller::GetInstance()->RemoveObserver(this); + if (soda_available_) + speech::SodaInstaller::GetInstance()->RemoveObserver(this); } void CaptionsHandler::RegisterMessages() { @@ -41,11 +51,13 @@ void CaptionsHandler::RegisterMessages() { } void CaptionsHandler::OnJavascriptAllowed() { - speech::SodaInstaller::GetInstance()->AddObserver(this); + if (soda_available_) + speech::SodaInstaller::GetInstance()->AddObserver(this); } void CaptionsHandler::OnJavascriptDisallowed() { - speech::SodaInstaller::GetInstance()->RemoveObserver(this); + if (soda_available_) + speech::SodaInstaller::GetInstance()->RemoveObserver(this); } void CaptionsHandler::HandleLiveCaptionSectionReady( @@ -61,7 +73,11 @@ void CaptionsHandler::HandleOpenSystemCaptionsDialog( } void CaptionsHandler::OnSodaInstalled() { - speech::SodaInstaller::GetInstance()->RemoveObserver(this); + if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage) && + soda_available_) { + speech::SodaInstaller::GetInstance()->RemoveObserver(this); + } + FireWebUIListener("soda-download-progress-changed", base::Value(l10n_util::GetStringUTF16( IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE))); @@ -69,6 +85,9 @@ void CaptionsHandler::OnSodaInstalled() { void CaptionsHandler::OnSodaLanguagePackInstalled( speech::LanguageCode language_code) { + if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) + return; + FireWebUIListener("soda-download-progress-changed", base::Value(l10n_util::GetStringUTF16( IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE)), @@ -88,10 +107,10 @@ void CaptionsHandler::OnSodaError() { void CaptionsHandler::OnSodaLanguagePackError( speech::LanguageCode language_code) { - if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) { - prefs_->SetBoolean(prefs::kLiveCaptionEnabled, false); - } + if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) + return; + prefs_->SetBoolean(prefs::kLiveCaptionEnabled, false); FireWebUIListener("soda-download-progress-changed", base::Value(l10n_util::GetStringUTF16( IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_ERROR)), @@ -109,6 +128,9 @@ void CaptionsHandler::OnSodaProgress(int combined_progress) { void CaptionsHandler::OnSodaLanguagePackProgress( int language_progress, speech::LanguageCode language_code) { + if (!base::FeatureList::IsEnabled(media::kLiveCaptionMultiLanguage)) + return; + FireWebUIListener("soda-download-progress-changed", base::Value(l10n_util::GetStringFUTF16Int( IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_PROGRESS, diff --git a/chromium/chrome/browser/ui/webui/settings/captions_handler.h b/chromium/chrome/browser/ui/webui/settings/captions_handler.h index 97cd77000bb..0358bfcaf4d 100644 --- a/chromium/chrome/browser/ui/webui/settings/captions_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/captions_handler.h @@ -41,6 +41,7 @@ class CaptionsHandler : public SettingsPageUIHandler, speech::LanguageCode language_code) override; PrefService* prefs_; + bool soda_available_ = true; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc b/chromium/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc index c7aa55a9836..5af8d6440d5 100644 --- a/chromium/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc +++ b/chromium/chrome/browser/ui/webui/settings/chrome_cleanup_handler_win.cc @@ -56,7 +56,7 @@ std::unique_ptr<base::ListValue> GetStringSetAsListStorage( const std::set<std::wstring>& string_set) { auto value = std::make_unique<base::ListValue>(); for (const std::wstring& string : string_set) - value->AppendString(base::AsString16(string)); + value->Append(base::AsString16(string)); return value; } @@ -287,13 +287,12 @@ void ChromeCleanupHandler::HandleGetItemsToRemovePluralString( void ChromeCleanupHandler::GetPluralString(int id, const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); + const auto& list = args->GetList(); + CHECK_EQ(2U, list.size()); - std::string callback_id; - CHECK(args->GetString(0, &callback_id)); + std::string callback_id = list[0].GetString(); - int num_items = 0; - args->GetInteger(1, &num_items); + int num_items = list[1].GetIfInt().value_or(0); const std::u16string plural_string = num_items > 0 ? l10n_util::GetPluralStringFUTF16(id, num_items) diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS b/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS index 1c079659d26..7e871b5ee5a 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/DEPS @@ -2,5 +2,6 @@ include_rules = [ "+ash/components/pcie_peripheral", "+components/account_manager_core", "+chrome/services/local_search_service", + "+chromeos/tpm:tpm", "+device/udev_linux/fake_udev_loader.h", # For keyboard unit test. ] diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS b/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS index e26540b4619..c7ffc2b1392 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/OWNERS @@ -3,3 +3,4 @@ file://chrome/browser/resources/settings/chromeos/OWNERS per-file languages_section*=myy@chromium.org per-file multidevice_handler*=file://chromeos/components/multidevice/OWNERS per-file account_manager_*=file://ash/components/account_manager/OWNERS +per-file apps_section*=file://chrome/browser/ui/webui/app_management/OWNERS diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.cc index d4bac0c4074..734b4934564 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.cc @@ -374,7 +374,8 @@ void AboutSection::AddLoadTimeData(content::WebUIDataSource* html_source) { void AboutSection::AddHandlers(content::WebUI* web_ui) { web_ui->AddMessageHandler( std::make_unique<::settings::AboutHandler>(profile())); - web_ui->AddMessageHandler(std::make_unique<DeviceNameHandler>()); + if (features::IsHostnameSettingEnabled()) + web_ui->AddMessageHandler(std::make_unique<DeviceNameHandler>()); } int AboutSection::GetSectionNameMessageId() const { diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc index 962027d8721..a0429575590 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc @@ -4,20 +4,30 @@ #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h" +#include <set> + +#include "ash/constants/ash_pref_names.h" #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/containers/flat_map.h" #include "base/metrics/histogram_functions.h" #include "chrome/browser/ash/accessibility/accessibility_manager.h" +#include "chrome/browser/ash/accessibility/dictation.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/grit/generated_resources.h" +#include "components/language/core/browser/pref_names.h" +#include "components/language/core/common/locale_util.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/web_ui.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" -#include "ui/accessibility/accessibility_switches.h" +#include "ui/accessibility/accessibility_features.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#include "ui/base/ime/chromeos/input_method_util.h" #include "ui/base/l10n/l10n_util.h" namespace chromeos { @@ -41,8 +51,6 @@ AccessibilityHandler::AccessibilityHandler(Profile* profile) AccessibilityHandler::~AccessibilityHandler() { if (a11y_nav_buttons_toggle_metrics_reporter_timer_.IsRunning()) a11y_nav_buttons_toggle_metrics_reporter_timer_.FireNow(); - if (::switches::IsExperimentalAccessibilityDictationOfflineEnabled()) - speech::SodaInstaller::GetInstance()->RemoveObserver(this); } void AccessibilityHandler::RegisterMessages() { @@ -109,12 +117,19 @@ void AccessibilityHandler::HandleRecordSelectedShowShelfNavigationButtonsValue( void AccessibilityHandler::HandleManageA11yPageReady( const base::ListValue* args) { AllowJavascript(); +} +void AccessibilityHandler::OnJavascriptAllowed() { FireWebUIListener( "initial-data-ready", base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled())); - MaybeAddSodaInstallerObserver(); + MaybeAddDictationLocales(); +} + +void AccessibilityHandler::OnJavascriptDisallowed() { + if (features::IsDictationOfflineAvailableAndEnabled()) + soda_observation_.Reset(); } void AccessibilityHandler::HandleShowChromeVoxTutorial( @@ -134,11 +149,19 @@ void AccessibilityHandler::OpenExtensionOptionsPage(const char extension_id[]) { } void AccessibilityHandler::MaybeAddSodaInstallerObserver() { - if (::switches::IsExperimentalAccessibilityDictationOfflineEnabled()) { - if (speech::SodaInstaller::GetInstance()->IsSodaInstalled()) + // TODO(crbug.com/1173135): Don't display SODA status if the Dictation + // language is not a downloaded or available SODA language. + if (features::IsDictationOfflineAvailableAndEnabled()) { + const std::string dictation_locale = + profile_->GetPrefs()->GetString(prefs::kAccessibilityDictationLocale); + if (speech::SodaInstaller::GetInstance()->IsSodaInstalled( + speech::GetLanguageCode(dictation_locale))) { OnSodaInstalled(); - else - speech::SodaInstaller::GetInstance()->AddObserver(this); + } else { + // Add self as an observer. If this was a page refresh we don't want to + // get added twice. + soda_observation_.Observe(speech::SodaInstaller::GetInstance()); + } } } @@ -166,5 +189,65 @@ void AccessibilityHandler::OnSodaError() { IDS_SETTINGS_ACCESSIBILITY_DICTATION_SUBTITLE_SODA_DOWNLOAD_ERROR))); } +void AccessibilityHandler::MaybeAddDictationLocales() { + if (!features::IsExperimentalAccessibilityDictationOfflineEnabled()) + return; + + base::flat_map<std::string, bool> locales = + ash::Dictation::GetAllSupportedLocales(); + + // Get application locale. + std::string application_locale = g_browser_process->GetApplicationLocale(); + std::pair<base::StringPiece, base::StringPiece> application_lang_and_locale = + language::SplitIntoMainAndTail(application_locale); + + // Get IME locales + input_method::InputMethodManager* ime_manager = + input_method::InputMethodManager::Get(); + std::vector<std::string> input_method_ids = + ime_manager->GetActiveIMEState()->GetActiveInputMethodIds(); + std::vector<std::string> ime_languages; + ime_manager->GetInputMethodUtil()->GetLanguageCodesFromInputMethodIds( + input_method_ids, &ime_languages); + + // Get enabled preferred UI languages. + std::string preferred_languages = + profile_->GetPrefs()->GetString(language::prefs::kPreferredLanguages); + std::vector<base::StringPiece> enabled_languages = + base::SplitStringPiece(preferred_languages, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + + // Combine these into one set for recommending Dication languages. + std::set<base::StringPiece> ui_languages; + ui_languages.insert(application_lang_and_locale.first); + for (auto& ime_language : ime_languages) { + ui_languages.insert(language::SplitIntoMainAndTail(ime_language).first); + } + for (auto& enabled_language : enabled_languages) { + ui_languages.insert(language::SplitIntoMainAndTail(enabled_language).first); + } + + base::Value locales_list(base::Value::Type::LIST); + for (auto& locale : locales) { + base::Value option(base::Value::Type::DICTIONARY); + option.SetKey("value", base::Value(locale.first)); + option.SetKey("name", + base::Value(l10n_util::GetDisplayNameForLocale( + locale.first, application_locale, /*is_for_ui=*/true))); + option.SetKey("offline", base::Value(locale.second)); + + // We can recommend languages that match the current application + // locale, IME languages or enabled preferred languages. + std::pair<base::StringPiece, base::StringPiece> lang_and_locale = + language::SplitIntoMainAndTail(locale.first); + bool is_recommended = base::Contains(ui_languages, lang_and_locale.first); + + option.SetKey("recommended", base::Value(is_recommended)); + locales_list.Append(std::move(option)); + } + + FireWebUIListener("dictation-locales-set", locales_list); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h index f778cfe3d7a..48ab03ddc1d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ACCESSIBILITY_HANDLER_H_ #include "base/macros.h" +#include "base/scoped_observation.h" #include "base/timer/timer.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/soda/soda_installer.h" @@ -27,8 +28,8 @@ class AccessibilityHandler : public ::settings::SettingsPageUIHandler, // SettingsPageUIHandler implementation. void RegisterMessages() override; - void OnJavascriptAllowed() override {} - void OnJavascriptDisallowed() override {} + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; // Callback which updates if startup sound is enabled. Visible for testing. void HandleManageA11yPageReady(const base::ListValue* args); @@ -60,6 +61,8 @@ class AccessibilityHandler : public ::settings::SettingsPageUIHandler, void OnSodaError() override; void OnSodaLanguagePackError(speech::LanguageCode language_code) override {} + void MaybeAddDictationLocales(); + Profile* profile_; // Weak pointer. // Timer to record user changed value for the accessibility setting to turn @@ -68,6 +71,10 @@ class AccessibilityHandler : public ::settings::SettingsPageUIHandler, // setting value in the screen UI. base::OneShotTimer a11y_nav_buttons_toggle_metrics_reporter_timer_; + base::ScopedObservation<speech::SodaInstaller, + speech::SodaInstaller::Observer> + soda_observation_{this}; + base::WeakPtrFactory<AccessibilityHandler> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(AccessibilityHandler); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc index 2b958a32afc..5752b5686ca 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler_browsertest.cc @@ -5,13 +5,28 @@ #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h" #include <memory> +#include <set> +#include "ash/constants/ash_features.h" +#include "chrome/browser/ash/input_method/mock_input_method_engine.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/browser.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" +#include "components/language/core/browser/pref_names.h" +#include "components/language/core/common/locale_util.h" +#include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" #include "content/public/test/test_web_ui.h" -#include "ui/accessibility/accessibility_switches.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/accessibility/accessibility_features.h" +#include "ui/base/ime/chromeos/input_method_descriptor.h" +#include "ui/base/ime/chromeos/input_method_manager.h" +#include "ui/base/ime/chromeos/input_method_util.h" + +using ::testing::Contains; +using ::testing::Not; namespace chromeos { namespace settings { @@ -25,14 +40,18 @@ class TestAccessibilityHandler : public AccessibilityHandler { class AccessibilityHandlerTest : public InProcessBrowserTest { public: - AccessibilityHandlerTest() = default; + AccessibilityHandlerTest() + : mock_ime_engine_handler_( + std::make_unique<input_method::MockInputMethodEngine>()) {} AccessibilityHandlerTest(const AccessibilityHandlerTest&) = delete; AccessibilityHandlerTest& operator=(const AccessibilityHandlerTest&) = delete; ~AccessibilityHandlerTest() override = default; void SetUpCommandLine(base::CommandLine* command_line) override { - command_line->AppendSwitch( - ::switches::kEnableExperimentalAccessibilityDictationOffline); + scoped_feature_list_.InitWithFeatures( + {::features::kExperimentalAccessibilityDictationOffline, + features::kOnDeviceSpeechRecognition}, + {}); } void SetUpOnMainThread() override { @@ -43,7 +62,12 @@ class AccessibilityHandlerTest : public InProcessBrowserTest { base::RunLoop().RunUntilIdle(); } - void TearDownOnMainThread() override { handler_.reset(); } + void TearDownOnMainThread() override { + handler_->DisallowJavascript(); + handler_.reset(); + } + + size_t GetNumWebUICalls() { return web_ui_.call_data().size(); } void AssertWebUICalls(unsigned int num) { ASSERT_EQ(num, web_ui_.call_data().size()); @@ -55,14 +79,13 @@ class AccessibilityHandlerTest : public InProcessBrowserTest { for (auto it = web_ui_.call_data().rbegin(); it != web_ui_.call_data().rend(); ++it) { const content::TestWebUI::CallData* data = it->get(); - std::string listener; - std::string listener_argument; - data->arg1()->GetAsString(&listener); - if (!data->arg2()->GetAsString(&listener_argument)) { + std::string listener = data->arg1()->GetString(); + if (!data->arg2()->is_string()) { // Only look for listeners with a single string argument. Continue // silently if we find anything else. continue; } + std::string listener_argument = data->arg2()->GetString(); if (data->function_name() == "cr.webUIListenerCallback" && listener == expected_listener && @@ -74,7 +97,23 @@ class AccessibilityHandlerTest : public InProcessBrowserTest { return false; } - void AddSodaInstallerObserver() { handler_->MaybeAddSodaInstallerObserver(); } + bool GetWebUIListenerArgumentListValue(const std::string& expected_listener, + const base::ListValue** argument) { + for (auto it = web_ui_.call_data().rbegin(); + it != web_ui_.call_data().rend(); ++it) { + const content::TestWebUI::CallData* data = it->get(); + std::string listener; + data->arg1()->GetAsString(&listener); + if (data->function_name() == "cr.webUIListenerCallback" && + listener == expected_listener) { + if (!data->arg2()->GetAsList(argument)) + return false; + return true; + } + } + + return false; + } void OnSodaInstalled() { handler_->OnSodaInstalled(); } @@ -82,10 +121,15 @@ class AccessibilityHandlerTest : public InProcessBrowserTest { void OnSodaError() { handler_->OnSodaError(); } + void MaybeAddDictationLocales() { handler_->MaybeAddDictationLocales(); } + + std::unique_ptr<input_method::MockInputMethodEngine> mock_ime_engine_handler_; + private: std::unique_ptr<TestingProfile> profile_; std::unique_ptr<TestAccessibilityHandler> handler_; content::TestWebUI web_ui_; + base::test::ScopedFeatureList scoped_feature_list_; }; // A sanity check that ensures that |handler_| can be used to call into @@ -93,18 +137,18 @@ class AccessibilityHandlerTest : public InProcessBrowserTest { // This also verifies that the correct string is sent to the JavaScript end // of the web UI. IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaInstalledTestApi) { - AssertWebUICalls(0); + size_t num_calls = GetNumWebUICalls(); OnSodaInstalled(); - AssertWebUICalls(1); + AssertWebUICalls(num_calls + 1); ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument( "dictation-setting-subtitle-changed", "Speech files downloaded")); } // Verifies that the correct string is sent to the JavaScript end of the web UI. IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaProgressTestApi) { - AssertWebUICalls(0); + size_t num_calls = GetNumWebUICalls(); OnSodaProgress(50); - AssertWebUICalls(1); + AssertWebUICalls(num_calls + 1); ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument( "dictation-setting-subtitle-changed", "Downloading speech recognition files… 50%")); @@ -112,9 +156,9 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaProgressTestApi) { // Verifies that the correct string is sent to the JavaScript end of the web UI. IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaErrorTestApi) { - AssertWebUICalls(0); + size_t num_calls = GetNumWebUICalls(); OnSodaError(); - AssertWebUICalls(1); + AssertWebUICalls(num_calls + 1); ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument( "dictation-setting-subtitle-changed", "Can't download speech files. Dictation will continue to work by sending " @@ -124,13 +168,84 @@ IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaErrorTestApi) { // Ensures that AccessibilityHandler listens to SODA download state and fires // the correct listener when SODA is installed. IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, OnSodaInstalledNotification) { - AssertWebUICalls(0); - AddSodaInstallerObserver(); + size_t num_calls = GetNumWebUICalls(); speech::SodaInstaller::GetInstance()->NotifySodaInstalledForTesting(); - AssertWebUICalls(1); + AssertWebUICalls(num_calls + 1); ASSERT_TRUE(WasWebUIListenerCalledWithStringArgument( "dictation-setting-subtitle-changed", "Speech files downloaded")); } +IN_PROC_BROWSER_TEST_F(AccessibilityHandlerTest, DictationLocalesCalculation) { + input_method::InputMethodManager* ime_manager = + input_method::InputMethodManager::Get(); + + struct { + std::string application_locale; + std::vector<std::string> ime_locales; + std::string preferred_languages; + std::set<base::StringPiece> expected_recommended_prefixes; + } kTestCases[] = { + {"en-US", {}, "", {"en"}}, + {"en", {}, "", {"en"}}, + {"fr", {}, "", {"fr"}}, + {"en", {"en", "en-US"}, "", {"en"}}, + {"en", {"en", "en-US"}, "en", {"en"}}, + {"en", {"en", "es"}, "", {"en", "es"}}, + {"en", {"fr", "es", "fr-FR"}, "", {"en", "es", "fr"}}, + {"it-IT", {"ar", "is-IS", "uk"}, "", {"it", "ar", "is", "uk"}}, + {"en", {"fr", "es", "fr-FR"}, "en-US,it-IT", {"en", "es", "fr", "it"}}, + {"en", {}, "en-US,it-IT,uk", {"en", "it", "uk"}}, + }; + for (const auto& testcase : kTestCases) { + // Set application locale. + g_browser_process->SetApplicationLocale(testcase.application_locale); + + // Set up fake IMEs. + auto state = + ime_manager->CreateNewState(ProfileManager::GetActiveUserProfile()); + ime_manager->SetState(state); + input_method::InputMethodDescriptors imes; + for (auto& locale : testcase.ime_locales) { + std::string id = "fake-ime-extension-" + locale; + input_method::InputMethodDescriptor descriptor(id, locale, std::string(), + std::string(), {locale}, + false, GURL(), GURL()); + imes.push_back(descriptor); + } + ime_manager->GetInputMethodUtil()->ResetInputMethods(imes); + + for (auto& descriptor : imes) { + state->AddInputMethodExtension(descriptor.id(), {descriptor}, + mock_ime_engine_handler_.get()); + ASSERT_TRUE(state->EnableInputMethod(descriptor.id())); + } + + // Set up fake preferred languages. + browser()->profile()->GetPrefs()->SetString( + language::prefs::kPreferredLanguages, testcase.preferred_languages); + + MaybeAddDictationLocales(); + + const base::ListValue* argument; + ASSERT_TRUE( + GetWebUIListenerArgumentListValue("dictation-locales-set", &argument)); + for (auto& it : argument->GetList()) { + const base::DictionaryValue* dict = &base::Value::AsDictionaryValue(it); + base::StringPiece language_code = + language::SplitIntoMainAndTail(*(dict->FindStringPath("value"))) + .first; + // Only expect some locales to be recommended based on application and + // IME languages. + if (*(dict->FindBoolPath("recommended"))) { + EXPECT_THAT(testcase.expected_recommended_prefixes, + Contains(language_code)); + } else { + EXPECT_THAT(testcase.expected_recommended_prefixes, + Not(Contains(language_code))); + } + } + } +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc index 8322d5a31fc..daa0d7ac0e0 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc @@ -9,9 +9,9 @@ #include <string> #include <vector> +#include "ash/constants/ash_features.h" +#include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/accessibility_controller_enums.h" -#include "ash/public/cpp/ash_features.h" -#include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/tablet_mode.h" #include "base/command_line.h" #include "base/feature_list.h" @@ -334,11 +334,11 @@ bool IsLiveCaptionEnabled() { } bool IsMagnifierPanningImprovementsEnabled() { - return features::IsMagnifierPanningImprovementsEnabled(); + return ::features::IsMagnifierPanningImprovementsEnabled(); } bool IsMagnifierContinuousMouseFollowingModeSettingEnabled() { - return features::IsMagnifierContinuousMouseFollowingModeSettingEnabled(); + return ::features::IsMagnifierContinuousMouseFollowingModeSettingEnabled(); } bool IsSwitchAccessTextAllowed() { @@ -347,7 +347,7 @@ bool IsSwitchAccessTextAllowed() { } bool IsSwitchAccessPointScanningEnabled() { - return features::IsSwitchAccessPointScanningEnabled(); + return ::features::IsSwitchAccessPointScanningEnabled(); } bool IsSwitchAccessSetupGuideAllowed() { @@ -360,6 +360,10 @@ bool AreTabletNavigationButtonsAllowed() { ash::TabletMode::IsBoardTypeMarkedAsTabletCapable(); } +bool AreDictationLocalePrefsAllowed() { + return ::features::IsExperimentalAccessibilityDictationOfflineEnabled(); +} + } // namespace AccessibilitySection::AccessibilitySection( @@ -498,6 +502,38 @@ void AccessibilitySection::AddLoadTimeData( {"dictationDescription", IDS_SETTINGS_ACCESSIBILITY_DICTATION_DESCRIPTION}, {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL}, + {"dictationLocaleMenuLabel", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_MENU_LABEL}, + {"dictationLocaleSubLabelOffline", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_OFFLINE}, + {"dictationLocaleSubLabelNetwork", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LOCALE_SUB_LABEL_NETWORK}, + {"dictationChangeLanguageButton", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_CHANGE_LANGUAGE_BUTTON}, + {"dictationChangeLanguageDialogTitle", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_CHANGE_LANGUAGE_DIALOG_TITLE}, + {"dictationChangeLanguageDialogSearchHint", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_SEARCH_HINT}, + {"dictationChangeLanguageDialogSearchClear", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_SEARCH_CLEAR}, + {"dictationChangeLanguageDialogRecommended", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_RECOMMENDED}, + {"dictationChangeLanguageDialogAll", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_ALL}, + {"dictationChangeLanguageDialogNoResults", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_NO_RESULTS}, + {"dictationChangeLanguageDialogUpdateButton", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_UPDATE_BUTTON}, + {"dictationChangeLanguageDialogCancelButton", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_CANCEL_BUTTON}, + {"dictationLocaleOfflineSubtitle", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_OFFLINE_SUBTITLE}, + {"dictationChangeLanguageDialogOfflineDescription", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_OFFLINE_DESCRIPTION}, + {"dictationChangeLanguageDialogSelectedDescription", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_SELECTED_DESCRIPTION}, + {"dictationChangeLanguageDialogNotSelectedDescription", + IDS_SETTINGS_ACCESSIBILITY_DICTATION_LANGUAGE_DIALOG_NOT_SELECTED_DESCRIPTION}, {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL}, {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL}, {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL}, @@ -549,39 +585,61 @@ void AccessibilitySection::AddLoadTimeData( IDS_SETTINGS_SWITCH_ACCESS_BLUETOOTH_DEVICE_TYPE_LABEL}, {"switchAccessUnknownDeviceTypeLabel", IDS_SETTINGS_SWITCH_ACCESS_UNKNOWN_DEVICE_TYPE_LABEL}, - {"switchAccessActionAssignmentDialogAssignedIconLabel", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_ASSIGNED_ICON_LABEL}, - {"switchAccessActionAssignmentDialogAddAssignmentIconLabel", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_ADD_ASSIGNMENT_ICON_LABEL}, - {"switchAccessActionAssignmentDialogRemoveAssignmentIconLabel", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_REMOVE_ASSIGNMENT_ICON_LABEL}, - {"switchAccessActionAssignmentDialogErrorIconLabel", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_ERROR_ICON_LABEL}, + {"switchAccessActionAssignmentAssignedIconLabel", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_ASSIGNED_ICON_LABEL}, + {"switchAccessActionAssignmentAddAssignmentIconLabel", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_ADD_ASSIGNMENT_ICON_LABEL}, + {"switchAccessActionAssignmentRemoveAssignmentIconLabel", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_REMOVE_ASSIGNMENT_ICON_LABEL}, + {"switchAccessActionAssignmentErrorIconLabel", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_ERROR_ICON_LABEL}, {"switchAccessActionAssignmentDialogTitle", IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_TITLE}, - {"switchAccessActionAssignmentDialogWarnNotConfirmedPrompt", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WARN_NOT_CONFIRMED_PROMPT}, - {"switchAccessActionAssignmentDialogWarnAlreadyAssignedActionPrompt", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WARN_ALREADY_ASSIGNED_ACTION_PROMPT}, - {"switchAccessActionAssignmentDialogWarnUnrecognizedKeyPrompt", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WARN_UNRECOGNIZED_KEY_PROMPT}, - {"switchAccessActionAssignmentDialogWaitForKeyPromptNoSwitches", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WAIT_FOR_KEY_PROMPT_NO_SWITCHES}, - {"switchAccessActionAssignmentDialogWaitForKeyPromptAtLeastOneSwitch", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH}, - {"switchAccessActionAssignmentDialogWaitForConfirmationPrompt", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WAIT_FOR_CONFIRMATION_PROMPT}, - {"switchAccessActionAssignmentDialogWaitForConfirmationRemovalPrompt", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WAIT_FOR_CONFIRMATION_REMOVAL_PROMPT}, - {"switchAccessActionAssignmentDialogWarnCannotRemoveLastSelectSwitch", - IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_DIALOG_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH}, + {"switchAccessActionAssignmentWarnNotConfirmedPrompt", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_NOT_CONFIRMED_PROMPT}, + {"switchAccessActionAssignmentWarnAlreadyAssignedActionPrompt", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_ALREADY_ASSIGNED_ACTION_PROMPT}, + {"switchAccessActionAssignmentWarnUnrecognizedKeyPrompt", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_UNRECOGNIZED_KEY_PROMPT}, + {"switchAccessActionAssignmentWaitForKeyPromptNoSwitches", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES}, + {"switchAccessActionAssignmentWaitForKeyPromptNoSwitchesSetupGuide", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_NO_SWITCHES_SETUP_GUIDE}, + {"switchAccessActionAssignmentWaitForKeyPromptAtLeastOneSwitch", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_KEY_PROMPT_AT_LEAST_ONE_SWITCH}, + {"switchAccessActionAssignmentWaitForConfirmationPrompt", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_PROMPT}, + {"switchAccessActionAssignmentExitResponse", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_EXIT_RESPONSE}, + {"switchAccessActionAssignmentContinueResponse", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_CONTINUE_RESPONSE}, + {"switchAccessActionAssignmentTryAgainResponse", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_TRY_AGAIN_RESPONSE}, + {"switchAccessActionAssignmentWaitForConfirmationRemovalPrompt", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WAIT_FOR_CONFIRMATION_REMOVAL_PROMPT}, + {"switchAccessActionAssignmentWarnCannotRemoveLastSelectSwitch", + IDS_SETTINGS_SWITCH_ACCESS_ACTION_ASSIGNMENT_WARN_CANNOT_REMOVE_LAST_SELECT_SWITCH}, {"switchAndDeviceType", IDS_SETTINGS_SWITCH_AND_DEVICE_TYPE}, {"noSwitchesAssigned", IDS_SETTINGS_NO_SWITCHES_ASSIGNED}, + {"noSwitchesAssignedSetupGuide", + IDS_SETTINGS_NO_SWITCHES_ASSIGNED_SETUP_GUIDE}, {"switchAccessDialogExit", IDS_SETTINGS_SWITCH_ACCESS_DIALOG_EXIT}, + {"switchAccessSetupGuideWarningDialogTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_TITLE}, + {"switchAccessSetupGuideWarningDialogMessage", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_GUIDE_WARNING_DIALOG_MESSAGE}, {"switchAccessSetupIntroTitle", IDS_SETTINGS_SWITCH_ACCESS_SETUP_INTRO_TITLE}, {"switchAccessSetupIntroBody", IDS_SETTINGS_SWITCH_ACCESS_SETUP_INTRO_BODY}, + {"switchAccessSetupAssignSelectTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_SELECT_TITLE}, + {"switchAccessSetupAutoScanEnabledTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_TITLE}, + {"switchAccessSetupAutoScanEnabledExplanation", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_EXPLANATION}, + {"switchAccessSetupAutoScanEnabledDirections", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_ENABLED_DIRECTIONS}, {"switchAccessSetupChooseSwitchCountTitle", IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_SWITCH_COUNT_TITLE}, {"switchAccessSetupChoose1Switch", @@ -594,6 +652,29 @@ void AccessibilitySection::AddLoadTimeData( IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES}, {"switchAccessSetupChoose3SwitchesDescription", IDS_SETTINGS_SWITCH_ACCESS_SETUP_CHOOSE_3_SWITCHES_DESCRIPTION}, + {"switchAccessSetupAutoScanSpeedTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_SPEED_TITLE}, + {"switchAccessSetupAutoScanSpeedDescription", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_SPEED_DESCRIPTION}, + {"switchAccessSetupAssignNextTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_NEXT_TITLE}, + {"switchAccessSetupAssignPreviousTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_ASSIGN_PREVIOUS_TITLE}, + {"switchAccessSetupClosingTitle", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_TITLE}, + {"switchAccessSetupClosingAutoScanInstructions", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_AUTO_SCAN_INSTRUCTIONS}, + {"switchAccessSetupClosingManualScanInstructions", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_MANUAL_SCAN_INSTRUCTIONS}, + {"switchAccessSetupClosingInfo", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_CLOSING_INFO}, + {"switchAccessSetupAutoScanSlower", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_SLOWER}, + {"switchAccessSetupAutoScanFaster", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_AUTO_SCAN_FASTER}, + {"switchAccessSetupStartOver", + IDS_SETTINGS_SWITCH_ACCESS_SETUP_START_OVER}, + {"switchAccessSetupDone", IDS_SETTINGS_SWITCH_ACCESS_SETUP_DONE}, {"switchAccessSetupPairBluetooth", IDS_SETTINGS_SWITCH_ACCESS_SETUP_PAIR_BLUETOOTH}, {"switchAccessSetupNext", IDS_SETTINGS_SWITCH_ACCESS_SETUP_NEXT}, @@ -712,6 +793,9 @@ void AccessibilitySection::AddLoadTimeData( "isMagnifierContinuousMouseFollowingModeSettingEnabled", IsMagnifierContinuousMouseFollowingModeSettingEnabled()); + html_source->AddBoolean("areDictationLocalePrefsAllowed", + AreDictationLocalePrefsAllowed()); + ::settings::AddCaptionSubpageStrings(html_source); } @@ -853,7 +937,7 @@ void AccessibilitySection::UpdateTextToSpeechVoiceSearchTags() { content::TtsController* tts_controller = content::TtsController::GetInstance(); std::vector<content::VoiceData> voices; - tts_controller->GetVoices(profile(), &voices); + tts_controller->GetVoices(profile(), GURL(), &voices); if (!voices.empty()) { updater.AddSearchTags(GetTextToSpeechVoiceSearchConcepts()); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc index dad823ff3c6..5b2e6528fc7 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc @@ -164,7 +164,7 @@ class AccountBuilder { } // namespace AccountManagerUIHandler::AccountManagerUIHandler( - AccountManager* account_manager, + account_manager::AccountManager* account_manager, account_manager::AccountManagerFacade* account_manager_facade, signin::IdentityManager* identity_manager) : account_manager_(account_manager), @@ -298,11 +298,9 @@ base::ListValue AccountManagerUIHandler::GetSecondaryGaiaAccounts( continue; } - absl::optional<AccountInfo> maybe_account_info = - identity_manager_ - ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId( - account_key.id); - if (!maybe_account_info.has_value()) { + AccountInfo maybe_account_info = + identity_manager_->FindExtendedAccountInfoByGaiaId(account_key.id); + if (maybe_account_info.IsEmpty()) { // This account hasn't propagated to IdentityManager yet. When this // happens, `IdentityManager` will call `OnRefreshTokenUpdatedForAccount` // which will trigger another UI update. @@ -313,16 +311,16 @@ base::ListValue AccountManagerUIHandler::GetSecondaryGaiaAccounts( account.SetId(account_key.id) .SetAccountType(static_cast<int>(account_key.account_type)) .SetIsDeviceAccount(false) - .SetFullName(maybe_account_info->full_name) + .SetFullName(maybe_account_info.full_name) .SetEmail(stored_account.raw_email) .SetUnmigrated(!is_child_user && account_token_pair.second) .SetIsSignedIn(!identity_manager_ ->HasAccountWithRefreshTokenInPersistentErrorState( - maybe_account_info->account_id)); + maybe_account_info.account_id)); - if (!maybe_account_info->account_image.IsEmpty()) { - account.SetPic(webui::GetBitmapDataUrl( - maybe_account_info->account_image.AsBitmap())); + if (!maybe_account_info.account_image.IsEmpty()) { + account.SetPic( + webui::GetBitmapDataUrl(maybe_account_info.account_image.AsBitmap())); } else { gfx::ImageSkia default_icon = *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h index fd8ac4098b4..d7789b13f8b 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h @@ -7,7 +7,6 @@ #include <vector> -#include "ash/components/account_manager/account_manager.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" @@ -15,6 +14,7 @@ #include "components/account_id/account_id.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" +#include "components/account_manager_core/chromeos/account_manager.h" #include "components/signin/public/identity_manager/identity_manager.h" class Profile; @@ -27,10 +27,11 @@ class AccountManagerUIHandler public account_manager::AccountManagerFacade::Observer, public signin::IdentityManager::Observer { public: - // Accepts non-owning pointers to |AccountManager|, |AccountManagerFacade| - // and |IdentityManager|. Both of these must outlive |this| instance. + // Accepts non-owning pointers to |account_manager::AccountManager|, + // |AccountManagerFacade| and |IdentityManager|. Both of these must outlive + // |this| instance. AccountManagerUIHandler( - AccountManager* account_manager, + account_manager::AccountManager* account_manager, account_manager::AccountManagerFacade* account_manager_facade, signin::IdentityManager* identity_manager); ~AccountManagerUIHandler() override; @@ -41,8 +42,8 @@ class AccountManagerUIHandler void OnJavascriptDisallowed() override; // |AccountManagerFacade::Observer| overrides. - // |AccountManager| is considered to be the source of truth for account - // information. + // |account_manager::AccountManager| is considered to be the source of truth + // for account information. void OnAccountUpserted(const ::account_manager::Account& account) override; void OnAccountRemoved(const ::account_manager::Account& account) override; @@ -76,7 +77,8 @@ class AccountManagerUIHandler // WebUI "showWelcomeDialogIfRequired" message callback. void HandleShowWelcomeDialogIfRequired(const base::ListValue* args); - // |AccountManager::CheckDummyGaiaTokenForAllAccounts| callback. + // |account_manager::AccountManager::CheckDummyGaiaTokenForAllAccounts| + // callback. void OnCheckDummyGaiaTokenForAllAccounts( base::Value callback_id, const std::vector<std::pair<::account_manager::Account, bool>>& @@ -100,8 +102,8 @@ class AccountManagerUIHandler Profile* profile_ = nullptr; - // A non-owning pointer to |AccountManager|. - AccountManager* const account_manager_; + // A non-owning pointer to |account_manager::AccountManager|. + account_manager::AccountManager* const account_manager_; // A non-owning pointer to |AccountManagerFacade|. account_manager::AccountManagerFacade* const account_manager_facade_; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc index f232e671d57..84d27e9c020 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler_browsertest.cc @@ -7,7 +7,6 @@ #include <memory> #include <ostream> -#include "ash/components/account_manager/account_manager.h" #include "ash/components/account_manager/account_manager_factory.h" #include "base/test/bind.h" #include "chrome/browser/account_manager_facade_factory.h" @@ -20,6 +19,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/testing_profile.h" #include "components/account_manager_core/account_manager_facade.h" +#include "components/account_manager_core/chromeos/account_manager.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/user_manager/scoped_user_manager.h" @@ -30,7 +30,7 @@ namespace { -using ::ash::AccountManager; +using ::account_manager::AccountManager; constexpr char kGetAccountsMessage[] = "getAccounts"; constexpr char kHandleFunctionName[] = "handleFunctionName"; @@ -267,9 +267,10 @@ IN_PROC_BROWSER_TEST_P(AccountManagerUIHandlerTest, ASSERT_EQ(1UL, account_manager_accounts.size()); // Call "getAccounts". - base::ListValue args; - args.AppendString(kHandleFunctionName); - web_ui()->HandleReceivedMessage(kGetAccountsMessage, &args); + base::Value args(base::Value::Type::LIST); + args.Append(kHandleFunctionName); + web_ui()->HandleReceivedMessage(kGetAccountsMessage, + &base::Value::AsListValue(args)); const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data.function_name()); @@ -315,9 +316,10 @@ IN_PROC_BROWSER_TEST_P(AccountManagerUIHandlerTest, base::RunLoop().RunUntilIdle(); // Call "getAccounts". - base::ListValue args; - args.AppendString(kHandleFunctionName); - web_ui()->HandleReceivedMessage(kGetAccountsMessage, &args); + base::Value args(base::Value::Type::LIST); + args.Append(kHandleFunctionName); + web_ui()->HandleReceivedMessage(kGetAccountsMessage, + &base::Value::AsListValue(args)); const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data.function_name()); @@ -371,16 +373,15 @@ IN_PROC_BROWSER_TEST_P(AccountManagerUIHandlerTest, EXPECT_EQ(expected_account.raw_email, ValueOrEmpty(account.FindStringKey("email"))); - absl::optional<AccountInfo> expected_account_info = - identity_manager() - ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId( - expected_account.key.id); - EXPECT_TRUE(expected_account_info.has_value()); - EXPECT_EQ(expected_account_info->full_name, + AccountInfo expected_account_info = + identity_manager()->FindExtendedAccountInfoByGaiaId( + expected_account.key.id); + EXPECT_FALSE(expected_account_info.IsEmpty()); + EXPECT_EQ(expected_account_info.full_name, ValueOrEmpty(account.FindStringKey("fullName"))); EXPECT_EQ( !identity_manager()->HasAccountWithRefreshTokenInPersistentErrorState( - expected_account_info->account_id), + expected_account_info.account_id), account.FindBoolKey("isSignedIn").value()); } } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc index 8f8daf6de1f..1d154071f40 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.cc @@ -19,7 +19,6 @@ #include "base/callback.h" #include "base/logging.h" #include "base/memory/ref_counted_memory.h" -#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/values.h" @@ -182,7 +181,7 @@ void AmbientModeHandler::OnEnabledPrefChanged() { void AmbientModeHandler::HandleRequestSettings(const base::ListValue* args) { CHECK(args); - CHECK(args->empty()); + CHECK(args->GetList().empty()); AllowJavascript(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h b/chromium/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h index a87e72e31b2..fbd61389666 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/app_management/app_management_uma.h @@ -23,7 +23,8 @@ enum class AppManagementEntryPoint { kAppManagementMainViewPluginVm = 10, kDBusServicePluginVm = 11, kNotificationPluginVm = 12, - kMaxValue = kNotificationPluginVm, + kAppManagementMainViewBorealis = 13, + kMaxValue = kAppManagementMainViewBorealis, }; #endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_APP_MANAGEMENT_APP_MANAGEMENT_UMA_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.cc index 4c280068a1c..20524cb4641 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.cc @@ -5,11 +5,11 @@ #include "chrome/browser/ui/webui/settings/chromeos/apps_section.h" #include "ash/constants/ash_features.h" -#include "ash/public/cpp/ash_features.h" #include "base/feature_list.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/ash/arc/arc_util.h" +#include "chrome/browser/ash/full_restore/full_restore_service_factory.h" #include "chrome/browser/ash/plugin_vm/plugin_vm_features.h" #include "chrome/browser/ash/plugin_vm/plugin_vm_pref_names.h" #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h" @@ -23,6 +23,7 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/os_settings_resources.h" #include "components/arc/arc_prefs.h" +#include "components/full_restore/features.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" @@ -52,6 +53,44 @@ const std::vector<SearchConcept>& GetAppsSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetAppNotificationsSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_APP_NOTIFICATIONS, + mojom::kAppNotificationsSubpagePath, + mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kAppNotifications}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetTurnOffAppNotificationSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags( + {{IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_OFF, + mojom::kAppNotificationsSubpagePath, + mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDoNotDisturbOnOff}, + {IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_OFF_ALT1, + SearchConcept::kAltTagEnd}}}); + return *tags; +} + +const std::vector<SearchConcept>& GetTurnOnAppNotificationSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags( + {{IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_ON, + mojom::kAppNotificationsSubpagePath, + mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDoNotDisturbOnOff}, + {IDS_OS_SETTINGS_TAG_DO_NOT_DISTURB_TURN_ON_ALT1, + SearchConcept::kAltTagEnd}}}); + return *tags; +} + const std::vector<SearchConcept>& GetAndroidPlayStoreSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_PLAY_STORE, @@ -114,18 +153,13 @@ const std::vector<SearchConcept>& GetAndroidPlayStoreDisabledSearchConcepts() { const std::vector<SearchConcept>& GetOnStartupSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_ON_STARTUP, - mojom::kOnStartupSubpagePath, - mojom::SearchResultIcon::kStartup, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kOnStartup}}, {IDS_OS_SETTINGS_TAG_RESTORE_APPS_AND_PAGES, - mojom::kOnStartupSubpagePath, + mojom::kAppsSectionPath, mojom::SearchResultIcon::kStartup, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kRestoreAppsAndPages}}, + {.setting = mojom::Setting::kRestoreAppsAndPages}, + {IDS_OS_SETTINGS_TAG_ON_STARTUP, SearchConcept::kAltTagEnd}}, }); return *tags; } @@ -137,6 +171,15 @@ void AddAppManagementStrings(content::WebUIDataSource* html_source) { {"appManagementCameraPermissionLabel", IDS_APP_MANAGEMENT_CAMERA}, {"appManagementContactsPermissionLabel", IDS_APP_MANAGEMENT_CONTACTS}, {"appManagementLocationPermissionLabel", IDS_APP_MANAGEMENT_LOCATION}, + {"appManagementIntentSharingOpenBrowserLabel", + IDS_APP_MANAGEMENT_INTENT_SHARING_BROWSER_OPEN}, + {"appManagementIntentSharingLabel", IDS_APP_MANAGEMENT_INTENT_SHARING}, + {"appManagementIntentSharingOpenAppLabel", + IDS_APP_MANAGEMENT_INTENT_SHARING_APP_OPEN}, + {"appManagementIntentSharingTabExplanation", + IDS_APP_MANAGEMENT_INTENT_SHARING_TAB_EXPLANATION}, + {"appManagementIntentSharingTabLearnMore", + IDS_APP_MANAGEMENT_INTENT_SHARING_TAB_LEARN_MORE}, {"appManagementMicrophonePermissionLabel", IDS_APP_MANAGEMENT_MICROPHONE}, {"appManagementMoreSettingsLabel", IDS_APP_MANAGEMENT_MORE_SETTINGS}, {"appManagementNoAppsFound", IDS_APP_MANAGEMENT_NO_APPS_FOUND}, @@ -145,6 +188,10 @@ void AddAppManagementStrings(content::WebUIDataSource* html_source) { {"appManagementNotificationsLabel", IDS_APP_MANAGEMENT_NOTIFICATIONS}, {"appManagementPermissionsLabel", IDS_APP_MANAGEMENT_PERMISSIONS}, {"appManagementPinToShelfLabel", IDS_APP_MANAGEMENT_PIN_TO_SHELF}, + {"appManagementPresetWindowSizesLabel", + IDS_APP_MANAGEMENT_PRESET_WINDOW_SIZES}, + {"appManagementPresetWindowSizesText", + IDS_APP_MANAGEMENT_PRESET_WINDOW_SIZES_TEXT}, {"appManagementPrintingPermissionLabel", IDS_APP_MANAGEMENT_PRINTING}, {"appManagementSearchPrompt", IDS_APP_MANAGEMENT_SEARCH_PROMPT}, {"appManagementStoragePermissionLabel", IDS_APP_MANAGEMENT_STORAGE}, @@ -183,6 +230,16 @@ void AddGuestOsStrings(content::WebUIDataSource* html_source) { html_source->AddLocalizedStrings(kLocalizedStrings); } +void AddBorealisStrings(content::WebUIDataSource* html_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"borealisMainPermissionText", + IDS_SETTINGS_APPS_BOREALIS_MAIN_PERMISSION_TEXT}, + {"borealisAppPermissionText", + IDS_SETTINGS_APPS_BOREALIS_APP_PERMISSION_TEXT}, + }; + html_source->AddLocalizedStrings(kLocalizedStrings); +} + bool ShowPluginVm(const Profile* profile, const PrefService& pref_service) { // Even if not allowed, we still want to show Plugin VM if the VM image is on // disk, so that users are still able to delete the image at will. @@ -190,23 +247,9 @@ bool ShowPluginVm(const Profile* profile, const PrefService& pref_service) { pref_service.GetBoolean(plugin_vm::prefs::kPluginVmImageExists); } -bool ShouldShowStartup() { - return ash::features::IsFullRestoreEnabled(); -} - -void AddOnStartupTimeData(content::WebUIDataSource* html_source) { - static constexpr webui::LocalizedString kLocalizedStrings[] = { - {"onStartupPageTitle", IDS_OS_SETTINGS_ON_STARTUP}, - {"onStartupRadioGroundTitle", - IDS_OS_SETTINGS_ON_STARTUP_RADIO_GROUP_TITLE}, - {"onStartupAlways", IDS_OS_SETTINGS_ON_STARTUP_ALWAYS}, - {"onStartupAskEveryTime", IDS_OS_SETTINGS_ON_STARTUP_ASK_EVERY_TIME}, - {"onStartupDoNotRestore", IDS_OS_SETTINGS_ON_STARTUP_DO_NOT_RESTORE}, - }; - - html_source->AddLocalizedStrings(kLocalizedStrings); - - html_source->AddBoolean("showStartup", ShouldShowStartup()); +bool ShouldShowStartup(const Profile* profile) { + return full_restore::FullRestoreServiceFactory:: + IsFullRestoreAvailableForProfile(profile); } } // namespace @@ -223,6 +266,13 @@ AppsSection::AppsSection(Profile* profile, SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.AddSearchTags(GetAppsSearchConcepts()); + // Note: The MessageCenterAsh check here is added for unit testing purposes + // otherwise check statements are not needed in production. + if (ash::MessageCenterAsh::Get()) { + ash::MessageCenterAsh::Get()->AddObserver(this); + OnQuietModeChanged(ash::MessageCenterAsh::Get()->IsQuietMode()); + } + if (arc::IsArcAllowedForProfile(profile)) { pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add( @@ -236,11 +286,18 @@ AppsSection::AppsSection(Profile* profile, UpdateAndroidSearchTags(); } - if (ShouldShowStartup()) + if (ShouldShowStartup(profile)) updater.AddSearchTags(GetOnStartupSearchConcepts()); } AppsSection::~AppsSection() { + // TODO(crbug.com/1237465): observer is never removed because ash::Shell is + // destroyed first. + // Note: The MessageCenterAsh check is also added for unit testing purposes. + if (ash::MessageCenterAsh::Get()) { + ash::MessageCenterAsh::Get()->RemoveObserver(this); + } + if (arc::IsArcAllowedForProfile(profile())) { if (arc_app_list_prefs_) arc_app_list_prefs_->RemoveObserver(this); @@ -251,9 +308,19 @@ void AppsSection::AddLoadTimeData(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"appsPageTitle", IDS_SETTINGS_APPS_TITLE}, {"appManagementTitle", IDS_SETTINGS_APPS_LINK_TEXT}, + {"appNotificationsTitle", IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TEXT}, + {"doNotDisturbToggleTitle", + IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_TITLE}, + {"doNotDisturbToggleDescription", + IDS_SETTINGS_APP_NOTIFICATIONS_DO_NOT_DISTURB_TOGGLE_DESCRIPTION}, + {"appNotificationsLinkToBrowserSettingsDescription", + IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TO_BROWSER_SETTINGS_DESCRIPTION}, }; html_source->AddLocalizedStrings(kLocalizedStrings); + html_source->AddString("appNotificationsBrowserSettingsURL", + chrome::kAppNotificationsBrowserSettingsURL); + // We have 2 variants of Android apps settings. Default case, when the Play // Store app exists we show expandable section that allows as to // enable/disable the Play Store and link to Android settings which is @@ -265,10 +332,16 @@ void AppsSection::AddLoadTimeData(content::WebUIDataSource* html_source) { arc::IsArcAllowedForProfile(profile())); html_source->AddBoolean("havePlayStoreApp", arc::IsPlayStoreAvailable()); + html_source->AddBoolean( + "showOsSettingsAppNotificationsRow", + base::FeatureList::IsEnabled( + chromeos::features::kOsSettingsAppNotificationsPage)); + AddAppManagementStrings(html_source); AddGuestOsStrings(html_source); AddAndroidAppStrings(html_source); AddPluginVmLoadTimeData(html_source); + AddBorealisStrings(html_source); AddOnStartupTimeData(html_source); } @@ -306,6 +379,7 @@ bool AppsSection::LogMetric(mojom::Setting setting, base::Value& value) const { void AppsSection::RegisterHierarchy(HierarchyGenerator* generator) const { generator->RegisterTopLevelSetting(mojom::Setting::kTurnOnPlayStore); + generator->RegisterTopLevelSetting(mojom::Setting::kRestoreAppsAndPages); // Manage apps. generator->RegisterTopLevelSubpage(IDS_SETTINGS_APPS_LINK_TEXT, @@ -313,6 +387,15 @@ void AppsSection::RegisterHierarchy(HierarchyGenerator* generator) const { mojom::SearchResultIcon::kAppsGrid, mojom::SearchResultDefaultRank::kMedium, mojom::kAppManagementSubpagePath); + // App Notifications + generator->RegisterTopLevelSubpage(IDS_SETTINGS_APP_NOTIFICATIONS_LINK_TEXT, + mojom::Subpage::kAppNotifications, + mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, + mojom::kAppNotificationsSubpagePath); + + generator->RegisterNestedSetting(mojom::Setting::kDoNotDisturbOnOff, + mojom::Subpage::kAppNotifications); // Note: The subpage name in the UI is updated dynamically based on the app // being shown, but we use a generic "App details" string here. generator->RegisterNestedSubpage( @@ -345,17 +428,6 @@ void AppsSection::RegisterHierarchy(HierarchyGenerator* generator) const { kGooglePlayStoreSettings, generator); generator->RegisterTopLevelAltSetting( mojom::Setting::kManageAndroidPreferences); - - // On startup - generator->RegisterTopLevelSubpage( - IDS_OS_SETTINGS_TAG_ON_STARTUP, mojom::Subpage::kOnStartup, - mojom::SearchResultIcon::kStartup, - mojom::SearchResultDefaultRank::kMedium, mojom::kOnStartupSubpagePath); - static constexpr mojom::Setting kOnStartupSettings[] = { - mojom::Setting::kRestoreAppsAndPages, - }; - RegisterNestedSettingBulk(mojom::Subpage::kOnStartup, kOnStartupSettings, - generator); } void AppsSection::OnAppRegistered(const std::string& app_id, @@ -414,14 +486,19 @@ void AppsSection::AddPluginVmLoadTimeData( l10n_util::GetStringFUTF16( IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_LOCATE, base::UTF8ToUTF16(plugin_vm::kChromeOSBaseDirectoryDisplayText))); - html_source->AddBoolean( - "showPluginVmCameraPermissions", - base::FeatureList::IsEnabled( - chromeos::features::kPluginVmShowCameraPermissions)); - html_source->AddBoolean( - "showPluginVmMicrophonePermissions", - base::FeatureList::IsEnabled( - chromeos::features::kPluginVmShowMicrophonePermissions)); +} + +void AppsSection::AddOnStartupTimeData(content::WebUIDataSource* html_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"onStartupTitle", IDS_OS_SETTINGS_ON_STARTUP_TITLE}, + {"onStartupAlways", IDS_OS_SETTINGS_ON_STARTUP_ALWAYS}, + {"onStartupAskEveryTime", IDS_OS_SETTINGS_ON_STARTUP_ASK_EVERY_TIME}, + {"onStartupDoNotRestore", IDS_OS_SETTINGS_ON_STARTUP_DO_NOT_RESTORE}, + }; + + html_source->AddLocalizedStrings(kLocalizedStrings); + + html_source->AddBoolean("showStartup", ShouldShowStartup(profile())); } void AppsSection::UpdateAndroidSearchTags() { @@ -450,5 +527,25 @@ void AppsSection::UpdateAndroidSearchTags() { } } +void AppsSection::OnQuietModeChanged(bool in_quiet_mode) { + if (!features::IsAppNotificationsPageEnabled()) { + return; + } + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + updater.RemoveSearchTags(GetTurnOnAppNotificationSearchConcepts()); + updater.RemoveSearchTags(GetTurnOffAppNotificationSearchConcepts()); + updater.RemoveSearchTags(GetAppNotificationsSearchConcepts()); + + updater.AddSearchTags(GetAppNotificationsSearchConcepts()); + + if (!ash::MessageCenterAsh::Get()->IsQuietMode()) { + updater.AddSearchTags(GetTurnOnAppNotificationSearchConcepts()); + return; + } + + updater.AddSearchTags(GetTurnOffAppNotificationSearchConcepts()); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.h index ce3c0304f1f..b2f2911d3b0 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_APPS_SECTION_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_APPS_SECTION_H_ +#include "ash/public/cpp/message_center_ash.h" #include "base/values.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" @@ -23,7 +24,9 @@ namespace settings { class SearchTagRegistry; // Provides UI strings and search tags for Apps settings. -class AppsSection : public OsSettingsSection, public ArcAppListPrefs::Observer { +class AppsSection : public OsSettingsSection, + public ArcAppListPrefs::Observer, + public ash::MessageCenterAsh::Observer { public: AppsSection(Profile* profile, SearchTagRegistry* search_tag_registry, @@ -47,8 +50,12 @@ class AppsSection : public OsSettingsSection, public ArcAppListPrefs::Observer { void OnAppRegistered(const std::string& app_id, const ArcAppListPrefs::AppInfo& app_info) override; + // MessageCenterAsh::Observer override: + void OnQuietModeChanged(bool in_quiet_mode) override; + void AddAndroidAppStrings(content::WebUIDataSource* html_source); void AddPluginVmLoadTimeData(content::WebUIDataSource* html_source); + void AddOnStartupTimeData(content::WebUIDataSource* html_source); void UpdateAndroidSearchTags(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc new file mode 100644 index 00000000000..0e948c16237 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc @@ -0,0 +1,74 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h" + +#include "base/bind.h" +#include "base/values.h" +#include "chromeos/network/network_event_log.h" +#include "content/public/browser/web_ui.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" + +namespace chromeos { +namespace { + +const char kIsDeviceBlockedByPolicy[] = "isDeviceBlockedByPolicy"; + +} // namespace + +namespace settings { + +BluetoothHandler::BluetoothHandler() { + device::BluetoothAdapterFactory::Get()->GetAdapter( + base::BindOnce(&BluetoothHandler::BluetoothDeviceAdapterReady, + weak_ptr_factory_.GetWeakPtr())); +} + +BluetoothHandler::~BluetoothHandler() {} + +void BluetoothHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + kIsDeviceBlockedByPolicy, + base::BindRepeating(&BluetoothHandler::HandleIsDeviceBlockedByPolicy, + base::Unretained(this))); +} + +void BluetoothHandler::OnJavascriptAllowed() {} + +void BluetoothHandler::OnJavascriptDisallowed() {} + +void BluetoothHandler::BluetoothDeviceAdapterReady( + scoped_refptr<device::BluetoothAdapter> adapter) { + DCHECK(adapter); + bluetooth_adapter_ = std::move(adapter); +} + +void BluetoothHandler::HandleIsDeviceBlockedByPolicy( + const base::ListValue* args) { + AllowJavascript(); + std::string callback_id; + std::string address; + CHECK_EQ(2U, args->GetSize()); + CHECK(args->GetString(0, &callback_id)); + CHECK(args->GetString(1, &address)); + + if (!bluetooth_adapter_) { + BLUETOOTH_LOG(EVENT) << "Bluetooth adapter not available."; + ResolveJavascriptCallback(base::Value(callback_id), base::Value(false)); + return; + } + + device::BluetoothDevice* device = bluetooth_adapter_->GetDevice(address); + if (!device) { + BLUETOOTH_LOG(EVENT) << "No device found for address."; + ResolveJavascriptCallback(base::Value(callback_id), base::Value(false)); + return; + } + + ResolveJavascriptCallback(base::Value(callback_id), + base::Value(device->IsBlockedByPolicy())); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h new file mode 100644 index 00000000000..b4d0ab718da --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h @@ -0,0 +1,45 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_BLUETOOTH_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_BLUETOOTH_HANDLER_H_ + +#include "base/macros.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +#include "device/bluetooth/bluetooth_adapter.h" + +namespace chromeos { +namespace settings { + +// Chrome OS Bluetooth subpage UI handler. +class BluetoothHandler : public ::settings::SettingsPageUIHandler { + public: + BluetoothHandler(); + BluetoothHandler(const BluetoothHandler&) = delete; + BluetoothHandler& operator=(const BluetoothHandler&) = delete; + ~BluetoothHandler() override; + + // SettingsPageUIHandler implementation. + void RegisterMessages() override; + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + + private: + friend class BluetoothHandlerTest; + + void BluetoothDeviceAdapterReady( + scoped_refptr<device::BluetoothAdapter> adapter); + + void HandleIsDeviceBlockedByPolicy(const base::ListValue* args); + + scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; + base::WeakPtrFactory<BluetoothHandler> weak_ptr_factory_{this}; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_BLUETOOTH_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc new file mode 100644 index 00000000000..ebeddf86dc9 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc @@ -0,0 +1,97 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h" + +#include "base/macros.h" +#include "content/public/test/test_web_ui.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/test/mock_bluetooth_adapter.h" +#include "device/bluetooth/test/mock_bluetooth_device.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace settings { + +namespace { + +const char kDeviceAddress[] = "12:34:56:78:90:12"; + +class TestBluetoothHandler : public BluetoothHandler { + public: + TestBluetoothHandler() : BluetoothHandler() {} + ~TestBluetoothHandler() override = default; + + // Make public for testing. + using BluetoothHandler::AllowJavascript; + using BluetoothHandler::RegisterMessages; + using BluetoothHandler::set_web_ui; +}; + +} // namespace + +class BluetoothHandlerTest : public testing::Test { + protected: + BluetoothHandlerTest() {} + BluetoothHandlerTest(const BluetoothHandlerTest&) = delete; + BluetoothHandlerTest& operator=(const BluetoothHandlerTest&) = delete; + ~BluetoothHandlerTest() override = default; + + // testing::Test: + void SetUp() override { + mock_adapter_ = new testing::NiceMock<device::MockBluetoothAdapter>(); + device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_); + mock_device_ = + std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>( + /*adapter=*/nullptr, /*bluetooth_class=*/0, + /*name=*/"Bluetooth 2.0 Mouse", kDeviceAddress, /*paired=*/false, + /*connected=*/false); + EXPECT_CALL(*mock_adapter_, GetDevice(testing::_)) + .WillRepeatedly(testing::Return(mock_device_.get())); + + test_web_ui_ = std::make_unique<content::TestWebUI>(); + handler_ = std::make_unique<TestBluetoothHandler>(); + handler_->set_web_ui(test_web_ui_.get()); + handler_->RegisterMessages(); + } + + content::TestWebUI* test_web_ui() { return test_web_ui_.get(); } + + const content::TestWebUI::CallData& CallDataAtIndex(size_t index) { + return *test_web_ui_->call_data()[index]; + } + + std::unique_ptr<device::MockBluetoothDevice> mock_device_; + + private: + scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>> mock_adapter_; + std::unique_ptr<content::TestWebUI> test_web_ui_; + std::unique_ptr<TestBluetoothHandler> handler_; +}; + +TEST_F(BluetoothHandlerTest, GetIsDeviceBlockedByPolicy) { + EXPECT_CALL(*mock_device_, IsBlockedByPolicy()) + .WillOnce(testing::Return(true)); + + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + base::Value args(base::Value::Type::LIST); + args.Append("handlerFunctionName"); + args.Append(kDeviceAddress); + test_web_ui()->HandleReceivedMessage("isDeviceBlockedByPolicy", + &base::Value::AsListValue(args)); + + ASSERT_EQ(call_data_count_before_call + 1u, + test_web_ui()->call_data().size()); + const content::TestWebUI::CallData& call_data = + CallDataAtIndex(call_data_count_before_call); + EXPECT_EQ("cr.webUIResponse", call_data.function_name()); + EXPECT_EQ("handlerFunctionName", call_data.arg1()->GetString()); + ASSERT_TRUE(call_data.arg2()->GetBool()); + EXPECT_TRUE(call_data.arg3()->GetBool()); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc index 5cb7ace2c8f..5dc33101659 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc @@ -4,10 +4,12 @@ #include "chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h" +#include "ash/constants/ash_features.h" #include "base/bind.h" #include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" -#include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h" +#include "chrome/browser/ui/webui/chromeos/bluetooth_shared_load_time_data_provider.h" +#include "chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom.h" @@ -16,11 +18,14 @@ #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/strings/grit/chromeos_strings.h" #include "content/public/browser/web_ui_data_source.h" #include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/chromeos/bluetooth_utils.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" +#include "device/bluetooth/floss/floss_dbus_manager.h" +#include "device/bluetooth/floss/floss_features.h" #include "device/bluetooth/strings/grit/bluetooth_strings.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -117,13 +122,45 @@ const std::vector<SearchConcept>& GetBluetoothPairedSearchConcepts() { return *tags; } +std::vector<mojom::Setting> GetBluetoothDevicesSubpageSettings() { + std::vector<mojom::Setting> bluetooth_devices_settings{ + mojom::Setting::kBluetoothOnOff, mojom::Setting::kBluetoothPairDevice}; + + if (!chromeos::features::IsBluetoothRevampEnabled()) { + bluetooth_devices_settings.insert( + bluetooth_devices_settings.end(), + {mojom::Setting::kBluetoothConnectToDevice, + mojom::Setting::kBluetoothDisconnectFromDevice, + mojom::Setting::kBluetoothUnpairDevice}); + } + + return bluetooth_devices_settings; +} + +std::vector<mojom::Setting> GetBluetoothDeviceDetailSubpageSettings() { + if (!chromeos::features::IsBluetoothRevampEnabled()) + return std::vector<mojom::Setting>{}; + + return std::vector<mojom::Setting>{ + mojom::Setting::kBluetoothConnectToDevice, + mojom::Setting::kBluetoothDisconnectFromDevice, + mojom::Setting::kBluetoothUnpairDevice}; +} + } // namespace BluetoothSection::BluetoothSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { + bool is_initialized = false; + if (base::FeatureList::IsEnabled(floss::features::kFlossEnabled)) { + is_initialized = floss::FlossDBusManager::IsInitialized(); + } else { + is_initialized = bluez::BluezDBusManager::IsInitialized(); + } + // Note: May be uninitialized in tests. - if (bluez::BluezDBusManager::IsInitialized()) { + if (is_initialized) { device::BluetoothAdapterFactory::Get()->GetAdapter( base::BindOnce(&BluetoothSection::OnFetchBluetoothAdapter, weak_ptr_factory_.GetWeakPtr())); @@ -144,6 +181,7 @@ void BluetoothSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"bluetoothDeviceListPaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_PAIRED}, {"bluetoothDeviceListUnpaired", IDS_SETTINGS_BLUETOOTH_DEVICE_LIST_UNPAIRED}, + {"bluetoothPairNewDevice", IDS_SETTINGS_BLUETOOTH_PAIR_NEW_DEVICES}, {"bluetoothConnect", IDS_SETTINGS_BLUETOOTH_CONNECT}, {"bluetoothDisconnect", IDS_SETTINGS_BLUETOOTH_DISCONNECT}, {"bluetoothToggleA11yLabel", @@ -154,9 +192,22 @@ void BluetoothSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"bluetoothNoDevicesFound", IDS_SETTINGS_BLUETOOTH_NO_DEVICES_FOUND}, {"bluetoothNotConnected", IDS_SETTINGS_BLUETOOTH_NOT_CONNECTED}, {"bluetoothPageTitle", IDS_SETTINGS_BLUETOOTH}, + {"bluetoothSummaryPageConnectedA11yOneDevice", + IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_CONNECTED_A11Y_ONE_DEVICE}, + {"bluetoothSummaryPageConnectedA11yTwoDevices", + IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_CONNECTED_A11Y_TWO_DEVICES}, + {"bluetoothSummaryPageConnectedA11yTwoOrMoreDevices", + IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_CONNECTED_A11Y_TWO_OR_MORE_DEVICES}, + {"bluetoothSummaryPageTwoOrMoreDevicesDescription", + IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_TWO_OR_MORE_DEVICES_DESCRIPTION}, + {"bluetoothSummaryPageTwoDevicesDescription", + IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_TWO_DEVICES_DESCRIPTION}, + {"bluetoothSummaryPageOff", IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_OFF}, + {"bluetoothSummaryPageOn", IDS_SETTINGS_BLUETOOTH_SUMMARY_PAGE_ON}, {"bluetoothPairDevicePageTitle", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE}, {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE}, + {"bluetoothManaged", IDS_SETTINGS_BLUETOOTH_MANAGED}, {"bluetoothPrimaryUserControlled", IDS_SETTINGS_BLUETOOTH_PRIMARY_USER_CONTROLLED}, {"bluetoothDeviceWithConnectionStatus", @@ -189,9 +240,17 @@ void BluetoothSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_KEYBOARD_MOUSE_COMBO}, {"bluetoothDeviceType_unknown", IDS_BLUETOOTH_ACCESSIBILITY_DEVICE_TYPE_UNKNOWN}, + {"bluetoothDeviceListCurrentlyConnected", + IDS_BLUETOOTH_DEVICE_LIST_CURRENTLY_CONNECTED}, + {"bluetoothDeviceListPreviouslyConnected", + IDS_BLUETOOTH_DEVICE_LIST_PREVIOUSLY_CONNECTED}, }; html_source->AddLocalizedStrings(kLocalizedStrings); - chromeos::bluetooth_dialog::AddLocalizedStrings(html_source); + chromeos::bluetooth::AddLoadTimeData(html_source); +} + +void BluetoothSection::AddHandlers(content::WebUI* web_ui) { + web_ui->AddMessageHandler(std::make_unique<BluetoothHandler>()); } int BluetoothSection::GetSectionNameMessageId() const { @@ -229,16 +288,20 @@ void BluetoothSection::RegisterHierarchy(HierarchyGenerator* generator) const { mojom::SearchResultIcon::kBluetooth, mojom::SearchResultDefaultRank::kMedium, mojom::kBluetoothDevicesSubpagePath); - static constexpr mojom::Setting kBluetoothDevicesSettings[] = { - mojom::Setting::kBluetoothOnOff, - mojom::Setting::kBluetoothConnectToDevice, - mojom::Setting::kBluetoothDisconnectFromDevice, - mojom::Setting::kBluetoothPairDevice, - mojom::Setting::kBluetoothUnpairDevice, - }; + RegisterNestedSettingBulk(mojom::Subpage::kBluetoothDevices, - kBluetoothDevicesSettings, generator); + GetBluetoothDevicesSubpageSettings(), generator); generator->RegisterTopLevelAltSetting(mojom::Setting::kBluetoothOnOff); + + generator->RegisterNestedSubpage(IDS_SETTINGS_BLUETOOTH_DEVICE_DETAILS, + mojom::Subpage::kBluetoothDeviceDetail, + mojom::Subpage::kBluetoothDevices, + mojom::SearchResultIcon::kBluetooth, + mojom::SearchResultDefaultRank::kMedium, + mojom::kBluetoothDeviceDetailSubpagePath); + RegisterNestedSettingBulk(mojom::Subpage::kBluetoothDeviceDetail, + GetBluetoothDeviceDetailSubpageSettings(), + generator); } void BluetoothSection::AdapterPresentChanged(device::BluetoothAdapter* adapter, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h index 63a9cede5aa..19bee711618 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h @@ -32,6 +32,7 @@ class BluetoothSection : public OsSettingsSection, private: // OsSettingsSection: void AddLoadTimeData(content::WebUIDataSource* html_source) override; + void AddHandlers(content::WebUI* web_ui) override; int GetSectionNameMessageId() const override; mojom::Section GetSection() const override; mojom::SearchResultIcon GetSectionIcon() const override; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc index 181d7bb23cb..8cf0a9ec01a 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.cc @@ -7,13 +7,14 @@ #include <numeric> #include "base/callback_helpers.h" +#include "base/memory/scoped_refptr.h" #include "base/system/sys_info.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/values.h" #include "chrome/browser/ash/crostini/crostini_features.h" +#include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/browsing_data/browsing_data_file_system_util.h" -#include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/profiles/profile.h" #include "chromeos/cryptohome/cryptohome_util.h" #include "chromeos/cryptohome/userdataauth_util.h" @@ -178,7 +179,7 @@ void BrowsingDataSizeCalculator::PerformCalculation() { new browsing_data::AppCacheHelper( storage_partition->GetAppCacheService()), new browsing_data::IndexedDBHelper(storage_partition), - browsing_data::FileSystemHelper::Create( + base::MakeRefCounted<browsing_data::FileSystemHelper>( storage_partition->GetFileSystemContext(), browsing_data_file_system_util::GetAdditionalFileSystemTypes(), storage_partition->GetNativeIOContext()), diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h index 5710cd90242..72e78b7c15c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h @@ -9,6 +9,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h" #include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h" +#include "third_party/abseil-cpp/absl/types/optional.h" namespace chromeos { namespace settings { diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc index 939e2d39754..7633dea116d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.cc @@ -12,11 +12,11 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/cxx17_backports.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/no_destructor.h" #include "base/path_service.h" -#include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" @@ -80,8 +80,22 @@ ui::SelectFileDialog::FileTypeInfo GetUserImageFileTypeInfo() { return file_type_info; } +void RecordUserImageChanged(int sample) { + // Although |ChangePictureHandler::kUserImageChangedHistogramName| is an + // enumerated histogram, we intentionally use UmaHistogramExactLinear() to + // emit the metric rather than UmaHistogramEnumeration(). This is because the + // enums.xml values correspond to (a) special constants and (b) indexes of an + // array containing resource IDs. + base::UmaHistogramExactLinear( + ChangePictureHandler::kUserImageChangedHistogramName, sample, + default_user_image::kHistogramImagesCount + 1); +} + } // namespace +const char ChangePictureHandler::kUserImageChangedHistogramName[] = + "UserImage.Changed2"; + ChangePictureHandler::ChangePictureHandler() : previous_image_index_(user_manager::User::USER_IMAGE_INVALID) { ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); @@ -142,12 +156,13 @@ void ChangePictureHandler::SendDefaultImages() { result.SetInteger("first", default_user_image::GetFirstDefaultImage()); std::unique_ptr<base::ListValue> default_images = default_user_image::GetAsDictionary(true /* all */); - result.Set("images", std::move(default_images)); + result.SetKey("images", + base::Value::FromUniquePtrValue(std::move(default_images))); FireWebUIListener("default-images-changed", result); } void ChangePictureHandler::HandleChooseFile(const base::ListValue* args) { - DCHECK(args && args->empty()); + DCHECK(args && args->GetList().empty()); select_file_dialog_ = ui::SelectFileDialog::Create( this, std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents())); @@ -169,7 +184,7 @@ void ChangePictureHandler::HandleChooseFile(const base::ListValue* args) { } void ChangePictureHandler::HandleDiscardPhoto(const base::ListValue* args) { - DCHECK(args->empty()); + DCHECK(args->GetList().empty()); AccessibilityManager::Get()->PlayEarcon( Sound::kObjectDelete, PlaySoundOption::kOnlyIfSpokenFeedbackEnabled); } @@ -204,7 +219,7 @@ void ChangePictureHandler::HandlePhotoTaken(const base::ListValue* args) { } void ChangePictureHandler::HandlePageInitialized(const base::ListValue* args) { - DCHECK(args && args->empty()); + DCHECK(args && args->GetList().empty()); AllowJavascript(); @@ -312,7 +327,7 @@ void ChangePictureHandler::HandleSelectImage(const base::ListValue* args) { ChromeUserManager::Get()->GetUserImageManager(GetUser()->GetAccountId()); bool waiting_for_camera_photo = false; - // track the index of previous selected message to be compared with the index + // Track the index of previous selected message to be compared with the index // of the new image. int previous_image_index = GetUser()->image_index(); @@ -342,14 +357,6 @@ void ChangePictureHandler::HandleSelectImage(const base::ListValue* args) { } else { LOG(WARNING) << "Invalid image_url for default image type: " << image_url; } - } else if (image_type == "camera") { - // Camera image is selected. - if (user_photo_.isNull()) { - waiting_for_camera_photo = true; - VLOG(1) << "Still waiting for camera image to decode"; - } else { - SetImageFromCamera(user_photo_, user_photo_data_.get()); - } } else if (image_type == "profile") { // Profile image selected. Could be previous (old) user image. user_image_manager->SaveUserImageFromProfileImage(); @@ -359,12 +366,10 @@ void ChangePictureHandler::HandleSelectImage(const base::ListValue* args) { int image_index = GetUser()->image_index(); // `previous_image_index` is used instead of `previous_image_index_` as the - // latter has the same value of `image_index` after new image is selected + // latter has the same value of `image_index` after new image is selected. if (previous_image_index != image_index) { - base::UmaHistogramExactLinear( - "UserImage.Changed", - user_image_manager->ImageIndexToHistogramIndex(image_index), - default_user_image::kHistogramImagesCount + 1); + RecordUserImageChanged( + user_image_manager->ImageIndexToHistogramIndex(image_index)); } // Ignore the result of the previous decoding if it's no longer needed. @@ -380,9 +385,13 @@ void ChangePictureHandler::HandleRequestSelectedImage( void ChangePictureHandler::FileSelected(const base::FilePath& path, int index, void* params) { - ChromeUserManager::Get() - ->GetUserImageManager(GetUser()->GetAccountId()) - ->SaveUserImageFromFile(path); + auto* user_image_manager = + ChromeUserManager::Get()->GetUserImageManager(GetUser()->GetAccountId()); + + // Log an impression if image is selected from a file. + RecordUserImageChanged(user_image_manager->ImageIndexToHistogramIndex( + user_manager::User::USER_IMAGE_EXTERNAL)); + user_image_manager->SaveUserImageFromFile(path); VLOG(1) << "Selected image from file"; } @@ -396,6 +405,9 @@ void ChangePictureHandler::SetImageFromCamera( ChromeUserManager::Get() ->GetUserImageManager(GetUser()->GetAccountId()) ->SaveUserImage(std::move(user_image)); + + // Log an impression if image is taken from photo. + RecordUserImageChanged(default_user_image::kHistogramImageFromCamera); VLOG(1) << "Selected camera photo"; } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h index adffb480e3d..db89522aa3e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h @@ -38,6 +38,9 @@ class ChangePictureHandler : public ::settings::SettingsPageUIHandler, ChangePictureHandler(); ~ChangePictureHandler() override; + // The name of the histogram that records when a user changes a device image. + static const char kUserImageChangedHistogramName[]; + // WebUIMessageHandler implementation. void RegisterMessages() override; void OnJavascriptAllowed() override; @@ -47,6 +50,8 @@ class ChangePictureHandler : public ::settings::SettingsPageUIHandler, void OnCameraPresenceCheckDone(bool is_camera_present) override; private: + friend class ChangePictureHandlerTest; + // Sends list of available default images to the page. void SendDefaultImages(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler_unittest.cc new file mode 100644 index 00000000000..aabcc4692f9 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/change_picture_handler_unittest.cc @@ -0,0 +1,235 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/change_picture_handler.h" + +#include <memory> + +#include "base/files/file_path.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/values.h" +#include "chrome/browser/ash/login/users/avatar/user_image_manager.h" +#include "chrome/browser/ash/login/users/default_user_image/default_user_images.h" +#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/ash/profiles/profile_helper.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "components/user_manager/scoped_user_manager.h" +#include "components/user_manager/user_manager.h" +#include "content/public/browser/audio_service.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_web_ui.h" +#include "services/audio/public/cpp/sounds/sounds_manager.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace settings { + +class ChangePictureHandlerTest : public testing::Test { + public: + ChangePictureHandlerTest() + : profile_manager_(TestingBrowserProcess::GetGlobal()), + user_manager_enabler_(std::make_unique<ash::FakeChromeUserManager>()) {} + ~ChangePictureHandlerTest() override = default; + + void SetUp() override { + audio::SoundsManager::Create(content::GetAudioServiceStreamFactoryBinder()); + + ASSERT_TRUE(profile_manager_.SetUp()); + account_id_ = AccountId::FromUserEmail("lala@example.com"); + + user_manager::User* user = GetFakeUserManager()->AddUser(account_id_); + + testing_profile_ = + profile_manager_.CreateTestingProfile(account_id_.GetUserEmail()); + ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, + testing_profile_); + + // Note that user profiles are created after user login in reality. + GetFakeUserManager()->LoginUser(account_id_); + GetFakeUserManager()->UserLoggedIn(account_id_, user->username_hash(), + /*browser_restart=*/false, + /*is_child=*/false); + + web_ui_ = std::make_unique<content::TestWebUI>(); + web_contents_ = content::WebContents::Create( + content::WebContents::CreateParams(testing_profile_)); + web_ui_->set_web_contents(web_contents_.get()); + + handler_ = std::make_unique<ChangePictureHandler>(); + handler_->set_web_ui(web_ui_.get()); + handler_->RegisterMessages(); + + listener_ = handler_.get(); + request_ = handler_.get(); + } + + void TearDown() override { + request_ = nullptr; + listener_ = nullptr; + handler_.reset(); + web_contents_.reset(); + web_ui_.reset(); + GetFakeUserManager()->Shutdown(); + testing_profile_ = nullptr; + profile_manager_.DeleteAllTestingProfiles(); + audio::SoundsManager::Shutdown(); + } + + content::TestWebUI* web_ui() { return web_ui_.get(); } + + ash::FakeChromeUserManager* GetFakeUserManager() const { + return static_cast<ash::FakeChromeUserManager*>( + user_manager::UserManager::Get()); + } + + const base::HistogramTester& histogram_tester() const { + return histogram_tester_; + } + + void SelectNewDefaultImage(int default_image_index) { + base::ListValue args; + args.Append(default_user_image::GetDefaultImageUrl(default_image_index)); + args.Append("default"); + + web_ui_->HandleReceivedMessage("selectImage", &args); + } + + void SelectProfileImage() { + base::ListValue args; + args.Append("empty url"); + args.Append("profile"); + + web_ui_->HandleReceivedMessage("selectImage", &args); + } + + void SelectImageFromFile(const base::FilePath& path, + const int index, + void* params) { + listener_->FileSelected(path, index, params); + } + + void OnCameraImageDecoded() { + SkBitmap bitmap; + bitmap.allocN32Pixels(1, 1); + + std::vector<unsigned char> data; + data.push_back('a'); + handler_->user_photo_data_ = base::RefCountedBytes::TakeVector(&data); + + request_->OnImageDecoded(bitmap); + } + + ash::UserImageManager* GetUserImageManager() { + return GetFakeUserManager()->GetUserImageManager(account_id_); + } + + private: + content::BrowserTaskEnvironment task_environment_{ + content::BrowserTaskEnvironment::REAL_IO_THREAD}; + std::unique_ptr<content::TestWebUI> web_ui_; + std::unique_ptr<content::WebContents> web_contents_; + std::unique_ptr<ChangePictureHandler> handler_; + base::HistogramTester histogram_tester_; + AccountId account_id_; + TestingProfile* testing_profile_; + TestingProfileManager profile_manager_; + user_manager::ScopedUserManager user_manager_enabler_; + ui::SelectFileDialog::Listener* listener_; + ImageDecoder::ImageRequest* request_; +}; + +TEST_F(ChangePictureHandlerTest, + ShouldSendUmaMetricWhenNewDefaultImageIsSelected) { + const int default_image_index = + default_user_image::GetRandomDefaultImageIndex(); + SelectNewDefaultImage(default_image_index); + + auto* user_image_manager = GetUserImageManager(); + + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex(default_image_index), 1); +} + +TEST_F(ChangePictureHandlerTest, + ShouldNotSendUmaMetricWhenDefaultImageIsReselected) { + const int default_image_index = + default_user_image::GetRandomDefaultImageIndex(); + auto* user_image_manager = GetUserImageManager(); + + SelectNewDefaultImage(default_image_index); + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex(default_image_index), 1); + + // Selecting the same default image should not log another impression. + SelectNewDefaultImage(default_image_index); + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex(default_image_index), 1); +} + +TEST_F(ChangePictureHandlerTest, ShoulSendUmaMetricWhenProfileImageIsSelected) { + const int default_image_index = + default_user_image::GetRandomDefaultImageIndex(); + auto* user_image_manager = GetUserImageManager(); + + // User selects a new default image. + SelectNewDefaultImage(default_image_index); + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex(default_image_index), 1); + + // User selects the profile image. + SelectProfileImage(); + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex( + user_manager::User::USER_IMAGE_PROFILE), + 1); +} + +TEST_F(ChangePictureHandlerTest, + ShoulNotSendUmaMetricWhenProfileImageIsReselected) { + auto* user_image_manager = GetUserImageManager(); + // User has profile image by default, thus reselecting profile does not log an + // impression + SelectProfileImage(); + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex( + user_manager::User::USER_IMAGE_PROFILE), + 0); +} + +TEST_F(ChangePictureHandlerTest, + ShouldSendUmaMetricWhenImageIsSelectedFromFile) { + auto* user_image_manager = GetUserImageManager(); + + const base::FilePath base_file_path("/this/is/a/test/directory/Base Name"); + const base::FilePath dir_path = base_file_path.AppendASCII("dir1"); + const base::FilePath file_path = dir_path.AppendASCII("file1.txt"); + const int index = 0; + void* params = nullptr; + SelectImageFromFile(file_path, index, params); + + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + user_image_manager->ImageIndexToHistogramIndex( + user_manager::User::USER_IMAGE_EXTERNAL), + 1); +} + +TEST_F(ChangePictureHandlerTest, ShouldSendUmaMetricWhenCameraImageIsDecoded) { + // Camera image is decoded + OnCameraImageDecoded(); + histogram_tester().ExpectBucketCount( + ChangePictureHandler::kUserImageChangedHistogramName, + default_user_image::kHistogramImageFromCamera, 1); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom index 34f389f6cd8..26cf88a9572 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom @@ -46,6 +46,7 @@ enum Subpage { // Bluetooth section. kBluetoothDevices = 100, + kBluetoothDeviceDetail = 101, // MultiDevice section. kMultiDeviceFeatures = 200, @@ -60,7 +61,8 @@ enum Subpage { kSecurityAndSignIn = 304, kFingerprint = 305, kManageOtherPeople = 306, - kKerberosAccounts = 307, + // Note: Value 307 was for Kerberos Accounts Subpage, which has been migrated + // to a separate section - see https://crbug.com/1186190. Do not reuse. // Device section. kPointers = 400, @@ -81,6 +83,7 @@ enum Subpage { kAmbientModeArtGalleryAlbum = 504, // 505 was used for kWallpaper. Do not reuse. // 506 was used for kWallpaperImages. Do not reuse. + kDarkMode = 507, // Search and Assistant section. kAssistant = 600, @@ -92,7 +95,8 @@ enum Subpage { kGooglePlayStore = 702, kPluginVmSharedPaths = 703, kPluginVmUsbPreferences = 704, - kOnStartup = 705, + // Note: Value 705 was for deprecated kOnStartup. Do not reuse. + kAppNotifications = 706, // Crostini section. kCrostiniDetails = 800, @@ -158,6 +162,7 @@ const string kVpnDetailsSubpagePath = "networkDetail"; // Bluetooth section. const string kBluetoothSectionPath = "bluetooth"; const string kBluetoothDevicesSubpagePath = "bluetoothDevices"; +const string kBluetoothDeviceDetailSubpagePath = "bluetoothDeviceDetail"; // MultiDevice section. const string kMultiDeviceSectionPath = "multidevice"; @@ -174,7 +179,6 @@ const string kSyncDeprecatedAdvancedSubpagePath = "syncSetup/advanced"; const string kSecurityAndSignInSubpagePath = "lockScreen"; const string kFingerprintSubpagePath = "lockScreen/fingerprint"; const string kManageOtherPeopleSubpagePath = "accounts"; -const string kKerberosAccountsSubpagePath = "kerberosAccounts"; // Device section. const string kDeviceSectionPath = "device"; @@ -194,6 +198,7 @@ const string kAmbientModeGooglePhotosAlbumSubpagePath = "ambientMode/photos?topicSource=0"; const string kAmbientModeArtGalleryAlbumSubpagePath = "ambientMode/photos?topicSource=1"; +const string kDarkModeSubpagePath = "darkMode"; // Search and Assistant section. const string kSearchAndAssistantSectionPath = "osSearch"; @@ -203,13 +208,13 @@ const string kSearchSubpagePath = "osSearch/search"; // Apps section. const string kAppsSectionPath = "apps"; const string kAppManagementSubpagePath = "app-management"; +const string kAppNotificationsSubpagePath = "app-notifications"; const string kAppDetailsSubpagePath = "app-management/detail"; const string kGooglePlayStoreSubpagePath = "androidAppsDetails"; const string kPluginVmSharedPathsSubpagePath = "app-management/pluginVm/sharedPaths"; const string kPluginVmUsbPreferencesSubpagePath = "app-management/pluginVm/sharedUsbDevices"; -const string kOnStartupSubpagePath = "onstartup"; // Crostini section. const string kCrostiniSectionPath = "crostini"; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc index b387dc7f871..dc438bef249 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes_util.cc @@ -46,7 +46,6 @@ bool IsOSSettingsSubPage(const std::string& sub_page) { chromeos::settings::mojom::kSecurityAndSignInSubpagePath, chromeos::settings::mojom::kFingerprintSubpagePath, chromeos::settings::mojom::kManageOtherPeopleSubpagePath, - chromeos::settings::mojom::kKerberosAccountsSubpagePath, // Device section. chromeos::settings::mojom::kDeviceSectionPath, @@ -62,6 +61,7 @@ bool IsOSSettingsSubPage(const std::string& sub_page) { chromeos::settings::mojom::kPersonalizationSectionPath, chromeos::settings::mojom::kChangePictureSubpagePath, chromeos::settings::mojom::kAmbientModeSubpagePath, + chromeos::settings::mojom::kDarkModeSubpagePath, // Search and Assistant section. chromeos::settings::mojom::kSearchAndAssistantSectionPath, @@ -74,7 +74,6 @@ bool IsOSSettingsSubPage(const std::string& sub_page) { chromeos::settings::mojom::kAppDetailsSubpagePath, chromeos::settings::mojom::kGooglePlayStoreSubpagePath, chromeos::settings::mojom::kPluginVmSharedPathsSubpagePath, - chromeos::settings::mojom::kOnStartupSubpagePath, // Crostini section. chromeos::settings::mojom::kCrostiniSectionPath, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom index 4524c3adb3a..47cbadd6297 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom @@ -79,9 +79,10 @@ enum Setting { kRestrictSignIn = 307, kAddToUserAllowlist = 308, kRemoveFromUserAllowlist = 309, - kAddKerberosTicket = 310, - kRemoveKerberosTicket = 311, - kSetActiveKerberosTicket = 312, + // Note: Values 310, 311 and 312 were for kAddKerberosTicket, + // kRemoveKerberosTicket and kSetActiveKerberosTicket, respectively. These + // settings have been moved to a separate Kerberos section - see + // https://crbug.com/1186190. Do not reuse. kAddFingerprint = 313, kRemoveFingerprint = 314, kSetUpParentalControls = 315, @@ -138,6 +139,8 @@ enum Setting { kChangeDeviceAccountImage = 503, // Note: Value 504 was for deprecated kAmbientModeUpdatePhotosContainers. // Do not reuse. + kDarkModeOnOff = 505, + kDarkModeThemed = 506, // Search and Assistant section. kPreferredSearchEngine = 600, @@ -150,12 +153,16 @@ enum Setting { kAssistantVoiceInput = 606, kTrainAssistantVoiceModel = 607, kQuickAnswersOnOff = 608, + kQuickAnswersDefinition = 609, + kQuickAnswersTranslation = 610, + kQuickAnswersUnitConversion = 611, // Apps section. kManageAndroidPreferences = 700, kRemovePlayStore = 701, kTurnOnPlayStore = 702, kRestoreAppsAndPages = 703, + kDoNotDisturbOnOff = 704, // Crostini section. kSetUpCrostini= 800, @@ -199,6 +206,7 @@ enum Setting { kOfferTranslation = 1205, kAddInputMethod = 1206, kSpellCheck = 1207, + kShowPredictiveWriting = 1208, // Files section. kGoogleDriveConnection = 1300, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc index 8865fcbdc5e..ba642c8a5f6 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc @@ -17,8 +17,8 @@ #include "chrome/browser/ash/crostini/crostini_pref_names.h" #include "chrome/browser/ash/crostini/crostini_types.mojom.h" #include "chrome/browser/ash/crostini/crostini_util.h" +#include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h" @@ -466,17 +466,13 @@ void CrostiniHandler::HandleAddCrostiniPortForward( void CrostiniHandler::HandleRemoveCrostiniPortForward( const base::ListValue* args) { - CHECK_EQ(5U, args->GetSize()); - std::string callback_id; - CHECK(args->GetString(0, &callback_id)); - std::string vm_name; - CHECK(args->GetString(1, &vm_name)); - std::string container_name; - CHECK(args->GetString(2, &container_name)); - int port_number; - CHECK(args->GetInteger(3, &port_number)); - int protocol_type; - CHECK(args->GetInteger(4, &protocol_type)); + const auto& list = args->GetList(); + CHECK_EQ(5U, list.size()); + std::string callback_id = list[0].GetString(); + std::string vm_name = list[1].GetString(); + std::string container_name = list[2].GetString(); + int port_number = list[3].GetInt(); + int protocol_type = list[4].GetInt(); if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { OnPortForwardComplete(callback_id, false); @@ -508,18 +504,14 @@ void CrostiniHandler::HandleRemoveAllCrostiniPortForwards( void CrostiniHandler::HandleActivateCrostiniPortForward( const base::ListValue* args) { - CHECK_EQ(5U, args->GetSize()); - - std::string callback_id; - CHECK(args->GetString(0, &callback_id)); - std::string vm_name; - CHECK(args->GetString(1, &vm_name)); - std::string container_name; - CHECK(args->GetString(2, &container_name)); - int port_number; - CHECK(args->GetInteger(3, &port_number)); - int protocol_type; - CHECK(args->GetInteger(4, &protocol_type)); + const auto& list = args->GetList(); + CHECK_EQ(5U, list.size()); + + std::string callback_id = list[0].GetString(); + std::string vm_name = list[1].GetString(); + std::string container_name = list[2].GetString(); + int port_number = list[3].GetInt(); + int protocol_type = list[4].GetInt(); if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { OnPortForwardComplete(callback_id, false); @@ -536,18 +528,14 @@ void CrostiniHandler::HandleActivateCrostiniPortForward( void CrostiniHandler::HandleDeactivateCrostiniPortForward( const base::ListValue* args) { - CHECK_EQ(5U, args->GetSize()); - - std::string callback_id; - CHECK(args->GetString(0, &callback_id)); - std::string vm_name; - CHECK(args->GetString(1, &vm_name)); - std::string container_name; - CHECK(args->GetString(2, &container_name)); - int port_number; - CHECK(args->GetInteger(3, &port_number)); - int protocol_type; - CHECK(args->GetInteger(4, &protocol_type)); + const auto& list = args->GetList(); + CHECK_EQ(5U, list.size()); + + std::string callback_id = list[0].GetString(); + std::string vm_name = list[1].GetString(); + std::string container_name = list[2].GetString(); + int port_number = list[3].GetInt(); + int protocol_type = list[4].GetInt(); if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { OnPortForwardComplete(callback_id, false); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index f5b09636a99..c509143cd48 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc @@ -278,10 +278,15 @@ CupsPrintersHandler::~CupsPrintersHandler() = default; void CupsPrintersHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "getCupsPrintersList", - base::BindRepeating(&CupsPrintersHandler::HandleGetCupsPrintersList, + "getCupsSavedPrintersList", + base::BindRepeating(&CupsPrintersHandler::HandleGetCupsSavedPrintersList, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "getCupsEnterprisePrintersList", + base::BindRepeating( + &CupsPrintersHandler::HandleGetCupsEnterprisePrintersList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "updateCupsPrinter", base::BindRepeating(&CupsPrintersHandler::HandleUpdateCupsPrinter, base::Unretained(this))); @@ -365,7 +370,7 @@ void CupsPrintersHandler::SetWebUIForTest(content::WebUI* web_ui) { set_web_ui(web_ui); } -void CupsPrintersHandler::HandleGetCupsPrintersList( +void CupsPrintersHandler::HandleGetCupsSavedPrintersList( const base::ListValue* args) { AllowJavascript(); @@ -380,6 +385,20 @@ void CupsPrintersHandler::HandleGetCupsPrintersList( ResolveJavascriptCallback(base::Value(callback_id), response); } +void CupsPrintersHandler::HandleGetCupsEnterprisePrintersList( + const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(1U, args->GetSize()); + std::string callback_id = args->GetList()[0].GetString(); + + std::vector<Printer> printers = + printers_manager_->GetPrinters(PrinterClass::kEnterprise); + + auto response = BuildCupsPrintersList(printers); + ResolveJavascriptCallback(base::Value(callback_id), response); +} + void CupsPrintersHandler::HandleUpdateCupsPrinter(const base::ListValue* args) { std::string callback_id; std::string printer_id; @@ -840,7 +859,7 @@ void CupsPrintersHandler::HandleGetCupsPrinterModels( if (manufacturer.empty()) { base::DictionaryValue response; response.SetBoolean("success", true); - response.Set("models", std::make_unique<base::ListValue>()); + response.SetKey("models", base::ListValue()); ResolveJavascriptCallback(base::Value(callback_id), response); return; } @@ -881,15 +900,15 @@ void CupsPrintersHandler::ResolveManufacturersDone( const std::string& callback_id, PpdProvider::CallbackResultCode result_code, const std::vector<std::string>& manufacturers) { - auto manufacturers_value = std::make_unique<base::ListValue>(); + base::ListValue manufacturers_value; if (result_code == PpdProvider::SUCCESS) { for (const std::string& manufacturer : manufacturers) { - manufacturers_value->Append(manufacturer); + manufacturers_value.Append(manufacturer); } } base::DictionaryValue response; response.SetBoolean("success", result_code == PpdProvider::SUCCESS); - response.Set("manufacturers", std::move(manufacturers_value)); + response.SetKey("manufacturers", std::move(manufacturers_value)); ResolveJavascriptCallback(base::Value(callback_id), response); } @@ -898,16 +917,16 @@ void CupsPrintersHandler::ResolvePrintersDone( const std::string& callback_id, PpdProvider::CallbackResultCode result_code, const PpdProvider::ResolvedPrintersList& printers) { - auto printers_value = std::make_unique<base::ListValue>(); + base::ListValue printers_value; if (result_code == PpdProvider::SUCCESS) { resolved_printers_[manufacturer] = printers; for (const auto& printer : printers) { - printers_value->AppendString(printer.name); + printers_value.Append(printer.name); } } base::DictionaryValue response; response.SetBoolean("success", result_code == PpdProvider::SUCCESS); - response.Set("models", std::move(printers_value)); + response.SetKey("models", std::move(printers_value)); ResolveJavascriptCallback(base::Value(callback_id), response); } @@ -990,12 +1009,13 @@ void CupsPrintersHandler::OnPrintersChanged( break; case PrinterClass::kSaved: { auto printers_list = BuildCupsPrintersList(printers); - FireWebUIListener("on-printers-changed", printers_list); + FireWebUIListener("on-saved-printers-changed", printers_list); break; } case PrinterClass::kEnterprise: - // These classes are not shown. - return; + auto enterprise_printers_list = BuildCupsPrintersList(printers); + FireWebUIListener("on-enterprise-printers-changed", + enterprise_printers_list); } } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index ac2cd672199..68a4c750c9b 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h @@ -71,7 +71,8 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler, CupsPrintersManager* printers_manager); // Gets all CUPS printers and return it to WebUI. - void HandleGetCupsPrintersList(const base::ListValue* args); + void HandleGetCupsSavedPrintersList(const base::ListValue* args); + void HandleGetCupsEnterprisePrintersList(const base::ListValue* args); void HandleUpdateCupsPrinter(const base::ListValue* args); void HandleRemoveCupsPrinter(const base::ListValue* args); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc index fac7aee93e1..fd51b02a46d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc @@ -56,10 +56,9 @@ class KeyboardHandlerTest : public testing::Test { for (auto it = web_ui_.call_data().rbegin(); it != web_ui_.call_data().rend(); ++it) { const content::TestWebUI::CallData* data = it->get(); - std::string name; - if (data->function_name() != "cr.webUIListenerCallback" || - !data->arg1()->GetAsString(&name) || - name != KeyboardHandler::kShowKeysChangedName) { + const std::string* name = data->arg1()->GetIfString(); + if (data->function_name() != "cr.webUIListenerCallback" || !name || + *name != KeyboardHandler::kShowKeysChangedName) { continue; } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc index d65abda5480..ed5a0b1c477 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.cc @@ -14,26 +14,78 @@ namespace chromeos { namespace settings { +namespace { + +// Key names for first and second key-value pairs in dictionary that is passed +// as argument to FireWebUIListener. +const char kMetadataFirstKey[] = "deviceName"; +const char kMetadataSecondKey[] = "deviceNameState"; + +} // namespace + +DeviceNameHandler::DeviceNameHandler() + : DeviceNameHandler(DeviceNameStore::GetInstance()) {} + +DeviceNameHandler::DeviceNameHandler(DeviceNameStore* device_name_store) + : device_name_store_(device_name_store) {} + +DeviceNameHandler::~DeviceNameHandler() = default; + +void DeviceNameHandler::OnJavascriptAllowed() { + observation_.Observe(device_name_store_); +} + +void DeviceNameHandler::OnJavascriptDisallowed() { + observation_.Reset(); +} + void DeviceNameHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "getDeviceNameMetadata", - base::BindRepeating(&DeviceNameHandler::HandleGetDeviceNameMetadata, + "notifyReadyForDeviceName", + base::BindRepeating(&DeviceNameHandler::HandleNotifyReadyForDeviceName, base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "attemptSetDeviceName", + base::BindRepeating(&DeviceNameHandler::HandleAttemptSetDeviceName, + base::Unretained(this))); +} + +base::Value DeviceNameHandler::GetDeviceNameMetadata() const { + base::Value metadata(base::Value::Type::DICTIONARY); + DeviceNameStore::DeviceNameMetadata device_name_metadata = + device_name_store_->GetDeviceNameMetadata(); + metadata.SetStringKey(kMetadataFirstKey, device_name_metadata.device_name); + metadata.SetIntKey(kMetadataSecondKey, + static_cast<int>(device_name_metadata.device_name_state)); + return metadata; } -void DeviceNameHandler::HandleGetDeviceNameMetadata( +void DeviceNameHandler::HandleAttemptSetDeviceName( const base::ListValue* args) { AllowJavascript(); - CHECK_EQ(1U, args->GetSize()); - std::string callback_id; - CHECK(args->GetString(0, &callback_id)); + DCHECK_EQ(2U, args->GetSize()); + const base::Value::ConstListView args_list = args->GetList(); + const std::string callback_id = args_list[0].GetString(); + const std::string name_from_user = args_list[1].GetString(); + DeviceNameStore::SetDeviceNameResult result = + device_name_store_->SetDeviceName(name_from_user); - base::DictionaryValue metadata; - metadata.SetString("deviceName", - DeviceNameStore::GetInstance()->GetDeviceName()); + ResolveJavascriptCallback(base::Value(callback_id), + base::Value(static_cast<int>(result))); +} + +void DeviceNameHandler::HandleNotifyReadyForDeviceName( + const base::ListValue* args) { + AllowJavascript(); + FireWebUIListener("settings.updateDeviceNameMetadata", + base::Value(GetDeviceNameMetadata())); +} - ResolveJavascriptCallback(base::Value(callback_id), metadata); +void DeviceNameHandler::OnDeviceNameMetadataChanged() { + FireWebUIListener("settings.updateDeviceNameMetadata", + base::Value(GetDeviceNameMetadata())); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h index 79b4f672e53..facee2f7922 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler.h @@ -6,6 +6,8 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_NAME_HANDLER_H_ #include "base/macros.h" +#include "base/scoped_observation.h" +#include "chrome/browser/chromeos/device_name_store.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" namespace base { @@ -17,20 +19,37 @@ namespace settings { // DeviceNameHandler handles calls from WebUI JS related to getting and setting // the device name. -class DeviceNameHandler : public ::settings::SettingsPageUIHandler { +class DeviceNameHandler : public ::settings::SettingsPageUIHandler, + public chromeos::DeviceNameStore::Observer { public: - DeviceNameHandler() = default; - ~DeviceNameHandler() override = default; + DeviceNameHandler(); + ~DeviceNameHandler() override; // SettingsPageUIHandler implementation. void RegisterMessages() override; - void OnJavascriptAllowed() override {} - void OnJavascriptDisallowed() override {} + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; protected: - void HandleGetDeviceNameMetadata(const base::ListValue* args); + void HandleAttemptSetDeviceName(const base::ListValue* args); + void HandleNotifyReadyForDeviceName(const base::ListValue* args); private: + friend class TestDeviceNameHandler; + + // DeviceNameStore::Observer: + void OnDeviceNameMetadataChanged() override; + + explicit DeviceNameHandler(DeviceNameStore* device_name_store); + + base::Value GetDeviceNameMetadata() const; + + DeviceNameStore* device_name_store_; + + base::ScopedObservation<chromeos::DeviceNameStore, + chromeos::DeviceNameStore::Observer> + observation_{this}; + DISALLOW_COPY_AND_ASSIGN(DeviceNameHandler); }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc index 5a9d3b13bbe..fb64773512e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_name_handler_unittest.cc @@ -7,9 +7,9 @@ #include <memory> #include <string> -#include "chrome/browser/chromeos/device_name_store.h" -#include "chrome/common/pref_names.h" -#include "components/prefs/testing_pref_service.h" +#include "ash/constants/ash_features.h" +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/chromeos/fake_device_name_store.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,14 +19,15 @@ namespace settings { class TestDeviceNameHandler : public DeviceNameHandler { public: - explicit TestDeviceNameHandler(content::WebUI* web_ui) : DeviceNameHandler() { + explicit TestDeviceNameHandler(content::WebUI* web_ui, + DeviceNameStore* fake_device_name_store) + : DeviceNameHandler(fake_device_name_store) { set_web_ui(web_ui); } // Raise visibility to public. - void HandleGetDeviceNameMetadata(const base::ListValue* args) { - DeviceNameHandler::HandleGetDeviceNameMetadata(args); - } + using DeviceNameHandler::HandleAttemptSetDeviceName; + using DeviceNameHandler::HandleNotifyReadyForDeviceName; }; class DeviceNameHandlerTest : public testing::Test { @@ -36,47 +37,171 @@ class DeviceNameHandlerTest : public testing::Test { void SetUp() override { testing::Test::SetUp(); - handler_ = std::make_unique<TestDeviceNameHandler>(web_ui()); - handler()->AllowJavascriptForTesting(); + handler_ = std::make_unique<TestDeviceNameHandler>( + web_ui(), &fake_device_name_store_); + web_ui()->ClearTrackedCalls(); + feature_list_.InitAndEnableFeature(ash::features::kEnableHostnameSetting); + } + + void CallHandleNotifyReadyForDeviceName() { + // Need to call HandleNotifyReadyForDeviceName() once for handler to start + // listening to changes in device name metadata. + base::Value args(base::Value::Type::LIST); + args.Append("callback-id"); + handler()->HandleNotifyReadyForDeviceName(&base::Value::AsListValue(args)); + + // On notifying, device name metadata should be received and be equal to the + // default values. + VerifyDeviceNameMetadata(FakeDeviceNameStore::kDefaultDeviceName, + DeviceNameStore::DeviceNameState::kCanBeModified); + } + + void TearDown() override { FakeDeviceNameStore::Shutdown(); } + + void VerifyDeviceNameMetadata( + const std::string& expected_device_name, + DeviceNameStore::DeviceNameState expected_device_name_state) { + const content::TestWebUI::CallData& call_data = + *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("settings.updateDeviceNameMetadata", + call_data.arg1()->GetString()); + + const base::DictionaryValue* returned_data; + ASSERT_TRUE(call_data.arg2()->GetAsDictionary(&returned_data)); + + std::string device_name; + returned_data->GetString("deviceName", &device_name); + EXPECT_EQ(expected_device_name, device_name); - DeviceNameStore::RegisterLocalStatePrefs(local_state_.registry()); + int device_name_state; + returned_data->GetInteger("deviceNameState", &device_name_state); + EXPECT_EQ(static_cast<int>(expected_device_name_state), device_name_state); + } + + void VerifySetDeviceNameResult( + const std::string& device_name, + DeviceNameStore::SetDeviceNameResult expected_result) { + base::Value args(base::Value::Type::LIST); + args.Append("callback-id"); + args.Append(device_name); + handler()->HandleAttemptSetDeviceName(&base::Value::AsListValue(args)); + + const content::TestWebUI::CallData& call_data = + *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIResponse", call_data.function_name()); + EXPECT_EQ("callback-id", call_data.arg1()->GetString()); + EXPECT_TRUE(call_data.arg2()->GetBool()); + + EXPECT_EQ(static_cast<int>(expected_result), call_data.arg3()->GetInt()); + } + + void VerifyValuesInDeviceNameStore( + const std::string& expected_name, + DeviceNameStore::DeviceNameState expected_state) { + DeviceNameStore::DeviceNameMetadata metadata = + fake_device_name_store()->GetDeviceNameMetadata(); + EXPECT_EQ(metadata.device_name, expected_name); + EXPECT_EQ(metadata.device_name_state, expected_state); + } - local_state()->SetString(prefs::kDeviceName, "TestDeviceName"); - DeviceNameStore::GetInstance()->Initialize(&local_state_); + FakeDeviceNameStore* fake_device_name_store() { + return &fake_device_name_store_; } TestDeviceNameHandler* handler() { return handler_.get(); } content::TestWebUI* web_ui() { return &web_ui_; } - TestingPrefServiceSimple* local_state() { return &local_state_; } private: // Run on the UI thread. content::BrowserTaskEnvironment task_environment_; - // Test backing store for prefs. - TestingPrefServiceSimple local_state_; - + FakeDeviceNameStore fake_device_name_store_; content::TestWebUI web_ui_; std::unique_ptr<TestDeviceNameHandler> handler_; + base::test::ScopedFeatureList feature_list_; }; -TEST_F(DeviceNameHandlerTest, DeviceNameMetadata_DeviceName) { - base::ListValue args; - args.AppendString("callback-id"); - handler()->HandleGetDeviceNameMetadata(&args); +TEST_F(DeviceNameHandlerTest, DeviceNameMetadata_ChangeName) { + CallHandleNotifyReadyForDeviceName(); + + EXPECT_EQ(DeviceNameStore::SetDeviceNameResult::kSuccess, + fake_device_name_store()->SetDeviceName("TestName")); + VerifyDeviceNameMetadata("TestName", + DeviceNameStore::DeviceNameState::kCanBeModified); - const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back(); - EXPECT_EQ("cr.webUIResponse", call_data.function_name()); - EXPECT_EQ("callback-id", call_data.arg1()->GetString()); - EXPECT_TRUE(call_data.arg2()->GetBool()); + // Verify that we can still provide updates to the device name as long as + // handleNotifyReadyForDeviceName() has been called once during setup. + EXPECT_EQ(DeviceNameStore::SetDeviceNameResult::kSuccess, + fake_device_name_store()->SetDeviceName("TestName1")); + VerifyDeviceNameMetadata("TestName1", + DeviceNameStore::DeviceNameState::kCanBeModified); +} - const base::DictionaryValue* returned_data; - ASSERT_TRUE(call_data.arg3()->GetAsDictionary(&returned_data)); +TEST_F(DeviceNameHandlerTest, DeviceNameMetadata_ChangeState) { + CallHandleNotifyReadyForDeviceName(); + + DeviceNameStore::DeviceNameState device_name_state = + DeviceNameStore::DeviceNameState::kCannotBeModifiedBecauseOfPolicy; + fake_device_name_store()->SetDeviceNameState(device_name_state); + VerifyDeviceNameMetadata(FakeDeviceNameStore::kDefaultDeviceName, + device_name_state); + + // Verify that we can still provide updates to the device name state as long + // as handleNotifyReadyForDeviceName() has been called once during setup. + device_name_state = + DeviceNameStore::DeviceNameState::kCannotBeModifiedBecauseNotDeviceOwner; + fake_device_name_store()->SetDeviceNameState(device_name_state); + VerifyDeviceNameMetadata(FakeDeviceNameStore::kDefaultDeviceName, + device_name_state); + + device_name_state = DeviceNameStore::DeviceNameState::kCanBeModified; + fake_device_name_store()->SetDeviceNameState(device_name_state); + VerifyDeviceNameMetadata(FakeDeviceNameStore::kDefaultDeviceName, + device_name_state); +} - std::string device_name; - ASSERT_TRUE(returned_data->GetString("deviceName", &device_name)); - EXPECT_EQ("TestDeviceName", device_name); +// Verify that DeviceNameHandler::HandleAttemptSetDeviceName() works for all +// possible name update results. +TEST_F(DeviceNameHandlerTest, SetDeviceName) { + // Verify default values in device name store. + VerifyValuesInDeviceNameStore( + "ChromeOS", DeviceNameStore::DeviceNameState::kCanBeModified); + + // Verify that name update is successful and that the name changes in device + // name store. + VerifySetDeviceNameResult("TestName", + DeviceNameStore::SetDeviceNameResult::kSuccess); + VerifyValuesInDeviceNameStore( + "TestName", DeviceNameStore::DeviceNameState::kCanBeModified); + + // Verify that name update is unsuccessful because of invalid name and that + // the name does not change in device name store. + VerifySetDeviceNameResult("Invalid Name", + DeviceNameStore::SetDeviceNameResult::kInvalidName); + VerifyValuesInDeviceNameStore( + "TestName", DeviceNameStore::DeviceNameState::kCanBeModified); + + // Verify that name update is unsuccessful because of policy and that the + // name does not change in device name store. + fake_device_name_store()->SetDeviceNameState( + DeviceNameStore::DeviceNameState::kCannotBeModifiedBecauseOfPolicy); + VerifySetDeviceNameResult( + "TestName", DeviceNameStore::SetDeviceNameResult::kProhibitedByPolicy); + VerifyValuesInDeviceNameStore( + "TestName", + DeviceNameStore::DeviceNameState::kCannotBeModifiedBecauseOfPolicy); + + // Verify that name update is unsuccessful because user is not device owner + // and that the name does not change in device name store. + fake_device_name_store()->SetDeviceNameState( + DeviceNameStore::DeviceNameState::kCannotBeModifiedBecauseNotDeviceOwner); + VerifySetDeviceNameResult( + "TestName", DeviceNameStore::SetDeviceNameResult::kNotDeviceOwner); + VerifyValuesInDeviceNameStore( + "TestName", + DeviceNameStore::DeviceNameState::kCannotBeModifiedBecauseNotDeviceOwner); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc index 945609de57d..6de5e6800d2 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler.cc @@ -7,7 +7,7 @@ #include <memory> #include <utility> -#include "ash/public/cpp/ash_pref_names.h" +#include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/power_utils.h" #include "base/bind.h" #include "base/callback_helpers.h" @@ -115,23 +115,24 @@ PowerHandler::TestAPI::TestAPI(PowerHandler* handler) : handler_(handler) {} PowerHandler::TestAPI::~TestAPI() = default; void PowerHandler::TestAPI::RequestPowerManagementSettings() { - base::ListValue args; - handler_->HandleRequestPowerManagementSettings(&args); + base::Value args(base::Value::Type::LIST); + handler_->HandleRequestPowerManagementSettings( + &base::Value::AsListValue(args)); } void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior, bool when_on_ac) { - base::ListValue args; - args.AppendInteger(static_cast<int>(behavior)); - args.AppendBoolean(when_on_ac); - handler_->HandleSetIdleBehavior(&args); + base::Value args(base::Value::Type::LIST); + args.Append(static_cast<int>(behavior)); + args.Append(when_on_ac); + handler_->HandleSetIdleBehavior(&base::Value::AsListValue(args)); } void PowerHandler::TestAPI::SetLidClosedBehavior( PowerPolicyController::Action behavior) { - base::ListValue args; - args.AppendInteger(behavior); - handler_->HandleSetLidClosedBehavior(&args); + base::Value args(base::Value::Type::LIST); + args.Append(behavior); + handler_->HandleSetLidClosedBehavior(&base::Value::AsListValue(args)); } PowerHandler::PowerHandler(PrefService* prefs) : prefs_(prefs) {} @@ -230,10 +231,10 @@ void PowerHandler::HandleRequestPowerManagementSettings( void PowerHandler::HandleSetIdleBehavior(const base::ListValue* args) { AllowJavascript(); - int value = 0; - bool when_on_ac = true; - CHECK(args->GetInteger(0, &value)); - CHECK(args->GetBoolean(1, &when_on_ac)); + const auto& list = args->GetList(); + CHECK_GE(list.size(), 2u); + int value = list[0].GetInt(); + bool when_on_ac = list[1].GetBool(); const char* idle_pref = when_on_ac ? ash::prefs::kPowerAcIdleAction : ash::prefs::kPowerBatteryIdleAction; @@ -280,8 +281,9 @@ void PowerHandler::HandleSetIdleBehavior(const base::ListValue* args) { void PowerHandler::HandleSetLidClosedBehavior(const base::ListValue* args) { AllowJavascript(); - int value = 0; - CHECK(args->GetInteger(0, &value)); + const auto& list = args->GetList(); + CHECK_GE(list.size(), 1u); + int value = list[0].GetInt(); switch (static_cast<PowerPolicyController::Action>(value)) { case PowerPolicyController::ACTION_SUSPEND: prefs_->ClearPref(ash::prefs::kPowerLidClosedAction); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc index 4d54e411208..aba54d7e5fa 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_power_handler_browsertest.cc @@ -6,7 +6,7 @@ #include <set> #include <utility> -#include "ash/public/cpp/ash_pref_names.h" +#include "ash/constants/ash_pref_names.h" #include "base/json/json_writer.h" #include "base/macros.h" #include "base/run_loop.h" @@ -83,9 +83,8 @@ class PowerHandlerTest : public InProcessBrowserTest { // InProcessBrowserTest: void SetUpInProcessBrowserTestFixture() override { // Initialize user policy. - ON_CALL(provider_, IsInitializationComplete(_)).WillByDefault(Return(true)); - ON_CALL(provider_, IsFirstPolicyLoadComplete(_)) - .WillByDefault(Return(true)); + provider_.SetDefaultReturns(/*is_initialization_complete_return=*/true, + /*is_first_policy_load_complete_return=*/true); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); } @@ -109,15 +108,14 @@ class PowerHandlerTest : public InProcessBrowserTest { for (auto it = web_ui_.call_data().rbegin(); it != web_ui_.call_data().rend(); ++it) { const content::TestWebUI::CallData* data = it->get(); - std::string name; + const std::string* name = data->arg1()->GetIfString(); const base::DictionaryValue* dict = nullptr; - if (data->function_name() != "cr.webUIListenerCallback" || - !data->arg1()->GetAsString(&name) || - name != PowerHandler::kPowerManagementSettingsChangedName) { + if (data->function_name() != "cr.webUIListenerCallback" || !name || + *name != PowerHandler::kPowerManagementSettingsChangedName) { continue; } if (!data->arg2()->GetAsDictionary(&dict)) { - ADD_FAILURE() << "Failed to get dict from " << name << " message"; + ADD_FAILURE() << "Failed to get dict from " << *name << " message"; continue; } std::string out; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.cc index adb76966d78..11e1cc8f52e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.cc @@ -7,7 +7,6 @@ #include "ash/constants/ash_features.h" #include "ash/constants/ash_switches.h" #include "ash/public/ash_interfaces.h" -#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/night_light_controller.h" #include "ash/public/cpp/stylus_utils.h" #include "base/command_line.h" diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc index 46951b8eaaf..96b2b70ded5 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc @@ -11,7 +11,7 @@ #include <utility> #include "chrome/browser/ash/arc/arc_util.h" -#include "chrome/browser/chromeos/file_manager/path_util.h" +#include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h" #include "chrome/grit/generated_resources.h" @@ -30,6 +30,9 @@ namespace settings { namespace { constexpr char kAndroidEnabled[] = "androidEnabled"; +// Dummy UUID for testing. The UUID is taken from +// components/arc/volume_mounter/arc_volume_mounter_bridge.cc. +constexpr char kDummyUuid[] = "00000000000000000000000000000000DEADBEEF"; const char* CalculationTypeToEventName( calculator::SizeCalculator::CalculationType x) { @@ -200,10 +203,10 @@ void StorageHandler::UpdateExternalStorages() { const chromeos::disks::Disk* disk = DiskMountManager::GetInstance()->FindDiskBySourcePath( mount_info.source_path); - if (!disk) - continue; - std::string label = disk->device_label(); + // Assigning a dummy UUID for diskless volume for testing. + const std::string uuid = disk ? disk->fs_uuid() : kDummyUuid; + std::string label = disk ? disk->device_label() : std::string(); if (label.empty()) { // To make volume labels consistent with Files app, we follow how Files // generates a volume label when the volume doesn't have specific label. @@ -213,7 +216,7 @@ void StorageHandler::UpdateExternalStorages() { label = base::FilePath(mount_info.mount_path).BaseName().AsUTF8Unsafe(); } base::Value device(base::Value::Type::DICTIONARY); - device.SetKey("uuid", base::Value(disk->fs_uuid())); + device.SetKey("uuid", base::Value(uuid)); device.SetKey("label", base::Value(label)); devices.Append(std::move(device)); } @@ -304,8 +307,8 @@ void StorageHandler::UpdateSizeStat( base::DictionaryValue size_stat; size_stat.SetString("availableSize", ui::FormatBytes(available_bytes)); size_stat.SetString("usedSize", ui::FormatBytes(in_use_total_bytes_)); - size_stat.SetDouble("usedRatio", static_cast<double>(in_use_total_bytes_) / - rounded_total_bytes); + size_stat.SetDoubleKey("usedRatio", static_cast<double>(in_use_total_bytes_) / + rounded_total_bytes); int storage_space_state = static_cast<int>(StorageSpaceState::kStorageSpaceNormal); if (available_bytes < kSpaceCriticallyLowBytes) diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc index c1c5bdd1149..245a8a5188e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler_unittest.cc @@ -15,8 +15,8 @@ #include "base/test/scoped_running_on_chromeos.h" #include "chrome/browser/ash/arc/session/arc_session_manager.h" #include "chrome/browser/ash/arc/test/test_arc_session_manager.h" -#include "chrome/browser/chromeos/file_manager/fake_disk_mount_manager.h" -#include "chrome/browser/chromeos/file_manager/path_util.h" +#include "chrome/browser/ash/file_manager/fake_disk_mount_manager.h" +#include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator_test_api.h" #include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h" #include "chrome/common/chrome_paths.h" @@ -149,12 +149,11 @@ class StorageHandlerTest : public testing::Test { for (auto it = web_ui_.call_data().rbegin(); it != web_ui_.call_data().rend(); ++it) { const content::TestWebUI::CallData* data = it->get(); - std::string name; - if (data->function_name() != "cr.webUIListenerCallback" || - !data->arg1()->GetAsString(&name)) { + const std::string* name = data->arg1()->GetIfString(); + if (data->function_name() != "cr.webUIListenerCallback" || !name) { continue; } - if (name == event_name) + if (*name == event_name) return data->arg2(); } return nullptr; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc index 48cac0a8934..0802990e4f9 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc @@ -7,6 +7,7 @@ #include <algorithm> #include <memory> +#include "ash/constants/ash_pref_names.h" #include "base/bind.h" #include "base/containers/contains.h" #include "base/strings/string_number_conversions.h" @@ -17,7 +18,6 @@ #include "chrome/browser/ash/login/quick_unlock/quick_unlock_storage.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/prefs/pref_service.h" #include "content/public/browser/device_service.h" @@ -36,17 +36,17 @@ constexpr int kMaxAllowedFingerprints = 3; std::unique_ptr<base::DictionaryValue> GetFingerprintsInfo( const std::vector<std::string>& fingerprints_list) { auto response = std::make_unique<base::DictionaryValue>(); - auto fingerprints = std::make_unique<base::ListValue>(); + base::ListValue fingerprints; DCHECK_LE(static_cast<int>(fingerprints_list.size()), kMaxAllowedFingerprints); for (auto& fingerprint_name: fingerprints_list) { std::unique_ptr<base::Value> str = std::make_unique<base::Value>(fingerprint_name); - fingerprints->Append(std::move(str)); + fingerprints.Append(std::move(str)); } - response->Set("fingerprintsList", std::move(fingerprints)); + response->SetKey("fingerprintsList", std::move(fingerprints)); response->SetBoolean("isMaxed", static_cast<int>(fingerprints_list.size()) >= kMaxAllowedFingerprints); return response; @@ -146,19 +146,19 @@ void FingerprintHandler::OnAuthScanDone( if (it == matches.end() || it->second.size() < 1) return; - auto fingerprint_ids = std::make_unique<base::ListValue>(); + base::ListValue fingerprint_ids; for (const std::string& matched_path : it->second) { auto path_it = std::find(fingerprints_paths_.begin(), fingerprints_paths_.end(), matched_path); DCHECK(path_it != fingerprints_paths_.end()); - fingerprint_ids->AppendInteger( + fingerprint_ids.Append( static_cast<int>(path_it - fingerprints_paths_.begin())); } auto fingerprint_attempt = std::make_unique<base::DictionaryValue>(); fingerprint_attempt->SetInteger("result", static_cast<int>(scan_result)); - fingerprint_attempt->Set("indexes", std::move(fingerprint_ids)); + fingerprint_attempt->SetKey("indexes", std::move(fingerprint_ids)); FireWebUIListener("on-fingerprint-attempt-received", *fingerprint_attempt); } @@ -259,11 +259,10 @@ void FingerprintHandler::OnCancelCurrentEnrollSession(bool success) { } void FingerprintHandler::HandleGetEnrollmentLabel(const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); - std::string callback_id; - int index; - CHECK(args->GetString(0, &callback_id)); - CHECK(args->GetInteger(1, &index)); + const auto& list = args->GetList(); + CHECK_EQ(2U, list.size()); + std::string callback_id = list[0].GetString(); + int index = list[1].GetInt(); DCHECK_LT(index, static_cast<int>(fingerprints_labels_.size())); AllowJavascript(); @@ -279,11 +278,10 @@ void FingerprintHandler::OnRequestRecordLabel(const std::string& callback_id, } void FingerprintHandler::HandleRemoveEnrollment(const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); - std::string callback_id; - int index; - CHECK(args->GetString(0, &callback_id)); - CHECK(args->GetInteger(1, &index)); + const auto& list = args->GetList(); + CHECK_EQ(2U, list.size()); + std::string callback_id = list[0].GetString(); + int index = list[1].GetInt(); DCHECK_LT(index, static_cast<int>(fingerprints_paths_.size())); AllowJavascript(); @@ -302,14 +300,12 @@ void FingerprintHandler::OnRemoveRecord(const std::string& callback_id, void FingerprintHandler::HandleChangeEnrollmentLabel( const base::ListValue* args) { - CHECK_EQ(3U, args->GetSize()); - std::string callback_id; - int index; - std::string new_label; + const auto& list = args->GetList(); + CHECK_EQ(3U, list.size()); - CHECK(args->GetString(0, &callback_id)); - CHECK(args->GetInteger(1, &index)); - CHECK(args->GetString(2, &new_label)); + std::string callback_id = list[0].GetString(); + int index = list[1].GetInt(); + std::string new_label = list[2].GetString(); AllowJavascript(); fp_service_->SetRecordLabel( diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h index 6bcd141b4ea..dc4afb8533e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.h @@ -9,7 +9,6 @@ #include "base/macros.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "mojo/public/cpp/bindings/remote.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace chromeos { namespace settings { diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc index 3c7919f7867..d048532bdd3 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/guest_os_handler.cc @@ -10,8 +10,8 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "chrome/browser/ash/file_manager/path_util.h" #include "chrome/browser/ash/guest_os/guest_os_share_path.h" -#include "chrome/browser/chromeos/file_manager/path_util.h" #include "chrome/browser/profiles/profile.h" #include "content/public/browser/browser_thread.h" @@ -78,9 +78,9 @@ void GuestOsHandler::HandleGetGuestOsSharedPathsDisplayText( CHECK_EQ(2U, args->GetSize()); std::string callback_id = args->GetList()[0].GetString(); - base::ListValue texts; + base::Value texts(base::Value::Type::LIST); for (const auto& path : args->GetList()[1].GetList()) { - texts.AppendString(file_manager::util::GetPathDisplayTextForSettings( + texts.Append(file_manager::util::GetPathDisplayTextForSettings( profile_, path.GetString())); } ResolveJavascriptCallback(base::Value(callback_id), texts); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc index 586dfec92a3..e30130eeebe 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc @@ -7,6 +7,7 @@ #include <memory> #include <vector> +#include "ash/constants/ash_pref_names.h" #include "base/bind.h" #include "base/values.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" @@ -24,6 +25,7 @@ #include "components/arc/mojom/net.mojom.h" #include "components/arc/session/arc_bridge_service.h" #include "components/onc/onc_constants.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "extensions/browser/api/vpn_provider/vpn_service.h" @@ -49,6 +51,12 @@ Profile* GetProfileForPrimaryUser() { user_manager::UserManager::Get()->GetPrimaryUser()); } +bool IsVpnConfigAllowed() { + PrefService* prefs = GetProfileForPrimaryUser()->GetPrefs(); + DCHECK(prefs); + return prefs->GetBoolean(prefs::kVpnConfigAllowed); +} + } // namespace namespace settings { @@ -116,6 +124,10 @@ void InternetHandler::AddThirdPartyVpn(const base::ListValue* args) { << "Only the primary user and non-child accounts can add VPNs"; return; } + if (!IsVpnConfigAllowed()) { + NET_LOG(ERROR) << "Cannot add VPN; prohibited by policy"; + return; + } // Request to launch Arc VPN provider. const auto* arc_app_list_prefs = ArcAppListPrefs::Get(profile_); @@ -143,6 +155,10 @@ void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) { NET_LOG(ERROR) << "Only the primary user can configure VPNs"; return; } + if (!IsVpnConfigAllowed()) { + NET_LOG(ERROR) << "Cannot configure VPN; prohibited by policy"; + return; + } const NetworkState* network = NetworkHandler::Get()->network_state_handler()->GetNetworkStateFromGuid( diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.cc index 156e0d73737..d147691af8c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.cc @@ -5,7 +5,6 @@ #include "chrome/browser/ui/webui/settings/chromeos/internet_section.h" #include "ash/constants/ash_features.h" -#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/network_config_service.h" #include "base/bind.h" #include "base/containers/contains.h" @@ -13,7 +12,6 @@ #include "base/no_destructor.h" #include "base/strings/stringprintf.h" #include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.h" -#include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/internet_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" @@ -29,6 +27,8 @@ #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" +#include "ui/chromeos/strings/grit/ui_chromeos_strings.h" +#include "ui/chromeos/strings/network_element_localized_strings_provider.h" namespace chromeos { namespace settings { @@ -614,21 +614,15 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"internetConfigName", IDS_SETTINGS_INTERNET_CONFIG_NAME}, {"internetDetailPageTitle", IDS_SETTINGS_INTERNET_DETAIL}, {"internetDeviceEnabling", IDS_SETTINGS_INTERNET_DEVICE_ENABLING}, - {"internetDeviceDisabling", IDS_SETTINGS_INTERNET_DEVICE_DISABLING}, - {"internetDeviceInitializing", IDS_SETTINGS_INTERNET_DEVICE_INITIALIZING}, {"internetDeviceBusy", IDS_SETTINGS_INTERNET_DEVICE_BUSY}, {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE}, {"internetKnownNetworksPageTitle", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS}, - {"internetMobileSearching", IDS_SETTINGS_INTERNET_MOBILE_SEARCH}, {"internetNoNetworks", IDS_SETTINGS_INTERNET_NO_NETWORKS}, {"internetPageTitle", IDS_SETTINGS_INTERNET}, {"internetSummaryButtonA11yLabel", IDS_SETTINGS_INTERNET_SUMMARY_BUTTON_ACCESSIBILITY_LABEL}, {"internetToggleMobileA11yLabel", IDS_SETTINGS_INTERNET_TOGGLE_MOBILE_ACCESSIBILITY_LABEL}, - {"internetToggleTetherLabel", IDS_SETTINGS_INTERNET_TOGGLE_TETHER_LABEL}, - {"internetToggleTetherSubtext", - IDS_SETTINGS_INTERNET_TOGGLE_TETHER_SUBTEXT}, {"internetToggleWiFiA11yLabel", IDS_SETTINGS_INTERNET_TOGGLE_WIFI_ACCESSIBILITY_LABEL}, {"knownNetworksAll", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_ALL}, @@ -642,6 +636,7 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_REMOVE_PREFERRED}, {"knownNetworksMenuForget", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS_MENU_FORGET}, + {"mobileNetworkScanningLabel", IDS_MOBILE_NETWORK_SCANNING_MESSAGE}, {"networkAllowDataRoaming", IDS_SETTINGS_SETTINGS_NETWORK_ALLOW_DATA_ROAMING}, {"networkAllowDataRoamingEnabledHome", @@ -819,16 +814,17 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { }; html_source->AddLocalizedStrings(kLocalizedStrings); - network_element::AddLocalizedStrings(html_source); - network_element::AddOncLocalizedStrings(html_source); - network_element::AddDetailsLocalizedStrings(html_source); - network_element::AddConfigLocalizedStrings(html_source); - network_element::AddErrorLocalizedStrings(html_source); + ui::network_element::AddLocalizedStrings(html_source); + ui::network_element::AddOncLocalizedStrings(html_source); + ui::network_element::AddDetailsLocalizedStrings(html_source); + ui::network_element::AddConfigLocalizedStrings(html_source); + ui::network_element::AddErrorLocalizedStrings(html_source); cellular_setup::AddNonStringLoadTimeData(html_source); - if (features::IsCellularActivationUiEnabled()) { - cellular_setup::AddLocalizedStrings(html_source); - } + cellular_setup::AddLocalizedStrings(html_source); + html_source->AddBoolean("allowPerNetworkRoaming", + base::FeatureList::IsEnabled( + ash::features::kCellularAllowPerNetworkRoaming)); html_source->AddBoolean("showTechnologyBadge", !ash::features::IsSeparateNetworkIconsEnabled()); html_source->AddBoolean( @@ -1077,7 +1073,7 @@ void InternetSection::OnDeviceList( // check is in OnNetworkList(). if (device->device_state == DeviceStateType::kEnabled) { updater.AddSearchTags(GetCellularOnSearchConcepts()); - if (features::IsCellularActivationUiEnabled() && IsESimCapable()) + if (IsESimCapable()) updater.AddSearchTags(GetCellularESimCapableSearchTerms()); } else if (device->device_state == DeviceStateType::kDisabled) { updater.AddSearchTags(GetCellularOffSearchConcepts()); @@ -1146,10 +1142,7 @@ void InternetSection::OnNetworkList( active_cellular_iccid_.has_value() && network->type_state->get_cellular()->iccid == *active_cellular_iccid_; - if (!features::IsCellularActivationUiEnabled()) { - active_cellular_guid_ = network->guid; - updater.AddSearchTags(GetCellularSearchConcepts()); - } else if (is_primary_cellular_network) { + if (is_primary_cellular_network) { active_cellular_guid_ = network->guid; updater.AddSearchTags(GetCellularSearchConcepts()); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc index f2d1346345f..a757b4fd771 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.cc @@ -7,7 +7,6 @@ #include <string> #include <utility> -#include "ash/constants/ash_features.h" #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/values.h" @@ -50,16 +49,12 @@ void AddKerberosTitleStrings(content::WebUIDataSource* html_source) { html_source->AddLocalizedStrings(kLocalizedStrings); } -// Adds flags related to Kerberos settings visibility and its corresponding -// settings section. -void AddKerberosSettingsVisibilityFlags( +// Adds load time boolean corresponding to Kerberos enable state. +void AddKerberosEnabledFlag( content::WebUIDataSource* html_source, KerberosCredentialsManager* kerberos_credentials_manager) { html_source->AddBoolean("isKerberosEnabled", IsKerberosEnabled(kerberos_credentials_manager)); - html_source->AddBoolean( - "isKerberosSettingsSectionEnabled", - chromeos::features::IsKerberosSettingsSectionEnabled()); } // Adds load time strings to Kerberos Add Accounts dialog. @@ -189,7 +184,7 @@ KerberosAccountsHandler::CreateIfKerberosEnabled(Profile* profile) { void KerberosAccountsHandler::AddLoadTimeKerberosStrings( content::WebUIDataSource* html_source, KerberosCredentialsManager* kerberos_credentials_manager) { - AddKerberosSettingsVisibilityFlags(html_source, kerberos_credentials_manager); + AddKerberosEnabledFlag(html_source, kerberos_credentials_manager); AddKerberosTitleStrings(html_source); AddKerberosAccountsPageStrings(html_source); AddKerberosAddAccountDialogStrings(html_source); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.cc index f94798ccf67..4bda75a807d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.cc @@ -4,7 +4,6 @@ #include "chrome/browser/ui/webui/settings/chromeos/kerberos_section.h" -#include "ash/constants/ash_features.h" #include "base/no_destructor.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h" @@ -71,10 +70,6 @@ KerberosSection::KerberosSection( KerberosCredentialsManager* kerberos_credentials_manager) : OsSettingsSection(profile, search_tag_registry), kerberos_credentials_manager_(kerberos_credentials_manager) { - // No search tags are registered if KerberosSettingsSection flag is disabled. - if (!chromeos::features::IsKerberosSettingsSectionEnabled()) - return; - if (kerberos_credentials_manager_) { // Kerberos search tags are added/removed dynamically. kerberos_credentials_manager_->AddObserver(this); @@ -83,10 +78,6 @@ KerberosSection::KerberosSection( } KerberosSection::~KerberosSection() { - // No observer has been added if KerberosSettingsSection flag is disabled. - if (!chromeos::features::IsKerberosSettingsSectionEnabled()) - return; - if (kerberos_credentials_manager_) kerberos_credentials_manager_->RemoveObserver(this); } @@ -100,10 +91,6 @@ void KerberosSection::AddLoadTimeData(content::WebUIDataSource* html_source) { } void KerberosSection::AddHandlers(content::WebUI* web_ui) { - // No handler is created/added if KerberosSettingsSection flag is disabled. - if (!chromeos::features::IsKerberosSettingsSectionEnabled()) - return; - std::unique_ptr<chromeos::settings::KerberosAccountsHandler> kerberos_accounts_handler = KerberosAccountsHandler::CreateIfKerberosEnabled(profile()); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.h index b84e9081e7b..34f951702b0 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/kerberos_section.h @@ -21,7 +21,7 @@ namespace settings { class SearchTagRegistry; // Provides UI strings and search tags for Kerberos settings. Search tags are -// only shown if they are allowed by policy/flags. +// only added if the feature is enabled by policy. class KerberosSection : public OsSettingsSection, public KerberosCredentialsManager::Observer { public: diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.cc index 970f827d83e..2b9b79b39a3 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.cc @@ -143,12 +143,31 @@ const std::vector<SearchConcept>& GetEmojiSuggestionSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetPredictiveWritingSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_LANGUAGES_PREDICTIVE_WRITING, + mojom::kSmartInputsSubpagePath, + mojom::SearchResultIcon::kGlobe, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kShowPredictiveWriting}, + {IDS_OS_SETTINGS_TAG_LANGUAGES_PREDICTIVE_WRITING_ALT1, + IDS_OS_SETTINGS_TAG_LANGUAGES_PREDICTIVE_WRITING_ALT2, + SearchConcept::kAltTagEnd}}, + }); + return *tags; +} + bool IsAssistivePersonalInfoAllowed() { return !features::IsGuestModeActive() && base::FeatureList::IsEnabled( ::chromeos::features::kAssistPersonalInfo); } +bool IsPredictiveWritingAllowed() { + return chromeos::features::IsAssistiveMultiWordEnabled(); +} + // TODO(crbug/1113611): As Smart Inputs page is renamed to Suggestions. // All related strings, function names and filenames should be renamed as well. void AddSmartInputsStrings(content::WebUIDataSource* html_source, @@ -165,12 +184,18 @@ void AddSmartInputsStrings(content::WebUIDataSource* html_source, {"emojiSuggestionTitle", IDS_SETTINGS_SUGGESTIONS_EMOJI_SUGGESTION_TITLE}, {"emojiSuggestionDescription", IDS_SETTINGS_SUGGESTIONS_EMOJI_SUGGESTION_DESCRIPTION}, + {"predictiveWritingTitle", + IDS_SETTINGS_SUGGESTIONS_PREDICTIVE_WRITING_TITLE}, + {"predictiveWritingDescription", + IDS_SETTINGS_SUGGESTIONS_PREDICTIVE_WRITING_DESCRIPTION}, }; html_source->AddLocalizedStrings(kLocalizedStrings); html_source->AddBoolean("allowAssistivePersonalInfo", IsAssistivePersonalInfoAllowed()); html_source->AddBoolean("allowEmojiSuggestion", is_emoji_suggestion_allowed); + html_source->AddBoolean("allowPredictiveWriting", + IsPredictiveWritingAllowed()); } void AddInputMethodOptionsStrings(content::WebUIDataSource* html_source) { @@ -197,6 +222,12 @@ void AddInputMethodOptionsStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION}, {"inputMethodOptionsXkbLayout", IDS_SETTINGS_INPUT_METHOD_OPTIONS_XKB_LAYOUT}, + {"inputMethodOptionsZhuyinKeyboardLayout", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_KEYBOARD_LAYOUT}, + {"inputMethodOptionsZhuyinSelectKeys", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_SELECT_KEYS}, + {"inputMethodOptionsZhuyinPageSize", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_PAGE_SIZE}, {"inputMethodOptionsEditUserDict", IDS_SETTINGS_INPUT_METHOD_OPTIONS_EDIT_USER_DICT}, {"inputMethodOptionsPinyinChinesePunctuation", @@ -219,6 +250,18 @@ void AddInputMethodOptionsStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION_AGGRESSIVE}, {"inputMethodOptionsUsKeyboard", IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_US}, + {"inputMethodOptionsZhuyinLayoutDefault", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_DEFAULT}, + {"inputMethodOptionsZhuyinLayoutIBM", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_IBM}, + {"inputMethodOptionsZhuyinLayoutEten", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ZHUYIN_LAYOUT_ETEN}, + {"inputMethodOptionsKoreanLayout", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_KOREAN_LAYOUT}, + {"inputMethodOptionsKoreanSyllableInput", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_KOREAN_SYLLABLE_INPUT}, + {"inputMethodOptionsKoreanShowHangulCandidate", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_KOREAN_SHOW_HANGUL_CANDIDATE}, {"inputMethodOptionsDvorakKeyboard", IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_DVORAK}, {"inputMethodOptionsColemakKeyboard", @@ -238,8 +281,6 @@ void AddLanguagesPageStringsV2(content::WebUIDataSource* html_source) { IDS_OS_SETTINGS_LANGUAGES_LANGUAGES_PREFERENCE_TITLE}, {"websiteLanguagesTitle", IDS_OS_SETTINGS_LANGUAGES_WEBSITE_LANGUAGES_TITLE}, - {"translateTargetLabel", - IDS_OS_SETTINGS_LANGUAGES_TRANSLATE_TARGET_LABEL}, {"offerToTranslateThisLanguage", IDS_OS_SETTINGS_LANGUAGES_OFFER_TO_TRANSLATE_THIS_LANGUAGE}, {"offerTranslationLabel", @@ -276,6 +317,12 @@ void AddLanguagesPageStringsV2(content::WebUIDataSource* html_source) { IDS_OS_SETTINGS_LANGUAGES_WEBSITE_LANGUAGES_DESCRIPTION, base::ASCIIToUTF16(chrome::kLanguageSettingsLearnMoreUrl))); html_source->AddString( + "translateTargetLabel", + l10n_util::GetStringUTF16( + ash::features::IsQuickAnswersV2Enabled() + ? IDS_OS_SETTINGS_LANGUAGES_TRANSLATE_TARGET_LABEL_WITH_QUICK_ANSWERS + : IDS_OS_SETTINGS_LANGUAGES_TRANSLATE_TARGET_LABEL)); + html_source->AddString( "changeDeviceLanguageDialogDescription", l10n_util::GetStringFUTF16( IDS_OS_SETTINGS_LANGUAGES_CHANGE_DEVICE_LANGUAGE_DIALOG_DESCRIPTION, @@ -305,6 +352,10 @@ void AddInputPageStringsV2(content::WebUIDataSource* html_source) { {"inputMethodNotAllowed", IDS_OS_SETTINGS_LANGUAGES_INPUT_METHOD_NOT_ALLOWED}, {"spellCheckTitle", IDS_OS_SETTINGS_LANGUAGES_SPELL_CHECK_TITLE}, + {"spellAndGrammarCheckTitle", + IDS_OS_SETTINGS_LANGUAGES_SPELL_AND_GRAMMAR_CHECK_TITLE}, + {"spellAndGrammarCheckDescription", + IDS_OS_SETTINGS_LANGUAGES_SPELL_AND_GRAMMAR_CHECK_DESCRIPTION}, {"spellCheckEnhancedLabel", IDS_OS_SETTINGS_LANGUAGES_SPELL_CHECK_ENHANCED_LABEL}, {"spellCheckLanguagesListTitle", @@ -370,12 +421,15 @@ LanguagesSection::LanguagesSection(Profile* profile, updater.AddSearchTags(GetInputPageSearchConceptsV2()); UpdateSpellCheckSearchTags(); - if (IsAssistivePersonalInfoAllowed() || IsEmojiSuggestionAllowed()) { + if (IsAssistivePersonalInfoAllowed() || IsEmojiSuggestionAllowed() || + IsPredictiveWritingAllowed()) { updater.AddSearchTags(GetSmartInputsSearchConcepts()); if (IsAssistivePersonalInfoAllowed()) updater.AddSearchTags(GetAssistivePersonalInfoSearchConcepts()); if (IsEmojiSuggestionAllowed()) updater.AddSearchTags(GetEmojiSuggestionSearchConcepts()); + if (IsPredictiveWritingAllowed()) + updater.AddSearchTags(GetPredictiveWritingSearchConcepts()); } } @@ -407,11 +461,16 @@ void LanguagesSection::AddLoadTimeData(content::WebUIDataSource* html_source) { AddLanguagesPageStringsV2(html_source); AddInputPageStringsV2(html_source); - html_source->AddBoolean("imeOptionsInSettings", - base::FeatureList::IsEnabled( - ::chromeos::features::kImeOptionsInSettings)); + html_source->AddBoolean( + "imeOptionsInSettings", + base::FeatureList::IsEnabled( + ::chromeos::features::kImeOptionsInSettings) && + base::FeatureList::IsEnabled(::chromeos::features::kImeMojoDecoder)); html_source->AddBoolean("enableLanguageSettingsV2Update2", IsLanguageSettingsV2Update2Enabled()); + html_source->AddBoolean("onDeviceGrammarCheckEnabled", + base::FeatureList::IsEnabled( + ::chromeos::features::kOnDeviceGrammarCheck)); } void LanguagesSection::AddHandlers(content::WebUI* web_ui) { @@ -493,6 +552,7 @@ void LanguagesSection::RegisterHierarchy(HierarchyGenerator* generator) const { static constexpr mojom::Setting kSmartInputsFeaturesSettings[] = { mojom::Setting::kShowPersonalInformationSuggestions, mojom::Setting::kShowEmojiSuggestions, + mojom::Setting::kShowPredictiveWriting, }; RegisterNestedSettingBulk(mojom::Subpage::kSmartInputs, kSmartInputsFeaturesSettings, generator); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.cc index f26640c26a7..c5bc09dd485 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.cc @@ -11,11 +11,11 @@ #include "base/i18n/number_formatting.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h" +#include "chrome/browser/ash/policy/handlers/minimum_version_policy_handler.h" #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/policy/minimum_version_policy_handler.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/plural_string_handler.h" @@ -23,6 +23,7 @@ #include "chrome/browser/ui/webui/settings/browser_lifetime_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h" #include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" @@ -49,23 +50,14 @@ void AddSearchInSettingsStrings(content::WebUIDataSource* html_source) { {"clearSearch", IDS_CLEAR_SEARCH}, }; html_source->AddLocalizedStrings(kLocalizedStrings); - - html_source->AddString( - "searchNoOsResultsHelp", - l10n_util::GetStringFUTF16( - IDS_SETTINGS_SEARCH_NO_RESULTS_HELP, - base::ASCIIToUTF16(chrome::kOsSettingsSearchHelpURL))); - - // TODO(crbug/1080777): Remove this flag and JS codepaths effected. - html_source->AddBoolean("newOsSettingsSearch", true); } void AddUpdateRequiredEolStrings(content::WebUIDataSource* html_source) { - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); + policy::BrowserPolicyConnectorAsh* connector = + g_browser_process->platform_part()->browser_policy_connector_ash(); policy::MinimumVersionPolicyHandler* handler = connector->GetMinimumVersionPolicyHandler(); - bool device_managed = connector->IsEnterpriseManaged(); + bool device_managed = connector->IsDeviceEnterpriseManaged(); // |eol_return_banner_text| contains the update required end of life banner // text which is left empty when the banner should not be shown. @@ -131,6 +123,7 @@ void MainSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"edit", IDS_SETTINGS_EDIT}, {"extensionsLinkTooltip", IDS_SETTINGS_MENU_EXTENSIONS_LINK_TOOLTIP}, {"learnMore", IDS_LEARN_MORE}, + {"shortcutBannerDismissed", IDS_SETTINGS_SHORTCUT_BANNER_DISMISSED}, {"menu", IDS_MENU}, {"menuButtonLabel", IDS_SETTINGS_MENU_BUTTON_LABEL}, {"moreActions", IDS_SETTINGS_MORE_ACTIONS}, @@ -172,6 +165,10 @@ void MainSection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddBoolean("isDeepLinkingEnabled", chromeos::features::IsDeepLinkingEnabled()); + html_source->AddBoolean( + "appManagementIntentSettingsEnabled", + base::FeatureList::IsEnabled(::features::kAppManagementIntentSettings)); + // Add the System Web App resources for Settings. html_source->AddResourcePath("icon-192.png", IDR_SETTINGS_LOGO_192); @@ -229,7 +226,7 @@ void MainSection::AddChromeOSUserStrings( ProfileHelper::Get()->GetUserByProfile(profile()); const user_manager::User* primary_user = user_manager::UserManager::Get()->GetPrimaryUser(); - std::string primary_user_email = primary_user->GetAccountId().GetUserEmail(); + std::string primary_user_email = primary_user->GetDisplayEmail(); html_source->AddString("primaryUserEmail", primary_user_email); html_source->AddBoolean("isActiveDirectoryUser", diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc index fa03b5bff73..df598d2e957 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc @@ -271,25 +271,20 @@ void MultideviceHandler::HandleGetPageContent(const base::ListValue* args) { void MultideviceHandler::HandleSetFeatureEnabledState( const base::ListValue* args) { - std::string callback_id; - bool result = args->GetString(0, &callback_id); - DCHECK(result); + const auto& list = args->GetList(); + DCHECK_GE(list.size(), 3u); + std::string callback_id = list[0].GetString(); - int feature_as_int; - result = args->GetInteger(1, &feature_as_int); - DCHECK(result); + int feature_as_int = list[1].GetInt(); auto feature = static_cast<multidevice_setup::mojom::Feature>(feature_as_int); DCHECK(multidevice_setup::mojom::IsKnownEnumValue(feature)); - bool enabled; - result = args->GetBoolean(2, &enabled); - DCHECK(result); + bool enabled = list[2].GetBool(); absl::optional<std::string> auth_token; - std::string possible_token_value; - if (args->GetString(3, &possible_token_value)) - auth_token = possible_token_value; + if (list.size() >= 4 && list[3].is_string()) + auth_token = list[3].GetString(); multidevice_setup_client_->SetFeatureEnabledState( feature, enabled, auth_token, @@ -540,7 +535,7 @@ void MultideviceHandler::NotifySmartLockSignInAllowedChanged() { bool MultideviceHandler::IsAuthTokenValid(const std::string& auth_token) { Profile* profile = Profile::FromWebUI(web_ui()); quick_unlock::QuickUnlockStorage* quick_unlock_storage = - chromeos::quick_unlock::QuickUnlockFactory::GetForProfile(profile); + quick_unlock::QuickUnlockFactory::GetForProfile(profile); return quick_unlock_storage->GetAuthToken() && auth_token == quick_unlock_storage->GetAuthToken()->Identifier(); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc index 264fd2e9449..52f9072b8b9 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc @@ -206,9 +206,10 @@ class MultideviceHandlerTest : public testing::Test { void CallGetPageContentData() { size_t call_data_count_before_call = test_web_ui()->call_data().size(); - base::ListValue args; - args.AppendString("handlerFunctionName"); - test_web_ui()->HandleReceivedMessage("getPageContentData", &args); + base::Value args(base::Value::Type::LIST); + args.Append("handlerFunctionName"); + test_web_ui()->HandleReceivedMessage("getPageContentData", + &base::Value::AsListValue(args)); EXPECT_EQ(call_data_count_before_call + 1u, test_web_ui()->call_data().size()); @@ -234,8 +235,9 @@ class MultideviceHandlerTest : public testing::Test { size_t call_data_count_before_call = test_web_ui()->call_data().size(); base::ListValue args; - args.AppendString("handlerFunctionName"); - test_web_ui()->HandleReceivedMessage("getAndroidSmsInfo", &args); + args.Append("handlerFunctionName"); + test_web_ui()->HandleReceivedMessage("getAndroidSmsInfo", + &base::Value::AsListValue(args)); ASSERT_EQ(call_data_count_before_call + 1u, test_web_ui()->call_data().size()); @@ -383,15 +385,16 @@ class MultideviceHandlerTest : public testing::Test { bool success) { size_t call_data_count_before_call = test_web_ui()->call_data().size(); - base::ListValue args; - args.AppendString("handlerFunctionName"); - args.AppendInteger(static_cast<int>(feature)); - args.AppendBoolean(enabled); + base::Value args(base::Value::Type::LIST); + args.Append("handlerFunctionName"); + args.Append(static_cast<int>(feature)); + args.Append(enabled); if (auth_token) - args.AppendString(*auth_token); + args.Append(*auth_token); base::ListValue empty_args; - test_web_ui()->HandleReceivedMessage("setFeatureEnabledState", &args); + test_web_ui()->HandleReceivedMessage("setFeatureEnabledState", + &base::Value::AsListValue(args)); fake_multidevice_setup_client() ->InvokePendingSetFeatureEnabledStateCallback( feature /* expected_feature */, enabled /* expected_enabled */, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.cc new file mode 100644 index 00000000000..5fa8398a945 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.cc @@ -0,0 +1,138 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h" + +#include "ash/public/cpp/message_center_ash.h" +#include "base/logging.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "components/services/app_service/public/cpp/types_util.h" +#include "components/services/app_service/public/mojom/types.mojom.h" + +namespace chromeos { +namespace settings { + +namespace { +app_notification::mojom::AppPtr CreateAppPtr(const apps::AppUpdate& update) { + apps::mojom::PermissionPtr permission_copy; + for (const auto& permission : update.Permissions()) { + if ((static_cast<app_management::mojom::PwaPermissionType>( + permission->permission_id) == + app_management::mojom::PwaPermissionType::NOTIFICATIONS) || + (static_cast<app_management::mojom::ArcPermissionType>( + permission->permission_id) == + app_management::mojom::ArcPermissionType::NOTIFICATIONS)) { + permission_copy = permission->Clone(); + break; + } + } + + auto app = app_notification::mojom::App::New(); + app->id = update.AppId(); + app->title = update.Name(); + app->notification_permission = std::move(permission_copy); + + return app; +} +} // namespace + +using app_notification::mojom::AppNotificationsHandler; +using app_notification::mojom::AppNotificationsObserver; + +AppNotificationHandler::AppNotificationHandler( + apps::AppServiceProxyChromeOs* app_service_proxy) + : app_service_proxy_(app_service_proxy) { + if (ash::MessageCenterAsh::Get()) { + ash::MessageCenterAsh::Get()->AddObserver(this); + } + // app_service_proxy_ = apps::AppServiceProxyFactory::GetForProfile(profile_); + Observe(&app_service_proxy_->AppRegistryCache()); +} + +AppNotificationHandler::~AppNotificationHandler() { + if (ash::MessageCenterAsh::Get()) { + ash::MessageCenterAsh::Get()->RemoveObserver(this); + } +} + +void AppNotificationHandler::AddObserver( + mojo::PendingRemote<app_notification::mojom::AppNotificationsObserver> + observer) { + observer_list_.Add(std::move(observer)); +} + +void AppNotificationHandler::BindInterface( + mojo::PendingReceiver<app_notification::mojom::AppNotificationsHandler> + receiver) { + if (receiver_.is_bound()) + receiver_.reset(); + receiver_.Bind(std::move(receiver)); +} + +void AppNotificationHandler::OnQuietModeChanged(bool in_quiet_mode) { + in_quiet_mode_ = in_quiet_mode; + for (const auto& observer : observer_list_) { + observer->OnQuietModeChanged(in_quiet_mode); + } +} + +void AppNotificationHandler::SetQuietMode(bool in_quiet_mode) { + ash::MessageCenterAsh::Get()->SetQuietMode(in_quiet_mode); +} + +void AppNotificationHandler::GetApps() { + std::vector<app_notification::mojom::AppPtr> apps; + app_service_proxy_->AppRegistryCache().ForEachApp( + [&apps](const apps::AppUpdate& update) { + if (update.ShowInManagement() != apps::mojom::OptionalBool::kTrue || + !apps_util::IsInstalled(update.Readiness())) { + return; + } + + // This statement only adds apps to the list if they are + // of app_type kArc or kWeb. + if (update.AppType() == apps::mojom::AppType::kArc) { + for (const auto& permission : update.Permissions()) { + if (static_cast<app_management::mojom::ArcPermissionType>( + permission->permission_id) == + app_management::mojom::ArcPermissionType::NOTIFICATIONS) { + apps.push_back(CreateAppPtr(update)); + break; + } + } + } else if (update.AppType() == apps::mojom::AppType::kWeb) { + for (const auto& permission : update.Permissions()) { + if (static_cast<app_management::mojom::PwaPermissionType>( + permission->permission_id) == + app_management::mojom::PwaPermissionType::NOTIFICATIONS) { + apps.push_back(CreateAppPtr(update)); + break; + } + } + } + }); + apps_ = std::move(apps); +} + +void AppNotificationHandler::OnAppUpdate(const apps::AppUpdate& update) { + // Each time an update is observed the entire list of apps is refetched. + // 'update' is a required parameter from the AppRegistryCache::Observer, + // but is not used in this implementation. + apps_.clear(); + GetApps(); +} + +void AppNotificationHandler::OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) { + Observe(nullptr); +} + +void AppNotificationHandler::NotifyPageReady() { + OnQuietModeChanged(ash::MessageCenterAsh::Get()->IsQuietMode()); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h new file mode 100644 index 00000000000..c56817a836c --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h @@ -0,0 +1,73 @@ +// Copyright (c) 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_APPS_PAGE_APP_NOTIFICATION_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_APPS_PAGE_APP_NOTIFICATION_HANDLER_H_ + +#include "ash/public/cpp/message_center_ash.h" +#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote_set.h" + +namespace apps { +class AppServiceProxyChromeOs; +} // namespace apps + +namespace chromeos { +namespace settings { + +class AppNotificationHandler + : public app_notification::mojom::AppNotificationsHandler, + public ash::MessageCenterAsh::Observer, + public apps::AppRegistryCache::Observer { + public: + explicit AppNotificationHandler( + apps::AppServiceProxyChromeOs* app_service_proxy); + ~AppNotificationHandler() override; + + // app_notification::mojom::AppNotificationHandler: + void AddObserver( + mojo::PendingRemote<app_notification::mojom::AppNotificationsObserver> + observer) override; + + void BindInterface( + mojo::PendingReceiver<app_notification::mojom::AppNotificationsHandler> + receiver); + + private: + friend class AppNotificationHandlerTest; + + // MessageCenterAsh::Observer override: + void OnQuietModeChanged(bool in_quiet_mode) override; + + // settings::mojom::AppNotificationHandler: + void SetQuietMode(bool in_quiet_mode) override; + void NotifyPageReady() override; + + // apps::AppRegistryCache::Observer: + void OnAppUpdate(const apps::AppUpdate& update) override; + void OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) override; + + void GetApps(); + + bool in_quiet_mode_; + + mojo::RemoteSet<app_notification::mojom::AppNotificationsObserver> + observer_list_; + + apps::AppServiceProxyChromeOs* app_service_proxy_; + std::vector<app_notification::mojom::AppPtr> apps_; + + mojo::Receiver<app_notification::mojom::AppNotificationsHandler> receiver_{ + this}; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_APPS_PAGE_APP_NOTIFICATION_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler_unittest.cc new file mode 100644 index 00000000000..366cb910f9c --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler_unittest.cc @@ -0,0 +1,192 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h" + +#include <memory> +#include <utility> +#include <vector> + +#include "ash/public/cpp/message_center_ash.h" +#include "base/logging.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/ui/webui/app_management/app_management.mojom.h" +#include "chrome/test/base/testing_profile.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/mojom/types.mojom.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace settings { + +namespace { + +class FakeMessageCenterAsh : public ash::MessageCenterAsh { + public: + FakeMessageCenterAsh() = default; + ~FakeMessageCenterAsh() override = default; + + // MessageCenterAsh override: + void SetQuietMode(bool in_quiet_mode) override { + if (in_quiet_mode != in_quiet_mode_) { + in_quiet_mode_ = in_quiet_mode; + NotifyOnQuietModeChanged(in_quiet_mode); + } + } + + bool IsQuietMode() const override { return in_quiet_mode_; } + + private: + bool in_quiet_mode_ = false; +}; + +} // namespace + +class AppNotificationHandlerTest : public testing::Test { + public: + AppNotificationHandlerTest() + : task_environment_(content::BrowserTaskEnvironment::REAL_IO_THREAD), + profile_(std::make_unique<TestingProfile>()) {} + ~AppNotificationHandlerTest() override = default; + + void SetUp() override { + ash::MessageCenterAsh::SetForTesting(&message_center_ash_); + app_service_proxy_ = + std::make_unique<apps::AppServiceProxyChromeOs>(profile_.get()); + handler_ = + std::make_unique<AppNotificationHandler>(app_service_proxy_.get()); + } + + void TearDown() override { + handler_.reset(); + app_service_proxy_.reset(); + ash::MessageCenterAsh::SetForTesting(nullptr); + } + + protected: + bool GetHandlerQuietModeState() { return handler_->in_quiet_mode_; } + + void SetQuietModeState(bool quiet_mode_enabled) { + handler_->SetQuietMode(quiet_mode_enabled); + } + + void CreateAndStoreFakeApp( + std::string fake_id, + apps::mojom::AppType app_type, + std::uint32_t permission_type, + apps::mojom::PermissionValueType permission_value_type) { + std::vector<apps::mojom::PermissionPtr> fake_permissions; + apps::mojom::PermissionPtr fake_permission = apps::mojom::Permission::New(); + fake_permission->permission_id = permission_type; + fake_permission->value_type = permission_value_type; + fake_permission->value = /*True=*/1; + fake_permission->is_managed = false; + + fake_permissions.push_back(fake_permission.Clone()); + + std::vector<apps::mojom::AppPtr> fake_apps; + apps::mojom::AppPtr fake_app = apps::mojom::App::New(); + fake_app->app_type = app_type; + fake_app->app_id = fake_id; + fake_app->show_in_management = apps::mojom::OptionalBool::kTrue; + fake_app->readiness = apps::mojom::Readiness::kReady; + fake_app->permissions = std::move(fake_permissions); + + fake_apps.push_back(fake_app.Clone()); + + UpdateAppRegistryCache(fake_apps, app_type); + } + + void UpdateAppRegistryCache(std::vector<apps::mojom::AppPtr>& fake_apps, + apps::mojom::AppType app_type) { + app_service_proxy_->AppRegistryCache().OnApps(std::move(fake_apps), + app_type, false); + } + + bool CheckIfFakeAppInList(std::string fake_id) { + bool app_found = false; + + for (app_notification::mojom::AppPtr const& app : handler_->apps_) { + if (app->id.compare(fake_id) == 0) { + app_found = true; + break; + } + } + return app_found; + } + + private: + std::unique_ptr<AppNotificationHandler> handler_; + content::BrowserTaskEnvironment task_environment_; + std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<apps::AppServiceProxyChromeOs> app_service_proxy_; + FakeMessageCenterAsh message_center_ash_; +}; + +// Tests for update of in_quiet_mode_ variable by MessageCenterAsh observer +// OnQuietModeChange() after quiet mode state change between true and false. +TEST_F(AppNotificationHandlerTest, TestOnQuietModeChanged) { + ash::MessageCenterAsh::Get()->SetQuietMode(true); + EXPECT_TRUE(GetHandlerQuietModeState()); + + ash::MessageCenterAsh::Get()->SetQuietMode(false); + EXPECT_FALSE(GetHandlerQuietModeState()); +} + +// Tests for update of in_quiet_mode_ variable after setting state +// with MessageCenterAsh SetQuietMode() true and false. +TEST_F(AppNotificationHandlerTest, TestSetQuietMode) { + SetQuietModeState(true); + EXPECT_TRUE(GetHandlerQuietModeState()); + + SetQuietModeState(false); + EXPECT_FALSE(GetHandlerQuietModeState()); +} + +// Tests the filtering of the GetApps() function +// by creating multiple fake apps with different parameters +// and confirming that GetApps() only adds the correct ones. +// GetApps() should only add kArc and kWeb apps +// with the NOTIFICATIONS permission. +TEST_F(AppNotificationHandlerTest, TestGetAppsFiltering) { + CreateAndStoreFakeApp( + "arcAppWithNotifications", apps::mojom::AppType::kArc, + static_cast<std::uint32_t>( + app_management::mojom::ArcPermissionType::NOTIFICATIONS), + apps::mojom::PermissionValueType::kBool); + + CreateAndStoreFakeApp( + "webAppWithNotifications", apps::mojom::AppType::kWeb, + static_cast<std::uint32_t>( + app_management::mojom::PwaPermissionType::NOTIFICATIONS), + apps::mojom::PermissionValueType::kBool); + + CreateAndStoreFakeApp("arcAppWithCamera", apps::mojom::AppType::kArc, + static_cast<std::uint32_t>( + app_management::mojom::ArcPermissionType::CAMERA), + apps::mojom::PermissionValueType::kBool); + + CreateAndStoreFakeApp( + "webAppWithGeolocation", apps::mojom::AppType::kWeb, + static_cast<std::uint32_t>( + app_management::mojom::PwaPermissionType::GEOLOCATION), + apps::mojom::PermissionValueType::kBool); + + CreateAndStoreFakeApp( + "pluginVmAppWithPrinting", apps::mojom::AppType::kPluginVm, + static_cast<std::uint32_t>( + app_management::mojom::PluginVmPermissionType::PRINTING), + apps::mojom::PermissionValueType::kBool); + + EXPECT_TRUE(CheckIfFakeAppInList("arcAppWithNotifications")); + EXPECT_TRUE(CheckIfFakeAppInList("webAppWithNotifications")); + EXPECT_FALSE(CheckIfFakeAppInList("arcAppWithCamera")); + EXPECT_FALSE(CheckIfFakeAppInList("webAppWithGeolocation")); + EXPECT_FALSE(CheckIfFakeAppInList("pluginVmAppWithPrinting")); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/BUILD.gn b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/BUILD.gn new file mode 100644 index 00000000000..1ac212210e5 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/BUILD.gn @@ -0,0 +1,14 @@ +# Copyright 2021 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojom") { + sources = [ "app_notification_handler.mojom" ] + + public_deps = [ + "//components/services/app_service/public/mojom", + "//mojo/public/mojom/base", + ] +} diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/OWNERS b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/OWNERS new file mode 100644 index 00000000000..20352ec8fe9 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/OWNERS @@ -0,0 +1,6 @@ +# Primary Owners +jimmyxgong@chromium.org +hsuregan@chromium.org + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
\ No newline at end of file diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom new file mode 100644 index 00000000000..890843935d2 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom @@ -0,0 +1,45 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module chromeos.settings.app_notification.mojom; + +import "components/services/app_service/public/mojom/types.mojom"; + +// Implementation of App +// Contains the app's id, title, and only the notification permission, as this +// is the only permission used in the AppNotificationsHandler. +// Only represents Apps with an app_type of kArc or kWeb (Pwa). +struct App { + // Unique identifier of the App. + string id; + + // The title of the app, + // this field may be null when this struct is used to signal updates. + string? title; + + // Contains the current permission state of the App's notification. + apps.mojom.Permission notification_permission; +}; + +// Browser interface. +// Interface for for fetching and setting App notification +// properties in OSSettings. +interface AppNotificationsHandler { + // Notify the App Notification Page of the quiet mode state. + NotifyPageReady(); + + // Updates QuietMode to enabled or disabled based on toggle state. + SetQuietMode(bool enabled); + + // Binds remote and notifies receiver in OsSettings app notifications page UI. + AddObserver(pending_remote<AppNotificationsObserver> observer); +}; + +// Frontend interface. +// Observer interface that sends remote updates to the App notifications +// subpage in OSSettings. +interface AppNotificationsObserver { + // Notifies client when the DoNotDisturb (QuietMode) state changes. + OnQuietModeChanged(bool enabled); +};
\ No newline at end of file diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.cc index 752b433e03b..e06b749c9ee 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.cc @@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/feature_list.h" #include "chrome/browser/ui/webui/settings/chromeos/hierarchy.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" @@ -53,7 +54,9 @@ OsSettingsManager::OsSettingsManager( std::make_unique<SearchHandler>(search_tag_registry_.get(), sections_.get(), hierarchy_.get(), - local_search_service_proxy)) {} + local_search_service_proxy)), + app_notification_handler_( + std::make_unique<AppNotificationHandler>(app_service_proxy)) {} OsSettingsManager::~OsSettingsManager() = default; @@ -71,6 +74,7 @@ void OsSettingsManager::AddHandlers(content::WebUI* web_ui) { void OsSettingsManager::Shutdown() { // Note: These must be deleted in the opposite order of their creation to // prevent against UAF violations. + app_notification_handler_.reset(); search_handler_.reset(); settings_user_action_tracker_.reset(); hierarchy_.reset(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h index 89951d980d0..b7f28fc1a3e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h @@ -60,6 +60,7 @@ class OsSettingsSections; class SearchHandler; class SearchTagRegistry; class SettingsUserActionTracker; +class AppNotificationHandler; // Manager for the Chrome OS settings page. This class is implemented as a // KeyedService, so one instance of the class is intended to be active for the @@ -115,6 +116,10 @@ class OsSettingsManager : public KeyedService { // Adds SettingsPageUIHandlers to an OS settings instance. void AddHandlers(content::WebUI* web_ui); + AppNotificationHandler* app_notification_handler() { + return app_notification_handler_.get(); + } + SearchHandler* search_handler() { return search_handler_.get(); } SettingsUserActionTracker* settings_user_action_tracker() { @@ -134,6 +139,7 @@ class OsSettingsManager : public KeyedService { std::unique_ptr<Hierarchy> hierarchy_; std::unique_ptr<SettingsUserActionTracker> settings_user_action_tracker_; std::unique_ptr<SearchHandler> search_handler_; + std::unique_ptr<AppNotificationHandler> app_notification_handler_; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc index 6a1931dcdfa..fd3d2f2e372 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.cc @@ -15,7 +15,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h" #include "chromeos/components/local_search_service/public/cpp/local_search_service_proxy_factory.h" @@ -44,7 +44,7 @@ OsSettingsManagerFactory::OsSettingsManagerFactory() local_search_service::LocalSearchServiceProxyFactory::GetInstance()); DependsOn(multidevice_setup::MultiDeviceSetupClientFactory::GetInstance()); DependsOn(phonehub::PhoneHubManagerFactory::GetInstance()); - DependsOn(ProfileSyncServiceFactory::GetInstance()); + DependsOn(SyncServiceFactory::GetInstance()); DependsOn(SupervisedUserServiceFactory::GetInstance()); DependsOn(KerberosCredentialsManagerFactory::GetInstance()); DependsOn(ArcAppListPrefsFactory::GetInstance()); @@ -75,7 +75,7 @@ KeyedService* OsSettingsManagerFactory::BuildServiceInstanceFor( GetForBrowserContext(context), multidevice_setup::MultiDeviceSetupClientFactory::GetForProfile(profile), phonehub::PhoneHubManagerFactory::GetForProfile(profile), - ProfileSyncServiceFactory::GetForProfile(profile), + SyncServiceFactory::GetForProfile(profile), SupervisedUserServiceFactory::GetForProfile(profile), kerberos_credentials_manager, ArcAppListPrefsFactory::GetForBrowserContext(profile), diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_unittest.cc index 5524951c4b6..df0fc05b939 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_manager_unittest.cc @@ -17,7 +17,7 @@ #include "chrome/browser/chromeos/printing/cups_printers_manager_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/constants_util.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" @@ -63,7 +63,7 @@ class OsSettingsManagerTest : public testing::Test { multidevice_setup::MultiDeviceSetupClientFactory::GetForProfile( profile), phonehub::PhoneHubManagerFactory::GetForProfile(profile), - ProfileSyncServiceFactory::GetForProfile(profile), + SyncServiceFactory::GetForProfile(profile), SupervisedUserServiceFactory::GetForProfile(profile), kerberos_credentials_manager, ArcAppListPrefsFactory::GetForBrowserContext(profile), diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.cc index 1679131226a..9c6d9698ca2 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.cc @@ -65,7 +65,7 @@ OsSettingsSections::OsSettingsSections( auto people_section = std::make_unique<PeopleSection>( profile, search_tag_registry, sync_service, supervised_user_service, - kerberos_credentials_manager, identity_manager, profile->GetPrefs()); + identity_manager, profile->GetPrefs()); sections_map_[mojom::Section::kPeople] = people_section.get(); sections_.push_back(std::move(people_section)); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc index b56089a88e0..5bc33396cb2 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc @@ -7,6 +7,7 @@ #include <utility> #include "ash/constants/ash_features.h" +#include "ash/public/cpp/bluetooth_config_service.h" #include "ash/public/cpp/esim_manager.h" #include "ash/public/cpp/network_config_service.h" #include "base/metrics/histogram_functions.h" @@ -17,6 +18,7 @@ #include "chrome/browser/nearby_sharing/nearby_sharing_service_impl.h" #include "chrome/browser/ui/webui/managed_ui_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_apps_page/app_notification_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h" #include "chrome/browser/ui/webui/settings/chromeos/pref_names.h" @@ -115,6 +117,14 @@ void OSSettingsUI::BindInterface( } void OSSettingsUI::BindInterface( + mojo::PendingReceiver<app_notification::mojom::AppNotificationsHandler> + receiver) { + OsSettingsManagerFactory::GetForProfile(Profile::FromWebUI(web_ui())) + ->app_notification_handler() + ->BindInterface(std::move(receiver)); +} + +void OSSettingsUI::BindInterface( mojo::PendingReceiver<app_management::mojom::PageHandlerFactory> receiver) { if (!app_management_page_handler_factory_) { app_management_page_handler_factory_ = @@ -164,6 +174,13 @@ void OSSettingsUI::BindInterface( service->GetContactManager()->Bind(std::move(receiver)); } +void OSSettingsUI::BindInterface( + mojo::PendingReceiver<bluetooth_config::mojom::CrosBluetoothConfig> + receiver) { + DCHECK(features::IsBluetoothRevampEnabled()); + ash::GetBluetoothConfigService(std::move(receiver)); +} + WEB_UI_CONTROLLER_TYPE_IMPL(OSSettingsUI) } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h index e06579b1244..368c2de04e9 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.h @@ -13,8 +13,10 @@ #include "chrome/browser/ui/webui/nearby_share/nearby_share.mojom.h" #include "chrome/browser/ui/webui/nearby_share/public/mojom/nearby_share_settings.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/app_management/app_management_page_handler_factory.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_apps_page/mojom/app_notification_handler.mojom-forward.h" #include "chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom-forward.h" #include "chrome/browser/ui/webui/webui_load_timer.h" +#include "chromeos/services/bluetooth_config/public/mojom/cros_bluetooth_config.mojom-forward.h" #include "chromeos/services/cellular_setup/public/mojom/cellular_setup.mojom-forward.h" #include "chromeos/services/cellular_setup/public/mojom/esim_manager.mojom-forward.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" @@ -64,6 +66,12 @@ class OSSettingsUI : public ui::MojoWebUIController { // passing the pending receiver that will be internally bound. void BindInterface(mojo::PendingReceiver<mojom::SearchHandler> receiver); + // Instantiates implementor of the mojom::AppNotificationsHandler mojo + // interface passing the pending receiver that will be internally bound. + void BindInterface( + mojo::PendingReceiver<app_notification::mojom::AppNotificationsHandler> + receiver); + // Instantiates implementor of the mojom::PageHandlerFactory mojo interface // passing the pending receiver that will be internally bound. void BindInterface( @@ -84,6 +92,12 @@ class OSSettingsUI : public ui::MojoWebUIController { void BindInterface( mojo::PendingReceiver<nearby_share::mojom::ContactManager> receiver); + // Instantiates implementor of the mojom::CrosBluetoothConfig mojo interface + // passing the pending receiver that will be internally bound. + void BindInterface( + mojo::PendingReceiver<bluetooth_config::mojom::CrosBluetoothConfig> + receiver); + private: base::TimeTicks time_when_opened_; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.cc index 0fd6de18db8..de1fbb976ed 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.cc @@ -7,7 +7,6 @@ #include "ash/components/account_manager/account_manager_factory.h" #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" -#include "ash/public/cpp/ash_features.h" #include "base/bind.h" #include "base/i18n/number_formatting.h" #include "base/metrics/histogram_functions.h" @@ -28,7 +27,6 @@ #include "chrome/browser/ui/webui/chromeos/sync/os_sync_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h" -#include "chrome/browser/ui/webui/settings/chromeos/kerberos_accounts_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h" #include "chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h" @@ -37,12 +35,12 @@ #include "chrome/browser/ui/webui/settings/profile_info_handler.h" #include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h" #include "chrome/browser/ui/webui/webui_util.h" -#include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "components/account_manager_core/account_manager_facade.h" +#include "components/account_manager_core/pref_names.h" #include "components/google/core/common/google_util.h" #include "components/omnibox/common/omnibox_features.h" #include "components/prefs/pref_service.h" @@ -182,7 +180,7 @@ const std::vector<SearchConcept>& GetRemoveAccountSearchConcepts() { return *tags; } -const std::vector<SearchConcept>& GetNonSplitSyncSearchConcepts() { +const std::vector<SearchConcept>& GetNonCategorizedSyncSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_SYNC_AND_GOOGLE_SERVICES, mojom::kSyncDeprecatedSubpagePath, @@ -226,7 +224,8 @@ const std::vector<SearchConcept>& GetNonSplitSyncSearchConcepts() { return *tags; } -const std::vector<SearchConcept>& GetSplitSyncSearchConcepts() { +const std::vector<SearchConcept>& GetCategorizedSyncSearchConcepts() { + DCHECK(chromeos::features::IsSyncSettingsCategorizationEnabled()); static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_SYNC, mojom::kSyncSubpagePath, @@ -238,7 +237,8 @@ const std::vector<SearchConcept>& GetSplitSyncSearchConcepts() { return *tags; } -const std::vector<SearchConcept>& GetSplitSyncOnSearchConcepts() { +const std::vector<SearchConcept>& GetSyncOnSearchConcepts() { + DCHECK(chromeos::features::IsSyncConsentOptionalEnabled()); static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_SYNC_TURN_OFF, mojom::kSyncSubpagePath, @@ -251,7 +251,8 @@ const std::vector<SearchConcept>& GetSplitSyncOnSearchConcepts() { return *tags; } -const std::vector<SearchConcept>& GetSplitSyncOffSearchConcepts() { +const std::vector<SearchConcept>& GetSyncOffSearchConcepts() { + DCHECK(chromeos::features::IsSyncConsentOptionalEnabled()); static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_SYNC_TURN_ON, mojom::kSyncSubpagePath, @@ -264,36 +265,6 @@ const std::vector<SearchConcept>& GetSplitSyncOffSearchConcepts() { return *tags; } -const std::vector<SearchConcept>& GetKerberosSearchConcepts() { - static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_KERBEROS_ADD, - mojom::kKerberosAccountsSubpagePath, - mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAddKerberosTicket}}, - {IDS_OS_SETTINGS_TAG_KERBEROS_REMOVE, - mojom::kKerberosAccountsSubpagePath, - mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kRemoveKerberosTicket}}, - {IDS_OS_SETTINGS_TAG_KERBEROS, - mojom::kKerberosAccountsSubpagePath, - mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kKerberosAccounts}}, - {IDS_OS_SETTINGS_TAG_KERBEROS_ACTIVE, - mojom::kKerberosAccountsSubpagePath, - mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kSetActiveKerberosTicket}}, - }); - return *tags; -} - const std::vector<SearchConcept>& GetFingerprintSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_FINGERPRINT_ADD, @@ -399,13 +370,15 @@ void AddAccountManagerPageStrings(content::WebUIDataSource* html_source, {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER_V2}, {"accountListHeaderChild", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER_CHILD}, - {"accountManagerDescription", - IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION_V2}, {"accountManagerChildDescription", IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_DESCRIPTION_V2}, {"accountManagerSecondaryAccountsDisabledText", IDS_SETTINGS_ACCOUNT_MANAGER_SECONDARY_ACCOUNTS_DISABLED_TEXT_V2}, }; + html_source->AddString( + "accountManagerDescription", + l10n_util::GetStringFUTF16(IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION_V2, + ui::GetChromeOSDeviceName())); html_source->AddLocalizedStrings(kLocalizedStringsV2); } else { static constexpr webui::LocalizedString kLocalizedStringsV1[] = { @@ -470,13 +443,11 @@ void AddLockScreenPageStrings(content::WebUIDataSource* html_source, }; html_source->AddLocalizedStrings(kLocalizedStrings); - html_source->AddBoolean("quickUnlockEnabled", - chromeos::quick_unlock::IsPinEnabled(pref_service)); + html_source->AddBoolean("quickUnlockEnabled", quick_unlock::IsPinEnabled()); html_source->AddBoolean("quickUnlockPinAutosubmitFeatureEnabled", chromeos::features::IsPinAutosubmitFeatureEnabled()); - html_source->AddBoolean( - "quickUnlockDisabledByPolicy", - chromeos::quick_unlock::IsPinDisabledByPolicy(pref_service)); + html_source->AddBoolean("quickUnlockDisabledByPolicy", + quick_unlock::IsPinDisabledByPolicy(pref_service)); html_source->AddBoolean("lockScreenNotificationsEnabled", ash::features::IsLockScreenNotificationsEnabled()); html_source->AddBoolean( @@ -518,13 +489,13 @@ void AddFingerprintResources(content::WebUIDataSource* html_source, html_source->AddBoolean("fingerprintUnlockEnabled", are_fingerprint_settings_allowed); if (are_fingerprint_settings_allowed) { - chromeos::quick_unlock::AddFingerprintResources(html_source); + quick_unlock::AddFingerprintResources(html_source); } int instruction_id, aria_label_id; bool aria_label_includes_device = false; - using FingerprintLocation = chromeos::quick_unlock::FingerprintLocation; - switch (chromeos::quick_unlock::GetFingerprintLocation()) { + using FingerprintLocation = quick_unlock::FingerprintLocation; + switch (quick_unlock::GetFingerprintLocation()) { case FingerprintLocation::TABLET_POWER_BUTTON: instruction_id = IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_POWER_BUTTON; @@ -610,6 +581,7 @@ void AddSetupPinDialogStrings(content::WebUIDataSource* html_source) { {"configurePinTooShort", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_SHORT}, {"configurePinTooLong", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_TOO_LONG}, {"configurePinWeakPin", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_WEAK_PIN}, + {"internalError", IDS_SETTINGS_PEOPLE_CONFIGURE_PIN_INTERNAL_ERROR}, {"pinKeyboardPlaceholderPin", IDS_PIN_KEYBOARD_HINT_TEXT_PIN}, {"pinKeyboardPlaceholderPinPassword", IDS_PIN_KEYBOARD_HINT_TEXT_PIN_PASSWORD}, @@ -641,8 +613,16 @@ void AddSyncControlsStrings(content::WebUIDataSource* html_source) { }; html_source->AddLocalizedStrings(kLocalizedStrings); + // TODO(https://crbug.com/1227694): Remove this after migrating all JS usages + // of splitSettingsSyncEnabled to syncSettingsCategorizationEnabled and + // syncConsentOptionalEnabled. html_source->AddBoolean("splitSettingsSyncEnabled", chromeos::features::IsSplitSettingsSyncEnabled()); + html_source->AddBoolean( + "syncSettingsCategorizationEnabled", + chromeos::features::IsSyncSettingsCategorizationEnabled()); + html_source->AddBoolean("syncConsentOptionalEnabled", + chromeos::features::IsSyncConsentOptionalEnabled()); html_source->AddBoolean("useBrowserSyncConsent", chromeos::features::ShouldUseBrowserSyncConsent()); html_source->AddString( @@ -659,6 +639,8 @@ void AddUsersStrings(content::WebUIDataSource* html_source) { {"restrictSigninLabel", IDS_SETTINGS_USERS_RESTRICT_SIGNIN_LABEL}, {"deviceOwnerLabel", IDS_SETTINGS_USERS_DEVICE_OWNER_LABEL}, {"removeUserTooltip", IDS_SETTINGS_USERS_REMOVE_USER_TOOLTIP}, + {"userRemovedMessage", IDS_SETTINGS_USERS_USER_REMOVED_MESSAGE}, + {"userAddedMessage", IDS_SETTINGS_USERS_USER_ADDED_MESSAGE}, {"addUsers", IDS_SETTINGS_USERS_ADD_USERS}, {"addUsersEmail", IDS_SETTINGS_USERS_ADD_USERS_EMAIL}, {"userExistsError", IDS_SETTINGS_USER_EXISTS_ERROR}, @@ -731,13 +713,11 @@ PeopleSection::PeopleSection( SearchTagRegistry* search_tag_registry, syncer::SyncService* sync_service, SupervisedUserService* supervised_user_service, - KerberosCredentialsManager* kerberos_credentials_manager, signin::IdentityManager* identity_manager, PrefService* pref_service) : OsSettingsSection(profile, search_tag_registry), sync_service_(sync_service), supervised_user_service_(supervised_user_service), - kerberos_credentials_manager_(kerberos_credentials_manager), identity_manager_(identity_manager), pref_service_(pref_service) { // No search tags are registered if in guest mode. @@ -762,25 +742,19 @@ PeopleSection::PeopleSection( FetchAccounts(); } - // No Kerberos search tags are registered here if Kerberos settings are in a - // separate section. - if (kerberos_credentials_manager_ && - !chromeos::features::IsKerberosSettingsSectionEnabled()) { - // Kerberos search tags are added/removed dynamically. - kerberos_credentials_manager_->AddObserver(this); - OnKerberosEnabledStateChanged(); - } - - if (chromeos::features::IsSplitSettingsSyncEnabled()) { - if (sync_service_) { - updater.AddSearchTags(GetSplitSyncSearchConcepts()); + if (sync_service_) { + if (chromeos::features::IsSyncConsentOptionalEnabled()) { + DCHECK(chromeos::features::IsSyncSettingsCategorizationEnabled()); + updater.AddSearchTags(GetCategorizedSyncSearchConcepts()); // Sync search tags are added/removed dynamically. sync_service_->AddObserver(this); OnStateChanged(sync_service_); + } else if (chromeos::features::IsSyncSettingsCategorizationEnabled()) { + updater.AddSearchTags(GetCategorizedSyncSearchConcepts()); + } else { + updater.AddSearchTags(GetNonCategorizedSyncSearchConcepts()); } - } else { - updater.AddSearchTags(GetNonSplitSyncSearchConcepts()); } // Parental control search tags are added if necessary and do not update @@ -796,7 +770,7 @@ PeopleSection::PeopleSection( fingerprint_pref_change_registrar_.Init(pref_service_); fingerprint_pref_change_registrar_.Add( - ::prefs::kQuickUnlockFingerprintRecord, + prefs::kQuickUnlockFingerprintRecord, base::BindRepeating(&PeopleSection::UpdateRemoveFingerprintSearchTags, base::Unretained(this))); UpdateRemoveFingerprintSearchTags(); @@ -804,12 +778,7 @@ PeopleSection::PeopleSection( } PeopleSection::~PeopleSection() { - if (kerberos_credentials_manager_ && - !chromeos::features::IsKerberosSettingsSectionEnabled()) { - kerberos_credentials_manager_->RemoveObserver(this); - } - - if (chromeos::features::IsSplitSettingsSyncEnabled() && sync_service_) + if (chromeos::features::IsSyncConsentOptionalEnabled() && sync_service_) sync_service_->RemoveObserver(this); } @@ -893,15 +862,17 @@ void PeopleSection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddBoolean( "secondaryGoogleAccountSigninAllowed", pref_service_->GetBoolean( - chromeos::prefs::kSecondaryGoogleAccountSigninAllowed)); + ::account_manager::prefs::kSecondaryGoogleAccountSigninAllowed)); html_source->AddBoolean( "driveSuggestAvailable", base::FeatureList::IsEnabled(omnibox::kDocumentProvider)); + html_source->AddBoolean( + "smartLockUIRevampEnabled", + base::FeatureList::IsEnabled(ash::features::kSmartLockUIRevamp)); + AddAccountManagerPageStrings(html_source, profile()); - KerberosAccountsHandler::AddLoadTimeKerberosStrings( - html_source, kerberos_credentials_manager_); AddLockScreenPageStrings(html_source, profile()->GetPrefs()); AddFingerprintListStrings(html_source); AddFingerprintResources(html_source, AreFingerprintSettingsAllowed()); @@ -931,7 +902,7 @@ void PeopleSection::AddHandlers(content::WebUI* web_ui) { account_manager_, account_manager_facade_, identity_manager_)); } - if (chromeos::features::IsSplitSettingsSyncEnabled()) + if (chromeos::features::IsSyncSettingsCategorizationEnabled()) web_ui->AddMessageHandler(std::make_unique<OSSyncHandler>(profile())); web_ui->AddMessageHandler( @@ -947,18 +918,6 @@ void PeopleSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<chromeos::settings::ParentalControlsHandler>( profile())); } - - // No Kerberos handler is created/added here if Kerberos settings are in a - // separate section. - if (!chromeos::features::IsKerberosSettingsSectionEnabled()) { - std::unique_ptr<chromeos::settings::KerberosAccountsHandler> - kerberos_accounts_handler = - KerberosAccountsHandler::CreateIfKerberosEnabled(profile()); - if (kerberos_accounts_handler) { - // Note that the UI is enabled only if Kerberos is enabled. - web_ui->AddMessageHandler(std::move(kerberos_accounts_handler)); - } - } } int PeopleSection::GetSectionNameMessageId() const { @@ -1059,6 +1018,10 @@ void PeopleSection::RegisterHierarchy(HierarchyGenerator* generator) const { RegisterNestedSettingBulk(mojom::Subpage::kFingerprint, kFingerprintSettings, generator); + // Smart Lock -- main setting is on multidevice page, but is mirrored here + generator->RegisterNestedAltSetting(mojom::Setting::kSmartLockOnOff, + mojom::Subpage::kSecurityAndSignIn); + // Manage other people. generator->RegisterTopLevelSubpage(IDS_SETTINGS_PEOPLE_MANAGE_OTHER_PEOPLE, mojom::Subpage::kManageOtherPeople, @@ -1074,20 +1037,6 @@ void PeopleSection::RegisterHierarchy(HierarchyGenerator* generator) const { }; RegisterNestedSettingBulk(mojom::Subpage::kManageOtherPeople, kManageOtherPeopleSettings, generator); - - // Kerberos. - generator->RegisterTopLevelSubpage(IDS_SETTINGS_KERBEROS_ACCOUNTS_PAGE_TITLE, - mojom::Subpage::kKerberosAccounts, - mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kMedium, - mojom::kKerberosAccountsSubpagePath); - static constexpr mojom::Setting kKerberosAccountsSettings[] = { - mojom::Setting::kAddKerberosTicket, - mojom::Setting::kRemoveKerberosTicket, - mojom::Setting::kSetActiveKerberosTicket, - }; - RegisterNestedSettingBulk(mojom::Subpage::kKerberosAccounts, - kKerberosAccountsSettings, generator); } void PeopleSection::FetchAccounts() { @@ -1128,32 +1077,23 @@ void PeopleSection::UpdateAccountManagerSearchTags( } void PeopleSection::OnStateChanged(syncer::SyncService* sync_service) { - DCHECK(chromeos::features::IsSplitSettingsSyncEnabled()); + DCHECK(chromeos::features::IsSyncConsentOptionalEnabled()); DCHECK_EQ(sync_service, sync_service_); SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); if (sync_service_->IsEngineInitialized() && sync_service_->GetUserSettings()->IsOsSyncFeatureEnabled()) { - updater.AddSearchTags(GetSplitSyncOnSearchConcepts()); - updater.RemoveSearchTags(GetSplitSyncOffSearchConcepts()); + updater.AddSearchTags(GetSyncOnSearchConcepts()); + updater.RemoveSearchTags(GetSyncOffSearchConcepts()); } else { - updater.RemoveSearchTags(GetSplitSyncOnSearchConcepts()); - updater.AddSearchTags(GetSplitSyncOffSearchConcepts()); + updater.RemoveSearchTags(GetSyncOnSearchConcepts()); + updater.AddSearchTags(GetSyncOffSearchConcepts()); } } -void PeopleSection::OnKerberosEnabledStateChanged() { - SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); - - if (kerberos_credentials_manager_->IsKerberosEnabled()) - updater.AddSearchTags(GetKerberosSearchConcepts()); - else - updater.RemoveSearchTags(GetKerberosSearchConcepts()); -} - bool PeopleSection::AreFingerprintSettingsAllowed() { - return chromeos::quick_unlock::IsFingerprintEnabled(profile()); + return quick_unlock::IsFingerprintEnabled(profile()); } void PeopleSection::UpdateRemoveFingerprintSearchTags() { @@ -1163,7 +1103,7 @@ void PeopleSection::UpdateRemoveFingerprintSearchTags() { // "Remove fingerprint" search tag should exist only when 1 or more // fingerprints are registered. int registered_fingerprint_count = - pref_service_->GetInteger(::prefs::kQuickUnlockFingerprintRecord); + pref_service_->GetInteger(prefs::kQuickUnlockFingerprintRecord); if (registered_fingerprint_count > 0) { updater.AddSearchTags(GetRemoveFingerprintSearchConcepts()); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.h index cddb87ae747..499cc517b7e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.h @@ -5,14 +5,13 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PEOPLE_SECTION_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_PEOPLE_SECTION_H_ -#include "ash/components/account_manager/account_manager.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observation.h" #include "base/values.h" -#include "chrome/browser/ash/kerberos/kerberos_credentials_manager.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" #include "components/account_manager_core/account.h" #include "components/account_manager_core/account_manager_facade.h" +#include "components/account_manager_core/chromeos/account_manager.h" #include "components/prefs/pref_change_registrar.h" #include "components/sync/driver/sync_service_observer.h" @@ -41,19 +40,17 @@ class SearchTagRegistry; // Provides UI strings and search tags for People settings. Search tags are only // added for non-guest sessions. // -// Kerberos, Fingerprint, and Parental Controls search tags are only shown if -// they are allowed by policy/flags. Different sets of Sync tags are shown -// depending on whether the feature is enabed or disabled. +// Fingerprint and Parental Controls search tags are only shown if they are +// allowed by policy/flags. Different sets of Sync tags are shown depending on +// whether the feature is enabed or disabled. class PeopleSection : public OsSettingsSection, public account_manager::AccountManagerFacade::Observer, - public syncer::SyncServiceObserver, - public KerberosCredentialsManager::Observer { + public syncer::SyncServiceObserver { public: PeopleSection(Profile* profile, SearchTagRegistry* search_tag_registry, syncer::SyncService* sync_service, SupervisedUserService* supervised_user_service, - KerberosCredentialsManager* kerberos_credentials_manager, signin::IdentityManager* identity_manager, PrefService* pref_service); ~PeopleSection() override; @@ -76,20 +73,16 @@ class PeopleSection : public OsSettingsSection, // syncer::SyncServiceObserver: void OnStateChanged(syncer::SyncService* sync_service) override; - // KerberosCredentialsManager::Observer: - void OnKerberosEnabledStateChanged() override; - bool AreFingerprintSettingsAllowed(); void FetchAccounts(); void UpdateAccountManagerSearchTags( const std::vector<::account_manager::Account>& accounts); void UpdateRemoveFingerprintSearchTags(); - AccountManager* account_manager_ = nullptr; + account_manager::AccountManager* account_manager_ = nullptr; account_manager::AccountManagerFacade* account_manager_facade_ = nullptr; syncer::SyncService* sync_service_; SupervisedUserService* supervised_user_service_; - KerberosCredentialsManager* kerberos_credentials_manager_; signin::IdentityManager* identity_manager_; PrefService* pref_service_; PrefChangeRegistrar fingerprint_pref_change_registrar_; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc index bd4fa75288d..05de44a349d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.cc @@ -8,6 +8,7 @@ #include <utility> #include "ash/components/pcie_peripheral/pcie_peripheral_manager.h" +#include "ash/constants/ash_pref_names.h" #include "base/bind.h" #include "base/callback_helpers.h" #include "base/files/file_path.h" @@ -15,9 +16,11 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/browser/ash/settings/cros_settings.h" -#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h" #include "chromeos/dbus/pciguard/pciguard_client.h" #include "chromeos/settings/cros_settings_names.h" +#include "chromeos/tpm/install_attributes.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" @@ -26,13 +29,39 @@ namespace settings { namespace { constexpr char thunderbolt_file_path[] = "/sys/bus/thunderbolt/devices/0-0"; +constexpr char local_state_pref_name[] = + "settings.local_state_device_pci_data_access_enabled"; +constexpr char cros_setting_pref_name[] = + "cros.device.peripheral_data_access_enabled"; } // namespace bool CheckIfThunderboltFilepathExists() { return base::PathExists(base::FilePath(thunderbolt_file_path)); } +// static +bool PeripheralDataAccessHandler::GetPrefState() { + // If the device is managed, use the local state pref. + if (InstallAttributes::Get()->IsEnterpriseManaged()) { + return g_browser_process->local_state()->GetBoolean( + ash::prefs::kLocalStateDevicePeripheralDataAccessEnabled); + } + + // Otherwise, use the CrosSetting for non-managed devices. + bool pcie_tunneling_allowed = false; + CrosSettings::Get()->GetBoolean(chromeos::kDevicePeripheralDataAccessEnabled, + &pcie_tunneling_allowed); + return pcie_tunneling_allowed; +} + PeripheralDataAccessHandler::PeripheralDataAccessHandler() { + auto* pref = g_browser_process->local_state()->FindPreference( + ash::prefs::kLocalStateDevicePeripheralDataAccessEnabled); + DCHECK(pref); + // If the user has a managed policy or is a guest profile, prevent user + // configuration of the setting. + is_user_configurable_ = !pref->IsManaged() && !features::IsGuestModeActive(); + peripheral_data_access_subscription_ = CrosSettings::Get()->AddSettingsObserver( kDevicePeripheralDataAccessEnabled, @@ -49,6 +78,11 @@ void PeripheralDataAccessHandler::RegisterMessages() { base::BindRepeating( &PeripheralDataAccessHandler::HandleThunderboltSupported, base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "getPolicyState", + base::BindRepeating(&PeripheralDataAccessHandler::HandleGetPolicyState, + base::Unretained(this))); } void PeripheralDataAccessHandler::OnJavascriptAllowed() {} @@ -69,6 +103,22 @@ void PeripheralDataAccessHandler::HandleThunderboltSupported( weak_ptr_factory_.GetWeakPtr(), callback_id)); } +void PeripheralDataAccessHandler::HandleGetPolicyState( + const base::ListValue* args) { + AllowJavascript(); + CHECK_EQ(1u, args->GetSize()); + const std::string& callback_id = args->GetList()[0].GetString(); + + const std::string& pref_name = InstallAttributes::Get()->IsEnterpriseManaged() + ? local_state_pref_name + : cros_setting_pref_name; + + base::Value response(base::Value::Type::DICTIONARY); + response.SetKey("prefName", base::Value(pref_name)); + response.SetKey("isUserConfigurable", base::Value(is_user_configurable_)); + ResolveJavascriptCallback(base::Value(callback_id), response); +} + void PeripheralDataAccessHandler::OnFilePathChecked( const std::string& callback_id, bool is_thunderbolt_supported) { ResolveJavascriptCallback(base::Value(callback_id), diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h index 422c0b1eab3..496e275a356 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h @@ -14,6 +14,8 @@ namespace settings { class PeripheralDataAccessHandler : public ::settings::SettingsPageUIHandler { public: + static bool GetPrefState(); + PeripheralDataAccessHandler(); ~PeripheralDataAccessHandler() override; @@ -30,14 +32,21 @@ class PeripheralDataAccessHandler : public ::settings::SettingsPageUIHandler { // Handles checking if thunderbolt is supported in this device. void HandleThunderboltSupported(const base::ListValue* args); + // Handles returning the policy state. + void HandleGetPolicyState(const base::ListValue* args); + // Observer for the CrosSetting. void OnPeripheralDataAccessProtectionChanged(); void OnFilePathChecked(const std::string& callback_id, bool is_thunderbolt_supported); + void OnLocalStatePrefChanged(); + base::CallbackListSubscription peripheral_data_access_subscription_; + bool is_user_configurable_ = false; + // Used for callbacks. base::WeakPtrFactory<PeripheralDataAccessHandler> weak_ptr_factory_{this}; }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc index eaaa465e7a0..68adb4dfea0 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/personalization_section.h" #include "ash/constants/ash_features.h" +#include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/ambient/ambient_client.h" #include "ash/public/cpp/ambient/ambient_prefs.h" #include "base/bind.h" @@ -122,6 +123,63 @@ const std::vector<SearchConcept>& GetAmbientModeOffSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetDarkModeSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_DARK_MODE_SUBPAGE, + mojom::kDarkModeSubpagePath, + mojom::SearchResultIcon::kDarkMode, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kDarkMode}, + {IDS_OS_SETTINGS_TAG_DARK_MODE_SUBPAGE_ALT1, + IDS_OS_SETTINGS_TAG_DARK_MODE_SUBPAGE_ALT2, + IDS_OS_SETTINGS_TAG_DARK_MODE_SUBPAGE_ALT3, SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_DARK_MODE_THEMED, + mojom::kDarkModeSubpagePath, + mojom::SearchResultIcon::kDarkMode, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDarkModeThemed}, + {IDS_OS_SETTINGS_TAG_DARK_MODE_THEMED_ALT1, + IDS_OS_SETTINGS_TAG_DARK_MODE_THEMED_ALT2, SearchConcept::kAltTagEnd}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetDarkModeOnSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_OFF, + mojom::kDarkModeSubpagePath, + mojom::SearchResultIcon::kDarkMode, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDarkModeOnOff}, + {IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_OFF_ALT1, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_OFF_ALT2, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_OFF_ALT3, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_OFF_ALT4, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_OFF_ALT5}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetDarkModeOffSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_ON, + mojom::kDarkModeSubpagePath, + mojom::SearchResultIcon::kDarkMode, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDarkModeOnOff}, + {IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_ON_ALT1, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_ON_ALT2, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_ON_ALT3, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_ON_ALT4, + IDS_OS_SETTINGS_TAG_DARK_MODE_TURN_ON_ALT5}}, + }); + return *tags; +} + bool IsAmbientModeAllowed() { // TODO(b/172029925): Set up to test this code. return chromeos::features::IsAmbientModeEnabled() && @@ -133,6 +191,10 @@ bool IsAmbientModePhotoPreviewAllowed() { return chromeos::features::IsAmbientModePhotoPreviewEnabled(); } +bool IsDarkModeAllowed() { + return ash::features::IsDarkLightModeEnabled(); +} + GURL GetGooglePhotosURL() { return GURL(chrome::kGooglePhotosURL); } @@ -152,10 +214,11 @@ PersonalizationSection::PersonalizationSection( SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); updater.AddSearchTags(GetPersonalizationSearchConcepts()); + if (IsAmbientModeAllowed() || IsDarkModeAllowed()) + pref_change_registrar_.Init(pref_service_); + if (IsAmbientModeAllowed()) { updater.AddSearchTags(GetAmbientModeSearchConcepts()); - - pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add( ash::ambient::prefs::kAmbientModeEnabled, base::BindRepeating( @@ -163,6 +226,17 @@ PersonalizationSection::PersonalizationSection( base::Unretained(this))); OnAmbientModeEnabledStateChanged(); } + + if (IsDarkModeAllowed()) { + updater.AddSearchTags(GetDarkModeSearchConcepts()); + + pref_change_registrar_.Add( + ash::prefs::kDarkModeEnabled, + base::BindRepeating( + &PersonalizationSection::OnDarkModeEnabledStateChanged, + base::Unretained(this))); + OnDarkModeEnabledStateChanged(); + } } PersonalizationSection::~PersonalizationSection() = default; @@ -209,6 +283,15 @@ void PersonalizationSection::AddLoadTimeData( {"ambientModeArtAlbumDialogCloseButtonLabel", IDS_OS_SETTINGS_AMBIENT_MODE_ART_ALBUM_DIALOG_CLOSE_BUTTON_LABEL}, {"changePictureTitle", IDS_OS_SETTINGS_CHANGE_PICTURE_TITLE}, + {"darkModeTitle", IDS_OS_SETTINGS_DARK_MODE_TITLE}, + {"darkModeOn", IDS_OS_SETTINGS_DARK_MODE_ON}, + {"darkModeOff", IDS_OS_SETTINGS_DARK_MODE_OFF}, + {"darkModeThemedRadioGroupTitle", + IDS_OS_SETTINGS_DARK_MODE_THEMED_RADIO_GROUP_TITLE}, + {"darkModeThemedRadioGroupDescription", + IDS_OS_SETTINGS_DARK_MODE_THEMED_RADIO_GROUP_DESCRIPTION}, + {"darkModeThemedOn", IDS_OS_SETTINGS_DARK_MODE_THEMED_ON}, + {"darkModeThemedOff", IDS_OS_SETTINGS_DARK_MODE_THEMED_OFF}, {"openWallpaperApp", IDS_OS_SETTINGS_OPEN_WALLPAPER_APP}, {"personalizationPageTitle", IDS_OS_SETTINGS_PERSONALIZATION}, {"setWallpaper", IDS_OS_SETTINGS_SET_WALLPAPER}, @@ -249,6 +332,7 @@ void PersonalizationSection::AddLoadTimeData( l10n_util::GetStringFUTF16( IDS_OS_SETTINGS_AMBIENT_MODE_ALBUMS_SUBPAGE_GOOGLE_PHOTOS_NO_ALBUM, base::UTF8ToUTF16(GetGooglePhotosURL().spec()))); + html_source->AddBoolean("isDarkModeAllowed", IsDarkModeAllowed()); } void PersonalizationSection::AddHandlers(content::WebUI* web_ui) { @@ -322,6 +406,18 @@ void PersonalizationSection::RegisterHierarchy( mojom::SearchResultIcon::kWallpaper, mojom::SearchResultDefaultRank::kMedium, mojom::kAmbientModeArtGalleryAlbumSubpagePath); + + // Dark mode. + generator->RegisterTopLevelSubpage( + IDS_OS_SETTINGS_AMBIENT_MODE_TITLE, mojom::Subpage::kDarkMode, + mojom::SearchResultIcon::kWallpaper, + mojom::SearchResultDefaultRank::kMedium, mojom::kDarkModeSubpagePath); + static constexpr mojom::Setting kDarkModeSettings[] = { + mojom::Setting::kDarkModeOnOff, + mojom::Setting::kDarkModeThemed, + }; + RegisterNestedSettingBulk(mojom::Subpage::kDarkMode, kDarkModeSettings, + generator); } void PersonalizationSection::OnAmbientModeEnabledStateChanged() { @@ -336,5 +432,17 @@ void PersonalizationSection::OnAmbientModeEnabledStateChanged() { } } +void PersonalizationSection::OnDarkModeEnabledStateChanged() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + if (pref_service_->GetBoolean(ash::prefs::kDarkModeEnabled)) { + updater.AddSearchTags(GetDarkModeOnSearchConcepts()); + updater.RemoveSearchTags(GetDarkModeOffSearchConcepts()); + } else { + updater.RemoveSearchTags(GetDarkModeOnSearchConcepts()); + updater.AddSearchTags(GetDarkModeOffSearchConcepts()); + } +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.h index 31e52ce5770..1e30eb9d41c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.h @@ -44,6 +44,8 @@ class PersonalizationSection : public OsSettingsSection { // ash::AmbientModeService::Observer: void OnAmbientModeEnabledStateChanged(); + void OnDarkModeEnabledStateChanged(); + PrefService* pref_service_; PrefChangeRegistrar pref_change_registrar_; }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.cc index fcb6da225cc..0ac876f683d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.cc @@ -111,6 +111,7 @@ void PrintingSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_SETTINGS_PRINTING_CUPS_PRINTERS_LEARN_MORE_LABEL}, {"addCupsPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_PRINTER}, {"editPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_EDIT}, + {"viewPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_VIEW}, {"removePrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_REMOVE}, {"setupPrinter", IDS_SETTINGS_PRINTING_CUPS_PRINTER_SETUP_BUTTON}, {"setupPrinterAria", @@ -151,6 +152,14 @@ void PrintingSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTER_COUNT_ONE}, {"nearbyPrintersCountNone", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_AVAILABLE_PRINTER_COUNT_NONE}, + {"enterprisePrintersTitle", + IDS_SETTINGS_PRINTING_ENTERPRISE_PRINTERS_TITLE}, + {"enterprisePrintersCountMany", + IDS_SETTINGS_PRINTING_ENTERPRISE_PRINTERS_AVAILABLE_PRINTERS_COUNT_MANY}, + {"enterprisePrintersCountOne", + IDS_SETTINGS_PRINTING_ENTERPRISE_PRINTERS_AVAILABLE_PRINTER_COUNT_ONE}, + {"enterprisePrintersCountNone", + IDS_SETTINGS_PRINTING_ENTERPRISE_PRINTERS_AVAILABLE_PRINTER_COUNT_NONE}, {"nearbyPrintersListDescription", IDS_SETTINGS_PRINTING_CUPS_PRINTERS_ADD_DETECTED_OR_NEW_PRINTER}, {"manufacturerAndModelAdditionalInformation", @@ -226,6 +235,8 @@ void PrintingSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_SETTINGS_PRINTING_CUPS_PRINTER_CONNECT_TO_NETWORK_SUBTEXT}, {"editPrinterDialogTitle", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_DIALOG_TITLE}, + {"viewPrinterDialogTitle", + IDS_SETTINGS_PRINTING_CUPS_VIEW_PRINTER_DIALOG_TITLE}, {"editPrinterButtonText", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_BUTTON}, {"currentPpdMessage", IDS_SETTINGS_PRINTING_CUPS_EDIT_PRINTER_CURRENT_PPD_MESSAGE}, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.cc index 33cccfd1349..135272cee4e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.cc @@ -5,6 +5,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/privacy_section.h" #include "ash/constants/ash_features.h" +#include "ash/constants/ash_pref_names.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/no_destructor.h" @@ -13,10 +14,10 @@ #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h" #include "chrome/browser/ui/webui/settings/chromeos/peripheral_data_access_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" +#include "chrome/browser/ui/webui/settings/settings_secure_dns_handler.h" #include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/chrome_features.h" -#include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "components/prefs/pref_service.h" @@ -177,6 +178,15 @@ const std::vector<SearchConcept>& GetPrivacyGoogleChromeSearchConcepts() { } #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) +bool IsSecureDnsAvailable() { + return +#if BUILDFLAG(IS_CHROMEOS_ASH) + base::FeatureList::IsEnabled(chromeos::features::kEnableDnsProxy) && + base::FeatureList::IsEnabled(::features::kDnsProxyEnableDOH) && +#endif + ::features::kDnsOverHttpsShowUiParam.Get(); +} + } // namespace PrivacySection::PrivacySection(Profile* profile, @@ -198,7 +208,7 @@ PrivacySection::PrivacySection(Profile* profile, fingerprint_pref_change_registrar_.Init(pref_service_); fingerprint_pref_change_registrar_.Add( - ::prefs::kQuickUnlockFingerprintRecord, + prefs::kQuickUnlockFingerprintRecord, base::BindRepeating(&PrivacySection::UpdateRemoveFingerprintSearchTags, base::Unretained(this))); UpdateRemoveFingerprintSearchTags(); @@ -214,6 +224,9 @@ PrivacySection::~PrivacySection() = default; void PrivacySection::AddHandlers(content::WebUI* web_ui) { web_ui->AddMessageHandler( std::make_unique<chromeos::settings::PeripheralDataAccessHandler>()); + + if (IsSecureDnsAvailable()) + web_ui->AddMessageHandler(std::make_unique<::settings::SecureDnsHandler>()); } void PrivacySection::AddLoadTimeData(content::WebUIDataSource* html_source) { @@ -261,7 +274,11 @@ void PrivacySection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddBoolean("pciguardUiEnabled", chromeos::features::IsPciguardUiEnabled()); + html_source->AddBoolean("showSecureDnsSetting", IsSecureDnsAvailable()); + html_source->AddBoolean("showSecureDnsOsSettingLink", false); + ::settings::AddPersonalizationOptionsStrings(html_source); + ::settings::AddSecureDnsStrings(html_source); } int PrivacySection::GetSectionNameMessageId() const { @@ -344,7 +361,7 @@ void PrivacySection::RegisterHierarchy(HierarchyGenerator* generator) const { } bool PrivacySection::AreFingerprintSettingsAllowed() { - return chromeos::quick_unlock::IsFingerprintEnabled(profile()); + return quick_unlock::IsFingerprintEnabled(profile()); } void PrivacySection::UpdateRemoveFingerprintSearchTags() { @@ -354,7 +371,7 @@ void PrivacySection::UpdateRemoveFingerprintSearchTags() { // "Remove fingerprint" search tag should exist only when 1 or more // fingerprints are registered. int registered_fingerprint_count = - pref_service_->GetInteger(::prefs::kQuickUnlockFingerprintRecord); + pref_service_->GetInteger(prefs::kQuickUnlockFingerprintRecord); if (registered_fingerprint_count > 0) { updater.AddSearchTags(GetRemoveFingerprintSearchConcepts()); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc index cf5401a1507..3e068749369 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.cc @@ -4,11 +4,11 @@ #include "chrome/browser/ui/webui/settings/chromeos/quick_unlock_handler.h" +#include "ash/constants/ash_pref_names.h" #include "base/bind.h" #include "chrome/browser/ash/login/quick_unlock/pin_backend.h" #include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_ui.h" @@ -36,7 +36,7 @@ void QuickUnlockHandler::RegisterMessages() { void QuickUnlockHandler::OnJavascriptAllowed() { pref_change_registrar_.Init(profile_->GetPrefs()); pref_change_registrar_.Add( - ::prefs::kQuickUnlockModeAllowlist, + prefs::kQuickUnlockModeAllowlist, base::BindRepeating( &QuickUnlockHandler::UpdateQuickUnlockDisabledByPolicy, weak_ptr_factory_.GetWeakPtr())); @@ -67,9 +67,9 @@ void QuickUnlockHandler::OnPinLoginAvailable(bool is_available) { } void QuickUnlockHandler::UpdateQuickUnlockDisabledByPolicy() { - FireWebUIListener("quick-unlock-disabled-by-policy-changed", - base::Value(chromeos::quick_unlock::IsPinDisabledByPolicy( - pref_service_))); + FireWebUIListener( + "quick-unlock-disabled-by-policy-changed", + base::Value(quick_unlock::IsPinDisabledByPolicy(pref_service_))); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom index 0afbaeb6305..5560e0b4925 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom @@ -16,6 +16,7 @@ enum SearchResultIcon { kCellular, kChrome, kClock, + kDarkMode, kDeveloperTags, kDisplay, kDrive, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.cc index ba576ca21ee..5192fdc7e13 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.cc @@ -36,7 +36,9 @@ namespace settings { namespace { bool ShouldShowQuickAnswersSettings() { - return ash::features::IsQuickAnswersStandaloneSettingsEnabled(); + return ash::features::IsQuickAnswersV2Enabled() && + ash::QuickAnswersState::Get() && + ash::QuickAnswersState::Get()->is_eligible(); } const std::vector<SearchConcept>& GetSearchPageSearchConcepts() { @@ -68,6 +70,30 @@ const std::vector<SearchConcept>& GetQuickAnswersSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetQuickAnswersOnSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_QUICK_ANSWERS_DEFINITION, + mojom::kSearchSubpagePath, + mojom::SearchResultIcon::kMagnifyingGlass, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kQuickAnswersDefinition}}, + {IDS_OS_SETTINGS_TAG_QUICK_ANSWERS_TRANSLATION, + mojom::kSearchSubpagePath, + mojom::SearchResultIcon::kMagnifyingGlass, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kQuickAnswersTranslation}}, + {IDS_OS_SETTINGS_TAG_QUICK_ANSWERS_UNIT_CONVERSION, + mojom::kSearchSubpagePath, + mojom::SearchResultIcon::kMagnifyingGlass, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kQuickAnswersUnitConversion}}, + }); + return *tags; +} + const std::vector<SearchConcept>& GetAssistantSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_ASSISTANT, @@ -155,9 +181,25 @@ void AddQuickAnswersStrings(content::WebUIDataSource* html_source) { {"quickAnswersEnable", IDS_SETTINGS_QUICK_ANSWERS_ENABLE}, {"quickAnswersEnableDescription", IDS_SETTINGS_QUICK_ANSWERS_ENABLE_DESCRIPTION}, + {"quickAnswersEnableDescriptionWithLink", + IDS_SETTINGS_QUICK_ANSWERS_ENABLE_DESCRIPTION_WITH_LINK}, + {"quickAnswersDefinitionEnable", + IDS_SETTINGS_QUICK_ANSWERS_DEFINITION_ENABLE}, + {"quickAnswersTranslationEnable", + IDS_SETTINGS_QUICK_ANSWERS_TRANSLATION_ENABLE}, + {"quickAnswersTranslationEnableDescription", + IDS_SETTINGS_QUICK_ANSWERS_TRANSLATION_ENABLE_DESCRIPTION}, + {"quickAnswersUnitConversionEnable", + IDS_SETTINGS_QUICK_ANSWERS_UNIT_CONVERSION_ENABLE}, }; html_source->AddLocalizedStrings(kLocalizedStrings); + + html_source->AddBoolean("quickAnswersTranslationDisabled", + ash::features::IsQuickAnswersV2TranslationDisabled()); + html_source->AddBoolean( + "quickAnswersSubToggleEnabled", + ash::features::IsQuickAnswersV2SettingsSubToggleEnabled()); } void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { @@ -165,7 +207,7 @@ void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { {"googleAssistantPageTitle", IDS_SETTINGS_GOOGLE_ASSISTANT}, {"googleAssistantEnableContext", IDS_ASSISTANT_SCREEN_CONTEXT_TITLE}, {"googleAssistantEnableContextDescription", - IDS_ASSISTANT_SCREEN_CONTEXT_DESC}, + IDS_SETTINGS_GOOGLE_ASSISTANT_SCREEN_CONTEXT_DESCRIPTION}, {"googleAssistantEnableHotword", IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD}, {"googleAssistantEnableHotwordDescription", @@ -201,18 +243,22 @@ void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { } const std::vector<mojom::Setting>& GetSearchSettings() { - if (ShouldShowQuickAnswersSettings()) { - static const base::NoDestructor<std::vector<mojom::Setting>> settings({ - mojom::Setting::kQuickAnswersOnOff, - mojom::Setting::kPreferredSearchEngine, - }); - return *settings; - } else { - static const base::NoDestructor<std::vector<mojom::Setting>> settings({ + static const base::NoDestructor<std::vector<mojom::Setting>> settings([] { + std::vector<mojom::Setting> base_settings{ mojom::Setting::kQuickAnswersOnOff, - }); - return *settings; - } + mojom::Setting::kQuickAnswersDefinition, + mojom::Setting::kQuickAnswersTranslation, + mojom::Setting::kQuickAnswersUnitConversion, + }; + + if (ShouldShowQuickAnswersSettings()) { + base_settings.insert(base_settings.end(), + mojom::Setting::kPreferredSearchEngine); + } + + return base_settings; + }()); + return *settings; } } // namespace @@ -233,6 +279,11 @@ SearchSection::SearchSection(Profile* profile, assistant_state->AddObserver(this); UpdateAssistantSearchTags(); } + + if (ShouldShowQuickAnswersSettings()) { + ash::QuickAnswersState::Get()->AddObserver(this); + UpdateQuickAnswersSearchTags(); + } } SearchSection::~SearchSection() { @@ -347,6 +398,10 @@ void SearchSection::OnAssistantHotwordEnabled(bool enabled) { UpdateAssistantSearchTags(); } +void SearchSection::OnSettingsEnabled(bool enabled) { + UpdateQuickAnswersSearchTags(); +} + bool SearchSection::IsAssistantAllowed() const { // NOTE: This will be false when the flag is disabled. return ::assistant::IsAssistantAllowedForProfile(profile()) == @@ -382,5 +437,17 @@ void SearchSection::UpdateAssistantSearchTags() { } } +void SearchSection::UpdateQuickAnswersSearchTags() { + DCHECK(ash::QuickAnswersState::Get()); + + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.RemoveSearchTags(GetQuickAnswersOnSearchConcepts()); + + if (ash::features::IsQuickAnswersV2SettingsSubToggleEnabled() && + ash::QuickAnswersState::Get()->settings_enabled()) { + updater.AddSearchTags(GetQuickAnswersOnSearchConcepts()); + } +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.h index 6ab696b1749..dd68b30acb0 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SECTION_H_ #include "ash/public/cpp/assistant/assistant_state_base.h" +#include "ash/public/cpp/quick_answers/quick_answers_state.h" #include "base/values.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" @@ -22,7 +23,8 @@ class SearchTagRegistry; // tags for Assistant settings are added/removed depending on whether the // feature and relevant flags are enabled/disabled. class SearchSection : public OsSettingsSection, - public ash::AssistantStateObserver { + public ash::AssistantStateObserver, + public ash::QuickAnswersStateObserver { public: SearchSection(Profile* profile, SearchTagRegistry* search_tag_registry); ~SearchSection() override; @@ -44,8 +46,12 @@ class SearchSection : public OsSettingsSection, void OnAssistantSettingsEnabled(bool enabled) override; void OnAssistantHotwordEnabled(bool enabled) override; + // ash::QuickAnswersStateObserver: + void OnSettingsEnabled(bool enabled) override; + bool IsAssistantAllowed() const; void UpdateAssistantSearchTags(); + void UpdateQuickAnswersSearchTags(); }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/settings_user_action_tracker.h b/chromium/chrome/browser/ui/webui/settings/chromeos/settings_user_action_tracker.h index 9f8130ed7da..cadc29d345f 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/settings_user_action_tracker.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/settings_user_action_tracker.h @@ -12,7 +12,6 @@ #include "chrome/browser/ui/webui/settings/chromeos/search/user_action_recorder.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" -#include "third_party/abseil-cpp/absl/types/optional.h" namespace chromeos { namespace settings { diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc index a8e2471db51..e9ac388a421 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.cc @@ -6,9 +6,9 @@ #include <memory> +#include "ash/constants/ash_constants.h" +#include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/accessibility_controller.h" -#include "ash/public/cpp/ash_constants.h" -#include "ash/public/cpp/ash_pref_names.h" #include "base/bind.h" #include "base/no_destructor.h" #include "base/values.h" @@ -92,16 +92,16 @@ void SwitchAccessHandler::RegisterMessages() { &SwitchAccessHandler::HandleRefreshAssignmentsFromPrefs, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "notifySwitchAccessActionAssignmentDialogAttached", + "notifySwitchAccessActionAssignmentPaneActive", base::BindRepeating( &SwitchAccessHandler:: - HandleNotifySwitchAccessActionAssignmentDialogAttached, + HandleNotifySwitchAccessActionAssignmentPaneActive, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "notifySwitchAccessActionAssignmentDialogDetached", + "notifySwitchAccessActionAssignmentPaneInactive", base::BindRepeating( &SwitchAccessHandler:: - HandleNotifySwitchAccessActionAssignmentDialogDetached, + HandleNotifySwitchAccessActionAssignmentPaneInactive, base::Unretained(this))); } @@ -160,18 +160,16 @@ void SwitchAccessHandler::HandleRefreshAssignmentsFromPrefs( OnSwitchAccessAssignmentsUpdated(); } -void SwitchAccessHandler:: - HandleNotifySwitchAccessActionAssignmentDialogAttached( - const base::ListValue* args) { +void SwitchAccessHandler::HandleNotifySwitchAccessActionAssignmentPaneActive( + const base::ListValue* args) { AllowJavascript(); OnSwitchAccessAssignmentsUpdated(); web_ui()->GetWebContents()->GetNativeView()->AddPreTargetHandler(this); ash::AccessibilityController::Get()->SuspendSwitchAccessKeyHandling(true); } -void SwitchAccessHandler:: - HandleNotifySwitchAccessActionAssignmentDialogDetached( - const base::ListValue* args) { +void SwitchAccessHandler::HandleNotifySwitchAccessActionAssignmentPaneInactive( + const base::ListValue* args) { web_ui()->GetWebContents()->GetNativeView()->RemovePreTargetHandler(this); ash::AccessibilityController::Get()->SuspendSwitchAccessKeyHandling(false); } @@ -189,7 +187,7 @@ void SwitchAccessHandler::OnSwitchAccessAssignmentsUpdated() { for (const AssignmentInfo& info : *kAssignmentInfo) { auto* keycodes = prefs_->GetDictionary(info.pref_name); base::ListValue keys; - for (const auto& item : keycodes->DictItems()) { + for (const auto item : keycodes->DictItems()) { int key_code; if (!base::StringToInt(item.first, &key_code)) { NOTREACHED(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h index 4132356c352..bcb49437b0a 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/switch_access_handler.h @@ -36,9 +36,9 @@ class SwitchAccessHandler : public ::settings::SettingsPageUIHandler, private: void HandleRefreshAssignmentsFromPrefs(const base::ListValue* args); - void HandleNotifySwitchAccessActionAssignmentDialogAttached( + void HandleNotifySwitchAccessActionAssignmentPaneActive( const base::ListValue* args); - void HandleNotifySwitchAccessActionAssignmentDialogDetached( + void HandleNotifySwitchAccessActionAssignmentPaneInactive( const base::ListValue* args); void OnSwitchAccessAssignmentsUpdated(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc index 705545443dd..8033326fe93 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/tts_handler.cc @@ -77,7 +77,7 @@ void TtsHandler::OnVoicesChanged() { content::TtsController* tts_controller = content::TtsController::GetInstance(); std::vector<content::VoiceData> voices; - tts_controller->GetVoices(Profile::FromWebUI(web_ui()), &voices); + tts_controller->GetVoices(Profile::FromWebUI(web_ui()), GURL(), &voices); const std::string& app_locale = g_browser_process->GetApplicationLocale(); base::ListValue responses; for (const auto& voice : voices) { diff --git a/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc b/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc index be684cae1e7..667410c6925 100644 --- a/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc @@ -9,6 +9,9 @@ #include "base/values.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/enterprise/connectors/connectors_prefs.h" +#include "chrome/browser/enterprise/connectors/file_system/service_settings.h" +#include "chrome/browser/enterprise/connectors/file_system/signin_experience.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/chrome_select_file_policy.h" #include "chrome/common/pref_names.h" @@ -21,10 +24,11 @@ #include "ui/base/l10n/l10n_util.h" #if BUILDFLAG(IS_CHROMEOS_ASH) -#include "chrome/browser/chromeos/file_manager/path_util.h" +#include "chrome/browser/ash/file_manager/path_util.h" #endif using base::UserMetricsAction; +namespace ec = enterprise_connectors; namespace settings { @@ -56,6 +60,12 @@ void DownloadsHandler::RegisterMessages() { base::BindRepeating(&DownloadsHandler::HandleGetDownloadLocationText, base::Unretained(this))); #endif + + web_ui()->RegisterMessageCallback( + "setDownloadsConnectionAccountLink", + base::BindRepeating( + &DownloadsHandler::HandleSetDownloadsConnectionAccountLink, + base::Unretained(this))); } void DownloadsHandler::OnJavascriptAllowed() { @@ -64,6 +74,11 @@ void DownloadsHandler::OnJavascriptAllowed() { prefs::kDownloadExtensionsToOpen, base::BindRepeating(&DownloadsHandler::SendAutoOpenDownloadsToJavascript, base::Unretained(this))); + pref_registrar_.Add( + enterprise_connectors::kSendDownloadToCloudPref, + base::BindRepeating( + &DownloadsHandler::SendDownloadsConnectionPolicyToJavascript, + base::Unretained(this))); } void DownloadsHandler::OnJavascriptDisallowed() { @@ -72,6 +87,7 @@ void DownloadsHandler::OnJavascriptDisallowed() { void DownloadsHandler::HandleInitialize(const base::ListValue* args) { AllowJavascript(); + SendDownloadsConnectionPolicyToJavascript(); SendAutoOpenDownloadsToJavascript(); } @@ -142,4 +158,73 @@ void DownloadsHandler::HandleGetDownloadLocationText( } #endif +using enterprise_connectors::FileSystemSigninDialogDelegate; + +bool DownloadsHandler::IsDownloadsConnectionPolicyEnabled() const { + return ec::GetFileSystemSettings(profile_).has_value(); +} + +void DownloadsHandler::SendDownloadsConnectionPolicyToJavascript() { + bool routing_enabled = IsDownloadsConnectionPolicyEnabled(); + if (routing_enabled) { + std::vector<std::string> connection_prefs = + ec::GetFileSystemConnectorPrefsForSettingsPage(profile_); + for (const std::string& pref : connection_prefs) { + if (pref_registrar_.IsObserved(pref)) + continue; + pref_registrar_.Add( + pref, base::BindRepeating( + &DownloadsHandler::SendDownloadsConnectionInfoToJavascript, + base::Unretained(this))); + } + SendDownloadsConnectionInfoToJavascript(); + } + + FireWebUIListener("downloads-connection-policy-changed", + base::Value(routing_enabled)); +} + +void DownloadsHandler::HandleSetDownloadsConnectionAccountLink( + const base::ListValue* args) { + DCHECK(IsDownloadsConnectionPolicyEnabled()); + CHECK_EQ(1U, args->GetSize()); + bool enable_link = args->GetList()[0].GetBool(); + ec::SetFileSystemConnectorAccountLinkForSettingsPage( + enable_link, profile_, + base::BindOnce(&DownloadsHandler::OnDownloadsConnectionAccountLinkSet, + weak_factory_.GetWeakPtr())); +} + +void DownloadsHandler::OnDownloadsConnectionAccountLinkSet(bool success) { + if (!success) { + DLOG(ERROR) << "Failed to set downloads connection account link"; + } + SendDownloadsConnectionInfoToJavascript(); +} + +void DownloadsHandler::SendDownloadsConnectionInfoToJavascript() { + absl::optional<ec::FileSystemSettings> settings = + ec::GetFileSystemSettings(profile_); + + absl::optional<ec::AccountInfo> info; + bool got_linked_account = + settings.has_value() && (info = GetFileSystemConnectorLinkedAccountInfo( + settings.value(), profile_->GetPrefs())) + .has_value(); + // Dict to match the fields used in downloads_page.html. + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetBoolKey("linked", got_linked_account); + if (got_linked_account) { + base::Value account(base::Value::Type::DICTIONARY); + account.SetStringKey("name", info->account_name); + account.SetStringKey("login", info->account_login); + dict.SetKey("account", std::move(account)); + base::Value folder(base::Value::Type::DICTIONARY); + folder.SetStringKey("name", info->folder_name); + folder.SetStringKey("link", info->folder_link); + dict.SetKey("folder", std::move(folder)); + } + FireWebUIListener("downloads-connection-link-changed", dict); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/downloads_handler.h b/chromium/chrome/browser/ui/webui/settings/downloads_handler.h index 3b758d26674..2ee531c668e 100644 --- a/chromium/chrome/browser/ui/webui/settings/downloads_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/downloads_handler.h @@ -57,12 +57,29 @@ class DownloadsHandler : public SettingsPageUIHandler, void HandleGetDownloadLocationText(const base::ListValue* args); #endif + bool IsDownloadsConnectionPolicyEnabled() const; + void SendDownloadsConnectionPolicyToJavascript(); + + // Callback for the "setDownloadsConnectionAccountLink" message. If there is + // no account linked and arg is true, this prompts the user to sign in; if + // there is an existing linked account and arg is false, this removes the + // linked account info and stored authentication tokens; otherwise, this + // merely sends the latest stored account info. + void HandleSetDownloadsConnectionAccountLink(const base::ListValue* args); + // Callback for file system connector code, since prompting the user to sign + // in is async. + void OnDownloadsConnectionAccountLinkSet(bool success); + // Sends the latest stored account info to the settings page. + void SendDownloadsConnectionInfoToJavascript(); + Profile* profile_; PrefChangeRegistrar pref_registrar_; scoped_refptr<ui::SelectFileDialog> select_folder_dialog_; + base::WeakPtrFactory<DownloadsHandler> weak_factory_{this}; + DISALLOW_COPY_AND_ASSIGN(DownloadsHandler); }; diff --git a/chromium/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc index 2fc26bd6471..204b58a4628 100644 --- a/chromium/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/downloads_handler_unittest.cc @@ -4,13 +4,20 @@ #include "chrome/browser/ui/webui/settings/downloads_handler.h" +#include "base/json/json_reader.h" #include "base/memory/ptr_util.h" +#include "base/strings/stringprintf.h" #include "chrome/browser/download/chrome_download_manager_delegate.h" #include "chrome/browser/download/download_core_service_factory.h" #include "chrome/browser/download/download_core_service_impl.h" #include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/enterprise/connectors/connectors_prefs.h" +#include "chrome/browser/enterprise/connectors/file_system/account_info_utils.h" +#include "chrome/browser/enterprise/connectors/file_system/service_settings.h" +#include "chrome/browser/enterprise/connectors/file_system/test_helper.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" +#include "components/os_crypt/os_crypt_mocker.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_ui.h" #include "content/public/test/browser_task_environment.h" @@ -18,9 +25,104 @@ #include "content/public/test/test_web_ui.h" #include "testing/gtest/include/gtest/gtest.h" +namespace { + +namespace ec = enterprise_connectors; +using WebUIDataReceivedPtr = std::unique_ptr<content::TestWebUI::CallData>; + +struct DownloadsSettings { + std::string auto_open_downloads = ""; + bool connection_init_enabled = false; + bool connection_init_linked_account = false; +}; + +const char kAccountName[] = "Jane Doe"; +const char kAccountLogin[] = "janedoe@downloads_handler_unittest.com"; +const char kFolderId[] = "12345"; +const char kFolderLinkFormat[] = "https://app.box.com/folder/%s"; +const char kFolderName[] = "ChromeDownloads"; + +void VerifyLinkedAccountInfo(const base::Value* dict, + bool expect_linked, + std::string expect_account_name, + std::string expect_account_login, + std::string expect_folder_name, + std::string expect_folder_id) { + ASSERT_TRUE(dict->is_dict()); + absl::optional<bool> has_account_linked_opt = dict->FindBoolKey("linked"); + ASSERT_TRUE(has_account_linked_opt.has_value()); + const bool has_account_linked = has_account_linked_opt.value(); + ASSERT_EQ(has_account_linked, expect_linked) << *dict; + + const std::string* account_name = dict->FindStringPath("account.name"); + const std::string* account_login = dict->FindStringPath("account.login"); + const std::string* folder_link = dict->FindStringPath("folder.link"); + const std::string* folder_name = dict->FindStringPath("folder.name"); + ASSERT_EQ(has_account_linked, account_name != nullptr) << *dict; + ASSERT_EQ(has_account_linked, account_login != nullptr) << *dict; + ASSERT_EQ(has_account_linked, folder_link != nullptr) << *dict; + ASSERT_EQ(has_account_linked, folder_name != nullptr) << *dict; + + if (has_account_linked) { + ASSERT_EQ(*account_name, expect_account_name); + ASSERT_EQ(*account_login, expect_account_login); + ASSERT_EQ(*folder_name, expect_folder_name); + std::string expect_folder_link = + base::StringPrintf(kFolderLinkFormat, expect_folder_id.c_str()); + ASSERT_EQ(*folder_link, expect_folder_link); + } +} + +void VerifyDownloadsConnectionPolicyChangedCallback( + const std::vector<WebUIDataReceivedPtr>& web_ui_call_data, + bool expect_connection_policy_enabled, + bool expect_policy_change_received, + size_t wait_till_nth_account_info, + bool expect_account_linked, + std::string expect_account_name, + std::string expect_account_login, + std::string expect_folder_name, + std::string expect_folder_id) { + ASSERT_FALSE(web_ui_call_data.empty()); + bool policy_change_received = false; + size_t account_info_received = 0; + for (auto& data : web_ui_call_data) { + EXPECT_EQ("cr.webUIListenerCallback", data->function_name()); + std::string event; + ASSERT_TRUE(data->arg1()->GetAsString(&event)); + if (event == "downloads-connection-policy-changed") { + policy_change_received = true; + ASSERT_TRUE(data->arg2()->is_bool()); + ASSERT_TRUE(expect_policy_change_received); + EXPECT_EQ(data->arg2()->GetBool(), expect_connection_policy_enabled); + } else if (event == "downloads-connection-link-changed") { + ++account_info_received; + if (account_info_received >= wait_till_nth_account_info) { + VerifyLinkedAccountInfo(data->arg2(), expect_account_linked, + expect_account_name, expect_account_login, + expect_folder_name, expect_folder_id); + } + } + } + ASSERT_EQ(expect_policy_change_received, policy_change_received); + ASSERT_GE(account_info_received, wait_till_nth_account_info); + ASSERT_EQ(expect_connection_policy_enabled, account_info_received > 0); +} + +void VerifyAutoOpenDownloadsChangedCallback(const WebUIDataReceivedPtr& data) { + EXPECT_EQ("cr.webUIListenerCallback", data->function_name()); + std::string event; + ASSERT_TRUE(data->arg1()->GetAsString(&event)); + EXPECT_EQ("auto-open-downloads-changed", event); + ASSERT_TRUE(data->arg2()->is_bool()); + EXPECT_FALSE(data->arg2()->GetBool()); +} + +} // namespace + namespace settings { -class DownloadsHandlerTest : public testing::Test { +class DownloadsHandlerTest : public testing::TestWithParam<DownloadsSettings> { public: DownloadsHandlerTest() : download_manager_(new content::MockDownloadManager()), @@ -40,36 +142,113 @@ class DownloadsHandlerTest : public testing::Test { } void SetUp() override { - EXPECT_TRUE(test_web_ui_.call_data().empty()); + EXPECT_TRUE(web_ui_call_data().empty()); + + const auto& param = GetParam(); + profile()->GetPrefs()->SetString(prefs::kDownloadExtensionsToOpen, + param.auto_open_downloads); + + // Setup the downloads connection feature. + OSCryptMocker::SetUp(); + feature_list_.InitWithFeatures({ec::kFileSystemConnectorEnabled}, {}); + ASSERT_TRUE(ec::SetFileSystemOAuth2Tokens( + profile()->GetPrefs(), ec::kFileSystemServiceProviderPrefNameBox, + "AToken", "RToken")); + if (param.connection_init_linked_account) + ASSERT_TRUE(param.connection_init_enabled); + SetDownloadsConnectionPolicy(param.connection_init_enabled); + if (param.connection_init_linked_account) + SetLinkedAccount(kAccountName, kAccountLogin, kFolderName, kFolderId); + + size_t expected_init_callback_count = 2u; + // SendDownloadsConnectionToJavascript(). + expected_init_callback_count += param.connection_init_enabled; base::ListValue args; handler()->HandleInitialize(&args); EXPECT_TRUE(handler()->IsJavascriptAllowed()); + ASSERT_EQ(web_ui_call_data().size(), expected_init_callback_count); VerifyAutoOpenDownloadsChangedCallback(); + VerifyDownloadsConnectionPolicyChangedCallback( + param.connection_init_linked_account); - test_web_ui_.ClearTrackedCalls(); + ClearWebUiTrackedCalls(); } void TearDown() override { service_->SetDownloadManagerDelegateForTesting(nullptr); + OSCryptMocker::TearDown(); testing::Test::TearDown(); } - void VerifyAutoOpenDownloadsChangedCallback() { - EXPECT_EQ(1u, test_web_ui_.call_data().size()); + void SetDownloadsConnectionPolicy(bool enable) { + profile()->GetPrefs()->Set( + ec::kSendDownloadToCloudPref, + enable ? *base::JSONReader::Read(ec::kWildcardSendDownloadToCloudPref) + : base::ListValue()); + ASSERT_EQ(handler_.IsDownloadsConnectionPolicyEnabled(), enable); + connection_policy_enabled_ = enable; + } - auto& data = *(test_web_ui_.call_data().back()); - EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); - std::string event; - ASSERT_TRUE(data.arg1()->GetAsString(&event)); - EXPECT_EQ("auto-open-downloads-changed", event); - ASSERT_TRUE(data.arg2()->is_bool()); - EXPECT_FALSE(data.arg2()->GetBool()); + void SetLinkedAccount(std::string account_name, + std::string account_login, + std::string folder_name, + std::string folder_id) { + base::DictionaryValue account_info; + account_info.SetStringKey("name", account_name); + account_info.SetStringKey("login", account_login); + ec::SetFileSystemAccountInfo(profile()->GetPrefs(), + ec::kFileSystemServiceProviderPrefNameBox, + std::move(account_info)); + ec::SetDefaultFolder(profile()->GetPrefs(), + ec::kFileSystemServiceProviderPrefNameBox, folder_id, + folder_name); + account_name_ = account_name; + account_login_ = account_login; + folder_name_ = folder_name; + folder_id_ = folder_id; + } + + void ToggleDownloadsConnectionPolicy() { + SetDownloadsConnectionPolicy(!connection_policy_enabled()); + } + + void VerifyDownloadsConnectionAccountLinkedUpdateCallback( + bool has_linked_account, + size_t wait_till_nth_account_info, + bool expect_policy_change_received = false) { + ASSERT_NE(web_ui_call_data().size(), 0u); + ::VerifyDownloadsConnectionPolicyChangedCallback( + web_ui_call_data(), connection_policy_enabled(), + expect_policy_change_received, wait_till_nth_account_info, + has_linked_account, account_name_, account_login_, folder_name_, + folder_id_); + } + + void VerifyDownloadsConnectionPolicyChangedCallback( + bool has_linked_account = GetParam().connection_init_linked_account) { + ASSERT_NE(web_ui_call_data().size(), 0u); + VerifyDownloadsConnectionAccountLinkedUpdateCallback( + has_linked_account, /* wait_till_nth_account_info = */ 0, + /* expect_policy_change_received = */ true); + } + + void VerifyAutoOpenDownloadsChangedCallback() const { + ASSERT_FALSE(web_ui_call_data().empty()); + ::VerifyAutoOpenDownloadsChangedCallback(web_ui_call_data().back()); } Profile* profile() { return &profile_; } DownloadsHandler* handler() { return &handler_; } + const std::vector<WebUIDataReceivedPtr>& web_ui_call_data() const { + return test_web_ui_.call_data(); + } + void ClearWebUiTrackedCalls() { + test_web_ui_.ClearTrackedCalls(); + ASSERT_EQ(web_ui_call_data().size(), 0u); + } + bool connection_policy_enabled() const { return connection_policy_enabled_; } private: content::BrowserTaskEnvironment task_environment_; @@ -80,13 +259,63 @@ class DownloadsHandlerTest : public testing::Test { content::MockDownloadManager* download_manager_; // Owned by |profile_|. ChromeDownloadManagerDelegate* chrome_download_manager_delegate_; + bool connection_policy_enabled_; + std::string account_name_, account_login_, folder_name_, folder_id_; + // Experimental flag for downloads connection. + base::test::ScopedFeatureList feature_list_; + DownloadsHandler handler_; }; -TEST_F(DownloadsHandlerTest, AutoOpenDownloads) { +TEST_P(DownloadsHandlerTest, AutoOpenDownloads) { // Touch the pref. - profile()->GetPrefs()->SetString(prefs::kDownloadExtensionsToOpen, ""); + profile()->GetPrefs()->SetString(prefs::kDownloadExtensionsToOpen, "def"); + EXPECT_EQ(web_ui_call_data().size(), 1u); VerifyAutoOpenDownloadsChangedCallback(); } +TEST_P(DownloadsHandlerTest, DownloadsConnectionToggle) { + // Toggle the feature policy. + ToggleDownloadsConnectionPolicy(); + VerifyDownloadsConnectionPolicyChangedCallback(); + ASSERT_EQ(connection_policy_enabled(), !GetParam().connection_init_enabled); +} + +TEST_P(DownloadsHandlerTest, DownloadsConnectionSendAccountInfo) { + // Ensure we can enable the feature policy. + if (!connection_policy_enabled()) { + SetDownloadsConnectionPolicy(true); + VerifyDownloadsConnectionPolicyChangedCallback( + /* has_linked_account = */ GetParam().connection_init_linked_account); + } + ASSERT_TRUE(connection_policy_enabled()); + ClearWebUiTrackedCalls(); + // Once feature is enabled via policy, account info updates are sent. + SetLinkedAccount("John Smith", "johnsmith@example.com", "DifferentFolderName", + "24680"); + // Expect number of account updates due to number of prefs being observed. The + // account infos received before this are mid-update. + const size_t expect_account_updates_count = + ec::GetFileSystemConnectorAccountInfoPrefs( + ec::kFileSystemServiceProviderPrefNameBox) + .size(); + ASSERT_GE(web_ui_call_data().size(), expect_account_updates_count); + VerifyDownloadsConnectionAccountLinkedUpdateCallback( + /* has_linked_account = */ true, + /* wait_till_nth_account_info = */ expect_account_updates_count, + /* expect_policy_change_received = */ false); +} + +const DownloadsSettings test_settings[] = + // .-- .auto_open_downloads + // | .-- .connection_init_enabled + // | | .---- .connection_init_linked_account + // | | | (must be false if `connection_init_enabled` is false) + {{"", true, true}, // Connection enabled + has linked account + {"", true, false}, // Connection enabled + no linked account + {"abc", false, false}}; // Connection disabled + no linked account +INSTANTIATE_TEST_SUITE_P(SettingsPage, + DownloadsHandlerTest, + testing::ValuesIn(test_settings)); + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/font_handler.cc b/chromium/chrome/browser/ui/webui/settings/font_handler.cc index 27fa6f75890..1e2ed5d4a2b 100644 --- a/chromium/chrome/browser/ui/webui/settings/font_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/font_handler.cc @@ -12,6 +12,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/i18n/rtl.h" +#include "base/strings/utf_string_conversions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" @@ -58,22 +59,21 @@ void FontHandler::HandleFetchFontsData(const base::ListValue* args) { void FontHandler::FontListHasLoaded(std::string callback_id, std::unique_ptr<base::ListValue> list) { + base::Value::ListView list_view = list->GetList(); // Font list. Selects the directionality for the fonts in the given list. - for (size_t i = 0; i < list->GetSize(); i++) { - base::ListValue* font; - bool has_font = list->GetList(i, &font); - DCHECK(has_font); + for (auto& i : list_view) { + DCHECK(i.is_list()); + base::Value::ConstListView font = i.GetList(); - std::u16string value; - bool has_value = font->GetString(1, &value); - DCHECK(has_value); + DCHECK(font.size() >= 2u && font[1].is_string()); + std::u16string value = base::UTF8ToUTF16(font[1].GetString()); bool has_rtl_chars = base::i18n::StringContainsStrongRTLChars(value); - font->AppendString(has_rtl_chars ? "rtl" : "ltr"); + i.Append(has_rtl_chars ? "rtl" : "ltr"); } base::DictionaryValue response; - response.Set("fontList", std::move(list)); + response.SetKey("fontList", base::Value::FromUniquePtrValue(std::move(list))); ResolveJavascriptCallback(base::Value(callback_id), response); } diff --git a/chromium/chrome/browser/ui/webui/settings/hats_handler.cc b/chromium/chrome/browser/ui/webui/settings/hats_handler.cc index 3c814af569f..da8a55dc24c 100644 --- a/chromium/chrome/browser/ui/webui/settings/hats_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/hats_handler.cc @@ -9,6 +9,8 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/hats/hats_service.h" #include "chrome/browser/ui/hats/hats_service_factory.h" +#include "chrome/browser/ui/hats/trust_safety_sentiment_service.h" +#include "chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h" #include "chrome/common/chrome_features.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/common/pref_names.h" @@ -56,36 +58,64 @@ HatsHandler::~HatsHandler() = default; void HatsHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "tryShowHatsSurvey", - base::BindRepeating(&HatsHandler::HandleTryShowHatsSurvey, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "tryShowPrivacySandboxSurvey", - base::BindRepeating(&HatsHandler::HandleTryShowPrivacySandboxHatsSurvey, + "trustSafetyInteractionOccurred", + base::BindRepeating(&HatsHandler::HandleTrustSafetyInteractionOccurred, base::Unretained(this))); } -void HatsHandler::HandleTryShowHatsSurvey(const base::ListValue* args) { - // If the privacy settings survey is explicitly targeting users who have not - // viewed the Privacy Sandbox page, and this user has viewed the page, do - // not attempt to show the privacy settings survey. - if (features::kHappinessTrackingSurveysForDesktopSettingsPrivacyNoSandbox - .Get() && - Profile::FromWebUI(web_ui())->GetPrefs()->GetBoolean( - prefs::kPrivacySandboxPageViewed)) { - return; - } +void HatsHandler::HandleTrustSafetyInteractionOccurred( + const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(1U, args->GetSize()); + auto interaction = + static_cast<TrustSafetyInteraction>(args->GetList()[0].GetInt()); - LaunchHatsSurveyWithProductSpecificData(Profile::FromWebUI(web_ui()), - web_ui()->GetWebContents(), - kHatsSurveyTriggerSettingsPrivacy); + // Both the HaTS service, and the T&S sentiment service (which is another + // wrapper on the HaTS service), may decide to launch surveys based on this + // user interaction. The HaTS service is responsible for ensuring that users + // are not over-surveyed, and that other potential issues such as simultaneous + // surveys are avoided. + RequestHatsSurvey(interaction); + InformSentimentService(interaction); } -void HatsHandler::HandleTryShowPrivacySandboxHatsSurvey( - const base::ListValue* args) { - LaunchHatsSurveyWithProductSpecificData(Profile::FromWebUI(web_ui()), - web_ui()->GetWebContents(), - kHatsSurveyTriggerPrivacySandbox); +void HatsHandler::RequestHatsSurvey(TrustSafetyInteraction interaction) { + if (interaction == TrustSafetyInteraction::OPENED_PRIVACY_SANDBOX) { + LaunchHatsSurveyWithProductSpecificData(Profile::FromWebUI(web_ui()), + web_ui()->GetWebContents(), + kHatsSurveyTriggerPrivacySandbox); + } else if (interaction == TrustSafetyInteraction::RAN_SAFETY_CHECK || + interaction == TrustSafetyInteraction::USED_PRIVACY_CARD) { + // If the privacy settings survey is explicitly targeting users who have not + // viewed the Privacy Sandbox page, and this user has viewed the page, do + // not attempt to show the privacy settings survey. + if (features::kHappinessTrackingSurveysForDesktopSettingsPrivacyNoSandbox + .Get() && + Profile::FromWebUI(web_ui())->GetPrefs()->GetBoolean( + prefs::kPrivacySandboxPageViewed)) { + return; + } + LaunchHatsSurveyWithProductSpecificData(Profile::FromWebUI(web_ui()), + web_ui()->GetWebContents(), + kHatsSurveyTriggerSettingsPrivacy); + } +} + +void HatsHandler::InformSentimentService(TrustSafetyInteraction interaction) { + auto* sentiment_service = TrustSafetySentimentServiceFactory::GetForProfile( + Profile::FromWebUI(web_ui())); + if (!sentiment_service) + return; + + if (interaction == TrustSafetyInteraction::USED_PRIVACY_CARD) { + sentiment_service->InteractedWithPrivacySettings( + web_ui()->GetWebContents()); + } else if (interaction == TrustSafetyInteraction::RAN_SAFETY_CHECK) { + sentiment_service->RanSafetyCheck(); + } else if (interaction == TrustSafetyInteraction::OPENED_PASSWORD_MANAGER) { + sentiment_service->OpenedPasswordManager(web_ui()->GetWebContents()); + } } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/hats_handler.h b/chromium/chrome/browser/ui/webui/settings/hats_handler.h index 69197fccb77..492e6dd9593 100644 --- a/chromium/chrome/browser/ui/webui/settings/hats_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/hats_handler.h @@ -23,13 +23,29 @@ class HatsHandler : public SettingsPageUIHandler { // WebUIMessageHandler implementation. void RegisterMessages() override; - void HandleTryShowHatsSurvey(const base::ListValue* args); - - void HandleTryShowPrivacySandboxHatsSurvey(const base::ListValue* args); + void HandleTrustSafetyInteractionOccurred(const base::ListValue* args); private: friend class HatsHandlerTest; - FRIEND_TEST_ALL_PREFIXES(HatsHandlerTest, HandleTryShowHatsSurvey); + FRIEND_TEST_ALL_PREFIXES(HatsHandlerTest, PrivacySettingsHats); + FRIEND_TEST_ALL_PREFIXES(HatsHandlerTest, PrivacySandboxHats); + FRIEND_TEST_ALL_PREFIXES(HatsHandlerTest, TrustSafetySentimentInteractions); + + // All Trust & Safety based interactions which may result in a HaTS survey. + // Must be kept in sync with the enum of the same name in + // hats_browser_proxy.js + enum class TrustSafetyInteraction { + RAN_SAFETY_CHECK = 0, + USED_PRIVACY_CARD = 1, + OPENED_PRIVACY_SANDBOX = 2, + OPENED_PASSWORD_MANAGER = 3, + }; + + // Requests the appropriate HaTS survey, which may be none, for |interaction|. + void RequestHatsSurvey(TrustSafetyInteraction interaction); + + // Informs the sentiment service, if appropriate, that |interaction| occurred. + void InformSentimentService(TrustSafetyInteraction interaction); // SettingsPageUIHandler implementation. void OnJavascriptAllowed() override {} diff --git a/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc index c7e564190b1..76f21c85ad5 100644 --- a/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/hats_handler_unittest.cc @@ -11,6 +11,8 @@ #include "chrome/browser/ui/hats/hats_service.h" #include "chrome/browser/ui/hats/hats_service_factory.h" #include "chrome/browser/ui/hats/mock_hats_service.h" +#include "chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h" +#include "chrome/browser/ui/hats/trust_safety_sentiment_service_factory.h" #include "chrome/common/chrome_features.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/content_settings/core/browser/cookie_settings.h" @@ -20,6 +22,8 @@ #include "content/public/test/test_web_ui.h" #include "testing/gmock/include/gmock/gmock.h" +using ::testing::_; + class Profile; namespace settings { @@ -39,6 +43,14 @@ class HatsHandlerTest : public ChromeRenderViewHostTestHarness { mock_hats_service_ = static_cast<MockHatsService*>( HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse( profile(), base::BindRepeating(&BuildMockHatsService))); + EXPECT_CALL(*mock_hats_service_, CanShowAnySurvey(_)) + .WillRepeatedly(testing::Return(true)); + + mock_sentiment_service_ = static_cast<MockTrustSafetySentimentService*>( + TrustSafetySentimentServiceFactory::GetInstance() + ->SetTestingFactoryAndUse( + profile(), + base::BindRepeating(&BuildMockTrustSafetySentimentService))); } void TearDown() override { @@ -52,6 +64,7 @@ class HatsHandlerTest : public ChromeRenderViewHostTestHarness { content::TestWebUI* web_ui() { return web_ui_.get(); } HatsHandler* handler() { return handler_.get(); } MockHatsService* mock_hats_service_; + MockTrustSafetySentimentService* mock_sentiment_service_; protected: base::test::ScopedFeatureList scoped_feature_list_; @@ -61,19 +74,32 @@ class HatsHandlerTest : public ChromeRenderViewHostTestHarness { std::unique_ptr<HatsHandler> handler_; }; -TEST_F(HatsHandlerTest, HandleTryShowHatsSurvey) { +TEST_F(HatsHandlerTest, PrivacySettingsHats) { profile()->GetPrefs()->SetBoolean(prefs::kPrivacySandboxApisEnabled, false); profile()->GetPrefs()->SetInteger( prefs::kCookieControlsMode, static_cast<int>(content_settings::CookieControlsMode::kBlockThirdParty)); - std::map<std::string, bool> expected_product_specific_data = { + SurveyBitsData expected_product_specific_data = { {"3P cookies blocked", true}, {"Privacy Sandbox enabled", false}}; - EXPECT_CALL(*mock_hats_service_, LaunchDelayedSurveyForWebContents( - kHatsSurveyTriggerSettingsPrivacy, - web_contents(), 20000, expected_product_specific_data)); - base::ListValue args; - handler()->HandleTryShowHatsSurvey(&args); + // Check that both interacting with the privacy card, and running Safety Check + // result in a survey request with the appropriate product specific data. + EXPECT_CALL(*mock_hats_service_, + LaunchDelayedSurveyForWebContents( + kHatsSurveyTriggerSettingsPrivacy, web_contents(), 20000, + expected_product_specific_data, _)) + .Times(2); + base::Value args(base::Value::Type::LIST); + args.Append( + static_cast<int>(HatsHandler::TrustSafetyInteraction::USED_PRIVACY_CARD)); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); + task_environment()->RunUntilIdle(); + + args.GetList()[0] = base::Value( + static_cast<int>(HatsHandler::TrustSafetyInteraction::RAN_SAFETY_CHECK)); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); testing::Mock::VerifyAndClearExpectations(mock_hats_service_); @@ -81,8 +107,7 @@ TEST_F(HatsHandlerTest, HandleTryShowHatsSurvey) { // Enable targeting for users who have not seen the Privacy Sandbox page and // ensure the handler does not attempt to launch the survey. EXPECT_CALL(*mock_hats_service_, - LaunchDelayedSurveyForWebContents(testing::_, testing::_, - testing::_, testing::_)) + LaunchDelayedSurveyForWebContents(_, _, _, _, _)) .Times(0); base::test::ScopedFeatureList::FeatureAndParams feature_and_params{ @@ -92,25 +117,67 @@ TEST_F(HatsHandlerTest, HandleTryShowHatsSurvey) { profile()->GetPrefs()->SetBoolean(prefs::kPrivacySandboxPageViewed, true); - handler()->HandleTryShowHatsSurvey(&args); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); } -TEST_F(HatsHandlerTest, HandleTryShowPrivacySandboxHatsSurvey) { +TEST_F(HatsHandlerTest, PrivacySandboxHats) { // Check that the handler correctly forwards the survey request to the // HaTS service and also includes the appropriate product specific data. profile()->GetPrefs()->SetBoolean(prefs::kPrivacySandboxApisEnabled, false); profile()->GetPrefs()->SetInteger( prefs::kCookieControlsMode, static_cast<int>(content_settings::CookieControlsMode::kBlockThirdParty)); - std::map<std::string, bool> expected_product_specific_data = { + SurveyBitsData expected_product_specific_data = { {"3P cookies blocked", true}, {"Privacy Sandbox enabled", false}}; - EXPECT_CALL(*mock_hats_service_, LaunchDelayedSurveyForWebContents( - kHatsSurveyTriggerPrivacySandbox, - web_contents(), 20000, expected_product_specific_data)); - base::ListValue args; - handler()->HandleTryShowPrivacySandboxHatsSurvey(&args); + EXPECT_CALL(*mock_hats_service_, + LaunchDelayedSurveyForWebContents( + kHatsSurveyTriggerPrivacySandbox, web_contents(), 20000, + expected_product_specific_data, _)); + base::Value args(base::Value::Type::LIST); + args.Append(static_cast<int>( + HatsHandler::TrustSafetyInteraction::OPENED_PRIVACY_SANDBOX)); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); } +TEST_F(HatsHandlerTest, TrustSafetySentimentInteractions) { + // Check that interactions relevant to the T&S sentiment service are + // correctly reported. + EXPECT_CALL(*mock_sentiment_service_, + InteractedWithPrivacySettings(web_contents())) + .Times(1); + base::Value args(base::Value::Type::LIST); + args.Append( + static_cast<int>(HatsHandler::TrustSafetyInteraction::USED_PRIVACY_CARD)); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); + + EXPECT_CALL(*mock_sentiment_service_, RanSafetyCheck()).Times(2); + args.GetList()[0] = base::Value( + static_cast<int>(HatsHandler::TrustSafetyInteraction::RAN_SAFETY_CHECK)); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); + + // A profile & feature state that would exclude the user from receiving the + // Privacy Settings HaTS survey should not stop the sentiment service being + // informed that the interaction occurred. + testing::Mock::VerifyAndClearExpectations(mock_hats_service_); + base::test::ScopedFeatureList::FeatureAndParams feature_and_params{ + features::kHappinessTrackingSurveysForDesktopSettingsPrivacy, + {{"no-sandbox", "true"}}}; + scoped_feature_list_.InitWithFeaturesAndParameters({feature_and_params}, {}); + profile()->GetPrefs()->SetBoolean(prefs::kPrivacySandboxPageViewed, true); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); + + EXPECT_CALL(*mock_sentiment_service_, OpenedPasswordManager(web_contents())); + args.GetList()[0] = base::Value(static_cast<int>( + HatsHandler::TrustSafetyInteraction::OPENED_PASSWORD_MANAGER)); + handler()->HandleTrustSafetyInteractionOccurred( + &base::Value::AsListValue(args)); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/import_data_handler.cc b/chromium/chrome/browser/ui/webui/settings/import_data_handler.cc index f1f2fe731b4..a00b40e8804 100644 --- a/chromium/chrome/browser/ui/webui/settings/import_data_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/import_data_handler.cc @@ -106,12 +106,13 @@ void ImportDataHandler::StartImport( void ImportDataHandler::HandleImportData(const base::ListValue* args) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + const auto& list = args->GetList(); + CHECK_GE(list.size(), 2u); - int browser_index; - CHECK(args->GetInteger(0, &browser_index)); + int browser_index = list[0].GetInt(); - const base::DictionaryValue* types = nullptr; - CHECK(args->GetDictionary(1, &types)); + const base::Value& types = list[1]; + CHECK(types.is_dict()); if (!importer_list_loaded_ || browser_index < 0 || browser_index >= static_cast<int>(importer_list_->count())) { @@ -120,15 +121,15 @@ void ImportDataHandler::HandleImportData(const base::ListValue* args) { } uint16_t selected_items = importer::NONE; - if (*types->FindBoolKey(prefs::kImportDialogAutofillFormData)) + if (*types.FindBoolKey(prefs::kImportDialogAutofillFormData)) selected_items |= importer::AUTOFILL_FORM_DATA; - if (*types->FindBoolKey(prefs::kImportDialogBookmarks)) + if (*types.FindBoolKey(prefs::kImportDialogBookmarks)) selected_items |= importer::FAVORITES; - if (*types->FindBoolKey(prefs::kImportDialogHistory)) + if (*types.FindBoolKey(prefs::kImportDialogHistory)) selected_items |= importer::HISTORY; - if (*types->FindBoolKey(prefs::kImportDialogSavedPasswords)) + if (*types.FindBoolKey(prefs::kImportDialogSavedPasswords)) selected_items |= importer::PASSWORDS; - if (*types->FindBoolKey(prefs::kImportDialogSearchEngine)) + if (*types.FindBoolKey(prefs::kImportDialogSearchEngine)) selected_items |= importer::SEARCH_ENGINES; const importer::SourceProfile& source_profile = @@ -167,7 +168,7 @@ void ImportDataHandler::HandleImportFromBookmarksFile( if (select_file_dialog_) return; - DCHECK(args && args->empty()); + DCHECK(args && args->GetList().empty()); select_file_dialog_ = ui::SelectFileDialog::Create( this, std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents())); diff --git a/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc b/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc index 51518ded9bc..7320a712d89 100644 --- a/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler.cc @@ -22,7 +22,7 @@ #if BUILDFLAG(IS_CHROMEOS_LACROS) #include "chromeos/crosapi/mojom/metrics_reporting.mojom.h" // nogncheck -#include "chromeos/lacros/lacros_chrome_service_impl.h" +#include "chromeos/lacros/lacros_service.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) namespace settings { @@ -82,7 +82,7 @@ std::unique_ptr<base::DictionaryValue> #if BUILDFLAG(IS_CHROMEOS_LACROS) // To match the pre-Lacros settings UX, we show the managed icon if the ash // device-level metrics reporting pref is managed. https://crbug.com/1148604 - auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get(); + auto* lacros_chrome_service = chromeos::LacrosService::Get(); // Service may be null in tests. bool managed = lacros_chrome_service && lacros_chrome_service->init_params()->ash_metrics_managed == @@ -114,7 +114,7 @@ void MetricsReportingHandler::HandleSetMetricsReportingEnabled( // To match the pre-Lacros settings UX, the metrics reporting toggle in Lacros // browser settings controls both browser metrics reporting and OS metrics // reporting. See https://crbug.com/1148604. - auto* lacros_chrome_service = chromeos::LacrosChromeServiceImpl::Get(); + auto* lacros_chrome_service = chromeos::LacrosService::Get(); // Service may be null in tests. if (!lacros_chrome_service) return; diff --git a/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc index c587ad61a1a..9e61775fbec 100644 --- a/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc @@ -43,8 +43,8 @@ class MetricsReportingHandlerTest : public testing::Test { handler_ = std::make_unique<TestingMetricsReportingHandler>(); handler_->set_web_ui(&test_web_ui_); - EXPECT_CALL(provider_, IsInitializationComplete(testing::_)).WillRepeatedly( - testing::Return(true)); + provider_.SetDefaultReturns(/*is_initialization_complete_return=*/true, + /*is_first_policy_load_complete_return=*/true); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); } @@ -83,7 +83,7 @@ class MetricsReportingHandlerTest : public testing::Test { std::unique_ptr<ScopedTestingLocalState> local_state_; std::unique_ptr<TestingMetricsReportingHandler> handler_; - policy::MockConfigurationPolicyProvider provider_; + testing::NiceMock<policy::MockConfigurationPolicyProvider> provider_; policy::PolicyMap map_; }; diff --git a/chromium/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc index 199f25f9b3f..b19ca49b163 100644 --- a/chromium/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/on_startup_handler_unittest.cc @@ -78,37 +78,35 @@ class OnStartupHandlerTest : public testing::Test { }; TEST_F(OnStartupHandlerTest, HandleGetNtpExtension) { - base::ListValue list_args; - list_args.AppendString(kCallbackId); - handler()->HandleGetNtpExtension(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kCallbackId); + handler()->HandleGetNtpExtension(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); EXPECT_TRUE(data.arg2()->GetBool()); } TEST_F(OnStartupHandlerTest, HandleValidateStartupPage_Valid) { - base::ListValue list_args; - list_args.AppendString(kCallbackId); - list_args.AppendString("http://example.com"); - handler()->HandleValidateStartupPage(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kCallbackId); + list_args.Append("http://example.com"); + handler()->HandleValidateStartupPage(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); EXPECT_TRUE(data.arg2()->GetBool()); @@ -118,19 +116,18 @@ TEST_F(OnStartupHandlerTest, HandleValidateStartupPage_Valid) { } TEST_F(OnStartupHandlerTest, HandleValidateStartupPage_Invalid) { - base::ListValue list_args; - list_args.AppendString(kCallbackId); - list_args.AppendString("@"); - handler()->HandleValidateStartupPage(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kCallbackId); + list_args.Append("@"); + handler()->HandleValidateStartupPage(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); EXPECT_TRUE(data.arg2()->GetBool()); diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.cc b/chromium/chrome/browser/ui/webui/settings/people_handler.cc index 95c22b6e7f8..4c17ccf73be 100644 --- a/chromium/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/people_handler.cc @@ -11,7 +11,6 @@ #include "base/compiler_specific.h" #include "base/i18n/time_formatting.h" #include "base/json/json_reader.h" -#include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -26,7 +25,7 @@ #include "chrome/browser/signin/signin_promo.h" #include "chrome/browser/signin/signin_ui_util.h" #include "chrome/browser/signin/signin_util.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" @@ -51,6 +50,7 @@ #include "components/sync/base/passphrase_enums.h" #include "components/sync/base/user_selectable_type.h" #include "components/sync/driver/sync_driver_switches.h" +#include "components/sync/driver/sync_service_utils.h" #include "components/sync/driver/sync_user_settings.h" #include "components/unified_consent/unified_consent_metrics.h" #include "content/public/browser/render_view_host.h" @@ -146,21 +146,21 @@ void ParseConfigurationArguments(const base::ListValue* args, NOTREACHED(); } -std::string GetSyncErrorAction(sync_ui_util::ActionType action_type) { +std::string GetSyncErrorAction(SyncStatusActionType action_type) { switch (action_type) { - case sync_ui_util::REAUTHENTICATE: + case SyncStatusActionType::kReauthenticate: return "reauthenticate"; - case sync_ui_util::SIGNOUT_AND_SIGNIN: + case SyncStatusActionType::kSignoutAndSignin: return "signOutAndSignIn"; - case sync_ui_util::UPGRADE_CLIENT: + case SyncStatusActionType::kUpgradeClient: return "upgradeClient"; - case sync_ui_util::ENTER_PASSPHRASE: + case SyncStatusActionType::kEnterPassphrase: return "enterPassphrase"; - case sync_ui_util::RETRIEVE_TRUSTED_VAULT_KEYS: + case SyncStatusActionType::kRetrieveTrustedVaultKeys: return "retrieveTrustedVaultKeys"; - case sync_ui_util::CONFIRM_SYNC_SETTINGS: + case SyncStatusActionType::kConfirmSyncSettings: return "confirmSyncSettings"; - case sync_ui_util::NO_ACTION: + case SyncStatusActionType::kNoAction: return "noAction"; } @@ -184,47 +184,6 @@ base::Value GetAccountValue(const AccountInfo& account) { return dictionary; } -std::u16string GetEnterPassphraseBody(syncer::PassphraseType passphrase_type, - base::Time passphrase_time) { - DCHECK(syncer::IsExplicitPassphrase(passphrase_type)); - switch (passphrase_type) { - case syncer::PassphraseType::kFrozenImplicitPassphrase: - case syncer::PassphraseType::kCustomPassphrase: - if (passphrase_time.is_null()) { - return GetStringUTF16(IDS_SYNC_ENTER_PASSPHRASE_BODY); - } - return GetStringFUTF16(IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE, - base::ASCIIToUTF16(chrome::kSyncErrorsHelpURL), - base::TimeFormatShortDate(passphrase_time)); - case syncer::PassphraseType::kImplicitPassphrase: - case syncer::PassphraseType::kKeystorePassphrase: - case syncer::PassphraseType::kTrustedVaultPassphrase: - break; - } - NOTREACHED(); - return std::u16string(); -} - -std::u16string GetFullEncryptionBody(syncer::PassphraseType passphrase_type, - base::Time passphrase_time) { - DCHECK(syncer::IsExplicitPassphrase(passphrase_type)); - if (passphrase_time.is_null()) { - return GetStringUTF16(IDS_SYNC_FULL_ENCRYPTION_BODY_CUSTOM); - } - switch (passphrase_type) { - case syncer::PassphraseType::kFrozenImplicitPassphrase: - case syncer::PassphraseType::kCustomPassphrase: - return GetStringFUTF16(IDS_SYNC_FULL_ENCRYPTION_BODY_CUSTOM_WITH_DATE, - base::TimeFormatShortDate(passphrase_time)); - case syncer::PassphraseType::kImplicitPassphrase: - case syncer::PassphraseType::kKeystorePassphrase: - case syncer::PassphraseType::kTrustedVaultPassphrase: - break; - } - NOTREACHED(); - return std::u16string(); -} - } // namespace namespace settings { @@ -341,7 +300,7 @@ void PeopleHandler::OnJavascriptAllowed() { // This is intentionally not using GetSyncService(), to go around the // Profile::IsSyncAllowed() check. syncer::SyncService* sync_service = - ProfileSyncServiceFactory::GetForProfile(profile_); + SyncServiceFactory::GetForProfile(profile_); if (sync_service) sync_service_observation_.Observe(sync_service); } @@ -385,10 +344,6 @@ void PeopleHandler::DisplayGaiaLoginInNewTabOrWindow( // re-auth scenario, and we need to ensure that the user signs in with the // same email address. if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) { - UMA_HISTOGRAM_ENUMERATION("Signin.Reauth", - signin_metrics::HISTOGRAM_REAUTH_SHOWN, - signin_metrics::HISTOGRAM_REAUTH_MAX); - SigninErrorController* error_controller = SigninErrorControllerFactory::GetForProfile(browser->profile()); DCHECK(error_controller->HasError()); @@ -412,8 +367,8 @@ void PeopleHandler::OnDidClosePage(const base::ListValue* args) { } syncer::SyncService* PeopleHandler::GetSyncService() const { - return ProfileSyncServiceFactory::IsSyncAllowed(profile_) - ? ProfileSyncServiceFactory::GetForProfile(profile_) + return SyncServiceFactory::IsSyncAllowed(profile_) + ? SyncServiceFactory::GetForProfile(profile_) : nullptr; } @@ -489,11 +444,10 @@ base::Value PeopleHandler::GetStoredAccountsList() { // Chrome OS), then show only the primary account, whether or not that account // has consented to sync. auto* identity_manager = IdentityManagerFactory::GetForProfile(profile_); - absl::optional<AccountInfo> primary_account_info = - identity_manager->FindExtendedAccountInfoForAccountWithRefreshToken( - identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSignin)); - if (primary_account_info.has_value()) - accounts.Append(GetAccountValue(primary_account_info.value())); + AccountInfo primary_account_info = identity_manager->FindExtendedAccountInfo( + identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSignin)); + if (!primary_account_info.IsEmpty()) + accounts.Append(GetAccountValue(primary_account_info)); return accounts; } @@ -508,14 +462,12 @@ void PeopleHandler::HandleStartSyncingWithEmail(const base::ListValue* args) { Browser* browser = chrome::FindBrowserWithWebContents(web_ui()->GetWebContents()); - absl::optional<AccountInfo> maybe_account = + AccountInfo maybe_account = IdentityManagerFactory::GetForProfile(profile_) - ->FindExtendedAccountInfoForAccountWithRefreshTokenByEmailAddress( - email->GetString()); + ->FindExtendedAccountInfoByEmailAddress(email->GetString()); signin_ui_util::EnableSyncFromMultiAccountPromo( - browser, - maybe_account.has_value() ? maybe_account.value() : AccountInfo(), + browser, maybe_account, signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS, is_default_promo_account->GetBool()); #else @@ -722,8 +674,8 @@ void PeopleHandler::HandleStartKeyRetrieval(const base::ListValue* args) { if (!browser) return; - sync_ui_util::OpenTabForSyncKeyRetrieval( - browser, syncer::KeyRetrievalTriggerForUMA::kSettings); + OpenTabForSyncKeyRetrieval( + browser, syncer::TrustedVaultUserActionTriggerForUMA::kSettings); } void PeopleHandler::HandleGetSyncStatus(const base::ListValue* args) { @@ -744,8 +696,9 @@ void PeopleHandler::HandleSyncPrefsDispatch(const base::ListValue* args) { void PeopleHandler::HandleOfferTrustedVaultOptInDispatch( const base::ListValue* args) { AllowJavascript(); - FireWebUIListener(kOfferTrustedVaultOptInChangedEvent, - base::Value(ShouldOfferTrustedVaultOptIn())); + FireWebUIListener( + kOfferTrustedVaultOptInChangedEvent, + base::Value(syncer::ShouldOfferTrustedVaultOptIn(GetSyncService()))); } void PeopleHandler::CloseSyncSetup() { @@ -823,39 +776,6 @@ void PeopleHandler::InitializeSyncBlocker() { } } -bool PeopleHandler::ShouldOfferTrustedVaultOptIn() const { - syncer::SyncService* sync_service = GetSyncService(); - if (!sync_service) { - return false; - } - - if (sync_service->GetTransportState() != - syncer::SyncService::TransportState::ACTIVE) { - // Transport state must be active so SyncUserSettings::GetPassphraseType() - // changes once the opt-in completes, and the UI is notified. - return false; - } - - switch (sync_service->GetUserSettings()->GetPassphraseType()) { - case syncer::PassphraseType::kImplicitPassphrase: - case syncer::PassphraseType::kFrozenImplicitPassphrase: - case syncer::PassphraseType::kCustomPassphrase: - case syncer::PassphraseType::kTrustedVaultPassphrase: - // Either trusted vault is already set or a transition from this - // passphrase type to trusted vault is disallowed. - return false; - case syncer::PassphraseType::kKeystorePassphrase: - if (sync_service->GetUserSettings()->IsPassphraseRequired()) { - // This should be extremely rare. - return false; - } - return base::FeatureList::IsEnabled( - switches::kSyncSupportTrustedVaultPassphraseRecovery) && - base::FeatureList::IsEnabled( - switches::kSyncOfferTrustedVaultOptIn); - } -} - void PeopleHandler::FocusUI() { WebContents* web_contents = web_ui()->GetWebContents(); web_contents->GetDelegate()->ActivateContents(web_contents); @@ -883,15 +803,15 @@ void PeopleHandler::OnPrimaryAccountChanged( } } -void PeopleHandler::OnStateChanged(syncer::SyncService* sync) { +void PeopleHandler::OnStateChanged(syncer::SyncService* sync_service) { UpdateSyncStatus(); // TODO(crbug.com/1106764): Re-evaluate marking sync as configuring here, - // since this gets called whenever ProfileSyncService changes state. Inline + // since this gets called whenever SyncService changes state. Inline // MaybeMarkSyncConfiguring() then. MaybeMarkSyncConfiguring(); PushSyncPrefs(); FireWebUIListener(kOfferTrustedVaultOptInChangedEvent, - base::Value(ShouldOfferTrustedVaultOptIn())); + base::Value(ShouldOfferTrustedVaultOptIn(sync_service))); } void PeopleHandler::BeforeUnloadDialogCancelled() { @@ -936,8 +856,7 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary() // This is intentionally not using GetSyncService(), in order to access more // nuanced information, since GetSyncService() returns nullptr if anything // makes Profile::IsSyncAllowed() false. - syncer::SyncService* service = - ProfileSyncServiceFactory::GetForProfile(profile_); + syncer::SyncService* service = SyncServiceFactory::GetForProfile(profile_); bool disallowed_by_policy = service && service->HasDisableReason( syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY); @@ -948,8 +867,7 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary() !service->GetUserSettings()->IsFirstSetupComplete() && identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - const sync_ui_util::StatusLabels status_labels = - sync_ui_util::GetStatusLabels(profile_); + const SyncStatusLabels status_labels = GetSyncStatusLabels(profile_); // TODO(crbug.com/1027467): Consider unifying some of the fields below to // avoid redundancy. sync_status->SetString("statusText", @@ -957,12 +875,13 @@ std::unique_ptr<base::DictionaryValue> PeopleHandler::GetSyncStatusDictionary() sync_status->SetString("statusActionText", GetStringUTF16(status_labels.button_string_id)); sync_status->SetBoolean( - "hasError", status_labels.message_type == sync_ui_util::SYNC_ERROR || - status_labels.message_type == - sync_ui_util::PASSWORDS_ONLY_SYNC_ERROR); - sync_status->SetBoolean( - "hasPasswordsOnlyError", - status_labels.message_type == sync_ui_util::PASSWORDS_ONLY_SYNC_ERROR); + "hasError", + status_labels.message_type == SyncStatusMessageType::kSyncError || + status_labels.message_type == + SyncStatusMessageType::kPasswordsOnlySyncError); + sync_status->SetBoolean("hasPasswordsOnlyError", + status_labels.message_type == + SyncStatusMessageType::kPasswordsOnlySyncError); sync_status->SetString("statusAction", GetSyncErrorAction(status_labels.action_type)); @@ -994,12 +913,17 @@ void PeopleHandler::PushSyncPrefs() { // <data_type>Registered: true if the associated data type is supported // <data_type>Synced: true if the user wants to sync that specific data type // paymentsIntegrationEnabled: true if the user wants Payments integration - // encryptionEnabled: true if sync supports encryption + // customPassphraseAllowed: true if sync allows setting a custom passphrase + // to encrypt data. // encryptAllData: true if user wants to encrypt all data (not just // passwords) // passphraseRequired: true if a passphrase is needed to start sync // trustedVaultKeysRequired: true if trusted vault keys are needed to start // sync. + // explicitPassphraseTime: the stringified time when the current explicit + // passphrase was set (in milliseconds since the Unix + // epoch); undefined if the time is unknown or no explicit + // passphrase is set. // base::DictionaryValue args; @@ -1035,15 +959,10 @@ void PeopleHandler::PushSyncPrefs() { args.SetBoolean("trustedVaultKeysRequired", sync_user_settings->IsTrustedVaultKeyRequired()); - syncer::PassphraseType passphrase_type = - sync_user_settings->GetPassphraseType(); - if (syncer::IsExplicitPassphrase(passphrase_type)) { - base::Time passphrase_time = - sync_user_settings->GetExplicitPassphraseTime(); - args.SetString("enterPassphraseBody", - GetEnterPassphraseBody(passphrase_type, passphrase_time)); - args.SetString("fullEncryptionBody", - GetFullEncryptionBody(passphrase_type, passphrase_time)); + base::Time passphrase_time = sync_user_settings->GetExplicitPassphraseTime(); + if (!passphrase_time.is_null()) { + args.SetString("explicitPassphraseTime", + base::TimeFormatShortDate(passphrase_time)); } FireWebUIListener("sync-prefs-changed", args); diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.h b/chromium/chrome/browser/ui/webui/settings/people_handler.h index f126be4cd12..6999ae51a54 100644 --- a/chromium/chrome/browser/ui/webui/settings/people_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/people_handler.h @@ -132,7 +132,7 @@ class PeopleHandler : public SettingsPageUIHandler, void OnExtendedAccountInfoRemoved(const AccountInfo& info) override; // syncer::SyncServiceObserver implementation. - void OnStateChanged(syncer::SyncService* sync) override; + void OnStateChanged(syncer::SyncService* sync_service) override; // content::WebContentsObserver implementation void BeforeUnloadDialogCancelled() override; @@ -208,10 +208,6 @@ class PeopleHandler : public SettingsPageUIHandler, // |sync_blocker_|. void InitializeSyncBlocker(); - // Whether the entry in settings to opt in to trusted vault encryption - // should be visible. - bool ShouldOfferTrustedVaultOptIn() const; - // Weak pointer. Profile* profile_; diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc index 43c20080e96..854db35c604 100644 --- a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc @@ -11,9 +11,10 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" +#include "base/i18n/time_formatting.h" #include "base/json/json_writer.h" #include "base/macros.h" -#include "base/stl_util.h" +#include "base/strings/utf_string_conversions.h" #include "base/test/mock_callback.h" #include "base/values.h" #include "build/build_config.h" @@ -23,7 +24,7 @@ #include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/browser/signin/signin_error_controller_factory.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/webui/signin/login_ui_service.h" #include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" @@ -118,28 +119,17 @@ std::string GetConfiguration(SyncAllDataConfig sync_all, } // Checks whether the passed |dictionary| contains a |key| with the given -// |expected_value|. If |omit_if_false| is true, then the value should only -// be present if |expected_value| is true. -void CheckBool(const base::DictionaryValue* dictionary, - const std::string& key, - bool expected_value, - bool omit_if_false) { - if (omit_if_false && !expected_value) { - EXPECT_FALSE(dictionary->HasKey(key)) << - "Did not expect to find value for " << key; - } else { - bool actual_value; - EXPECT_TRUE(dictionary->GetBoolean(key, &actual_value)) << - "No value found for " << key; - EXPECT_EQ(expected_value, actual_value) << - "Mismatch found for " << key; - } -} - -void CheckBool(const base::DictionaryValue* dictionary, - const std::string& key, - bool expected_value) { - return CheckBool(dictionary, key, expected_value, false); +// |expected_value|. This will fail if the key isn't present, even if +// |expected_value| is false. +void ExpectHasBoolKey(const base::DictionaryValue* dictionary, + const std::string& key, + bool expected_value) { + absl::optional<bool> actual_value = dictionary->FindBoolKey(key); + // The comparison with |expected_valued| could be done in a single + // expectation, but the semantics would be confusing since the values are + // booleans. + ASSERT_TRUE(actual_value.has_value()) << "No value found for " << key; + EXPECT_EQ(expected_value, *actual_value) << "Mismatch found for " << key; } // Checks to make sure that the values stored in |dictionary| match the values @@ -148,29 +138,29 @@ void CheckBool(const base::DictionaryValue* dictionary, void CheckConfigDataTypeArguments(const base::DictionaryValue* dictionary, SyncAllDataConfig config, syncer::UserSelectableTypeSet types) { - CheckBool(dictionary, "syncAllDataTypes", config == SYNC_ALL_DATA); - CheckBool(dictionary, "appsSynced", - types.Has(syncer::UserSelectableType::kApps)); - CheckBool(dictionary, "autofillSynced", - types.Has(syncer::UserSelectableType::kAutofill)); - CheckBool(dictionary, "bookmarksSynced", - types.Has(syncer::UserSelectableType::kBookmarks)); - CheckBool(dictionary, "extensionsSynced", - types.Has(syncer::UserSelectableType::kExtensions)); - CheckBool(dictionary, "passwordsSynced", - types.Has(syncer::UserSelectableType::kPasswords)); - CheckBool(dictionary, "preferencesSynced", - types.Has(syncer::UserSelectableType::kPreferences)); - CheckBool(dictionary, "readingListSynced", - types.Has(syncer::UserSelectableType::kReadingList)); - CheckBool(dictionary, "tabsSynced", - types.Has(syncer::UserSelectableType::kTabs)); - CheckBool(dictionary, "themesSynced", - types.Has(syncer::UserSelectableType::kThemes)); - CheckBool(dictionary, "typedUrlsSynced", - types.Has(syncer::UserSelectableType::kHistory)); - CheckBool(dictionary, "wifiConfigurationsSynced", - types.Has(syncer::UserSelectableType::kWifiConfigurations)); + ExpectHasBoolKey(dictionary, "syncAllDataTypes", config == SYNC_ALL_DATA); + ExpectHasBoolKey(dictionary, "appsSynced", + types.Has(syncer::UserSelectableType::kApps)); + ExpectHasBoolKey(dictionary, "autofillSynced", + types.Has(syncer::UserSelectableType::kAutofill)); + ExpectHasBoolKey(dictionary, "bookmarksSynced", + types.Has(syncer::UserSelectableType::kBookmarks)); + ExpectHasBoolKey(dictionary, "extensionsSynced", + types.Has(syncer::UserSelectableType::kExtensions)); + ExpectHasBoolKey(dictionary, "passwordsSynced", + types.Has(syncer::UserSelectableType::kPasswords)); + ExpectHasBoolKey(dictionary, "preferencesSynced", + types.Has(syncer::UserSelectableType::kPreferences)); + ExpectHasBoolKey(dictionary, "readingListSynced", + types.Has(syncer::UserSelectableType::kReadingList)); + ExpectHasBoolKey(dictionary, "tabsSynced", + types.Has(syncer::UserSelectableType::kTabs)); + ExpectHasBoolKey(dictionary, "themesSynced", + types.Has(syncer::UserSelectableType::kThemes)); + ExpectHasBoolKey(dictionary, "typedUrlsSynced", + types.Has(syncer::UserSelectableType::kHistory)); + ExpectHasBoolKey(dictionary, "wifiConfigurationsSynced", + types.Has(syncer::UserSelectableType::kWifiConfigurations)); } std::unique_ptr<KeyedService> BuildMockSyncService( @@ -221,7 +211,7 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness { std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile()); mock_sync_service_ = static_cast<syncer::MockSyncService*>( - ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( + SyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( profile(), base::BindRepeating(&BuildMockSyncService))); ON_CALL(*mock_sync_service_, IsAuthenticatedAccountPrimary()) @@ -250,7 +240,10 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness { GetIdentityTestEnvironmentFactories(); } - void SigninUser() { identity_test_env()->SetPrimaryAccount(kTestUser); } + void SigninUser() { + identity_test_env()->SetPrimaryAccount(kTestUser, + signin::ConsentLevel::kSync); + } void CreatePeopleHandler() { handler_ = std::make_unique<TestingPeopleHandler>(&web_ui_, profile()); @@ -290,14 +283,13 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness { void ExpectPageStatusResponse(const std::string& expected_status) { auto& data = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kTestCallbackId, callback_id); + + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kTestCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); EXPECT_TRUE(data.arg2()->GetBool()); - std::string status; - ASSERT_TRUE(data.arg3()->GetAsString(&status)); - EXPECT_EQ(expected_status, status); + ASSERT_TRUE(data.arg3()->is_string()); + EXPECT_EQ(expected_status, data.arg3()->GetString()); } // Expects a call to ResolveJavascriptCallback() with |should_succeed| as its @@ -394,8 +386,8 @@ TEST_F(PeopleHandlerTest, DisplayBasicLogin) { .WillByDefault(Return(false)); // Ensure that the user is not signed in before calling |HandleStartSignin()|. identity_test_env()->ClearPrimaryAccount(); - base::ListValue list_args; - handler_->HandleStartSignin(&list_args); + base::Value list_args(base::Value::Type::LIST); + handler_->HandleStartSignin(&base::Value::AsListValue(list_args)); // Sync setup hands off control to the gaia login tab. EXPECT_EQ( @@ -481,11 +473,11 @@ TEST_F(PeopleHandlerTest, EXPECT_EQ(3U, web_ui_.call_data().size()); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "syncAllDataTypes", true); - CheckBool(dictionary, "customPassphraseAllowed", true); - CheckBool(dictionary, "encryptAllData", false); - CheckBool(dictionary, "passphraseRequired", false); - CheckBool(dictionary, "trustedVaultKeysRequired", false); + ExpectHasBoolKey(dictionary, "syncAllDataTypes", true); + ExpectHasBoolKey(dictionary, "customPassphraseAllowed", true); + ExpectHasBoolKey(dictionary, "encryptAllData", false); + ExpectHasBoolKey(dictionary, "passphraseRequired", false); + ExpectHasBoolKey(dictionary, "trustedVaultKeysRequired", false); } // Verifies the case where the user cancels after the sync engine has @@ -653,9 +645,9 @@ TEST_F(PeopleHandlerTest, TestSyncEverything) { SigninUser(); CreatePeopleHandler(); std::string args = GetConfiguration(SYNC_ALL_DATA, GetAllTypes()); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append(args); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequiredForPreferredDataTypes()) .WillByDefault(Return(false)); @@ -664,7 +656,7 @@ TEST_F(PeopleHandlerTest, TestSyncEverything) { SetupInitializedSyncService(); EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetSelectedTypes(true, _)); - handler_->HandleSetDatatypes(&list_args); + handler_->HandleSetDatatypes(&base::Value::AsListValue(list_args)); ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); } @@ -690,10 +682,10 @@ TEST_F(PeopleHandlerTest, EnterCorrectExistingPassphrase) { SetDecryptionPassphrase("correct_passphrase")) .WillOnce(Return(true)); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString("correct_passphrase"); - handler_->HandleSetDecryptionPassphrase(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append("correct_passphrase"); + handler_->HandleSetDecryptionPassphrase(&base::Value::AsListValue(list_args)); ExpectSetPassphraseSuccess(true); } @@ -718,10 +710,10 @@ TEST_F(PeopleHandlerTest, SuccessfullyCreateCustomPassphrase) { EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetEncryptionPassphrase("custom_passphrase")); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString("custom_passphrase"); - handler_->HandleSetEncryptionPassphrase(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append("custom_passphrase"); + handler_->HandleSetEncryptionPassphrase(&base::Value::AsListValue(list_args)); ExpectSetPassphraseSuccess(true); } @@ -747,10 +739,10 @@ TEST_F(PeopleHandlerTest, EnterWrongExistingPassphrase) { SetDecryptionPassphrase("invalid_passphrase")) .WillOnce(Return(false)); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString("invalid_passphrase"); - handler_->HandleSetDecryptionPassphrase(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append("invalid_passphrase"); + handler_->HandleSetDecryptionPassphrase(&base::Value::AsListValue(list_args)); ExpectSetPassphraseSuccess(false); } @@ -776,10 +768,10 @@ TEST_F(PeopleHandlerTest, CannotCreateBlankPassphrase) { SetEncryptionPassphrase) .Times(0); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(""); - handler_->HandleSetEncryptionPassphrase(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append(""); + handler_->HandleSetEncryptionPassphrase(&base::Value::AsListValue(list_args)); ExpectSetPassphraseSuccess(false); } @@ -794,9 +786,9 @@ TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) { syncer::UserSelectableTypeSet type_to_set; type_to_set.Put(type); std::string args = GetConfiguration(CHOOSE_WHAT_TO_SYNC, type_to_set); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append(args); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequiredForPreferredDataTypes()) .WillByDefault(Return(false)); @@ -806,7 +798,7 @@ TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) { EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetSelectedTypes(false, type_to_set)); - handler_->HandleSetDatatypes(&list_args); + handler_->HandleSetDatatypes(&base::Value::AsListValue(list_args)); ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); Mock::VerifyAndClearExpectations(mock_sync_service_); } @@ -817,9 +809,9 @@ TEST_F(PeopleHandlerTest, TestSyncAllManually) { CreatePeopleHandler(); SetDefaultExpectationsForConfigPage(); std::string args = GetConfiguration(CHOOSE_WHAT_TO_SYNC, GetAllTypes()); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append(args); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequiredForPreferredDataTypes()) .WillByDefault(Return(false)); @@ -828,7 +820,7 @@ TEST_F(PeopleHandlerTest, TestSyncAllManually) { SetupInitializedSyncService(); EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetSelectedTypes(false, GetAllTypes())); - handler_->HandleSetDatatypes(&list_args); + handler_->HandleSetDatatypes(&base::Value::AsListValue(list_args)); ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); } @@ -849,14 +841,14 @@ TEST_F(PeopleHandlerTest, NonRegisteredType) { // Simulate "Sync everything" being turned off, but all individual // toggles left on. std::string config = GetConfiguration(CHOOSE_WHAT_TO_SYNC, GetAllTypes()); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString(config); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append(config); // Only the registered types are selected. EXPECT_CALL(*mock_sync_service_->GetMockUserSettings(), SetSelectedTypes(/*sync_everything=*/false, registered_types)); - handler_->HandleSetDatatypes(&list_args); + handler_->HandleSetDatatypes(&base::Value::AsListValue(list_args)); } TEST_F(PeopleHandlerTest, ShowSyncSetup) { @@ -889,20 +881,20 @@ TEST_F(PeopleHandlerTest, ShowSetupSyncEverything) { handler_->HandleShowSyncSetupUI(nullptr); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "syncAllDataTypes", true); - CheckBool(dictionary, "appsRegistered", true); - CheckBool(dictionary, "autofillRegistered", true); - CheckBool(dictionary, "bookmarksRegistered", true); - CheckBool(dictionary, "extensionsRegistered", true); - CheckBool(dictionary, "passwordsRegistered", true); - CheckBool(dictionary, "preferencesRegistered", true); - CheckBool(dictionary, "readingListRegistered", true); - CheckBool(dictionary, "tabsRegistered", true); - CheckBool(dictionary, "themesRegistered", true); - CheckBool(dictionary, "typedUrlsRegistered", true); - CheckBool(dictionary, "paymentsIntegrationEnabled", true); - CheckBool(dictionary, "passphraseRequired", false); - CheckBool(dictionary, "encryptAllData", false); + ExpectHasBoolKey(dictionary, "syncAllDataTypes", true); + ExpectHasBoolKey(dictionary, "appsRegistered", true); + ExpectHasBoolKey(dictionary, "autofillRegistered", true); + ExpectHasBoolKey(dictionary, "bookmarksRegistered", true); + ExpectHasBoolKey(dictionary, "extensionsRegistered", true); + ExpectHasBoolKey(dictionary, "passwordsRegistered", true); + ExpectHasBoolKey(dictionary, "preferencesRegistered", true); + ExpectHasBoolKey(dictionary, "readingListRegistered", true); + ExpectHasBoolKey(dictionary, "tabsRegistered", true); + ExpectHasBoolKey(dictionary, "themesRegistered", true); + ExpectHasBoolKey(dictionary, "typedUrlsRegistered", true); + ExpectHasBoolKey(dictionary, "paymentsIntegrationEnabled", true); + ExpectHasBoolKey(dictionary, "passphraseRequired", false); + ExpectHasBoolKey(dictionary, "encryptAllData", false); CheckConfigDataTypeArguments(dictionary, SYNC_ALL_DATA, GetAllTypes()); } @@ -961,37 +953,49 @@ TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) { TEST_F(PeopleHandlerTest, ShowSetupOldGaiaPassphraseRequired) { SigninUser(); CreatePeopleHandler(); + SetupInitializedSyncService(); + SetDefaultExpectationsForConfigPage(); + + const auto passphrase_time = base::Time::Now(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + GetExplicitPassphraseTime()) + .WillByDefault(Return(passphrase_time)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) .WillByDefault(Return(true)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetPassphraseType()) .WillByDefault(Return(syncer::PassphraseType::kFrozenImplicitPassphrase)); - SetupInitializedSyncService(); - SetDefaultExpectationsForConfigPage(); - // This should display the sync setup dialog (not login). handler_->HandleShowSyncSetupUI(nullptr); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "passphraseRequired", true); - EXPECT_TRUE(dictionary->FindKey("enterPassphraseBody")); + ExpectHasBoolKey(dictionary, "passphraseRequired", true); + ASSERT_TRUE(dictionary->FindStringKey("explicitPassphraseTime")); + EXPECT_EQ(base::UTF16ToUTF8(base::TimeFormatShortDate(passphrase_time)), + *dictionary->FindStringKey("explicitPassphraseTime")); } TEST_F(PeopleHandlerTest, ShowSetupCustomPassphraseRequired) { SigninUser(); CreatePeopleHandler(); + SetupInitializedSyncService(); + SetDefaultExpectationsForConfigPage(); + + const auto passphrase_time = base::Time::Now(); + ON_CALL(*mock_sync_service_->GetMockUserSettings(), + GetExplicitPassphraseTime()) + .WillByDefault(Return(passphrase_time)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), IsPassphraseRequired()) .WillByDefault(Return(true)); ON_CALL(*mock_sync_service_->GetMockUserSettings(), GetPassphraseType()) .WillByDefault(Return(syncer::PassphraseType::kCustomPassphrase)); - SetupInitializedSyncService(); - SetDefaultExpectationsForConfigPage(); - // This should display the sync setup dialog (not login). handler_->HandleShowSyncSetupUI(nullptr); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "passphraseRequired", true); - EXPECT_TRUE(dictionary->FindKey("enterPassphraseBody")); + ExpectHasBoolKey(dictionary, "passphraseRequired", true); + ASSERT_TRUE(dictionary->FindStringKey("explicitPassphraseTime")); + EXPECT_EQ(base::UTF16ToUTF8(base::TimeFormatShortDate(passphrase_time)), + *dictionary->FindStringKey("explicitPassphraseTime")); } TEST_F(PeopleHandlerTest, ShowSetupTrustedVaultKeysRequired) { @@ -1009,9 +1013,9 @@ TEST_F(PeopleHandlerTest, ShowSetupTrustedVaultKeysRequired) { handler_->HandleShowSyncSetupUI(nullptr); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "passphraseRequired", false); - CheckBool(dictionary, "trustedVaultKeysRequired", true); - EXPECT_FALSE(dictionary->FindKey("enterPassphraseBody")); + ExpectHasBoolKey(dictionary, "passphraseRequired", false); + ExpectHasBoolKey(dictionary, "trustedVaultKeysRequired", true); + EXPECT_FALSE(dictionary->FindStringKey("explicitPassphraseTime")); } TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) { @@ -1032,7 +1036,7 @@ TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) { handler_->HandleShowSyncSetupUI(nullptr); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "encryptAllData", true); + ExpectHasBoolKey(dictionary, "encryptAllData", true); } TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) { @@ -1053,8 +1057,8 @@ TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) { handler_->HandleShowSyncSetupUI(nullptr); const base::DictionaryValue* dictionary = ExpectSyncPrefsChanged(); - CheckBool(dictionary, "encryptAllData", false); - CheckBool(dictionary, "customPassphraseAllowed", false); + ExpectHasBoolKey(dictionary, "encryptAllData", false); + ExpectHasBoolKey(dictionary, "customPassphraseAllowed", false); } TEST_F(PeopleHandlerTest, CannotCreatePassphraseIfCustomPassphraseDisallowed) { @@ -1078,10 +1082,10 @@ TEST_F(PeopleHandlerTest, CannotCreatePassphraseIfCustomPassphraseDisallowed) { SetEncryptionPassphrase) .Times(0); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString("passphrase123"); - handler_->HandleSetEncryptionPassphrase(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append("passphrase123"); + handler_->HandleSetEncryptionPassphrase(&base::Value::AsListValue(list_args)); ExpectSetPassphraseSuccess(false); } @@ -1107,10 +1111,10 @@ TEST_F(PeopleHandlerTest, CannotOverwritePassphraseWithNewOne) { SetEncryptionPassphrase) .Times(0); - base::ListValue list_args; - list_args.AppendString(kTestCallbackId); - list_args.AppendString("passphrase123"); - handler_->HandleSetEncryptionPassphrase(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(kTestCallbackId); + list_args.Append("passphrase123"); + handler_->HandleSetEncryptionPassphrase(&base::Value::AsListValue(list_args)); ExpectSetPassphraseSuccess(false); } @@ -1268,7 +1272,8 @@ TEST(PeopleHandlerDiceUnifiedConsentTest, StoredAccountsList) { auto account_1 = identity_test_env->MakeAccountAvailable("a@gmail.com"); auto account_2 = identity_test_env->MakeAccountAvailable("b@gmail.com"); - identity_test_env->SetPrimaryAccount(account_1.email); + identity_test_env->SetPrimaryAccount(account_1.email, + signin::ConsentLevel::kSync); PeopleHandler handler(profile.get()); base::Value accounts = handler.GetStoredAccountsList(); @@ -1299,19 +1304,21 @@ TEST(PeopleHandlerGuestModeTest, GetStoredAccountsList) { TEST_F(PeopleHandlerTest, TurnOffSync) { // Simulate a user who previously turned on sync. - identity_test_env()->MakePrimaryAccountAvailable("user@gmail.com"); + identity_test_env()->MakePrimaryAccountAvailable("user@gmail.com", + ConsentLevel::kSync); ASSERT_TRUE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync)); CreatePeopleHandler(); handler_->HandleTurnOffSync(nullptr); EXPECT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync)); const base::DictionaryValue* status = ExpectSyncStatusChanged(); - CheckBool(status, "signedIn", false); + ExpectHasBoolKey(status, "signedIn", false); } TEST_F(PeopleHandlerTest, GetStoredAccountsList) { // Chrome OS sets an unconsented primary account on login. - identity_test_env()->MakeUnconsentedPrimaryAccountAvailable("user@gmail.com"); + identity_test_env()->MakePrimaryAccountAvailable("user@gmail.com", + ConsentLevel::kSignin); ASSERT_FALSE(identity_manager()->HasPrimaryAccount(ConsentLevel::kSync)); CreatePeopleHandler(); diff --git a/chromium/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc index 844cff90a0b..15a61406cee 100644 --- a/chromium/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/privacy_sandbox_handler_unittest.cc @@ -89,13 +89,14 @@ class PrivacySandboxHandlerTest : public testing::Test { }; TEST_F(PrivacySandboxHandlerTest, GetFlocId) { - federated_learning::FlocId floc_id(123456, base::Time(), base::Time::Now(), - /*sorting_lsh_version=*/0); + federated_learning::FlocId floc_id = federated_learning::FlocId::CreateValid( + 123456, base::Time(), base::Time::Now(), + /*sorting_lsh_version=*/0); floc_id.SaveToPrefs(profile()->GetTestingPrefService()); - base::ListValue args; - args.AppendString(kCallbackId); - handler()->HandleGetFlocId(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + handler()->HandleGetFlocId(&base::Value::AsListValue(args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ(kCallbackId, data.arg1()->GetString()); @@ -105,8 +106,9 @@ TEST_F(PrivacySandboxHandlerTest, GetFlocId) { } TEST_F(PrivacySandboxHandlerTest, ResetFlocId) { - federated_learning::FlocId floc_id(123456, base::Time(), base::Time::Now(), - /*sorting_lsh_version=*/0); + federated_learning::FlocId floc_id = federated_learning::FlocId::CreateValid( + 123456, base::Time(), base::Time::Now(), + /*sorting_lsh_version=*/0); floc_id.SaveToPrefs(profile()->GetTestingPrefService()); // Observers of the PrivacySandboxSettings service should be informed that @@ -115,8 +117,8 @@ TEST_F(PrivacySandboxHandlerTest, ResetFlocId) { privacy_sandbox_settings()->AddObserver(&observer); EXPECT_CALL(observer, OnFlocDataAccessibleSinceUpdated(true)); - base::ListValue args; - handler()->HandleResetFlocId(&args); + base::Value args(base::Value::Type::LIST); + handler()->HandleResetFlocId(&base::Value::AsListValue(args)); // Resetting the FLoC ID should also fire the appropriate WebUI listener. const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); diff --git a/chromium/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc index e7ff776badb..02c6a3ef317 100644 --- a/chromium/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/profile_info_handler_unittest.cc @@ -114,18 +114,17 @@ class ProfileInfoHandlerTest : public testing::Test { }; TEST_F(ProfileInfoHandlerTest, GetProfileInfo) { - base::ListValue list_args; - list_args.AppendString("get-profile-info-callback-id"); - handler()->HandleGetProfileInfo(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append("get-profile-info-callback-id"); + handler()->HandleGetProfileInfo(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ("get-profile-info-callback-id", callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ("get-profile-info-callback-id", data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); EXPECT_TRUE(data.arg2()->GetBool()); @@ -143,9 +142,9 @@ TEST_F(ProfileInfoHandlerTest, PushProfileInfo) { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); - std::string event_id; - ASSERT_TRUE(data.arg1()->GetAsString(&event_id)); - EXPECT_EQ(ProfileInfoHandler::kProfileInfoChangedEventName, event_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(ProfileInfoHandler::kProfileInfoChangedEventName, + data.arg1()->GetString()); VerifyProfileInfo(data.arg2()); } diff --git a/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc b/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc index 8c0eea5add4..f528080e180 100644 --- a/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc @@ -93,10 +93,10 @@ void ProtocolHandlersHandler::GetHandlersForProtocol( ProtocolHandler::GetProtocolDisplayName(protocol)); handlers_value->SetString("protocol", protocol); - auto handlers_list = std::make_unique<base::ListValue>(); + base::ListValue handlers_list; GetHandlersAsListValue(*registry, registry->GetHandlersFor(protocol), - handlers_list.get()); - handlers_value->Set("handlers", std::move(handlers_list)); + &handlers_list); + handlers_value->SetKey("handlers", std::move(handlers_list)); } void ProtocolHandlersHandler::GetIgnoredHandlers(base::ListValue* handlers) { diff --git a/chromium/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc index 4800e171f3d..1a424508126 100644 --- a/chromium/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/reset_settings_handler_unittest.cc @@ -89,20 +89,21 @@ class ResetSettingsHandlerTest : public testing::Test { }; TEST_F(ResetSettingsHandlerTest, HandleResetProfileSettings) { - base::ListValue list; + base::Value list(base::Value::Type::LIST); std::string expected_callback_id("dummyCallbackId"); - list.AppendString(expected_callback_id); - list.AppendBoolean(false); - list.AppendString(""); - handler()->HandleResetProfileSettings(&list); + list.Append(expected_callback_id); + list.Append(false); + list.Append(""); + handler()->HandleResetProfileSettings(&base::Value::AsListValue(list)); // Check that the delegate ProfileResetter was called. EXPECT_EQ(1u, handler()->resets()); // Check that Javascript side is notified after resetting is done. EXPECT_EQ("cr.webUIResponse", web_ui()->call_data()[0]->function_name()); - std::string callback_id; - EXPECT_TRUE(web_ui()->call_data()[0]->arg1()->GetAsString(&callback_id)); - EXPECT_EQ(expected_callback_id, callback_id); + const std::string* callback_id = + web_ui()->call_data()[0]->arg1()->GetIfString(); + EXPECT_NE(nullptr, callback_id); + EXPECT_EQ(expected_callback_id, *callback_id); } } // namespace diff --git a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc index acc87b378e9..73bf7307f7d 100644 --- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc @@ -18,7 +18,6 @@ #include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/api/passwords_private/passwords_private_delegate_factory.h" -#include "chrome/browser/extensions/blocklist_extension_prefs.h" #include "chrome/browser/password_manager/bulk_leak_check_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/version/version_ui.h" @@ -34,6 +33,7 @@ #include "components/version_info/version_info.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/storage_partition.h" +#include "extensions/browser/blocklist_extension_prefs.h" #include "extensions/browser/extension_prefs_factory.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension_id.h" diff --git a/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc index c8694f5f3da..2f1d49618e0 100644 --- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler_unittest.cc @@ -38,6 +38,8 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" +#include "extensions/browser/blocklist_extension_prefs.h" +#include "extensions/browser/blocklist_state.h" #include "extensions/browser/extension_prefs.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" @@ -172,13 +174,17 @@ class TestPasswordsDelegate : public extensions::TestPasswordsPrivateDelegate { "test" + base::NumberToString(test_credential_counter_++)); form.password_value = u"password"; form.username_element = u"username_element"; + // TODO(crbug.com/1223022): Once all places that operate changes on forms + // via UpdateLogin properly set |password_issues|, setting them to an empty + // map should be part of the default constructor. + form.password_issues = + base::flat_map<password_manager::InsecureType, + password_manager::InsecurityMetadata>(); store_->AddLogin(form); - base::RunLoop().RunUntilIdle(); - - store_->AddInsecureCredential(password_manager::InsecureCredential( - form.signon_realm, form.username_value, base::Time(), - password_manager::InsecureType::kLeaked, - password_manager::IsMuted(false))); + form.password_issues = { + {password_manager::InsecureType::kLeaked, + password_manager::InsecurityMetadata( + base::Time(), password_manager::IsMuted(false))}}; base::RunLoop().RunUntilIdle(); } @@ -372,11 +378,9 @@ SafetyCheckHandlerTest::GetSafetyCheckStatusChangedWithDataIfExists( if (data.function_name() != "cr.webUIListenerCallback") { continue; } - std::string event; - if ((!data.arg1()->GetAsString(&event)) || - event != "safety-check-" + component + "-status-changed") { + const std::string* event = data.arg1()->GetIfString(); + if (!event || *event != "safety-check-" + component + "-status-changed") continue; - } const base::DictionaryValue* dictionary = nullptr; if (!data.arg2()->GetAsDictionary(&dictionary)) { continue; @@ -1253,8 +1257,9 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_NoneBlocklisted) { test_extension_prefs_->OnExtensionInstalled( extension.get(), extensions::Extension::State::ENABLED, syncer::StringOrdinal(), ""); - test_extension_prefs_->SetExtensionBlocklistState( - extension_id, extensions::NOT_BLOCKLISTED); + extensions::blocklist_prefs::SetSafeBrowsingExtensionBlocklistState( + extension_id, extensions::BitMapBlocklistState::NOT_BLOCKLISTED, + test_extension_prefs_); safety_check_->PerformSafetyCheck(); const base::DictionaryValue* event = GetSafetyCheckStatusChangedWithDataIfExists( @@ -1276,8 +1281,9 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedAllDisabled) { test_extension_prefs_->OnExtensionInstalled( extension.get(), extensions::Extension::State::DISABLED, syncer::StringOrdinal(), ""); - test_extension_prefs_->SetExtensionBlocklistState( - extension_id, extensions::BLOCKLISTED_MALWARE); + extensions::blocklist_prefs::SetSafeBrowsingExtensionBlocklistState( + extension_id, extensions::BitMapBlocklistState::BLOCKLISTED_MALWARE, + test_extension_prefs_); test_extension_service_.AddExtensionState(extension_id, Enabled(false), UserCanDisable(false)); safety_check_->PerformSafetyCheck(); @@ -1301,8 +1307,10 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledAllByUser) { test_extension_prefs_->OnExtensionInstalled( extension.get(), extensions::Extension::State::ENABLED, syncer::StringOrdinal(), ""); - test_extension_prefs_->SetExtensionBlocklistState( - extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED); + extensions::blocklist_prefs::SetSafeBrowsingExtensionBlocklistState( + extension_id, + extensions::BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED, + test_extension_prefs_); test_extension_service_.AddExtensionState(extension_id, Enabled(true), UserCanDisable(true)); safety_check_->PerformSafetyCheck(); @@ -1325,8 +1333,10 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledAllByAdmin) { test_extension_prefs_->OnExtensionInstalled( extension.get(), extensions::Extension::State::ENABLED, syncer::StringOrdinal(), ""); - test_extension_prefs_->SetExtensionBlocklistState( - extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED); + extensions::blocklist_prefs::SetSafeBrowsingExtensionBlocklistState( + extension_id, + extensions::BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED, + test_extension_prefs_); test_extension_service_.AddExtensionState(extension_id, Enabled(true), UserCanDisable(false)); safety_check_->PerformSafetyCheck(); @@ -1349,8 +1359,10 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) { test_extension_prefs_->OnExtensionInstalled( extension.get(), extensions::Extension::State::ENABLED, syncer::StringOrdinal(), ""); - test_extension_prefs_->SetExtensionBlocklistState( - extension_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED); + extensions::blocklist_prefs::SetSafeBrowsingExtensionBlocklistState( + extension_id, + extensions::BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED, + test_extension_prefs_); test_extension_service_.AddExtensionState(extension_id, Enabled(true), UserCanDisable(true)); @@ -1360,8 +1372,10 @@ TEST_F(SafetyCheckHandlerTest, CheckExtensions_BlocklistedReenabledSomeByUser) { test_extension_prefs_->OnExtensionInstalled( extension2.get(), extensions::Extension::State::ENABLED, syncer::StringOrdinal(), ""); - test_extension_prefs_->SetExtensionBlocklistState( - extension2_id, extensions::BLOCKLISTED_POTENTIALLY_UNWANTED); + extensions::blocklist_prefs::SetSafeBrowsingExtensionBlocklistState( + extension2_id, + extensions::BitMapBlocklistState::BLOCKLISTED_POTENTIALLY_UNWANTED, + test_extension_prefs_); test_extension_service_.AddExtensionState(extension2_id, Enabled(true), UserCanDisable(false)); diff --git a/chromium/chrome/browser/ui/webui/settings/search_engines_handler.cc b/chromium/chrome/browser/ui/webui/settings/search_engines_handler.cc index fcc19c65815..8554df8b803 100644 --- a/chromium/chrome/browser/ui/webui/settings/search_engines_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/search_engines_handler.cc @@ -108,7 +108,7 @@ SearchEnginesHandler::GetSearchEnginesList() { list_controller_.table_model()->IndexOfTemplateURL(default_engine); // Build the first list (default search engines). - auto defaults = std::make_unique<base::ListValue>(); + base::ListValue defaults; int last_default_engine_index = list_controller_.table_model()->last_search_engine_index(); @@ -117,37 +117,51 @@ SearchEnginesHandler::GetSearchEnginesList() { for (int i = 0; i < last_default_engine_index; ++i) { // Third argument is false, as the engine is not from an extension. - defaults->Append(CreateDictionaryForEngine(i, i == default_index)); + defaults.Append(CreateDictionaryForEngine(i, i == default_index)); + } + + // Build the second list (active search engines). This will not have any + // entries if the new Search Engines page is not enabled. + base::ListValue actives; + int last_active_engine_index = + list_controller_.table_model()->last_active_engine_index(); + + CHECK_LE(last_default_engine_index, last_active_engine_index); + for (int i = std::max(last_default_engine_index, 0); + i < last_active_engine_index; ++i) { + // Third argument is false, as the engine is not from an extension. + actives.Append(CreateDictionaryForEngine(i, i == default_index)); } // Build the second list (other search engines). - auto others = std::make_unique<base::ListValue>(); + base::ListValue others; int last_other_engine_index = list_controller_.table_model()->last_other_engine_index(); // Sanity check for https://crbug.com/781703. - CHECK_LE(last_default_engine_index, last_other_engine_index); + CHECK_LE(last_active_engine_index, last_other_engine_index); - for (int i = std::max(last_default_engine_index, 0); + for (int i = std::max(last_active_engine_index, 0); i < last_other_engine_index; ++i) { - others->Append(CreateDictionaryForEngine(i, i == default_index)); + others.Append(CreateDictionaryForEngine(i, i == default_index)); } // Build the third list (omnibox extensions). - auto extensions = std::make_unique<base::ListValue>(); + base::ListValue extensions; int engine_count = list_controller_.table_model()->RowCount(); // Sanity check for https://crbug.com/781703. CHECK_LE(last_other_engine_index, engine_count); for (int i = std::max(last_other_engine_index, 0); i < engine_count; ++i) { - extensions->Append(CreateDictionaryForEngine(i, i == default_index)); + extensions.Append(CreateDictionaryForEngine(i, i == default_index)); } auto search_engines_info = std::make_unique<base::DictionaryValue>(); - search_engines_info->Set("defaults", std::move(defaults)); - search_engines_info->Set("others", std::move(others)); - search_engines_info->Set("extensions", std::move(extensions)); + search_engines_info->SetKey("defaults", std::move(defaults)); + search_engines_info->SetKey("actives", std::move(actives)); + search_engines_info->SetKey("others", std::move(others)); + search_engines_info->SetKey("extensions", std::move(extensions)); return search_engines_info; } diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc index 9f2b1a9aea7..179ad851bb1 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.cc @@ -8,10 +8,10 @@ #include <vector> #include "base/bind.h" +#include "base/cxx17_backports.h" #include "base/feature_list.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" -#include "base/stl_util.h" #include "base/values.h" #include "chrome/browser/browsing_data/browsing_data_important_sites_util.h" #include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h" @@ -19,23 +19,31 @@ #include "chrome/browser/browsing_data/counters/browsing_data_counter_utils.h" #include "chrome/browser/engagement/important_sites_util.h" #include "chrome/browser/history/web_history_service_factory.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/signin/account_reconcilor_factory.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/common/channel_info.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" +#include "chrome/common/url_constants.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" #include "components/browsing_data/content/browsing_data_helper.h" #include "components/browsing_data/core/browsing_data_utils.h" #include "components/browsing_data/core/history_notice_utils.h" #include "components/browsing_data/core/pref_names.h" #include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" +#include "components/search_engines/search_engine_type.h" +#include "components/search_engines/template_url_service.h" #include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/browsing_data_filter_builder.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" using BrowsingDataType = browsing_data::BrowsingDataType; @@ -76,7 +84,7 @@ namespace settings { ClearBrowsingDataHandler::ClearBrowsingDataHandler(content::WebUI* webui, Profile* profile) : profile_(profile), - sync_service_(ProfileSyncServiceFactory::GetForProfile(profile_)), + sync_service_(SyncServiceFactory::GetForProfile(profile_)), show_history_deletion_dialog_(false) {} ClearBrowsingDataHandler::~ClearBrowsingDataHandler() { @@ -103,6 +111,8 @@ void ClearBrowsingDataHandler::OnJavascriptAllowed() { if (sync_service_) sync_service_observation_.Observe(sync_service_); + dse_service_observation_.Observe( + TemplateURLServiceFactory::GetForProfile(profile_)); DCHECK(counters_.empty()); for (const std::string& pref : kCounterPrefsBasic) { AddCounter(BrowsingDataCounterFactory::GetForProfileAndPref(profile_, pref), @@ -126,6 +136,7 @@ void ClearBrowsingDataHandler::OnJavascriptAllowed() { } void ClearBrowsingDataHandler::OnJavascriptDisallowed() { + dse_service_observation_.Reset(); sync_service_observation_.Reset(); weak_ptr_factory_.InvalidateWeakPtrs(); counters_.clear(); @@ -139,29 +150,26 @@ void ClearBrowsingDataHandler::HandleClearBrowsingDataForTest() { // types that the user cleared from the clear browsing data UI and time period // of the data to be cleared. - std::unique_ptr<base::ListValue> data_types = - std::make_unique<base::ListValue>(); - data_types->AppendString("browser.clear_data.browsing_history"); + base::Value data_types(base::Value::Type::LIST); + data_types.Append("browser.clear_data.browsing_history"); - std::unique_ptr<base::ListValue> installed_apps = - std::make_unique<base::ListValue>(); + base::Value installed_apps(base::Value::Type::LIST); - base::ListValue list_args; - list_args.AppendString("webui_callback_id"); + base::Value list_args(base::Value::Type::LIST); + list_args.Append("webui_callback_id"); list_args.Append(std::move(data_types)); - list_args.AppendInteger(1u); + list_args.Append(1); list_args.Append(std::move(installed_apps)); - HandleClearBrowsingData(&list_args); + HandleClearBrowsingData(&base::Value::AsListValue(list_args)); } void ClearBrowsingDataHandler::GetRecentlyLaunchedInstalledApps( const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); - std::string webui_callback_id; - int period_selected; - CHECK(args->GetString(0, &webui_callback_id)); + const auto& list = args->GetList(); + CHECK_EQ(2U, list.size()); + std::string webui_callback_id = list[0].GetString(); + int period_selected = list[1].GetInt(); - CHECK(args->GetInteger(1, &period_selected)); browsing_data::TimePeriod time_period = static_cast<browsing_data::TimePeriod>(period_selected); @@ -198,12 +206,12 @@ void ClearBrowsingDataHandler::OnGotInstalledApps( std::unique_ptr<content::BrowsingDataFilterBuilder> ClearBrowsingDataHandler::ProcessInstalledApps( - const base::ListValue* installed_apps) { + base::Value::ConstListView installed_apps) { std::vector<std::string> excluded_domains; std::vector<int32_t> excluded_domain_reasons; std::vector<std::string> ignored_domains; std::vector<int32_t> ignored_domain_reasons; - for (const auto& item : installed_apps->GetList()) { + for (const auto& item : installed_apps) { const base::DictionaryValue* site = nullptr; CHECK(item.GetAsDictionary(&site)); bool is_checked = false; @@ -236,9 +244,9 @@ ClearBrowsingDataHandler::ProcessInstalledApps( void ClearBrowsingDataHandler::HandleClearBrowsingData( const base::ListValue* args) { - CHECK_EQ(4U, args->GetSize()); - std::string webui_callback_id; - CHECK(args->GetString(0, &webui_callback_id)); + base::Value::ConstListView args_list = args->GetList(); + CHECK_EQ(4U, args_list.size()); + std::string webui_callback_id = args_list[0].GetString(); PrefService* prefs = profile_->GetPrefs(); @@ -250,11 +258,11 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData( uint64_t remove_mask = 0; uint64_t origin_mask = 0; std::vector<BrowsingDataType> data_type_vector; - const base::ListValue* data_type_list = nullptr; - CHECK(args->GetList(1, &data_type_list)); - for (const base::Value& type : data_type_list->GetList()) { - std::string pref_name; - CHECK(type.GetAsString(&pref_name)); + + CHECK(args_list[1].is_list()); + base::Value::ConstListView data_type_list = args_list[1].GetList(); + for (const base::Value& type : data_type_list) { + const std::string pref_name = type.GetString(); BrowsingDataType data_type = browsing_data::GetDataTypeFromDeletionPreference(pref_name); data_type_vector.push_back(data_type); @@ -342,18 +350,16 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData( // If Sync is running, prevent it from being paused during the operation. // However, if Sync is in error, clearing cookies should pause it. if (!profile_->IsGuestSession() && - sync_ui_util::GetStatus(profile_) == sync_ui_util::SYNCED) { + GetSyncStatusMessageType(profile_) == SyncStatusMessageType::kSynced) { // Settings can not be opened in incognito windows. DCHECK(!profile_->IsOffTheRecord()); scoped_data_deletion = AccountReconcilorFactory::GetForProfile(profile_) ->GetScopedSyncDataDeletion(); } - int period_selected; - CHECK(args->GetInteger(2, &period_selected)); + int period_selected = args_list[2].GetInt(); - const base::ListValue* installed_apps = nullptr; - CHECK(args->GetList(3, &installed_apps)); + const base::Value::ConstListView installed_apps = args_list[3].GetList(); std::unique_ptr<content::BrowsingDataFilterBuilder> filter_builder = ProcessInstalledApps(installed_apps); @@ -450,6 +456,26 @@ void ClearBrowsingDataHandler::UpdateSyncState() { event.SetBoolKey( "shouldShowCookieException", browsing_data_counter_utils::ShouldShowCookieException(profile_)); + + event.SetBoolKey("isNonGoogleDse", false); + if (base::FeatureList::IsEnabled(features::kSearchHistoryLink)) { + const TemplateURLService* template_url_service = + TemplateURLServiceFactory::GetForProfile(profile_); + const TemplateURL* dse = template_url_service->GetDefaultSearchProvider(); + if (dse && dse->GetEngineType(template_url_service->search_terms_data()) != + SearchEngineType::SEARCH_ENGINE_GOOGLE) { + // Non-Google DSE. Prepopulated DSEs have an ID > 0. + event.SetBoolKey("isNonGoogleDse", true); + event.SetStringKey( + "nonGoogleSearchHistoryString", + (dse->prepopulate_id() > 0) + ? l10n_util::GetStringFUTF16( + IDS_SETTINGS_CLEAR_NON_GOOGLE_SEARCH_HISTORY_PREPOPULATED_DSE, + dse->short_name()) + : l10n_util::GetStringUTF16( + IDS_SETTINGS_CLEAR_NON_GOOGLE_SEARCH_HISTORY_NON_PREPOPULATED_DSE)); + } + } FireWebUIListener("update-sync-state", event); } @@ -503,4 +529,8 @@ void ClearBrowsingDataHandler::HandleTimePeriodChanged( browsing_data::RecordTimePeriodChange(time_period); } +void ClearBrowsingDataHandler::OnTemplateURLServiceChanged() { + UpdateSyncState(); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h index d0afce69538..3588663d7f7 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h @@ -12,18 +12,17 @@ #include "base/containers/flat_set.h" #include "base/macros.h" #include "base/scoped_observation.h" +#include "base/values.h" #include "chrome/browser/engagement/important_sites_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/browsing_data/core/browsing_data_utils.h" #include "components/browsing_data/core/counters/browsing_data_counter.h" +#include "components/search/search_provider_observer.h" +#include "components/search_engines/template_url_service_observer.h" #include "components/signin/core/browser/account_reconcilor.h" #include "components/sync/driver/sync_service.h" -namespace base { -class ListValue; -} - namespace content { class BrowsingDataFilterBuilder; class WebUI; @@ -33,7 +32,8 @@ namespace settings { // Chrome browser startup settings handler. class ClearBrowsingDataHandler : public SettingsPageUIHandler, - public syncer::SyncServiceObserver { + public syncer::SyncServiceObserver, + public TemplateURLServiceObserver { public: ClearBrowsingDataHandler(content::WebUI* webui, Profile* profile); ~ClearBrowsingDataHandler() override; @@ -52,6 +52,15 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler, void GetRecentlyLaunchedInstalledApps(const base::ListValue* args); private: + friend class TestingClearBrowsingDataHandler; + friend class ClearBrowsingDataHandlerUnitTest; + FRIEND_TEST_ALL_PREFIXES(ClearBrowsingDataHandlerUnitTest, + UpdateSyncState_GoogleDse); + FRIEND_TEST_ALL_PREFIXES(ClearBrowsingDataHandlerUnitTest, + UpdateSyncState_NonGoogleDsePrepopulated); + FRIEND_TEST_ALL_PREFIXES(ClearBrowsingDataHandlerUnitTest, + UpdateSyncState_NonGoogleDseNotPrepopulated); + // Respond to the WebUI callback with the list of installed apps. void OnGotInstalledApps( const std::string& webui_callback_id, @@ -63,7 +72,7 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler, // based on whether installed apps were marked for deletion by the checkbox on // the installed apps warning dialog. std::unique_ptr<content::BrowsingDataFilterBuilder> ProcessInstalledApps( - const base::ListValue* installed_apps); + base::Value::ConstListView installed_apps); // Clears browsing data, called by Javascript. void HandleClearBrowsingData(const base::ListValue* value); @@ -85,7 +94,7 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler, void OnStateChanged(syncer::SyncService* sync) override; // Updates the footer of the dialog when the sync state changes. - void UpdateSyncState(); + virtual void UpdateSyncState(); // Finds out whether we should show notice about other forms of history stored // in user's account. @@ -107,6 +116,9 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler, // Record changes to the time period preferences. void HandleTimePeriodChanged(const std::string& pref_name); + // Implementation of TemplateURLServiceObserver. + void OnTemplateURLServiceChanged() override; + // Cached profile corresponding to the WebUI of this handler. Profile* profile_; @@ -118,6 +130,9 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler, base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver> sync_service_observation_{this}; + base::ScopedObservation<TemplateURLService, TemplateURLServiceObserver> + dse_service_observation_{this}; + // Whether we should show a dialog informing the user about other forms of // history stored in their account after the history deletion is finished. bool show_history_deletion_dialog_; diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc index 466b9de8f6c..a05f6fe811d 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_browsertest.cc @@ -6,6 +6,7 @@ #include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h" #include "base/values.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" @@ -81,11 +82,12 @@ class ClearBrowsingDataHandlerBrowserTest IN_PROC_BROWSER_TEST_F(ClearBrowsingDataHandlerBrowserTest, GetInstalledApps) { GURL url(https_server()->GetURL("/title1.html")); InstallAndLaunchApp(url); - base::ListValue args; - args.AppendString(kWebUiFunctionName); - args.AppendInteger(1U); + base::Value args(base::Value::Type::LIST); + args.Append(kWebUiFunctionName); + args.Append(1); - web_ui()->HandleReceivedMessage(kGetInstalledApps, &args); + web_ui()->HandleReceivedMessage(kGetInstalledApps, + &base::Value::AsListValue(args)); const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data.function_name()); EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString()); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc new file mode 100644 index 00000000000..cc2afcdc20c --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler_unittest.cc @@ -0,0 +1,176 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h" + +#include "base/test/scoped_feature_list.h" +#include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/browser/search_engines/template_url_service_factory_test_util.h" +#include "chrome/common/chrome_features.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/test/base/testing_profile.h" +#include "components/search_engines/template_url.h" +#include "components/search_engines/template_url_service.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_web_ui.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" + +namespace settings { + +class TestingClearBrowsingDataHandler + : public settings::ClearBrowsingDataHandler { + public: + using settings::ClearBrowsingDataHandler::AllowJavascript; + using settings::ClearBrowsingDataHandler::set_web_ui; + + TestingClearBrowsingDataHandler(content::WebUI* webui, Profile* profile) + : ClearBrowsingDataHandler(webui, profile) {} + + // Some services initialized in |OnJavascriptAllowed()| don't have test + // versions, hence are not available in unittests. For this reason we only + // initialize services needed by the unittests below. + void OnJavascriptAllowed() override { + dse_service_observation_.Observe( + TemplateURLServiceFactory::GetForProfile(profile_)); + } +}; + +class ClearBrowsingDataHandlerUnitTest : public testing::Test { + public: + void SetUp() override; + void TearDown() override; + void VerifySearchHistoryWebUIUpdate( + const bool expected_is_non_google_dse, + const std::u16string& expected_non_google_search_history_strin); + TemplateURL* AddSearchEngine(const std::u16string& short_name, + const GURL& searchable_url, + int prepopulate_id, + bool set_default); + + protected: + content::BrowserTaskEnvironment browser_task_environment_; + std::unique_ptr<TestingProfile> profile_; + std::unique_ptr<content::WebContents> web_contents_; + content::TestWebUI test_web_ui_; + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<TestingClearBrowsingDataHandler> handler_; + std::unique_ptr<TemplateURLServiceFactoryTestUtil> dse_factory_util_; + TemplateURLService* template_url_service; +}; + +void ClearBrowsingDataHandlerUnitTest::SetUp() { + feature_list_.InitWithFeatures({features::kSearchHistoryLink}, {}); + + TestingProfile::Builder builder; + profile_ = builder.Build(); + + web_contents_ = content::WebContents::Create( + content::WebContents::CreateParams(profile_.get())); + + test_web_ui_.set_web_contents(web_contents_.get()); + test_web_ui_.ClearTrackedCalls(); + + dse_factory_util_ = + std::make_unique<TemplateURLServiceFactoryTestUtil>(profile_.get()); + dse_factory_util_->VerifyLoad(); + template_url_service = + TemplateURLServiceFactory::GetForProfile(profile_.get()); + + handler_ = std::make_unique<TestingClearBrowsingDataHandler>(&test_web_ui_, + profile_.get()); + handler_->set_web_ui(&test_web_ui_); + handler_->AllowJavascript(); + + browser_task_environment_.RunUntilIdle(); +} + +void ClearBrowsingDataHandlerUnitTest::TearDown() { + dse_factory_util_.reset(); +} + +void ClearBrowsingDataHandlerUnitTest::VerifySearchHistoryWebUIUpdate( + const bool expected_is_non_google_dse, + const std::u16string& expected_non_google_search_history_string) { + // Verify the latest update if multiple, so iterate from the end. + const std::vector<std::unique_ptr<content::TestWebUI::CallData>>& call_data = + test_web_ui_.call_data(); + for (int i = call_data.size() - 1; i >= 0; --i) { + const content::TestWebUI::CallData& data = *(call_data[i]); + if (data.function_name() != "cr.webUIListenerCallback") { + continue; + } + const std::string* event = data.arg1()->GetIfString(); + if (!event || *event != "update-sync-state") + continue; + const base::DictionaryValue* dictionary = nullptr; + if (!data.arg2()->GetAsDictionary(&dictionary)) { + continue; + } + bool actual_is_non_google_dse; + dictionary->GetBoolean("isNonGoogleDse", &actual_is_non_google_dse); + ASSERT_EQ(expected_is_non_google_dse, actual_is_non_google_dse); + if (expected_is_non_google_dse) { + std::u16string actual_non_google_search_history_string; + dictionary->GetString("nonGoogleSearchHistoryString", + &actual_non_google_search_history_string); + ASSERT_EQ(expected_non_google_search_history_string, + actual_non_google_search_history_string); + } + return; + } + NOTREACHED(); +} + +TemplateURL* ClearBrowsingDataHandlerUnitTest::AddSearchEngine( + const std::u16string& short_name, + const GURL& searchable_url, + int prepopulate_id, + bool set_default) { + TemplateURLData data; + data.SetShortName(short_name); + data.SetKeyword(short_name); + data.SetURL(searchable_url.possibly_invalid_spec()); + data.favicon_url = TemplateURL::GenerateFaviconURL(searchable_url); + data.prepopulate_id = prepopulate_id; + TemplateURL* url = + template_url_service->Add(std::make_unique<TemplateURL>(data)); + if (set_default) + template_url_service->SetUserSelectedDefaultSearchProvider(url); + return url; +} + +TEST_F(ClearBrowsingDataHandlerUnitTest, UpdateSyncState_GoogleDse) { + handler_->UpdateSyncState(); + VerifySearchHistoryWebUIUpdate(false, u""); +} + +TEST_F(ClearBrowsingDataHandlerUnitTest, + UpdateSyncState_NonGoogleDsePrepopulated) { + // Prepopulated search engines have an ID > 0. + AddSearchEngine(u"SomeSE", GURL("https://somese.com?q={searchTerms}"), 1001, + true); + + // DSE changes should update the handler, no need to call |UpdateSyncState()|. + VerifySearchHistoryWebUIUpdate( + true, l10n_util::GetStringFUTF16( + IDS_SETTINGS_CLEAR_NON_GOOGLE_SEARCH_HISTORY_PREPOPULATED_DSE, + u"SomeSE")); +} + +TEST_F(ClearBrowsingDataHandlerUnitTest, + UpdateSyncState_NonGoogleDseNotPrepopulated) { + // Custom search engines have a prepopulated ID of 0. + AddSearchEngine(u"SomeSE", GURL("https://somese.com?q={searchTerms}"), 0, + true); + + // DSE changes should update the handler, no need to call |UpdateSyncState()|. + VerifySearchHistoryWebUIUpdate( + true, + l10n_util::GetStringUTF16( + IDS_SETTINGS_CLEAR_NON_GOOGLE_SEARCH_HISTORY_NON_PREPOPULATED_DSE)); +} + +} // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc index 13c78fab95a..312e28188dc 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc @@ -11,8 +11,8 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/cxx17_backports.h" #include "base/i18n/number_formatting.h" -#include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browsing_data/third_party_data_remover.h" @@ -460,7 +460,8 @@ void CookiesViewHandler::ReturnLocalDataList(const std::string& callback_id) { FALLTHROUGH; case CookieTreeNode::DetailedInfo::TYPE_COOKIES: description += l10n_util::GetPluralStringFUTF16( - IDS_SETTINGS_SITE_SETTINGS_NUM_COOKIES, int{item_count}); + IDS_SETTINGS_SITE_SETTINGS_NUM_COOKIES, + static_cast<int>(item_count)); break; default: int ids_value = GetCategoryLabelID(node_type); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc index 2e2e56d4a66..9583b0d7040 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler_unittest.cc @@ -13,6 +13,7 @@ #include "components/browsing_data/content/mock_cookie_helper.h" #include "components/browsing_data/content/mock_local_storage_helper.h" #include "content/public/test/test_web_ui.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" namespace { @@ -69,10 +70,10 @@ class CookiesViewHandlerTest : public ChromeRenderViewHostTestHarness { auto mock_cookies_tree_model = std::make_unique<CookiesTreeModel>( std::move(container), profile()->GetExtensionSpecialStoragePolicy()); - mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - url::Origin::Create(GURL(kTestOrigin1)), 2); - mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - url::Origin::Create(GURL(kTestOrigin2)), 3); + mock_browsing_data_local_storage_helper->AddLocalStorageForStorageKey( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin1), 2); + mock_browsing_data_local_storage_helper->AddLocalStorageForStorageKey( + blink::StorageKey::CreateFromStringForTesting(kTestOrigin2), 3); mock_browsing_data_cookie_helper->AddCookieSamples(GURL(kTestOrigin1), kTestCookie1); @@ -90,9 +91,9 @@ class CookiesViewHandlerTest : public ChromeRenderViewHostTestHarness { void SetupHandlerWithTreeModel() { SetupTreeModelForTesting(); - base::ListValue reload_args; - reload_args.AppendString(kCallbackId); - handler()->HandleReloadCookies(&reload_args); + base::Value reload_args(base::Value::Type::LIST); + reload_args.Append(kCallbackId); + handler()->HandleReloadCookies(&base::Value::AsListValue(reload_args)); // The handler will post a task to recreate the tree model. task_environment()->RunUntilIdle(); @@ -132,18 +133,19 @@ TEST_F(CookiesViewHandlerTest, SingleRequestDuringBatch) { constexpr char kReloadCallbackID[] = "reload-cookies-callback"; constexpr char kGetDisplaylistCallbackID[] = "get-display-list-callback"; - base::ListValue reload_args; - reload_args.AppendString(kReloadCallbackID); - handler()->HandleReloadCookies(&reload_args); + base::Value reload_args(base::Value::Type::LIST); + reload_args.Append(kReloadCallbackID); + handler()->HandleReloadCookies(&base::Value::AsListValue(reload_args)); task_environment()->RunUntilIdle(); // At the point the handler will have recreated the model (using the provided // test model) and will be awaiting batch end. Performing another request // should result in it not being satisfied, and instead being queued. - base::ListValue get_display_list_args; - get_display_list_args.AppendString(kGetDisplaylistCallbackID); - get_display_list_args.AppendString(""); - handler()->HandleGetDisplayList(&get_display_list_args); + base::Value get_display_list_args(base::Value::Type::LIST); + get_display_list_args.Append(kGetDisplaylistCallbackID); + get_display_list_args.Append(""); + handler()->HandleGetDisplayList( + &base::Value::AsListValue(get_display_list_args)); task_environment()->RunUntilIdle(); // Because the tree model hasn't completed the batch, no callback should @@ -184,37 +186,37 @@ TEST_F(CookiesViewHandlerTest, NoStarvation) { std::string current_filter = kTestHost1; auto get_display_list_new_filter = base::BindLambdaForTesting([&](std::string callback_id) { - base::ListValue args; - args.AppendString(callback_id); + base::Value args(base::Value::Type::LIST); + args.Append(callback_id); current_filter = current_filter == kTestHost1 ? "" : kTestHost1; - args.AppendString(kTestHost1); - handler()->HandleGetDisplayList(&args); + args.Append(kTestHost1); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); }); auto get_display_list_same_filter = base::BindLambdaForTesting([&](std::string callback_id) { - base::ListValue args; - args.AppendString(callback_id); - args.AppendString(current_filter); - handler()->HandleGetDisplayList(&args); + base::Value args(base::Value::Type::LIST); + args.Append(callback_id); + args.Append(current_filter); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); }); auto get_cookie_details = base::BindLambdaForTesting([&](std::string callback_id) { - base::ListValue args; - args.AppendString(callback_id); - args.AppendString(kTestHost1); - handler()->HandleGetCookieDetails(&args); + base::Value args(base::Value::Type::LIST); + args.Append(callback_id); + args.Append(kTestHost1); + handler()->HandleGetCookieDetails(&base::Value::AsListValue(args)); }); auto reload_cookies = base::BindLambdaForTesting([&](std::string callback_id) { - base::ListValue args; - args.AppendString(callback_id); - handler()->HandleReloadCookies(&args); + base::Value args(base::Value::Type::LIST); + args.Append(callback_id); + handler()->HandleReloadCookies(&base::Value::AsListValue(args)); }); auto remove_third_party = base::BindLambdaForTesting([&](std::string callback_id) { - base::ListValue args; - args.AppendString(callback_id); - handler()->HandleRemoveThirdParty(&args); + base::Value args(base::Value::Type::LIST); + args.Append(callback_id); + handler()->HandleRemoveThirdParty(&base::Value::AsListValue(args)); }); // Include a dummy request which allows the request queue to be cleared. This // ensures that requests may be queued up both during, and outside of, batch @@ -267,10 +269,10 @@ TEST_F(CookiesViewHandlerTest, ImmediateTreeOperation) { // previously results in a tree being created before the request is handled. SetupTreeModelForTesting(); - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(kTestHost1); - handler()->HandleGetCookieDetails(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(kTestHost1); + handler()->HandleGetCookieDetails(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); // At this point the handler should have queued the creation of a tree and @@ -297,11 +299,11 @@ TEST_F(CookiesViewHandlerTest, HandleGetDisplayList) { // Retrieve a filtered list. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(kTestHost1); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(kTestHost1); - handler()->HandleGetDisplayList(&args); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -315,11 +317,11 @@ TEST_F(CookiesViewHandlerTest, HandleGetDisplayList) { // Remove the filter and confirm the full list is returned. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(""); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(""); - handler()->HandleGetDisplayList(&args); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -340,10 +342,10 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveShownItems) { // Apply a filter to the list and confirm it is returned. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(kTestHost2); - handler()->HandleGetDisplayList(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(kTestHost2); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -357,17 +359,17 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveShownItems) { // Remove displayed items. { - base::ListValue args; - handler()->HandleRemoveShownItems(&args); + base::Value args(base::Value::Type::LIST); + handler()->HandleRemoveShownItems(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); } // Remove the filter and confirm unremoved items are returned. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(""); - handler()->HandleGetDisplayList(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(""); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -383,10 +385,10 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveShownItems) { TEST_F(CookiesViewHandlerTest, HandleGetCookieDetails) { // Ensure that the cookie details are correctly returned for a site. SetupHandlerWithTreeModel(); - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(kTestHost1); - handler()->HandleGetCookieDetails(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(kTestHost1); + handler()->HandleGetCookieDetails(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -404,9 +406,9 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveAll) { // Ensure that RemoveAll removes all cookies & storage. SetupHandlerWithTreeModel(); { - base::ListValue args; - args.AppendString(kCallbackId); - handler()->HandleRemoveAll(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + handler()->HandleRemoveAll(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -417,10 +419,10 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveAll) { // Ensure returned display list is empty. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(""); - handler()->HandleGetDisplayList(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(""); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -440,10 +442,10 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveItem) { // Get the appropriate path for removal. std::string node_path_id; { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(kTestHost1); - handler()->HandleGetCookieDetails(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(kTestHost1); + handler()->HandleGetCookieDetails(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -458,9 +460,9 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveItem) { // Remove path and ensure that the removed item listener fires. { - base::ListValue args; - args.AppendString(node_path_id); - handler()->HandleRemoveItem(&args); + base::Value args(base::Value::Type::LIST); + args.Append(node_path_id); + handler()->HandleRemoveItem(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); // Removal should fire an update event. @@ -472,10 +474,10 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveItem) { // Ensure that the removed item is no longer present in cookie details. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(kTestHost1); - handler()->HandleGetCookieDetails(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(kTestHost1); + handler()->HandleGetCookieDetails(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -490,9 +492,9 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveSite) { // Check that removing a single site works. { - base::ListValue args; - args.AppendString(kTestHost1); - handler()->HandleRemoveSite(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kTestHost1); + handler()->HandleRemoveSite(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); // Removal should fire an update event. @@ -503,10 +505,10 @@ TEST_F(CookiesViewHandlerTest, HandleRemoveSite) { // Check that the removed site is no longer present in the display list. { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(""); - handler()->HandleGetDisplayList(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(""); + handler()->HandleGetDisplayList(&base::Value::AsListValue(args)); task_environment()->RunUntilIdle(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc index b5ccfd55881..c773004acca 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc @@ -28,7 +28,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_shortcut_manager.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" -#include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_service_factory.h" #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/webui/management/management_ui.h" @@ -92,19 +92,17 @@ #include "ui/strings/grit/ui_strings.h" #if BUILDFLAG(IS_CHROMEOS_LACROS) -#include "chrome/browser/lacros/account_manager_util.h" +#include "chrome/browser/lacros/account_manager/account_manager_util.h" #endif // BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_CHROMEOS_ASH) #include "ash/constants/ash_features.h" -#include "ash/public/cpp/ash_switches.h" #include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/ash/assistant/assistant_util.h" #include "chrome/browser/ash/kerberos/kerberos_credentials_manager.h" #include "chrome/browser/ash/login/quick_unlock/quick_unlock_utils.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash.h" #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" #include "chrome/common/webui_url_constants.h" #include "components/user_manager/user_manager.h" @@ -114,6 +112,10 @@ #include "ui/accessibility/accessibility_features.h" #endif +#if defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#include "ui/display/screen.h" +#endif + #if defined(OS_WIN) #include "chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.h" #include "device/fido/win/webauthn_api.h" @@ -129,6 +131,12 @@ #if defined(USE_NSS_CERTS) #include "chrome/browser/ui/webui/certificate_manager_localized_strings_provider.h" #endif + +#if defined(USE_OZONE) +#include "ui/base/ui_base_features.h" +#include "ui/ozone/public/ozone_platform.h" +#endif + namespace settings { namespace { @@ -192,7 +200,7 @@ void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) { user_manager::UserManager::Get()->IsLoggedInAsGuest() || user_manager::UserManager::Get()->IsLoggedInAsPublicAccount()); #else - profile->IsGuestSession() || profile->IsEphemeralGuestProfile()); + profile->IsGuestSession()); #endif html_source->AddBoolean("isSupervised", profile->IsSupervised()); @@ -271,17 +279,33 @@ void AddAboutStrings(content::WebUIDataSource* html_source, Profile* profile) { l10n_util::GetStringUTF16(IDS_SETTINGS_UPGRADE_UP_TO_DATE)); #endif - html_source->AddString( - "aboutBrowserVersion", - l10n_util::GetStringFUTF16( - IDS_SETTINGS_ABOUT_PAGE_BROWSER_VERSION, - base::UTF8ToUTF16(version_info::GetVersionNumber()), - l10n_util::GetStringUTF16(version_info::IsOfficialBuild() - ? IDS_VERSION_UI_OFFICIAL - : IDS_VERSION_UI_UNOFFICIAL), - base::UTF8ToUTF16( - chrome::GetChannelName(chrome::WithExtendedStable(true))), - l10n_util::GetStringUTF16(VersionUI::VersionProcessorVariation()))); +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // On Lacros, we don't have the concept of channels, in their usual semantics. + // Replace the channel string with "Lacros". https://crbug.com/1215734. + std::string channel_name = "Lacros"; +#else + std::string channel_name = + chrome::GetChannelName(chrome::WithExtendedStable(true)); +#endif + + std::u16string browser_version = l10n_util::GetStringFUTF16( + IDS_SETTINGS_ABOUT_PAGE_BROWSER_VERSION, + base::UTF8ToUTF16(version_info::GetVersionNumber()), + l10n_util::GetStringUTF16(version_info::IsOfficialBuild() + ? IDS_VERSION_UI_OFFICIAL + : IDS_VERSION_UI_UNOFFICIAL), + base::UTF8ToUTF16(channel_name), + l10n_util::GetStringUTF16(VersionUI::VersionProcessorVariation())); + +#if BUILDFLAG(IS_CHROMEOS_LACROS) + // Lacros is in development so we don't worry about l10n for now. This message + // will not be shown for the full release. + browser_version += u". "; + browser_version += + l10n_util::GetStringUTF16(IDS_EXPERIMENTAL_LACROS_WARNING_MESSAGE); +#endif + + html_source->AddString("aboutBrowserVersion", browser_version); html_source->AddString( "aboutProductCopyright", base::i18n::MessageFormatter::FormatWithNumberedArgs( @@ -363,6 +387,21 @@ void AddAppearanceStrings(content::WebUIDataSource* html_source, zoom::GetPresetZoomFactorsAsJSON()); html_source->AddBoolean("showReaderModeOption", dom_distiller::OfferReaderModeInSettings()); + +// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch +// of lacros-chrome is complete. +#if defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS) +#if defined(USE_OZONE) + const bool show_custom_chrome_frame = + features::IsUsingOzonePlatform() && + ui::OzonePlatform::GetInstance() + ->GetPlatformRuntimeProperties() + .supports_server_side_window_decorations; +#else + const bool show_custom_chrome_frame = true; +#endif + html_source->AddBoolean("showCustomChromeFrame", show_custom_chrome_frame); +#endif } void AddClearBrowsingDataStrings(content::WebUIDataSource* html_source, @@ -420,12 +459,17 @@ void AddClearBrowsingDataStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED, base::ASCIIToUTF16(chrome::kMyActivityUrlInClearBrowsingData))); html_source->AddString( - "clearSearchHistorySummarySignedIn", + "clearGoogleSearchHistoryGoogleDse", l10n_util::GetStringFUTF16( - IDS_SETTINGS_CLEAR_SEARCH_BROWSING_HISTORY_SUMMARY_SIGNED_IN, + IDS_SETTINGS_CLEAR_GOOGLE_SEARCH_HISTORY_GOOGLE_DSE, base::ASCIIToUTF16(chrome::kSearchHistoryUrlInClearBrowsingData), base::ASCIIToUTF16(chrome::kMyActivityUrlInClearBrowsingData))); html_source->AddString( + "clearGoogleSearchHistoryNonGoogleDse", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_CLEAR_GOOGLE_SEARCH_HISTORY_NON_GOOGLE_DSE, + base::ASCIIToUTF16(chrome::kMyActivityUrlInClearBrowsingData))); + html_source->AddString( "historyDeletionDialogBody", l10n_util::GetStringFUTF16( IDS_CLEAR_BROWSING_DATA_HISTORY_NOTICE, @@ -459,12 +503,40 @@ void AddDownloadsStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"downloadsPageTitle", IDS_SETTINGS_DOWNLOADS}, {"downloadLocation", IDS_SETTINGS_DOWNLOAD_LOCATION}, + {"downloadLocalLocation", IDS_SETTINGS_DOWNLOAD_LOCAL_LOCATION}, + {"downloadConnectionAccountTitle", + IDS_SETTINGS_DOWNLOAD_CONNECTION_ACCOUNT_TITLE}, + {"downloadConnectionLearnMore", + IDS_SETTINGS_DOWNLOAD_CONNECTION_LEARN_MORE}, {"changeDownloadLocation", IDS_SETTINGS_CHANGE_DOWNLOAD_LOCATION}, {"promptForDownload", IDS_SETTINGS_PROMPT_FOR_DOWNLOAD}, {"openFileTypesAutomatically", IDS_SETTINGS_OPEN_FILE_TYPES_AUTOMATICALLY}, }; html_source->AddLocalizedStrings(kLocalizedStrings); + const std::u16string kBox = + l10n_util::GetStringUTF16(IDS_FILE_SYSTEM_CONNECTOR_BOX); + html_source->AddString( + "downloadsConnectionTitle", + l10n_util::GetStringFUTF16(IDS_SETTINGS_DOWNLOAD_CONNECTION_TITLE, kBox)); + html_source->AddString( + "downloadsConnectionUnlinkedMessage", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_DOWNLOAD_CONNECTION_UNLINKED_MESSAGE, kBox)); + html_source->AddString( + "downloadsConnectionLinkButton", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_DOWNLOAD_CONNECTION_SIGN_IN_BUTTON, kBox)); + html_source->AddString( + "downloadsConnectionLinkedMessage", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_DOWNLOAD_CONNECTION_LINKED_MESSAGE, kBox)); + html_source->AddString("downloadsConnectionUnlinkButton", + l10n_util::GetStringUTF16( + IDS_SETTINGS_DOWNLOAD_CONNECTION_SIGN_OUT_BUTTON)); + html_source->AddString("downloadConnectionLinkedFolder", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_DOWNLOAD_WEB_DRIVE_LOCATION, kBox)); } #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) @@ -630,8 +702,8 @@ void AddResetStrings(content::WebUIDataSource* html_source, Profile* profile) { ResetSettingsHandler::ShouldShowResetProfileBanner(profile)); bool is_reset_shortcuts_feature_enabled = false; #if defined(OS_WIN) - is_reset_shortcuts_feature_enabled = - base::FeatureList::IsEnabled(safe_browsing::kResetShortcutsFeature); + // TODO(crbug/1234599): Remove this flag from the JS. + is_reset_shortcuts_feature_enabled = true; #endif html_source->AddBoolean("showExplanationWithBulletPoints", is_reset_shortcuts_feature_enabled); @@ -666,6 +738,7 @@ void AddImportDataStrings(content::WebUIDataSource* html_source) { void AddLanguagesStrings(content::WebUIDataSource* html_source, Profile* profile) { +#if !BUILDFLAG(IS_CHROMEOS_ASH) static constexpr webui::LocalizedString kLocalizedStrings[] = { {"languagesPageTitle", IDS_SETTINGS_LANGUAGES_PAGE_TITLE}, {"languagesListTitle", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_TITLE}, @@ -680,8 +753,6 @@ void AddLanguagesStrings(content::WebUIDataSource* html_source, {"removeLanguage", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_REMOVE}, {"addLanguages", IDS_SETTINGS_LANGUAGES_LANGUAGES_ADD}, {"addLanguagesDialogTitle", IDS_SETTINGS_LANGUAGES_MANAGE_LANGUAGES_TITLE}, - {"allLanguages", IDS_SETTINGS_LANGUAGES_ALL_LANGUAGES}, - {"enabledLanguages", IDS_SETTINGS_LANGUAGES_ENABLED_LANGUAGES}, #if defined(OS_WIN) {"isDisplayedInThisLanguage", IDS_SETTINGS_LANGUAGES_IS_DISPLAYED_IN_THIS_LANGUAGE}, @@ -731,24 +802,16 @@ void AddLanguagesStrings(content::WebUIDataSource* html_source, #endif }; html_source->AddLocalizedStrings(kLocalizedStrings); - +#endif // !BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_ASH) - user_manager::UserManager* user_manager = user_manager::UserManager::Get(); - const user_manager::User* user = - chromeos::ProfileHelper::Get()->GetUserByProfile(profile); - const user_manager::User* primary_user = user_manager->GetPrimaryUser(); - html_source->AddBoolean( - "isSecondaryUser", - user && user->GetAccountId() != primary_user->GetAccountId()); - - html_source->AddString( + html_source->AddLocalizedString("languagesPageTitle", + IDS_SETTINGS_LANGUAGES_PAGE_TITLE); + html_source->AddLocalizedString( "openChromeOSLanguagesSettingsLabel", - l10n_util::GetStringUTF16( - IDS_SETTINGS_LANGUAGES_OPEN_CHROME_OS_SETTINGS_LABEL)); + IDS_SETTINGS_LANGUAGES_OPEN_CHROME_OS_SETTINGS_LABEL); html_source->AddString( "chromeOSLanguagesSettingsPath", chromeos::settings::mojom::kLanguagesAndInputSectionPath); - #endif // BUILDFLAG(IS_CHROMEOS_ASH) } @@ -1022,7 +1085,10 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_PAYMENTS_SAVED_TO_THIS_DEVICE_ONLY}, {"trustedVaultOptInLabel", IDS_SETTINGS_TRUSTED_VAULT_OPT_IN_LABEL}, {"trustedVaultOptInSubLabel", - IDS_SETTINGS_TRUSTED_VAULT_OPT_IN_SUB_LABEL}}; + IDS_SETTINGS_TRUSTED_VAULT_OPT_IN_SUB_LABEL}, + {"noSearchResults", IDS_SEARCH_NO_RESULTS}, + {"searchResultsPlural", IDS_SEARCH_RESULTS_PLURAL}, + {"searchResultsSingular", IDS_SEARCH_RESULTS_SINGULAR}}; GURL google_password_manager_url = GetGooglePasswordManagerURL( password_manager::ManagePasswordsReferrer::kChromeSettings); @@ -1085,9 +1151,8 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, l10n_util::GetStringFUTF16( IDS_SETTINGS_SIGNED_OUT_USER_HAS_COMPROMISED_CREDENTIALS_LABEL, base::ASCIIToUTF16(chrome::kSyncLearnMoreURL))); - // TODO(crbug.com/1202088): Add the correct URL here when that's available. html_source->AddString("trustedVaultOptInUrl", - google_password_manager_url.spec()); + chrome::kSyncTrustedVaultOptInURL); bool is_guest_mode = false; #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -1102,7 +1167,7 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, "migrationEnabled", !is_guest_mode && autofill::IsCreditCardMigrationEnabled( personal_data, profile->GetPrefs(), - ProfileSyncServiceFactory::GetForProfile(profile), + SyncServiceFactory::GetForProfile(profile), /*is_test_mode=*/false, /*log_manager=*/nullptr)); html_source->AddBoolean( @@ -1266,6 +1331,7 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { #elif BUILDFLAG(IS_CHROMEOS_LACROS) html_source->AddBoolean("isAccountManagerEnabled", IsAccountManagerAvailable(profile)); + html_source->AddBoolean("isMainProfile", profile->IsMainProfile()); #endif AddSignOutDialogStrings(html_source, profile); @@ -1277,130 +1343,124 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { AddSyncPageStrings(html_source); } +bool ShouldLinkSecureDnsOsSettings() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + return base::FeatureList::IsEnabled(chromeos::features::kEnableDnsProxy) && + base::FeatureList::IsEnabled(::features::kDnsProxyEnableDOH); +#else + return false; +#endif +} + +bool IsSecureDnsAvailable() { + return features::kDnsOverHttpsShowUiParam.Get(); +} + void AddPrivacyStrings(content::WebUIDataSource* html_source, Profile* profile) { static constexpr webui::LocalizedString kLocalizedStrings[] = { - {"privacyPageTitle", IDS_SETTINGS_PRIVACY}, - {"privacyPageMore", IDS_SETTINGS_PRIVACY_MORE}, - {"doNotTrack", IDS_SETTINGS_ENABLE_DO_NOT_TRACK}, - {"doNotTrackDialogTitle", IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TITLE}, - // TODO(crbug.com/1062607): This string is no longer used. Remove. - {"permissionsPageTitle", IDS_SETTINGS_PERMISSIONS}, - {"permissionsPageDescription", IDS_SETTINGS_PERMISSIONS_DESCRIPTION}, - {"securityPageTitle", IDS_SETTINGS_SECURITY}, - {"securityPageDescription", IDS_SETTINGS_SECURITY_DESCRIPTION}, - {"advancedProtectionProgramTitle", - IDS_SETTINGS_ADVANCED_PROTECTION_PROGRAM}, - {"advancedProtectionProgramDesc", - IDS_SETTINGS_ADVANCED_PROTECTION_PROGRAM_DESC}, - {"manageCertificates", IDS_SETTINGS_MANAGE_CERTIFICATES}, - {"manageCertificatesDescription", - IDS_SETTINGS_MANAGE_CERTIFICATES_DESCRIPTION}, - {"secureDns", IDS_SETTINGS_SECURE_DNS}, - {"secureDnsDescription", IDS_SETTINGS_SECURE_DNS_DESCRIPTION}, - {"secureDnsDisabledForManagedEnvironment", - IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_MANAGED_ENVIRONMENT}, - {"secureDnsDisabledForParentalControl", - IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_PARENTAL_CONTROL}, - {"secureDnsAutomaticModeDescription", - IDS_SETTINGS_AUTOMATIC_MODE_DESCRIPTION}, - {"secureDnsAutomaticModeDescriptionSecondary", - IDS_SETTINGS_AUTOMATIC_MODE_DESCRIPTION_SECONDARY}, - {"secureDnsSecureModeA11yLabel", - IDS_SETTINGS_SECURE_MODE_DESCRIPTION_ACCESSIBILITY_LABEL}, - {"secureDnsDropdownA11yLabel", - IDS_SETTINGS_SECURE_DNS_DROPDOWN_ACCESSIBILITY_LABEL}, - {"secureDnsSecureDropdownModeDescription", - IDS_SETTINGS_SECURE_DROPDOWN_MODE_DESCRIPTION}, - {"secureDnsSecureDropdownModePrivacyPolicy", - IDS_SETTINGS_SECURE_DROPDOWN_MODE_PRIVACY_POLICY}, - {"secureDnsCustomPlaceholder", - IDS_SETTINGS_SECURE_DNS_CUSTOM_PLACEHOLDER}, - {"secureDnsCustomFormatError", - IDS_SETTINGS_SECURE_DNS_CUSTOM_FORMAT_ERROR}, - {"secureDnsCustomConnectionError", - IDS_SETTINGS_SECURE_DNS_CUSTOM_CONNECTION_ERROR}, - {"contentSettings", IDS_SETTINGS_CONTENT_SETTINGS}, - {"siteSettings", IDS_SETTINGS_SITE_SETTINGS}, - {"siteSettingsDescription", IDS_SETTINGS_SITE_SETTINGS_DESCRIPTION}, - {"clearData", IDS_SETTINGS_CLEAR_DATA}, - {"clearingData", IDS_SETTINGS_CLEARING_DATA}, - {"clearedData", IDS_SETTINGS_CLEARED_DATA}, - {"clearBrowsingData", IDS_SETTINGS_CLEAR_BROWSING_DATA}, - {"clearBrowsingDataDescription", IDS_SETTINGS_CLEAR_DATA_DESCRIPTION}, - {"titleAndCount", IDS_SETTINGS_TITLE_AND_COUNT}, - {"safeBrowsingEnableExtendedReporting", - IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING}, - {"safeBrowsingEnableExtendedReportingDesc", - IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING_DESC}, - {"safeBrowsingEnhanced", IDS_SETTINGS_SAFEBROWSING_ENHANCED}, - {"safeBrowsingEnhancedDesc", IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC}, - {"safeBrowsingEnhancedExpandA11yLabel", - IDS_SETTINGS_SAFEBROWSING_ENHANCED_EXPAND_ACCESSIBILITY_LABEL}, - {"safeBrowsingEnhancedBulOne", - IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_ONE}, - {"safeBrowsingEnhancedBulTwo", - IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_TWO}, - {"safeBrowsingEnhancedBulThree", - IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_THREE}, - {"safeBrowsingEnhancedBulFour", - IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_FOUR}, - {"safeBrowsingEnhancedBulFive", - IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_FIVE}, - {"safeBrowsingStandard", IDS_SETTINGS_SAFEBROWSING_STANDARD}, - {"safeBrowsingStandardDesc", IDS_SETTINGS_SAFEBROWSING_STANDARD_DESC}, - {"safeBrowsingStandardExpandA11yLabel", - IDS_SETTINGS_SAFEBROWSING_STANDARD_EXPAND_ACCESSIBILITY_LABEL}, - {"safeBrowsingStandardBulOne", - IDS_SETTINGS_SAFEBROWSING_STANDARD_BULLET_ONE}, - {"safeBrowsingStandardBulTwo", - IDS_SETTINGS_SAFEBROWSING_STANDARD_BULLET_TWO}, - {"safeBrowsingStandardReportingLabel", - IDS_SETTINGS_SAFEBROWSING_STANDARD_HELP_IMPROVE}, - {"safeBrowsingNone", IDS_SETTINGS_SAFEBROWSING_NONE}, - {"safeBrowsingNoneDesc", IDS_SETTINGS_SAFEBROWSING_NONE_DESC}, - {"safeBrowsingDisableDialog", - IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_TITLE}, - {"safeBrowsingDisableDialogDesc", - IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_DESC}, - {"safeBrowsingDisableDialogConfirm", - IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_CONFIRM}, - {"safeBrowsingEnableProtection", - IDS_SETTINGS_SAFEBROWSING_ENABLEPROTECTION}, - {"safeBrowsingEnableProtectionDesc", - IDS_SETTINGS_SAFEBROWSING_ENABLEPROTECTION_DESC}, - {"safeBrowsingSectionLabel", IDS_SETTINGS_SAFEBROWSING_SECTION_LABEL}, - {"syncAndGoogleServicesPrivacyDescription", - IDS_SETTINGS_SYNC_AND_GOOGLE_SERVICES_PRIVACY_DESC_UNIFIED_CONSENT}, - {"urlKeyedAnonymizedDataCollection", - IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION}, - {"urlKeyedAnonymizedDataCollectionDesc", - IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION_DESC}, - {"noRecentPermissions", IDS_SETTINGS_RECENT_PERMISSIONS_NO_CHANGES}, - {"recentPermissionAllowedOneItem", - IDS_SETTINGS_RECENT_PERMISSIONS_ALLOWED_ONE_ITEM}, - {"recentPermissionAllowedTwoItems", - IDS_SETTINGS_RECENT_PERMISSIONS_ALLOWED_TWO_ITEMS}, - {"recentPermissionAllowedMoreThanTwoItems", - IDS_SETTINGS_RECENT_PERMISSIONS_ALLOWED_MORE_THAN_TWO_ITEMS}, - {"recentPermissionAutoBlockedOneItem", - IDS_SETTINGS_RECENT_PERMISSIONS_AUTOMATICALLY_BLOCKED_ONE_ITEM}, - {"recentPermissionAutoBlockedTwoItems", - IDS_SETTINGS_RECENT_PERMISSIONS_AUTOMATICALLY_BLOCKED_TWO_ITEMS}, - {"recentPermissionAutoBlockedMoreThanTwoItems", - IDS_SETTINGS_RECENT_PERMISSIONS_AUTOMATICALLY_BLOCKED_MORE_THAN_TWO_ITEMS}, - {"recentPermissionBlockedOneItem", - IDS_SETTINGS_RECENT_PERMISSIONS_BLOCKED_ONE_ITEM}, - {"recentPermissionBlockedTwoItems", - IDS_SETTINGS_RECENT_PERMISSIONS_BLOCKED_TWO_ITEMS}, - {"recentPermissionBlockedMoreThanTwoItems", - IDS_SETTINGS_RECENT_PERMISSIONS_BLOCKED_MORE_THAN_TWO_ITEMS}, - {"networkPredictionEnabled", - IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_LABEL}, - {"networkPredictionEnabledDesc", - IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESC}, - {"networkPredictionEnabledDescCookiesPage", - IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESC_COOKIES_PAGE}, + {"privacyPageTitle", IDS_SETTINGS_PRIVACY}, + {"privacyPageMore", IDS_SETTINGS_PRIVACY_MORE}, + {"doNotTrack", IDS_SETTINGS_ENABLE_DO_NOT_TRACK}, + {"doNotTrackDialogTitle", IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TITLE}, + // TODO(crbug.com/1062607): This string is no longer used. Remove. + {"permissionsPageTitle", IDS_SETTINGS_PERMISSIONS}, + {"permissionsPageDescription", IDS_SETTINGS_PERMISSIONS_DESCRIPTION}, + {"securityPageTitle", IDS_SETTINGS_SECURITY}, + {"securityPageDescription", IDS_SETTINGS_SECURITY_DESCRIPTION}, + {"advancedProtectionProgramTitle", + IDS_SETTINGS_ADVANCED_PROTECTION_PROGRAM}, + {"advancedProtectionProgramDesc", + IDS_SETTINGS_ADVANCED_PROTECTION_PROGRAM_DESC}, + {"httpsOnlyModeTitle", IDS_SETTINGS_HTTPS_ONLY_MODE}, + {"httpsOnlyModeDescription", IDS_SETTINGS_HTTPS_ONLY_MODE_DESCRIPTION}, + {"manageCertificates", IDS_SETTINGS_MANAGE_CERTIFICATES}, + {"manageCertificatesDescription", + IDS_SETTINGS_MANAGE_CERTIFICATES_DESCRIPTION}, + {"contentSettings", IDS_SETTINGS_CONTENT_SETTINGS}, + {"siteSettings", IDS_SETTINGS_SITE_SETTINGS}, + {"siteSettingsDescription", IDS_SETTINGS_SITE_SETTINGS_DESCRIPTION}, + {"clearData", IDS_SETTINGS_CLEAR_DATA}, + {"clearingData", IDS_SETTINGS_CLEARING_DATA}, + {"clearedData", IDS_SETTINGS_CLEARED_DATA}, + {"clearBrowsingData", IDS_SETTINGS_CLEAR_BROWSING_DATA}, + {"clearBrowsingDataDescription", IDS_SETTINGS_CLEAR_DATA_DESCRIPTION}, + {"titleAndCount", IDS_SETTINGS_TITLE_AND_COUNT}, + {"safeBrowsingEnableExtendedReporting", + IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING}, + {"safeBrowsingEnableExtendedReportingDesc", + IDS_SETTINGS_SAFEBROWSING_ENABLE_REPORTING_DESC}, + {"safeBrowsingEnhanced", IDS_SETTINGS_SAFEBROWSING_ENHANCED}, + {"safeBrowsingEnhancedDesc", IDS_SETTINGS_SAFEBROWSING_ENHANCED_DESC}, + {"safeBrowsingEnhancedExpandA11yLabel", + IDS_SETTINGS_SAFEBROWSING_ENHANCED_EXPAND_ACCESSIBILITY_LABEL}, + {"safeBrowsingEnhancedBulOne", + IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_ONE}, + {"safeBrowsingEnhancedBulTwo", + IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_TWO}, + {"safeBrowsingEnhancedBulThree", + IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_THREE}, + {"safeBrowsingEnhancedBulFour", + IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_FOUR}, + {"safeBrowsingEnhancedBulFive", + IDS_SETTINGS_SAFEBROWSING_ENHANCED_BULLET_FIVE}, + {"safeBrowsingStandard", IDS_SETTINGS_SAFEBROWSING_STANDARD}, + {"safeBrowsingStandardDesc", IDS_SETTINGS_SAFEBROWSING_STANDARD_DESC}, + {"safeBrowsingStandardExpandA11yLabel", + IDS_SETTINGS_SAFEBROWSING_STANDARD_EXPAND_ACCESSIBILITY_LABEL}, + {"safeBrowsingStandardBulOne", + IDS_SETTINGS_SAFEBROWSING_STANDARD_BULLET_ONE}, + {"safeBrowsingStandardBulTwo", + IDS_SETTINGS_SAFEBROWSING_STANDARD_BULLET_TWO}, + {"safeBrowsingStandardReportingLabel", + IDS_SETTINGS_SAFEBROWSING_STANDARD_HELP_IMPROVE}, + {"safeBrowsingNone", IDS_SETTINGS_SAFEBROWSING_NONE}, + {"safeBrowsingNoneDesc", IDS_SETTINGS_SAFEBROWSING_NONE_DESC}, + {"safeBrowsingDisableDialog", + IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_TITLE}, + {"safeBrowsingDisableDialogDesc", + IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_DESC}, + {"safeBrowsingDisableDialogConfirm", + IDS_SETTINGS_SAFEBROWSING_DISABLE_DIALOG_CONFIRM}, + {"safeBrowsingEnableProtection", + IDS_SETTINGS_SAFEBROWSING_ENABLEPROTECTION}, + {"safeBrowsingEnableProtectionDesc", + IDS_SETTINGS_SAFEBROWSING_ENABLEPROTECTION_DESC}, + {"safeBrowsingSectionLabel", IDS_SETTINGS_SAFEBROWSING_SECTION_LABEL}, + {"syncAndGoogleServicesPrivacyDescription", + IDS_SETTINGS_SYNC_AND_GOOGLE_SERVICES_PRIVACY_DESC_UNIFIED_CONSENT}, + {"urlKeyedAnonymizedDataCollection", + IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION}, + {"urlKeyedAnonymizedDataCollectionDesc", + IDS_SETTINGS_ENABLE_URL_KEYED_ANONYMIZED_DATA_COLLECTION_DESC}, + {"noRecentPermissions", IDS_SETTINGS_RECENT_PERMISSIONS_NO_CHANGES}, + {"recentPermissionAllowedOneItem", + IDS_SETTINGS_RECENT_PERMISSIONS_ALLOWED_ONE_ITEM}, + {"recentPermissionAllowedTwoItems", + IDS_SETTINGS_RECENT_PERMISSIONS_ALLOWED_TWO_ITEMS}, + {"recentPermissionAllowedMoreThanTwoItems", + IDS_SETTINGS_RECENT_PERMISSIONS_ALLOWED_MORE_THAN_TWO_ITEMS}, + {"recentPermissionAutoBlockedOneItem", + IDS_SETTINGS_RECENT_PERMISSIONS_AUTOMATICALLY_BLOCKED_ONE_ITEM}, + {"recentPermissionAutoBlockedTwoItems", + IDS_SETTINGS_RECENT_PERMISSIONS_AUTOMATICALLY_BLOCKED_TWO_ITEMS}, + {"recentPermissionAutoBlockedMoreThanTwoItems", + IDS_SETTINGS_RECENT_PERMISSIONS_AUTOMATICALLY_BLOCKED_MORE_THAN_TWO_ITEMS}, + {"recentPermissionBlockedOneItem", + IDS_SETTINGS_RECENT_PERMISSIONS_BLOCKED_ONE_ITEM}, + {"recentPermissionBlockedTwoItems", + IDS_SETTINGS_RECENT_PERMISSIONS_BLOCKED_TWO_ITEMS}, + {"recentPermissionBlockedMoreThanTwoItems", + IDS_SETTINGS_RECENT_PERMISSIONS_BLOCKED_MORE_THAN_TWO_ITEMS}, + {"networkPredictionEnabled", IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_LABEL}, + {"networkPredictionEnabledDesc", + IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESC}, + {"networkPredictionEnabledDescCookiesPage", + IDS_SETTINGS_NETWORK_PREDICTION_ENABLED_DESC_COOKIES_PAGE}, +#if BUILDFLAG(IS_CHROMEOS_ASH) + {"openChromeOSSecureDnsSettingsLabel", + IDS_SETTINGS_SECURE_DNS_OPEN_CHROME_OS_SETTINGS_LABEL}, +#endif }; html_source->AddLocalizedStrings(kLocalizedStrings); @@ -1427,8 +1487,22 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, html_source->AddBoolean( "driveSuggestAvailable", base::FeatureList::IsEnabled(omnibox::kDocumentProvider)); + + bool show_secure_dns = IsSecureDnsAvailable(); + bool link_secure_dns = ShouldLinkSecureDnsOsSettings(); html_source->AddBoolean("showSecureDnsSetting", - features::kDnsOverHttpsShowUiParam.Get()); + show_secure_dns && !link_secure_dns); +#if BUILDFLAG(IS_CHROMEOS_ASH) + html_source->AddBoolean("showSecureDnsSettingLink", + show_secure_dns && link_secure_dns); + html_source->AddString( + "chromeOSPrivacyAndSecuritySectionPath", + chromeos::settings::mojom::kPrivacyAndSecuritySectionPath); +#endif + + html_source->AddBoolean( + "showHttpsOnlyModeSetting", + base::FeatureList::IsEnabled(features::kHttpsOnlyMode)); // The link to the Advanced Protection Program landing page, with a referrer // from Chrome settings. @@ -1444,6 +1518,7 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, advanced_protection_url.spec()); AddPersonalizationOptionsStrings(html_source); + AddSecureDnsStrings(html_source); } void AddPrivacySandboxStrings(content::WebUIDataSource* html_source, @@ -1546,6 +1621,43 @@ void AddPrivacySandboxStrings(content::WebUIDataSource* html_source, } } +void AddPrivacyReviewStrings(content::WebUIDataSource* html_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"privacyReviewLabel", IDS_SETTINGS_PRIVACY_REVIEW_LABEL}, + {"privacyReviewSublabel", IDS_SETTINGS_PRIVACY_REVIEW_SUBLABEL}, + {"privacyReviewPromoTitle", IDS_SETTINGS_PRIVACY_REVIEW_PROMO_TITLE}, + {"privacyReviewPromoBody", IDS_SETTINGS_PRIVACY_REVIEW_PROMO_BODY}, + {"privacyReviewPromoStartButton", + IDS_SETTINGS_PRIVACY_REVIEW_PROMO_START_BUTTON}, + {"privacyReviewNextButton", IDS_SETTINGS_PRIVACY_REVIEW_NEXT_BUTTON}, + {"privacyReviewFeatureDescriptionHeader", + IDS_SETTINGS_PRIVACY_REVIEW_FEATURE_DESCRIPTION_HEADER}, + {"privacyReviewWhatYouShareWithGoogle", + IDS_SETTINGS_PRIVACY_REVIEW_WHAT_YOU_SHARE_WITH_GOOGLE}, + {"privacyReviewWelcomeCardHeader", + IDS_SETTINGS_PRIVACY_REVIEW_WELCOME_CARD_HEADER}, + {"privacyReviewWelcomeCardStartButton", + IDS_SETTINGS_PRIVACY_REVIEW_WELCOME_CARD_START_BUTTON}, + {"privacyReviewCompletionCardHeader", + IDS_SETTINGS_PRIVACY_REVIEW_COMPLETION_CARD_HEADER}, + {"privacyReviewCompletionCardLeaveButton", + IDS_SETTINGS_PRIVACY_REVIEW_COMPLETION_CARD_LEAVE_BUTTON}, + {"privacyReviewMsbbCardHeader", + IDS_SETTINGS_PRIVACY_REVIEW_MSBB_CARD_HEADER}, + {"privacyReviewMsbbFeatureDescription1", + IDS_SETTINGS_PRIVACY_REVIEW_MSBB_FEATURE_DESCRIPTION1}, + {"privacyReviewMsbbFeatureDescription2", + IDS_SETTINGS_PRIVACY_REVIEW_MSBB_FEATURE_DESCRIPTION2}, + {"privacyReviewMsbbFeatureDescription3", + IDS_SETTINGS_PRIVACY_REVIEW_MSBB_FEATURE_DESCRIPTION3}, + {"privacyReviewMsbbPrivacyDescription1", + IDS_SETTINGS_PRIVACY_REVIEW_MSBB_PRIVACY_DESCRIPTION1}, + {"privacyReviewMsbbPrivacyDescription2", + IDS_SETTINGS_PRIVACY_REVIEW_MSBB_PRIVACY_DESCRIPTION2}, + }; + html_source->AddLocalizedStrings(kLocalizedStrings); +} + void AddSafetyCheckStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"safetyCheckSectionTitle", IDS_SETTINGS_SAFETY_CHECK_SECTION_TITLE}, @@ -1629,6 +1741,7 @@ void AddSearchEnginesStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_SEARCH_ENGINES_EDIT_SEARCH_ENGINE}, {"searchEngines", IDS_SETTINGS_SEARCH_ENGINES}, {"searchEnginesDefault", IDS_SETTINGS_SEARCH_ENGINES_DEFAULT_ENGINES}, + {"searchEnginesActive", IDS_SETTINGS_SEARCH_ENGINES_YOUR_ENGINES}, {"searchEnginesOther", IDS_SETTINGS_SEARCH_ENGINES_OTHER_ENGINES}, {"searchEnginesNoOtherEngines", IDS_SETTINGS_SEARCH_ENGINES_NO_OTHER_ENGINES}, @@ -1658,6 +1771,9 @@ void AddSearchEnginesStrings(content::WebUIDataSource* html_source) { html_source->AddBoolean( "showKeywordTriggerSetting", base::FeatureList::IsEnabled(omnibox::kKeywordSpaceTriggeringSetting)); + html_source->AddBoolean( + "showActiveSearchEngines", + base::FeatureList::IsEnabled(omnibox::kActiveSearchEngines)); } void AddSiteSettingsStrings(content::WebUIDataSource* html_source, @@ -1847,11 +1963,29 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS}, {"siteSettingsProtectedContentEnable", IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_ENABLE}, + {"siteSettingsProtectedContentDescription", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_DESCRIPTION}, + {"siteSettingsProtectedContentAllowed", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_ALLOWED}, + {"siteSettingsProtectedContentBlocked", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED}, + {"siteSettingsProtectedContentBlockedSubLabel", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED_SUB_LABEL}, #if BUILDFLAG(IS_CHROMEOS_ASH) || defined(OS_WIN) {"siteSettingsProtectedContentIdentifiersExplanation", IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_EXPLANATION}, {"siteSettingsProtectedContentEnableIdentifiers", IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_ENABLE_IDENTIFIERS}, + {"siteSettingsProtectedContentIdentifiersAllowed", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_ALLOWED}, + {"siteSettingsProtectedContentIdentifiersBlocked", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_BLOCKED}, + {"siteSettingsProtectedContentIdentifiersBlockedSubLabel", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_BLOCKED_SUB_LABEL}, + {"siteSettingsProtectedContentIdentifiersAllowedExceptions", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_ALLOWED_EXCEPTIONS}, + {"siteSettingsProtectedContentIdentifiersBlockedExceptions", + IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_IDENTIFIERS_BLOCKED_EXCEPTIONS}, #endif {"siteSettingsPopups", IDS_SETTINGS_SITE_SETTINGS_POPUPS}, {"siteSettingsPopupsMidSentence", @@ -2109,6 +2243,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_CUSTOMIZED_BEHAVIORS}, {"siteSettingsCustomizedBehaviorsDescription", IDS_SETTINGS_SITE_SETTINGS_CUSTOMIZED_BEHAVIORS_DESCRIPTION}, + {"siteSettingsCustomizedBehaviorsDescriptionShort", + IDS_SETTINGS_SITE_SETTINGS_CUSTOMIZED_BEHAVIORS_DESCRIPTION_SHORT}, {"siteSettingsAdsDescription", IDS_SETTINGS_SITE_SETTINGS_ADS_DESCRIPTION}, {"siteSettingsAdsAllowed", IDS_SETTINGS_SITE_SETTINGS_ADS_ALLOWED}, {"siteSettingsAdsBlocked", IDS_SETTINGS_SITE_SETTINGS_ADS_BLOCKED}, @@ -2318,18 +2454,6 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_POPUPS_ALLOWED_EXCEPTIONS}, {"siteSettingsPopupsBlockedExceptions", IDS_SETTINGS_SITE_SETTINGS_POPUPS_BLOCKED_EXCEPTIONS}, - {"siteSettingsProtectedContentDescription", - IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_DESCRIPTION}, - {"siteSettingsProtectedContentAllowed", - IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_ALLOWED}, - {"siteSettingsProtectedContentBlocked", - IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED}, - {"siteSettingsProtectedContentBlockedSubLabel", - IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED_SUB_LABEL}, - {"siteSettingsProtectedContentAllowedExceptions", - IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_ALLOWED_EXCEPTIONS}, - {"siteSettingsProtectedContentBlockedExceptions", - IDS_SETTINGS_SITE_SETTINGS_PROTECTED_CONTENT_BLOCKED_EXCEPTIONS}, {"siteSettingsProtocolHandlersDescription", IDS_SETTINGS_SITE_SETTINGS_PROTOCOL_HANDLERS_DESCRIPTION}, {"siteSettingsProtocolHandlersAllowed", @@ -2665,6 +2789,7 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source, AddOnStartupStrings(html_source); AddPeopleStrings(html_source, profile); AddPrivacySandboxStrings(html_source, profile); + AddPrivacyReviewStrings(html_source); AddPrivacyStrings(html_source, profile); AddSafetyCheckStrings(html_source); AddResetStrings(html_source, profile); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc index 8220f6aa7ea..c0b68c71115 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler_unittest.cc @@ -75,7 +75,7 @@ class ManageProfileHandlerTest : public testing::Test { // Expect a non-empty list of dictionaries containing non-empty strings for // profile avatar icon urls and labels. - EXPECT_FALSE(icons->empty()); + EXPECT_FALSE(icons->GetList().empty()); if (gaia_included) { VerifyGaiaAvatar(icons, gaia_selected); } else { @@ -165,9 +165,10 @@ TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToGaiaAvatar) { } TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultCustomAvatar) { - base::ListValue list_args; - list_args.AppendInteger(15); - handler()->HandleSetProfileIconToDefaultAvatar(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(15); + handler()->HandleSetProfileIconToDefaultAvatar( + &base::Value::AsListValue(list_args)); PrefService* pref_service = profile()->GetPrefs(); EXPECT_EQ(15, pref_service->GetInteger(prefs::kProfileAvatarIndex)); @@ -177,9 +178,10 @@ TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultCustomAvatar) { TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultGenericAvatar) { int generic_avatar_index = profiles::GetPlaceholderAvatarIndex(); - base::ListValue list_args; - list_args.AppendInteger(generic_avatar_index); - handler()->HandleSetProfileIconToDefaultAvatar(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append(generic_avatar_index); + handler()->HandleSetProfileIconToDefaultAvatar( + &base::Value::AsListValue(list_args)); PrefService* pref_service = profile()->GetPrefs(); EXPECT_EQ(generic_avatar_index, @@ -189,9 +191,9 @@ TEST_F(ManageProfileHandlerTest, HandleSetProfileIconToDefaultGenericAvatar) { } TEST_F(ManageProfileHandlerTest, HandleSetProfileName) { - base::ListValue list_args; - list_args.AppendString("New Profile Name"); - handler()->HandleSetProfileName(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append("New Profile Name"); + handler()->HandleSetProfileName(&base::Value::AsListValue(list_args)); PrefService* pref_service = profile()->GetPrefs(); EXPECT_EQ("New Profile Name", pref_service->GetString(prefs::kProfileName)); @@ -204,9 +206,9 @@ TEST_F(ManageProfileHandlerTest, HandleGetAvailableIcons) { EXPECT_EQ(1U, web_ui()->call_data().size()); web_ui()->ClearTrackedCalls(); - base::ListValue list_args_1; - list_args_1.AppendString("get-icons-callback-id"); - handler()->HandleGetAvailableIcons(&list_args_1); + base::Value list_args_1(base::Value::Type::LIST); + list_args_1.Append("get-icons-callback-id"); + handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args_1)); EXPECT_EQ(1U, web_ui()->call_data().size()); @@ -223,9 +225,9 @@ TEST_F(ManageProfileHandlerTest, HandleGetAvailableIconsOldIconSelected) { EXPECT_EQ(1U, web_ui()->call_data().size()); web_ui()->ClearTrackedCalls(); - base::ListValue list_args; - list_args.AppendString("get-icons-callback-id"); - handler()->HandleGetAvailableIcons(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append("get-icons-callback-id"); + handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); @@ -242,9 +244,9 @@ TEST_F(ManageProfileHandlerTest, GetAvailableIconsSignedInProfile) { EXPECT_TRUE(entry()->IsUsingGAIAPicture()); web_ui()->ClearTrackedCalls(); - base::ListValue list_args; - list_args.AppendString("get-icons-callback-id"); - handler()->HandleGetAvailableIcons(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append("get-icons-callback-id"); + handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); @@ -288,9 +290,9 @@ TEST_F(ManageProfileHandlerTest, GetAvailableIconsLocalProfile) { EXPECT_EQ(entry()->GetAvatarIconIndex(), profiles::GetPlaceholderAvatarIndex()); - base::ListValue list_args; - list_args.AppendString("get-icons-callback-id"); - handler()->HandleGetAvailableIcons(&list_args); + base::Value list_args(base::Value::Type::LIST); + list_args.Append("get-icons-callback-id"); + handler()->HandleGetAvailableIcons(&base::Value::AsListValue(list_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc index fc55f424783..056257c287f 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler_browsertest.cc @@ -111,9 +111,8 @@ class SecureDnsHandlerTest : public InProcessBrowserTest { // InProcessBrowserTest: void SetUpInProcessBrowserTestFixture() override { // Initialize user policy. - ON_CALL(provider_, IsInitializationComplete(_)).WillByDefault(Return(true)); - ON_CALL(provider_, IsFirstPolicyLoadComplete(_)) - .WillByDefault(Return(true)); + provider_.SetDefaultReturns(/*is_initialization_complete_return=*/true, + /*is_first_policy_load_complete_return=*/true); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); } @@ -291,10 +290,11 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, OtherPoliciesSet) { // This test makes no assumptions about the country or underlying resolver list. IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownList) { - base::ListValue args; - args.AppendString(kWebUiFunctionName); + base::Value args(base::Value::Type::LIST); + args.Append(kWebUiFunctionName); - web_ui_.HandleReceivedMessage(kGetSecureDnsResolverList, &args); + web_ui_.HandleReceivedMessage(kGetSecureDnsResolverList, + &base::Value::AsListValue(args)); const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data.function_name()); EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString()); @@ -324,11 +324,11 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListChange) { handler_->SetProvidersForTesting(GetDohProviderListForTesting()); base::HistogramTester histograms; - base::ListValue args; - args.AppendString(std::string() /* old_provider */); - args.AppendString( - "https://global1.provider/dns-query{?dns}" /* new_provider */); - web_ui_.HandleReceivedMessage(kRecordUserDropdownInteraction, &args); + base::Value args(base::Value::Type::LIST); + args.Append(std::string() /* old_provider */); + args.Append("https://global1.provider/dns-query{?dns}" /* new_provider */); + web_ui_.HandleReceivedMessage(kRecordUserDropdownInteraction, + &base::Value::AsListValue(args)); const std::string kUmaBase = "Net.DNS.UI.DropdownSelectionEvent"; histograms.ExpectTotalCount(kUmaBase + ".Ignored", 4u); @@ -375,12 +375,13 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsTemplates) { } IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateValid) { - base::ListValue args; - args.AppendString(kWebUiFunctionName); - args.AppendString("https://example.template/dns-query"); + base::Value args(base::Value::Type::LIST); + args.Append(kWebUiFunctionName); + args.Append("https://example.template/dns-query"); base::HistogramTester histograms; - web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, &args); + web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, + &base::Value::AsListValue(args)); const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data.function_name()); EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString()); @@ -395,12 +396,13 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateValid) { } IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateInvalid) { - base::ListValue args; - args.AppendString(kWebUiFunctionName); - args.AppendString("invalid_template"); + base::Value args(base::Value::Type::LIST); + args.Append(kWebUiFunctionName); + args.Append("invalid_template"); base::HistogramTester histograms; - web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, &args); + web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, + &base::Value::AsListValue(args)); const content::TestWebUI::CallData& call_data = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data.function_name()); EXPECT_EQ(kWebUiFunctionName, call_data.arg1()->GetString()); @@ -414,11 +416,12 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateInvalid) { IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) { base::HistogramTester histograms; - base::ListValue args_valid; - args_valid.AppendString(kWebUiFunctionName); - args_valid.AppendString( + base::Value args_valid(base::Value::Type::LIST); + args_valid.Append(kWebUiFunctionName); + args_valid.Append( "https://example1.template/dns https://example2.template/dns-query"); - web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, &args_valid); + web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, + &base::Value::AsListValue(args_valid)); const content::TestWebUI::CallData& call_data_valid = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data_valid.function_name()); @@ -433,10 +436,11 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, MultipleTemplates) { histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", false, 0); histograms.ExpectBucketCount("Net.DNS.UI.ValidationAttemptSuccess", true, 1); - base::ListValue args_invalid; - args_invalid.AppendString(kWebUiFunctionName); - args_invalid.AppendString("invalid_template https://example.template/dns"); - web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, &args_invalid); + base::Value args_invalid(base::Value::Type::LIST); + args_invalid.Append(kWebUiFunctionName); + args_invalid.Append("invalid_template https://example.template/dns"); + web_ui_.HandleReceivedMessage(kParseCustomDnsEntry, + &base::Value::AsListValue(args_invalid)); const content::TestWebUI::CallData& call_data_invalid = *web_ui_.call_data().back(); EXPECT_EQ("cr.webUIResponse", call_data_invalid.function_name()); @@ -461,10 +465,11 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeSuccess) { SingleResult>() /* google_config_result_list */); handler_->SetNetworkContextForTesting(network_context_.get()); base::HistogramTester histograms; - base::ListValue args_valid; - args_valid.AppendString(kWebUiFunctionName); - args_valid.AppendString("https://example.template/dns-query"); - web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid); + base::Value args_valid(base::Value::Type::LIST); + args_valid.Append(kWebUiFunctionName); + args_valid.Append("https://example.template/dns-query"); + web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, + &base::Value::AsListValue(args_valid)); base::RunLoop().RunUntilIdle(); const content::TestWebUI::CallData& call_data_valid = @@ -492,10 +497,11 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeFailure) { SingleResult>() /* google_config_result_list */); handler_->SetNetworkContextForTesting(network_context_.get()); base::HistogramTester histograms; - base::ListValue args_valid; - args_valid.AppendString(kWebUiFunctionName); - args_valid.AppendString("https://example.template/dns-query"); - web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid); + base::Value args_valid(base::Value::Type::LIST); + args_valid.Append(kWebUiFunctionName); + args_valid.Append("https://example.template/dns-query"); + web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, + &base::Value::AsListValue(args_valid)); base::RunLoop().RunUntilIdle(); const content::TestWebUI::CallData& call_data_valid = @@ -524,12 +530,13 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeDebounce) { std::vector<chrome_browser_net::FakeHostResolver:: SingleResult>() /* google_config_result_list */); base::HistogramTester histograms; - base::ListValue args_valid; - args_valid.AppendString(kWebUiFunctionName); - args_valid.AppendString("https://example.template/dns-query"); + base::Value args_valid(base::Value::Type::LIST); + args_valid.Append(kWebUiFunctionName); + args_valid.Append("https://example.template/dns-query"); // Request a probe that will hang. handler_->SetNetworkContextForTesting(network_context_hang.get()); - web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid); + web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, + &base::Value::AsListValue(args_valid)); size_t responses = web_ui_.call_data().size(); base::RunLoop().RunUntilIdle(); // No response yet from the hanging probe. @@ -537,7 +544,8 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateProbeDebounce) { // Request a probe that will fail. handler_->SetNetworkContextForTesting(network_context_fail.get()); - web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, &args_valid); + web_ui_.HandleReceivedMessage(kProbeCustomDnsTemplate, + &base::Value::AsListValue(args_valid)); // The hanging response should now have arrived. EXPECT_EQ(responses + 1, web_ui_.call_data().size()); const content::TestWebUI::CallData& first_response = diff --git a/chromium/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc index 0509d30670e..7bdf6cb2e88 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_startup_pages_handler.cc @@ -105,45 +105,41 @@ void StartupPagesHandler::OnItemsRemoved(int start, int length) { } void StartupPagesHandler::HandleAddStartupPage(const base::ListValue* args) { - CHECK_EQ(2U, args->GetSize()); + const auto& list = args->GetList(); + CHECK_EQ(2U, list.size()); - const base::Value* callback_id; - CHECK(args->Get(0, &callback_id)); - - std::string url_string; - CHECK(args->GetString(1, &url_string)); + const base::Value& callback_id = list[0]; + std::string url_string = list[1].GetString(); GURL url; if (!settings_utils::FixupAndValidateStartupPage(url_string, &url)) { - ResolveJavascriptCallback(*callback_id, base::Value(false)); + ResolveJavascriptCallback(callback_id, base::Value(false)); return; } int row_count = startup_custom_pages_table_model_.RowCount(); - int index; - if (!args->GetInteger(1, &index) || index > row_count) - index = row_count; + int index = row_count; + if (list[1].is_int() && list[1].GetInt() <= row_count) + index = list[1].GetInt(); startup_custom_pages_table_model_.Add(index, url); SaveStartupPagesPref(); - ResolveJavascriptCallback(*callback_id, base::Value(true)); + ResolveJavascriptCallback(callback_id, base::Value(true)); } void StartupPagesHandler::HandleEditStartupPage(const base::ListValue* args) { - CHECK_EQ(args->GetSize(), 3U); - const base::Value* callback_id; - CHECK(args->Get(0, &callback_id)); - int index; - CHECK(args->GetInteger(1, &index)); + const auto& list = args->GetList(); + CHECK_EQ(list.size(), 3U); + const base::Value& callback_id = list[0]; + int index = list[1].GetInt(); if (index < 0 || index > startup_custom_pages_table_model_.RowCount()) { - RejectJavascriptCallback(*callback_id, base::Value()); + RejectJavascriptCallback(callback_id, base::Value()); NOTREACHED(); return; } - std::string url_string; - CHECK(args->GetString(2, &url_string)); + std::string url_string = list[2].GetString(); GURL fixed_url; if (settings_utils::FixupAndValidateStartupPage(url_string, &fixed_url)) { @@ -151,9 +147,9 @@ void StartupPagesHandler::HandleEditStartupPage(const base::ListValue* args) { urls[index] = fixed_url; startup_custom_pages_table_model_.SetURLs(urls); SaveStartupPagesPref(); - ResolveJavascriptCallback(*callback_id, base::Value(true)); + ResolveJavascriptCallback(callback_id, base::Value(true)); } else { - ResolveJavascriptCallback(*callback_id, base::Value(false)); + ResolveJavascriptCallback(callback_id, base::Value(false)); } } @@ -163,11 +159,13 @@ void StartupPagesHandler::HandleOnStartupPrefsPageLoad( } void StartupPagesHandler::HandleRemoveStartupPage(const base::ListValue* args) { - int selected_index; - if (!args->GetInteger(0, &selected_index)) { + const auto& list = args->GetList(); + DCHECK_GE(list.size(), 1u); + if (!list[0].is_int()) { NOTREACHED(); return; } + int selected_index = list[0].GetInt(); if (selected_index < 0 || selected_index >= startup_custom_pages_table_model_.RowCount()) { diff --git a/chromium/chrome/browser/ui/webui/settings/settings_ui.cc b/chromium/chrome/browser/ui/webui/settings/settings_ui.cc index b310471e7e7..66aed92a5ea 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_ui.cc @@ -11,14 +11,14 @@ #include <utility> #include <vector> -#include "ash/public/cpp/ash_features.h" +#include "ash/constants/ash_features.h" #include "base/feature_list.h" #include "base/memory/ptr_util.h" -#include "base/stl_util.h" #include "build/branding_buildflags.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/account_manager_facade_factory.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings.h" #include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h" #include "chrome/browser/profiles/profile.h" @@ -60,7 +60,6 @@ #include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h" #include "chrome/browser/ui/webui/settings/site_settings_handler.h" #include "chrome/browser/ui/webui/webui_util.h" -#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/common/chrome_features.h" @@ -74,7 +73,7 @@ #include "components/password_manager/core/common/password_manager_features.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" -#include "components/safe_browsing/core/features.h" +#include "components/safe_browsing/core/common/features.h" #include "components/signin/public/base/signin_pref_names.h" #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_contents.h" @@ -103,12 +102,10 @@ #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/components/account_manager/account_manager.h" #include "ash/components/account_manager/account_manager_factory.h" #include "ash/constants/ash_features.h" #include "chrome/browser/ash/account_manager/account_manager_util.h" #include "chrome/browser/ash/profiles/profile_helper.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/android_sms/android_sms_app_manager.h" #include "chrome/browser/chromeos/android_sms/android_sms_service_factory.h" @@ -122,6 +119,7 @@ #include "chrome/grit/browser_resources.h" #include "chromeos/components/phonehub/phone_hub_manager.h" #include "chromeos/login/auth/password_visibility_utils.h" +#include "components/account_manager_core/chromeos/account_manager.h" #include "components/arc/arc_util.h" #include "components/user_manager/user.h" #include "ui/base/ui_base_features.h" @@ -140,6 +138,12 @@ #include "chrome/browser/ui/webui/settings/native_certificates_handler.h" #endif // defined(USE_NSS_CERTS) +#if defined(OS_WIN) || defined(OS_MAC) || \ + (defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS)) +#include "chrome/browser/ui/webui/settings/url_handlers_handler.h" +#include "chrome/browser/web_applications/components/url_handler_prefs.h" +#endif + namespace settings { // static @@ -152,7 +156,7 @@ void SettingsUI::RegisterProfilePrefs( registry->RegisterBooleanPref(prefs::kImportDialogSearchEngine, true); } -web_app::AppRegistrar& GetRegistrarForProfile(Profile* profile) { +web_app::WebAppRegistrar& GetRegistrarForProfile(Profile* profile) { return web_app::WebAppProvider::Get(profile)->registrar(); } @@ -248,6 +252,13 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) AddSettingsPageUIHandler(std::make_unique<ChromeCleanupHandler>(profile)); #endif // defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_MAC) || \ + (defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_LACROS)) + AddSettingsPageUIHandler(std::make_unique<UrlHandlersHandler>( + g_browser_process->local_state(), profile, + &GetRegistrarForProfile(profile))); +#endif + #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING) bool has_incompatible_applications = IncompatibleApplicationsUpdater::HasCachedApplications(); @@ -268,6 +279,12 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) html_source->AddBoolean("enableLandingPageRedesign", enable_landing_page_redesign); + html_source->AddString( + "enableBrandingUpdateAttribute", + base::FeatureList::IsEnabled(features::kWebUIBrandingUpdate) + ? "enable-branding-update" + : ""); + html_source->AddBoolean("signinAllowed", !profile->IsGuestSession() && profile->GetPrefs()->GetBoolean( prefs::kSigninAllowed)); @@ -277,11 +294,6 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) password_manager::features::kPasswordImport)); html_source->AddBoolean( - "enableAccountStorage", - base::FeatureList::IsEnabled( - password_manager::features::kEnablePasswordsAccountStorage)); - - html_source->AddBoolean( "enableMovingMultiplePasswordsToAccount", base::FeatureList::IsEnabled( password_manager::features::kEnableMovingMultiplePasswordsToAccount)); @@ -311,8 +323,16 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) #endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS) #if BUILDFLAG(IS_CHROMEOS_ASH) + // TODO(https://crbug.com/1227694): Remove this after migrating all JS usages + // of splitSettingsSyncEnabled to syncSettingsCategorizationEnabled and + // syncConsentOptionalEnabled. html_source->AddBoolean("splitSettingsSyncEnabled", chromeos::features::IsSplitSettingsSyncEnabled()); + html_source->AddBoolean( + "syncSettingsCategorizationEnabled", + chromeos::features::IsSyncSettingsCategorizationEnabled()); + html_source->AddBoolean("syncConsentOptionalEnabled", + chromeos::features::IsSyncConsentOptionalEnabled()); html_source->AddBoolean("useBrowserSyncConsent", chromeos::features::ShouldUseBrowserSyncConsent()); @@ -331,6 +351,10 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) "safetyCheckWeakPasswordsEnabled", base::FeatureList::IsEnabled(features::kSafetyCheckWeakPasswords)); + html_source->AddBoolean( + "privacyReviewEnabled", + base::FeatureList::IsEnabled(features::kPrivacyReview)); + AddSettingsPageUIHandler(std::make_unique<AboutHandler>(profile)); AddSettingsPageUIHandler(std::make_unique<ResetSettingsHandler>(profile)); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc index bde9f8e8a3c..5ca2f79bcb6 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_ui_browsertest.cc @@ -54,7 +54,7 @@ IN_PROC_BROWSER_TEST_F(SettingsUITest, TriggerHappinessTrackingSurveys) { HatsServiceFactory::GetInstance()->SetTestingFactoryAndUse( browser()->profile(), base::BindRepeating(&BuildMockHatsService))); EXPECT_CALL(*mock_hats_service_, LaunchDelayedSurveyForWebContents( - kHatsSurveyTriggerSettings, _, _, _)); + kHatsSurveyTriggerSettings, _, _, _, _)); NavigateToURL(browser(), GURL(chrome::kChromeUISettingsURL)); base::RunLoop().RunUntilIdle(); } diff --git a/chromium/chrome/browser/ui/webui/settings/settings_utils.cc b/chromium/chrome/browser/ui/webui/settings/settings_utils.cc index 63454ec5057..1349dc1b3eb 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_utils.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_utils.cc @@ -24,13 +24,14 @@ bool FixupAndValidateStartupPage(const std::string& url_string, return valid; } -base::RefCountedMemory* GetFaviconResourceBytes(ui::ScaleFactor scale_factor) { +base::RefCountedMemory* GetFaviconResourceBytes( + ui::ResourceScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( IDR_SETTINGS_FAVICON, scale_factor); } base::RefCountedMemory* GetPrivacySandboxFaviconResourceBytes( - ui::ScaleFactor scale_factor) { + ui::ResourceScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( IDR_FLAGS_FAVICON, scale_factor); } diff --git a/chromium/chrome/browser/ui/webui/settings/settings_utils.h b/chromium/chrome/browser/ui/webui/settings/settings_utils.h index 0c7e77d3373..b52c9b7f1e7 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_utils.h +++ b/chromium/chrome/browser/ui/webui/settings/settings_utils.h @@ -36,10 +36,11 @@ void ShowManageSSLCertificates(content::WebContents* web_contents); bool FixupAndValidateStartupPage(const std::string& url_string, GURL* fixed_url); -base::RefCountedMemory* GetFaviconResourceBytes(ui::ScaleFactor scale_factor); +base::RefCountedMemory* GetFaviconResourceBytes( + ui::ResourceScaleFactor scale_factor); base::RefCountedMemory* GetPrivacySandboxFaviconResourceBytes( - ui::ScaleFactor scale_factor); + ui::ResourceScaleFactor scale_factor); #if defined(OS_MAC) void ValidateSavedFonts(PrefService* prefs); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_utils_fuchsia.cc b/chromium/chrome/browser/ui/webui/settings/settings_utils_fuchsia.cc new file mode 100644 index 00000000000..4f9a345aada --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/settings_utils_fuchsia.cc @@ -0,0 +1,16 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/settings_utils.h" + +#include "base/notreached.h" + +namespace settings_utils { + +void ShowNetworkProxySettings(content::WebContents* web_contents) { + // TODO(crbug.com/1234748) + NOTIMPLEMENTED_LOG_ONCE(); +} + +} // namespace settings_utils diff --git a/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc index 9625bff827b..378e6eea9ff 100644 --- a/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc +++ b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.cc @@ -22,6 +22,7 @@ #include "components/google/core/common/google_util.h" #include "components/soda/constants.h" #include "components/strings/grit/components_strings.h" +#include "components/sync/driver/sync_driver_switches.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_features.h" @@ -31,6 +32,7 @@ #include "ui/base/webui/web_ui_util.h" #include "ui/chromeos/devicetype_utils.h" #if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chrome/browser/ash/crosapi/browser_util.h" #include "chrome/browser/nearby_sharing/common/nearby_share_features.h" #include "chrome/common/url_constants.h" #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -50,6 +52,25 @@ std::u16string GetHelpUrlWithBoard(const std::string& original_url) { } // namespace #endif +#if BUILDFLAG(IS_CHROMEOS_ASH) +bool ShouldShowLacrosSideBySideWarningInAsh() { + return base::FeatureList::IsEnabled( + switches::kSyncSettingsShowLacrosSideBySideWarning) && + crosapi::browser_util::IsAshWebBrowserEnabled() && + crosapi::browser_util::IsLacrosEnabled(); +} +#endif + +#if BUILDFLAG(IS_CHROMEOS_LACROS) +bool ShouldShowLacrosSideBySideWarningInLacros() { + // TODO(crbug.com/1221498): determine whether Lacros is enabled in + // side-by-side mode (needs exposure of LacrosLaunchSwitch by Ash into + // Lacros). + return base::FeatureList::IsEnabled( + switches::kSyncSettingsShowLacrosSideBySideWarning); +} +#endif + void AddCaptionSubpageStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"captionsTitle", IDS_SETTINGS_CAPTIONS}, @@ -223,40 +244,51 @@ void AddPasswordPromptDialogStrings(content::WebUIDataSource* html_source) { void AddSyncPageStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { - {"syncDisabledByAdministrator", - IDS_SIGNED_IN_WITH_SYNC_DISABLED_BY_POLICY}, - {"passwordsCheckboxLabel", IDS_SETTINGS_PASSWORDS_CHECKBOX_LABEL}, - {"passphrasePlaceholder", IDS_SETTINGS_PASSPHRASE_PLACEHOLDER}, - {"peopleSignInSyncPagePromptSecondaryWithAccount", - IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT}, - {"peopleSignInSyncPagePromptSecondaryWithNoAccount", - IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT}, - {"existingPassphraseTitle", IDS_SETTINGS_EXISTING_PASSPHRASE_TITLE}, - {"submitPassphraseButton", IDS_SETTINGS_SUBMIT_PASSPHRASE}, - {"encryptWithGoogleCredentialsLabel", - IDS_SETTINGS_ENCRYPT_WITH_GOOGLE_CREDENTIALS_LABEL}, - {"bookmarksCheckboxLabel", IDS_SETTINGS_BOOKMARKS_CHECKBOX_LABEL}, - {"encryptionOptionsTitle", IDS_SETTINGS_ENCRYPTION_OPTIONS}, - {"mismatchedPassphraseError", IDS_SETTINGS_MISMATCHED_PASSPHRASE_ERROR}, - {"emptyPassphraseError", IDS_SETTINGS_EMPTY_PASSPHRASE_ERROR}, - {"incorrectPassphraseError", IDS_SETTINGS_INCORRECT_PASSPHRASE_ERROR}, - {"syncPageTitle", IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES}, - {"passphraseConfirmationPlaceholder", - IDS_SETTINGS_PASSPHRASE_CONFIRMATION_PLACEHOLDER}, - {"readingListCheckboxLabel", IDS_SETTINGS_READING_LIST_CHECKBOX_LABEL}, - {"syncLoading", IDS_SETTINGS_SYNC_LOADING}, - {"themesAndWallpapersCheckboxLabel", - IDS_SETTINGS_THEMES_AND_WALLPAPERS_CHECKBOX_LABEL}, - {"syncDataEncryptedText", IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT}, - {"sync", IDS_SETTINGS_SYNC}, - {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC}, - {"syncSetupCancelDialogTitle", - IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_TITLE}, - {"syncSetupCancelDialogBody", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_BODY}, - {"personalizeGoogleServicesTitle", - IDS_SETTINGS_PERSONALIZE_GOOGLE_SERVICES_TITLE}, - {"manageSyncedDataTitle", - IDS_SETTINGS_NEW_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT}, + {"syncDisabledByAdministrator", IDS_SIGNED_IN_WITH_SYNC_DISABLED_BY_POLICY}, + {"passwordsCheckboxLabel", IDS_SETTINGS_PASSWORDS_CHECKBOX_LABEL}, + {"passphrasePlaceholder", IDS_SETTINGS_PASSPHRASE_PLACEHOLDER}, + {"peopleSignInSyncPagePromptSecondaryWithAccount", + IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT}, + {"peopleSignInSyncPagePromptSecondaryWithNoAccount", + IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT}, + {"existingPassphraseTitle", IDS_SETTINGS_EXISTING_PASSPHRASE_TITLE}, + {"submitPassphraseButton", IDS_SETTINGS_SUBMIT_PASSPHRASE}, + {"encryptWithGoogleCredentialsLabel", + IDS_SETTINGS_ENCRYPT_WITH_GOOGLE_CREDENTIALS_LABEL}, + {"bookmarksCheckboxLabel", IDS_SETTINGS_BOOKMARKS_CHECKBOX_LABEL}, + {"encryptionOptionsTitle", IDS_SETTINGS_ENCRYPTION_OPTIONS}, + {"mismatchedPassphraseError", IDS_SETTINGS_MISMATCHED_PASSPHRASE_ERROR}, + {"emptyPassphraseError", IDS_SETTINGS_EMPTY_PASSPHRASE_ERROR}, + {"incorrectPassphraseError", IDS_SETTINGS_INCORRECT_PASSPHRASE_ERROR}, + {"syncPageTitle", IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES}, + {"passphraseConfirmationPlaceholder", + IDS_SETTINGS_PASSPHRASE_CONFIRMATION_PLACEHOLDER}, + {"readingListCheckboxLabel", IDS_SETTINGS_READING_LIST_CHECKBOX_LABEL}, + {"syncLoading", IDS_SETTINGS_SYNC_LOADING}, + {"themesAndWallpapersCheckboxLabel", + IDS_SETTINGS_THEMES_AND_WALLPAPERS_CHECKBOX_LABEL}, + {"syncDataEncryptedText", IDS_SETTINGS_SYNC_DATA_ENCRYPTED_TEXT}, + {"sync", IDS_SETTINGS_SYNC}, + {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC}, + {"syncSetupCancelDialogTitle", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_TITLE}, + {"syncSetupCancelDialogBody", IDS_SETTINGS_SYNC_SETUP_CANCEL_DIALOG_BODY}, + {"personalizeGoogleServicesTitle", + IDS_SETTINGS_PERSONALIZE_GOOGLE_SERVICES_TITLE}, + {"manageSyncedDataTitle", + IDS_SETTINGS_NEW_MANAGE_SYNCED_DATA_TITLE_UNIFIED_CONSENT}, + {"enterPassphraseLabel", IDS_SYNC_ENTER_PASSPHRASE_BODY}, + {"enterPassphraseLabelWithDate", IDS_SYNC_ENTER_PASSPHRASE_BODY_WITH_DATE}, + {"existingPassphraseLabelWithDate", + IDS_SYNC_FULL_ENCRYPTION_BODY_CUSTOM_WITH_DATE}, + {"existingPassphraseLabel", IDS_SYNC_FULL_ENCRYPTION_BODY_CUSTOM}, + // Settings warning for Lacros side-by-side mode. +#if BUILDFLAG(IS_CHROMEOS_ASH) + {"syncSettingsLacrosSideBySideWarning", + IDS_SYNC_SETTINGS_SIDE_BY_SIDE_WARNING_ASH}, +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + {"syncSettingsLacrosSideBySideWarning", + IDS_SYNC_SETTINGS_SIDE_BY_SIDE_WARNING_LACROS}, +#endif }; html_source->AddLocalizedStrings(kLocalizedStrings); @@ -290,6 +322,14 @@ void AddSyncPageStrings(content::WebUIDataSource* html_source) { #else base::ASCIIToUTF16(chrome::kSyncEncryptionHelpURL))); #endif +#if BUILDFLAG(IS_CHROMEOS_ASH) + html_source->AddBoolean("shouldShowLacrosSideBySideWarning", + ShouldShowLacrosSideBySideWarningInAsh()); +#elif BUILDFLAG(IS_CHROMEOS_LACROS) + html_source->AddBoolean("shouldShowLacrosSideBySideWarning", + ShouldShowLacrosSideBySideWarningInLacros()); +#endif + html_source->AddString("syncErrorsHelpUrl", chrome::kSyncErrorsHelpURL); } #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -365,4 +405,34 @@ void AddNearbyShareData(content::WebUIDataSource* html_source) { } #endif // BUILDFLAG(IS_CHROMEOS_ASH) +void AddSecureDnsStrings(content::WebUIDataSource* html_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"secureDns", IDS_SETTINGS_SECURE_DNS}, + {"secureDnsDescription", IDS_SETTINGS_SECURE_DNS_DESCRIPTION}, + {"secureDnsDisabledForManagedEnvironment", + IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_MANAGED_ENVIRONMENT}, + {"secureDnsDisabledForParentalControl", + IDS_SETTINGS_SECURE_DNS_DISABLED_FOR_PARENTAL_CONTROL}, + {"secureDnsAutomaticModeDescription", + IDS_SETTINGS_AUTOMATIC_MODE_DESCRIPTION}, + {"secureDnsAutomaticModeDescriptionSecondary", + IDS_SETTINGS_AUTOMATIC_MODE_DESCRIPTION_SECONDARY}, + {"secureDnsSecureModeA11yLabel", + IDS_SETTINGS_SECURE_MODE_DESCRIPTION_ACCESSIBILITY_LABEL}, + {"secureDnsDropdownA11yLabel", + IDS_SETTINGS_SECURE_DNS_DROPDOWN_ACCESSIBILITY_LABEL}, + {"secureDnsSecureDropdownModeDescription", + IDS_SETTINGS_SECURE_DROPDOWN_MODE_DESCRIPTION}, + {"secureDnsSecureDropdownModePrivacyPolicy", + IDS_SETTINGS_SECURE_DROPDOWN_MODE_PRIVACY_POLICY}, + {"secureDnsCustomPlaceholder", + IDS_SETTINGS_SECURE_DNS_CUSTOM_PLACEHOLDER}, + {"secureDnsCustomFormatError", + IDS_SETTINGS_SECURE_DNS_CUSTOM_FORMAT_ERROR}, + {"secureDnsCustomConnectionError", + IDS_SETTINGS_SECURE_DNS_CUSTOM_CONNECTION_ERROR}, + }; + html_source->AddLocalizedStrings(kLocalizedStrings); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h index b05355d9f25..7fcfceff8cf 100644 --- a/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h +++ b/chromium/chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h @@ -41,6 +41,8 @@ void AddSyncPageStrings(content::WebUIDataSource* html_source); void AddNearbyShareData(content::WebUIDataSource* html_source); #endif // BUILDFLAG(IS_CHROMEOS_ASH) +// Adds strings used by the <settings-secure-dns> element. +void AddSecureDnsStrings(content::WebUIDataSource* html_source); } // namespace settings #endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_SHARED_SETTINGS_LOCALIZED_STRINGS_PROVIDER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc index 918e662ffe1..e2bf79a59ef 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc @@ -161,7 +161,7 @@ void AddExceptionsGrantedByHostedApps(content::BrowserContext* context, base::flat_set<std::string> GetInstalledAppOrigins( Profile* profile, - const web_app::AppRegistrar& registrar) { + const web_app::WebAppRegistrar& registrar) { base::flat_set<std::string> origins; for (const web_app::AppId& app : registrar.GetAppIds()) origins.insert(registrar.GetAppScope(app).GetOrigin().spec()); @@ -234,7 +234,7 @@ void ConvertSiteGroupMapToListValue( const std::set<std::string>& origin_permission_set, base::Value* list_value, Profile* profile, - const web_app::AppRegistrar& registrar) { + const web_app::WebAppRegistrar& registrar) { DCHECK_EQ(base::Value::Type::LIST, list_value->type()); DCHECK(profile); base::flat_set<std::string> installed_origins = @@ -390,8 +390,9 @@ std::string GetCookieSettingDescription(Profile* profile) { } // namespace -SiteSettingsHandler::SiteSettingsHandler(Profile* profile, - web_app::AppRegistrar& app_registrar) +SiteSettingsHandler::SiteSettingsHandler( + Profile* profile, + web_app::WebAppRegistrar& app_registrar) : profile_(profile), app_registrar_(app_registrar) {} SiteSettingsHandler::~SiteSettingsHandler() { @@ -422,6 +423,10 @@ void SiteSettingsHandler::RegisterMessages() { base::BindRepeating(&SiteSettingsHandler::HandleGetAllSites, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "getCategoryList", + base::BindRepeating(&SiteSettingsHandler::HandleGetCategoryList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "getCookieSettingDescription", base::BindRepeating( &SiteSettingsHandler::HandleGetCookieSettingDescription, @@ -730,15 +735,12 @@ void SiteSettingsHandler::HandleGetDefaultValueForContentType( void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { AllowJavascript(); - CHECK_EQ(2U, args->GetList().size()); + CHECK_EQ(1U, args->GetList().size()); std::string callback_id = args->GetList()[0].GetString(); - auto types = args->GetList()[1].GetList(); all_sites_map_.clear(); origin_permission_set_.clear(); - auto content_types = site_settings::ContentSettingsTypesFromGroupNames(types); - // Incognito contains incognito content settings plus non-incognito content // settings. Thus if it exists, just get exceptions for the incognito profile. Profile* profile = profile_; @@ -750,6 +752,12 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { HostContentSettingsMap* map = HostContentSettingsMapFactory::GetForProfile(profile); + std::vector<ContentSettingsType> content_types = + site_settings::GetVisiblePermissionCategories(); + // Make sure to include cookies, because All Sites handles data storage + // cookies as well as regular ContentSettingsTypes. + content_types.push_back(ContentSettingsType::COOKIES); + // Retrieve a list of embargoed settings to check separately. This ensures // that only settings included in |content_types| will be listed in all sites. auto* autoblocker = @@ -792,6 +800,24 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { ResolveJavascriptCallback(base::Value(callback_id), result); } +void SiteSettingsHandler::HandleGetCategoryList(const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(2U, args->GetList().size()); + std::string callback_id = args->GetList()[0].GetString(); + GURL origin(args->GetList()[1].GetString()); + + std::vector<ContentSettingsType> content_types = + site_settings::GetVisiblePermissionCategoriesForOrigin(profile_, origin); + + base::Value result(base::Value::Type::LIST); + for (ContentSettingsType content_type : content_types) { + result.Append(site_settings::ContentSettingsTypeToGroupName(content_type)); + } + + ResolveJavascriptCallback(base::Value(callback_id), result); +} + void SiteSettingsHandler::HandleGetCookieSettingDescription( const base::ListValue* args) { AllowJavascript(); @@ -805,12 +831,12 @@ void SiteSettingsHandler::HandleGetRecentSitePermissions( const base::ListValue* args) { AllowJavascript(); - CHECK_EQ(3U, args->GetList().size()); + CHECK_EQ(2U, args->GetList().size()); std::string callback_id = args->GetList()[0].GetString(); - auto types = args->GetList()[1].GetList(); - size_t max_sources = base::checked_cast<size_t>(args->GetList()[2].GetInt()); + size_t max_sources = base::checked_cast<size_t>(args->GetList()[1].GetInt()); - auto content_types = site_settings::ContentSettingsTypesFromGroupNames(types); + const std::vector<ContentSettingsType>& content_types = + site_settings::GetVisiblePermissionCategories(); auto recent_site_permissions = site_settings::GetRecentSitePermissions( profile_, content_types, max_sources); @@ -900,15 +926,11 @@ void SiteSettingsHandler::OnStorageFetched() { void SiteSettingsHandler::HandleGetFormattedBytes(const base::ListValue* args) { AllowJavascript(); - - CHECK_EQ(2U, args->GetSize()); - const base::Value* callback_id; - CHECK(args->Get(0, &callback_id)); - double num_bytes; - CHECK(args->GetDouble(1, &num_bytes)); - - const std::u16string string = ui::FormatBytes(int64_t(num_bytes)); - ResolveJavascriptCallback(*callback_id, base::Value(string)); + base::Value::ConstListView list = args->GetList(); + CHECK_EQ(2U, list.size()); + int64_t num_bytes = static_cast<int64_t>(list[1].GetDouble()); + ResolveJavascriptCallback(/*callback_id=*/list[0], + base::Value(ui::FormatBytes(num_bytes))); } void SiteSettingsHandler::HandleGetExceptionList(const base::ListValue* args) { @@ -969,20 +991,21 @@ void SiteSettingsHandler::HandleGetOriginPermissions( const base::ListValue* args) { AllowJavascript(); - CHECK_EQ(3U, args->GetSize()); - const base::Value* callback_id; - CHECK(args->Get(0, &callback_id)); - std::string origin; - CHECK(args->GetString(1, &origin)); - const base::ListValue* types; - CHECK(args->GetList(2, &types)); + base::Value::ConstListView args_list = args->GetList(); + CHECK_EQ(3U, args_list.size()); + const base::Value& callback_id = args_list[0]; + std::string origin = args_list[1].GetString(); + base::Value::ConstListView types = args_list[2].GetList(); // Note: Invalid URLs will just result in default settings being shown. const GURL origin_url(origin); - auto exceptions = std::make_unique<base::ListValue>(); - for (size_t i = 0; i < types->GetSize(); ++i) { + base::Value exceptions(base::Value::Type::LIST); + for (const auto& type_val : types) { std::string type; - types->GetString(i, &type); + DCHECK(type_val.is_string()); + const std::string* maybe_type = type_val.GetIfString(); + if (maybe_type) + type = *maybe_type; ContentSettingsType content_type = site_settings::ContentSettingsTypeFromGroupName(type); HostContentSettingsMap* map = @@ -997,50 +1020,50 @@ void SiteSettingsHandler::HandleGetOriginPermissions( std::string content_setting_string = content_settings::ContentSettingToString(content_setting); - auto raw_site_exception = std::make_unique<base::DictionaryValue>(); - raw_site_exception->SetString(site_settings::kEmbeddingOrigin, origin); - raw_site_exception->SetBoolean(site_settings::kIncognito, - profile_->IsOffTheRecord()); - raw_site_exception->SetString(site_settings::kOrigin, origin); - raw_site_exception->SetString(site_settings::kDisplayName, display_name); - raw_site_exception->SetString(site_settings::kSetting, - content_setting_string); - raw_site_exception->SetString(site_settings::kSettingDetail, - content_settings::GetPermissionDetailString( - profile_, content_type, origin_url)); - raw_site_exception->SetString(site_settings::kSource, source_string); - - exceptions->Append(std::move(raw_site_exception)); + base::Value raw_site_exception(base::Value::Type::DICTIONARY); + raw_site_exception.SetStringKey(site_settings::kEmbeddingOrigin, origin); + raw_site_exception.SetBoolKey(site_settings::kIncognito, + profile_->IsOffTheRecord()); + raw_site_exception.SetStringKey(site_settings::kOrigin, origin); + raw_site_exception.SetStringKey(site_settings::kDisplayName, display_name); + raw_site_exception.SetStringKey(site_settings::kSetting, + content_setting_string); + raw_site_exception.SetStringKey(site_settings::kSettingDetail, + content_settings::GetPermissionDetailString( + profile_, content_type, origin_url)); + raw_site_exception.SetStringKey(site_settings::kSource, source_string); + + exceptions.Append(std::move(raw_site_exception)); } - ResolveJavascriptCallback(*callback_id, *exceptions); + ResolveJavascriptCallback(callback_id, exceptions); } void SiteSettingsHandler::HandleSetOriginPermissions( const base::ListValue* args) { CHECK_EQ(3U, args->GetSize()); - std::string origin_string; - CHECK(args->GetString(0, &origin_string)); - const base::ListValue* types; - CHECK(args->GetList(1, &types)); - std::string value; - CHECK(args->GetString(2, &value)); + std::string origin_string = args->GetList()[0].GetString(); + const std::string* type_string = args->GetList()[1].GetIfString(); + std::string value = args->GetList()[2].GetString(); const GURL origin(origin_string); if (!origin.is_valid()) return; + std::vector<ContentSettingsType> types; + if (type_string) { + types.push_back( + site_settings::ContentSettingsTypeFromGroupName(*type_string)); + } else { + types = site_settings::GetVisiblePermissionCategoriesForOrigin(profile_, + origin); + } + ContentSetting setting; CHECK(content_settings::ContentSettingFromString(value, &setting)); - for (size_t i = 0; i < types->GetSize(); ++i) { - std::string type; - types->GetString(i, &type); - - ContentSettingsType content_type = - site_settings::ContentSettingsTypeFromGroupName(type); - HostContentSettingsMap* map = - HostContentSettingsMapFactory::GetForProfile(profile_); - + HostContentSettingsMap* map = + HostContentSettingsMapFactory::GetForProfile(profile_); + for (ContentSettingsType content_type : types) { permissions::PermissionUmaUtil::ScopedRevocationReporter scoped_revocation_reporter( profile_, origin, origin, content_type, @@ -1572,9 +1595,9 @@ void SiteSettingsHandler::HandleClearEtldPlus1DataAndCookies( } void SiteSettingsHandler::HandleRecordAction(const base::ListValue* args) { - CHECK_EQ(1U, args->GetSize()); - int action; - CHECK(args->GetInteger(0, &action)); + const auto& list = args->GetList(); + CHECK_EQ(1U, list.size()); + int action = list[0].GetInt(); DCHECK_LE(action, static_cast<int>(AllSitesAction2::kMaxValue)); DCHECK_GE(action, static_cast<int>(AllSitesAction2::kLoadPage)); diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h index 202503c7433..2e94cd81cbc 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h @@ -10,14 +10,12 @@ #include <set> #include <string> -#include "base/containers/flat_set.h" #include "base/scoped_multi_source_observation.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/browsing_data/cookies_tree_model.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_observer.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" -#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "components/content_settings/core/browser/content_settings_observer.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -44,7 +42,7 @@ class SiteSettingsHandler public CookiesTreeModel::Observer { public: explicit SiteSettingsHandler(Profile* profile, - web_app::AppRegistrar& web_app_registrar); + web_app::WebAppRegistrar& web_app_registrar); ~SiteSettingsHandler() override; // SettingsPageUIHandler: @@ -170,14 +168,20 @@ class SiteSettingsHandler // the front end when fetching finished. void HandleGetAllSites(const base::ListValue* args); + // Returns a list of content settings types that are controlled via a standard + // permissions UI and should be made visible to the user. There is a single + // nullable string argument, which represents an associated origin. See + // `SiteSettingsPrefsBrowserProxy#getCategoryList`. + void HandleGetCategoryList(const base::ListValue* args); + // Returns a string for display describing the current cookie settings. void HandleGetCookieSettingDescription(const base::ListValue* args); // Returns a list containing the most recent permission changes for the - // provided content types grouped by origin/profile (incognito, regular) - // combinations, limited to N origin/profile pairings. This includes - // permission changes made by embargo, but does not include permissions - // enforced via policy. + // content types that are visiblein settings, grouped by origin/profile + // (incognito, regular) combinations, limited to N origin/profile pairings. + // This includes permission changes made by embargo, but does not include + // permissions enforced via policy. void HandleGetRecentSitePermissions(const base::ListValue* args); // Called when the list of origins using storage has been fetched, and sends @@ -261,7 +265,7 @@ class SiteSettingsHandler void SendCookieSettingDescription(); Profile* profile_; - web_app::AppRegistrar& app_registrar_; + web_app::WebAppRegistrar& app_registrar_; base::ScopedMultiSourceObservation<Profile, ProfileObserver> observed_profiles_{this}; diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc index 132d2d6ff3e..6a7143b8631 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc @@ -32,7 +32,8 @@ #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" -#include "chrome/browser/web_applications/test/test_app_registrar.h" +#include "chrome/browser/web_applications/test/test_web_app_registry_controller.h" +#include "chrome/browser/web_applications/web_app.h" #include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/browser_with_test_window_test.h" @@ -65,11 +66,12 @@ #include "ppapi/buildflags/buildflags.h" #include "services/device/public/cpp/test/fake_usb_device_manager.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/storage_key/storage_key.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" #include "ui/webui/webui_allowlist.h" -#if BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) #include "chrome/browser/ash/login/users/mock_user_manager.h" #include "components/user_manager/scoped_user_manager.h" #endif @@ -106,10 +108,6 @@ const struct PatternContentTypeTestCase { {{"http://127.0.0.1", "location"}, {true, ""}}, // Localhost is secure. {{"http://[::1]", "location"}, {true, ""}}}; -std::string GenerateFakeAppId(const GURL& url) { - return web_app::GenerateAppIdFromURL(url); -} - } // namespace namespace settings { @@ -171,17 +169,19 @@ class SiteSettingsHandlerTest : public testing::Test { } void SetUp() override { + test_registry_controller_ = + std::make_unique<web_app::TestWebAppRegistryController>(); + test_registry_controller_->SetUp(profile()); + controller().Init(); + handler_ = - std::make_unique<SiteSettingsHandler>(profile_.get(), app_registrar_); + std::make_unique<SiteSettingsHandler>(profile_.get(), app_registrar()); handler()->set_web_ui(web_ui()); handler()->AllowJavascript(); // AllowJavascript() adds a callback to create leveldb_env::ChromiumEnv // which reads the FeatureList. Wait for the callback to be finished so that // we won't destruct |feature_list_| before the callback is executed. - // We also want to let the storage system finish setting up, to avoid test - // flakiness caused by the quota storage system shutting down at test end, - // while still being set up. - task_environment_.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); web_ui()->ClearTrackedCalls(); } @@ -193,9 +193,27 @@ class SiteSettingsHandlerTest : public testing::Test { } } + std::unique_ptr<web_app::WebApp> CreateWebApp() { + const GURL app_url = GURL("http://abc.example.com/path"); + const web_app::AppId app_id = + web_app::GenerateAppId(/*manifest_id=*/absl::nullopt, app_url); + + auto web_app = std::make_unique<web_app::WebApp>(app_id); + web_app->AddSource(web_app::Source::kSync); + web_app->SetDisplayMode(web_app::DisplayMode::kStandalone); + web_app->SetUserDisplayMode(web_app::DisplayMode::kStandalone); + web_app->SetName("Name"); + web_app->SetStartUrl(app_url); + + return web_app; + } + + web_app::TestWebAppRegistryController& controller() { + return *test_registry_controller_; + } + web_app::WebAppRegistrar& app_registrar() { return controller().registrar(); } TestingProfile* profile() { return profile_.get(); } TestingProfile* incognito_profile() { return incognito_profile_; } - web_app::TestAppRegistrar& app_registrar() { return app_registrar_; } content::TestWebUI* web_ui() { return &web_ui_; } SiteSettingsHandler* handler() { return handler_.get(); } @@ -203,9 +221,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); - std::string event_name; - ASSERT_TRUE(data.arg1()->GetAsString(&event_name)); - EXPECT_EQ("onBlockAutoplayStatusChanged", event_name); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ("onBlockAutoplayStatusChanged", data.arg1()->GetString()); const base::DictionaryValue* event_data = nullptr; ASSERT_TRUE(data.arg2()->GetAsDictionary(&event_data)); @@ -237,9 +254,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); ASSERT_TRUE(data.arg2()->GetBool()); @@ -267,9 +283,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); ASSERT_TRUE(data.arg2()->GetBool()); @@ -301,9 +316,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); ASSERT_TRUE(data.arg2()->GetBool()); @@ -321,9 +335,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ(kCallbackId, callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kCallbackId, data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); ASSERT_TRUE(data.arg2()->GetBool()); @@ -347,9 +360,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ("onIncognitoStatusChanged", callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ("onIncognitoStatusChanged", data.arg1()->GetString()); ASSERT_TRUE(data.arg2()->is_bool()); EXPECT_EQ(expected_incognito, data.arg2()->GetBool()); @@ -363,9 +375,8 @@ class SiteSettingsHandlerTest : public testing::Test { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ("onZoomLevelsChanged", callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ("onZoomLevelsChanged", data.arg1()->GetString()); const base::ListValue* exceptions; ASSERT_TRUE(data.arg2()->GetAsList(&exceptions)); @@ -436,11 +447,15 @@ class SiteSettingsHandlerTest : public testing::Test { auto mock_cookies_tree_model = std::make_unique<CookiesTreeModel>( std::move(container), profile()->GetExtensionSpecialStoragePolicy()); - mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - url::Origin::Create(GURL("https://www.example.com/")), 2); + mock_browsing_data_local_storage_helper->AddLocalStorageForStorageKey( + blink::StorageKey::CreateFromStringForTesting( + "https://www.example.com/"), + 2); - mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin( - url::Origin::Create(GURL("https://www.google.com/")), 50000000000); + mock_browsing_data_local_storage_helper->AddLocalStorageForStorageKey( + blink::StorageKey::CreateFromStringForTesting( + "https://www.google.com/"), + 50000000000); mock_browsing_data_local_storage_helper->Notify(); mock_browsing_data_cookie_helper->AddCookieSamples( @@ -465,8 +480,6 @@ class SiteSettingsHandlerTest : public testing::Test { handler()->ClearAllSitesMapForTesting(); handler()->OnStorageFetched(); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); - std::string callback_id; - data.arg1()->GetAsString(&callback_id); const base::ListValue* storage_and_cookie_list; data.arg2()->GetAsList(&storage_and_cookie_list); return storage_and_cookie_list; @@ -487,7 +500,8 @@ class SiteSettingsHandlerTest : public testing::Test { content::BrowserTaskEnvironment task_environment_; std::unique_ptr<TestingProfile> profile_; TestingProfile* incognito_profile_; - web_app::TestAppRegistrar app_registrar_; + std::unique_ptr<web_app::TestWebAppRegistryController> + test_registry_controller_; content::TestWebUI web_ui_; std::unique_ptr<SiteSettingsHandler> handler_; #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -497,38 +511,38 @@ class SiteSettingsHandlerTest : public testing::Test { TEST_F(SiteSettingsHandlerTest, GetAndSetDefault) { // Test the JS -> C++ -> JS callback path for getting and setting defaults. - base::ListValue get_args; - get_args.AppendString(kCallbackId); - get_args.AppendString(kNotifications); - handler()->HandleGetDefaultValueForContentType(&get_args); + base::Value get_args(base::Value::Type::LIST); + get_args.Append(kCallbackId); + get_args.Append(kNotifications); + handler()->HandleGetDefaultValueForContentType( + &base::Value::AsListValue(get_args)); ValidateDefault(CONTENT_SETTING_ASK, site_settings::SiteSettingSource::kDefault, 1U); // Set the default to 'Blocked'. - base::ListValue set_args; - set_args.AppendString(kNotifications); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - handler()->HandleSetDefaultValueForContentType(&set_args); + handler()->HandleSetDefaultValueForContentType( + &base::Value::AsListValue(set_args)); EXPECT_EQ(2U, web_ui()->call_data().size()); // Verify that the default has been set to 'Blocked'. - handler()->HandleGetDefaultValueForContentType(&get_args); + handler()->HandleGetDefaultValueForContentType( + &base::Value::AsListValue(get_args)); ValidateDefault(CONTENT_SETTING_BLOCK, site_settings::SiteSettingSource::kDefault, 3U); } // Flaky on CrOS and Linux. https://crbug.com/930481 TEST_F(SiteSettingsHandlerTest, GetAllSites) { - base::ListValue get_all_sites_args; - get_all_sites_args.AppendString(kCallbackId); - base::Value category_list(base::Value::Type::LIST); - category_list.Append(kNotifications); - get_all_sites_args.Append(std::move(category_list)); + base::Value get_all_sites_args(base::Value::Type::LIST); + get_all_sites_args.Append(kCallbackId); // Test all sites is empty when there are no preferences. - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); { @@ -550,7 +564,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { url1, url1, ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK); map->SetContentSettingDefaultScope( url2, url2, ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_ALLOW); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -578,7 +592,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { const GURL url3("https://example2.net"); map->SetContentSettingDefaultScope( url3, url3, ContentSettingsType::NOTIFICATIONS, CONTENT_SETTING_BLOCK); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -618,7 +632,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { CONTENT_SETTING_BLOCK, auto_blocker->GetEmbargoResult(url4, ContentSettingsType::NOTIFICATIONS) .content_setting); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -632,7 +646,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { // Check |url4| disappears from the list when its embargo expires. clock.Advance(base::TimeDelta::FromDays(8)); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); @@ -662,7 +676,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { auto_blocker->GetEmbargoResult(url3, ContentSettingsType::NOTIFICATIONS) .content_setting); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -691,7 +705,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { auto_blocker->GetEmbargoResult(url5, ContentSettingsType::NOTIFICATIONS) .content_setting); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -722,11 +736,8 @@ TEST_F(SiteSettingsHandlerTest, GetRecentSitePermissions) { std::string kPreference = SiteSettingSourceToString(site_settings::SiteSettingSource::kPreference); - base::ListValue get_recent_permissions_args; - get_recent_permissions_args.AppendString(kCallbackId); - base::Value category_list(base::Value::Type::LIST); - category_list.Append(kNotifications); - get_recent_permissions_args.Append(std::move(category_list)); + base::Value get_recent_permissions_args(base::Value::Type::LIST); + get_recent_permissions_args.Append(kCallbackId); get_recent_permissions_args.Append(3); // Configure prefs and auto blocker with a controllable clock. @@ -741,7 +752,8 @@ TEST_F(SiteSettingsHandlerTest, GetRecentSitePermissions) { clock.Advance(base::TimeDelta::FromHours(1)); // Test recent permissions is empty when there are no preferences. - handler()->HandleGetRecentSitePermissions(&get_recent_permissions_args); + handler()->HandleGetRecentSitePermissions( + &base::Value::AsListValue(get_recent_permissions_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); { @@ -763,15 +775,11 @@ TEST_F(SiteSettingsHandlerTest, GetRecentSitePermissions) { url1, ContentSettingsType::NOTIFICATIONS, false); clock.Advance(base::TimeDelta::FromHours(2)); - map->SetContentSettingDefaultScope(url2, url2, ContentSettingsType::IMAGES, - CONTENT_SETTING_ALLOW); clock.Advance(base::TimeDelta::FromHours(1)); CreateIncognitoProfile(); HostContentSettingsMap* incognito_map = HostContentSettingsMapFactory::GetForProfile(incognito_profile()); incognito_map->SetClockForTesting(&clock); - incognito_map->SetContentSettingDefaultScope( - url1, url1, ContentSettingsType::IMAGES, CONTENT_SETTING_ALLOW); clock.Advance(base::TimeDelta::FromHours(1)); permissions::PermissionDecisionAutoBlocker* incognito_auto_blocker = @@ -781,7 +789,8 @@ TEST_F(SiteSettingsHandlerTest, GetRecentSitePermissions) { incognito_auto_blocker->RecordDismissAndEmbargo( url1, ContentSettingsType::NOTIFICATIONS, false); - handler()->HandleGetRecentSitePermissions(&get_recent_permissions_args); + handler()->HandleGetRecentSitePermissions( + &base::Value::AsListValue(get_recent_permissions_args)); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -827,9 +836,8 @@ TEST_F(SiteSettingsHandlerTest, OnStorageFetched) { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); - std::string callback_id; - ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); - EXPECT_EQ("onStorageListFetched", callback_id); + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ("onStorageListFetched", data.arg1()->GetString()); const base::ListValue* storage_and_cookie_list; ASSERT_TRUE(data.arg2()->GetAsList(&storage_and_cookie_list)); @@ -906,9 +914,8 @@ TEST_F(SiteSettingsHandlerTest, OnStorageFetched) { } TEST_F(SiteSettingsHandlerTest, InstalledApps) { - web_app::TestAppRegistrar& registrar = app_registrar(); - const GURL url("http://abc.example.com/"); - registrar.AddExternalApp(GenerateFakeAppId(url), {url}); + auto web_app = CreateWebApp(); + controller().RegisterApp(std::move(web_app)); SetUpCookiesTreeModel(); @@ -953,20 +960,22 @@ TEST_F(SiteSettingsHandlerTest, IncognitoExceptions) { CreateIncognitoProfile(); { - base::ListValue set_args; - set_args.AppendString(kOriginToBlock); // Primary pattern. - set_args.AppendString(std::string()); // Secondary pattern. - set_args.AppendString(kNotifications); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(kOriginToBlock); // Primary pattern. + set_args.Append(std::string()); // Secondary pattern. + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_args.AppendBoolean(true); // Incognito. + set_args.Append(true); // Incognito. - handler()->HandleSetCategoryPermissionForPattern(&set_args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(set_args)); - base::ListValue get_exception_list_args; - get_exception_list_args.AppendString(kCallbackId); - get_exception_list_args.AppendString(kNotifications); - handler()->HandleGetExceptionList(&get_exception_list_args); + base::Value get_exception_list_args(base::Value::Type::LIST); + get_exception_list_args.Append(kCallbackId); + get_exception_list_args.Append(kNotifications); + handler()->HandleGetExceptionList( + &base::Value::AsListValue(get_exception_list_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); const base::ListValue* exceptions; @@ -981,20 +990,22 @@ TEST_F(SiteSettingsHandlerTest, IncognitoExceptions) { } { - base::ListValue set_args; - set_args.AppendString(kOriginToBlock); // Primary pattern. - set_args.AppendString(std::string()); // Secondary pattern. - set_args.AppendString(kNotifications); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(kOriginToBlock); // Primary pattern. + set_args.Append(std::string()); // Secondary pattern. + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_args.AppendBoolean(false); // Incognito. + set_args.Append(false); // Incognito. - handler()->HandleSetCategoryPermissionForPattern(&set_args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(set_args)); - base::ListValue get_exception_list_args; - get_exception_list_args.AppendString(kCallbackId); - get_exception_list_args.AppendString(kNotifications); - handler()->HandleGetExceptionList(&get_exception_list_args); + base::Value get_exception_list_args(base::Value::Type::LIST); + get_exception_list_args.Append(kCallbackId); + get_exception_list_args.Append(kNotifications); + handler()->HandleGetExceptionList( + &base::Value::AsListValue(get_exception_list_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); const base::ListValue* exceptions; @@ -1021,15 +1032,16 @@ TEST_F(SiteSettingsHandlerTest, ResetCategoryPermissionForEmbargoedOrigins) { // Add and test 1 blocked origin { - base::ListValue set_args; - set_args.AppendString(kOriginToBlock); // Primary pattern. - set_args.AppendString(std::string()); // Secondary pattern. - set_args.AppendString(kNotifications); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(kOriginToBlock); // Primary pattern. + set_args.Append(std::string()); // Secondary pattern. + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_args.AppendBoolean(false); // Incognito. + set_args.Append(false); // Incognito. - handler()->HandleSetCategoryPermissionForPattern(&set_args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(set_args)); ASSERT_EQ(1U, web_ui()->call_data().size()); } @@ -1063,12 +1075,13 @@ TEST_F(SiteSettingsHandlerTest, ResetCategoryPermissionForEmbargoedOrigins) { { // Reset blocked origin. - base::ListValue reset_args; - reset_args.AppendString(kOriginToBlock); - reset_args.AppendString(std::string()); - reset_args.AppendString(kNotifications); - reset_args.AppendBoolean(false); // Incognito. - handler()->HandleResetCategoryPermissionForPattern(&reset_args); + base::Value reset_args(base::Value::Type::LIST); + reset_args.Append(kOriginToBlock); + reset_args.Append(std::string()); + reset_args.Append(kNotifications); + reset_args.Append(false); // Incognito. + handler()->HandleResetCategoryPermissionForPattern( + &base::Value::AsListValue(reset_args)); // Check there is 1 blocked origin. base::ListValue exceptions; @@ -1081,12 +1094,13 @@ TEST_F(SiteSettingsHandlerTest, ResetCategoryPermissionForEmbargoedOrigins) { { // Reset embargoed origin. - base::ListValue reset_args; - reset_args.AppendString(kOriginToEmbargo); - reset_args.AppendString(std::string()); - reset_args.AppendString(kNotifications); - reset_args.AppendBoolean(false); // Incognito. - handler()->HandleResetCategoryPermissionForPattern(&reset_args); + base::Value reset_args(base::Value::Type::LIST); + reset_args.Append(kOriginToEmbargo); + reset_args.Append(std::string()); + reset_args.Append(kNotifications); + reset_args.Append(false); // Incognito. + handler()->HandleResetCategoryPermissionForPattern( + &base::Value::AsListValue(reset_args)); // Check that there are no blocked or embargoed origins. base::ListValue exceptions; @@ -1104,25 +1118,27 @@ TEST_F(SiteSettingsHandlerTest, ResetCategoryPermissionForInvalidOrigins) { EXPECT_FALSE(url.is_valid()); EXPECT_TRUE(url.is_empty()); - base::ListValue set_args; - set_args.AppendString(kInvalidOrigin); // Primary pattern. - set_args.AppendString(std::string()); // Secondary pattern. - set_args.AppendString(kNotifications); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(kInvalidOrigin); // Primary pattern. + set_args.Append(std::string()); // Secondary pattern. + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_args.AppendBoolean(false); // Incognito. + set_args.Append(false); // Incognito. - handler()->HandleSetCategoryPermissionForPattern(&set_args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(set_args)); ASSERT_EQ(1U, web_ui()->call_data().size()); // Reset blocked origin. - base::ListValue reset_args; - reset_args.AppendString(kInvalidOrigin); - reset_args.AppendString(std::string()); - reset_args.AppendString(kNotifications); - reset_args.AppendBoolean(false); // Incognito. + base::Value reset_args(base::Value::Type::LIST); + reset_args.Append(kInvalidOrigin); + reset_args.Append(std::string()); + reset_args.Append(kNotifications); + reset_args.Append(false); // Incognito. // Check that this method is not crashing for an invalid origin. - handler()->HandleResetCategoryPermissionForPattern(&reset_args); + handler()->HandleResetCategoryPermissionForPattern( + &base::Value::AsListValue(reset_args)); } TEST_F(SiteSettingsHandlerTest, Origins) { @@ -1131,15 +1147,16 @@ TEST_F(SiteSettingsHandlerTest, Origins) { { // Test the JS -> C++ -> JS callback path for configuring origins, by // setting Google.com to blocked. - base::ListValue set_args; - set_args.AppendString(google); // Primary pattern. - set_args.AppendString(std::string()); // Secondary pattern. - set_args.AppendString(kNotifications); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(google); // Primary pattern. + set_args.Append(std::string()); // Secondary pattern. + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_args.AppendBoolean(false); // Incognito. + set_args.Append(false); // Incognito. base::HistogramTester histograms; - handler()->HandleSetCategoryPermissionForPattern(&set_args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(set_args)); EXPECT_EQ(1U, web_ui()->call_data().size()); histograms.ExpectTotalCount(uma_base, 1); histograms.ExpectTotalCount(uma_base + ".Allowed", 0); @@ -1148,22 +1165,24 @@ TEST_F(SiteSettingsHandlerTest, Origins) { histograms.ExpectTotalCount(uma_base + ".SessionOnly", 0); } - base::ListValue get_exception_list_args; - get_exception_list_args.AppendString(kCallbackId); - get_exception_list_args.AppendString(kNotifications); - handler()->HandleGetExceptionList(&get_exception_list_args); + base::Value get_exception_list_args(base::Value::Type::LIST); + get_exception_list_args.Append(kCallbackId); + get_exception_list_args.Append(kNotifications); + handler()->HandleGetExceptionList( + &base::Value::AsListValue(get_exception_list_args)); ValidateOrigin(google, "", google, CONTENT_SETTING_BLOCK, site_settings::SiteSettingSource::kPreference, 2U); { // Reset things back to how they were. - base::ListValue reset_args; - reset_args.AppendString(google); - reset_args.AppendString(std::string()); - reset_args.AppendString(kNotifications); - reset_args.AppendBoolean(false); // Incognito. + base::Value reset_args(base::Value::Type::LIST); + reset_args.Append(google); + reset_args.Append(std::string()); + reset_args.Append(kNotifications); + reset_args.Append(false); // Incognito. base::HistogramTester histograms; - handler()->HandleResetCategoryPermissionForPattern(&reset_args); + handler()->HandleResetCategoryPermissionForPattern( + &base::Value::AsListValue(reset_args)); EXPECT_EQ(3U, web_ui()->call_data().size()); histograms.ExpectTotalCount(uma_base, 1); histograms.ExpectTotalCount(uma_base + ".Allowed", 0); @@ -1172,7 +1191,8 @@ TEST_F(SiteSettingsHandlerTest, Origins) { } // Verify the reset was successful. - handler()->HandleGetExceptionList(&get_exception_list_args); + handler()->HandleGetExceptionList( + &base::Value::AsListValue(get_exception_list_args)); ValidateNoOrigin(4U); } @@ -1188,27 +1208,27 @@ TEST_F(SiteSettingsHandlerTest, NotificationPermissionRevokeUkm) { origin_queried_waiter.QuitClosure()); { - base::ListValue set_notification_origin_args; - set_notification_origin_args.AppendString(google); - set_notification_origin_args.AppendString(""); - set_notification_origin_args.AppendString(kNotifications); - set_notification_origin_args.AppendString( + base::Value set_notification_origin_args(base::Value::Type::LIST); + set_notification_origin_args.Append(google); + set_notification_origin_args.Append(""); + set_notification_origin_args.Append(kNotifications); + set_notification_origin_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_ALLOW)); - set_notification_origin_args.AppendBoolean(false /* incognito */); + set_notification_origin_args.Append(false /* incognito */); handler()->HandleSetCategoryPermissionForPattern( - &set_notification_origin_args); + &base::Value::AsListValue(set_notification_origin_args)); } { - base::ListValue set_notification_origin_args; - set_notification_origin_args.AppendString(google); - set_notification_origin_args.AppendString(""); - set_notification_origin_args.AppendString(kNotifications); - set_notification_origin_args.AppendString( + base::Value set_notification_origin_args(base::Value::Type::LIST); + set_notification_origin_args.Append(google); + set_notification_origin_args.Append(""); + set_notification_origin_args.Append(kNotifications); + set_notification_origin_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_notification_origin_args.AppendBoolean(false /* incognito */); + set_notification_origin_args.Append(false /* incognito */); handler()->HandleSetCategoryPermissionForPattern( - &set_notification_origin_args); + &base::Value::AsListValue(set_notification_origin_args)); } origin_queried_waiter.Run(); @@ -1244,59 +1264,65 @@ TEST_F(SiteSettingsHandlerTest, MAYBE_DefaultSettingSource) { ContentSettingSourceSetter source_setter(profile(), ContentSettingsType::NOTIFICATIONS); - base::ListValue get_origin_permissions_args; - get_origin_permissions_args.AppendString(kCallbackId); - get_origin_permissions_args.AppendString(google); - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value get_origin_permissions_args(base::Value::Type::LIST); + get_origin_permissions_args.Append(kCallbackId); + get_origin_permissions_args.Append(google); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); get_origin_permissions_args.Append(std::move(category_list)); // Test Chrome built-in defaults are marked as default. - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ASK, site_settings::SiteSettingSource::kDefault, 1U); - base::ListValue default_value_args; - default_value_args.AppendString(kNotifications); - default_value_args.AppendString( + base::Value default_value_args(base::Value::Type::LIST); + default_value_args.Append(kNotifications); + default_value_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - handler()->HandleSetDefaultValueForContentType(&default_value_args); + handler()->HandleSetDefaultValueForContentType( + &base::Value::AsListValue(default_value_args)); // A user-set global default should also show up as default. - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_BLOCK, site_settings::SiteSettingSource::kDefault, 3U); - base::ListValue set_notification_pattern_args; - set_notification_pattern_args.AppendString("[*.]google.com"); - set_notification_pattern_args.AppendString(""); - set_notification_pattern_args.AppendString(kNotifications); - set_notification_pattern_args.AppendString( + base::Value set_notification_pattern_args(base::Value::Type::LIST); + set_notification_pattern_args.Append("[*.]google.com"); + set_notification_pattern_args.Append(""); + set_notification_pattern_args.Append(kNotifications); + set_notification_pattern_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_ALLOW)); - set_notification_pattern_args.AppendBoolean(false); + set_notification_pattern_args.Append(false); handler()->HandleSetCategoryPermissionForPattern( - &set_notification_pattern_args); + &base::Value::AsListValue(set_notification_pattern_args)); // A user-set pattern should not show up as default. - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ALLOW, site_settings::SiteSettingSource::kPreference, 5U); - base::ListValue set_notification_origin_args; - set_notification_origin_args.AppendString(google); - set_notification_origin_args.AppendString(""); - set_notification_origin_args.AppendString(kNotifications); - set_notification_origin_args.AppendString( + base::Value set_notification_origin_args(base::Value::Type::LIST); + set_notification_origin_args.Append(google); + set_notification_origin_args.Append(""); + set_notification_origin_args.Append(kNotifications); + set_notification_origin_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - set_notification_origin_args.AppendBoolean(false); + set_notification_origin_args.Append(false); handler()->HandleSetCategoryPermissionForPattern( - &set_notification_origin_args); + &base::Value::AsListValue(set_notification_origin_args)); // A user-set per-origin permission should not show up as default. - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_BLOCK, site_settings::SiteSettingSource::kPreference, 7U); // Enterprise-policy set defaults should not show up as default. source_setter.SetPolicyDefault(CONTENT_SETTING_ALLOW); - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); ValidateOrigin(google, google, expected_display_name, CONTENT_SETTING_ALLOW, site_settings::SiteSettingSource::kPolicy, 8U); } @@ -1305,46 +1331,40 @@ TEST_F(SiteSettingsHandlerTest, GetAndSetOriginPermissions) { const std::string origin_with_port("https://www.example.com:443"); // The display name won't show the port if it's default for that scheme. const std::string origin("www.example.com"); - base::ListValue get_args; - get_args.AppendString(kCallbackId); - get_args.AppendString(origin_with_port); + base::Value get_args(base::Value::Type::LIST); + get_args.Append(kCallbackId); + get_args.Append(origin_with_port); { - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); get_args.Append(std::move(category_list)); } - handler()->HandleGetOriginPermissions(&get_args); + handler()->HandleGetOriginPermissions(&base::Value::AsListValue(get_args)); ValidateOrigin(origin_with_port, origin_with_port, origin, CONTENT_SETTING_ASK, site_settings::SiteSettingSource::kDefault, 1U); // Block notifications. - base::ListValue set_args; - set_args.AppendString(origin_with_port); - { - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); - set_args.Append(std::move(category_list)); - } - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(origin_with_port); + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - handler()->HandleSetOriginPermissions(&set_args); + handler()->HandleSetOriginPermissions(&base::Value::AsListValue(set_args)); EXPECT_EQ(2U, web_ui()->call_data().size()); // Reset things back to how they were. - base::ListValue reset_args; - reset_args.AppendString(origin_with_port); - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); - reset_args.Append(std::move(category_list)); - reset_args.AppendString( + base::Value reset_args(base::Value::Type::LIST); + reset_args.Append(origin_with_port); + reset_args.Append(std::move(kNotifications)); + reset_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT)); - handler()->HandleSetOriginPermissions(&reset_args); + handler()->HandleSetOriginPermissions(&base::Value::AsListValue(reset_args)); EXPECT_EQ(3U, web_ui()->call_data().size()); // Verify the reset was successful. - handler()->HandleGetOriginPermissions(&get_args); + handler()->HandleGetOriginPermissions(&base::Value::AsListValue(get_args)); ValidateOrigin(origin_with_port, origin_with_port, origin, CONTENT_SETTING_ASK, site_settings::SiteSettingSource::kDefault, 4U); @@ -1353,15 +1373,15 @@ TEST_F(SiteSettingsHandlerTest, GetAndSetOriginPermissions) { TEST_F(SiteSettingsHandlerTest, GetAndSetForInvalidURLs) { const std::string origin("arbitrary string"); EXPECT_FALSE(GURL(origin).is_valid()); - base::ListValue get_args; - get_args.AppendString(kCallbackId); - get_args.AppendString(origin); + base::Value get_args(base::Value::Type::LIST); + get_args.Append(kCallbackId); + get_args.Append(origin); { - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); get_args.Append(std::move(category_list)); } - handler()->HandleGetOriginPermissions(&get_args); + handler()->HandleGetOriginPermissions(&base::Value::AsListValue(get_args)); // Verify that it'll return CONTENT_SETTING_BLOCK as |origin| is not a secure // context, a requirement for notifications. Note that the display string // will be blank since it's an invalid URL. @@ -1369,19 +1389,19 @@ TEST_F(SiteSettingsHandlerTest, GetAndSetForInvalidURLs) { site_settings::SiteSettingSource::kInsecureOrigin, 1U); // Make sure setting a permission on an invalid origin doesn't crash. - base::ListValue set_args; - set_args.AppendString(origin); + base::Value set_args(base::Value::Type::LIST); + set_args.Append(origin); { - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); set_args.Append(std::move(category_list)); } - set_args.AppendString( + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_ALLOW)); - handler()->HandleSetOriginPermissions(&set_args); + handler()->HandleSetOriginPermissions(&base::Value::AsListValue(set_args)); // Also make sure the content setting for |origin| wasn't actually changed. - handler()->HandleGetOriginPermissions(&get_args); + handler()->HandleGetOriginPermissions(&base::Value::AsListValue(get_args)); ValidateOrigin(origin, origin, "", CONTENT_SETTING_BLOCK, site_settings::SiteSettingSource::kInsecureOrigin, 2U); } @@ -1407,16 +1427,17 @@ TEST_F(SiteSettingsHandlerTest, ExceptionHelpers) { CHECK(exception->GetString(site_settings::kSetting, &type)); CHECK(exception->GetBoolean(site_settings::kIncognito, &incognito)); - base::ListValue args; - args.AppendString(primary_pattern); - args.AppendString(secondary_pattern); - args.AppendString(kNotifications); // Chosen arbitrarily. - args.AppendString(type); - args.AppendBoolean(incognito); + base::Value args(base::Value::Type::LIST); + args.Append(primary_pattern); + args.Append(secondary_pattern); + args.Append(kNotifications); // Chosen arbitrarily. + args.Append(type); + args.Append(incognito); // We don't need to check the results. This is just to make sure it doesn't // crash on the input. - handler()->HandleSetCategoryPermissionForPattern(&args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(args)); scoped_refptr<const extensions::Extension> extension; extension = extensions::ExtensionBuilder() @@ -1442,7 +1463,8 @@ TEST_F(SiteSettingsHandlerTest, ExceptionHelpers) { CHECK(dictionary->GetBoolean(site_settings::kIncognito, &incognito)); // Again, don't need to check the results. - handler()->HandleSetCategoryPermissionForPattern(&args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(args)); } TEST_F(SiteSettingsHandlerTest, ExtensionDisplayName) { @@ -1460,15 +1482,16 @@ TEST_F(SiteSettingsHandlerTest, ExtensionDisplayName) { .Build(); extension_registry->AddEnabled(extension); - base::ListValue get_origin_permissions_args; - get_origin_permissions_args.AppendString(kCallbackId); - get_origin_permissions_args.AppendString(test_extension_url); + base::Value get_origin_permissions_args(base::Value::Type::LIST); + get_origin_permissions_args.Append(kCallbackId); + get_origin_permissions_args.Append(test_extension_url); { - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); get_origin_permissions_args.Append(std::move(category_list)); } - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); ValidateOrigin(test_extension_url, test_extension_url, kExtensionName, CONTENT_SETTING_ASK, site_settings::SiteSettingSource::kDefault, 1U); @@ -1477,11 +1500,11 @@ TEST_F(SiteSettingsHandlerTest, ExtensionDisplayName) { TEST_F(SiteSettingsHandlerTest, PatternsAndContentType) { unsigned counter = 1; for (const auto& test_case : kPatternsAndContentTypeTestCases) { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(test_case.arguments.pattern); - args.AppendString(test_case.arguments.content_type); - handler()->HandleIsPatternValidForType(&args); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(test_case.arguments.pattern); + args.Append(test_case.arguments.content_type); + handler()->HandleIsPatternValidForType(&base::Value::AsListValue(args)); ValidatePattern(test_case.expected.validity, counter, test_case.expected.reason); ++counter; @@ -1489,8 +1512,8 @@ TEST_F(SiteSettingsHandlerTest, PatternsAndContentType) { } TEST_F(SiteSettingsHandlerTest, Incognito) { - base::ListValue args; - handler()->HandleUpdateIncognitoStatus(&args); + base::Value args(base::Value::Type::LIST); + handler()->HandleUpdateIncognitoStatus(&base::Value::AsListValue(args)); ValidateIncognitoExists(false, 1U); CreateIncognitoProfile(); @@ -1509,12 +1532,12 @@ TEST_F(SiteSettingsHandlerTest, ZoomLevels) { host_zoom_map->SetZoomLevelForHost(host, zoom_level); ValidateZoom(host, "122%", 1U); - base::ListValue args; - handler()->HandleFetchZoomLevels(&args); + base::Value args(base::Value::Type::LIST); + handler()->HandleFetchZoomLevels(&base::Value::AsListValue(args)); ValidateZoom(host, "122%", 2U); - args.AppendString("http://www.google.com"); - handler()->HandleRemoveZoomLevel(&args); + args.Append("http://www.google.com"); + handler()->HandleRemoveZoomLevel(&base::Value::AsListValue(args)); ValidateZoom("", "", 3U); double default_level = host_zoom_map->GetDefaultZoomLevel(); @@ -1533,7 +1556,13 @@ class SiteSettingsHandlerInfobarTest : public BrowserWithTestWindowTest { const SiteSettingsHandlerInfobarTest&) = delete; void SetUp() override { BrowserWithTestWindowTest::SetUp(); - handler_ = std::make_unique<SiteSettingsHandler>(profile(), app_registrar_); + + test_registry_controller_ = + std::make_unique<web_app::TestWebAppRegistryController>(); + test_registry_controller_->SetUp(profile()); + + handler_ = + std::make_unique<SiteSettingsHandler>(profile(), app_registrar()); handler()->set_web_ui(web_ui()); handler()->AllowJavascript(); web_ui()->ClearTrackedCalls(); @@ -1547,6 +1576,9 @@ class SiteSettingsHandlerInfobarTest : public BrowserWithTestWindowTest { extensions::ExtensionSystem::Get(profile())); extension_system->CreateExtensionService( base::CommandLine::ForCurrentProcess(), base::FilePath(), false); + + // Wait for the sync bridge to be ready synchronously. + controller().Init(); } void TearDown() override { @@ -1577,10 +1609,17 @@ class SiteSettingsHandlerInfobarTest : public BrowserWithTestWindowTest { Browser* browser2() { return browser2_.get(); } + web_app::TestWebAppRegistryController& controller() { + return *test_registry_controller_; + } + + web_app::WebAppRegistrar& app_registrar() { return controller().registrar(); } + const std::string kNotifications; private: - web_app::TestAppRegistrar app_registrar_; + std::unique_ptr<web_app::TestWebAppRegistryController> + test_registry_controller_; content::TestWebUI web_ui_; std::unique_ptr<SiteSettingsHandler> handler_; std::unique_ptr<BrowserWindow> window2_; @@ -1640,16 +1679,12 @@ TEST_F(SiteSettingsHandlerInfobarTest, SettingPermissionsTriggersInfobar) { } // Block notifications. - base::ListValue set_args; - set_args.AppendString(origin_anchor_string); - { - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); - set_args.Append(std::move(category_list)); - } - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(origin_anchor_string); + set_args.Append(kNotifications); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_BLOCK)); - handler()->HandleSetOriginPermissions(&set_args); + handler()->HandleSetOriginPermissions(&base::Value::AsListValue(set_args)); // Make sure all tabs belonging to the same origin as |origin_anchor| have an // infobar shown. @@ -1698,14 +1733,14 @@ TEST_F(SiteSettingsHandlerInfobarTest, SettingPermissionsTriggersInfobar) { NavigateAndCommit(origin_query_controller, example_without_www); // Reset all permissions. - base::ListValue reset_args; - reset_args.AppendString(origin_anchor_string); - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value reset_args(base::Value::Type::LIST); + reset_args.Append(origin_anchor_string); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); reset_args.Append(std::move(category_list)); - reset_args.AppendString( + reset_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_DEFAULT)); - handler()->HandleSetOriginPermissions(&reset_args); + handler()->HandleSetOriginPermissions(&base::Value::AsListValue(reset_args)); // Check the same tabs (plus the tab navigated to |origin_path|) still have // infobars showing. @@ -1741,15 +1776,16 @@ TEST_F(SiteSettingsHandlerInfobarTest, SettingPermissionsTriggersInfobar) { TEST_F(SiteSettingsHandlerTest, SessionOnlyException) { const std::string google_with_port("https://www.google.com:443"); const std::string uma_base("WebsiteSettings.Menu.PermissionChanged"); - base::ListValue set_args; - set_args.AppendString(google_with_port); // Primary pattern. - set_args.AppendString(std::string()); // Secondary pattern. - set_args.AppendString(kCookies); - set_args.AppendString( + base::Value set_args(base::Value::Type::LIST); + set_args.Append(google_with_port); // Primary pattern. + set_args.Append(std::string()); // Secondary pattern. + set_args.Append(kCookies); + set_args.Append( content_settings::ContentSettingToString(CONTENT_SETTING_SESSION_ONLY)); - set_args.AppendBoolean(false); // Incognito. + set_args.Append(false); // Incognito. base::HistogramTester histograms; - handler()->HandleSetCategoryPermissionForPattern(&set_args); + handler()->HandleSetCategoryPermissionForPattern( + &base::Value::AsListValue(set_args)); EXPECT_EQ(kNumberContentSettingListeners, web_ui()->call_data().size()); histograms.ExpectTotalCount(uma_base, 1); @@ -1757,8 +1793,8 @@ TEST_F(SiteSettingsHandlerTest, SessionOnlyException) { } TEST_F(SiteSettingsHandlerTest, BlockAutoplay_SendOnRequest) { - base::ListValue args; - handler()->HandleFetchBlockAutoplayStatus(&args); + base::Value args(base::Value::Type::LIST); + handler()->HandleFetchBlockAutoplayStatus(&base::Value::AsListValue(args)); // Check that we are checked and enabled. ValidateBlockAutoplay(true, true); @@ -1795,10 +1831,10 @@ TEST_F(SiteSettingsHandlerTest, BlockAutoplay_PrefUpdate) { TEST_F(SiteSettingsHandlerTest, BlockAutoplay_Update) { EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled)); - base::ListValue data; - data.AppendBoolean(false); + base::Value data(base::Value::Type::LIST); + data.Append(false); - handler()->HandleSetBlockAutoplayEnabled(&data); + handler()->HandleSetBlockAutoplayEnabled(&base::Value::AsListValue(data)); EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled)); } @@ -1836,13 +1872,10 @@ TEST_F(SiteSettingsHandlerTest, ExcludeWebUISchemesInLists) { // GetAllSites() only returns website exceptions. { - base::ListValue get_all_sites_args; - get_all_sites_args.AppendString(kCallbackId); - base::Value category_list(base::Value::Type::LIST); - category_list.Append(kNotifications); - get_all_sites_args.Append(std::move(category_list)); + base::Value get_all_sites_args(base::Value::Type::LIST); + get_all_sites_args.Append(kCallbackId); - handler()->HandleGetAllSites(&get_all_sites_args); + handler()->HandleGetAllSites(&base::Value::AsListValue(get_all_sites_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); base::Value::ConstListView site_groups = data.arg3()->GetList(); @@ -1859,11 +1892,12 @@ TEST_F(SiteSettingsHandlerTest, ExcludeWebUISchemesInLists) { // GetExceptionList() only returns website exceptions. { - base::ListValue get_exception_list_args; - get_exception_list_args.AppendString(kCallbackId); - get_exception_list_args.AppendString(kNotifications); + base::Value get_exception_list_args(base::Value::Type::LIST); + get_exception_list_args.Append(kCallbackId); + get_exception_list_args.Append(kNotifications); - handler()->HandleGetExceptionList(&get_exception_list_args); + handler()->HandleGetExceptionList( + &base::Value::AsListValue(get_exception_list_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); base::Value::ConstListView exception_list = data.arg3()->GetList(); @@ -1874,14 +1908,12 @@ TEST_F(SiteSettingsHandlerTest, ExcludeWebUISchemesInLists) { // GetRecentSitePermissions() only returns website exceptions. { - base::ListValue get_recent_permissions_args; - get_recent_permissions_args.AppendString(kCallbackId); - base::Value category_list(base::Value::Type::LIST); - category_list.Append(kNotifications); - get_recent_permissions_args.Append(std::move(category_list)); + base::Value get_recent_permissions_args(base::Value::Type::LIST); + get_recent_permissions_args.Append(kCallbackId); get_recent_permissions_args.Append(3); - handler()->HandleGetRecentSitePermissions(&get_recent_permissions_args); + handler()->HandleGetRecentSitePermissions( + &base::Value::AsListValue(get_recent_permissions_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); base::Value::ConstListView recent_permission_list = data.arg3()->GetList(); @@ -1910,14 +1942,15 @@ TEST_F(SiteSettingsHandlerTest, IncludeWebUISchemesInGetOriginPermissions) { allowlist->RegisterAutoGrantedPermission(origin, content_settings_type); for (const url::Origin& origin : kWebUIOrigins) { - base::ListValue get_origin_permissions_args; - get_origin_permissions_args.AppendString(kCallbackId); - get_origin_permissions_args.AppendString(origin.GetURL().spec()); - auto category_list = std::make_unique<base::ListValue>(); - category_list->AppendString(kNotifications); + base::Value get_origin_permissions_args(base::Value::Type::LIST); + get_origin_permissions_args.Append(kCallbackId); + get_origin_permissions_args.Append(origin.GetURL().spec()); + base::Value category_list(base::Value::Type::LIST); + category_list.Append(kNotifications); get_origin_permissions_args.Append(std::move(category_list)); - handler()->HandleGetOriginPermissions(&get_origin_permissions_args); + handler()->HandleGetOriginPermissions( + &base::Value::AsListValue(get_origin_permissions_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); const base::Value::ConstListView exception_list = data.arg3()->GetList(); EXPECT_EQ(1UL, exception_list.size()); @@ -2062,11 +2095,11 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest { // and return the exception list received by the WebUI. void ValidateChooserExceptionList(const std::string& chooser_type, size_t expected_total_calls) { - base::ListValue args; - args.AppendString(kCallbackId); - args.AppendString(chooser_type); + base::Value args(base::Value::Type::LIST); + args.Append(kCallbackId); + args.Append(chooser_type); - handler()->HandleGetChooserExceptionList(&args); + handler()->HandleGetChooserExceptionList(&base::Value::AsListValue(args)); EXPECT_EQ(web_ui()->call_data().size(), expected_total_calls); @@ -2217,19 +2250,21 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest, // User granted USB permissions for devices also containing policy permissions // should be able to be reset without removing the chooser exception object // from the list. - base::ListValue args; - args.AppendString(kUsbChooserGroupName); - args.AppendString("https://unused.com"); - args.AppendString(kGoogleOriginStr); - args.Append(base::Value::ToUniquePtrValue( - UsbChooserContext::DeviceInfoToValue(*persistent_device_info_))); + base::Value args(base::Value::Type::LIST); + args.Append(kUsbChooserGroupName); + args.Append("https://unused.com"); + args.Append(kGoogleOriginStr); + args.Append(UsbChooserContext::DeviceInfoToValue(*persistent_device_info_)); EXPECT_CALL(observer_, OnObjectPermissionChanged(absl::optional<ContentSettingsType>( ContentSettingsType::USB_GUARD), ContentSettingsType::USB_CHOOSER_DATA)); EXPECT_CALL(observer_, OnPermissionRevoked(kGoogleOrigin)); - handler()->HandleResetChooserExceptionForSite(&args); + handler()->HandleResetChooserExceptionForSite( + &base::Value::AsListValue(args)); + auto* chooser_context = UsbChooserContextFactory::GetForProfile(profile()); + chooser_context->FlushScheduledSaveSettingsCalls(); // The HandleResetChooserExceptionForSite() method should have also caused the // WebUIListenerCallbacks for contentSettingSitePermissionChanged and @@ -2250,12 +2285,11 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest, // User granted USB permissions that are also granted by policy should not // be able to be reset. - args.Clear(); - args.AppendString(kUsbChooserGroupName); - args.AppendString("https://unused.com"); - args.AppendString(kChromiumOriginStr); - args.Append(base::Value::ToUniquePtrValue( - UsbChooserContext::DeviceInfoToValue(*persistent_device_info_))); + args.ClearList(); + args.Append(kUsbChooserGroupName); + args.Append("https://unused.com"); + args.Append(kChromiumOriginStr); + args.Append(UsbChooserContext::DeviceInfoToValue(*persistent_device_info_)); { const base::Value& exceptions = @@ -2276,7 +2310,9 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest, ContentSettingsType::USB_GUARD), ContentSettingsType::USB_CHOOSER_DATA)); EXPECT_CALL(observer_, OnPermissionRevoked(kChromiumOrigin)); - handler()->HandleResetChooserExceptionForSite(&args); + handler()->HandleResetChooserExceptionForSite( + &base::Value::AsListValue(args)); + chooser_context->FlushScheduledSaveSettingsCalls(); // The HandleResetChooserExceptionForSite() method should have also caused the // WebUIListenerCallbacks for contentSettingSitePermissionChanged and @@ -2302,12 +2338,11 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest, // User granted USB permissions that are not covered by policy should be able // to be reset and the chooser exception entry should be removed from the list // when the exception only has one site exception granted to it.. - args.Clear(); - args.AppendString(kUsbChooserGroupName); - args.AppendString("https://unused.com"); - args.AppendString(kAndroidOriginStr); - args.Append(base::Value::ToUniquePtrValue( - UsbChooserContext::DeviceInfoToValue(*user_granted_device_info_))); + args.ClearList(); + args.Append(kUsbChooserGroupName); + args.Append("https://unused.com"); + args.Append(kAndroidOriginStr); + args.Append(UsbChooserContext::DeviceInfoToValue(*user_granted_device_info_)); { const base::Value& exceptions = @@ -2322,7 +2357,9 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest, ContentSettingsType::USB_GUARD), ContentSettingsType::USB_CHOOSER_DATA)); EXPECT_CALL(observer_, OnPermissionRevoked(kAndroidOrigin)); - handler()->HandleResetChooserExceptionForSite(&args); + handler()->HandleResetChooserExceptionForSite( + &base::Value::AsListValue(args)); + chooser_context->FlushScheduledSaveSettingsCalls(); // The HandleResetChooserExceptionForSite() method should have also caused the // WebUIListenerCallbacks for contentSettingSitePermissionChanged and @@ -2351,9 +2388,10 @@ TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) { ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); ASSERT_EQ("example.com", etld_plus1_string); - base::ListValue args; - args.AppendString("example.com"); - handler()->HandleClearEtldPlus1DataAndCookies(&args); + base::Value args(base::Value::Type::LIST); + args.Append("example.com"); + handler()->HandleClearEtldPlus1DataAndCookies( + &base::Value::AsListValue(args)); EXPECT_EQ(11, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); storage_and_cookie_list = GetOnStorageFetchedSentListValue(); @@ -2362,10 +2400,11 @@ TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) { ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); ASSERT_EQ("google.com", etld_plus1_string); - args.Clear(); - args.AppendString("google.com"); + args.ClearList(); + args.Append("google.com"); - handler()->HandleClearEtldPlus1DataAndCookies(&args); + handler()->HandleClearEtldPlus1DataAndCookies( + &base::Value::AsListValue(args)); EXPECT_EQ(4, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); @@ -2375,10 +2414,11 @@ TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) { ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); ASSERT_EQ("google.com.au", etld_plus1_string); - args.Clear(); - args.AppendString("google.com.au"); + args.ClearList(); + args.Append("google.com.au"); - handler()->HandleClearEtldPlus1DataAndCookies(&args); + handler()->HandleClearEtldPlus1DataAndCookies( + &base::Value::AsListValue(args)); EXPECT_EQ(1, handler()->cookies_tree_model_->GetRoot()->GetTotalNodeCount()); @@ -2411,9 +2451,10 @@ TEST_F(SiteSettingsHandlerTest, CookieSettingDescription) { web_ui()->ClearTrackedCalls(); // Validate get method works. - base::ListValue get_args; - get_args.AppendString(kCallbackId); - handler()->HandleGetCookieSettingDescription(&get_args); + base::Value get_args(base::Value::Type::LIST); + get_args.Append(kCallbackId); + handler()->HandleGetCookieSettingDescription( + &base::Value::AsListValue(get_args)); const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -2482,10 +2523,10 @@ TEST_F(SiteSettingsHandlerTest, CookieSettingDescription) { TEST_F(SiteSettingsHandlerTest, HandleGetFormattedBytes) { const double size = 120000000000; - base::ListValue get_args; - get_args.AppendString(kCallbackId); + base::Value get_args(base::Value::Type::LIST); + get_args.Append(kCallbackId); get_args.Append(size); - handler()->HandleGetFormattedBytes(&get_args); + handler()->HandleGetFormattedBytes(&base::Value::AsListValue(get_args)); // Validate that this method can handle large data. const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_helper.cc b/chromium/chrome/browser/ui/webui/settings/site_settings_helper.cc index b4dcf0a97cb..bf5f79be19f 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_helper.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_helper.cc @@ -9,10 +9,13 @@ #include <set> #include <string> +#include "base/command_line.h" #include "base/containers/contains.h" #include "base/feature_list.h" +#include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/browser/bluetooth/bluetooth_chooser_context_factory.h" #include "chrome/browser/content_settings/chrome_content_settings_utils.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" @@ -25,6 +28,7 @@ #include "chrome/browser/subresource_filter/subresource_filter_profile_context_factory.h" #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" +#include "chrome/browser/web_applications/components/web_app_utils.h" #include "chrome/common/pref_names.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" @@ -43,6 +47,7 @@ #include "components/subresource_filter/core/browser/subresource_filter_features.h" #include "components/url_formatter/url_formatter.h" #include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" #include "content/public/common/url_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" @@ -154,6 +159,8 @@ const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = { {ContentSettingsType::DISPLAY_CAPTURE, nullptr}, {ContentSettingsType::FEDERATED_IDENTITY_SHARING, nullptr}, {ContentSettingsType::FEDERATED_IDENTITY_REQUEST, nullptr}, + {ContentSettingsType::JAVASCRIPT_JIT, nullptr}, + {ContentSettingsType::HTTP_ALLOWED, nullptr}, }; static_assert(base::size(kContentSettingsTypeGroupNames) == @@ -401,16 +408,88 @@ base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type) { return base::StringPiece(); } -std::vector<ContentSettingsType> ContentSettingsTypesFromGroupNames( - const base::Value::ConstListView types) { - std::vector<ContentSettingsType> content_types; - content_types.reserve(types.size()); - for (const auto& value : types) { - const auto& type = value.GetString(); - content_types.push_back( - site_settings::ContentSettingsTypeFromGroupName(type)); +const std::vector<ContentSettingsType>& GetVisiblePermissionCategories() { + // First build the list of permissions that will be shown regardless of + // `origin`. Some categories such as COOKIES store their data in a custom way, + // so are not included here. + static base::NoDestructor<std::vector<ContentSettingsType>> base_types{{ + ContentSettingsType::AR, + ContentSettingsType::AUTOMATIC_DOWNLOADS, + ContentSettingsType::BACKGROUND_SYNC, + ContentSettingsType::CLIPBOARD_READ_WRITE, + ContentSettingsType::FILE_HANDLING, + ContentSettingsType::FILE_SYSTEM_WRITE_GUARD, + ContentSettingsType::FONT_ACCESS, + ContentSettingsType::GEOLOCATION, + ContentSettingsType::HID_GUARD, + ContentSettingsType::IDLE_DETECTION, + ContentSettingsType::IMAGES, + ContentSettingsType::JAVASCRIPT, + ContentSettingsType::MEDIASTREAM_CAMERA, + ContentSettingsType::MEDIASTREAM_MIC, + ContentSettingsType::MIDI_SYSEX, + ContentSettingsType::MIXEDSCRIPT, + ContentSettingsType::NOTIFICATIONS, + ContentSettingsType::POPUPS, +#if defined(IS_CHROMEOS_ASH) || defined(OS_WIN) + ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER, +#endif + ContentSettingsType::SENSORS, + ContentSettingsType::SERIAL_GUARD, + ContentSettingsType::SOUND, + ContentSettingsType::USB_GUARD, + ContentSettingsType::VR, + ContentSettingsType::WINDOW_PLACEMENT, + }}; + static bool initialized = false; + if (!initialized) { + // The permission categories in this block are only shown when running with + // certain flags/switches. + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches::kEnableExperimentalWebPlatformFeatures)) { + base_types->push_back(ContentSettingsType::BLUETOOTH_SCANNING); + } + + if (base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps)) + base_types->push_back(ContentSettingsType::PAYMENT_HANDLER); + + if (base::FeatureList::IsEnabled( + features::kWebBluetoothNewPermissionsBackend)) { + base_types->push_back(ContentSettingsType::BLUETOOTH_GUARD); + } + + if (base::FeatureList::IsEnabled( + subresource_filter::kSafeBrowsingSubresourceFilter)) { + base_types->push_back(ContentSettingsType::ADS); + } + + initialized = true; } - return content_types; + + return *base_types; +} + +std::vector<ContentSettingsType> GetVisiblePermissionCategoriesForOrigin( + Profile* profile, + const GURL& origin) { + const std::vector<ContentSettingsType>& base_types = + GetVisiblePermissionCategories(); + std::vector<ContentSettingsType> types_for_origin; + std::copy_if( + base_types.begin(), base_types.end(), + std::back_inserter(types_for_origin), + [&profile, &origin](ContentSettingsType type) { + // File Handling is only relevant for installed PWAs that ask for + // certain file types; if this is not the case, the control will do + // nothing and thus is hidden. + if (type == ContentSettingsType::FILE_HANDLING && + web_app::GetFileHandlersForAllWebAppsWithOrigin(profile, origin) + .empty()) { + return false; + } + return true; + }); + return types_for_origin; } std::string SiteSettingSourceToString(const SiteSettingSource source) { @@ -762,12 +841,11 @@ void GetPolicyAllowedUrls( // Convert the URLs to |ContentSettingsPattern|s. Ignore any invalid ones. std::vector<ContentSettingsPattern> patterns; for (const auto& entry : policy_urls->GetList()) { - std::string url; - bool valid_string = entry.GetAsString(&url); - if (!valid_string) + const std::string* url = entry.GetIfString(); + if (!url) continue; - ContentSettingsPattern pattern = ContentSettingsPattern::FromString(url); + ContentSettingsPattern pattern = ContentSettingsPattern::FromString(*url); if (!pattern.IsValid()) continue; diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_helper.h b/chromium/chrome/browser/ui/webui/settings/site_settings_helper.h index 817b2b013b7..685203f7b19 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_helper.h +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_helper.h @@ -112,9 +112,17 @@ bool HasRegisteredGroupName(ContentSettingsType type); ContentSettingsType ContentSettingsTypeFromGroupName(base::StringPiece name); base::StringPiece ContentSettingsTypeToGroupName(ContentSettingsType type); -// Converts a ListValue of group names to a list of ContentSettingsTypes -std::vector<ContentSettingsType> ContentSettingsTypesFromGroupNames( - const base::Value::ConstListView types); +// Returns a list of all content settings types that correspond to permissions +// and which should be displayed in chrome://settings, for any situation not +// tied to particular a origin. +const std::vector<ContentSettingsType>& GetVisiblePermissionCategories(); + +// Returns a list of all content settings types that correspond to permissions +// and which should be displayed in chrome://settings for the given |origin|. +// This will not include categories that are not relevant for the given origin. +std::vector<ContentSettingsType> GetVisiblePermissionCategoriesForOrigin( + Profile* profile, + const GURL& origin); // Converts a SiteSettingSource to its string identifier. std::string SiteSettingSourceToString(const SiteSettingSource source); diff --git a/chromium/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc b/chromium/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc index 1739d38abbf..8198b2d6890 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc @@ -347,7 +347,7 @@ TEST_F(SiteSettingsHelperTest, CheckExceptionOrder) { map, std::move(extension_provider), HostContentSettingsMap::CUSTOM_EXTENSION_PROVIDER); - exceptions.Clear(); + exceptions.ClearList(); GetExceptionsForContentType(kContentType, &profile, /*extension_registry=*/nullptr, /*web_ui=*/nullptr, diff --git a/chromium/chrome/browser/ui/webui/settings/url_handlers_handler.cc b/chromium/chrome/browser/ui/webui/settings/url_handlers_handler.cc new file mode 100644 index 00000000000..5237f6b272b --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/url_handlers_handler.cc @@ -0,0 +1,415 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/url_handlers_handler.h" + +#include <memory> +#include <utility> + +#include "base/bind.h" +#include "base/check.h" +#include "base/containers/flat_map.h" +#include "base/containers/flat_set.h" +#include "base/strings/utf_string_conversions.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/components/url_handler_launch_params.h" +#include "chrome/browser/web_applications/components/url_handler_prefs.h" +#include "chrome/browser/web_applications/web_app_registrar.h" +#include "chrome/common/pref_names.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/prefs/pref_service.h" +#include "components/url_formatter/elide_url.h" +#include "content/public/browser/web_ui.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace settings { + +namespace { + +struct EnabledRow { + std::string origin_key; // Eg. "https://contoso.com" + std::string app_id; + std::string short_name; + std::u16string publisher; + bool has_origin_wildcard; + std::string path; // Eg. "/*" or "/news" + absl::optional<std::u16string> display_url; // Eg. "contoso.com/news" + + bool operator<(const EnabledRow& other) const { + if (this == &other) + return false; + + if (short_name < other.short_name) + return true; + if (origin_key < other.origin_key) + return true; + if (has_origin_wildcard < other.has_origin_wildcard) + return true; + if (path < other.path) + return true; + + return false; + } +}; + +struct DisabledRow { + std::string origin_key; + bool has_origin_wildcard; + std::string path; // Eg. "/*" or "/news" + std::u16string display_url; + + bool operator<(const DisabledRow& other) const { + if (this == &other) + return false; + + if (origin_key < other.origin_key) + return true; + if (has_origin_wildcard < other.has_origin_wildcard) + return true; + if (path < other.path) + return true; + + return false; + } +}; + +// Example of returned Value: +// [ +// { +// "app_entries": [ +// { +// "app_id": "jncifgjpfigpfjphlanoeonmiedopibl", +// "display_url": "example.com/abc", // optional +// "has_origin_wildcard": true, +// "origin_key": "https://example.com", +// "path": "/abc", +// "publisher": "example.com", +// "short_name": "Example App +// } +// ], +// "display_origin": "*.example.com" +// } +// ] +base::Value SerializeEnabledHandlersList( + const base::flat_map<std::u16string, base::flat_set<EnabledRow>>& + organizer) { + base::Value result_list(base::Value::Type::LIST); + + for (const auto& kv : organizer) { + const std::u16string& origin_str = kv.first; + const base::flat_set<EnabledRow>& app_rows = kv.second; + + base::Value result_entry(base::Value::Type::DICTIONARY); + result_entry.SetStringKey("display_origin", origin_str); + base::Value app_entries(base::Value::Type::LIST); + for (const auto& app_row : app_rows) { + base::Value app_entry(base::Value::Type::DICTIONARY); + app_entry.SetStringKey("origin_key", app_row.origin_key); + app_entry.SetStringKey("app_id", app_row.app_id); + app_entry.SetStringKey("short_name", app_row.short_name); + app_entry.SetStringKey("publisher", app_row.publisher); + app_entry.SetBoolKey("has_origin_wildcard", app_row.has_origin_wildcard); + app_entry.SetStringKey("path", app_row.path); + // "display_url" is optional. It's only needed when path != "/*". + if (app_row.display_url.has_value()) + app_entry.SetStringKey("display_url", app_row.display_url.value()); + + app_entries.Append(std::move(app_entry)); + } + result_entry.SetKey("app_entries", std::move(app_entries)); + result_list.Append(std::move(result_entry)); + } + return result_list; +} + +// Example of returned value: +// [ +// { +// "display_url": "*.example.com/abc", +// "has_origin_wildcard": true, +// "origin_key": "https://example.com", +// "path": "/abc" +// } +// ] +base::Value SerializeDisabledHandlersList( + const base::flat_set<DisabledRow>& organizer) { + base::Value disabled_entries(base::Value::Type::LIST); + + for (const DisabledRow& row : organizer) { + base::Value entry(base::Value::Type::DICTIONARY); + entry.SetStringKey("origin_key", row.origin_key); + entry.SetBoolKey("has_origin_wildcard", row.has_origin_wildcard); + entry.SetStringKey("path", row.path); + entry.SetStringKey("display_url", row.display_url); + disabled_entries.Append(std::move(entry)); + } + return disabled_entries; +} + +std::u16string FormatOriginString(const url::Origin& origin, + bool has_origin_wildcard) { + std::u16string origin_str = url_formatter::FormatOriginForSecurityDisplay( + origin, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); + + if (has_origin_wildcard) + origin_str = u"*." + origin_str; + + return origin_str; +} + +} // namespace + +UrlHandlersHandler::UrlHandlersHandler( + PrefService* local_state, + Profile* profile, + web_app::WebAppRegistrar* web_app_registrar) + : local_state_(local_state), + profile_(profile), + web_app_registrar_(web_app_registrar) { + DCHECK(local_state_); + DCHECK(profile_); + DCHECK(web_app_registrar_); +} + +UrlHandlersHandler::~UrlHandlersHandler() = default; + +void UrlHandlersHandler::OnJavascriptAllowed() { + DCHECK(local_state_); + + local_state_pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); + local_state_pref_change_registrar_->Init(local_state_); + local_state_pref_change_registrar_->Add( + prefs::kWebAppsUrlHandlerInfo, + base::BindRepeating( + &UrlHandlersHandler::OnUrlHandlersLocalStatePrefChanged, + // Using base::Unretained(this) here is safe because the lifetime of + // this UrlHandlersHandler instance is the same or longer than that of + // local_state_pref_change_registrar_. + // local_state_pref_change_registrar_ is destroyed either in + // |OnJavascriptDisallowed| or when this UrlHandlersHandler is + // destroyed. + base::Unretained(this))); +} + +void UrlHandlersHandler::OnJavascriptDisallowed() { + local_state_pref_change_registrar_.reset(); +} + +void UrlHandlersHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "getUrlHandlers", + base::BindRepeating(&UrlHandlersHandler::HandleGetUrlHandlers, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "resetUrlHandlerSavedChoice", + base::BindRepeating(&UrlHandlersHandler::HandleResetUrlHandlerSavedChoice, + base::Unretained(this))); +} + +void UrlHandlersHandler::OnUrlHandlersLocalStatePrefChanged() { + UpdateModel(); +} + +void UrlHandlersHandler::UpdateModel() { + base::Value enabled_handlers_list = GetEnabledHandlersList(); + base::Value disabled_handlers_list = GetDisabledHandlersList(); + + // TODO(crbug.com/1217423): Implement a handler on the WebUI side to accept + // this data and update the UI. + FireWebUIListener("updateUrlHandlers", enabled_handlers_list, + disabled_handlers_list); +} + +void UrlHandlersHandler::HandleGetUrlHandlers(const base::ListValue* args) { + CHECK_EQ(1U, args->GetList().size()); + const base::Value& callback_id = args->GetList()[0]; + AllowJavascript(); + + base::Value result(base::Value::Type::DICTIONARY); + result.SetKey("enabled", base::Value(GetEnabledHandlersList())); + result.SetKey("disabled", base::Value(GetDisabledHandlersList())); + ResolveJavascriptCallback(callback_id, result); +} + +void UrlHandlersHandler::HandleResetUrlHandlerSavedChoice( + const base::ListValue* args) { + CHECK_EQ(4U, args->GetList().size()); + const std::string& origin = args->GetList()[0].GetString(); + bool has_origin_wildcard = args->GetList()[1].GetBool(); + const std::string& path = args->GetList()[2].GetString(); + // If app_id is an empty string, reset saved choices for all applicable + // entries regardless of app_id. + const std::string& app_id = args->GetList()[3].GetString(); + absl::optional<std::string> app_id_opt = + app_id.empty() ? absl::nullopt : absl::make_optional(app_id); + + web_app::url_handler_prefs::ResetSavedChoice(local_state_, app_id_opt, + profile_->GetPath(), origin, + has_origin_wildcard, path); + + // No need to call UpdateModel() here - we should receive a notification + // that local state prefs have changed and we will update the view + // then. +} + +// Example of returned value: +// [ +// { +// "display_origin": "example.com", +// "app_entries": [ +// { +// "app_id": "jncifgjpfigpfjphlanoeonmiedopibl", +// "has_origin_wildcard": false, +// "origin_key": "https://example.com", +// "path": "/abc", +// "publisher": "example.com", +// "short_name": "Example App", +// "display_url": "example.com/abc" // optional +// } +// ] +// } +// ] +base::Value UrlHandlersHandler::GetEnabledHandlersList() { + const base::Value* const pref_value = + local_state_->Get(prefs::kWebAppsUrlHandlerInfo); + if (!pref_value || !pref_value->is_dict()) + return base::Value(base::Value::Type::LIST); + + // Ensure that both keys and values are sorted. + base::flat_map<std::u16string, base::flat_set<EnabledRow>> organizer; + for (const auto kv : pref_value->DictItems()) { + const auto& origin_key = kv.first; + auto origin = url::Origin::Create(GURL(kv.first)); + + for (const auto& handler : kv.second.GetList()) { + // Only process handlers from current profile. + if (!web_app::url_handler_prefs::IsHandlerForProfile( + handler, profile_->GetPath())) { + continue; + } + + absl::optional<const web_app::url_handler_prefs::HandlerView> + handler_view = + web_app::url_handler_prefs::GetConstHandlerView(handler); + + const std::string& short_name = + web_app_registrar_->GetAppShortName(handler_view->app_id); + + url::Origin app_origin = url::Origin::Create( + GURL(web_app_registrar_->GetAppStartUrl(handler_view->app_id))); + + std::u16string publisher = url_formatter::FormatOriginForSecurityDisplay( + app_origin, url_formatter::SchemeDisplay::OMIT_HTTP_AND_HTTPS); + + // For every include_path that has kInApp choice, add a "row" to + // app_entries. Each "row" has the same app_id, etc, but different path + // information. This create a list that is easy to process in WebUI. + for (const auto& include_path_dict : + handler_view->include_paths.GetList()) { + const std::string* path = include_path_dict.FindStringKey("path"); + absl::optional<int> choice = include_path_dict.FindIntKey("choice"); + if (!path || !choice) + continue; + + // Only show entries that open in app. + if (*choice != static_cast<int>(web_app::UrlHandlerSavedChoice::kInApp)) + continue; + + EnabledRow app_row; + app_row.origin_key = origin_key; + app_row.app_id = handler_view->app_id; + app_row.short_name = short_name; + app_row.publisher = publisher; + app_row.has_origin_wildcard = handler_view->has_origin_wildcard; + app_row.path = *path; + + std::u16string origin_str = + FormatOriginString(origin, handler_view->has_origin_wildcard); + + // Only include a formatted URL with path if the path is not /*. + // Eg. example.com/* only needs to display example.com, while + // example.com/abc needs to be displayed in full. + if (*path != "/*") + app_row.display_url = origin_str + base::UTF8ToUTF16(*path); + + // Add app_row to the correct bucket according to displayed origin. + organizer[origin_str].insert(app_row); + } + } + } + return SerializeEnabledHandlersList(organizer); +} + +// Example of returned Value: +// [ +// { +// "display_url": "https://example.com/", +// "has_origin_wildcard": true, +// "origin_key": "https://example.com", +// "path": "/*" +// } +// ] +base::Value UrlHandlersHandler::GetDisabledHandlersList() { + const base::Value* const pref_value = + local_state_->Get(prefs::kWebAppsUrlHandlerInfo); + if (!pref_value || !pref_value->is_dict()) + return base::Value(base::Value::Type::LIST); + + // Ensure that values are deduplicated and sorted. + base::flat_set<DisabledRow> organizer; + for (const auto kv : pref_value->DictItems()) { + const auto& origin_key = kv.first; + url::Origin origin = url::Origin::Create(GURL(kv.first)); + + for (const auto& handler : kv.second.GetList()) { + // Only process handlers from current profile. + if (!web_app::url_handler_prefs::IsHandlerForProfile( + handler, profile_->GetPath())) { + continue; + } + + absl::optional<const web_app::url_handler_prefs::HandlerView> + handler_view = + web_app::url_handler_prefs::GetConstHandlerView(handler); + if (!handler_view) + continue; + + for (const base::Value& include_path_dict : + handler_view->include_paths.GetList()) { + if (!include_path_dict.is_dict()) + continue; + + absl::optional<int> choice = include_path_dict.FindIntKey("choice"); + if (!choice || + *choice != + static_cast<int>(web_app::UrlHandlerSavedChoice::kInBrowser)) + continue; + + const std::string* path = include_path_dict.FindStringKey("path"); + if (!path) + continue; + + DisabledRow row; + row.origin_key = origin_key; + row.has_origin_wildcard = handler_view->has_origin_wildcard; + row.path = *path; + + std::u16string origin_str = + FormatOriginString(origin, handler_view->has_origin_wildcard); + std::u16string display_url = + *path == "/*" ? origin_str : origin_str + base::UTF8ToUTF16(*path); + row.display_url = display_url; + organizer.insert(row); + } + } + } + + return SerializeDisabledHandlersList(organizer); +} + +} // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/url_handlers_handler.h b/chromium/chrome/browser/ui/webui/settings/url_handlers_handler.h new file mode 100644 index 00000000000..9ffbf9afe99 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/url_handlers_handler.h @@ -0,0 +1,73 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_URL_HANDLERS_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_URL_HANDLERS_HANDLER_H_ + +#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" + +class PrefChangeRegistrar; +class PrefService; +class Profile; + +namespace base { +class Value; +} + +namespace web_app { +class WebAppRegistrar; +} // namespace web_app + +namespace settings { + +class UrlHandlersHandlerTest; + +class UrlHandlersHandler : public SettingsPageUIHandler { + public: + UrlHandlersHandler(PrefService* local_state, + Profile* profile, + web_app::WebAppRegistrar* web_app_registrar); + ~UrlHandlersHandler() override; + UrlHandlersHandler(const UrlHandlersHandler&) = delete; + UrlHandlersHandler& operator=(const UrlHandlersHandler&) = delete; + + // SettingsPageUIHandler: + void OnJavascriptAllowed() override; + void OnJavascriptDisallowed() override; + void RegisterMessages() override; + + private: + friend class ::settings::UrlHandlersHandlerTest; + + // Handles calls from WebUI to update the model data of URL handlers settings. + // Takes no args. + void HandleGetUrlHandlers(const base::ListValue* args); + + // Handles calls from WebUI to reset the user's saved choice for one or more + // URL handler entries. + // When reset, the choice becomes kNone and the timestamp is updated. + // |args| is a list of [app_id, origin_key, has_origin_wildcard, url_path]. + void HandleResetUrlHandlerSavedChoice(const base::ListValue* args); + + // Reads and formats data from UrlHandlerPrefs then sends it to the WebUI + // frontend. + void UpdateModel(); + + // Listens to relevant prefs changes and updates WebUI with new data. + void OnUrlHandlersLocalStatePrefChanged(); + + // Helper functions that read and format UrlHandlerPrefs data for settings + // page in WebUI. + base::Value GetEnabledHandlersList(); + base::Value GetDisabledHandlersList(); + + std::unique_ptr<PrefChangeRegistrar> local_state_pref_change_registrar_; + PrefService* local_state_ = nullptr; + Profile* profile_ = nullptr; + web_app::WebAppRegistrar* web_app_registrar_ = nullptr; +}; + +} // namespace settings + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_URL_HANDLERS_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/url_handlers_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/url_handlers_handler_unittest.cc new file mode 100644 index 00000000000..7fc223e16a3 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/url_handlers_handler_unittest.cc @@ -0,0 +1,367 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/webui/settings/url_handlers_handler.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/test/values_test_util.h" +#include "base/time/time.h" +#include "base/values.h" +#include "chrome/browser/web_applications/components/url_handler_prefs.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "chrome/browser/web_applications/test/test_web_app_registry_controller.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_registrar.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/scoped_testing_local_state.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "components/services/app_service/public/cpp/url_handler_info.h" +#include "content/public/browser/web_ui_message_handler.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_web_ui.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace settings { +namespace { + +class TestUrlHandlersHandler : public settings::UrlHandlersHandler { + public: + TestUrlHandlersHandler(PrefService* local_state, + Profile* profile, + web_app::WebAppRegistrar* web_app_registrar) + : UrlHandlersHandler(local_state, profile, web_app_registrar) {} + ~TestUrlHandlersHandler() override = default; + TestUrlHandlersHandler(const TestUrlHandlersHandler&) = delete; + TestUrlHandlersHandler& operator=(const TestUrlHandlersHandler&) = delete; + + using settings::UrlHandlersHandler::set_web_ui; + + private: + friend class ::settings::UrlHandlersHandlerTest; +}; + +constexpr char kTestCallbackId[] = "test-callback-id"; +constexpr char kEmptyList[] = R"([ ])"; + +} // namespace + +class UrlHandlersHandlerTest : public testing::Test { + public: + UrlHandlersHandlerTest() + : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) { + EXPECT_TRUE(base::Time::FromString("1 Jan 2000 00:00:00 GMT", &time_1_)); + } + + ~UrlHandlersHandlerTest() override = default; + UrlHandlersHandlerTest(const UrlHandlersHandlerTest&) = delete; + UrlHandlersHandlerTest& operator=(const UrlHandlersHandlerTest&) = delete; + + void SetUp() override { + profile_ = std::make_unique<TestingProfile>(); + + test_registry_controller_ = + std::make_unique<web_app::TestWebAppRegistryController>(); + test_registry_controller_->SetUp(profile_.get()); + + handler_ = std::make_unique<TestUrlHandlersHandler>( + local_state(), profile(), &test_app_registrar()); + handler_->set_web_ui(web_ui()); + handler_->RegisterMessages(); + handler_->AllowJavascriptForTesting(); + + web_ui()->ClearTrackedCalls(); + + controller().Init(); + } + + const web_app::WebApp* RegisterWebAppWithUrlHandlers( + const GURL& app_url, + const apps::UrlHandlers& url_handlers) { + std::unique_ptr<web_app::WebApp> web_app = + std::make_unique<web_app::WebApp>(web_app::GenerateAppId( + /*manifest_id=*/absl::nullopt, GURL(app_url))); + web_app->AddSource(web_app::Source::kDefault); + web_app->SetName("App Name"); + web_app->SetDisplayMode(web_app::DisplayMode::kStandalone); + web_app->SetUserDisplayMode(web_app::DisplayMode::kStandalone); + web_app->SetStartUrl(app_url); + web_app->SetUrlHandlers(url_handlers); + const web_app::AppId app_id = web_app->app_id(); + web_app::url_handler_prefs::AddWebApp( + local_state(), app_id, profile()->GetPath(), web_app->url_handlers()); + controller().RegisterApp(std::move(web_app)); + return registrar().GetAppById(app_id); + } + + void TearDown() override { + profile_.reset(); + handler_.reset(); + } + + web_app::TestWebAppRegistryController& controller() { + return *test_registry_controller_; + } + + web_app::WebAppRegistrar& registrar() { return controller().registrar(); } + + web_app::WebAppRegistrar& test_app_registrar() { + return controller().registrar(); + } + + TestingProfile* profile() { return profile_.get(); } + + content::TestWebUI* web_ui() { return &web_ui_; } + + PrefService* local_state() { + return TestingBrowserProcess::GetGlobal()->local_state(); + } + + TestUrlHandlersHandler* handler() { return handler_.get(); } + + void ParseAndExpectValue(const base::Value& value, + const std::string& expectation) { + base::Value expected_value = base::test::ParseJson(expectation); + EXPECT_EQ(value, expected_value); + } + + void CallAndExpectGetUrlHandlers( + const std::string& expected_enabled_handlers = "", + const std::string& expected_disabled_handlers = "") { + base::ListValue list_args; + list_args.AppendString(kTestCallbackId); + web_ui()->HandleReceivedMessage("getUrlHandlers", &list_args); + + ASSERT_EQ(1u, web_ui()->call_data().size()); + const auto& data = *web_ui()->call_data()[0]; + EXPECT_EQ("cr.webUIResponse", data.function_name()); + + ASSERT_TRUE(data.arg1()->is_string()); + EXPECT_EQ(kTestCallbackId, data.arg1()->GetString()); + + // Check that ResolveJavascriptCallback was called by the handler. + ASSERT_TRUE(data.arg2()->is_bool()); + EXPECT_TRUE(data.arg2()->GetBool()) + << "Callback should be resolved successfully by HandleGetUrlHandlers"; + + // Check data given to ResolveJavascriptCallback. + ASSERT_TRUE(data.arg3()->is_dict()); + const base::Value* callback_data = data.arg3(); + ASSERT_TRUE(callback_data != nullptr); + const base::Value* enabled_handlers = callback_data->FindKey("enabled"); + const base::Value* disabled_handlers = callback_data->FindKey("disabled"); + ASSERT_TRUE(enabled_handlers != nullptr); + ASSERT_TRUE(disabled_handlers != nullptr); + if (!expected_enabled_handlers.empty()) + ParseAndExpectValue(*enabled_handlers, expected_enabled_handlers); + if (!expected_disabled_handlers.empty()) + ParseAndExpectValue(*disabled_handlers, expected_disabled_handlers); + + web_ui()->ClearTrackedCalls(); + } + + void ExpectUpdateUrlHandlers( + const std::string& expected_enabled_handlers = "", + const std::string& expected_disabled_handlers = "") { + ASSERT_EQ(web_ui()->call_data().size(), 1u); + const content::TestWebUI::CallData& data = *web_ui()->call_data()[0]; + EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); + std::string event_name; + ASSERT_TRUE(data.arg1()->GetAsString(&event_name)); + EXPECT_EQ("updateUrlHandlers", event_name); + + if (!expected_enabled_handlers.empty()) + ParseAndExpectValue(*data.arg2(), expected_enabled_handlers); + if (!expected_disabled_handlers.empty()) + ParseAndExpectValue(*data.arg3(), expected_disabled_handlers); + + web_ui()->ClearTrackedCalls(); + } + + void ExpectEnabledHandlersList(const std::string& expected) { + const base::Value expected_value = base::test::ParseJson(expected); + EXPECT_EQ(handler()->GetEnabledHandlersList(), expected_value); + } + + void ExpectDisabledHandlersList(const std::string& expected) { + const base::Value expected_value = base::test::ParseJson(expected); + EXPECT_EQ(handler()->GetDisabledHandlersList(), expected_value); + } + + void ExpectUrlHandlerPrefs(const std::string& expected_prefs) { + const base::Value* const stored_prefs = + local_state()->Get(prefs::kWebAppsUrlHandlerInfo); + ASSERT_TRUE(stored_prefs); + const base::Value expected_prefs_value = + base::test::ParseJson(expected_prefs); + EXPECT_EQ(*stored_prefs, expected_prefs_value); + } + + protected: + content::BrowserTaskEnvironment task_environment_; + ScopedTestingLocalState scoped_testing_local_state_; + std::unique_ptr<TestingProfile> profile_; + content::TestWebUI web_ui_; + std::unique_ptr<web_app::TestWebAppRegistryController> + test_registry_controller_; + std::unique_ptr<TestUrlHandlersHandler> handler_; + base::Time time_1_; + const GURL app_url_ = GURL("https://app.com"); + const GURL app2_url_ = GURL("https://app2.com"); + const url::Origin target_origin_ = + url::Origin::Create(GURL("https://target-1.com")); + const GURL url_in_target_origin_ = + target_origin_.GetURL().Resolve("/index.html"); +}; + +TEST_F(UrlHandlersHandlerTest, HandleGetUrlHandlers) { + // Trigger HandleGetUrlHandlers and observe that it calls + // ResolveJavascriptCallback successfully. + CallAndExpectGetUrlHandlers(kEmptyList, kEmptyList); + + // Install app. + const auto* web_app = RegisterWebAppWithUrlHandlers( + app_url_, {apps::UrlHandlerInfo(target_origin_)}); + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); + + // Save user choice to open in app. + web_app::url_handler_prefs::SaveOpenInApp(local_state(), web_app->app_id(), + profile()->GetPath(), + url_in_target_origin_, time_1_); + constexpr char kEnabledHandlers[] = R"([ { + "app_entries": [ { + "app_id": "ahkofokocdmhbhhpkeohpoocnniagaac", + "has_origin_wildcard": false, + "origin_key": "https://target-1.com", + "path": "/*", + "publisher": "app.com", + "short_name": "App Name" + } ], + "display_origin": "target-1.com" + } ])"; + ExpectUpdateUrlHandlers(kEnabledHandlers, kEmptyList); + // Trigger HandleGetUrlHandlers and observe that it calls + // ResolveJavascriptCallback successfully. This isn't necessary but we call + // "getUrlHandlers" here to check that its values are identical to values from + // "updateUrlHandlers". + CallAndExpectGetUrlHandlers(kEnabledHandlers, kEmptyList); + + // Save user choice to open in browser. + web_app::url_handler_prefs::SaveOpenInBrowser(local_state(), + url_in_target_origin_, time_1_); + constexpr char kDisabledHandlers[] = R"([ { + "display_url": "target-1.com", + "has_origin_wildcard": false, + "origin_key": "https://target-1.com", + "path": "/*" + }])"; + ExpectUpdateUrlHandlers(kEmptyList, kDisabledHandlers); + CallAndExpectGetUrlHandlers(kEmptyList, kDisabledHandlers); +} + +TEST_F(UrlHandlersHandlerTest, HandleResetUrlHandlerSavedChoice) { + const auto* web_app = RegisterWebAppWithUrlHandlers( + app_url_, {apps::UrlHandlerInfo(target_origin_)}); + // Prefs changes should cause data to be sent to WebUI. + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); + + // Save user choice to open in app. + web_app::url_handler_prefs::SaveOpenInApp(local_state(), web_app->app_id(), + profile()->GetPath(), + url_in_target_origin_, time_1_); + ExpectUpdateUrlHandlers(R"([ { + "app_entries": [ { + "app_id": "ahkofokocdmhbhhpkeohpoocnniagaac", + "has_origin_wildcard": false, + "origin_key": "https://target-1.com", + "path": "/*", + "publisher": "app.com", + "short_name": "App Name" + } ], + "display_origin": "target-1.com" + } ])", + kEmptyList); + + // Trigger resetUrlHandlerSavedChoice event directly. That should result + // in local state prefs being updated and then update to WebUI. + base::ListValue list_args; + list_args.AppendString("https://target-1.com"); // origin + list_args.Append(false); // has_origin_wildcard + list_args.AppendString("/*"); // url_path + list_args.AppendString(web_app->app_id()); // app_id + web_ui()->HandleReceivedMessage("resetUrlHandlerSavedChoice", &list_args); + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); +} + +TEST_F(UrlHandlersHandlerTest, EnabledHandlers) { + const auto* web_app = RegisterWebAppWithUrlHandlers( + app_url_, {apps::UrlHandlerInfo(target_origin_)}); + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); + // Save user choice to open in app. + web_app::url_handler_prefs::SaveOpenInApp(local_state(), web_app->app_id(), + profile()->GetPath(), + url_in_target_origin_, time_1_); + + ExpectUpdateUrlHandlers(R"([ { + "app_entries": [ { + "app_id": "ahkofokocdmhbhhpkeohpoocnniagaac", + "has_origin_wildcard": false, + "origin_key": "https://target-1.com", + "path": "/*", + "publisher": "app.com", + "short_name": "App Name" + } ], + "display_origin": "target-1.com" + } ])", + kEmptyList); +} + +TEST_F(UrlHandlersHandlerTest, DisabledHandlers) { + RegisterWebAppWithUrlHandlers(app_url_, + {apps::UrlHandlerInfo(target_origin_)}); + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); + + // Save user choice to open in browser. + web_app::url_handler_prefs::SaveOpenInBrowser(local_state(), + url_in_target_origin_, time_1_); + ExpectUpdateUrlHandlers(kEmptyList, + R"([ { + "display_url": "target-1.com", + "has_origin_wildcard": false, + "origin_key": "https://target-1.com", + "path": "/*" + } ])"); +} + +TEST_F(UrlHandlersHandlerTest, GetDisabledHandlersList_MultipleApps) { + RegisterWebAppWithUrlHandlers(app_url_, + {apps::UrlHandlerInfo(target_origin_)}); + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); + + RegisterWebAppWithUrlHandlers(app2_url_, + {apps::UrlHandlerInfo(target_origin_)}); + ExpectUpdateUrlHandlers(kEmptyList, kEmptyList); + + // Save user choice to open in browser. + web_app::url_handler_prefs::SaveOpenInBrowser(local_state(), + url_in_target_origin_, time_1_); + + // WebUI should show the entry to open this origin+path in the browser only + // once even though it is written to multiple apps. + constexpr char kDisabledHandlers[] = R"([ { + "display_url": "target-1.com", + "has_origin_wildcard": false, + "origin_key": "https://target-1.com", + "path": "/*" + }])"; + ExpectUpdateUrlHandlers(kEmptyList, kDisabledHandlers); +} + +} // namespace settings |