diff options
Diffstat (limited to 'chromium/chrome/browser/ui/webui')
378 files changed, 10817 insertions, 4766 deletions
diff --git a/chromium/chrome/browser/ui/webui/DEPS b/chromium/chrome/browser/ui/webui/DEPS index fcf6dcdf5a4..6a321049a58 100644 --- a/chromium/chrome/browser/ui/webui/DEPS +++ b/chromium/chrome/browser/ui/webui/DEPS @@ -1,5 +1,5 @@ include_rules = [ - "+chrome/services/app_service/public", + "+components/services/app_service/public", "+device/bluetooth", "+extensions/strings/grit/extensions_strings.h", @@ -11,3 +11,10 @@ include_rules = [ "+third_party/brotli", # For compressed resources. "+third_party/zlib/zlib.h", # For compression level constants. ] + +specific_include_rules = { + "chrome_webui_navigation_browsertest.cc": [ + "+content/browser/frame_host/render_frame_host_impl.h", + "+content/common/frame.mojom.h", + ], +}
\ No newline at end of file diff --git a/chromium/chrome/browser/ui/webui/about_ui.cc b/chromium/chrome/browser/ui/webui/about_ui.cc index 2bda9c07e29..a4fe8c0e5aa 100644 --- a/chromium/chrome/browser/ui/webui/about_ui.cc +++ b/chromium/chrome/browser/ui/webui/about_ui.cc @@ -440,7 +440,7 @@ class CrostiniCreditsHandler auto component_manager = g_browser_process->platform_part()->cros_component_manager(); if (!component_manager) { - LoadCredits(base::FilePath(chrome::kLinuxCreditsPath)); + RespondWithPlaceholder(); return; } component_manager->Load( @@ -461,8 +461,8 @@ class CrostiniCreditsHandler void LoadCrostiniCreditsFileAsync(base::FilePath credits_file_path) { if (!base::ReadFileToString(credits_file_path, &contents_)) { - // File with credits not found, ResponseOnUIThread will load credits - // from resources if contents_ is empty. + // File with credits not found, ResponseOnUIThread will load a placeholder + // if contents_ is empty. contents_.clear(); } } @@ -473,18 +473,19 @@ class CrostiniCreditsHandler LoadCredits(path.Append(kTerminaCreditsPath)); return; } - LoadCredits(base::FilePath(chrome::kLinuxCreditsPath)); + RespondWithPlaceholder(); + } + + void RespondWithPlaceholder() { + contents_.clear(); + ResponseOnUIThread(); } void ResponseOnUIThread() { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // If we fail to load Linux credits from disk, load the placeholder from - // resources. - // TODO(rjwright): Add a linux-specific placeholder in resources. + // If we fail to load Linux credits from disk, use the placeholder. if (contents_.empty() && path_ != kKeyboardUtilsPath) { - contents_ = - ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_OS_CREDITS_HTML); + contents_ = l10n_util::GetStringUTF8(IDS_CROSTINI_CREDITS_PLACEHOLDER); } std::move(callback_).Run(base::RefCountedString::TakeString(&contents_)); } diff --git a/chromium/chrome/browser/ui/webui/app_launcher_page_ui.cc b/chromium/chrome/browser/ui/webui/app_launcher_page_ui.cc index a6b2b88ee09..1fcf042bf88 100644 --- a/chromium/chrome/browser/ui/webui/app_launcher_page_ui.cc +++ b/chromium/chrome/browser/ui/webui/app_launcher_page_ui.cc @@ -28,6 +28,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "extensions/browser/extension_system.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -137,18 +138,21 @@ bool AppLauncherPageUI::HTMLSource::AllowCaching() { return false; } -std::string AppLauncherPageUI::HTMLSource::GetContentSecurityPolicyScriptSrc() { - // 'unsafe-inline' is added to script-src. - return "script-src chrome://resources 'self' 'unsafe-eval' 'unsafe-inline';"; -} - -std::string AppLauncherPageUI::HTMLSource::GetContentSecurityPolicyStyleSrc() { - return "style-src 'self' chrome://resources chrome://theme 'unsafe-inline';"; -} +std::string AppLauncherPageUI::HTMLSource::GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) { + if (directive == network::mojom::CSPDirectiveName::ScriptSrc) { + // 'unsafe-inline' is added to script-src. + return "script-src chrome://resources 'self' 'unsafe-eval' " + "'unsafe-inline';"; + } else if (directive == network::mojom::CSPDirectiveName::StyleSrc) { + return "style-src 'self' chrome://resources chrome://theme " + "'unsafe-inline';"; + } else if (directive == network::mojom::CSPDirectiveName::ImgSrc) { + return "img-src chrome://extension-icon chrome://app-icon chrome://theme " + "chrome://resources data:;"; + } -std::string AppLauncherPageUI::HTMLSource::GetContentSecurityPolicyImgSrc() { - return "img-src chrome://extension-icon chrome://app-icon chrome://theme " - "chrome://resources data:;"; + return content::URLDataSource::GetContentSecurityPolicy(directive); } AppLauncherPageUI::HTMLSource::~HTMLSource() = default; diff --git a/chromium/chrome/browser/ui/webui/app_launcher_page_ui.h b/chromium/chrome/browser/ui/webui/app_launcher_page_ui.h index 280e6003845..070ba242b3c 100644 --- a/chromium/chrome/browser/ui/webui/app_launcher_page_ui.h +++ b/chromium/chrome/browser/ui/webui/app_launcher_page_ui.h @@ -45,9 +45,8 @@ class AppLauncherPageUI : public content::WebUIController { std::string GetMimeType(const std::string&) override; bool ShouldReplaceExistingSource() override; bool AllowCaching() override; - std::string GetContentSecurityPolicyScriptSrc() override; - std::string GetContentSecurityPolicyStyleSrc() override; - std::string GetContentSecurityPolicyImgSrc() override; + std::string GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) override; private: diff --git a/chromium/chrome/browser/ui/webui/app_management/BUILD.gn b/chromium/chrome/browser/ui/webui/app_management/BUILD.gn index 6db2265d29e..d96d406038e 100644 --- a/chromium/chrome/browser/ui/webui/app_management/BUILD.gn +++ b/chromium/chrome/browser/ui/webui/app_management/BUILD.gn @@ -7,5 +7,5 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("mojo_bindings") { sources = [ "app_management.mojom" ] - public_deps = [ "//chrome/services/app_service/public/mojom" ] + public_deps = [ "//components/services/app_service/public/mojom" ] } diff --git a/chromium/chrome/browser/ui/webui/app_management/app_management.mojom b/chromium/chrome/browser/ui/webui/app_management/app_management.mojom index dce93502f75..c8b279f43f6 100644 --- a/chromium/chrome/browser/ui/webui/app_management/app_management.mojom +++ b/chromium/chrome/browser/ui/webui/app_management/app_management.mojom @@ -4,7 +4,7 @@ module app_management.mojom; -import "chrome/services/app_service/public/mojom/types.mojom"; +import "components/services/app_service/public/mojom/types.mojom"; struct App { string id; @@ -87,4 +87,6 @@ enum PwaPermissionType { // The Plugin VM app publisher uses this enum directly. enum PluginVmPermissionType { PRINTING = 0, + CAMERA = 1, + MICROPHONE = 2, }; diff --git a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc index 5c0641f3604..70124e8868f 100644 --- a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc +++ b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.cc @@ -15,8 +15,8 @@ #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/app_management/app_management.mojom.h" -#include "chrome/services/app_service/public/cpp/app_registry_cache.h" -#include "chrome/services/app_service/public/mojom/types.mojom.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/mojom/types.mojom.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" diff --git a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h index 039c18af90e..cd94f678a88 100644 --- a/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h +++ b/chromium/chrome/browser/ui/webui/app_management/app_management_page_handler.h @@ -9,7 +9,7 @@ #include "base/scoped_observer.h" #include "chrome/browser/ui/webui/app_management/app_management.mojom-forward.h" #include "chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.h" -#include "chrome/services/app_service/public/cpp/app_registry_cache.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/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" diff --git a/chromium/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc b/chromium/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc index 5ea8f88ffef..7df9ca2b444 100644 --- a/chromium/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/app_management/app_management_shelf_delegate_chromeos.cc @@ -10,7 +10,7 @@ #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" #include "chrome/browser/ui/webui/app_management/app_management_page_handler.h" -#include "chrome/services/app_service/public/mojom/types.mojom.h" +#include "components/services/app_service/public/mojom/types.mojom.h" using apps::mojom::OptionalBool; diff --git a/chromium/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc b/chromium/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc index 99a612517da..e570ba4c5ed 100644 --- a/chromium/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/chrome_url_data_manager_browsertest.cc @@ -140,7 +140,8 @@ IN_PROC_BROWSER_TEST_F(ChromeURLDataManagerTest, LargeResourceScale) { } class ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled - : public InProcessBrowserTest { + : public InProcessBrowserTest, + public testing::WithParamInterface<const char*> { public: ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled() { feature_list_.InitAndEnableFeature(features::kWebUIReportOnlyTrustedTypes); @@ -166,229 +167,77 @@ class ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled }; // Verify that there's no Trusted Types violation in chrome://chrome-urls -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInChromeUrls) { - CheckTrustedTypesViolation("chrome://chrome-urls"); -} - -// Verify that there's no Trusted Types violation in chrome://blob-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInBlobInternals) { - CheckTrustedTypesViolation("chrome://blob-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://device-log -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInDeviceLog) { - CheckTrustedTypesViolation("chrome://device-log"); -} - -// Verify that there's no Trusted Types violation in chrome://devices -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInDevices) { - CheckTrustedTypesViolation("chrome://devices"); -} - -// Verify that there's no Trusted Types violation in chrome://gcm-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInGCMInternals) { - CheckTrustedTypesViolation("chrome://gcm-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://inspect -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInInspect) { - CheckTrustedTypesViolation("chrome://inspect"); -} - -// Verify that there's no Trusted Types violation in chrome://local-state -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInLocalState) { - CheckTrustedTypesViolation("chrome://local-state"); -} - -// Verify that there's no Trusted Types violation in chrome://net-export -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInNetExport) { - CheckTrustedTypesViolation("chrome://net-export"); -} - -// Verify that there's no Trusted Types violation in chrome://policy -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInPolicy) { - CheckTrustedTypesViolation("chrome://policy"); -} - -// Verify that there's no Trusted Types violation in chrome://predictors -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInPredictors) { - CheckTrustedTypesViolation("chrome://predictors"); -} - -// Verify that there's no Trusted Types violation in chrome://prefs-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInPrefsInternals) { - CheckTrustedTypesViolation("chrome://prefs-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://sandbox -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInSandbox) { - CheckTrustedTypesViolation("chrome://sandbox"); -} - -// Verify that there's no Trusted Types violation in chrome://suggestions -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInSuggestions) { - CheckTrustedTypesViolation("chrome://suggestions"); -} - -// Verify that there's no Trusted Types violation in chrome://terms -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInTerms) { - CheckTrustedTypesViolation("chrome://terms"); -} - -// Verify that there's no Trusted Types violation in chrome://user-actions -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInUserActions) { - CheckTrustedTypesViolation("chrome://user-actions"); -} - -// Verify that there's no Trusted Types violation in chrome://webrtc-logs -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInWebrtcLogs) { - CheckTrustedTypesViolation("chrome://webrtc-logs"); -} - -// Verify that there's no Trusted Types violation in chrome://autofill-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInAutofillInternals) { - CheckTrustedTypesViolation("chrome://autofill-internals"); -} - -// Verify that there's no Trusted Types violation in -// chrome://password-manager-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInPasswordManagerInternals) { - CheckTrustedTypesViolation("chrome://password-manager-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://media-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInMediaInternals) { - CheckTrustedTypesViolation("chrome://media-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://histograms -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInHistograms) { - CheckTrustedTypesViolation("chrome://histograms"); -} - -// Verify that there's no Trusted Types violation in chrome://accessibility -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInAccessibility) { - CheckTrustedTypesViolation("chrome://accessibility"); -} - -// Verify that there's no Trusted Types violation in chrome://process-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInProcessInternals) { - CheckTrustedTypesViolation("chrome://process-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://credits -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInCredits) { - CheckTrustedTypesViolation("chrome://credits"); -} - -// Verify that there's no Trusted Types violation in -// chrome://bluetooth-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInBluetoothInternals) { - CheckTrustedTypesViolation("chrome://bluetooth-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://media-engagement -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInMediaEngagement) { - CheckTrustedTypesViolation("chrome://media-engagement"); -} - -// Verify that there's no Trusted Types violation in chrome://site-engagement -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInSiteEngagement) { - CheckTrustedTypesViolation("chrome://site-engagement"); -} - -// Verify that there's no Trusted Types violation in -// chrome://translate-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInTranslateInternals) { - CheckTrustedTypesViolation("chrome://translate-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://system -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInSystem) { - CheckTrustedTypesViolation("chrome://system"); -} - -// Verify that there's no Trusted Types violation in chrome://usb-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInUSBInternals) { - CheckTrustedTypesViolation("chrome://usb-internals"); -} - -// Verify that there's no Trusted Types violation in -// chrome://interventions-internals -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInInterventionsInternals) { - CheckTrustedTypesViolation("chrome://interventions-internals"); -} - -// Verify that there's no Trusted Types violation in chrome://version -IN_PROC_BROWSER_TEST_F( - ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInVersion) { - CheckTrustedTypesViolation("chrome://version"); -} +IN_PROC_BROWSER_TEST_P( + ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, + NoTrustedTypesViolation) { + CheckTrustedTypesViolation(GetParam()); +} + +// Non-exhaustive list of chrome:// URLs to test for trusted types violations. +// This list was derived from chrome://about. :) +static constexpr const char* const kChromeUrls[] = { + "chrome://accessibility", + "chrome://autofill-internals", + "chrome://blob-internals", + "chrome://bluetooth-internals", + "chrome://chrome-urls", + "chrome://components", + "chrome://conflicts", + "chrome://crashes", + "chrome://credits", + "chrome://cryptohome", + "chrome://device-log", + "chrome://devices", + "chrome://download-internals", + "chrome://drive-internals", + "chrome://explore-sites-internals", + "chrome://first-run", + "chrome://flags", + "chrome://gcm-internals", + "chrome://gpu", + "chrome://histograms", + "chrome://indexeddb-internals", + "chrome://inspect", + "chrome://interventions-internals", + "chrome://invalidations", + "chrome://linux-proxy-config", + "chrome://local-state", + "chrome://machine-learning-internals", + "chrome://media-engagement", + "chrome://media-internals", + "chrome://nacl", + "chrome://net-export", + "chrome://network-errors", + "chrome://ntp-tiles-internals", + "chrome://omnibox", + "chrome://password-manager-internals", + "chrome://policy", + "chrome://power", + "chrome://predictors", + "chrome://prefs-internals", + "chrome://process-internals", + "chrome://quota-internals", + "chrome://safe-browsing", + "chrome://sandbox", + "chrome://serviceworker-internals", + "chrome://signin-internals", + "chrome://site-engagement", + "chrome://snippets-internals", + "chrome://suggestions", + "chrome://supervised-user-internals", + "chrome://sync-internals", + "chrome://system", + "chrome://terms", + "chrome://translate-internals", + "chrome://usb-internals", + "chrome://user-actions", + "chrome://version", + "chrome://webapks", + "chrome://webrtc-internals", + "chrome://webrtc-logs", +}; -// Verify that there's no Trusted Types violation in chrome://quota-internals -IN_PROC_BROWSER_TEST_F( +INSTANTIATE_TEST_SUITE_P( + , ChromeURLDataManagerTestWithWebUIReportOnlyTrustedTypesEnabled, - NoTrustedTypesViolationInQuotaInternals) { - CheckTrustedTypesViolation("chrome://quota-internals"); -} + ::testing::ValuesIn(kChromeUrls)); diff --git a/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 525c874c05e..60709ee12ab 100644 --- a/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc @@ -15,6 +15,7 @@ #include "build/build_config.h" #include "chrome/browser/about_flags.h" #include "chrome/browser/accessibility/accessibility_ui.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/buildflags.h" #include "chrome/browser/devtools/devtools_ui_bindings.h" #include "chrome/browser/engagement/site_engagement_service.h" @@ -28,10 +29,9 @@ #include "chrome/browser/ui/webui/autofill_and_password_manager_internals/password_manager_internals_ui.h" #include "chrome/browser/ui/webui/bluetooth_internals/bluetooth_internals_ui.h" #include "chrome/browser/ui/webui/chrome_url_disabled_ui.h" -#include "chrome/browser/ui/webui/chromeos/account_manager_error_ui.h" -#include "chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h" -#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.h" -#include "chrome/browser/ui/webui/chromeos/camera/camera_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.h" #include "chrome/browser/ui/webui/components/components_ui.h" #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" @@ -43,6 +43,7 @@ #include "chrome/browser/ui/webui/flags_ui.h" #include "chrome/browser/ui/webui/gcm_internals_ui.h" #include "chrome/browser/ui/webui/identity_internals_ui.h" +#include "chrome/browser/ui/webui/internals/internals_ui.h" #include "chrome/browser/ui/webui/interstitials/interstitial_ui.h" #include "chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h" #include "chrome/browser/ui/webui/invalidations_ui.h" @@ -53,6 +54,7 @@ #include "chrome/browser/ui/webui/media/media_history_ui.h" #include "chrome/browser/ui/webui/media/webrtc_logs_ui.h" #include "chrome/browser/ui/webui/memory_internals_ui.h" +#include "chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h" #include "chrome/browser/ui/webui/net_export_ui.h" #include "chrome/browser/ui/webui/net_internals/net_internals_ui.h" #include "chrome/browser/ui/webui/notifications_internals/notifications_internals_ui.h" @@ -66,15 +68,17 @@ #include "chrome/browser/ui/webui/signin_internals_ui.h" #include "chrome/browser/ui/webui/sync_internals_ui.h" #include "chrome/browser/ui/webui/translate_internals/translate_internals_ui.h" -#include "chrome/browser/ui/webui/ukm/ukm_internals_ui.h" #include "chrome/browser/ui/webui/usb_internals/usb_internals_ui.h" #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h" #include "chrome/browser/ui/webui/version_ui.h" +#include "chrome/browser/web_applications/system_web_app_manager.h" #include "chrome/common/buildflags.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" +#include "chromeos/components/camera_app_ui/camera_app_ui.h" +#include "chromeos/components/camera_app_ui/url_constants.h" #include "components/favicon/core/favicon_service.h" #include "components/favicon_base/favicon_util.h" #include "components/favicon_base/select_favicon_frames.h" @@ -101,12 +105,6 @@ #include "ui/web_dialogs/web_dialog_ui.h" #include "url/gurl.h" -#if BUILDFLAG(ENABLE_KALEIDOSCOPE) -#include "chrome/browser/media/kaleidoscope/internal/kaleidoscope_content_ui.h" -#include "chrome/browser/media/kaleidoscope/internal/kaleidoscope_ui.h" -#include "media/base/media_switches.h" -#endif // BUILDFLAG(ENABLE_KALEIDOSCOPE) - #if BUILDFLAG(ENABLE_NACL) #include "chrome/browser/ui/webui/nacl_ui.h" #endif @@ -131,7 +129,10 @@ #endif // BUILDFLAG(ENABLE_FEED_IN_CHROME) #else // defined(OS_ANDROID) #include "chrome/browser/media/feeds/media_feeds_service.h" +#include "chrome/browser/media/kaleidoscope/constants.h" +#include "chrome/browser/media/kaleidoscope/kaleidoscope_ui.h" #include "chrome/browser/media/router/media_router_feature.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h" #include "chrome/browser/ui/webui/devtools_ui.h" #include "chrome/browser/ui/webui/downloads/downloads_ui.h" @@ -139,6 +140,7 @@ #include "chrome/browser/ui/webui/inspect_ui.h" #include "chrome/browser/ui/webui/management_ui.h" #include "chrome/browser/ui/webui/media_router/media_router_internals_ui.h" +#include "chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" #include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h" @@ -146,7 +148,9 @@ #include "chrome/browser/ui/webui/signin/sync_confirmation_ui.h" #include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h" #include "chrome/browser/ui/webui/system_info_ui.h" +#include "chrome/browser/ui/webui/tab_search/tab_search_ui.h" #include "chrome/browser/ui/webui/web_footer_experiment_ui.h" +#include "media/base/media_switches.h" #endif // defined(OS_ANDROID) #if defined(OS_CHROMEOS) @@ -206,6 +210,8 @@ #include "chrome/browser/ui/webui/chromeos/emulator/device_emulator_ui.h" #include "chromeos/components/sample_system_web_app_ui/sample_system_web_app_ui.h" #include "chromeos/components/sample_system_web_app_ui/url_constants.h" +#include "chromeos/components/telemetry_extension_ui/telemetry_extension_ui.h" +#include "chromeos/components/telemetry_extension_ui/url_constants.h" #endif #if !defined(OS_CHROMEOS) @@ -214,11 +220,11 @@ #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) #include "chrome/browser/ui/sync/sync_promo_ui.h" -#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/webui/browser_switch/browser_switch_ui.h" #include "chrome/browser/ui/webui/signin/profile_picker_ui.h" #include "chrome/browser/ui/webui/signin/signin_email_confirmation_ui.h" #include "chrome/browser/ui/webui/signin/signin_error_ui.h" +#include "chrome/browser/ui/webui/signin/signin_reauth_ui.h" #include "chrome/browser/ui/webui/signin/user_manager_ui.h" #include "chrome/browser/ui/webui/welcome/helpers.h" #include "chrome/browser/ui/webui/welcome/welcome_ui.h" @@ -397,6 +403,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, if (!content::HasWebUIScheme(url)) return nullptr; + // This factory doesn't support chrome-untrusted:// WebUIs. + if (url.SchemeIs(content::kChromeUIUntrustedScheme)) + return nullptr; + // Please keep this in alphabetical order. If #ifs or special logics are // required, add it below in the appropriate section. // @@ -436,6 +446,8 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI<FlagsUI>; if (url.host_piece() == chrome::kChromeUIGCMInternalsHost) return &NewWebUI<GCMInternalsUI>; + if (url.host_piece() == chrome::kChromeUIInternalsHost) + return &NewWebUI<InternalsUI>; if (url.host_piece() == chrome::kChromeUIInterstitialHost) return &NewWebUI<InterstitialUI>; if (url.host_piece() == chrome::kChromeUIInterventionsInternalsHost) @@ -478,8 +490,6 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI<SyncInternalsUI>; if (url.host_piece() == chrome::kChromeUITranslateInternalsHost) return &NewWebUI<TranslateInternalsUI>; - if (url.host_piece() == chrome::kChromeUIUkmHost) - return &NewWebUI<UkmInternalsUI>; if (url.host_piece() == chrome::kChromeUIUsbInternalsHost) return &NewWebUI<UsbInternalsUI>; if (url.host_piece() == chrome::kChromeUIUserActionsHost) @@ -513,6 +523,14 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, // Identity API is not available on Android. if (url.host_piece() == chrome::kChromeUIIdentityInternalsHost) return &NewWebUI<IdentityInternalsUI>; + if (base::FeatureList::IsEnabled(features::kNearbySharing)) { + if (url.host_piece() == chrome::kChromeUINearbyInternalsHost) + return &NewWebUI<NearbyInternalsUI>; + if (url.host_piece() == chrome::kChromeUINearbyShareHost && + profile->IsRegularProfile()) { + return &NewWebUI<nearby_share::NearbyShareDialogUI>; + } + } if (url.host_piece() == chrome::kChromeUINewTabHost) return &NewWebUI<NewTabUI>; if (url.host_piece() == chrome::kChromeUINewTabPageHost) @@ -520,6 +538,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, // Settings are implemented with native UI elements on Android. if (url.host_piece() == chrome::kChromeUISettingsHost) return &NewWebUI<settings::SettingsUI>; + if (url.host_piece() == chrome::kChromeUITabSearchHost && + base::FeatureList::IsEnabled(features::kTabSearch)) { + return &NewWebUI<TabSearchUI>; + } if (url.host_piece() == chrome::kChromeUIExtensionsHost) return &NewWebUI<extensions::ExtensionsUI>; if (url.host_piece() == chrome::kChromeUIHistoryHost) @@ -636,9 +658,10 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, return &NewWebUI<SysInternalsUI>; if (url.host_piece() == chrome::kChromeUIAssistantOptInHost) return &NewWebUI<chromeos::AssistantOptInUI>; - if (url.host_piece() == chrome::kChromeUICameraHost && - chromeos::CameraUI::IsEnabled()) { - return &NewWebUI<chromeos::CameraUI>; + if (url.host_piece() == chromeos::kChromeUICameraAppHost && + web_app::SystemWebAppManager::IsAppEnabled( + web_app::SystemAppType::CAMERA)) { + return &NewWebUI<chromeos::CameraAppUI>; } if (url.host_piece() == chrome::kChromeUIArcGraphicsTracingHost) @@ -655,6 +678,11 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, } if (url.host_piece() == chromeos::kChromeUISampleSystemWebAppHost) return &NewWebUI<chromeos::SampleSystemWebAppUI>; + if (url.host_piece() == chromeos::kChromeUITelemetryExtensionHost) { + if (base::FeatureList::IsEnabled(chromeos::features::kTelemetryExtension)) { + return &NewWebUI<chromeos::TelemetryExtensionUI>; + } + } #endif // !defined(OFFICIAL_BUILD) #endif // defined(OS_CHROMEOS) #if defined(OS_ANDROID) @@ -708,19 +736,21 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI* web_ui, if (url.host_piece() == chrome::kChromeUISigninEmailConfirmationHost && !profile->IsOffTheRecord()) return &NewWebUI<SigninEmailConfirmationUI>; + if (url.host_piece() == chrome::kChromeUISigninReauthHost && + !profile->IsOffTheRecord()) { + return &NewWebUI<SigninReauthUI>; + } if (url.host_piece() == chrome::kChromeUIWelcomeHost && welcome::IsEnabled(profile)) return &NewWebUI<WelcomeUI>; #endif -#if BUILDFLAG(ENABLE_KALEIDOSCOPE) +#if !defined(OS_ANDROID) if (base::FeatureList::IsEnabled(media::kKaleidoscope)) { - if (url.host_piece() == chrome::kChromeUIKaleidoscopeHost) + if (url.host_piece() == kKaleidoscopeUIHost) return &NewWebUI<KaleidoscopeUI>; - if (url.host_piece() == chrome::kChromeUIKaleidoscopeContentHost) - return &NewWebUI<KaleidoscopeContentUI>; } -#endif // BUILDFLAG(ENABLE_KALEIDOSCOPE) +#endif // !defined(OS_ANDROID) #if BUILDFLAG(ENABLE_NACL) if (url.host_piece() == chrome::kChromeUINaClHost) return &NewWebUI<NaClUI>; @@ -945,11 +975,6 @@ bool ChromeWebUIControllerFactory::IsWebUIAllowedToMakeNetworkRequests( // https://crbug.com/829414 origin.host() == chrome::kChromeUIPrintHost || #endif -#if BUILDFLAG(ENABLE_KALEIDOSCOPE) - // TODO(https://crbug.com/1039904): This is only for prototyping purposes. - // Must be removed before launch. - origin.host() == chrome::kChromeUIKaleidoscopeContentHost || -#endif // https://crbug.com/831812 origin.host() == chrome::kChromeUISyncConfirmationHost || // https://crbug.com/831813 diff --git a/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory_browsertest.cc b/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory_browsertest.cc new file mode 100644 index 00000000000..90231185b83 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chrome_web_ui_controller_factory_browsertest.cc @@ -0,0 +1,42 @@ +// Copyright 2020 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/chrome_web_ui_controller_factory.h" + +#include "base/strings/strcat.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/web_ui_browsertest_util.h" + +using ChromeWebUIControllerFactoryBrowserTest = InProcessBrowserTest; + +// Verify that if there is a chrome-untrusted:// URLDataSource with the same +// host as a chrome:// WebUI, we serve the right resources and we don't use the +// wrong WebUI object. +IN_PROC_BROWSER_TEST_F(ChromeWebUIControllerFactoryBrowserTest, + ChromeUntrustedSameHost) { + content::AddUntrustedDataSource(browser()->profile(), + chrome::kChromeUIVersionHost); + EXPECT_TRUE(ui_test_utils::NavigateToURL( + browser(), + GURL(base::StrCat({"chrome-untrusted://", chrome::kChromeUIVersionHost, + "/title2.html"})))); + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + EXPECT_EQ(base::ASCIIToUTF16("Title Of Awesomeness"), + web_contents->GetTitle()); + EXPECT_FALSE(web_contents->GetWebUI()); + + // Check that we can navigate to chrome://version and that it serves the right + // resources and has a WebUI. + EXPECT_TRUE(ui_test_utils::NavigateToURL( + browser(), GURL(base::StrCat({"chrome://", chrome::kChromeUIVersionHost, + "/title2.html"})))); + EXPECT_EQ(base::ASCIIToUTF16("About Version"), web_contents->GetTitle()); + EXPECT_TRUE(web_contents->GetWebUI()); +} diff --git a/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc b/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc index 52c3b47241d..1023da7f2bd 100644 --- a/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/chrome_webui_navigation_browsertest.cc @@ -8,6 +8,8 @@ #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/common/frame.mojom.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -18,6 +20,19 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "url/url_constants.h" +namespace { + +content::mojom::OpenURLParamsPtr CreateOpenURLParams(const GURL& url) { + auto params = content::mojom::OpenURLParams::New(); + params->url = url; + params->disposition = WindowOpenDisposition::CURRENT_TAB; + params->should_replace_current_entry = false; + params->user_gesture = true; + return params; +} + +} // namespace + // Tests embedder specific behavior of WebUIs. class ChromeWebUINavigationBrowserTest : public InProcessBrowserTest { public: @@ -61,9 +76,9 @@ IN_PROC_BROWSER_TEST_F(ChromeWebUINavigationBrowserTest, EXPECT_EQ("about:blank", child->GetLastCommittedURL()); content::TestNavigationObserver observer(web_contents); - GURL webui_url(content::GetWebUIURL("web-ui/title1.html?noxfo=true")); - content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(), - webui_url); + static_cast<content::RenderFrameHostImpl*>(child)->OpenURL( + CreateOpenURLParams( + content::GetWebUIURL("web-ui/title1.html?noxfo=true"))); observer.Wait(); // Retrieve the RenderFrameHost again since it might have been swapped. @@ -100,10 +115,9 @@ IN_PROC_BROWSER_TEST_F( content::AddUntrustedDataSource(browser()->profile(), "test-iframe-host", csp); - GURL untrusted_url( - content::GetChromeUntrustedUIURL("test-iframe-host/title1.html")); - content::PwnMessageHelper::OpenURL(child->GetProcess(), child->GetRoutingID(), - untrusted_url); + static_cast<content::RenderFrameHostImpl*>(child)->OpenURL( + CreateOpenURLParams( + content::GetChromeUntrustedUIURL("test-iframe-host/title1.html"))); observer.Wait(); // Retrieve the RenderFrameHost again since it might have been swapped. diff --git a/chromium/chrome/browser/ui/webui/chromeos/DEPS b/chromium/chrome/browser/ui/webui/chromeos/DEPS index c80e0efe1d0..a0bba8a28e5 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/DEPS +++ b/chromium/chrome/browser/ui/webui/chromeos/DEPS @@ -7,10 +7,3 @@ include_rules = [ "+services/device/public/mojom", "+services/network", ] - -specific_include_rules = { - "keyboard_overlay_ui\.cc": [ - # TODO(mash): Remove. http://crbug.com/770866 - "+ash/shell.h", - ], -} diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/account_manager/OWNERS new file mode 100644 index 00000000000..4df9ab85cdc --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/OWNERS @@ -0,0 +1,2 @@ +anastasiian@chromium.org +sinhak@chromium.org diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.cc index 83c0f366342..b329c687a33 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/account_manager_error_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.h" #include "base/bind.h" #include "build/branding_buildflags.h" @@ -53,6 +53,10 @@ AccountManagerErrorUI::AccountManagerErrorUI(content::WebUI* web_ui) // Add required resources. html_source->AddResourcePath("account_manager_shared.css", IDR_ACCOUNT_MANAGER_SHARED_CSS); + html_source->AddResourcePath("account_manager_browser_proxy.html", + IDR_ACCOUNT_MANAGER_BROWSER_PROXY_HTML); + html_source->AddResourcePath("account_manager_browser_proxy.js", + IDR_ACCOUNT_MANAGER_BROWSER_PROXY_JS); html_source->AddResourcePath("account_manager_error.js", IDR_ACCOUNT_MANAGER_ERROR_JS); diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.h index 95e8a498e36..f740e1bf35f 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_error_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ERROR_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ERROR_UI_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_ERROR_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_ERROR_UI_H_ #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -25,4 +25,4 @@ class AccountManagerErrorUI : public ui::WebDialogUI { } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ERROR_UI_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_ERROR_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_dialog.cc index b17dd07fe5f..0765cfa96f0 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_dialog.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_dialog.h" #include <string> diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_dialog.h index 67fea954e98..e92b754253c 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_dialog.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ #include <string> @@ -37,4 +37,4 @@ class AccountManagerWelcomeDialog : public SystemWebDialogDelegate { } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_WELCOME_DIALOG_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.cc index 16a69c1d232..8248231f214 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.h" #include "base/bind.h" #include "base/strings/utf_string_conversions.h" @@ -45,6 +45,10 @@ AccountManagerWelcomeUI::AccountManagerWelcomeUI(content::WebUI* web_ui) IDR_ACCOUNT_MANAGER_SHARED_CSS); html_source->AddResourcePath("account_manager_welcome.js", IDR_ACCOUNT_MANAGER_WELCOME_JS); + html_source->AddResourcePath("account_manager_browser_proxy.html", + IDR_ACCOUNT_MANAGER_BROWSER_PROXY_HTML); + html_source->AddResourcePath("account_manager_browser_proxy.js", + IDR_ACCOUNT_MANAGER_BROWSER_PROXY_JS); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) html_source->AddResourcePath("account_manager_welcome_1x.png", IDR_ACCOUNT_MANAGER_WELCOME_1X_PNG); diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.h index ded176fe6df..9a68ddc6579 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_manager_welcome_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_UI_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_WELCOME_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_WELCOME_UI_H_ #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -24,4 +24,4 @@ class AccountManagerWelcomeUI : public ui::WebDialogUI { } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_WELCOME_UI_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MANAGER_WELCOME_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_dialog.cc index aeb9b5bfaa6..31504a89ca1 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_dialog.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_dialog.h" #include <string> @@ -10,7 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/settings_window_manager_chromeos.h" -#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h" #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "components/prefs/pref_service.h" diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_dialog.h index 96670974836..6622d961508 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.h +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_dialog.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_DIALOG_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_DIALOG_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MIGRATION_WELCOME_DIALOG_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MIGRATION_WELCOME_DIALOG_H_ #include <string> @@ -42,4 +42,4 @@ class AccountMigrationWelcomeDialog : public SystemWebDialogDelegate { } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_DIALOG_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MIGRATION_WELCOME_DIALOG_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.cc index 12b79aaed4a..2d6596522c5 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h" #include <memory> #include <string> @@ -12,7 +12,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/branding_buildflags.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h" +#include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" @@ -54,9 +54,9 @@ class MigrationMessageHandler : public content::WebUIMessageHandler { CHECK(!args->GetList().empty()); const std::string& account_email = args->GetList()[0].GetString(); - InlineLoginHandlerDialogChromeOS::Show( - account_email, InlineLoginHandlerDialogChromeOS::Source:: - kAccountManagerMigrationWelcomeScreen); + InlineLoginDialogChromeOS::Show(account_email, + InlineLoginDialogChromeOS::Source:: + kAccountManagerMigrationWelcomeScreen); HandleCloseDialog(args); } @@ -98,10 +98,10 @@ AccountMigrationWelcomeUI::AccountMigrationWelcomeUI(content::WebUI* web_ui) IDR_ACCOUNT_MANAGER_SHARED_CSS); html_source->AddResourcePath("account_migration_welcome.js", IDR_ACCOUNT_MIGRATION_WELCOME_JS); - html_source->AddResourcePath("account_migration_browser_proxy.html", - IDR_ACCOUNT_MIGRATION_BROWSER_PROXY_HTML); - html_source->AddResourcePath("account_migration_browser_proxy.js", - IDR_ACCOUNT_MIGRATION_BROWSER_PROXY_JS); + html_source->AddResourcePath("account_manager_browser_proxy.html", + IDR_ACCOUNT_MANAGER_BROWSER_PROXY_HTML); + html_source->AddResourcePath("account_manager_browser_proxy.js", + IDR_ACCOUNT_MANAGER_BROWSER_PROXY_JS); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) html_source->AddResourcePath("account_manager_welcome_1x.png", IDR_ACCOUNT_MANAGER_WELCOME_1X_PNG); diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.h b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h index 24a0c7dd8be..3c7ec92e12d 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_UI_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MIGRATION_WELCOME_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MIGRATION_WELCOME_UI_H_ #include "base/macros.h" #include "base/memory/weak_ptr.h" @@ -26,4 +26,4 @@ class AccountMigrationWelcomeUI : public ui::WebDialogUI { } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_UI_H_ +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MANAGER_ACCOUNT_MIGRATION_WELCOME_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_proxy_test.js b/chromium/chrome/browser/ui/webui/chromeos/account_migration_proxy_test.js deleted file mode 100644 index a81f50bc8c0..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_proxy_test.js +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019 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. - -/** @implements {account_migration.AccountMigrationBrowserProxy} */ -class TestAccountMigrationBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'closeDialog', - 'reauthenticateAccount', - ]); - } - - /** @override */ - closeDialog() { - this.methodCalled('closeDialog'); - } - - /** @override */ - reauthenticateAccount(account_email) { - this.methodCalled('reauthenticateAccount', account_email); - } -} diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js b/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js deleted file mode 100644 index 7c8a1f74674..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2019 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. - -GEN('#include "content/public/test/browser_test.h"'); - -/** - * Test fixture for generated tests. - * @extends {testing.Test} - */ -function AccountMigrationWelcomeUITest() {} -let testBrowserProxy = null; - -AccountMigrationWelcomeUITest.prototype = { - __proto__: testing.Test.prototype, - - /** - * Define the C++ fixture class and include it. - * @type {?string} - * @override - */ - typedefCppFixture: 'AccountMigrationWelcomeUITest', - - /** @override */ - extraLibraries: [ - '//chrome/test/data/webui/test_browser_proxy.js', - 'account_migration_proxy_test.js', - ], - - /** @override */ - setUp: function() { - testBrowserProxy = new TestAccountMigrationBrowserProxy(); - account_migration.AccountMigrationBrowserProxyImpl.instance_ = - testBrowserProxy; - testing.Test.prototype.setUp.call(this); - }, - - /** @override */ - testGenPreamble: function() { - GEN('ShowDialog();'); - }, - - /** - * Tests that the dialog opened to the correct URL. - */ - testDialogUrl: function() { - // Remove slash at the end of URL if present. - const url = window.location.href.replace(/\/$/, ''); - assertEquals(chrome.getVariableValue('expectedUrl'), url); - }, - - /** - * Tests that |closeDialog| function get called after clicking - * the cancel button - */ - testCloseDialog: function() { - $('cancel-button').click(); - assertEquals(1, testBrowserProxy.getCallCount('closeDialog')); - }, - - /** - * Tests that |reauthenticateAccount| function get called with expected email - * after clicking the migrate button. - */ - testReauthenticateAccount: function() { - $('migrate-button').click(); - assertEquals(1, testBrowserProxy.getCallCount('reauthenticateAccount')); - testBrowserProxy.whenCalled('reauthenticateAccount').then(email => { - assertEquals(chrome.getVariableValue('expectedEmail'), email); - }); - }, -}; - -GEN('#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.h"'); -GEN(''); - - -TEST_F('AccountMigrationWelcomeUITest', 'testDialogURL', function() { - this.testDialogUrl(); -}); - -TEST_F('AccountMigrationWelcomeUITest', 'testCloseDialog', function() { - this.testCloseDialog(); -}); - -TEST_F( - 'AccountMigrationWelcomeUITest', 'testReauthenticateAccount', function() { - this.testReauthenticateAccount(); - }); diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc b/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc deleted file mode 100644 index a9b5b792260..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.cc +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2019 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/chromeos/account_migration_welcome_ui_test.h" - -#include "base/macros.h" -#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.h" -#include "chrome/common/url_constants.h" -#include "content/public/browser/render_view_host.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_message_handler.h" -#include "content/public/test/browser_test_utils.h" -#include "ui/web_dialogs/web_dialog_ui.h" - -AccountMigrationWelcomeUITest::AccountMigrationWelcomeUITest() = default; -AccountMigrationWelcomeUITest::~AccountMigrationWelcomeUITest() = default; - -void AccountMigrationWelcomeUITest::ShowDialog() { - auto* account_email = "test@example.com"; - auto* dialog = chromeos::AccountMigrationWelcomeDialog::Show(account_email); - auto* webui = dialog->GetWebUIForTest(); - auto* web_contents = webui->GetWebContents(); - content::WaitForLoadStop(web_contents); - web_contents->GetMainFrame()->SetWebUIProperty( - "expectedUrl", chrome::kChromeUIAccountMigrationWelcomeURL); - web_contents->GetMainFrame()->SetWebUIProperty("expectedEmail", - account_email); - SetWebUIInstance(webui); -} diff --git a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.h b/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.h deleted file mode 100644 index 29ef97bf54a..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/account_migration_welcome_ui_test.h +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2019 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_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_UI_TEST_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_UI_TEST_H_ - -#include "chrome/test/base/ui_test_utils.h" -#include "chrome/test/base/web_ui_browser_test.h" -// Test framework for -// chrome/browser/ui/webui/chromeos/account_migration_welcome_test.js -class AccountMigrationWelcomeUITest : public WebUIBrowserTest { - public: - AccountMigrationWelcomeUITest(); - ~AccountMigrationWelcomeUITest() override; - - protected: - void ShowDialog(); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ACCOUNT_MIGRATION_WELCOME_UI_TEST_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc index cc951296439..021040da4f5 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc @@ -20,7 +20,7 @@ #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_metrics_recorder.h" -#include "chrome/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" #include "components/signin/public/identity_manager/access_token_fetcher.h" #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/consent_level.h" @@ -55,10 +55,16 @@ void AddSupervisionHandler::RequestClose(RequestCloseCallback callback) { void AddSupervisionHandler::GetInstalledArcApps( GetInstalledArcAppsCallback callback) { Profile* profile = Profile::FromWebUI(web_ui_); + if (!profile) { + DLOG(WARNING) << "Profile not found in WebUI"; + std::move(callback).Run({}); + return; + } + apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile(profile); - if (arc::ArcSessionManager::Get() == nullptr) { + if (!arc::ArcSessionManager::Get()) { DLOG(WARNING) << "No ArcSessionManager available"; std::move(callback).Run({}); return; @@ -71,15 +77,9 @@ void AddSupervisionHandler::GetInstalledArcApps( } std::vector<std::string> installed_arc_apps; - proxy->AppRegistryCache().ForEachApp( [&installed_arc_apps, profile](const apps::AppUpdate& update) { - // We don't include "sticky" ARC apps because they are system-required - // apps that should not be offered for uninstallation. TODO(danan): - // check for stickyness via the App Service instead when that is - // available. (https://crbug.com/948408). - if (ShouldIncludeAppUpdate(update) && - !arc::IsArcAppSticky(update.AppId(), profile)) { + if (ShouldIncludeAppUpdate(update)) { std::string package_name = arc::AppIdToArcPackageName(update.AppId(), profile); if (!package_name.empty()) diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.cc index 0c7a610df3e..8bc9b023bb2 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.cc @@ -9,14 +9,12 @@ #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_metrics_recorder.h" -#include "chrome/services/app_service/public/cpp/app_update.h" -#include "chrome/services/app_service/public/mojom/types.mojom.h" +#include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/mojom/types.mojom.h" bool ShouldIncludeAppUpdate(const apps::AppUpdate& app_update) { - // TODO(danan): update this to only return sticky = true arc apps when that - // attribute is available via the App Service (https://crbug.com/948408). - - return app_update.AppType() == apps::mojom::AppType::kArc; + return app_update.AppType() == apps::mojom::AppType::kArc && + app_update.InstallSource() != apps::mojom::InstallSource::kSystem; } void LogOutHelper() { diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils_unittest.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils_unittest.cc index 6236a41ff69..2640236a92b 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils_unittest.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils_unittest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.h" -#include "chrome/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/cpp/app_update.h" #include "testing/gtest/include/gtest/gtest.h" using AddSupervisionHandlerUtilsTest = testing::Test; @@ -13,12 +13,13 @@ TEST_F(AddSupervisionHandlerUtilsTest, TestShouldIncludeAppUpdate) { // Return ARC apps. apps::mojom::App arc_state; arc_state.app_type = apps::mojom::AppType::kArc; - apps::AppUpdate arc_update(&arc_state, nullptr /* delta */); + apps::AppUpdate arc_update(&arc_state, nullptr /* delta */, EmptyAccountId()); EXPECT_TRUE(ShouldIncludeAppUpdate(arc_update)); // Don't return non-ARC apps. apps::mojom::App non_arc_state; non_arc_state.app_type = apps::mojom::AppType::kBuiltIn; - apps::AppUpdate non_arc_update(&non_arc_state, nullptr /* delta */); + apps::AppUpdate non_arc_update(&non_arc_state, nullptr /* delta */, + EmptyAccountId()); EXPECT_FALSE(ShouldIncludeAppUpdate(non_arc_update)); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc index 7e7fde7f98c..fa0110c7cf3 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui_browsertest.cc @@ -25,10 +25,6 @@ namespace chromeos { -// NOTE: This test is flaky and therefore disabled under MSAN: -// https://crbug.com/1002560 -#if !defined(MEMORY_SANITIZER) - namespace { const char kGetAddSupervisionUIElementJS[] = @@ -94,14 +90,7 @@ class AddSupervisionBrowserTest : public InProcessBrowserTest { DISALLOW_COPY_AND_ASSIGN(AddSupervisionBrowserTest); }; -// Disabled on ASan and LSAn builds, because it's very flaky. See -// crbug.com/1004237 -#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) -#define MAYBE_URLParameters DISABLED_URLParameters -#else -#define MAYBE_URLParameters URLParameters -#endif -IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, MAYBE_URLParameters) { +IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, URLParameters) { // Open the Add Supervision URL. ui_test_utils::NavigateToURL(browser(), add_supervision_webui_url()); content::WaitForLoadStop(contents()); @@ -172,15 +161,7 @@ IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, ShowOfflineScreen) { std::string(".webviewDiv"))); } -// Disabled on ASan and LSAn builds, because it's very flaky. See -// crbug.com/1004237 -#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) -#define MAYBE_ShowConfirmSignoutDialog DISABLED_ShowConfirmSignoutDialog -#else -#define MAYBE_ShowConfirmSignoutDialog ShowConfirmSignoutDialog -#endif -IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, - MAYBE_ShowConfirmSignoutDialog) { +IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, ShowConfirmSignoutDialog) { // Open the Add Supervision URL. ui_test_utils::NavigateToURL(browser(), add_supervision_webui_url()); content::WaitForLoadStop(contents()); @@ -206,14 +187,7 @@ IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, ASSERT_TRUE(ConfirmSignoutDialog::IsShowing()); } -// Disabled on ASan and LSAn builds, because it's very flaky. See -// crbug.com/1004237 -#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) -#define MAYBE_UMATest DISABLED_UMATest -#else -#define MAYBE_UMATest UMATest -#endif -IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, MAYBE_UMATest) { +IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, UMATest) { base::HistogramTester histogram_tester; base::UserActionTester user_action_tester; @@ -246,6 +220,4 @@ IN_PROC_BROWSER_TEST_F(AddSupervisionBrowserTest, MAYBE_UMATest) { 1); } -#endif // !defined(MEMORY_SANITIZER) - } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.cc index d0a7fc4bb75..8beb112fa72 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/arc_graphics_tracing/arc_graphics_tracing_ui.cc @@ -14,6 +14,7 @@ #include "chrome/grit/browser_resources.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/webui/web_ui_util.h" namespace { @@ -36,7 +37,8 @@ content::WebUIDataSource* CreateGraphicsDataSource() { IDR_ARC_GRAPHICS_TRACING_UI_JS); source->AddResourcePath(kArcTracingCssPath, IDR_ARC_TRACING_CSS); source->AddResourcePath(kArcTracingUiJsPath, IDR_ARC_TRACING_UI_JS); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self';"); base::DictionaryValue localized_strings; @@ -58,7 +60,8 @@ content::WebUIDataSource* CreateOverviewDataSource() { IDR_ARC_OVERVIEW_TRACING_UI_JS); source->AddResourcePath(kArcTracingCssPath, IDR_ARC_TRACING_CSS); source->AddResourcePath(kArcTracingUiJsPath, IDR_ARC_TRACING_UI_JS); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self';"); base::DictionaryValue localized_strings; diff --git a/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc index d74e24d8ba0..8a66b8f69fe 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc @@ -31,6 +31,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_features.h" #include "net/base/url_util.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/chromeos/resources/grit/ui_chromeos_resources.h" #include "ui/display/display.h" #include "ui/display/screen.h" @@ -93,7 +94,8 @@ AssistantOptInUI::AssistantOptInUI(content::WebUI* web_ui) IDR_ASSISTANT_VOICE_MATCH_ANIMATION); source->AddResourcePath("voice_match_already_setup_animation.json", IDR_ASSISTANT_VOICE_MATCH_ALREADY_SETUP_ANIMATION); - source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, "worker-src blob: 'self';"); content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source); // Do not zoom for Assistant opt-in web contents. diff --git a/chromium/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc index b65490702e4..4ff6decf773 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/bluetooth_pairing_dialog.cc @@ -7,8 +7,10 @@ #include "base/json/json_writer.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chromeos/bluetooth_dialog_localized_strings_provider.h" +#include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" -#include "chrome/grit/browser_resources.h" +#include "chrome/grit/bluetooth_pairing_dialog_resources.h" +#include "chrome/grit/bluetooth_pairing_dialog_resources_map.h" #include "chrome/grit/generated_resources.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui.h" @@ -20,6 +22,14 @@ namespace chromeos { namespace { +#if !BUILDFLAG(OPTIMIZE_WEBUI) +namespace { +const char kGeneratedPath[] = + "@out_folder@/gen/chrome/browser/resources/chromeos/" + "bluetooth_pairing_dialog/"; +} +#endif + constexpr int kBluetoothPairingDialogHeight = 375; void AddBluetoothStrings(content::WebUIDataSource* html_source) { @@ -103,15 +113,17 @@ BluetoothPairingDialogUI::BluetoothPairingDialogUI(content::WebUI* web_ui) AddBluetoothStrings(source); source->AddLocalizedString("title", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE); - source->UseStringsJs(); #if BUILDFLAG(OPTIMIZE_WEBUI) - source->SetDefaultResource(IDR_BLUETOOTH_PAIRING_DIALOG_VULCANIZED_HTML); - source->AddResourcePath("crisper.js", - IDR_BLUETOOTH_PAIRING_DIALOG_CRISPER_JS); + webui::SetupBundledWebUIDataSource( + source, "bluetooth_pairing_dialog.js", + IDR_BLUETOOTH_PAIRING_DIALOG_ROLLUP_JS, + IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML); #else - source->SetDefaultResource(IDR_BLUETOOTH_PAIRING_DIALOG_HTML); - source->AddResourcePath("bluetooth_pairing_dialog.js", - IDR_BLUETOOTH_PAIRING_DIALOG_JS); + webui::SetupWebUIDataSource( + source, + base::make_span(kBluetoothPairingDialogResources, + kBluetoothPairingDialogResourcesSize), + kGeneratedPath, IDR_BLUETOOTH_PAIRING_DIALOG_CONTAINER_HTML); #endif content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/camera/camera_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/camera/camera_ui.cc deleted file mode 100644 index 9906f67c75e..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/camera/camera_ui.cc +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2019 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/chromeos/camera/camera_ui.h" - -#include <utility> - -#include "base/bind.h" -#include "base/feature_list.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/webui_util.h" -#include "chrome/browser/web_applications/system_web_app_manager.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/browser_resources.h" -#include "chrome/grit/camera_resources.h" -#include "chrome/grit/camera_resources_map.h" -#include "chromeos/constants/chromeos_features.h" -#include "content/public/browser/web_ui_data_source.h" -#include "mojo/public/js/grit/mojo_bindings_resources.h" - -namespace chromeos { - -namespace { - -content::WebUIDataSource* CreateCameraUIHTMLSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUICameraHost); - - // Add all settings resources. - webui::AddResourcePathsBulk( - source, base::make_span(kCameraResources, kCameraResourcesSize)); - - static constexpr webui::ResourcePath kAdditionalResources[] = { - // Add WebUI version of the CCA browser proxy. - {"src/js/browser_proxy/browser_proxy.js", IDR_CAMERA_WEBUI_BROWSER_PROXY}, - - // Add mojom-lite files under expected paths. - {"src/js/mojo/camera_intent.mojom-lite.js", - IDR_CAMERA_CAMERA_INTENT_MOJOM_LITE_JS}, - {"src/js/mojo/image_capture.mojom-lite.js", - IDR_CAMERA_IMAGE_CAPTURE_MOJOM_LITE_JS}, - {"src/js/mojo/camera_common.mojom-lite.js", - IDR_CAMERA_CAMERA_COMMON_MOJOM_LITE_JS}, - {"src/js/mojo/camera_metadata.mojom-lite.js", - IDR_CAMERA_CAMERA_METADATA_MOJOM_LITE_JS}, - {"src/js/mojo/camera_metadata_tags.mojom-lite.js", - IDR_CAMERA_CAMERA_METADATA_TAGS_MOJOM_LITE_JS}, - {"src/js/mojo/camera_app.mojom-lite.js", IDR_CAMERA_APP_MOJOM_LITE_JS}, - {"src/js/mojo/mojo_bindings_lite.js", IDR_MOJO_MOJO_BINDINGS_LITE_JS}, - - // Add System Web App resources. - {"pwa.html", IDR_PWA_HTML}, - }; - webui::AddResourcePathsBulk(source, kAdditionalResources); - - source->UseStringsJs(); - - return source; -} - -} // namespace - -/////////////////////////////////////////////////////////////////////////////// -// -// CameraUI -// -/////////////////////////////////////////////////////////////////////////////// - -CameraUI::CameraUI(content::WebUI* web_ui) : ui::MojoWebUIController(web_ui) { - Profile* profile = Profile::FromWebUI(web_ui); - - // Set up the data source. - content::WebUIDataSource* source = CreateCameraUIHTMLSource(); - content::WebUIDataSource::Add(profile, source); -} - -CameraUI::~CameraUI() = default; - -// static -bool CameraUI::IsEnabled() { - return web_app::SystemWebAppManager::IsAppEnabled( - web_app::SystemAppType::CAMERA); -} - -} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/camera/camera_ui.h b/chromium/chrome/browser/ui/webui/chromeos/camera/camera_ui.h deleted file mode 100644 index 31dabca4e5e..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/camera/camera_ui.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 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_CHROMEOS_CAMERA_CAMERA_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CAMERA_CAMERA_UI_H_ - -#include "base/macros.h" -#include "ui/webui/mojo_web_ui_controller.h" - -namespace chromeos { - -class CameraUI : public ui::MojoWebUIController { - public: - explicit CameraUI(content::WebUI* web_ui); - ~CameraUI() override; - - // True when the Camera as a System Web App flag is true. - static bool IsEnabled(); - - private: - DISALLOW_COPY_AND_ASSIGN(CameraUI); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CAMERA_CAMERA_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom index e679865fb55..72e63a90a51 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer.mojom @@ -25,10 +25,15 @@ interface PageHandler { // If a user cancels the installation without starting it at all, this should // be called so that metrics can be recorded. CancelBeforeStart(); - // The page normally is displayed in a dialog. Call this to close the dialog. - // chrome.send('dialogClose') should not be used, which could kill the page - // handler before previous mojom calls have been run. - Close(); + // This is called when the web page is "closed", and the dialog (or whatever) + // hosting it should also be closed. This can happen as a result of + // Page::RequestClose() being called, or it can happen spontaneously (e.g. + // user clicking cancel on the page or installation finished). + // + // Note that the web page should not use something like + // chrome.send('dialogClose'), which could kill the page handler before + // previous mojom calls have been run. + OnPageClosed(); // Fetches the amount of free disk space, the result is sent via // OnAmountOfFreeDiskSpace. RequestAmountOfFreeDiskSpace(); @@ -54,4 +59,7 @@ interface Page { OnAmountOfFreeDiskSpace(array<crostini.mojom.DiskSliderTick> ticks, int8 default_index, bool is_low_space_available); + // Informs the page that it should be closed. The page should respond with + // PageHandler::OnPageClosed() to indicate it is ready to be closed. + RequestClose(); }; diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc index b3f75d222e5..28c41a9a9af 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc @@ -4,10 +4,13 @@ #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h" +#include "ash/public/cpp/shelf_types.h" +#include "ash/public/cpp/window_properties.h" #include "base/bind_helpers.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/crostini/crostini_features.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h" #include "chrome/common/webui_url_constants.h" #include "ui/base/ui_base_types.h" @@ -75,6 +78,10 @@ bool CrostiniInstallerDialog::ShouldCloseDialogOnEscape() const { void CrostiniInstallerDialog::AdjustWidgetInitParams( views::Widget::InitParams* params) { params->z_order = ui::ZOrderLevel::kNormal; + + const ash::ShelfID shelf_id(crostini::kCrostiniInstallerShelfId); + params->init_properties_container.SetProperty(ash::kShelfIDKey, + shelf_id.Serialize()); } bool CrostiniInstallerDialog::CanCloseDialog() const { @@ -82,7 +89,14 @@ bool CrostiniInstallerDialog::CanCloseDialog() const { // closing logic, we should find a more general solution. // Disallow closing without WebUI consent. - return installer_ui_ == nullptr || installer_ui_->can_close(); + // + // Note that while the function name |CanCloseDialog| does not indicate the + // intend to close the dialog, but it is indeed only called when we are + // closing it, so requesting closing the page here is appropriate. One might + // think we should actually do all of this in |OnDialogCloseRequested| + // instead, but unfortunately that function is called after the web content is + // closed. + return installer_ui_ == nullptr || installer_ui_->RequestClosePage(); } void CrostiniInstallerDialog::OnDialogShown(content::WebUI* webui) { diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc index 0bd746d7079..306b66c00bd 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.cc @@ -29,11 +29,11 @@ CrostiniInstallerPageHandler::CrostiniInstallerPageHandler( mojo::PendingReceiver<chromeos::crostini_installer::mojom::PageHandler> pending_page_handler, mojo::PendingRemote<chromeos::crostini_installer::mojom::Page> pending_page, - base::OnceClosure close_dialog_callback) + base::OnceClosure on_page_closed) : installer_ui_delegate_{installer_ui_delegate}, receiver_{this, std::move(pending_page_handler)}, page_{std::move(pending_page)}, - close_dialog_callback_{std::move(close_dialog_callback)} {} + on_page_closed_{std::move(on_page_closed)} {} CrostiniInstallerPageHandler::~CrostiniInstallerPageHandler() = default; @@ -43,9 +43,7 @@ void CrostiniInstallerPageHandler::Install(int64_t disk_size_bytes, if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing)) { options.disk_size_bytes = disk_size_bytes; } - if (base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsername)) { - options.container_username = username; - } + options.container_username = username; installer_ui_delegate_->Install( std::move(options), base::BindRepeating(&CrostiniInstallerPageHandler::OnProgressUpdate, @@ -64,9 +62,9 @@ void CrostiniInstallerPageHandler::CancelBeforeStart() { installer_ui_delegate_->CancelBeforeStart(); } -void CrostiniInstallerPageHandler::Close() { - if (close_dialog_callback_) { - std::move(close_dialog_callback_).Run(); +void CrostiniInstallerPageHandler::OnPageClosed() { + if (on_page_closed_) { + std::move(on_page_closed_).Run(); } } @@ -94,6 +92,10 @@ void CrostiniInstallerPageHandler::RequestAmountOfFreeDiskSpace() { weak_ptr_factory_.GetWeakPtr())); } +void CrostiniInstallerPageHandler::RequestClosePage() { + page_->RequestClose(); +} + void CrostiniInstallerPageHandler::OnAmountOfFreeDiskSpace(int64_t free_bytes) { int64_t max_bytes = free_bytes - crostini::disk::kDiskHeadroomBytes; diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h index 94128cd43f6..8794f3de1ba 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_page_handler.h @@ -30,16 +30,19 @@ class CrostiniInstallerPageHandler pending_page_handler, mojo::PendingRemote<chromeos::crostini_installer::mojom::Page> pending_page, - base::OnceClosure close_dialog_callback); + base::OnceClosure on_page_closed); ~CrostiniInstallerPageHandler() override; // chromeos::crostini_installer::mojom::PageHandler: void Install(int64_t disk_size_bytes, const std::string& username) override; void Cancel() override; void CancelBeforeStart() override; - void Close() override; + void OnPageClosed() override; void RequestAmountOfFreeDiskSpace() override; + // Send a close request to the web page. + void RequestClosePage(); + private: void OnProgressUpdate(crostini::mojom::InstallerState installer_state, double progress_fraction); @@ -50,7 +53,7 @@ class CrostiniInstallerPageHandler crostini::CrostiniInstallerUIDelegate* installer_ui_delegate_; mojo::Receiver<chromeos::crostini_installer::mojom::PageHandler> receiver_; mojo::Remote<chromeos::crostini_installer::mojom::Page> page_; - base::OnceClosure close_dialog_callback_; + base::OnceClosure on_page_closed_; base::WeakPtrFactory<CrostiniInstallerPageHandler> weak_ptr_factory_{this}; diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc index 47cab7a6f56..0e249a5e3cb 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.cc @@ -23,6 +23,7 @@ #include "chromeos/constants/chromeos_features.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" #include "ui/base/webui/web_ui_util.h" @@ -84,6 +85,7 @@ void AddStringResources(content::WebUIDataSource* source) { IDS_CROSTINI_INSTALLER_USERNAME_INVALID_CHARACTERS_ERROR}, {"usernameNotAvailableError", IDS_CROSTINI_INSTALLER_USERNAME_NOT_AVAILABLE_ERROR}, + {"customDiskSizeLabel", IDS_CROSTINI_INSTALLER_CUSTOM_DISK_SIZE_LABEL}, }; AddLocalizedStringsBulk(source, kStrings); @@ -117,6 +119,13 @@ void AddStringResources(content::WebUIDataSource* source) { ui::FormatBytesWithUnits(crostini::disk::kRecommendedDiskSizeBytes, ui::DATA_UNITS_GIBIBYTE, /*show_units=*/true))); + source->AddString( + "recommendedDiskSizeLabel", + l10n_util::GetStringFUTF8( + IDS_CROSTINI_INSTALLER_RECOMMENDED_DISK_SIZE_LABEL, + ui::FormatBytesWithUnits(crostini::disk::kRecommendedDiskSizeBytes, + ui::DATA_UNITS_GIBIBYTE, + /*show_units=*/true))); source->AddString("offlineError", l10n_util::GetStringFUTF8( IDS_CROSTINI_INSTALLER_OFFLINE_ERROR, device_name)); @@ -130,15 +139,13 @@ CrostiniInstallerUI::CrostiniInstallerUI(content::WebUI* web_ui) content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUICrostiniInstallerHost); auto* profile = Profile::FromWebUI(web_ui); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); AddStringResources(source); source->AddBoolean( "diskResizingEnabled", base::FeatureList::IsEnabled(chromeos::features::kCrostiniDiskResizing)); - source->AddBoolean( - "crostiniCustomUsername", - base::FeatureList::IsEnabled(chromeos::features::kCrostiniUsername)); source->AddString("defaultContainerUsername", crostini::DefaultContainerUserNameForProfile(profile)); @@ -162,8 +169,13 @@ CrostiniInstallerUI::CrostiniInstallerUI(content::WebUI* web_ui) CrostiniInstallerUI::~CrostiniInstallerUI() = default; -bool CrostiniInstallerUI::can_close() { - return can_close_; +bool CrostiniInstallerUI::RequestClosePage() { + if (page_closed_ || !page_handler_) { + return true; + } + + page_handler_->RequestClosePage(); + return false; } void CrostiniInstallerUI::ClickInstallForTesting() { @@ -200,12 +212,12 @@ void CrostiniInstallerUI::CreatePageHandler( std::move(pending_page_handler), std::move(pending_page), // Using Unretained(this) because |page_handler_| will not out-live // |this|. - base::BindOnce(&CrostiniInstallerUI::OnWebUICloseDialog, + base::BindOnce(&CrostiniInstallerUI::OnPageClosed, base::Unretained(this))); } -void CrostiniInstallerUI::OnWebUICloseDialog() { - can_close_ = true; +void CrostiniInstallerUI::OnPageClosed() { + page_closed_ = true; // CloseDialog() is a no-op if we are not in a dialog (e.g. user // access the page using the URL directly, which is not supported). ui::MojoWebDialogUI::CloseDialog(nullptr); diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h index 8f4fee5f139..de78f42ac95 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h @@ -24,7 +24,10 @@ class CrostiniInstallerUI explicit CrostiniInstallerUI(content::WebUI* web_ui); ~CrostiniInstallerUI() override; - bool can_close(); + // Send a close request to the web page. Return true if the page is already + // closed. + bool RequestClosePage(); + void ClickInstallForTesting(); // Instantiates implementor of the mojom::PageHandlerFactory @@ -41,12 +44,12 @@ class CrostiniInstallerUI mojo::PendingReceiver<chromeos::crostini_installer::mojom::PageHandler> pending_page_handler) override; - void OnWebUICloseDialog(); + void OnPageClosed(); std::unique_ptr<CrostiniInstallerPageHandler> page_handler_; mojo::Receiver<chromeos::crostini_installer::mojom::PageHandlerFactory> page_factory_receiver_{this}; - bool can_close_ = false; + bool page_closed_ = false; WEB_UI_CONTROLLER_TYPE_DECL(); diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom index 7f01682dc54..94cf4daa863 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader.mojom @@ -42,10 +42,15 @@ interface PageHandler { CancelBeforeStart(); // If an upgrade fails, the user may choose to restore a container backup. Restore(); - // The page normally is displayed in a dialog. Call this to close the dialog. - // chrome.send('dialogClose') should not be used, which could kill the page - // handler before previous mojom calls have been run. - Close(); + // This is called when the web page is "closed", and the dialog (or whatever) + // hosting it should also be closed. This can happen as a result of + // Page::RequestClose() being called, or it can happen spontaneously (e.g. + // user clicking cancel on the page or installation finished). + // + // Note that the web page should not use something like + // chrome.send('dialogClose'), which could kill the page handler before + // previous mojom calls have been run. + OnPageClosed(); // Close the dialog and launch the Terminal or other app after a successful // upgrade. Launch(); @@ -81,4 +86,7 @@ interface Page { // After user cancels the upgrade, this is called when the cancellation // finishes. OnCanceled(); + // Informs the page that it should be closed. The page should respond with + // PageHandler::OnPageClosed() to indicate it is ready to be closed. + RequestClose(); }; diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc index 11110bd02dc..9860f0058e0 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc @@ -4,8 +4,11 @@ #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h" +#include "ash/public/cpp/shelf_types.h" +#include "ash/public/cpp/window_properties.h" #include "base/metrics/histogram_functions.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" +#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h" #include "chrome/browser/chromeos/crostini/crostini_simple_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h" @@ -35,8 +38,7 @@ void CrostiniUpgraderDialog::Show(base::OnceClosure launch_closure, instance = new CrostiniUpgraderDialog(std::move(launch_closure), only_run_launch_closure_on_restart); instance->ShowSystemDialog(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kDialogShown); + EmitUpgradeDialogEventHistogram(crostini::UpgradeDialogEvent::kDialogShown); } CrostiniUpgraderDialog::CrostiniUpgraderDialog( @@ -67,6 +69,10 @@ bool CrostiniUpgraderDialog::ShouldCloseDialogOnEscape() const { void CrostiniUpgraderDialog::AdjustWidgetInitParams( views::Widget::InitParams* params) { params->z_order = ui::ZOrderLevel::kNormal; + + const ash::ShelfID shelf_id(crostini::kCrostiniUpgraderShelfId); + params->init_properties_container.SetProperty(ash::kShelfIDKey, + shelf_id.Serialize()); } void CrostiniUpgraderDialog::SetDeletionClosureForTesting( @@ -83,7 +89,14 @@ bool CrostiniUpgraderDialog::CanCloseDialog() const { return true; } // Disallow closing without WebUI consent. - return upgrader_ui_ == nullptr || upgrader_ui_->can_close(); + // + // Note that while the function name |CanCloseDialog| does not indicate the + // intend to close the dialog, but it is indeed only called when we are + // closing it, so requesting closing the page here is appropriate. One might + // think we should actually do all of this in |OnDialogCloseRequested| + // instead, but unfortunately that function is called after the web content is + // closed. + return upgrader_ui_ == nullptr || upgrader_ui_->RequestClosePage(); } namespace { @@ -101,7 +114,7 @@ void RunLaunchClosure(base::WeakPtr<crostini::CrostiniManager> crostini_manager, return; } crostini_manager->RestartCrostini( - crostini::kCrostiniDefaultVmName, crostini::kCrostiniDefaultContainerName, + crostini::ContainerId::GetDefault(), base::BindOnce( [](base::OnceClosure launch_closure, crostini::CrostiniResult result) { @@ -122,9 +135,7 @@ void CrostiniUpgraderDialog::OnDialogShown(content::WebUI* webui) { crostini::CrostiniManager::GetForProfile(Profile::FromWebUI(webui)); crostini_manager->SetCrostiniDialogStatus(crostini::DialogType::UPGRADER, true); - crostini_manager->UpgradePromptShown( - crostini::ContainerId(crostini::kCrostiniDefaultVmName, - crostini::kCrostiniDefaultContainerName)); + crostini_manager->UpgradePromptShown(crostini::ContainerId::GetDefault()); upgrader_ui_ = static_cast<CrostiniUpgraderUI*>(webui->GetController()); upgrader_ui_->set_launch_callback(base::BindOnce( @@ -143,4 +154,9 @@ void CrostiniUpgraderDialog::OnCloseContents(content::WebContents* source, return SystemWebDialogDelegate::OnCloseContents(source, out_close_dialog); } +void CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent event) { + base::UmaHistogramEnumeration("Crostini.UpgradeDialogEvent", event); +} + } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h index 7f1a2195063..356b0403b47 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_CROSTINI_UPGRADER_CROSTINI_UPGRADER_DIALOG_H_ #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CROSTINI_UPGRADER_CROSTINI_UPGRADER_DIALOG_H_ +#include "chrome/browser/chromeos/crostini/crostini_simple_types.h" #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" namespace chromeos { @@ -25,6 +26,9 @@ class CrostiniUpgraderDialog : public SystemWebDialogDelegate { void SetDeletionClosureForTesting( base::OnceClosure deletion_closure_for_testing); + static void EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent event); + private: explicit CrostiniUpgraderDialog(base::OnceClosure launch_closure, bool only_run_launch_closure_on_restart); diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc index 48239a18d87..d1c08e6622b 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog_browsertest.cc @@ -90,8 +90,7 @@ class CrostiniUpgraderDialogBrowserTest : public CrostiniDialogBrowserTest { os_release.set_id("debian"); os_release.set_version_id("9"); auto container_id = crostini::DefaultContainerId(); - crostini_manager()->SetContainerOsRelease( - container_id.vm_name, container_id.container_name, os_release); + crostini_manager()->SetContainerOsRelease(container_id, os_release); } const std::string& app_id() const { return app_id_; } @@ -132,7 +131,7 @@ IN_PROC_BROWSER_TEST_F(CrostiniUpgraderDialogBrowserTest, ShowsOnAppLaunch) { ExpectNoDialog(); histogram_tester.ExpectUniqueSample( - crostini::kUpgradeDialogEventHistogram, + "Crostini.UpgradeDialogEvent", static_cast<base::HistogramBase::Sample>( crostini::UpgradeDialogEvent::kDialogShown), 1); diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc index fd13e73652c..b16643e8411 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.cc @@ -22,13 +22,13 @@ CrostiniUpgraderPageHandler::CrostiniUpgraderPageHandler( mojo::PendingReceiver<chromeos::crostini_upgrader::mojom::PageHandler> pending_page_handler, mojo::PendingRemote<chromeos::crostini_upgrader::mojom::Page> pending_page, - base::OnceClosure close_dialog_callback, + base::OnceClosure on_page_closed, base::OnceCallback<void(bool)> launch_callback) : web_contents_{web_contents}, upgrader_ui_delegate_{upgrader_ui_delegate}, receiver_{this, std::move(pending_page_handler)}, page_{std::move(pending_page)}, - close_dialog_callback_{std::move(close_dialog_callback)}, + on_page_closed_{std::move(on_page_closed)}, launch_callback_{std::move(launch_callback)} { upgrader_ui_delegate_->AddObserver(this); } @@ -49,14 +49,17 @@ void CrostiniUpgraderPageHandler::OnBackupMaybeStarted(bool did_start) { Redisplay(); } +// Send a close request to the web page. +void CrostiniUpgraderPageHandler::RequestClosePage() { + page_->RequestClose(); +} + void CrostiniUpgraderPageHandler::Backup(bool show_file_chooser) { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kDidBackup); - upgrader_ui_delegate_->Backup( - crostini::ContainerId(crostini::kCrostiniDefaultVmName, - crostini::kCrostiniDefaultContainerName), - show_file_chooser, web_contents_); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kDidBackup); + upgrader_ui_delegate_->Backup(crostini::ContainerId::GetDefault(), + show_file_chooser, web_contents_); } void CrostiniUpgraderPageHandler::StartPrechecks() { @@ -65,24 +68,20 @@ void CrostiniUpgraderPageHandler::StartPrechecks() { void CrostiniUpgraderPageHandler::Upgrade() { Redisplay(); - upgrader_ui_delegate_->Upgrade( - crostini::ContainerId(crostini::kCrostiniDefaultVmName, - crostini::kCrostiniDefaultContainerName)); + upgrader_ui_delegate_->Upgrade(crostini::ContainerId::GetDefault()); } void CrostiniUpgraderPageHandler::Restore() { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kDidRestore); - upgrader_ui_delegate_->Restore( - crostini::ContainerId(crostini::kCrostiniDefaultVmName, - crostini::kCrostiniDefaultContainerName), - web_contents_); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kDidRestore); + upgrader_ui_delegate_->Restore(crostini::ContainerId::GetDefault(), + web_contents_); } void CrostiniUpgraderPageHandler::Cancel() { - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kUpgradeCanceled); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kUpgradeCanceled); upgrader_ui_delegate_->Cancel(); } @@ -91,8 +90,8 @@ void CrostiniUpgraderPageHandler::Launch() { } void CrostiniUpgraderPageHandler::CancelBeforeStart() { - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kNotStarted); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kNotStarted); restart_required_ = false; upgrader_ui_delegate_->CancelBeforeStart(); if (launch_callback_) { @@ -101,12 +100,12 @@ void CrostiniUpgraderPageHandler::CancelBeforeStart() { } } -void CrostiniUpgraderPageHandler::Close() { +void CrostiniUpgraderPageHandler::OnPageClosed() { if (launch_callback_) { Launch(); } - if (close_dialog_callback_) { - std::move(close_dialog_callback_).Run(); + if (on_page_closed_) { + std::move(on_page_closed_).Run(); } } @@ -117,15 +116,15 @@ void CrostiniUpgraderPageHandler::OnUpgradeProgress( void CrostiniUpgraderPageHandler::OnUpgradeSucceeded() { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kUpgradeSuccess); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kUpgradeSuccess); page_->OnUpgradeSucceeded(); } void CrostiniUpgraderPageHandler::OnUpgradeFailed() { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kUpgradeFailed); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kUpgradeFailed); page_->OnUpgradeFailed(); } @@ -135,15 +134,15 @@ void CrostiniUpgraderPageHandler::OnBackupProgress(int percent) { void CrostiniUpgraderPageHandler::OnBackupSucceeded(bool was_cancelled) { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kBackupSucceeded); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kBackupSucceeded); page_->OnBackupSucceeded(was_cancelled); } void CrostiniUpgraderPageHandler::OnBackupFailed() { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kBackupFailed); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kBackupFailed); page_->OnBackupFailed(); } @@ -158,16 +157,15 @@ void CrostiniUpgraderPageHandler::OnRestoreProgress(int percent) { void CrostiniUpgraderPageHandler::OnRestoreSucceeded() { Redisplay(); - base::UmaHistogramEnumeration( - crostini::kUpgradeDialogEventHistogram, + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( crostini::UpgradeDialogEvent::kRestoreSucceeded); page_->OnRestoreSucceeded(); } void CrostiniUpgraderPageHandler::OnRestoreFailed() { Redisplay(); - base::UmaHistogramEnumeration(crostini::kUpgradeDialogEventHistogram, - crostini::UpgradeDialogEvent::kRestoreFailed); + CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram( + crostini::UpgradeDialogEvent::kRestoreFailed); page_->OnRestoreFailed(); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h index edf98821f6e..01c0ac74c9c 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_page_handler.h @@ -32,10 +32,13 @@ class CrostiniUpgraderPageHandler pending_page_handler, mojo::PendingRemote<chromeos::crostini_upgrader::mojom::Page> pending_page, - base::OnceClosure close_dialog_callback, + base::OnceClosure on_page_closed, base::OnceCallback<void(bool)> launch_callback); ~CrostiniUpgraderPageHandler() override; + // Send a close request to the web page. + void RequestClosePage(); + // chromeos::crostini_upgrader::mojom::PageHandler: void Backup(bool show_file_chooser) override; void StartPrechecks() override; @@ -43,7 +46,7 @@ class CrostiniUpgraderPageHandler void Restore() override; void Cancel() override; void CancelBeforeStart() override; - void Close() override; + void OnPageClosed() override; void Launch() override; // CrostiniUpgraderUIObserver @@ -68,7 +71,7 @@ class CrostiniUpgraderPageHandler crostini::CrostiniUpgraderUIDelegate* upgrader_ui_delegate_; // Not owned. mojo::Receiver<chromeos::crostini_upgrader::mojom::PageHandler> receiver_; mojo::Remote<chromeos::crostini_upgrader::mojom::Page> page_; - base::OnceClosure close_dialog_callback_; + base::OnceClosure on_page_closed_; base::OnceCallback<void(bool)> launch_callback_; // Will we need to restart the container as part of launch_callback? // |restart_required_| is true unless the user cancels before starting the diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc index 8d195a25f0e..a9dbb7b64c1 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc @@ -21,6 +21,7 @@ #include "chromeos/constants/chromeos_features.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" #include "ui/base/webui/web_ui_util.h" @@ -97,7 +98,8 @@ CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui) : ui::MojoWebDialogUI{web_ui} { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUICrostiniUpgraderHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); AddStringResources(source); @@ -122,6 +124,15 @@ CrostiniUpgraderUI::CrostiniUpgraderUI(content::WebUI* web_ui) CrostiniUpgraderUI::~CrostiniUpgraderUI() = default; +bool CrostiniUpgraderUI::RequestClosePage() { + if (page_closed_ || !page_handler_) { + return true; + } + + page_handler_->RequestClosePage(); + return false; +} + void CrostiniUpgraderUI::BindInterface( mojo::PendingReceiver< chromeos::crostini_upgrader::mojom::PageHandlerFactory> @@ -145,13 +156,12 @@ void CrostiniUpgraderUI::CreatePageHandler( std::move(pending_page_handler), std::move(pending_page), // Using Unretained(this) because |page_handler_| will not out-live // |this|. - base::BindOnce(&CrostiniUpgraderUI::OnWebUICloseDialog, - base::Unretained(this)), + base::BindOnce(&CrostiniUpgraderUI::OnPageClosed, base::Unretained(this)), std::move(launch_callback_)); } -void CrostiniUpgraderUI::OnWebUICloseDialog() { - can_close_ = true; +void CrostiniUpgraderUI::OnPageClosed() { + page_closed_ = true; // CloseDialog() is a no-op if we are not in a dialog (e.g. user // access the page using the URL directly, which is not supported). ui::MojoWebDialogUI::CloseDialog(nullptr); diff --git a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h index 6126283abd6..13c5605c215 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h @@ -27,7 +27,10 @@ class CrostiniUpgraderUI explicit CrostiniUpgraderUI(content::WebUI* web_ui); ~CrostiniUpgraderUI() override; - bool can_close() { return can_close_; } + // Send a close request to the web page. Return true if the page is already + // closed. + bool RequestClosePage(); + void set_launch_callback(base::OnceCallback<void(bool)>(launch_callback)) { launch_callback_ = std::move(launch_callback); } @@ -47,7 +50,7 @@ class CrostiniUpgraderUI mojo::PendingReceiver<chromeos::crostini_upgrader::mojom::PageHandler> pending_page_handler) override; - void OnWebUICloseDialog(); + void OnPageClosed(); std::unique_ptr<CrostiniUpgraderPageHandler> page_handler_; mojo::Receiver<chromeos::crostini_upgrader::mojom::PageHandlerFactory> @@ -56,7 +59,7 @@ class CrostiniUpgraderUI // Not owned. Passed to |page_handler_| base::OnceCallback<void(bool)> launch_callback_; - bool can_close_ = false; + bool page_closed_ = false; WEB_UI_CONTROLLER_TYPE_DECL(); diff --git a/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc index 0611cef1174..6a9d0c38941 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.cc @@ -5,7 +5,6 @@ #include "chrome/browser/ui/webui/chromeos/cryptohome_web_ui_handler.h" #include "base/bind.h" -#include "base/task/post_task.h" #include "base/values.h" #include "chromeos/dbus/cryptohome/cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" @@ -40,9 +39,8 @@ void CryptohomeWebUIHandler::OnPageLoaded(const base::ListValue* args) { cryptohome_client->Pkcs11IsTpmTokenReady( GetCryptohomeBoolCallback("pkcs11-is-tpm-token-ready")); - base::PostTaskAndReplyWithResult( - FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&crypto::IsTPMTokenReady, base::Closure()), + content::GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&crypto::IsTPMTokenReady, base::Closure()), base::BindOnce(&CryptohomeWebUIHandler::DidGetNSSUtilInfoOnUIThread, weak_ptr_factory_.GetWeakPtr())); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc index 4333fb4d05c..3345379fa27 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc @@ -22,6 +22,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/path_service.h" +#include "base/process/launch.h" #include "base/strings/pattern.h" #include "base/strings/strcat.h" #include "base/strings/stringprintf.h" @@ -217,6 +218,14 @@ std::pair<ino_t, base::ListValue> GetServiceLogContents( return {inode, std::move(result)}; } +bool GetDeveloperMode() { + std::string output; + if (!base::GetAppOutput({"/usr/bin/crossystem", "cros_debug"}, &output)) { + return false; + } + return output == "1"; +} + class DriveInternalsWebUIHandler; void ZipLogs(Profile* profile, @@ -263,6 +272,19 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { base::BindRepeating(&DriveInternalsWebUIHandler::OnPeriodicUpdate, weak_ptr_factory_.GetWeakPtr())); web_ui()->RegisterMessageCallback( + "setVerboseLoggingEnabled", + base::BindRepeating( + &DriveInternalsWebUIHandler::SetVerboseLoggingEnabled, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "enableTracing", + base::BindRepeating(&DriveInternalsWebUIHandler::SetTracingEnabled, + weak_ptr_factory_.GetWeakPtr(), true)); + web_ui()->RegisterMessageCallback( + "disableTracing", + base::BindRepeating(&DriveInternalsWebUIHandler::SetTracingEnabled, + weak_ptr_factory_.GetWeakPtr(), false)); + web_ui()->RegisterMessageCallback( "restartDrive", base::BindRepeating(&DriveInternalsWebUIHandler::RestartDrive, weak_ptr_factory_.GetWeakPtr())); @@ -276,6 +298,38 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { weak_ptr_factory_.GetWeakPtr())); } + void RegisterDeveloperMessages() { + CHECK(developer_mode_); + web_ui()->RegisterMessageCallback( + "setStartupArguments", + base::BindRepeating(&DriveInternalsWebUIHandler::SetStartupArguments, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "enableNetworking", + base::BindRepeating(&DriveInternalsWebUIHandler::SetNetworkingEnabled, + weak_ptr_factory_.GetWeakPtr(), true)); + web_ui()->RegisterMessageCallback( + "disableNetworking", + base::BindRepeating(&DriveInternalsWebUIHandler::SetNetworkingEnabled, + weak_ptr_factory_.GetWeakPtr(), false)); + web_ui()->RegisterMessageCallback( + "enableForcePauseSyncing", + base::BindRepeating(&DriveInternalsWebUIHandler::ForcePauseSyncing, + weak_ptr_factory_.GetWeakPtr(), true)); + web_ui()->RegisterMessageCallback( + "disableForcePauseSyncing", + base::BindRepeating(&DriveInternalsWebUIHandler::ForcePauseSyncing, + weak_ptr_factory_.GetWeakPtr(), false)); + web_ui()->RegisterMessageCallback( + "dumpAccountSettings", + base::BindRepeating(&DriveInternalsWebUIHandler::DumpAccountSettings, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "loadAccountSettings", + base::BindRepeating(&DriveInternalsWebUIHandler::LoadAccountSettings, + weak_ptr_factory_.GetWeakPtr())); + } + // Called when the page is first loaded. void OnPageLoaded(const base::ListValue* args) { AllowJavascript(); @@ -410,6 +464,17 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { void UpdateDriveDebugSection() { SetSectionEnabled("drive-debug", true); + bool verbose_logging_enabled = profile()->GetPrefs()->GetBoolean( + drive::prefs::kDriveFsEnableVerboseLogging); + MaybeCallJavascript("updateVerboseLogging", + base::Value(verbose_logging_enabled)); + + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(GetDeveloperMode), + base::BindOnce(&DriveInternalsWebUIHandler::OnGetDeveloperMode, + weak_ptr_factory_.GetWeakPtr())); + // Propagate the amount of local free space in bytes. base::FilePath home_path; if (base::PathService::Get(base::DIR_HOME, &home_path)) { @@ -423,6 +488,33 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { } } + // Called when GetDeveloperMode() is complete. + void OnGetDeveloperMode(bool enabled) { + developer_mode_ = enabled; + if (!enabled) { + return; + } + + RegisterDeveloperMessages(); + + // Get the startup arguments. + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (integration_service) { + integration_service->GetStartupArguments( + base::BindOnce(&DriveInternalsWebUIHandler::OnGetStartupArguments, + weak_ptr_factory_.GetWeakPtr())); + } + } + + // Called when GetStartupArguments() is complete. + void OnGetStartupArguments(const std::string& arguments) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(developer_mode_); + MaybeCallJavascript("updateStartupArguments", base::Value(arguments)); + SetSectionEnabled("developer-mode-controls", true); + } + // Called when AmountOfFreeDiskSpace() is complete. void OnGetFreeDiskSpace(int64_t free_space) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -440,6 +532,7 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { drive::prefs::kDisableDriveOverCellular, drive::prefs::kDriveFsWasLaunchedAtLeastOnce, drive::prefs::kDriveFsPinnedMigrated, + drive::prefs::kDriveFsEnableVerboseLogging, }; PrefService* pref_service = profile()->GetPrefs(); @@ -552,6 +645,105 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { std::move(response.second)); } + // Called when the "Verbose Logging" checkbox on the page is changed. + void SetVerboseLoggingEnabled(const base::ListValue* args) { + AllowJavascript(); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (!integration_service) { + return; + } + + if (args->GetList().size() == 1 && args->GetList()[0].is_bool()) { + bool enabled = args->GetList()[0].GetBool(); + profile()->GetPrefs()->SetBoolean( + drive::prefs::kDriveFsEnableVerboseLogging, enabled); + RestartDrive(nullptr); + } + } + + // Called when the "Startup Arguments" field on the page is submitted. + void SetStartupArguments(const base::ListValue* args) { + AllowJavascript(); + + CHECK(developer_mode_); + + if (args->GetList().size() < 1 || !args->GetList()[0].is_string()) { + OnSetStartupArguments(false); + return; + } + + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (!integration_service) { + OnSetStartupArguments(false); + return; + } + + integration_service->SetStartupArguments( + args->GetList()[0].GetString(), + base::BindOnce(&DriveInternalsWebUIHandler::OnSetStartupArguments, + weak_ptr_factory_.GetWeakPtr())); + } + + void OnSetStartupArguments(bool success) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + DCHECK(developer_mode_); + if (success) { + RestartDrive(nullptr); + } + MaybeCallJavascript("updateStartupArgumentsStatus", base::Value(success)); + } + + void SetTracingEnabled(bool enabled, const base::ListValue* args) { + AllowJavascript(); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (integration_service) { + integration_service->SetTracingEnabled(enabled); + } + } + + void SetNetworkingEnabled(bool enabled, const base::ListValue* args) { + AllowJavascript(); + CHECK(developer_mode_); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (integration_service) { + integration_service->SetNetworkingEnabled(enabled); + } + } + + void ForcePauseSyncing(bool enabled, const base::ListValue* args) { + AllowJavascript(); + CHECK(developer_mode_); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (integration_service) { + integration_service->ForcePauseSyncing(enabled); + } + } + + void DumpAccountSettings(const base::ListValue* args) { + AllowJavascript(); + CHECK(developer_mode_); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (integration_service) { + integration_service->DumpAccountSettings(); + } + } + + void LoadAccountSettings(const base::ListValue* args) { + AllowJavascript(); + CHECK(developer_mode_); + drive::DriveIntegrationService* integration_service = + GetIntegrationService(); + if (integration_service) { + integration_service->LoadAccountSettings(); + } + } + // Called when the "Restart Drive" button on the page is pressed. void RestartDrive(const base::ListValue* args) { AllowJavascript(); @@ -619,6 +811,9 @@ class DriveInternalsWebUIHandler : public content::WebUIMessageHandler { // Service log file is being parsed. bool service_log_file_is_processing_ = false; + // Whether developer mode is enabled for debug commands. + bool developer_mode_ = false; + base::WeakPtrFactory<DriveInternalsWebUIHandler> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DriveInternalsWebUIHandler); }; @@ -695,8 +890,7 @@ class LogsZipper : public download::AllDownloadItemNotifier::Observer { void CleanUp() { base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::BindOnce(base::IgnoreResult(&base::DeleteFile), zip_path_, - false)); + base::BindOnce(base::GetDeleteFileCallback(), zip_path_)); download_notifier_.reset(); if (drive_internals_) { drive_internals_->OnZipDone(); diff --git a/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc index 99f1d0742c2..a0611a51052 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/edu_account_login_handler_chromeos.cc @@ -18,7 +18,7 @@ #include "chrome/browser/profiles/profile_key.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h" +#include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" #include "chromeos/components/account_manager/account_manager.h" #include "chromeos/components/account_manager/account_manager_factory.h" #include "components/image_fetcher/core/image_fetcher_service.h" @@ -193,11 +193,11 @@ void EduAccountLoginHandler::HandleUpdateEduCoexistenceFlowResult( const base::Value::ConstListView& args_list = args->GetList(); CHECK_EQ(args_list.size(), 1u); int result = args_list[0].GetInt(); - DCHECK(result <= static_cast<int>(InlineLoginHandlerDialogChromeOS:: - EduCoexistenceFlowResult::kMaxValue)); - InlineLoginHandlerDialogChromeOS::UpdateEduCoexistenceFlowResult( - static_cast<InlineLoginHandlerDialogChromeOS::EduCoexistenceFlowResult>( - result)); + DCHECK(result <= + static_cast<int>( + InlineLoginDialogChromeOS::EduCoexistenceFlowResult::kMaxValue)); + InlineLoginDialogChromeOS::UpdateEduCoexistenceFlowResult( + static_cast<InlineLoginDialogChromeOS::EduCoexistenceFlowResult>(result)); } void EduAccountLoginHandler::FetchFamilyMembers() { diff --git a/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc index 93318f93336..40bff048c98 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc @@ -91,11 +91,10 @@ class DeviceEmulatorMessageHandler::BluetoothObserver void DeviceEmulatorMessageHandler::BluetoothObserver::DeviceAdded( const dbus::ObjectPath& object_path) { - std::unique_ptr<base::DictionaryValue> device = - owner_->GetDeviceInfo(object_path); + base::Value device = owner_->GetDeviceInfo(object_path); // Request to add the device to the view's list of devices. - owner_->FireWebUIListener("bluetooth-device-added", *device); + owner_->FireWebUIListener("bluetooth-device-added", device); } void DeviceEmulatorMessageHandler::BluetoothObserver::DevicePropertyChanged( @@ -223,42 +222,40 @@ void DeviceEmulatorMessageHandler::HandleRequestBluetoothInfo( fake_bluetooth_device_client_->GetDevicesForAdapter( dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath)); - auto devices = std::make_unique<base::ListValue>(); // Get each device's properties. - for (const dbus::ObjectPath& path : paths) { - std::unique_ptr<base::DictionaryValue> device = GetDeviceInfo(path); - devices->Append(std::move(device)); - } + base::Value devices(base::Value::Type::LIST); + for (const dbus::ObjectPath& path : paths) + devices.Append(GetDeviceInfo(path)); - std::unique_ptr<base::ListValue> predefined_devices = + base::Value predefined_devices = fake_bluetooth_device_client_->GetBluetoothDevicesAsDictionaries(); - auto pairing_method_options = std::make_unique<base::ListValue>(); - pairing_method_options->AppendString( + base::Value pairing_method_options(base::Value::Type::LIST); + pairing_method_options.Append( bluez::FakeBluetoothDeviceClient::kPairingMethodNone); - pairing_method_options->AppendString( + pairing_method_options.Append( bluez::FakeBluetoothDeviceClient::kPairingMethodPinCode); - pairing_method_options->AppendString( + pairing_method_options.Append( bluez::FakeBluetoothDeviceClient::kPairingMethodPassKey); - auto pairing_action_options = std::make_unique<base::ListValue>(); - pairing_action_options->AppendString( + base::Value pairing_action_options(base::Value::Type::LIST); + pairing_action_options.Append( bluez::FakeBluetoothDeviceClient::kPairingActionDisplay); - pairing_action_options->AppendString( + pairing_action_options.Append( bluez::FakeBluetoothDeviceClient::kPairingActionRequest); - pairing_action_options->AppendString( + pairing_action_options.Append( bluez::FakeBluetoothDeviceClient::kPairingActionConfirmation); - pairing_action_options->AppendString( + pairing_action_options.Append( bluez::FakeBluetoothDeviceClient::kPairingActionFail); - auto info = std::make_unique<base::DictionaryValue>(); - info->Set("predefined_devices", std::move(predefined_devices)); - info->Set("devices", std::move(devices)); - info->Set("pairing_method_options", std::move(pairing_method_options)); - info->Set("pairing_action_options", std::move(pairing_action_options)); + base::Value info(base::Value::Type::DICTIONARY); + info.SetKey("predefined_devices", std::move(predefined_devices)); + info.SetKey("devices", std::move(devices)); + info.SetKey("pairing_method_options", std::move(pairing_method_options)); + info.SetKey("pairing_action_options", std::move(pairing_action_options)); // Send the list of devices to the view. - FireWebUIListener("bluetooth-info-updated", *info); + FireWebUIListener("bluetooth-info-updated", info); } void DeviceEmulatorMessageHandler::HandleRequestBluetoothPair( @@ -579,39 +576,36 @@ std::string DeviceEmulatorMessageHandler::CreateBluetoothDeviceFromListValue( return props.device_path; } -std::unique_ptr<base::DictionaryValue> -DeviceEmulatorMessageHandler::GetDeviceInfo( +base::Value DeviceEmulatorMessageHandler::GetDeviceInfo( const dbus::ObjectPath& object_path) { // Get the device's properties. bluez::FakeBluetoothDeviceClient::Properties* props = fake_bluetooth_device_client_->GetProperties(object_path); - std::unique_ptr<base::DictionaryValue> device(new base::DictionaryValue()); - std::unique_ptr<base::ListValue> uuids(new base::ListValue); bluez::FakeBluetoothDeviceClient::SimulatedPairingOptions* options = fake_bluetooth_device_client_->GetPairingOptions(object_path); - device->SetString("path", object_path.value()); - device->SetString("name", props->name.value()); - device->SetString("alias", props->alias.value()); - device->SetString("address", props->address.value()); + base::Value device(base::Value::Type::DICTIONARY); + device.SetStringKey("path", object_path.value()); + device.SetStringKey("name", props->name.value()); + device.SetStringKey("alias", props->alias.value()); + device.SetStringKey("address", props->address.value()); if (options) { - device->SetString("pairingMethod", options->pairing_method); - device->SetString("pairingAuthToken", options->pairing_auth_token); - device->SetString("pairingAction", options->pairing_action); + device.SetStringKey("pairingMethod", options->pairing_method); + device.SetStringKey("pairingAuthToken", options->pairing_auth_token); + device.SetStringKey("pairingAction", options->pairing_action); } else { - device->SetString("pairingMethod", ""); - device->SetString("pairingAuthToken", ""); - device->SetString("pairingAction", ""); - } - device->SetInteger("classValue", props->bluetooth_class.value()); - device->SetBoolean("isTrusted", props->trusted.value()); - device->SetBoolean("incoming", false); - - for (const std::string& uuid : props->uuids.value()) { - uuids->AppendString(uuid); + device.SetStringKey("pairingMethod", ""); + device.SetStringKey("pairingAuthToken", ""); + device.SetStringKey("pairingAction", ""); } - - device->Set("uuids", std::move(uuids)); + device.SetIntKey("classValue", props->bluetooth_class.value()); + device.SetBoolKey("isTrusted", props->trusted.value()); + device.SetBoolKey("incoming", false); + + base::Value uuids(base::Value::Type::LIST); + for (const std::string& uuid : props->uuids.value()) + uuids.Append(uuid); + device.SetKey("uuids", std::move(uuids)); return device; } diff --git a/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h b/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h index 3afd435d960..9a59d740741 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.h @@ -16,7 +16,6 @@ #include "device/bluetooth/bluetooth_adapter.h" namespace base { -class DictionaryValue; class ListValue; } // namespace base @@ -118,8 +117,7 @@ class DeviceEmulatorMessageHandler : // Builds a dictionary with each key representing a property of the device // with path |object_path|. - std::unique_ptr<base::DictionaryValue> GetDeviceInfo( - const dbus::ObjectPath& object_path); + base::Value GetDeviceInfo(const dbus::ObjectPath& object_path); void ConnectToBluetoothDevice(const std::string& address); diff --git a/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/OWNERS b/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/OWNERS index e7edf2e630f..a8183f48709 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/OWNERS +++ b/chromium/chrome/browser/ui/webui/chromeos/in_session_password_change/OWNERS @@ -1,2 +1 @@ -olsen@chromium.org rsorokin@chromium.org diff --git a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc index 43f44e8bbe9..af861bf1ef7 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.cc @@ -19,6 +19,7 @@ #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "ui/wm/core/shadow_types.h" namespace chromeos { @@ -114,6 +115,13 @@ const std::string& InternetConfigDialog::Id() { return dialog_id_; } +void InternetConfigDialog::AdjustWidgetInitParams( + views::Widget::InitParams* params) { + params->type = views::Widget::InitParams::Type::TYPE_WINDOW_FRAMELESS; + params->shadow_type = views::Widget::InitParams::ShadowType::kDrop; + params->shadow_elevation = wm::kShadowElevationActiveWindow; +} + void InternetConfigDialog::GetDialogSize(gfx::Size* size) const { const NetworkState* network = network_id_.empty() ? nullptr diff --git a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h index f3d3dfcaf9f..4888ee69139 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h +++ b/chromium/chrome/browser/ui/webui/chromeos/internet_config_dialog.h @@ -25,6 +25,9 @@ class InternetConfigDialog : public SystemWebDialogDelegate { // Shows a network configuration dialog for a new network of |network_type|. static void ShowDialogForNetworkType(const std::string& network_type); + // SystemWebDialogDelegate + void AdjustWidgetInitParams(views::Widget::InitParams* params) override; + protected: // |dialog_id| provides a pre-calculated identifier for the dialog based on // the network type and the network id. diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/DEPS b/chromium/chrome/browser/ui/webui/chromeos/login/DEPS index 4994ed97905..6e2f237df12 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/DEPS +++ b/chromium/chrome/browser/ui/webui/chromeos/login/DEPS @@ -1,5 +1,4 @@ specific_include_rules = { - # TODO(mash): Fix. https://crbug.com/856375. "core_oobe_handler\.cc": [ "+ash/shell.h", ], @@ -8,8 +7,6 @@ specific_include_rules = { "+ash/shell.h", ], "oobe_display_chooser_unittest.cc": [ - # TODO(mash) Use a non-ash test ui::InputDeviceEventObserver - # environment for testing this. "+ash/display/display_configuration_controller.h", "+ash/shell.h", "+ash/test/ash_test_base.h", diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc index f2882ee9ec6..1b1f25b9582 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.cc @@ -4,19 +4,9 @@ #include "chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h" -#include <memory> - -#include "base/bind.h" -#include "chrome/browser/chromeos/authpolicy/authpolicy_helper.h" -#include "chrome/browser/chromeos/login/oobe_screen.h" -#include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h" -#include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" #include "chrome/grit/generated_resources.h" -#include "chromeos/login/auth/key.h" #include "components/login/localized_values_builder.h" -#include "components/user_manager/known_user.h" -#include "ui/base/l10n/l10n_util.h" namespace chromeos { @@ -25,24 +15,19 @@ namespace { constexpr char kUsernameKey[] = "username"; constexpr char kErrorKey[] = "error"; -// Possible error states of the Active Directory password change screen. Must be -// in the same order as ACTIVE_DIRECTORY_PASSWORD_CHANGE_ERROR_STATE enum -// values. -enum class ActiveDirectoryPasswordChangeErrorState { - WRONG_OLD_PASSWORD = 0, - NEW_PASSWORD_REJECTED = 1, -}; - } // namespace +constexpr StaticOobeScreenId ActiveDirectoryPasswordChangeView::kScreenId; + ActiveDirectoryPasswordChangeScreenHandler:: ActiveDirectoryPasswordChangeScreenHandler( JSCallsContainer* js_calls_container, CoreOobeView* core_oobe_view) - : BaseScreenHandler(OobeScreen::SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE, - js_calls_container), - authpolicy_login_helper_(std::make_unique<AuthPolicyHelper>()), - core_oobe_view_(core_oobe_view) {} + : BaseScreenHandler(kScreenId, js_calls_container), + core_oobe_view_(core_oobe_view) { + set_user_acted_method_path( + "login.ActiveDirectoryPasswordChangeScreen.userActed"); +} ActiveDirectoryPasswordChangeScreenHandler:: ~ActiveDirectoryPasswordChangeScreenHandler() {} @@ -55,86 +40,41 @@ void ActiveDirectoryPasswordChangeScreenHandler::DeclareLocalizedValues( void ActiveDirectoryPasswordChangeScreenHandler::Initialize() {} void ActiveDirectoryPasswordChangeScreenHandler::RegisterMessages() { - AddCallback("completeActiveDirectoryPasswordChange", + BaseScreenHandler::RegisterMessages(); + AddCallback("login.ActiveDirectoryPasswordChangeScreen.changePassword", &ActiveDirectoryPasswordChangeScreenHandler::HandleComplete); - AddCallback("cancelActiveDirectoryPasswordChange", - &ActiveDirectoryPasswordChangeScreenHandler::HandleCancel); } -void ActiveDirectoryPasswordChangeScreenHandler::HandleComplete( +void ActiveDirectoryPasswordChangeScreenHandler::Show( const std::string& username, - const std::string& old_password, - const std::string& new_password) { - authpolicy_login_helper_->AuthenticateUser( - username, std::string() /* object_guid */, - old_password + "\n" + new_password + "\n" + new_password, - base::BindOnce( - &ActiveDirectoryPasswordChangeScreenHandler::OnAuthFinished, - weak_factory_.GetWeakPtr(), username, Key(new_password))); + int error) { + base::DictionaryValue data; + data.SetString(kUsernameKey, username); + data.SetInteger(kErrorKey, error); + ShowScreenWithData(kScreenId, &data); } -void ActiveDirectoryPasswordChangeScreenHandler::HandleCancel() { - authpolicy_login_helper_->CancelRequestsAndRestart(); +void ActiveDirectoryPasswordChangeScreenHandler::Bind( + ActiveDirectoryPasswordChangeScreen* screen) { + screen_ = screen; + BaseScreenHandler::SetBaseScreen(screen_); } -void ActiveDirectoryPasswordChangeScreenHandler::ShowScreen( - const std::string& username) { - base::DictionaryValue data; - data.SetString(kUsernameKey, username); - ShowScreenWithData(OobeScreen::SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE, - &data); +void ActiveDirectoryPasswordChangeScreenHandler::Unbind() { + screen_ = nullptr; + BaseScreenHandler::SetBaseScreen(nullptr); } -void ActiveDirectoryPasswordChangeScreenHandler::ShowScreenWithError( - int error) { - base::DictionaryValue data; - data.SetInteger(kErrorKey, error); - ShowScreenWithData(OobeScreen::SCREEN_ACTIVE_DIRECTORY_PASSWORD_CHANGE, - &data); +void ActiveDirectoryPasswordChangeScreenHandler::ShowSignInError( + const std::string& error_text) { + core_oobe_view_->ShowSignInError(0, error_text, std::string(), + HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); } -void ActiveDirectoryPasswordChangeScreenHandler::OnAuthFinished( - const std::string& username, - const Key& key, - authpolicy::ErrorType error, - const authpolicy::ActiveDirectoryAccountInfo& account_info) { - switch (error) { - case authpolicy::ERROR_NONE: { - DCHECK(account_info.has_account_id() && - !account_info.account_id().empty()); - const AccountId account_id = user_manager::known_user::GetAccountId( - username, account_info.account_id(), AccountType::ACTIVE_DIRECTORY); - DCHECK(LoginDisplayHost::default_host()); - LoginDisplayHost::default_host()->SetDisplayAndGivenName( - account_info.display_name(), account_info.given_name()); - UserContext user_context( - user_manager::UserType::USER_TYPE_ACTIVE_DIRECTORY, account_id); - user_context.SetKey(key); - user_context.SetAuthFlow(UserContext::AUTH_FLOW_ACTIVE_DIRECTORY); - user_context.SetIsUsingOAuth(false); - LoginDisplayHost::default_host()->CompleteLogin(user_context); - break; - } - case authpolicy::ERROR_BAD_PASSWORD: - ShowScreenWithError(static_cast<int>( - ActiveDirectoryPasswordChangeErrorState::WRONG_OLD_PASSWORD)); - break; - case authpolicy::ERROR_PASSWORD_REJECTED: - ShowScreenWithError(static_cast<int>( - ActiveDirectoryPasswordChangeErrorState::NEW_PASSWORD_REJECTED)); - core_oobe_view_->ShowSignInError( - 0, - l10n_util::GetStringUTF8( - IDS_AD_PASSWORD_CHANGE_NEW_PASSWORD_REJECTED_LONG_ERROR), - std::string(), HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); - break; - default: - NOTREACHED() << "Unhandled error: " << error; - ShowScreen(username); - core_oobe_view_->ShowSignInError( - 0, l10n_util::GetStringUTF8(IDS_AD_AUTH_UNKNOWN_ERROR), std::string(), - HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); - } +void ActiveDirectoryPasswordChangeScreenHandler::HandleComplete( + const std::string& old_password, + const std::string& new_password) { + screen_->ChangePassword(old_password, new_password); } } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h index 8768175e503..33e5eb4d230 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h @@ -8,21 +8,42 @@ #include <string> #include "base/macros.h" -#include "chrome/browser/chromeos/authpolicy/authpolicy_helper.h" +#include "chrome/browser/chromeos/login/screens/active_directory_password_change_screen.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" -namespace authpolicy { -class ActiveDirectoryAccountInfo; -} - namespace chromeos { +class ActiveDirectoryPasswordChangeScreen; class CoreOobeView; -class Key; -// A class that handles WebUI hooks in Active Directory password change screen. -class ActiveDirectoryPasswordChangeScreenHandler : public BaseScreenHandler { +// Interface for dependency injection between +// ActiveDirectoryPasswordChangeScreen and its WebUI representation. +class ActiveDirectoryPasswordChangeView { + public: + constexpr static StaticOobeScreenId kScreenId{"ad-password-change"}; + + virtual ~ActiveDirectoryPasswordChangeView() {} + + // Shows the contents of the screen. + virtual void Show(const std::string& username, int error) = 0; + + // Binds |screen| to the view. + virtual void Bind(ActiveDirectoryPasswordChangeScreen* screen) = 0; + + // Unbinds the screen from the view. + virtual void Unbind() = 0; + + // Shows sign-in error bubble. + virtual void ShowSignInError(const std::string& error_text) = 0; +}; + +// A class that handles WebUI hooks in Active Directory password change screen. +class ActiveDirectoryPasswordChangeScreenHandler + : public ActiveDirectoryPasswordChangeView, + public BaseScreenHandler { public: + using TView = ActiveDirectoryPasswordChangeView; + ActiveDirectoryPasswordChangeScreenHandler( JSCallsContainer* js_calls_container, CoreOobeView* core_oobe_view); @@ -36,37 +57,22 @@ class ActiveDirectoryPasswordChangeScreenHandler : public BaseScreenHandler { // WebUIMessageHandler implementation: void RegisterMessages() override; - // WebUI message handlers. - void HandleComplete(const std::string& username, - const std::string& old_password, - const std::string& new_password); - void HandleCancel(); - - // Shows the password change screen for |username|. - void ShowScreen(const std::string& username); + // ActiveDirectoryPasswordChangeView: + void Show(const std::string& username, int error) override; + void Bind(ActiveDirectoryPasswordChangeScreen* screen) override; + void Unbind() override; + void ShowSignInError(const std::string& error_text) override; private: - // Shows the screen with the error message corresponding to |error|. - void ShowScreenWithError(int error); - - // Callback called by AuthPolicyHelper::AuthenticateUser with results and - // error code. (see AuthPolicyHelper::AuthenticateUser) - void OnAuthFinished( - const std::string& username, - const Key& key, - authpolicy::ErrorType error, - const authpolicy::ActiveDirectoryAccountInfo& account_info); + // WebUI message handlers. + void HandleComplete(const std::string& old_password, + const std::string& new_password); - // Helper to call AuthPolicyClient and cancel calls if needed. Used to change - // password on the Active Directory server. - std::unique_ptr<AuthPolicyHelper> authpolicy_login_helper_; + ActiveDirectoryPasswordChangeScreen* screen_ = nullptr; // Non-owned. Used to display signin error. CoreOobeView* core_oobe_view_ = nullptr; - base::WeakPtrFactory<ActiveDirectoryPasswordChangeScreenHandler> - weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(ActiveDirectoryPasswordChangeScreenHandler); }; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc index 30bfa1f347e..fd90616362b 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc @@ -136,7 +136,7 @@ void AssistantOptInFlowScreenHandler::RegisterMessages() { &AssistantOptInFlowScreenHandler::HandleVoiceMatchScreenShown); AddCallback("login.AssistantOptInFlowScreen.GetMoreScreen.screenShown", &AssistantOptInFlowScreenHandler::HandleGetMoreScreenShown); - AddCallback("login.AssistantOptInFlowScreen.LoadingScreen.timeout", + AddCallback("login.AssistantOptInFlowScreen.timeout", &AssistantOptInFlowScreenHandler::HandleLoadingTimeout); AddCallback("login.AssistantOptInFlowScreen.flowFinished", &AssistantOptInFlowScreenHandler::HandleFlowFinished); @@ -519,7 +519,8 @@ void AssistantOptInFlowScreenHandler::HandleVoiceMatchScreenUserAction( // No need to disable hotword for retrain flow since user has a model. prefs->SetBoolean(assistant::prefs::kAssistantHotwordEnabled, false); } - StopSpeakerIdEnrollment(); + if (voice_match_enrollment_started_) + StopSpeakerIdEnrollment(); ShowNextScreen(); } else if (action == kRecordPressed) { if (!prefs->GetBoolean(assistant::prefs::kAssistantHotwordEnabled)) { diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h index 2839eb2f64b..cff23bb6dcd 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.h @@ -9,7 +9,6 @@ #include <string> #include <utility> -#include "ash/public/cpp/assistant/assistant_settings.h" #include "ash/public/cpp/assistant/assistant_setup.h" #include "ash/public/cpp/assistant/assistant_state.h" #include "base/macros.h" @@ -42,7 +41,6 @@ class AssistantOptInFlowScreenView { DISALLOW_COPY_AND_ASSIGN(AssistantOptInFlowScreenView); }; -// TODO(updowndota): Refactor to reuse AssistantOptInHandler methods. class AssistantOptInFlowScreenHandler : public BaseScreenHandler, public AssistantOptInFlowScreenView, diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/base_webui_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/base_webui_handler.cc index cff1e165eaa..7d650badd2d 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/base_webui_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/base_webui_handler.cc @@ -41,8 +41,6 @@ void BaseWebUIHandler::ShowScreen(OobeScreenId screen) { void BaseWebUIHandler::ShowScreenWithData(OobeScreenId screen, const base::DictionaryValue* data) { - if (!web_ui()) - return; base::DictionaryValue screen_params; screen_params.SetString("id", screen.name); if (data) { diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc index b4a51961a0f..7071f8ae0f9 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc @@ -19,8 +19,6 @@ #include "build/branding_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" -#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" -#include "chrome/browser/chromeos/accessibility/magnification_manager.h" #include "chrome/browser/chromeos/login/configuration_keys.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h" @@ -29,8 +27,7 @@ #include "chrome/browser/chromeos/login/screens/reset_screen.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/chromeos/login/wizard_controller.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" +#include "chrome/browser/chromeos/policy/enrollment_requisition_manager.h" #include "chrome/browser/chromeos/system/input_device_settings.h" #include "chrome/browser/chromeos/system/timezone_resolver_manager.h" #include "chrome/browser/lifetime/application_lifetime.h" @@ -64,24 +61,9 @@ namespace chromeos { namespace { -bool IsRemoraRequisition() { - policy::DeviceCloudPolicyManagerChromeOS* policy_manager = - g_browser_process->platform_part() - ->browser_policy_connector_chromeos() - ->GetDeviceCloudPolicyManager(); - return policy_manager && policy_manager->IsRemoraRequisition(); -} - void LaunchResetScreen() { - // Don't recreate WizardController if it already exists. - WizardController* const wizard_controller = - WizardController::default_controller(); - if (wizard_controller && !wizard_controller->login_screen_started()) { - wizard_controller->AdvanceToScreen(ResetView::kScreenId); - } else { - DCHECK(LoginDisplayHost::default_host()); - LoginDisplayHost::default_host()->StartWizard(ResetView::kScreenId); - } + DCHECK(LoginDisplayHost::default_host()); + LoginDisplayHost::default_host()->StartWizard(ResetView::kScreenId); } } // namespace @@ -91,11 +73,6 @@ void LaunchResetScreen() { CoreOobeHandler::CoreOobeHandler(JSCallsContainer* js_calls_container) : BaseWebUIHandler(js_calls_container), version_info_updater_(this) { DCHECK(js_calls_container); - AccessibilityManager* accessibility_manager = AccessibilityManager::Get(); - CHECK(accessibility_manager); - accessibility_subscription_ = accessibility_manager->RegisterCallback( - base::Bind(&CoreOobeHandler::OnAccessibilityStatusChanged, - base::Unretained(this))); ash::TabletMode::Get()->AddObserver(this); @@ -118,17 +95,6 @@ void CoreOobeHandler::DeclareLocalizedValues( builder->Add("productName", IDS_SHORT_PRODUCT_NAME); builder->Add("learnMore", IDS_LEARN_MORE); - // OOBE accessibility options menu strings shown on each screen. - builder->Add("accessibilityLink", IDS_OOBE_ACCESSIBILITY_LINK); - builder->Add("spokenFeedbackOption", IDS_OOBE_SPOKEN_FEEDBACK_OPTION); - builder->Add("selectToSpeakOption", IDS_OOBE_SELECT_TO_SPEAK_OPTION); - builder->Add("largeCursorOption", IDS_OOBE_LARGE_CURSOR_OPTION); - builder->Add("highContrastOption", IDS_OOBE_HIGH_CONTRAST_MODE_OPTION); - builder->Add("screenMagnifierOption", IDS_OOBE_SCREEN_MAGNIFIER_OPTION); - builder->Add("dockedMagnifierOption", IDS_OOBE_DOCKED_MAGNIFIER_OPTION); - builder->Add("virtualKeyboardOption", IDS_OOBE_VIRTUAL_KEYBOARD_OPTION); - builder->Add("closeAccessibilityMenu", IDS_OOBE_CLOSE_ACCESSIBILITY_MENU); - // Strings for the device requisition prompt. builder->Add("deviceRequisitionPromptCancel", IDS_ENTERPRISE_DEVICE_REQUISITION_PROMPT_CANCEL); @@ -161,7 +127,6 @@ void CoreOobeHandler::DeclareLocalizedValues( } void CoreOobeHandler::Initialize() { - UpdateA11yState(); UpdateOobeUIVisibility(); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) version_info_updater_.StartUpdate(true); @@ -188,18 +153,6 @@ void CoreOobeHandler::RegisterMessages() { &CoreOobeHandler::HandleSkipUpdateEnrollAfterEula); AddCallback("updateCurrentScreen", &CoreOobeHandler::HandleUpdateCurrentScreen); - AddCallback("enableHighContrast", &CoreOobeHandler::HandleEnableHighContrast); - AddCallback("enableLargeCursor", &CoreOobeHandler::HandleEnableLargeCursor); - AddCallback("enableVirtualKeyboard", - &CoreOobeHandler::HandleEnableVirtualKeyboard); - AddCallback("enableScreenMagnifier", - &CoreOobeHandler::HandleEnableScreenMagnifier); - AddCallback("enableSpokenFeedback", - &CoreOobeHandler::HandleEnableSpokenFeedback); - AddCallback("enableSelectToSpeak", - &CoreOobeHandler::HandleEnableSelectToSpeak); - AddCallback("enableDockedMagnifier", - &CoreOobeHandler::HandleEnableDockedMagnifier); AddCallback("setDeviceRequisition", &CoreOobeHandler::HandleSetDeviceRequisition); AddCallback("skipToLoginForTesting", @@ -234,38 +187,20 @@ void CoreOobeHandler::ShowSignInError( help_link_text, static_cast<int>(help_topic_id)); } -void CoreOobeHandler::ShowTpmError() { - CallJS("cr.ui.Oobe.showTpmError"); -} - void CoreOobeHandler::ShowDeviceResetScreen() { LaunchResetScreen(); } void CoreOobeHandler::ShowEnableDebuggingScreen() { - // Don't recreate WizardController if it already exists. - WizardController* wizard_controller = WizardController::default_controller(); - if (wizard_controller && !wizard_controller->login_screen_started()) { - wizard_controller->AdvanceToScreen(EnableDebuggingScreenView::kScreenId); - } + DCHECK(LoginDisplayHost::default_host()); + LoginDisplayHost::default_host()->StartWizard( + EnableDebuggingScreenView::kScreenId); } void CoreOobeHandler::ShowEnableAdbSideloadingScreen() { - // Don't recreate WizardController if it already exists. - WizardController* wizard_controller = WizardController::default_controller(); - if (wizard_controller && !wizard_controller->login_screen_started()) { - wizard_controller->AdvanceToScreen( - EnableAdbSideloadingScreenView::kScreenId); - } else { - DCHECK(LoginDisplayHost::default_host()); - LoginDisplayHost::default_host()->StartWizard( - EnableAdbSideloadingScreenView::kScreenId); - } -} - -void CoreOobeHandler::ShowActiveDirectoryPasswordChangeScreen( - const std::string& username) { - CallJS("cr.ui.Oobe.showActiveDirectoryPasswordChangeScreen", username); + DCHECK(LoginDisplayHost::default_host()); + LoginDisplayHost::default_host()->StartWizard( + EnableAdbSideloadingScreenView::kScreenId); } void CoreOobeHandler::ShowSignInUI(const std::string& email) { @@ -284,19 +219,6 @@ void CoreOobeHandler::RefocusCurrentPod() { CallJS("cr.ui.Oobe.refocusCurrentPod"); } -void CoreOobeHandler::ShowPasswordChangedScreen(bool show_password_error, - const std::string& email) { - CallJS("cr.ui.Oobe.showPasswordChangedScreen", show_password_error, email); -} - -void CoreOobeHandler::SetUsageStats(bool checked) { - CallJS("cr.ui.Oobe.setUsageStats", checked); -} - -void CoreOobeHandler::SetTpmPassword(const std::string& tpm_password) { - CallJS("cr.ui.Oobe.setTpmPassword", tpm_password); -} - void CoreOobeHandler::ClearErrors() { CallJS("cr.ui.Oobe.clearErrors"); } @@ -324,7 +246,8 @@ void CoreOobeHandler::SetShelfHeight(int height) { void CoreOobeHandler::HandleInitialized() { // TODO(crbug.com/1082670): Remove excessive logging after investigation. - LOG(ERROR) << "CoreOobeHandler::HandleInitialized"; + LOG(ERROR) << "1082670 : CoreOobeHandler::HandleInitialized"; + GetOobeUI()->InitializeHandlers(); AllowJavascript(); } @@ -344,44 +267,6 @@ void CoreOobeHandler::HandleUpdateCurrentScreen( screen == EulaView::kScreenId); } -void CoreOobeHandler::HandleEnableHighContrast(bool enabled) { - AccessibilityManager::Get()->EnableHighContrast(enabled); -} - -void CoreOobeHandler::HandleEnableLargeCursor(bool enabled) { - AccessibilityManager::Get()->EnableLargeCursor(enabled); -} - -void CoreOobeHandler::HandleEnableVirtualKeyboard(bool enabled) { - AccessibilityManager::Get()->EnableVirtualKeyboard(enabled); -} - -void CoreOobeHandler::HandleEnableScreenMagnifier(bool enabled) { - DCHECK(MagnificationManager::Get()); - MagnificationManager::Get()->SetMagnifierEnabled(enabled); -} - -void CoreOobeHandler::HandleEnableSpokenFeedback(bool /* enabled */) { - // Checkbox is initialized on page init and updates when spoken feedback - // setting is changed so just toggle spoken feedback here. - AccessibilityManager::Get()->EnableSpokenFeedback( - !AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); -} - -void CoreOobeHandler::HandleEnableSelectToSpeak(bool /* enabled */) { - // Checkbox is initialized on page init and updates when Select to Speak - // setting is changed so just toggle Select to Speak here. - AccessibilityManager::Get()->SetSelectToSpeakEnabled( - !AccessibilityManager::Get()->IsSelectToSpeakEnabled()); -} - -void CoreOobeHandler::HandleEnableDockedMagnifier(bool enabled) { - // Checkbox is initialized on page init and updates when the docked magnifier - // setting is changed so just toggle Select to Speak here. - DCHECK(MagnificationManager::Get()); - MagnificationManager::Get()->SetDockedMagnifierEnabled(enabled); -} - void CoreOobeHandler::HandleHideOobeDialog() { if (LoginDisplayHost::default_host()) LoginDisplayHost::default_host()->HideOobeDialog(); @@ -389,13 +274,11 @@ void CoreOobeHandler::HandleHideOobeDialog() { void CoreOobeHandler::HandleSetDeviceRequisition( const std::string& requisition) { - policy::BrowserPolicyConnectorChromeOS* connector = - g_browser_process->platform_part()->browser_policy_connector_chromeos(); std::string initial_requisition = - connector->GetDeviceCloudPolicyManager()->GetDeviceRequisition(); - connector->GetDeviceCloudPolicyManager()->SetDeviceRequisition(requisition); + policy::EnrollmentRequisitionManager::GetDeviceRequisition(); + policy::EnrollmentRequisitionManager::SetDeviceRequisition(requisition); - if (IsRemoraRequisition()) { + if (policy::EnrollmentRequisitionManager::IsRemoraRequisition()) { // CfM devices default to static timezone. g_browser_process->local_state()->SetInteger( prefs::kResolveDeviceTimezoneByGeolocationMethod, @@ -405,19 +288,21 @@ void CoreOobeHandler::HandleSetDeviceRequisition( // Exit Chrome to force the restart as soon as a new requisition is set. if (initial_requisition != - connector->GetDeviceCloudPolicyManager()->GetDeviceRequisition()) { + policy::EnrollmentRequisitionManager::GetDeviceRequisition()) { chrome::AttemptRestart(); } } void CoreOobeHandler::HandleSkipToLoginForTesting() { - if (WizardController::default_controller()) + WizardController* controller = WizardController::default_controller(); + if (controller && controller->is_initialized()) WizardController::default_controller()->SkipToLoginForTesting(); } void CoreOobeHandler::HandleSkipToUpdateForTesting() { - if (WizardController::default_controller()) - WizardController::default_controller()->SkipToUpdateForTesting(); + WizardController* controller = WizardController::default_controller(); + if (controller && controller->is_initialized()) + controller->SkipToUpdateForTesting(); } void CoreOobeHandler::HandleToggleResetScreen() { @@ -464,26 +349,6 @@ void CoreOobeHandler::ForwardAccelerator(std::string accelerator_name) { CallJS("cr.ui.Oobe.handleAccelerator", accelerator_name); } -void CoreOobeHandler::UpdateA11yState() { - base::DictionaryValue a11y_info; - a11y_info.SetBoolean("highContrastEnabled", - AccessibilityManager::Get()->IsHighContrastEnabled()); - a11y_info.SetBoolean("largeCursorEnabled", - AccessibilityManager::Get()->IsLargeCursorEnabled()); - a11y_info.SetBoolean("spokenFeedbackEnabled", - AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); - a11y_info.SetBoolean("selectToSpeakEnabled", - AccessibilityManager::Get()->IsSelectToSpeakEnabled()); - DCHECK(MagnificationManager::Get()); - a11y_info.SetBoolean("screenMagnifierEnabled", - MagnificationManager::Get()->IsMagnifierEnabled()); - a11y_info.SetBoolean("dockedMagnifierEnabled", - MagnificationManager::Get()->IsDockedMagnifierEnabled()); - a11y_info.SetBoolean("virtualKeyboardEnabled", - AccessibilityManager::Get()->IsVirtualKeyboardEnabled()); - CallJS("cr.ui.Oobe.refreshA11yInfo", a11y_info); -} - void CoreOobeHandler::UpdateOobeUIVisibility() { const std::string& display = GetOobeUI()->display_type(); bool has_api_keys_configured = google_apis::HasAPIKeyConfigured() && @@ -529,14 +394,8 @@ void CoreOobeHandler::UpdateLabel(const std::string& id, } void CoreOobeHandler::UpdateDeviceRequisition() { - policy::DeviceCloudPolicyManagerChromeOS* policy_manager = - g_browser_process->platform_part() - ->browser_policy_connector_chromeos() - ->GetDeviceCloudPolicyManager(); - if (policy_manager) { - CallJS("cr.ui.Oobe.updateDeviceRequisition", - policy_manager->GetDeviceRequisition()); - } + CallJS("cr.ui.Oobe.updateDeviceRequisition", + policy::EnrollmentRequisitionManager::GetDeviceRequisition()); } void CoreOobeHandler::UpdateKeyboardState() { @@ -588,14 +447,6 @@ void CoreOobeHandler::OnOobeConfigurationChanged() { CallJS("cr.ui.Oobe.updateOobeConfiguration", configuration); } -void CoreOobeHandler::OnAccessibilityStatusChanged( - const AccessibilityStatusEventDetails& details) { - if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN) - accessibility_subscription_.reset(); - else - UpdateA11yState(); -} - void CoreOobeHandler::HandleLaunchHelpApp(double help_topic_id) { if (!help_app_.get()) help_app_ = new HelpAppLauncher( diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h index 44940f99887..fc684c7f0a5 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h @@ -16,7 +16,6 @@ #include "base/memory/weak_ptr.h" #include "base/optional.h" #include "base/values.h" -#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/login/demo_mode/demo_mode_detector.h" #include "chrome/browser/chromeos/login/help_app_launcher.h" #include "chrome/browser/chromeos/login/oobe_configuration.h" @@ -56,15 +55,10 @@ class CoreOobeView { const std::string& error_text, const std::string& help_link_text, HelpAppLauncher::HelpTopic help_topic_id) = 0; - virtual void ShowTpmError() = 0; virtual void ShowSignInUI(const std::string& email) = 0; virtual void ResetSignInUI(bool force_online) = 0; virtual void ClearUserPodPassword() = 0; virtual void RefocusCurrentPod() = 0; - virtual void ShowPasswordChangedScreen(bool show_password_error, - const std::string& email) = 0; - virtual void SetUsageStats(bool checked) = 0; - virtual void SetTpmPassword(const std::string& tmp_password) = 0; virtual void ClearErrors() = 0; virtual void ReloadContent(const base::DictionaryValue& dictionary) = 0; virtual void ReloadEulaContent(const base::DictionaryValue& dictionary) = 0; @@ -78,8 +72,6 @@ class CoreOobeView { virtual void InitDemoModeDetection() = 0; virtual void StopDemoModeDetection() = 0; virtual void UpdateKeyboardState() = 0; - virtual void ShowActiveDirectoryPasswordChangeScreen( - const std::string& username) = 0; }; // The core handler for Javascript messages related to the "oobe" view. @@ -139,15 +131,10 @@ class CoreOobeHandler : public BaseWebUIHandler, const std::string& error_text, const std::string& help_link_text, HelpAppLauncher::HelpTopic help_topic_id) override; - void ShowTpmError() override; void ShowSignInUI(const std::string& email) override; void ResetSignInUI(bool force_online) override; void ClearUserPodPassword() override; void RefocusCurrentPod() override; - void ShowPasswordChangedScreen(bool show_password_error, - const std::string& email) override; - void SetUsageStats(bool checked) override; - void SetTpmPassword(const std::string& tmp_password) override; void ClearErrors() override; void ReloadContent(const base::DictionaryValue& dictionary) override; void ReloadEulaContent(const base::DictionaryValue& dictionary) override; @@ -158,8 +145,6 @@ class CoreOobeHandler : public BaseWebUIHandler, void ShowDeviceResetScreen() override; void ShowEnableAdbSideloadingScreen() override; void ShowEnableDebuggingScreen() override; - void ShowActiveDirectoryPasswordChangeScreen( - const std::string& username) override; void InitDemoModeDetection() override; void StopDemoModeDetection() override; @@ -173,13 +158,6 @@ class CoreOobeHandler : public BaseWebUIHandler, void OnOobeConfigurationChanged() override; // Handlers for JS WebUI messages. - void HandleEnableLargeCursor(bool enabled); - void HandleEnableHighContrast(bool enabled); - void HandleEnableVirtualKeyboard(bool enabled); - void HandleEnableScreenMagnifier(bool enabled); - void HandleEnableSpokenFeedback(bool /* enabled */); - void HandleEnableSelectToSpeak(bool /* enabled */); - void HandleEnableDockedMagnifier(bool /* enabled */); void HandleHideOobeDialog(); void HandleInitialized(); void HandleSkipUpdateEnrollAfterEula(); @@ -211,9 +189,6 @@ class CoreOobeHandler : public BaseWebUIHandler, // to tab/shift-tab event. void HandleRaiseTabKeyEvent(bool reverse); - // Updates a11y menu state based on the current a11y features state(on/off). - void UpdateA11yState(); - // Calls javascript to sync OOBE UI visibility with show_oobe_ui_. void UpdateOobeUIVisibility(); @@ -226,10 +201,6 @@ class CoreOobeHandler : public BaseWebUIHandler, // Updates client area size based on the primary screen size. void UpdateClientAreaSize(); - // Notification of a change in the accessibility settings. - void OnAccessibilityStatusChanged( - const AccessibilityStatusEventDetails& details); - // True if we should show OOBE instead of login. bool show_oobe_ui_ = false; @@ -239,8 +210,6 @@ class CoreOobeHandler : public BaseWebUIHandler, // Help application used for help dialogs. scoped_refptr<HelpAppLauncher> help_app_; - std::unique_ptr<AccessibilityStatusSubscription> accessibility_subscription_; - DemoModeDetector demo_mode_detector_; mojo::Remote<ash::mojom::CrosDisplayConfigController> cros_display_config_; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/debug/debug_overlay_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/debug/debug_overlay_handler.cc index 1520461230b..5548ccda6a3 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/debug/debug_overlay_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/debug/debug_overlay_handler.cc @@ -12,6 +12,9 @@ #include "base/files/file_util.h" #include "base/path_service.h" #include "base/system/sys_info.h" +#include "base/task/post_task.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" #include "base/time/time.h" #include "chrome/common/chrome_paths.h" #include "chromeos/constants/chromeos_switches.h" @@ -44,9 +47,10 @@ void RunStoreScreenshotOnTaskRunner( const base::FilePath& screenshot_dir, const std::string& screenshot_name, scoped_refptr<base::RefCountedMemory> png_data) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&StoreScreenshot, screenshot_dir, - screenshot_name, png_data)); + base::ThreadPool::PostTask( + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, + base::BindOnce(&StoreScreenshot, screenshot_dir, screenshot_name, + png_data)); } } // namespace diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc index a0b5afecfe5..b63e52d4391 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.cc @@ -20,37 +20,30 @@ DeviceDisabledScreenHandler::DeviceDisabledScreenHandler( } DeviceDisabledScreenHandler::~DeviceDisabledScreenHandler() { - if (delegate_) - delegate_->OnViewDestroyed(this); + if (screen_) + screen_->OnViewDestroyed(this); } -void DeviceDisabledScreenHandler::Show() { - if (!page_is_ready()) { - show_on_init_ = true; - return; - } - - if (delegate_) { - CallJS("login.DeviceDisabledScreen.setSerialNumberAndEnrollmentDomain", - delegate_->GetSerialNumber(), delegate_->GetEnrollmentDomain()); - CallJS("login.DeviceDisabledScreen.setMessage", delegate_->GetMessage()); - } - ShowScreen(kScreenId); +void DeviceDisabledScreenHandler::Show(const std::string& serial, + const std::string& domain, + const std::string& message) { + base::DictionaryValue screen_data; + screen_data.SetStringPath("serial", serial); + screen_data.SetStringPath("domain", domain); + screen_data.SetStringPath("message", message); + ShowScreenWithData(kScreenId, &screen_data); } void DeviceDisabledScreenHandler::Hide() { - show_on_init_ = false; + NOTREACHED() << "Device should reboot upon removing device disabled flag"; } -void DeviceDisabledScreenHandler::SetDelegate(DeviceDisabledScreen* delegate) { - delegate_ = delegate; - if (page_is_ready()) - Initialize(); +void DeviceDisabledScreenHandler::Bind(DeviceDisabledScreen* screen) { + screen_ = screen; } void DeviceDisabledScreenHandler::UpdateMessage(const std::string& message) { - if (page_is_ready()) - CallJS("login.DeviceDisabledScreen.setMessage", message); + CallJS("login.DeviceDisabledScreen.setMessage", message); } void DeviceDisabledScreenHandler::DeclareLocalizedValues( @@ -63,13 +56,6 @@ void DeviceDisabledScreenHandler::DeclareLocalizedValues( } void DeviceDisabledScreenHandler::Initialize() { - if (!page_is_ready() || !delegate_) - return; - - if (show_on_init_) { - Show(); - show_on_init_ = false; - } } void DeviceDisabledScreenHandler::RegisterMessages() { diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h index 1cb75a48ab2..ed647dea28b 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/device_disabled_screen_handler.h @@ -19,9 +19,11 @@ class DeviceDisabledScreenView { virtual ~DeviceDisabledScreenView() {} - virtual void Show() = 0; + virtual void Show(const std::string& serial, + const std::string& domain, + const std::string& message) = 0; virtual void Hide() = 0; - virtual void SetDelegate(DeviceDisabledScreen* delegate) = 0; + virtual void Bind(DeviceDisabledScreen* screen) = 0; virtual void UpdateMessage(const std::string& message) = 0; }; @@ -35,9 +37,11 @@ class DeviceDisabledScreenHandler : public DeviceDisabledScreenView, ~DeviceDisabledScreenHandler() override; // DeviceDisabledScreenActor: - void Show() override; + void Show(const std::string& serial, + const std::string& domain, + const std::string& message) override; void Hide() override; - void SetDelegate(DeviceDisabledScreen* delegate) override; + void Bind(DeviceDisabledScreen* screen) override; void UpdateMessage(const std::string& message) override; // BaseScreenHandler: @@ -49,10 +53,7 @@ class DeviceDisabledScreenHandler : public DeviceDisabledScreenView, // WebUIMessageHandler: void RegisterMessages() override; - DeviceDisabledScreen* delegate_ = nullptr; - - // Indicates whether the screen should be shown right after initialization. - bool show_on_init_ = false; + DeviceDisabledScreen* screen_ = nullptr; DISALLOW_COPY_AND_ASSIGN(DeviceDisabledScreenHandler); }; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc index e5f84a27dd2..81308cb95f2 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc @@ -27,7 +27,7 @@ #include "chrome/browser/chromeos/login/ui/login_display_host.h" #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/policy/device_cloud_policy_manager_chromeos.h" +#include "chrome/browser/chromeos/policy/enrollment_requisition_manager.h" #include "chrome/browser/chromeos/policy/policy_oauth2_token_fetcher.h" #include "chrome/browser/policy/enrollment_status.h" #include "chrome/browser/profiles/profile.h" @@ -412,6 +412,12 @@ void EnrollmentScreenHandler::ShowEnrollmentStatus( IDS_ENTERPRISE_ENROLLMENT_CONSUMER_ACCOUNT_WITH_PACKAGED_LICENSE, true); break; + case policy:: + DM_STATUS_SERVICE_ENTERPRISE_ACCOUNT_IS_NOT_ELIGIBLE_TO_ENROLL: + ShowError( + IDS_ENTERPRISE_ENROLLMENT_ENTERPRISE_ACCOUNT_IS_NOT_ELIGIBLE_TO_ENROLL, + true); + break; case policy::DM_STATUS_SERVICE_ENTERPRISE_TOS_HAS_NOT_BEEN_ACCEPTED: ShowError( IDS_ENTERPRISE_ENROLLMENT_ENTERPRISE_TOS_HAS_NOT_BEEN_ACCEPTED, @@ -772,12 +778,12 @@ void EnrollmentScreenHandler::HandleCompleteLogin(const std::string& user) { void EnrollmentScreenHandler::OnGetCookiesForCompleteLogin( const std::string& user, - const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies) { + const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies) { std::string auth_code; - for (const auto& cookie_with_status : cookies) { - if (cookie_with_status.cookie.Name() == "oauth_code") { - auth_code = cookie_with_status.cookie.Value(); + for (const auto& cookie_with_access_result : cookies) { + if (cookie_with_access_result.cookie.Name() == "oauth_code") { + auth_code = cookie_with_access_result.cookie.Value(); break; } } @@ -882,11 +888,7 @@ void EnrollmentScreenHandler::DoShowWithPartition( if (!app_locale.empty()) screen_data.SetString("hl", app_locale); - policy::DeviceCloudPolicyManagerChromeOS* policy_manager = - g_browser_process->platform_part() - ->browser_policy_connector_chromeos() - ->GetDeviceCloudPolicyManager(); - const bool cfm = policy_manager && policy_manager->IsRemoraRequisition(); + const bool cfm = policy::EnrollmentRequisitionManager::IsRemoraRequisition(); screen_data.SetString("flow", cfm ? "cfm" : "enterprise"); ShowScreenWithData(EnrollmentScreenView::kScreenId, &screen_data); diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h index b83224e3d25..4feaf4b6886 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h @@ -105,8 +105,8 @@ class EnrollmentScreenHandler void HandleCompleteLogin(const std::string& user); void OnGetCookiesForCompleteLogin( const std::string& user, - const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies); + const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies); void HandleAdCompleteLogin(const std::string& machine_name, const std::string& distinguished_name, const std::string& encryption_types, diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc index 03e3c845076..3040f27e447 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/eula_screen_handler.cc @@ -8,6 +8,7 @@ #include <string> #include "base/bind.h" +#include "base/command_line.h" #include "base/macros.h" #include "base/strings/stringprintf.h" #include "chrome/browser/browser_process.h" @@ -143,7 +144,7 @@ void EulaScreenHandler::Initialize() { if (!page_is_ready() || !screen_) return; - core_oobe_view_->SetUsageStats(screen_->IsUsageStatsEnabled()); + CallJS("login.EulaScreen.setUsageStats", screen_->IsUsageStatsEnabled()); if (show_on_init_) { Show(); @@ -152,7 +153,7 @@ void EulaScreenHandler::Initialize() { } void EulaScreenHandler::OnPasswordFetched(const std::string& tpm_password) { - core_oobe_view_->SetTpmPassword(tpm_password); + CallJS("login.EulaScreen.setTpmPassword", tpm_password); } void EulaScreenHandler::HandleOnLearnMore() { diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h index 4dc7fb49bde..956bf1de8c8 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/fake_update_required_screen_handler.h @@ -39,6 +39,7 @@ class FakeUpdateRequiredScreenHandler : public UpdateRequiredView { void SetUIState(UpdateRequiredView::UIState ui_state) override; void SetEnterpriseAndDeviceName(const std::string& enterpriseDomain, const base::string16& deviceName) override {} + void SetEolMessage(const std::string& eolMessage) override {} UpdateRequiredView::UIState ui_state_; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc index 14d58280bee..f22c63fb699 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc @@ -4,45 +4,11 @@ #include "chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h" -#include "base/bind.h" #include "base/strings/string_number_conversions.h" #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h" #include "chrome/browser/chromeos/login/screens/fingerprint_setup_screen.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/profiles/profile_manager.h" -#include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/login/localized_values_builder.h" -#include "components/prefs/pref_service.h" -#include "content/public/browser/device_service.h" -#include "ui/base/l10n/l10n_util.h" - -namespace { - -// The max number of fingerprints that can be stored. -constexpr int kMaxAllowedFingerprints = 3; - -// Determines what the newly added fingerprint's name should be. -std::string GetDefaultFingerprintName(int enrolled_finger_count) { - DCHECK(enrolled_finger_count < kMaxAllowedFingerprints); - switch (enrolled_finger_count) { - case 0: - return l10n_util::GetStringUTF8( - IDS_OOBE_FINGERPINT_SETUP_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME_1); - case 1: - return l10n_util::GetStringUTF8( - IDS_OOBE_FINGERPINT_SETUP_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME_2); - case 2: - return l10n_util::GetStringUTF8( - IDS_OOBE_FINGERPINT_SETUP_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME_3); - default: - NOTREACHED(); - } - return std::string(); -} - -} // namespace namespace chromeos { @@ -52,10 +18,6 @@ FingerprintSetupScreenHandler::FingerprintSetupScreenHandler( JSCallsContainer* js_calls_container) : BaseScreenHandler(kScreenId, js_calls_container) { set_user_acted_method_path("login.FingerprintSetupScreen.userActed"); - - content::GetDeviceService().BindFingerprint( - fp_service_.BindNewPipeAndPassReceiver()); - fp_service_->AddFingerprintObserver(receiver_.BindNewPipeAndPassRemote()); } FingerprintSetupScreenHandler::~FingerprintSetupScreenHandler() = default; @@ -104,10 +66,6 @@ void FingerprintSetupScreenHandler::DeclareLocalizedValues( void FingerprintSetupScreenHandler::RegisterMessages() { BaseScreenHandler::RegisterMessages(); - web_ui()->RegisterMessageCallback( - "startEnroll", - base::BindRepeating(&FingerprintSetupScreenHandler::HandleStartEnroll, - base::Unretained(this))); } void FingerprintSetupScreenHandler::Bind(FingerprintSetupScreen* screen) { @@ -119,70 +77,21 @@ void FingerprintSetupScreenHandler::Show() { ShowScreen(kScreenId); } -void FingerprintSetupScreenHandler::Hide() { - // Clean up existing fingerprint enroll session. - if (enroll_session_started_) { - fp_service_->CancelCurrentEnrollSession(base::BindOnce( - &FingerprintSetupScreenHandler::OnCancelCurrentEnrollSession, - weak_ptr_factory_.GetWeakPtr())); - } -} +void FingerprintSetupScreenHandler::Hide() {} void FingerprintSetupScreenHandler::Initialize() {} -void FingerprintSetupScreenHandler::OnRestarted() { - VLOG(1) << "Fingerprint session restarted."; -} - void FingerprintSetupScreenHandler::OnEnrollScanDone( device::mojom::ScanResult scan_result, bool enroll_session_complete, int percent_complete) { - VLOG(1) << "Receive fingerprint enroll scan result. scan_result=" - << scan_result - << ", enroll_session_complete=" << enroll_session_complete - << ", percent_complete=" << percent_complete; CallJS("login.FingerprintSetupScreen.onEnrollScanDone", static_cast<int>(scan_result), enroll_session_complete, percent_complete); - - if (enroll_session_complete) { - enroll_session_started_ = false; - - ++enrolled_finger_count_; - CallJS("login.FingerprintSetupScreen.enableAddAnotherFinger", - enrolled_finger_count_ < kMaxAllowedFingerprints); - - // Update the number of registered fingers, it's fine to override because - // this is the first time user log in and have no finger registered. - ProfileManager::GetActiveUserProfile()->GetPrefs()->SetInteger( - prefs::kQuickUnlockFingerprintRecord, enrolled_finger_count_); - } -} - -void FingerprintSetupScreenHandler::OnAuthScanDone( - device::mojom::ScanResult scan_result, - const base::flat_map<std::string, std::vector<std::string>>& matches) {} - -void FingerprintSetupScreenHandler::OnSessionFailed() { - // TODO(xiaoyinh): Add more user visible information when available. - LOG(ERROR) << "Fingerprint session failed."; -} - -void FingerprintSetupScreenHandler::HandleStartEnroll( - const base::ListValue* args) { - DCHECK(enrolled_finger_count_ < kMaxAllowedFingerprints); - - enroll_session_started_ = true; - fp_service_->StartEnrollSession( - ProfileHelper::Get()->GetUserIdHashFromProfile( - ProfileManager::GetActiveUserProfile()), - GetDefaultFingerprintName(enrolled_finger_count_)); } -void FingerprintSetupScreenHandler::OnCancelCurrentEnrollSession(bool success) { - if (!success) - LOG(ERROR) << "Failed to cancel current fingerprint enroll session."; +void FingerprintSetupScreenHandler::EnableAddAnotherFinger(bool enable) { + CallJS("login.FingerprintSetupScreen.enableAddAnotherFinger", enable); } } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h index 8e752278477..7eef2972b25 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h @@ -7,8 +7,6 @@ #include "base/macros.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" -#include "mojo/public/cpp/bindings/receiver.h" -#include "mojo/public/cpp/bindings/remote.h" #include "services/device/public/mojom/fingerprint.mojom.h" namespace chromeos { @@ -31,13 +29,19 @@ class FingerprintSetupScreenView { // Hides the contents of the screen. virtual void Hide() = 0; + + // Enables adding new finger. + virtual void EnableAddAnotherFinger(bool enable) = 0; + + // Trigger update UI state due to enroll status update. + virtual void OnEnrollScanDone(device::mojom::ScanResult scan_result, + bool enroll_session_complete, + int percent_complete) = 0; }; // The sole implementation of the FingerprintSetupScreenView, using WebUI. -class FingerprintSetupScreenHandler - : public BaseScreenHandler, - public FingerprintSetupScreenView, - public device::mojom::FingerprintObserver { +class FingerprintSetupScreenHandler : public BaseScreenHandler, + public FingerprintSetupScreenView { public: using TView = FingerprintSetupScreenView; @@ -53,36 +57,17 @@ class FingerprintSetupScreenHandler void Bind(FingerprintSetupScreen* screen) override; void Show() override; void Hide() override; - - // BaseScreenHandler: - void Initialize() override; - - // device::mojom::FingerprintObserver: - void OnRestarted() override; + void EnableAddAnotherFinger(bool enable) override; void OnEnrollScanDone(device::mojom::ScanResult scan_result, bool enroll_session_complete, int percent_complete) override; - void OnAuthScanDone( - device::mojom::ScanResult scan_result, - const base::flat_map<std::string, std::vector<std::string>>& matches) - override; - void OnSessionFailed() override; - private: - // JS callbacks. - void HandleStartEnroll(const base::ListValue* args); - - void OnCancelCurrentEnrollSession(bool success); + // BaseScreenHandler: + void Initialize() override; + private: FingerprintSetupScreen* screen_ = nullptr; - mojo::Remote<device::mojom::Fingerprint> fp_service_; - mojo::Receiver<device::mojom::FingerprintObserver> receiver_{this}; - int enrolled_finger_count_ = 0; - bool enroll_session_started_ = false; - - base::WeakPtrFactory<FingerprintSetupScreenHandler> weak_ptr_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(FingerprintSetupScreenHandler); }; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.cc new file mode 100644 index 00000000000..b901c35566a --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.cc @@ -0,0 +1,77 @@ +// Copyright 2020 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/chromeos/login/gaia_password_changed_screen_handler.h" + +#include "base/values.h" +#include "chrome/browser/chromeos/login/oobe_screen.h" +#include "chrome/browser/chromeos/login/screens/gaia_password_changed_screen.h" +#include "chrome/browser/chromeos/login/ui/login_display_host.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "components/login/localized_values_builder.h" +#include "ui/chromeos/devicetype_utils.h" + +namespace chromeos { + +constexpr StaticOobeScreenId GaiaPasswordChangedView::kScreenId; + +GaiaPasswordChangedScreenHandler::GaiaPasswordChangedScreenHandler( + JSCallsContainer* js_calls_container) + : BaseScreenHandler(kScreenId, js_calls_container) { + set_user_acted_method_path("login.GaiaPasswordChangedScreen.userActed"); +} + +GaiaPasswordChangedScreenHandler::~GaiaPasswordChangedScreenHandler() { + if (screen_) + screen_->OnViewDestroyed(this); +} + +void GaiaPasswordChangedScreenHandler::DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) { + builder->Add("nextButtonText", IDS_OFFLINE_LOGIN_NEXT_BUTTON_TEXT); + builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT); + builder->Add("oldPasswordIncorrect", + IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD); + builder->Add("proceedAnywayButton", + IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON); + builder->Add("forgotOldPasswordButtonText", + IDS_LOGIN_PASSWORD_CHANGED_FORGOT_PASSWORD); + builder->AddF("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE, + ui::GetChromeOSDeviceName()); + builder->Add("passwordChangedProceedAnywayTitle", + IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY); + builder->Add("passwordChangedTryAgain", IDS_LOGIN_PASSWORD_CHANGED_TRY_AGAIN); +} + +void GaiaPasswordChangedScreenHandler::Initialize() { + AddCallback("migrateUserData", + &GaiaPasswordChangedScreenHandler::HandleMigrateUserData); +} + +void GaiaPasswordChangedScreenHandler::Show(const std::string& email, + bool has_error) { + base::DictionaryValue data; + data.SetStringPath("email", email); + data.SetBoolPath("showError", has_error); + ShowScreenWithData(kScreenId, &data); +} + +void GaiaPasswordChangedScreenHandler::Bind(GaiaPasswordChangedScreen* screen) { + screen_ = screen; + BaseScreenHandler::SetBaseScreen(screen_); +} + +void GaiaPasswordChangedScreenHandler::Unbind() { + screen_ = nullptr; + BaseScreenHandler::SetBaseScreen(nullptr); +} + +void GaiaPasswordChangedScreenHandler::HandleMigrateUserData( + const std::string& old_password) { + if (screen_) + screen_->MigrateUserData(old_password); +} + +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h new file mode 100644 index 00000000000..3c6d65fb1e7 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h @@ -0,0 +1,64 @@ +// Copyright 2020 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_CHROMEOS_LOGIN_GAIA_PASSWORD_CHANGED_SCREEN_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_GAIA_PASSWORD_CHANGED_SCREEN_HANDLER_H_ + +#include <string> + +#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" + +namespace chromeos { + +class GaiaPasswordChangedScreen; + +// Interface for dependency injection between GaiaPasswordChangedScreen and its +// WebUI representation. +class GaiaPasswordChangedView { + public: + constexpr static StaticOobeScreenId kScreenId{"gaia-password-changed"}; + + virtual ~GaiaPasswordChangedView() {} + + // Shows the contents of the screen. + virtual void Show(const std::string& email, bool has_error) = 0; + + // Binds |screen| to the view. + virtual void Bind(GaiaPasswordChangedScreen* screen) = 0; + + // Unbinds the screen from the view. + virtual void Unbind() = 0; +}; + +class GaiaPasswordChangedScreenHandler : public GaiaPasswordChangedView, + public BaseScreenHandler { + public: + using TView = GaiaPasswordChangedView; + + explicit GaiaPasswordChangedScreenHandler( + JSCallsContainer* js_calls_container); + GaiaPasswordChangedScreenHandler(const GaiaPasswordChangedScreenHandler&) = + delete; + GaiaPasswordChangedScreenHandler& operator=( + const GaiaPasswordChangedScreenHandler&) = delete; + ~GaiaPasswordChangedScreenHandler() override; + + private: + void Show(const std::string& email, bool has_error) override; + void Bind(GaiaPasswordChangedScreen* screen) override; + void Unbind() override; + + void HandleMigrateUserData(const std::string& old_password); + + // BaseScreenHandler: + void DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) override; + void Initialize() override; + + GaiaPasswordChangedScreen* screen_ = nullptr; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_GAIA_PASSWORD_CHANGED_SCREEN_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc index 64879360d33..1babe0f4d85 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc @@ -54,7 +54,6 @@ #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/ash/login_screen_client.h" -#include "chrome/browser/ui/webui/chromeos/login/active_directory_password_change_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h" #include "chrome/browser/ui/webui/metrics_handler.h" @@ -340,14 +339,10 @@ GaiaScreenHandler::GaiaContext::GaiaContext() {} GaiaScreenHandler::GaiaScreenHandler( JSCallsContainer* js_calls_container, CoreOobeView* core_oobe_view, - const scoped_refptr<NetworkStateInformer>& network_state_informer, - ActiveDirectoryPasswordChangeScreenHandler* - active_directory_password_change_screen_handler) + const scoped_refptr<NetworkStateInformer>& network_state_informer) : BaseScreenHandler(kScreenId, js_calls_container), network_state_informer_(network_state_informer), - core_oobe_view_(core_oobe_view), - active_directory_password_change_screen_handler_( - active_directory_password_change_screen_handler) { + core_oobe_view_(core_oobe_view) { DCHECK(network_state_informer_.get()); } @@ -427,7 +422,7 @@ void GaiaScreenHandler::LoadGaiaWithPartition( base::BindOnce(&GaiaScreenHandler::OnSetCookieForLoadGaiaWithPartition, weak_factory_.GetWeakPtr(), context, partition_name); if (context.gaps_cookie.empty()) { - std::move(callback).Run(net::CanonicalCookie::CookieInclusionStatus()); + std::move(callback).Run(net::CookieInclusionStatus()); return; } @@ -465,7 +460,7 @@ void GaiaScreenHandler::LoadGaiaWithPartition( void GaiaScreenHandler::OnSetCookieForLoadGaiaWithPartition( const GaiaContext& context, const std::string& partition_name, - net::CanonicalCookie::CookieInclusionStatus status) { + net::CookieInclusionStatus status) { std::unique_ptr<std::string> version = std::make_unique<std::string>(); std::unique_ptr<bool> consent = std::make_unique<bool>(); base::OnceClosure get_version_and_consent = @@ -858,7 +853,9 @@ void GaiaScreenHandler::DoAdAuth( break; } case authpolicy::ERROR_PASSWORD_EXPIRED: - active_directory_password_change_screen_handler_->ShowScreen(username); + LoginDisplayHost::default_host() + ->GetWizardController() + ->ShowActiveDirectoryPasswordChangeScreen(username); break; case authpolicy::ERROR_PARSE_UPN_FAILED: case authpolicy::ERROR_BAD_USER_NAME: @@ -965,11 +962,11 @@ void GaiaScreenHandler::ContinueAuthenticationWhenCookiesAvailable() { } void GaiaScreenHandler::OnGetCookiesForCompleteAuthentication( - const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies) { + const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies) { std::string auth_code, gaps_cookie; - for (const auto& cookie_with_status : cookies) { - const auto& cookie = cookie_with_status.cookie; + for (const auto& cookie_with_access_result : cookies) { + const auto& cookie = cookie_with_access_result.cookie; if (cookie.Name() == kOAUTHCodeCookie) auth_code = cookie.Value(); else if (cookie.Name() == kGAPSCookie) @@ -1086,8 +1083,6 @@ void GaiaScreenHandler::HandleShowAddUser(const base::ListValue* args) { if (args) args->GetString(0, &email); set_populated_account(AccountId::FromUserEmail(email)); - if (!email.empty()) - SendReauthReason(AccountId::FromUserEmail(email)); OnShowAddUser(); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h index 02c0cce7974..3b00660c72b 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h @@ -23,6 +23,7 @@ #include "components/user_manager/user_type.h" #include "net/base/net_errors.h" #include "net/cookies/canonical_cookie.h" +#include "net/cookies/cookie_inclusion_status.h" #include "services/network/public/mojom/cookie_manager.mojom.h" class AccountId; @@ -38,7 +39,6 @@ class NSSTempCertsCacheChromeOS; namespace chromeos { -class ActiveDirectoryPasswordChangeScreenHandler; class Key; class SamlPasswordAttributes; class SigninScreenHandler; @@ -109,9 +109,7 @@ class GaiaScreenHandler : public BaseScreenHandler, GaiaScreenHandler( JSCallsContainer* js_calls_container, CoreOobeView* core_oobe_view, - const scoped_refptr<NetworkStateInformer>& network_state_informer, - ActiveDirectoryPasswordChangeScreenHandler* - active_directory_password_change_screen_handler); + const scoped_refptr<NetworkStateInformer>& network_state_informer); ~GaiaScreenHandler() override; // GaiaView: @@ -155,10 +153,9 @@ class GaiaScreenHandler : public BaseScreenHandler, const std::string& partition_name); // Called after the GAPS cookie, if present, is added to the cookie store. - void OnSetCookieForLoadGaiaWithPartition( - const GaiaContext& context, - const std::string& partition_name, - net::CanonicalCookie::CookieInclusionStatus status); + void OnSetCookieForLoadGaiaWithPartition(const GaiaContext& context, + const std::string& partition_name, + net::CookieInclusionStatus status); // Callback that loads GAIA after version and stat consent information has // been retrieved. @@ -332,8 +329,8 @@ class GaiaScreenHandler : public BaseScreenHandler, void ContinueAuthenticationWhenCookiesAvailable(); void OnGetCookiesForCompleteAuthentication( - const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies); + const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies); void OnCookieWaitTimeout(); @@ -356,9 +353,6 @@ class GaiaScreenHandler : public BaseScreenHandler, CoreOobeView* core_oobe_view_ = nullptr; - ActiveDirectoryPasswordChangeScreenHandler* - active_directory_password_change_screen_handler_ = nullptr; - // Account to pre-populate with. AccountId populated_account_id_; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/native_window_delegate.h b/chromium/chrome/browser/ui/webui/chromeos/login/native_window_delegate.h deleted file mode 100644 index f7453e022bd..00000000000 --- a/chromium/chrome/browser/ui/webui/chromeos/login/native_window_delegate.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2012 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_CHROMEOS_LOGIN_NATIVE_WINDOW_DELEGATE_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_NATIVE_WINDOW_DELEGATE_H_ - -#include "ui/gfx/native_widget_types.h" - -namespace chromeos { - -// An interface to get gfx::NativeWindow. -class NativeWindowDelegate { - public: - NativeWindowDelegate() {} - virtual ~NativeWindowDelegate() {} - - // Returns corresponding native window. - virtual gfx::NativeWindow GetNativeWindow() const = 0; -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_NATIVE_WINDOW_DELEGATE_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc index 9423ee9eb01..29c58fa4b2a 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc @@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/strings/string_number_conversions.h" -#include "base/task/post_task.h" #include "chrome/browser/ui/ash/ash_util.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -58,8 +57,8 @@ void OobeDisplayChooser::TryToPlaceUiOnTouchDisplay() { display::Screen::GetScreen()->GetPrimaryDisplay(); if (primary_display.is_valid() && !TouchSupportAvailable(primary_display)) { - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&OobeDisplayChooser::MaybeMoveToTouchDisplay, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&OobeDisplayChooser::MaybeMoveToTouchDisplay, weak_ptr_factory_.GetWeakPtr())); } } diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index a8b92fcbf79..414a359c54e 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc @@ -31,6 +31,7 @@ #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_service_factory.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/chromeos/policy/enrollment_requisition_manager.h" #include "chrome/browser/chromeos/settings/shutdown_policy_handler.h" #include "chrome/browser/chromeos/system/input_device_settings.h" #include "chrome/browser/extensions/tab_helper.h" @@ -56,6 +57,7 @@ #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.h" +#include "chrome/browser/ui/webui/chromeos/login/gaia_password_changed_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gesture_navigation_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/hid_detection_screen_handler.h" @@ -74,6 +76,7 @@ #include "chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.h" +#include "chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/update_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/user_board_screen_handler.h" @@ -101,6 +104,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_features.h" #include "ui/base/webui/web_ui_util.h" @@ -192,7 +196,8 @@ void AddAssistantScreensResources(content::WebUIDataSource* source) { IDR_ASSISTANT_VOICE_MATCH_ANIMATION); source->AddResourcePath("voice_match_already_setup_animation.json", IDR_ASSISTANT_VOICE_MATCH_ALREADY_SETUP_ANIMATION); - source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, "worker-src blob: 'self';"); } void AddGestureNavigationResources(content::WebUIDataSource* source) { @@ -202,13 +207,15 @@ void AddGestureNavigationResources(content::WebUIDataSource* source) { IDR_GESTURE_NAVIGATION_GO_BACK_ANIMATION); source->AddResourcePath("gesture_hotseat_overview.json", IDR_GESTURE_NAVIGATION_HOTSEAT_OVERVIEW_ANIMATION); - source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, "worker-src blob: 'self';"); } void AddMarketingOptInResources(content::WebUIDataSource* source) { source->AddResourcePath("all_set.json", IDR_MARKETING_OPT_IN_ALL_SET_ANIMATION); - source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, "worker-src blob: 'self';"); } void AddFingerprintResources(content::WebUIDataSource* source) { @@ -238,7 +245,9 @@ void AddFingerprintResources(content::WebUIDataSource* source) { // lottie animations, this update has to be performed manually. As the usage // increases, set this as the default so manual override is no longer // required. - source->OverrideContentSecurityPolicyWorkerSrc("worker-src blob: 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, + "worker-src blob: 'self';"); } else { source->AddResourcePath("fingerprint_scanner_animation.png", animation_id); } @@ -250,10 +259,12 @@ void AddDebuggerResources(content::WebUIDataSource* source) { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); bool enable_debugger = command_line->HasSwitch(::chromeos::switches::kShowOobeDevOverlay); - // TODO(crbug.com/1073095): Also enable for ChromeOS test images. - // Enable for ChromeOS-on-linux for developers. - bool test_mode = !base::SysInfo::IsRunningOnChromeOS(); - if (enable_debugger && test_mode) { + // Enable for ChromeOS-on-linux for developers and test images. + if (enable_debugger && base::SysInfo::IsRunningOnChromeOS()) { + LOG(WARNING) << "OOBE Debug overlay can only be used on test images"; + base::SysInfo::CrashIfChromeOSNonTestImage(); + } + if (enable_debugger) { source->AddResourcePath(kDebuggerJSPath, IDR_OOBE_DEBUGGER_JS); } else { source->AddResourcePath(kDebuggerJSPath, IDR_OOBE_DEBUGGER_STUB_JS); @@ -325,8 +336,8 @@ content::WebUIDataSource* CreateOobeUIDataSource( AddDebuggerResources(source); source->AddResourcePath(kKeyboardUtilsJSPath, IDR_KEYBOARD_UTILS_JS); - source->OverrideContentSecurityPolicyObjectSrc( - "object-src chrome:;"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ObjectSrc, "object-src chrome:;"); // Only add a filter when runing as test. const bool is_running_test = command_line->HasSwitch(::switches::kTestName) || @@ -348,14 +359,6 @@ std::string GetDisplayType(const GURL& url) { return path; } -bool IsRemoraRequisitioned() { - policy::DeviceCloudPolicyManagerChromeOS* policy_manager = - g_browser_process->platform_part() - ->browser_policy_connector_chromeos() - ->GetDeviceCloudPolicyManager(); - return policy_manager && policy_manager->IsRemoraRequisition(); -} - } // namespace // static @@ -454,13 +457,15 @@ void OobeUI::ConfigureOobeDisplay() { AddScreenHandler( std::make_unique<MarketingOptInScreenHandler>(js_calls_container_.get())); + AddScreenHandler(std::make_unique<GaiaPasswordChangedScreenHandler>( + js_calls_container_.get())); + auto password_change_handler = std::make_unique<ActiveDirectoryPasswordChangeScreenHandler>( js_calls_container_.get(), core_handler_); AddScreenHandler(std::make_unique<GaiaScreenHandler>( - js_calls_container_.get(), core_handler_, network_state_informer_, - password_change_handler.get())); + js_calls_container_.get(), core_handler_, network_state_informer_)); AddScreenHandler(std::move(password_change_handler)); @@ -494,6 +499,9 @@ void OobeUI::ConfigureOobeDisplay() { AddScreenHandler(std::make_unique<PackagedLicenseScreenHandler>( js_calls_container_.get())); + AddScreenHandler( + std::make_unique<TpmErrorScreenHandler>(js_calls_container_.get())); + Profile* profile = Profile::FromWebUI(web_ui()); // Set up the chrome://theme/ source, for Chrome logo. content::URLDataSource::Add(profile, std::make_unique<ThemeSource>(profile)); @@ -514,7 +522,7 @@ void OobeUI::ConfigureOobeDisplay() { content::URLDataSource::Add(profile, std::make_unique<chromeos::VideoSource>()); - if (IsRemoraRequisitioned()) + if (policy::EnrollmentRequisitionManager::IsRemoraRequisition()) oobe_display_chooser_ = std::make_unique<OobeDisplayChooser>(); } @@ -547,7 +555,7 @@ void OobeUI::BindInterface( OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url) : ui::MojoWebUIController(web_ui, true /* enable_chrome_send */) { // TODO(crbug.com/1082670): Remove excessive logging after investigation. - LOG(ERROR) << "Creating new OobeUI"; + LOG(ERROR) << "1082670 : Creating new OobeUI"; display_type_ = GetDisplayType(url); @@ -648,12 +656,12 @@ void OobeUI::AddScreenHandler(std::unique_ptr<BaseScreenHandler> handler) { void OobeUI::InitializeHandlers() { // TODO(crbug.com/1082670): Remove excessive logging after investigation. - LOG(ERROR) << "OobeUI::InitializeHandlers"; + LOG(ERROR) << "1082670 : OobeUI::InitializeHandlers"; js_calls_container_->ExecuteDeferredJSCalls(web_ui()); // TODO(crbug.com/1082670): Remove excessive logging after investigation. - LOG(ERROR) << "OobeUI::Marking as ready and executing callbacks"; + LOG(ERROR) << "1082670 : OobeUI::Marking as ready and executing callbacks"; ready_ = true; for (size_t i = 0; i < ready_callbacks_.size(); ++i) @@ -686,7 +694,8 @@ bool OobeUI::IsScreenInitialized(OobeScreenId screen) { bool OobeUI::IsJSReady(const base::Closure& display_is_ready_callback) { // TODO(crbug.com/1082670): Remove excessive logging after investigation. - LOG(ERROR) << "OobeUI::IsJSReady? = " << ready_; + LOG(ERROR) << "1082670 : OobeUI::IsJSReady? = " << ready_; + if (!ready_) ready_callbacks_.push_back(display_is_ready_callback); return ready_; @@ -699,8 +708,7 @@ void OobeUI::ShowOobeUI(bool show) { oobe_display_chooser_->TryToPlaceUiOnTouchDisplay(); } -void OobeUI::ShowSigninScreen(SigninScreenHandlerDelegate* delegate, - NativeWindowDelegate* native_window_delegate) { +void OobeUI::ShowSigninScreen(SigninScreenHandlerDelegate* delegate) { // Check our device mode. policy::BrowserPolicyConnectorChromeOS* connector = g_browser_process->platform_part()->browser_policy_connector_chromeos(); @@ -712,7 +720,6 @@ void OobeUI::ShowSigninScreen(SigninScreenHandlerDelegate* delegate, } signin_screen_handler_->SetDelegate(delegate); - signin_screen_handler_->SetNativeWindowDelegate(native_window_delegate); signin_screen_handler_->Show(core_handler_->show_oobe_ui()); } @@ -723,7 +730,6 @@ void OobeUI::ForwardAccelerator(std::string accelerator_name) { void OobeUI::ResetSigninScreenHandlerDelegate() { signin_screen_handler_->SetDelegate(nullptr); - signin_screen_handler_->SetNativeWindowDelegate(nullptr); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h index a87658eadf2..676a0c4ab5c 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/oobe_ui.h @@ -29,7 +29,6 @@ class DictionaryValue; namespace chromeos { class ErrorScreen; -class NativeWindowDelegate; class NetworkStateInformer; class OobeDisplayChooser; class SigninScreenHandler; @@ -87,8 +86,7 @@ class OobeUI : public ui::MojoWebUIController { void ShowOobeUI(bool show); // Shows the signin screen. - void ShowSigninScreen(SigninScreenHandlerDelegate* delegate, - NativeWindowDelegate* native_window_delegate); + void ShowSigninScreen(SigninScreenHandlerDelegate* delegate); // Forwards an accelerator to the webui to be handled. void ForwardAccelerator(std::string accelerator_name); diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc index 499ad8e79e8..489d834c216 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/saml_challenge_key_handler.cc @@ -6,6 +6,7 @@ #include "base/base64.h" #include "base/bind.h" +#include "base/logging.h" #include "base/metrics/histogram_functions.h" #include "base/values.h" #include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h" diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc index 98622fce340..0ae35058be3 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.cc @@ -71,7 +71,6 @@ #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/l10n_util.h" -#include "chrome/browser/ui/webui/chromeos/login/native_window_delegate.h" #include "chrome/browser/ui/webui/chromeos/login/network_state_informer.h" #include "chrome/common/channel_info.h" #include "chrome/common/pref_names.h" @@ -159,12 +158,6 @@ class CallOnReturn { DISALLOW_COPY_AND_ASSIGN(CallOnReturn); }; -policy::MinimumVersionPolicyHandler* GetMinimumVersionPolicyHandler() { - return g_browser_process->platform_part() - ->browser_policy_connector_chromeos() - ->GetMinimumVersionPolicyHandler(); -} - } // namespace namespace chromeos { @@ -323,10 +316,6 @@ void SigninScreenHandler::DeclareLocalizedValues( builder->Add("offlineLogin", IDS_OFFLINE_LOGIN_HTML); builder->Add("ownerUserPattern", IDS_LOGIN_POD_OWNER_USER); builder->Add("removeUser", IDS_LOGIN_POD_REMOVE_USER); - builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE); - builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT); - builder->Add("errorTpmFailureRebootButton", - IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON); policy::BrowserPolicyConnectorChromeOS* connector = g_browser_process->platform_part()->browser_policy_connector_chromeos(); @@ -349,20 +338,9 @@ void SigninScreenHandler::DeclareLocalizedValues( builder->Add("multiProfilesOwnerPrimaryOnlyMsg", IDS_MULTI_PROFILES_OWNER_PRIMARY_ONLY_MSG); - // Strings used by password changed dialog. - builder->Add("oldPasswordHint", IDS_LOGIN_PASSWORD_CHANGED_OLD_PASSWORD_HINT); - builder->Add("oldPasswordIncorrect", - IDS_LOGIN_PASSWORD_CHANGED_INCORRECT_OLD_PASSWORD); - builder->Add("proceedAnywayButton", - IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY_BUTTON); + // Used by SAML password dialog. builder->Add("nextButtonText", IDS_OFFLINE_LOGIN_NEXT_BUTTON_TEXT); - builder->Add("forgotOldPasswordButtonText", - IDS_LOGIN_PASSWORD_CHANGED_FORGOT_PASSWORD); - builder->AddF("passwordChangedTitle", IDS_LOGIN_PASSWORD_CHANGED_TITLE, - ui::GetChromeOSDeviceName()); - builder->Add("passwordChangedProceedAnywayTitle", - IDS_LOGIN_PASSWORD_CHANGED_PROCEED_ANYWAY); - builder->Add("passwordChangedTryAgain", IDS_LOGIN_PASSWORD_CHANGED_TRY_AGAIN); + builder->Add("publicAccountInfoFormat", IDS_LOGIN_PUBLIC_ACCOUNT_INFO_FORMAT); builder->Add("publicAccountReminder", IDS_LOGIN_PUBLIC_ACCOUNT_SIGNOUT_REMINDER); @@ -439,7 +417,6 @@ void SigninScreenHandler::RegisterMessages() { &SigninScreenHandler::HandleLaunchSAMLPublicSession); AddRawCallback("offlineLogin", &SigninScreenHandler::HandleOfflineLogin); AddCallback("rebootSystem", &SigninScreenHandler::HandleRebootSystem); - AddCallback("removeUser", &SigninScreenHandler::HandleRemoveUser); AddCallback("toggleEnrollmentScreen", &SigninScreenHandler::HandleToggleEnrollmentScreen); AddCallback("toggleEnableDebuggingScreen", @@ -451,11 +428,7 @@ void SigninScreenHandler::RegisterMessages() { AddCallback("openInternetDetailDialog", &SigninScreenHandler::HandleOpenInternetDetailDialog); AddCallback("loginVisible", &SigninScreenHandler::HandleLoginVisible); - AddCallback("cancelPasswordChangedFlow", - &SigninScreenHandler::HandleCancelPasswordChangedFlow); AddCallback("cancelUserAdding", &SigninScreenHandler::HandleCancelUserAdding); - AddCallback("migrateUserData", &SigninScreenHandler::HandleMigrateUserData); - AddCallback("resyncUserData", &SigninScreenHandler::HandleResyncUserData); AddCallback("loginUIStateChanged", &SigninScreenHandler::HandleLoginUIStateChanged); AddCallback("showLoadingTimeoutError", @@ -492,11 +465,6 @@ void SigninScreenHandler::SetDelegate(SigninScreenHandlerDelegate* delegate) { delegate_->SetWebUIHandler(this); } -void SigninScreenHandler::SetNativeWindowDelegate( - NativeWindowDelegate* native_window_delegate) { - native_window_delegate_ = native_window_delegate; -} - void SigninScreenHandler::OnNetworkReady() { VLOG(1) << "OnNetworkReady() call."; gaia_screen_handler_->MaybePreloadAuthExtension(); @@ -931,26 +899,10 @@ void SigninScreenHandler::ShowError(int login_attempts, help_topic_id); } -void SigninScreenHandler::ShowErrorScreen(LoginDisplay::SigninError error_id) { - switch (error_id) { - case LoginDisplay::TPM_ERROR: - core_oobe_view_->ShowTpmError(); - break; - default: - NOTREACHED() << "Unknown sign in error"; - break; - } -} - void SigninScreenHandler::ShowSigninUI(const std::string& email) { core_oobe_view_->ShowSignInUI(email); } -void SigninScreenHandler::ShowPasswordChangedDialog(bool show_password_error, - const std::string& email) { - core_oobe_view_->ShowPasswordChangedScreen(show_password_error, email); -} - void SigninScreenHandler::ShowWhitelistCheckFailedError() { gaia_screen_handler_->ShowWhitelistCheckFailedError(); } @@ -1138,20 +1090,6 @@ void SigninScreenHandler::HandleRebootSystem() { power_manager::REQUEST_RESTART_FOR_USER, "WebUI signin screen"); } -void SigninScreenHandler::HandleRemoveUser(const AccountId& account_id) { - if (delegate_ && - (delegate_->IsUserSigninCompleted() || delegate_->IsSigninInProgress())) { - return; - } - - ProfileMetrics::LogProfileDeleteUser( - ProfileMetrics::DELETE_PROFILE_USER_MANAGER); - - if (!delegate_) - return; - delegate_->RemoveUser(account_id); -} - void SigninScreenHandler::HandleToggleEnrollmentScreen() { if (delegate_) delegate_->ShowEnterpriseEnrollmentScreen(); @@ -1201,12 +1139,6 @@ void SigninScreenHandler::HandleAccountPickerReady() { return; } - if (delegate_ && !oobe_ui_ && GetMinimumVersionPolicyHandler() && - !GetMinimumVersionPolicyHandler()->RequirementsAreSatisfied()) { - delegate_->ShowUpdateRequiredScreen(); - return; - } - is_account_picker_showing_first_time_ = true; // The wallpaper may have been set before the instance is initialized, so make @@ -1250,32 +1182,11 @@ void SigninScreenHandler::HandleLoginVisible(const std::string& source) { OnPreferencesChanged(); } -void SigninScreenHandler::HandleCancelPasswordChangedFlow( - const AccountId& account_id) { - if (account_id.is_valid()) { - RecordReauthReason(account_id, ReauthReason::PASSWORD_UPDATE_SKIPPED); - } - gaia_screen_handler_->StartClearingCookies( - base::Bind(&SigninScreenHandler::CancelPasswordChangedFlowInternal, - weak_factory_.GetWeakPtr())); -} - void SigninScreenHandler::HandleCancelUserAdding() { if (delegate_) delegate_->CancelUserAdding(); } -void SigninScreenHandler::HandleMigrateUserData( - const std::string& old_password) { - if (LoginDisplayHost::default_host()) - LoginDisplayHost::default_host()->MigrateUserData(old_password); -} - -void SigninScreenHandler::HandleResyncUserData() { - if (LoginDisplayHost::default_host()) - LoginDisplayHost::default_host()->ResyncUserData(); -} - void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source, bool active) { VLOG(0) << "Login WebUI >> active: " << active << ", " @@ -1432,14 +1343,6 @@ bool SigninScreenHandler::AllWhitelistedUsersPresent() { return true; } -void SigninScreenHandler::CancelPasswordChangedFlowInternal() { - if (delegate_) - ShowImpl(); - - if (LoginDisplayHost::default_host()) - LoginDisplayHost::default_host()->CancelPasswordChangedFlow(); -} - bool SigninScreenHandler::IsGaiaVisible() const { return IsSigninScreen(GetCurrentScreen()) && ui_state_ == UI_STATE_GAIA_SIGNIN; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h index fd1bcb346e3..f250227407b 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/signin_screen_handler.h @@ -55,7 +55,6 @@ class CoreOobeView; class ErrorScreensHistogramHelper; class GaiaScreenHandler; class LoginFeedback; -class NativeWindowDelegate; class User; class UserContext; @@ -73,10 +72,7 @@ class LoginDisplayWebUIHandler { const std::string& error_text, const std::string& help_link_text, HelpAppLauncher::HelpTopic help_topic_id) = 0; - virtual void ShowErrorScreen(LoginDisplay::SigninError error_id) = 0; virtual void ShowSigninUI(const std::string& email) = 0; - virtual void ShowPasswordChangedDialog(bool show_password_error, - const std::string& email) = 0; virtual void ShowWhitelistCheckFailedError() = 0; virtual void LoadUsers(const user_manager::UserList& users, const base::ListValue& users_list) = 0; @@ -119,16 +115,10 @@ class SigninScreenHandlerDelegate { // Show wrong hwid screen. virtual void ShowWrongHWIDScreen() = 0; - // Show update required screen. - virtual void ShowUpdateRequiredScreen() = 0; - // --------------- Rest of the methods. // Cancels user adding. virtual void CancelUserAdding() = 0; - // Attempts to remove given user. - virtual void RemoveUser(const AccountId& account_id) = 0; - // Let the delegate know about the handler it is supposed to be using. virtual void SetWebUIHandler(LoginDisplayWebUIHandler* webui_handler) = 0; @@ -197,8 +187,6 @@ class SigninScreenHandler // delegate is set before Show() method will be called. void SetDelegate(SigninScreenHandlerDelegate* delegate); - void SetNativeWindowDelegate(NativeWindowDelegate* native_window_delegate); - // NetworkStateInformer::NetworkStateInformerObserver implementation: void OnNetworkReady() override; void UpdateState(NetworkError::ErrorReason reason) override; @@ -272,9 +260,6 @@ class SigninScreenHandler const std::string& help_link_text, HelpAppLauncher::HelpTopic help_topic_id) override; void ShowSigninUI(const std::string& email) override; - void ShowPasswordChangedDialog(bool show_password_error, - const std::string& email) override; - void ShowErrorScreen(LoginDisplay::SigninError error_id) override; void ShowWhitelistCheckFailedError() override; void LoadUsers(const user_manager::UserList& users, const base::ListValue& users_list) override; @@ -318,7 +303,6 @@ class SigninScreenHandler const std::string& input_method); void HandleOfflineLogin(const base::ListValue* args); void HandleRebootSystem(); - void HandleRemoveUser(const AccountId& account_id); void HandleToggleEnrollmentScreen(); void HandleToggleEnrollmentAd(); void HandleToggleEnableDebuggingScreen(); @@ -334,10 +318,7 @@ class SigninScreenHandler void HandleAccountPickerReady(); void HandleOpenInternetDetailDialog(); void HandleLoginVisible(const std::string& source); - void HandleCancelPasswordChangedFlow(const AccountId& account_id); void HandleCancelUserAdding(); - void HandleMigrateUserData(const std::string& password); - void HandleResyncUserData(); void HandleLoginUIStateChanged(const std::string& source, bool active); void HandleLoginScreenUpdate(); void HandleShowLoadingTimeoutError(); @@ -409,9 +390,6 @@ class SigninScreenHandler // A delegate that glues this handler with backend LoginDisplay. SigninScreenHandlerDelegate* delegate_ = nullptr; - // A delegate used to get gfx::NativeWindow. - NativeWindowDelegate* native_window_delegate_ = nullptr; - // Whether screen should be shown right after initialization. bool show_on_init_ = false; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc index 311bd578880..7d212337687 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.cc @@ -13,6 +13,7 @@ #include "chrome/browser/chromeos/arc/session/arc_session_manager.h" #include "chrome/browser/chromeos/login/oobe_screen.h" #include "chrome/browser/chromeos/login/screens/supervision_transition_screen.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/login_screen_client.h" #include "chrome/browser/ui/ash/system_tray_client.h" @@ -90,7 +91,10 @@ void SupervisionTransitionScreenHandler::Show() { &SupervisionTransitionScreenHandler::OnSupervisionTransitionFailed, weak_factory_.GetWeakPtr())); - registrar_.Init(profile_->GetPrefs()); + Profile* profile = ProfileManager::GetActiveUserProfile(); + DCHECK(!ProfileHelper::IsSigninProfile(profile)); + + registrar_.Init(profile->GetPrefs()); registrar_.Add( arc::prefs::kArcSupervisionTransition, base::BindRepeating( @@ -106,7 +110,7 @@ void SupervisionTransitionScreenHandler::Show() { base::DictionaryValue data; data.SetBoolean("isRemovingSupervision", - arc::GetSupervisionTransition(profile_) == + arc::GetSupervisionTransition(profile) == arc::ArcSupervisionTransition::CHILD_TO_REGULAR); ShowScreenWithData(kScreenId, &data); } @@ -118,8 +122,6 @@ base::OneShotTimer* SupervisionTransitionScreenHandler::GetTimerForTesting() { } void SupervisionTransitionScreenHandler::Initialize() { - profile_ = ProfileManager::GetPrimaryUserProfile(); - if (!screen_ || !show_on_init_) return; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h index 5785e0e65fc..76d085f82d7 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/supervision_transition_screen_handler.h @@ -82,9 +82,6 @@ class SupervisionTransitionScreenHandler base::TimeTicks screen_shown_time_; - // The primary user profile. - Profile* profile_ = nullptr; - // Timer used to exit the page when timeout reaches. base::OneShotTimer timer_; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc index 2e83bfb9b3d..a7bdc97a447 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc @@ -13,6 +13,7 @@ #include "components/login/localized_values_builder.h" #include "components/user_manager/user_manager.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/chromeos/devicetype_utils.h" namespace { @@ -111,6 +112,8 @@ void SyncConsentScreenHandler::DeclareLocalizedValues( builder); // SplitSettingsSync strings. + RememberLocalizedValue("syncConsentScreenSubtitle", + IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE, builder); RememberLocalizedValue("syncConsentScreenOsSyncName", IDS_LOGIN_SYNC_CONSENT_SCREEN_OS_SYNC_NAME, builder); RememberLocalizedValue("syncConsentScreenOsSyncDescription", @@ -119,6 +122,10 @@ void SyncConsentScreenHandler::DeclareLocalizedValues( RememberLocalizedValue("syncConsentScreenChromeBrowserSyncName", IDS_LOGIN_SYNC_CONSENT_SCREEN_CHROME_BROWSER_SYNC_NAME, builder); + RememberLocalizedValue("syncConsentScreenAccept", + IDS_LOGIN_SYNC_CONSENT_SCREEN_ACCEPT2, builder); + RememberLocalizedValue("syncConsentScreenDecline", + IDS_LOGIN_SYNC_CONSENT_SCREEN_DECLINE2, builder); } void SyncConsentScreenHandler::Bind(SyncConsentScreen* screen) { @@ -127,10 +134,10 @@ void SyncConsentScreenHandler::Bind(SyncConsentScreen* screen) { } void SyncConsentScreenHandler::Show() { - bool is_child_account_ = - user_manager::UserManager::Get()->IsLoggedInAsChildUser(); + auto* user_manager = user_manager::UserManager::Get(); base::DictionaryValue data; - data.SetBoolean("isChildAccount", is_child_account_); + data.SetBoolean("isChildAccount", user_manager->IsLoggedInAsChildUser()); + data.SetString("deviceType", ui::GetChromeOSDeviceName()); ShowScreenWithData(kScreenId, &data); } @@ -149,6 +156,8 @@ void SyncConsentScreenHandler::RegisterMessages() { &SyncConsentScreenHandler::HandleContinueWithDefaults); AddCallback("login.SyncConsentScreen.acceptAndContinue", &SyncConsentScreenHandler::HandleAcceptAndContinue); + AddCallback("login.SyncConsentScreen.declineAndContinue", + &SyncConsentScreenHandler::HandleDeclineAndContinue); } void SyncConsentScreenHandler::GetAdditionalParameters( @@ -198,16 +207,26 @@ void SyncConsentScreenHandler::HandleContinueWithDefaults( void SyncConsentScreenHandler::HandleAcceptAndContinue( const login::StringList& consent_description, + const std::string& consent_confirmation) { + Continue(consent_description, consent_confirmation, UserChoice::kAccepted); +} + +void SyncConsentScreenHandler::HandleDeclineAndContinue( + const login::StringList& consent_description, + const std::string& consent_confirmation) { + Continue(consent_description, consent_confirmation, UserChoice::kDeclined); +} + +void SyncConsentScreenHandler::Continue( + const login::StringList& consent_description, const std::string& consent_confirmation, - bool enable_os_sync, - bool enable_browser_sync) { + UserChoice choice) { DCHECK(chromeos::features::IsSplitSettingsSyncEnabled()); std::vector<int> consent_description_ids; int consent_confirmation_id; GetConsentIDs(known_string_ids_, consent_description, consent_confirmation, &consent_description_ids, &consent_confirmation_id); - screen_->OnAcceptAndContinue(consent_description_ids, consent_confirmation_id, - enable_os_sync, enable_browser_sync); + screen_->OnContinue(consent_description_ids, consent_confirmation_id, choice); SyncConsentScreen::SyncConsentScreenTestDelegate* test_delegate = screen_->GetDelegateForTesting(); diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h index af58bff845a..a11e554f091 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h @@ -42,6 +42,10 @@ class SyncConsentScreenHandler : public BaseScreenHandler, public: using TView = SyncConsentScreenView; + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. Public for testing. + enum class UserChoice { kDeclined = 0, kAccepted = 1, kMaxValue = kAccepted }; + explicit SyncConsentScreenHandler(JSCallsContainer* js_calls_container); ~SyncConsentScreenHandler() override; @@ -67,10 +71,17 @@ class SyncConsentScreenHandler : public BaseScreenHandler, void HandleContinueWithDefaults( const ::login::StringList& consent_description, const std::string& consent_confirmation); + + // WebUI message handlers for SplitSettingsSync. void HandleAcceptAndContinue(const ::login::StringList& consent_description, - const std::string& consent_confirmation, - bool enable_os_sync, - bool enable_browser_sync); + const std::string& consent_confirmation); + void HandleDeclineAndContinue(const ::login::StringList& consent_description, + const std::string& consent_confirmation); + + // Helper for the accept and decline cases. + void Continue(const ::login::StringList& consent_description, + const std::string& consent_confirmation, + UserChoice choice); // Adds resource |resource_id| both to |builder| and to |known_string_ids_|. void RememberLocalizedValue(const std::string& name, diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc index 241a06360c0..873c6a473fc 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/terms_of_service_screen_handler.cc @@ -63,6 +63,8 @@ void TermsOfServiceScreenHandler::DeclareLocalizedValues( IDS_TERMS_OF_SERVICE_SCREEN_BACK_BUTTON); builder->Add("termsOfServiceAcceptButton", IDS_TERMS_OF_SERVICE_SCREEN_ACCEPT_BUTTON); + builder->Add("termsOfServiceRetryButton", + IDS_TERMS_OF_SERVICE_SCREEN_RETRY_BUTTON); } void TermsOfServiceScreenHandler::SetScreen(TermsOfServiceScreen* screen) { diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.cc new file mode 100644 index 00000000000..16f1e686924 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.cc @@ -0,0 +1,62 @@ +// Copyright 2020 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/chromeos/login/tpm_error_screen_handler.h" + +#include "base/values.h" +#include "chrome/browser/chromeos/login/oobe_screen.h" +#include "chrome/browser/chromeos/login/screens/tpm_error_screen.h" +#include "chrome/grit/chromium_strings.h" +#include "chrome/grit/generated_resources.h" +#include "components/login/localized_values_builder.h" + +namespace chromeos { + +constexpr StaticOobeScreenId TpmErrorView::kScreenId; + +TpmErrorScreenHandler::TpmErrorScreenHandler( + JSCallsContainer* js_calls_container) + : BaseScreenHandler(kScreenId, js_calls_container) { + set_user_acted_method_path("login.TPMErrorMessageScreen.userActed"); +} + +TpmErrorScreenHandler::~TpmErrorScreenHandler() { + if (screen_) + screen_->OnViewDestroyed(this); +} + +void TpmErrorScreenHandler::DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) { + builder->Add("errorTpmFailureTitle", IDS_LOGIN_ERROR_TPM_FAILURE_TITLE); + builder->Add("errorTpmFailureReboot", IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT); + builder->Add("errorTpmFailureRebootButton", + IDS_LOGIN_ERROR_TPM_FAILURE_REBOOT_BUTTON); +} + +void TpmErrorScreenHandler::Initialize() { + if (show_on_init_) { + show_on_init_ = false; + Show(); + } +} + +void TpmErrorScreenHandler::Show() { + if (!page_is_ready()) { + show_on_init_ = true; + return; + } + ShowScreen(kScreenId); +} + +void TpmErrorScreenHandler::Bind(TpmErrorScreen* screen) { + screen_ = screen; + BaseScreenHandler::SetBaseScreen(screen_); +} + +void TpmErrorScreenHandler::Unbind() { + screen_ = nullptr; + BaseScreenHandler::SetBaseScreen(nullptr); +} + +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h new file mode 100644 index 00000000000..a8258774ae7 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/login/tpm_error_screen_handler.h @@ -0,0 +1,60 @@ +// Copyright 2020 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_CHROMEOS_LOGIN_TPM_ERROR_SCREEN_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_TPM_ERROR_SCREEN_HANDLER_H_ + +#include <string> + +#include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" + +namespace chromeos { + +class TpmErrorScreen; + +// Interface for dependency injection between TpmErrorScreen and its +// WebUI representation. +class TpmErrorView { + public: + constexpr static StaticOobeScreenId kScreenId{"tpm-error-message"}; + + virtual ~TpmErrorView() {} + + // Shows the contents of the screen. + virtual void Show() = 0; + + // Binds |screen| to the view. + virtual void Bind(TpmErrorScreen* screen) = 0; + + // Unbinds the screen from the view. + virtual void Unbind() = 0; +}; + +class TpmErrorScreenHandler : public TpmErrorView, public BaseScreenHandler { + public: + using TView = TpmErrorView; + + explicit TpmErrorScreenHandler(JSCallsContainer* js_calls_container); + TpmErrorScreenHandler(const TpmErrorScreenHandler&) = delete; + TpmErrorScreenHandler& operator=(const TpmErrorScreenHandler&) = delete; + ~TpmErrorScreenHandler() override; + + private: + void Show() override; + void Bind(TpmErrorScreen* screen) override; + void Unbind() override; + + // BaseScreenHandler: + void DeclareLocalizedValues( + ::login::LocalizedValuesBuilder* builder) override; + void Initialize() override; + + bool show_on_init_ = false; + + TpmErrorScreen* screen_ = nullptr; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_TPM_ERROR_SCREEN_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc index d938229bbd9..1ba28b56d11 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.cc @@ -65,6 +65,7 @@ void UpdateRequiredScreenHandler::DeclareLocalizedValues( IDS_OFFERS_CONSENT_INFOBAR_DISABLE_BUTTON); builder->Add("noNetworkMessage", IDS_UPDATE_REQUIRED_SCREEN_NO_NETWORK_MESSAGE); + builder->Add("eolAdminMessageTitle", IDS_UPDATE_REQUIRED_EOL_ADMIN_MESSAGE); } void UpdateRequiredScreenHandler::Initialize() { @@ -81,6 +82,10 @@ void UpdateRequiredScreenHandler::SetEnterpriseAndDeviceName( enterpriseDomain, deviceName); } +void UpdateRequiredScreenHandler::SetEolMessage(const std::string& eolMessage) { + CallJS("login.UpdateRequiredScreen.setEolMessage", eolMessage); +} + void UpdateRequiredScreenHandler::Show() { if (!page_is_ready()) { show_on_init_ = true; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h index 48bffc48e60..6c01540cd95 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/update_required_screen_handler.h @@ -65,6 +65,7 @@ class UpdateRequiredView { // Set enterprise and device name to be used in strings in the UI. virtual void SetEnterpriseAndDeviceName(const std::string& enterpriseDomain, const base::string16& deviceName) = 0; + virtual void SetEolMessage(const std::string& eolMessage) = 0; }; class UpdateRequiredScreenHandler : public UpdateRequiredView, @@ -90,6 +91,7 @@ class UpdateRequiredScreenHandler : public UpdateRequiredView, void SetUIState(UpdateRequiredView::UIState ui_state) override; void SetEnterpriseAndDeviceName(const std::string& enterpriseDomain, const base::string16& deviceName) override; + void SetEolMessage(const std::string& eolMessage) override; // BaseScreenHandler: void DeclareLocalizedValues( diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h index be45877d228..7f2b3630ab0 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h @@ -19,7 +19,7 @@ class UpdateScreen; // representation. Owned by UpdateScreen. class UpdateView { public: - constexpr static StaticOobeScreenId kScreenId{"update"}; + constexpr static StaticOobeScreenId kScreenId{"oobe-update"}; virtual ~UpdateView() {} diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc index cf6cf3e7cf3..38efaf95f19 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc @@ -15,6 +15,8 @@ #include "base/task_runner_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" +#include "chrome/browser/chromeos/accessibility/magnification_manager.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/screens/welcome_screen.h" #include "chrome/browser/chromeos/login/ui/input_events_blocker.h" @@ -47,6 +49,12 @@ WelcomeScreenHandler::WelcomeScreenHandler(JSCallsContainer* js_calls_container, core_oobe_view_(core_oobe_view) { set_user_acted_method_path("login.WelcomeScreen.userActed"); DCHECK(core_oobe_view_); + + AccessibilityManager* accessibility_manager = AccessibilityManager::Get(); + CHECK(accessibility_manager); + accessibility_subscription_ = accessibility_manager->RegisterCallback( + base::Bind(&WelcomeScreenHandler::OnAccessibilityStatusChanged, + base::Unretained(this))); } WelcomeScreenHandler::~WelcomeScreenHandler() { @@ -145,6 +153,17 @@ void WelcomeScreenHandler::DeclareLocalizedValues( builder->Add("keyboardDropdownTitle", IDS_KEYBOARD_DROPDOWN_TITLE); builder->Add("keyboardDropdownLabel", IDS_KEYBOARD_DROPDOWN_LABEL); + // OOBE accessibility options menu strings shown on each screen. + builder->Add("accessibilityLink", IDS_OOBE_ACCESSIBILITY_LINK); + builder->Add("spokenFeedbackOption", IDS_OOBE_SPOKEN_FEEDBACK_OPTION); + builder->Add("selectToSpeakOption", IDS_OOBE_SELECT_TO_SPEAK_OPTION); + builder->Add("largeCursorOption", IDS_OOBE_LARGE_CURSOR_OPTION); + builder->Add("highContrastOption", IDS_OOBE_HIGH_CONTRAST_MODE_OPTION); + builder->Add("screenMagnifierOption", IDS_OOBE_SCREEN_MAGNIFIER_OPTION); + builder->Add("dockedMagnifierOption", IDS_OOBE_DOCKED_MAGNIFIER_OPTION); + builder->Add("virtualKeyboardOption", IDS_OOBE_VIRTUAL_KEYBOARD_OPTION); + builder->Add("closeAccessibilityMenu", IDS_OOBE_CLOSE_ACCESSIBILITY_MENU); + builder->Add("a11ySettingToggleOptionOff", IDS_A11Y_SETTING_TOGGLE_OPTION_OFF); builder->Add("a11ySettingToggleOptionOn", IDS_A11Y_SETTING_TOGGLE_OPTION_ON); @@ -162,6 +181,21 @@ void WelcomeScreenHandler::DeclareJSCallbacks() { &WelcomeScreenHandler::HandleSetInputMethodId); AddCallback("WelcomeScreen.setTimezoneId", &WelcomeScreenHandler::HandleSetTimezoneId); + + AddCallback("WelcomeScreen.enableHighContrast", + &WelcomeScreenHandler::HandleEnableHighContrast); + AddCallback("WelcomeScreen.enableLargeCursor", + &WelcomeScreenHandler::HandleEnableLargeCursor); + AddCallback("WelcomeScreen.enableVirtualKeyboard", + &WelcomeScreenHandler::HandleEnableVirtualKeyboard); + AddCallback("WelcomeScreen.enableScreenMagnifier", + &WelcomeScreenHandler::HandleEnableScreenMagnifier); + AddCallback("WelcomeScreen.enableSpokenFeedback", + &WelcomeScreenHandler::HandleEnableSpokenFeedback); + AddCallback("WelcomeScreen.enableSelectToSpeak", + &WelcomeScreenHandler::HandleEnableSelectToSpeak); + AddCallback("WelcomeScreen.enableDockedMagnifier", + &WelcomeScreenHandler::HandleEnableDockedMagnifier); } void WelcomeScreenHandler::GetAdditionalParameters( @@ -227,8 +261,11 @@ void WelcomeScreenHandler::Initialize() { // Reload localized strings if they are already resolved. if (screen_ && screen_->language_list()) ReloadLocalizedContent(); + UpdateA11yState(); } +// WelcomeScreenHandler, private: ---------------------------------------------- + void WelcomeScreenHandler::HandleSetLocaleId(const std::string& locale_id) { if (screen_) screen_->SetApplicationLocale(locale_id); @@ -245,7 +282,71 @@ void WelcomeScreenHandler::HandleSetTimezoneId(const std::string& timezone_id) { screen_->SetTimezone(timezone_id); } -// WelcomeScreenHandler, private: ---------------------------------------------- +void WelcomeScreenHandler::HandleEnableHighContrast(bool enabled) { + AccessibilityManager::Get()->EnableHighContrast(enabled); +} + +void WelcomeScreenHandler::HandleEnableLargeCursor(bool enabled) { + AccessibilityManager::Get()->EnableLargeCursor(enabled); +} + +void WelcomeScreenHandler::HandleEnableVirtualKeyboard(bool enabled) { + AccessibilityManager::Get()->EnableVirtualKeyboard(enabled); +} + +void WelcomeScreenHandler::HandleEnableScreenMagnifier(bool enabled) { + DCHECK(MagnificationManager::Get()); + MagnificationManager::Get()->SetMagnifierEnabled(enabled); +} + +void WelcomeScreenHandler::HandleEnableSpokenFeedback(bool /* enabled */) { + // Checkbox is initialized on page init and updates when spoken feedback + // setting is changed so just toggle spoken feedback here. + AccessibilityManager::Get()->EnableSpokenFeedback( + !AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); +} + +void WelcomeScreenHandler::HandleEnableSelectToSpeak(bool /* enabled */) { + // Checkbox is initialized on page init and updates when Select to Speak + // setting is changed so just toggle Select to Speak here. + AccessibilityManager::Get()->SetSelectToSpeakEnabled( + !AccessibilityManager::Get()->IsSelectToSpeakEnabled()); +} + +void WelcomeScreenHandler::HandleEnableDockedMagnifier(bool enabled) { + // Checkbox is initialized on page init and updates when the docked magnifier + // setting is changed so just toggle Select to Speak here. + DCHECK(MagnificationManager::Get()); + MagnificationManager::Get()->SetDockedMagnifierEnabled(enabled); +} + +void WelcomeScreenHandler::OnAccessibilityStatusChanged( + const AccessibilityStatusEventDetails& details) { + if (details.notification_type == ACCESSIBILITY_MANAGER_SHUTDOWN) + accessibility_subscription_.reset(); + else + UpdateA11yState(); +} + +void WelcomeScreenHandler::UpdateA11yState() { + base::DictionaryValue a11y_info; + a11y_info.SetBoolean("highContrastEnabled", + AccessibilityManager::Get()->IsHighContrastEnabled()); + a11y_info.SetBoolean("largeCursorEnabled", + AccessibilityManager::Get()->IsLargeCursorEnabled()); + a11y_info.SetBoolean("spokenFeedbackEnabled", + AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); + a11y_info.SetBoolean("selectToSpeakEnabled", + AccessibilityManager::Get()->IsSelectToSpeakEnabled()); + DCHECK(MagnificationManager::Get()); + a11y_info.SetBoolean("screenMagnifierEnabled", + MagnificationManager::Get()->IsMagnifierEnabled()); + a11y_info.SetBoolean("dockedMagnifierEnabled", + MagnificationManager::Get()->IsDockedMagnifierEnabled()); + a11y_info.SetBoolean("virtualKeyboardEnabled", + AccessibilityManager::Get()->IsVirtualKeyboardEnabled()); + CallJS("login.WelcomeScreen.refreshA11yInfo", a11y_info); +} // static std::unique_ptr<base::ListValue> WelcomeScreenHandler::GetTimezoneList() { diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h index 437027ab74a..6f7a19e6b12 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h @@ -9,6 +9,7 @@ #include <string> #include "base/macros.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/ui/webui/chromeos/login/base_screen_handler.h" namespace base { @@ -80,6 +81,20 @@ class WelcomeScreenHandler : public WelcomeView, public BaseScreenHandler { void HandleSetLocaleId(const std::string& locale_id); void HandleSetInputMethodId(const std::string& input_method_id); void HandleSetTimezoneId(const std::string& timezone_id); + void HandleEnableLargeCursor(bool enabled); + void HandleEnableHighContrast(bool enabled); + void HandleEnableVirtualKeyboard(bool enabled); + void HandleEnableScreenMagnifier(bool enabled); + void HandleEnableSpokenFeedback(bool /* enabled */); + void HandleEnableSelectToSpeak(bool /* enabled */); + void HandleEnableDockedMagnifier(bool /* enabled */); + + // Notification of a change in the accessibility settings. + void OnAccessibilityStatusChanged( + const AccessibilityStatusEventDetails& details); + + // Updates a11y menu state based on the current a11y features state(on/off). + void UpdateA11yState(); // Returns available timezones. Caller gets the ownership. static std::unique_ptr<base::ListValue> GetTimezoneList(); @@ -90,6 +105,8 @@ class WelcomeScreenHandler : public WelcomeView, public BaseScreenHandler { // Keeps whether screen should be shown right after initialization. bool show_on_init_ = false; + std::unique_ptr<AccessibilityStatusSubscription> accessibility_subscription_; + DISALLOW_COPY_AND_ASSIGN(WelcomeScreenHandler); }; diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.cc index e1b8a87d274..22167c3d0b2 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.cc @@ -16,11 +16,12 @@ constexpr StaticOobeScreenId WrongHWIDScreenView::kScreenId; WrongHWIDScreenHandler::WrongHWIDScreenHandler( JSCallsContainer* js_calls_container) : BaseScreenHandler(kScreenId, js_calls_container) { + set_user_acted_method_path("login.WrongHWIDMessageScreen.userActed"); } WrongHWIDScreenHandler::~WrongHWIDScreenHandler() { - if (delegate_) - delegate_->OnViewDestroyed(this); + if (screen_) + screen_->OnViewDestroyed(this); } void WrongHWIDScreenHandler::Show() { @@ -34,10 +35,14 @@ void WrongHWIDScreenHandler::Show() { void WrongHWIDScreenHandler::Hide() { } -void WrongHWIDScreenHandler::SetDelegate(WrongHWIDScreen* delegate) { - delegate_ = delegate; - if (page_is_ready()) - Initialize(); +void WrongHWIDScreenHandler::Bind(WrongHWIDScreen* screen) { + screen_ = screen; + BaseScreenHandler::SetBaseScreen(screen_); +} + +void WrongHWIDScreenHandler::Unbind() { + screen_ = nullptr; + BaseScreenHandler::SetBaseScreen(nullptr); } void WrongHWIDScreenHandler::DeclareLocalizedValues( @@ -52,22 +57,10 @@ void WrongHWIDScreenHandler::DeclareLocalizedValues( } void WrongHWIDScreenHandler::Initialize() { - if (!page_is_ready() || !delegate_) - return; - if (show_on_init_) { - Show(); show_on_init_ = false; + Show(); } } -void WrongHWIDScreenHandler::RegisterMessages() { - AddCallback("wrongHWIDOnSkip", &WrongHWIDScreenHandler::HandleOnSkip); -} - -void WrongHWIDScreenHandler::HandleOnSkip() { - if (delegate_) - delegate_->OnExit(); -} - } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h b/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h index c66ca8105d5..09a9b3456b5 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h +++ b/chromium/chrome/browser/ui/webui/chromeos/login/wrong_hwid_screen_handler.h @@ -23,7 +23,12 @@ class WrongHWIDScreenView { virtual void Show() = 0; virtual void Hide() = 0; - virtual void SetDelegate(WrongHWIDScreen* delegate) = 0; + + // Binds |screen| to the view. + virtual void Bind(WrongHWIDScreen* screen) = 0; + + // Unbinds the screen from the view. + virtual void Unbind() = 0; }; // WebUI implementation of WrongHWIDScreenActor. @@ -35,24 +40,19 @@ class WrongHWIDScreenHandler : public WrongHWIDScreenView, explicit WrongHWIDScreenHandler(JSCallsContainer* js_calls_container); ~WrongHWIDScreenHandler() override; + private: // WrongHWIDScreenActor implementation: void Show() override; void Hide() override; - void SetDelegate(WrongHWIDScreen* delegate) override; + void Bind(WrongHWIDScreen* screen) override; + void Unbind() override; // BaseScreenHandler implementation: void DeclareLocalizedValues( ::login::LocalizedValuesBuilder* builder) override; void Initialize() override; - // WebUIMessageHandler implementation: - void RegisterMessages() override; - - private: - // JS messages handlers. - void HandleOnSkip(); - - WrongHWIDScreen* delegate_ = nullptr; + WrongHWIDScreen* screen_ = nullptr; // Keeps whether screen should be shown right after initialization. bool show_on_init_ = false; @@ -63,4 +63,3 @@ class WrongHWIDScreenHandler : public WrongHWIDScreenView, } // namespace chromeos #endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_WRONG_HWID_SCREEN_HANDLER_H_ - diff --git a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc index ace92dd56d2..b84b0101053 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/machine_learning/machine_learning_internals_ui.cc @@ -22,32 +22,45 @@ MachineLearningInternalsUI::MachineLearningInternalsUI( content::WebUIDataSource* const source = content::WebUIDataSource::Create( chrome::kChromeUIMachineLearningInternalsHost); - source->AddResourcePath( - "chromeos/services/machine_learning/public/mojom/tensor.mojom-lite.js", - IDR_MACHINE_LEARNING_INTERNALS_TENSOR_MOJO_JS); - source->AddResourcePath( - "chromeos/services/machine_learning/public/mojom/model.mojom-lite.js", - IDR_MACHINE_LEARNING_INTERNALS_MODEL_MOJO_JS); - source->AddResourcePath( - "chromeos/services/machine_learning/public/mojom/" - "graph_executor.mojom-lite.js", - IDR_MACHINE_LEARNING_INTERNALS_GRAPH_EXECUTOR_MOJO_JS); - source->AddResourcePath( - "chromeos/services/machine_learning/public/" - "mojom/machine_learning_service.mojom-lite.js", - IDR_MACHINE_LEARNING_INTERNALS_MACHINE_LEARNING_SERVICE_MOJO_JS); - source->AddResourcePath( - "chrome/browser/ui/webui/chromeos/machine_learning/" - "machine_learning_internals_page_handler.mojom-lite.js", - IDR_MACHINE_LEARNING_INTERNALS_PAGE_HANDLER_MOJO_JS); - source->AddResourcePath("machine_learning_internals.js", - IDR_MACHINE_LEARNING_INTERNALS_JS); - source->AddResourcePath("machine_learning_internals_utils.js", - IDR_MACHINE_LEARNING_INTERNALS_UTILS_JS); - source->AddResourcePath("test_model_tab.js", - IDR_MACHINE_LEARNING_INTERNALS_TEST_MODEL_TAB_JS); - source->SetDefaultResource(IDR_MACHINE_LEARNING_INTERNALS_HTML); + const std::map<int, std::string> resource_paths = { + {IDR_MACHINE_LEARNING_INTERNALS_GRAPH_EXECUTOR_MOJO_JS, + "chromeos/services/machine_learning/public/mojom/" + "graph_executor.mojom-lite.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_HANDWRITING_RECOGNIZER_MOJO_JS, + "chromeos/services/machine_learning/public/mojom/" + "handwriting_recognizer.mojom-lite.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_JS, "machine_learning_internals.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_MACHINE_LEARNING_SERVICE_MOJO_JS, + "chromeos/services/machine_learning/public/mojom/" + "machine_learning_service.mojom-lite.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_MODEL_MOJO_JS, + "chromeos/services/machine_learning/public/mojom/model.mojom-lite.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_PAGE_HANDLER_MOJO_JS, + "chrome/browser/ui/webui/chromeos/machine_learning/" + "machine_learning_internals_page_handler.mojom-lite.js"}, + {IDR_MACHINE_LEARNING_INTERNALS_TENSOR_MOJO_JS, + "chromeos/services/machine_learning/public/mojom/tensor.mojom-lite.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_TEST_MODEL_TAB_JS, "test_model_tab.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_TIME_MOJO_JS, + "mojo/public/mojom/base/time.mojom-lite.js"}, + + {IDR_MACHINE_LEARNING_INTERNALS_UTILS_JS, + "machine_learning_internals_utils.js"}, + }; + + for (const auto& path : resource_paths) { + source->AddResourcePath(path.second, path.first); + } + + source->SetDefaultResource(IDR_MACHINE_LEARNING_INTERNALS_HTML); content::WebUIDataSource::Add(Profile::FromWebUI(web_ui), source); } diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc index 13fe503151a..603514f0d85 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.cc @@ -26,11 +26,13 @@ namespace network_element { namespace { constexpr webui::LocalizedString kElementLocalizedStrings[] = { + {"OncType", IDS_NETWORK_TYPE}, {"OncTypeCellular", IDS_NETWORK_TYPE_CELLULAR}, {"OncTypeEthernet", IDS_NETWORK_TYPE_ETHERNET}, {"OncTypeMobile", IDS_NETWORK_TYPE_MOBILE_DATA}, {"OncTypeTether", IDS_NETWORK_TYPE_TETHER}, {"OncTypeVPN", IDS_NETWORK_TYPE_VPN}, + {"OncTypeWireless", IDS_NETWORK_TYPE_WIRELESS}, {"OncTypeWiFi", IDS_NETWORK_TYPE_WIFI}, {"ipAddressNotAvailable", IDS_NETWORK_IP_ADDRESS_NA}, {"networkListItemConnected", IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED}, diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_logs_message_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/network_logs_message_handler.cc new file mode 100644 index 00000000000..423901dfc52 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/network_logs_message_handler.cc @@ -0,0 +1,203 @@ +// Copyright 2020 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/chromeos/network_logs_message_handler.h" + +#include <iostream> + +#include "base/files/file_util.h" +#include "base/strings/stringprintf.h" +#include "base/system/sys_info.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" +#include "chrome/browser/chromeos/system_logs/debug_log_writer.h" +#include "chrome/browser/chromeos/system_logs/system_logs_writer.h" +#include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/policy/chrome_policy_conversions_client.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/logging_chrome.h" +#include "chrome/grit/generated_resources.h" +#include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" +#include "components/policy/core/browser/policy_conversions.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "ui/base/l10n/l10n_util.h" + +namespace chromeos { + +namespace { + +base::FilePath GetDownloadsDirectory(content::WebUI* web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(profile); + base::FilePath path = prefs->DownloadPath(); + if (file_manager::util::IsUnderNonNativeLocalPath(profile, path)) + path = prefs->GetDefaultDownloadDirectoryForProfile(); + return path; +} + +std::string GetJsonPolicies(content::WebUI* web_ui) { + auto client = std::make_unique<policy::ChromePolicyConversionsClient>( + web_ui->GetWebContents()->GetBrowserContext()); + return policy::DictionaryPolicyConversions(std::move(client)).ToJSON(); +} + +bool WriteTimestampedFile(const base::FilePath& file_path, + const std::string& contents) { + base::FilePath timestamped_file_path = + logging::GenerateTimestampedName(file_path, base::Time::Now()); + int bytes_written = + base::WriteFile(timestamped_file_path, contents.data(), contents.size()); + return bytes_written > 0; +} + +bool GetBoolOrFalse(const base::Value* dict, const char* keyname) { + const base::Value* key = dict->FindKey(keyname); + return key && key->GetBool(); +} + +} // namespace + +NetworkLogsMessageHandler::NetworkLogsMessageHandler() = default; + +NetworkLogsMessageHandler::~NetworkLogsMessageHandler() = default; + +void NetworkLogsMessageHandler::RegisterMessages() { + out_dir_ = GetDownloadsDirectory(web_ui()); + web_ui()->RegisterMessageCallback( + "storeLogs", base::BindRepeating(&NetworkLogsMessageHandler::OnStoreLogs, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setShillDebugging", + base::BindRepeating(&NetworkLogsMessageHandler::OnSetShillDebugging, + base::Unretained(this))); +} + +void NetworkLogsMessageHandler::Respond(const std::string& callback_id, + const std::string& result, + bool is_error) { + base::Value response(base::Value::Type::LIST); + response.Append(result); + response.Append(is_error); + ResolveJavascriptCallback(base::Value(callback_id), response); +} + +void NetworkLogsMessageHandler::OnStoreLogs(const base::ListValue* list) { + CHECK_EQ(2u, list->GetSize()); + std::string callback_id; + CHECK(list->GetString(0, &callback_id)); + const base::Value* options; + CHECK(list->Get(1, &options)); + AllowJavascript(); + + if (GetBoolOrFalse(options, "systemLogs")) { + bool scrub_data = GetBoolOrFalse(options, "filterPII"); + chromeos::system_logs_writer::WriteSystemLogs( + out_dir_, scrub_data, + base::BindOnce(&NetworkLogsMessageHandler::OnWriteSystemLogs, + weak_factory_.GetWeakPtr(), callback_id, + options->Clone())); + } else { + MaybeWriteDebugLogs(callback_id, options->Clone()); + } +} + +void NetworkLogsMessageHandler::OnWriteSystemLogs( + const std::string& callback_id, + base::Value&& options, + base::Optional<base::FilePath> syslogs_path) { + if (!syslogs_path) { + Respond(callback_id, "Error writing system logs file.", /*is_error=*/true); + return; + } + MaybeWriteDebugLogs(callback_id, std::move(options)); +} + +void NetworkLogsMessageHandler::MaybeWriteDebugLogs( + const std::string& callback_id, + base::Value&& options) { + if (GetBoolOrFalse(&options, "debugLogs")) { + if (!base::SysInfo::IsRunningOnChromeOS()) { + Respond(callback_id, "Debug logs unavailable on Linux build.", + /*is_error=*/true); + return; + } + bool include_chrome = GetBoolOrFalse(&options, "chromeLogs"); + chromeos::debug_log_writer::StoreLogs( + out_dir_, include_chrome, + base::BindOnce(&NetworkLogsMessageHandler::OnWriteDebugLogs, + weak_factory_.GetWeakPtr(), callback_id, + std::move(options))); + } else { + MaybeWritePolicies(callback_id, std::move(options)); + } +} + +void NetworkLogsMessageHandler::OnWriteDebugLogs( + const std::string& callback_id, + base::Value&& options, + base::Optional<base::FilePath> logs_path) { + if (!logs_path) { + Respond(callback_id, "Error writing debug logs.", /*is_error=*/true); + return; + } + MaybeWritePolicies(callback_id, std::move(options)); +} + +void NetworkLogsMessageHandler::MaybeWritePolicies( + const std::string& callback_id, + base::Value&& options) { + if (GetBoolOrFalse(&options, "policies")) { + std::string json_policies = GetJsonPolicies(web_ui()); + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}, + base::BindOnce(WriteTimestampedFile, out_dir_.Append("policies.json"), + json_policies), + base::BindOnce(&NetworkLogsMessageHandler::OnWritePolicies, + weak_factory_.GetWeakPtr(), callback_id)); + } else { + OnWriteSystemLogsCompleted(callback_id); + } +} + +void NetworkLogsMessageHandler::OnWritePolicies(const std::string& callback_id, + bool result) { + if (!result) { + Respond(callback_id, "Error writing policies.", /*is_error=*/true); + return; + } + OnWriteSystemLogsCompleted(callback_id); +} + +void NetworkLogsMessageHandler::OnWriteSystemLogsCompleted( + const std::string& callback_id) { + Respond(callback_id, + l10n_util::GetStringUTF8(IDS_NETWORK_UI_NETWORK_LOGS_SUCCESS), + /*is_error=*/false); +} + +void NetworkLogsMessageHandler::OnSetShillDebugging( + const base::ListValue* list) { + CHECK_EQ(2u, list->GetSize()); + std::string callback_id, subsystem; + CHECK(list->GetString(0, &callback_id)); + CHECK(list->GetString(1, &subsystem)); + AllowJavascript(); + chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->SetDebugMode( + subsystem, + base::BindOnce(&NetworkLogsMessageHandler::OnSetShillDebuggingCompleted, + weak_factory_.GetWeakPtr(), callback_id)); +} + +void NetworkLogsMessageHandler::OnSetShillDebuggingCompleted( + const std::string& callback_id, + bool succeeded) { + Respond(callback_id, /*result=*/"", !succeeded); +} + +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_logs_message_handler.h b/chromium/chrome/browser/ui/webui/chromeos/network_logs_message_handler.h new file mode 100644 index 00000000000..6ecb291a883 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/network_logs_message_handler.h @@ -0,0 +1,56 @@ +// Copyright 2020 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_CHROMEOS_NETWORK_LOGS_MESSAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_NETWORK_LOGS_MESSAGE_HANDLER_H_ + +#include <string> + +#include "base/files/file_path.h" +#include "base/memory/weak_ptr.h" +#include "base/optional.h" +#include "base/values.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace chromeos { + +class NetworkLogsMessageHandler : public content::WebUIMessageHandler { + public: + NetworkLogsMessageHandler(); + ~NetworkLogsMessageHandler() override; + NetworkLogsMessageHandler(const NetworkLogsMessageHandler&) = delete; + NetworkLogsMessageHandler& operator=(const NetworkLogsMessageHandler&) = + delete; + + private: + // WebUIMessageHandler + void RegisterMessages() override; + + void Respond(const std::string& callback_id, + const std::string& result, + bool is_error); + void OnStoreLogs(const base::ListValue* list); + void OnWriteSystemLogs(const std::string& callback_id, + base::Value&& options, + base::Optional<base::FilePath> syslogs_path); + void MaybeWriteDebugLogs(const std::string& callback_id, + base::Value&& options); + void OnWriteDebugLogs(const std::string& callback_id, + base::Value&& options, + base::Optional<base::FilePath> logs_path); + void MaybeWritePolicies(const std::string& callback_id, + base::Value&& options); + void OnWritePolicies(const std::string& callback_id, bool result); + void OnWriteSystemLogsCompleted(const std::string& callback_id); + void OnSetShillDebugging(const base::ListValue* list); + void OnSetShillDebuggingCompleted(const std::string& callback_id, + bool succeeded); + + base::FilePath out_dir_; + base::WeakPtrFactory<NetworkLogsMessageHandler> weak_factory_{this}; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_NETWORK_LOGS_MESSAGE_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc index da91385d0c7..410696940e1 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/network_ui.cc @@ -14,11 +14,15 @@ #include "base/memory/weak_ptr.h" #include "base/strings/stringprintf.h" #include "base/values.h" +#include "chrome/browser/chromeos/net/network_health/network_health_localized_strings.h" +#include "chrome/browser/chromeos/net/network_health/network_health_service.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.h" #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h" #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h" #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h" +#include "chrome/browser/ui/webui/chromeos/network_logs_message_handler.h" +#include "chrome/browser/ui/webui/chromeos/onc_import_message_handler.h" #include "chrome/common/url_constants.h" #include "chrome/grit/browser_resources.h" #include "chrome/grit/generated_resources.h" @@ -29,12 +33,14 @@ #include "chromeos/network/network_state_handler.h" #include "chromeos/network/onc/onc_utils.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" +#include "chromeos/services/network_health/public/mojom/network_health.mojom.h" #include "components/device_event_log/device_event_log.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "mojo/public/cpp/bindings/remote.h" #include "third_party/cros_system_api/dbus/service_constants.h" #include "ui/base/l10n/l10n_util.h" @@ -132,29 +138,35 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { } private: + void Respond(const std::string& callback_id, const base::Value& response) { + AllowJavascript(); + ResolveJavascriptCallback(base::Value(callback_id), response); + } + void GetShillNetworkProperties(const base::ListValue* arg_list) { - std::string guid; - if (!arg_list->GetString(0, &guid)) { - NOTREACHED(); - return; - } + CHECK_EQ(2u, arg_list->GetSize()); + std::string callback_id, guid; + CHECK(arg_list->GetString(0, &callback_id)); + CHECK(arg_list->GetString(1, &guid)); + std::string service_path; if (!GetServicePathFromGuid(guid, &service_path)) { - ErrorCallback(guid, kGetNetworkProperties, "Error.InvalidNetworkGuid", - nullptr); + ErrorCallback(callback_id, guid, kGetNetworkProperties, + "Error.InvalidNetworkGuid", nullptr); return; } NetworkHandler::Get()->network_configuration_handler()->GetShillProperties( service_path, base::BindOnce( &NetworkConfigMessageHandler::GetShillNetworkPropertiesSuccess, - weak_ptr_factory_.GetWeakPtr()), + weak_ptr_factory_.GetWeakPtr(), callback_id), base::Bind(&NetworkConfigMessageHandler::ErrorCallback, - weak_ptr_factory_.GetWeakPtr(), guid, + weak_ptr_factory_.GetWeakPtr(), callback_id, guid, kGetNetworkProperties)); } void GetShillNetworkPropertiesSuccess( + const std::string& callback_id, const std::string& service_path, const base::DictionaryValue& dictionary) { std::unique_ptr<base::DictionaryValue> dictionary_copy( @@ -167,47 +179,46 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { base::ListValue return_arg_list; return_arg_list.Append(std::move(dictionary_copy)); - - AllowJavascript(); - CallJavascriptFunction( - base::StringPrintf("NetworkUI.%sResult", kGetNetworkProperties), - return_arg_list); + Respond(callback_id, return_arg_list); } void GetShillDeviceProperties(const base::ListValue* arg_list) { - std::string type; - if (!arg_list->GetString(0, &type)) { - NOTREACHED(); - return; - } + CHECK_EQ(2u, arg_list->GetSize()); + std::string callback_id, type; + CHECK(arg_list->GetString(0, &callback_id)); + CHECK(arg_list->GetString(1, &type)); + const DeviceState* device = NetworkHandler::Get()->network_state_handler()->GetDeviceStateByType( onc::NetworkTypePatternFromOncType(type)); if (!device) { - ErrorCallback(type, kGetDeviceProperties, "Error.InvalidDeviceType", - nullptr); + ErrorCallback(callback_id, type, kGetDeviceProperties, + "Error.InvalidDeviceType", nullptr); return; } NetworkHandler::Get()->network_device_handler()->GetDeviceProperties( device->path(), base::BindOnce( &NetworkConfigMessageHandler::GetShillDevicePropertiesSuccess, - weak_ptr_factory_.GetWeakPtr()), + weak_ptr_factory_.GetWeakPtr(), callback_id), base::Bind(&NetworkConfigMessageHandler::ErrorCallback, - weak_ptr_factory_.GetWeakPtr(), type, kGetDeviceProperties)); + weak_ptr_factory_.GetWeakPtr(), callback_id, type, + kGetDeviceProperties)); } void GetShillEthernetEAP(const base::ListValue* arg_list) { + CHECK_EQ(1u, arg_list->GetSize()); + std::string callback_id; + CHECK(arg_list->GetString(0, &callback_id)); + NetworkStateHandler::NetworkStateList list; NetworkHandler::Get()->network_state_handler()->GetNetworkListByType( NetworkTypePattern::Primitive(shill::kTypeEthernetEap), true /* configured_only */, false /* visible_only */, 1 /* limit */, &list); - AllowJavascript(); if (list.empty()) { - CallJavascriptFunction( - base::StringPrintf("NetworkUI.%sResult", kGetEthernetEAP)); + Respond(callback_id, base::Value(base::Value::Type::LIST)); return; } const NetworkState* eap = list.front(); @@ -215,21 +226,25 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { properties.SetStringKey("guid", eap->guid()); properties.SetStringKey("name", eap->name()); properties.SetStringKey("type", eap->type()); - CallJavascriptFunction( - base::StringPrintf("NetworkUI.%sResult", kGetEthernetEAP), properties); + base::Value response(base::Value::Type::LIST); + response.Append(std::move(properties)); + Respond(callback_id, response); } void OpenCellularActivationUi(const base::ListValue* arg_list) { + CHECK_EQ(1u, arg_list->GetSize()); + std::string callback_id; + CHECK(arg_list->GetString(0, &callback_id)); + const NetworkState* cellular_network = NetworkHandler::Get()->network_state_handler()->FirstNetworkByType( NetworkTypePattern::Cellular()); if (cellular_network) cellular_setup::OpenCellularSetupDialog(cellular_network->guid()); - AllowJavascript(); - CallJavascriptFunction( - base::StringPrintf("NetworkUI.%sResult", kOpenCellularActivationUi), - base::Value(cellular_network != nullptr)); + base::Value response(base::Value::Type::LIST); + response.Append(base::Value(cellular_network != nullptr)); + Respond(callback_id, response); } void ShowNetworkDetails(const base::ListValue* arg_list) { @@ -257,6 +272,7 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { } void GetShillDevicePropertiesSuccess( + const std::string& callback_id, const std::string& device_path, const base::DictionaryValue& dictionary) { std::unique_ptr<base::DictionaryValue> dictionary_copy( @@ -267,14 +283,11 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { base::ListValue return_arg_list; return_arg_list.Append(std::move(dictionary_copy)); - - AllowJavascript(); - CallJavascriptFunction( - base::StringPrintf("NetworkUI.%sResult", kGetDeviceProperties), - return_arg_list); + Respond(callback_id, return_arg_list); } - void ErrorCallback(const std::string& guid_or_type, + void ErrorCallback(const std::string& callback_id, + const std::string& guid_or_type, const std::string& function_name, const std::string& error_name, std::unique_ptr<base::DictionaryValue> /* error_data */) { @@ -287,11 +300,7 @@ class NetworkConfigMessageHandler : public content::WebUIMessageHandler { dictionary.SetKey(key, base::Value(guid_or_type)); dictionary.SetKey("ShillError", base::Value(error_name)); return_arg_list.Append(std::move(dictionary)); - - AllowJavascript(); - CallJavascriptFunction( - base::StringPrintf("NetworkUI.%sResult", function_name.c_str()), - return_arg_list); + Respond(callback_id, return_arg_list); } void AddNetwork(const base::ListValue* args) { @@ -312,8 +321,21 @@ void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) { localized_strings->SetString("titleText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE)); - localized_strings->SetString("titleText", - l10n_util::GetStringUTF16(IDS_NETWORK_UI_TITLE)); + localized_strings->SetString( + "generalTab", l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_GENERAL)); + localized_strings->SetString( + "networkHealthTab", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_HEALTH)); + localized_strings->SetString( + "networkLogsTab", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_LOGS)); + localized_strings->SetString( + "networkStateTab", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_STATE)); + localized_strings->SetString( + "networkSelectTab", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_TAB_NETWORK_SELECT)); + localized_strings->SetString( "autoRefreshText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_AUTO_REFRESH)); @@ -347,6 +369,9 @@ void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) { "networkListsLabel", l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LISTS)); localized_strings->SetString( + "networkHealthLabel", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_HEALTH)); + localized_strings->SetString( "visibleNetworksLabel", l10n_util::GetStringUTF16(IDS_NETWORK_UI_VISIBLE_NETWORKS)); localized_strings->SetString( @@ -375,11 +400,60 @@ void NetworkUI::GetLocalizedStrings(base::DictionaryValue* localized_strings) { localized_strings->SetString( "addNewWifiButtonText", l10n_util::GetStringUTF16(IDS_NETWORK_UI_ADD_NEW_WIFI_BUTTON_TEXT)); + + localized_strings->SetString( + "importOncButtonText", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_IMPORT_ONC_BUTTON_TEXT)); + + localized_strings->SetString( + "addWiFiListItemName", + l10n_util::GetStringUTF16(IDS_NETWORK_ADD_WI_FI_LIST_ITEM_NAME)); + + // Network logs + localized_strings->SetString( + "networkLogsDescription", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DESCRIPTION)); + localized_strings->SetString( + "networkLogsSystemLogs", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_SYSTEM_LOGS)); + localized_strings->SetString( + "networkLogsFilterPii", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_FILTER_PII)); + localized_strings->SetString( + "networkLogsPolicies", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_POLICIES)); + localized_strings->SetString( + "networkLogsDebugLogs", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DEBUG_LOGS)); + localized_strings->SetString( + "networkLogsChromeLogs", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_CHROME_LOGS)); + localized_strings->SetString( + "networkLogsStoreButton", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_STORE_BUTTON)); + localized_strings->SetString( + "networkLogsStatus", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_STATUS)); + localized_strings->SetString( + "networkLogsDebuggingTitle", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_TITLE)); + localized_strings->SetString( + "networkLogsDebuggingDescription", + l10n_util::GetStringUTF16( + IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_DESCRIPTION)); + localized_strings->SetString( + "networkLogsDebuggingNone", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_NONE)); + localized_strings->SetString( + "networkLogsDebuggingUnknown", + l10n_util::GetStringUTF16(IDS_NETWORK_UI_NETWORK_LOGS_DEBUGGING_UNKNOWN)); } NetworkUI::NetworkUI(content::WebUI* web_ui) : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) { web_ui->AddMessageHandler(std::make_unique<NetworkConfigMessageHandler>()); + web_ui->AddMessageHandler(std::make_unique<OncImportMessageHandler>()); + web_ui->AddMessageHandler(std::make_unique<NetworkLogsMessageHandler>()); // Enable extension API calls in the WebUI. extensions::TabHelper::CreateForWebContents(web_ui->GetWebContents()); @@ -390,13 +464,23 @@ NetworkUI::NetworkUI(content::WebUI* web_ui) content::WebUIDataSource* html = content::WebUIDataSource::Create(chrome::kChromeUINetworkHost); html->AddLocalizedStrings(localized_strings); + network_health::AddLocalizedStrings(html); network_element::AddLocalizedStrings(html); - + network_element::AddOncLocalizedStrings(html); html->UseStringsJs(); - html->AddResourcePath("network_ui.css", IDR_NETWORK_UI_CSS); + + html->AddResourcePath("network_ui_browser_proxy.html", + IDR_NETWORK_UI_BROWSER_PROXY_HTML); + html->AddResourcePath("network_ui_browser_proxy.js", + IDR_NETWORK_UI_BROWSER_PROXY_JS); + html->AddResourcePath("network_ui.html", IDR_NETWORK_UI_HTML); html->AddResourcePath("network_ui.js", IDR_NETWORK_UI_JS); - html->SetDefaultResource(IDR_NETWORK_UI_HTML); + html->AddResourcePath("network_state_ui.html", IDR_NETWORK_STATE_UI_HTML); + html->AddResourcePath("network_state_ui.js", IDR_NETWORK_STATE_UI_JS); + html->AddResourcePath("network_logs_ui.html", IDR_NETWORK_LOGS_UI_HTML); + html->AddResourcePath("network_logs_ui.js", IDR_NETWORK_LOGS_UI_JS); + html->SetDefaultResource(IDR_NETWORK_UI_PAGE_HTML); content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), html); @@ -409,6 +493,13 @@ void NetworkUI::BindInterface( ash::GetNetworkConfigService(std::move(receiver)); } +void NetworkUI::BindInterface( + mojo::PendingReceiver<network_health::mojom::NetworkHealthService> + receiver) { + network_health::NetworkHealthService::GetInstance()->BindRemote( + std::move(receiver)); +} + WEB_UI_CONTROLLER_TYPE_IMPL(NetworkUI) } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/network_ui.h b/chromium/chrome/browser/ui/webui/chromeos/network_ui.h index 8e4fc290ebd..b7bbd7dbae0 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/network_ui.h +++ b/chromium/chrome/browser/ui/webui/chromeos/network_ui.h @@ -7,6 +7,7 @@ #include "base/macros.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom-forward.h" +#include "chromeos/services/network_health/public/mojom/network_health.mojom-forward.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "ui/webui/mojo_web_ui_controller.h" @@ -24,11 +25,17 @@ class NetworkUI : public ui::MojoWebUIController { static void GetLocalizedStrings(base::DictionaryValue* localized_strings); - // Instantiates implementor of the mojom::CrosNetworkConfig mojo interface + // Instantiates implementation of the mojom::CrosNetworkConfig mojo interface // passing the pending receiver that will be internally bound. void BindInterface( mojo::PendingReceiver<network_config::mojom::CrosNetworkConfig> receiver); + // Instantiates implementation of the mojom::NetworkHealthService mojo + // interface passing the pending receiver that will be bound. + void BindInterface( + mojo::PendingReceiver<network_health::mojom::NetworkHealthService> + receiver); + private: WEB_UI_CONTROLLER_TYPE_DECL(); diff --git a/chromium/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc b/chromium/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc new file mode 100644 index 00000000000..27cd4019b27 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/onc_import_message_handler.cc @@ -0,0 +1,124 @@ +// Copyright 2020 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/chromeos/onc_import_message_handler.h" + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/strings/stringprintf.h" +#include "base/values.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/browser/net/nss_context.h" +#include "chrome/browser/profiles/profile.h" +#include "chromeos/network/onc/onc_certificate_importer_impl.h" +#include "chromeos/network/onc/onc_parsed_certificates.h" +#include "chromeos/network/onc/onc_utils.h" +#include "components/onc/onc_constants.h" +#include "components/policy/core/browser/policy_conversions.h" +#include "content/public/browser/browser_task_traits.h" +#include "content/public/browser/browser_thread.h" + +namespace chromeos { + +OncImportMessageHandler::OncImportMessageHandler() = default; + +OncImportMessageHandler::~OncImportMessageHandler() = default; + +void OncImportMessageHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "importONC", base::BindRepeating(&OncImportMessageHandler::OnImportONC, + base::Unretained(this))); +} + +void OncImportMessageHandler::Respond(const std::string& callback_id, + const std::string& result, + bool is_error) { + base::Value response(base::Value::Type::LIST); + response.Append(result); + response.Append(is_error); + ResolveJavascriptCallback(base::Value(callback_id), response); +} + +void OncImportMessageHandler::OnImportONC(const base::ListValue* list) { + CHECK_EQ(2u, list->GetSize()); + std::string callback_id, onc_blob; + CHECK(list->GetString(0, &callback_id)); + CHECK(list->GetString(1, &onc_blob)); + AllowJavascript(); + GetNSSCertDatabaseForProfile( + Profile::FromWebUI(web_ui()), + base::Bind(&OncImportMessageHandler::ImportONCToNSSDB, + weak_factory_.GetWeakPtr(), callback_id, onc_blob)); +} + +void OncImportMessageHandler::ImportONCToNSSDB(const std::string& callback_id, + const std::string& onc_blob, + net::NSSCertDatabase* nssdb) { + const user_manager::User* user = + ProfileHelper::Get()->GetUserByProfile(Profile::FromWebUI(web_ui())); + if (!user) { + Respond(callback_id, "User not found.", /*is_error=*/true); + return; + } + + std::string result; + bool has_error = false; + + ::onc::ONCSource onc_source = ::onc::ONC_SOURCE_USER_IMPORT; + base::ListValue network_configs; + base::DictionaryValue global_network_config; + base::ListValue certificates; + if (!onc::ParseAndValidateOncForImport( + onc_blob, onc_source, /*passphrase=*/std::string(), &network_configs, + &global_network_config, &certificates)) { + has_error = true; + result += "Errors occurred during ONC parsing.\n"; + } + + std::string import_error; + int num_networks_imported = + onc::ImportNetworksForUser(user, network_configs, &import_error); + if (!import_error.empty()) { + has_error = true; + result += "Error importing networks: " + import_error + "\n"; + } + result += + base::StringPrintf("Networks imported: %d\n", num_networks_imported); + if (certificates.GetList().empty()) { + if (!num_networks_imported) + has_error = true; + Respond(callback_id, result, has_error); + return; + } + + auto cert_importer = std::make_unique<onc::CertificateImporterImpl>( + content::GetIOThreadTaskRunner({}), nssdb); + auto certs = std::make_unique<onc::OncParsedCertificates>(certificates); + if (certs->has_error()) { + has_error = true; + result += "Some certificates could not be parsed.\n"; + } + cert_importer->ImportAllCertificatesUserInitiated( + certs->server_or_authority_certificates(), certs->client_certificates(), + base::BindOnce(&OncImportMessageHandler::OnCertificatesImported, + weak_factory_.GetWeakPtr(), std::move(cert_importer), + callback_id, result, has_error)); +} + +void OncImportMessageHandler::OnCertificatesImported( + std::unique_ptr<onc::CertificateImporterImpl> cert_importer, + const std::string& callback_id, + const std::string& previous_result, + bool has_error, + bool cert_import_success) { + std::string result = previous_result; + if (!cert_import_success) { + has_error = true; + result += "Some certificates couldn't be imported.\n"; + } + Respond(callback_id, result, has_error); + // |cert_importer| will be destroyed when the callback exits. +} + +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/onc_import_message_handler.h b/chromium/chrome/browser/ui/webui/chromeos/onc_import_message_handler.h new file mode 100644 index 00000000000..834850e6f58 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/chromeos/onc_import_message_handler.h @@ -0,0 +1,57 @@ +// Copyright 2020 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_CHROMEOS_ONC_IMPORT_MESSAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ONC_IMPORT_MESSAGE_HANDLER_H_ + +#include <string> + +#include "base/memory/weak_ptr.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace base { +class ListValue; +} + +namespace net { +class NSSCertDatabase; +} + +namespace chromeos { + +namespace onc { +class CertificateImporterImpl; +} + +class OncImportMessageHandler : public content::WebUIMessageHandler { + public: + OncImportMessageHandler(); + ~OncImportMessageHandler() override; + OncImportMessageHandler(const OncImportMessageHandler&) = delete; + OncImportMessageHandler& operator=(const OncImportMessageHandler&) = delete; + + private: + // WebUIMessageHandler + void RegisterMessages() override; + + void Respond(const std::string& callback_id, + const std::string& result, + bool is_error); + void OnImportONC(const base::ListValue* list); + void ImportONCToNSSDB(const std::string& callback_id, + const std::string& onc_blob, + net::NSSCertDatabase* nssdb); + void OnCertificatesImported( + std::unique_ptr<onc::CertificateImporterImpl> cert_importer, + const std::string& callback_id, + const std::string& previous_error, + bool has_error, + bool cert_import_success); + + base::WeakPtrFactory<OncImportMessageHandler> weak_factory_{this}; +}; + +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ONC_IMPORT_MESSAGE_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc b/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc index cc12e4bb71f..c1a0275910c 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/set_time_ui.cc @@ -33,6 +33,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/webui/web_ui_util.h" #include "ui/resources/grit/webui_resources.h" @@ -173,7 +174,8 @@ SetTimeUI::SetTimeUI(content::WebUI* web_ui) : WebDialogUI(web_ui) { // Set up the chrome://set-time source. content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUISetTimeHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); static constexpr webui::LocalizedString kStrings[] = { diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc index 0e64776606e..1fc4d7be1c1 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.cc @@ -20,7 +20,7 @@ namespace chromeos { namespace smb_dialog { namespace { -constexpr int kSmbCredentialsDialogHeight = 250; +constexpr int kSmbCredentialsDialogHeight = 230; void AddSmbCredentialsDialogStrings(content::WebUIDataSource* html_source) { static const struct { @@ -135,5 +135,9 @@ void SmbCredentialsDialogUI::OnUpdateCredentials(const std::string& username, } } +bool SmbCredentialsDialog::ShouldShowCloseButton() const { + return false; +} + } // namespace smb_dialog } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h index b614f60c71c..1836c16f136 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h +++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_credentials_dialog.h @@ -41,6 +41,7 @@ class SmbCredentialsDialog : public SystemWebDialogDelegate { // ui::WebDialogDelegate void GetDialogSize(gfx::Size* size) const override; std::string GetDialogArgs() const override; + bool ShouldShowCloseButton() const override; private: const std::string mount_id_; diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc index 2aa8bca9516..8ffea982338 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc +++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.cc @@ -21,7 +21,7 @@ namespace chromeos { namespace smb_dialog { namespace { -constexpr int kSmbShareDialogHeight = 564; +constexpr int kSmbShareDialogHeight = 515; void AddSmbSharesStrings(content::WebUIDataSource* html_source) { // Add strings specific to smb_dialog. @@ -96,5 +96,9 @@ SmbShareDialogUI::SmbShareDialogUI(content::WebUI* web_ui) SmbShareDialogUI::~SmbShareDialogUI() = default; +bool SmbShareDialog::ShouldShowCloseButton() const { + return false; +} + } // namespace smb_dialog } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h index 15ff3f6bee9..8902231aff8 100644 --- a/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h +++ b/chromium/chrome/browser/ui/webui/chromeos/smb_shares/smb_share_dialog.h @@ -23,6 +23,7 @@ class SmbShareDialog : public SystemWebDialogDelegate { // ui::WebDialogDelegate void GetDialogSize(gfx::Size* size) const override; + bool ShouldShowCloseButton() const override; DISALLOW_COPY_AND_ASSIGN(SmbShareDialog); }; diff --git a/chromium/chrome/browser/ui/webui/components/components_handler.cc b/chromium/chrome/browser/ui/webui/components/components_handler.cc index 504d9bbc6c6..283f8ad5901 100644 --- a/chromium/chrome/browser/ui/webui/components/components_handler.cc +++ b/chromium/chrome/browser/ui/webui/components/components_handler.cc @@ -8,7 +8,8 @@ #include <vector> #include "base/bind.h" -#include "base/logging.h" +#include "base/check.h" +#include "base/notreached.h" #include "base/values.h" #include "chrome/grit/generated_resources.h" #include "components/update_client/crx_update_item.h" diff --git a/chromium/chrome/browser/ui/webui/components/components_ui.cc b/chromium/chrome/browser/ui/webui/components/components_ui.cc index cddfc815037..3eaf975d70c 100644 --- a/chromium/chrome/browser/ui/webui/components/components_ui.cc +++ b/chromium/chrome/browser/ui/webui/components/components_ui.cc @@ -27,6 +27,7 @@ #include "chrome/grit/theme_resources.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/web_ui_util.h" @@ -40,7 +41,8 @@ content::WebUIDataSource* CreateComponentsUIHTMLSource(Profile* profile) { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIComponentsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); static constexpr webui::LocalizedString kStrings[] = { diff --git a/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc b/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc index d7a42770c33..04c2f2a0c7d 100644 --- a/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc +++ b/chromium/chrome/browser/ui/webui/conflicts/conflicts_data_fetcher.cc @@ -7,7 +7,6 @@ #include <string> #include <utility> -#include "base/task/post_task.h" #include "base/values.h" #include "base/win/windows_version.h" #include "chrome/browser/win/conflicts/module_database.h" @@ -483,15 +482,15 @@ void ConflictsDataFetcher::OnModuleDatabaseIdle() { #if defined(GOOGLE_CHROME_BUILD) // The state of third-party features must be determined on the UI thread. - base::PostTask( - FROM_HERE, {content::BrowserThread::UI}, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce( OnModuleDataFetched, std::move(on_conflicts_data_fetched_callback_), std::move(results), std::move(third_party_conflicts_manager_state_))); #else // The third-party features are always disabled on Chromium builds. - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(OnConflictsDataFetched, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(OnConflictsDataFetched, std::move(on_conflicts_data_fetched_callback_), std::move(results), kNonGoogleChromeBuild)); #endif diff --git a/chromium/chrome/browser/ui/webui/conflicts/conflicts_ui.cc b/chromium/chrome/browser/ui/webui/conflicts/conflicts_ui.cc index 38b4f7f1cc1..15d96b0b21d 100644 --- a/chromium/chrome/browser/ui/webui/conflicts/conflicts_ui.cc +++ b/chromium/chrome/browser/ui/webui/conflicts/conflicts_ui.cc @@ -16,6 +16,7 @@ #include "chrome/grit/theme_resources.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/resource/resource_bundle.h" namespace { @@ -23,7 +24,8 @@ namespace { content::WebUIDataSource* CreateConflictsUIHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIConflictsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->AddResourcePath("conflicts.js", IDR_ABOUT_CONFLICTS_JS); diff --git a/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc b/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc index 4a9faa8ce8c..63add823a35 100644 --- a/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc +++ b/chromium/chrome/browser/ui/webui/devtools_ui_data_source.cc @@ -57,6 +57,8 @@ std::string GetMimeTypeForPath(const std::string& path) { base::CompareCase::INSENSITIVE_ASCII)) { return "text/css"; } else if (base::EndsWith(filename, ".js", + base::CompareCase::INSENSITIVE_ASCII) || + base::EndsWith(filename, ".mjs", base::CompareCase::INSENSITIVE_ASCII)) { return "application/javascript"; } else if (base::EndsWith(filename, ".png", @@ -113,15 +115,20 @@ void DevToolsDataSource::StartDataRequest( base::CompareCase::INSENSITIVE_ASCII)); std::string path_under_bundled = path_without_params.substr(bundled_path_prefix.length()); -#if !BUILDFLAG(DEBUG_DEVTOOLS) - if (!GetCustomDevToolsFrontendURL().SchemeIsFile()) { + GURL custom_devtools_frontend = GetCustomDevToolsFrontendURL(); + if (!custom_devtools_frontend.is_valid()) { // Fetch from packaged resources. StartBundledDataRequest(path_under_bundled, std::move(callback)); return; } -#endif - // Fetch from file system. - StartFileRequest(path_under_bundled, std::move(callback)); + if (GetCustomDevToolsFrontendURL().SchemeIsFile()) { + // Fetch from file system. + StartFileRequest(path_under_bundled, std::move(callback)); + return; + } + GURL remote_url(custom_devtools_frontend.spec() + path_under_bundled); + // Fetch from remote URL. + StartCustomDataRequest(remote_url, std::move(callback)); return; } @@ -190,10 +197,7 @@ void DevToolsDataSource::StartBundledDataRequest( scoped_refptr<base::RefCountedMemory> bytes = content::DevToolsFrontendHost::GetFrontendResourceBytes(path); - DLOG_IF(WARNING, !bytes) - << "Unable to find dev tool resource: " << path - << ". If you compiled with debug_devtools=1, try running with " - "--debug-devtools."; + DLOG_IF(WARNING, !bytes) << "Unable to find DevTools resource: " << path; std::move(callback).Run(bytes); } @@ -303,21 +307,11 @@ void DevToolsDataSource::StartFileRequest(const std::string& path, GotDataCallback callback) { base::FilePath base_path; GURL custom_devtools_frontend = GetCustomDevToolsFrontendURL(); - if (custom_devtools_frontend.SchemeIsFile()) { - if (!net::FileURLToFilePath(custom_devtools_frontend, &base_path)) { - std::move(callback).Run(CreateNotFoundResponse()); - return; - } - } else { -#if BUILDFLAG(DEBUG_DEVTOOLS) - // Use default path for unbundled files when debug_devtools=true - if (!base::PathService::Get(chrome::DIR_INSPECTOR_DEBUG, &base_path)) { - std::move(callback).Run(CreateNotFoundResponse()); - return; - } -#else - NOTREACHED(); -#endif + DCHECK(custom_devtools_frontend.SchemeIsFile()); + if (!net::FileURLToFilePath(custom_devtools_frontend, &base_path)) { + std::move(callback).Run(CreateNotFoundResponse()); + LOG(WARNING) << "Unable to find DevTools resource: " << path; + return; } base::FilePath full_path = base_path.AppendASCII(path); diff --git a/chromium/chrome/browser/ui/webui/devtools_ui_data_source_unittest.cc b/chromium/chrome/browser/ui/webui/devtools_ui_data_source_unittest.cc index fe7e72ffe11..464223bd09a 100644 --- a/chromium/chrome/browser/ui/webui/devtools_ui_data_source_unittest.cc +++ b/chromium/chrome/browser/ui/webui/devtools_ui_data_source_unittest.cc @@ -96,7 +96,7 @@ class DevToolsUIDataSourceTest : public testing::Test { private: void OnDataReceived(scoped_refptr<base::RefCountedMemory> bytes) { data_received_ = true; - if (bytes.get() != nullptr) { + if (bytes.get()) { data_ = base::StringPiece(reinterpret_cast<const char*>(bytes->front()), bytes->size()) .as_string(); @@ -128,7 +128,7 @@ TEST_F(DevToolsUIDataSourceTest, TestDevToolsBundledURLWithQueryParam) { EXPECT_FALSE(data().empty()); } -TEST_F(DevToolsUIDataSourceTest, TestDevToolsBundledURLWithSwitch) { +TEST_F(DevToolsUIDataSourceTest, TestDevToolsBundledFileURLWithSwitch) { #if defined(OS_WIN) const char* flag_value = "file://C:/tmp/"; #else @@ -143,6 +143,17 @@ TEST_F(DevToolsUIDataSourceTest, TestDevToolsBundledURLWithSwitch) { EXPECT_EQ(data(), "file: devtools_app.html"); } +TEST_F(DevToolsUIDataSourceTest, TestDevToolsBundledRemoteURLWithSwitch) { + const char* flag_value = "http://example.com/example/path/"; + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + switches::kCustomDevtoolsFrontend, flag_value); + const GURL path = + DevToolsUrl().Resolve(DevToolsBundledPath(kDevToolsUITestFrontEndUrl)); + StartRequest(path.path()); + EXPECT_TRUE(data_received()); + EXPECT_EQ(data(), "url: http://example.com/example/path/devtools_app.html"); +} + TEST_F(DevToolsUIDataSourceTest, TestDevToolsInvalidBundledURL) { const GURL path = DevToolsUrl().Resolve(DevToolsBundledPath("invalid_devtools_app.html")); diff --git a/chromium/chrome/browser/ui/webui/discards/discards.mojom b/chromium/chrome/browser/ui/webui/discards/discards.mojom index aec7bd7dcff..1b54372b1cb 100644 --- a/chromium/chrome/browser/ui/webui/discards/discards.mojom +++ b/chromium/chrome/browser/ui/webui/discards/discards.mojom @@ -9,14 +9,16 @@ import "mojo/public/mojom/base/process_id.mojom"; import "mojo/public/mojom/base/time.mojom"; import "url/mojom/url.mojom"; -// Identical to content::Visibility. +// Identical to content::Visibility. Sent from browser to the chrome://discards +// WebUI. enum LifecycleUnitVisibility { HIDDEN = 0, OCCLUDED = 1, VISIBLE = 2, }; -// Discard related information about a single tab in a browser. +// Discard related information about a single tab in a browser. Sent from +// browser to the chrome://discards WebUI. struct TabDiscardsInfo { // The URL associated with the tab. This corresponds to GetLastCommittedURL, // and is also what is visible in the Omnibox for a given tab. @@ -29,10 +31,6 @@ struct TabDiscardsInfo { mojom.LifecycleUnitLoadingState loading_state; // The state of the LifecycleUnit. mojom.LifecycleUnitState state; - // Whether the tab can be frozen. - bool can_freeze; - // List of human-readable reasons why a tab can't be frozen. - array<string> cannot_freeze_reasons; // Whether the tab can be discarded. bool can_discard; // List of human-readable reasons why a tab can't be discarded. @@ -85,9 +83,6 @@ interface DetailsProvider { // Invokes a callback when the discard is complete. DiscardById(int32 tab_id) => (); - // Freezes a tab given its |tab_id|. - FreezeById(int32 tab_id); - // Loads a tab given its |tab_id|. LoadById(int32 tab_id); @@ -98,12 +93,16 @@ interface DetailsProvider { Discard() => (); }; -// Represents the momentary state of a Page node. +// Represents the momentary state of a Page node. Sent from browser to the +// chrome://discards WebUI via the GraphChangeStream (defined below). struct PageInfo { int64 id; url.mojom.Url main_frame_url; + // The id of the frame that "opened" this page, if any. + int64 opener_frame_id; + // This field is a dictionary of values, where each value is generated by // a performance_manager::NodeDataDescriber implementation and keyed by the // name it registered with. The intent is for each describer to describe @@ -112,46 +111,74 @@ struct PageInfo { string description_json; }; -// Represents the momentary state of a Frame node. +// Represents the momentary state of a Frame node. Sent from browser to the +// chrome://discards WebUI via the GraphChangeStream (defined below). struct FrameInfo { int64 id; + // The last committed URL of this frame. url.mojom.Url url; + + // The ID of the page node this frame is associated with. int64 page_id; + + // The ID of the parent frame, if there is one. If not, this is a main frame. int64 parent_frame_id; + + // The ID of the process in which this frame is hosted. int64 process_id; // See PageInfo::description_json. string description_json; }; -// Represents the momentary state of a Process node. +// Represents the momentary state of a Process node. Sent from browser to the +// chrome://discards WebUI via the GraphChangeStream (defined below). struct ProcessInfo { int64 id; + // The PID of the process associated with this node. mojo_base.mojom.ProcessId pid; + + // The private memory usage of this process in KB. uint64 private_footprint_kb; // See PageInfo::description_json. string description_json; }; -// Represents the momentary state of a Worker node. +// Represents the momentary state of a Worker node. Sent from browser to the +// chrome://discards WebUI via the GraphChangeStream (defined below). struct WorkerInfo { int64 id; + // The URL of the worker. url.mojom.Url url; + + // The ID of the process is which this worker is hosted. int64 process_id; + // An array of frames (by ID) that are clients of this worker (the worker is + // doing work on behalf of this frame). See + // WorkerNode::GetClientFrames() for details. array<int64> client_frame_ids; + + // An array of other workers (by ID) that are clients of this worker (the + // worker is doing work on behalf of these other workers). See + // WorkerNode::GetClientWorkers() for details. array<int64> client_worker_ids; + + // An array of workers (by ID) that are children of this worker. This can + // occur with shared and service workers owning their own dedicated workers. + // See WorkerNode::GetChildWorkers() for details. array<int64> child_worker_ids; // See PageInfo::description_json. string description_json; }; -// Used to transport favicon data. +// Used to transport favicon data. Sent from browser to the chrome://discards +// WebUI via the GraphChangeStream (defined below). struct FavIconInfo { int64 node_id; @@ -161,7 +188,11 @@ struct FavIconInfo { }; // Implement to receive a stream of notifications when performance manager -// graph nodes are created, changed or deleted. +// graph nodes are created, changed or deleted. Implemented in Javascript code +// running in the chrome://discards WebUI, with data routed to it from an +// observer of the performance_manager::Graph in the browser. The implementation +// is injected into the browser via the browser-exposed GraphDump interface, +// defined below. interface GraphChangeStream { // The |frame| was created. FrameCreated(FrameInfo frame); @@ -190,7 +221,8 @@ interface GraphChangeStream { }; // This interface allows subscribing to a stream of events that track the state -// of the performance manager graph. +// of the performance manager graph. Implemented in browser code, and used from +// Javascript code running in the chrome://discards WebUI. interface GraphDump { // Subscribes |change_subscriber| to a graph change stream. SubscribeToChanges(pending_remote<GraphChangeStream> change_subscriber); diff --git a/chromium/chrome/browser/ui/webui/discards/discards_ui.cc b/chromium/chrome/browser/ui/webui/discards/discards_ui.cc index fdbf79d7a00..95448e0d72c 100644 --- a/chromium/chrome/browser/ui/webui/discards/discards_ui.cc +++ b/chromium/chrome/browser/ui/webui/discards/discards_ui.cc @@ -41,6 +41,7 @@ #include "content/public/browser/web_ui_message_handler.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/resources/grit/ui_resources.h" #include "url/gurl.h" #include "url/origin.h" @@ -133,9 +134,6 @@ class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider { GetLifecycleUnitVisibility(lifecycle_unit->GetVisibility()); info->loading_state = lifecycle_unit->GetLoadingState(); info->state = lifecycle_unit->GetState(); - resource_coordinator::DecisionDetails freeze_details; - info->can_freeze = lifecycle_unit->CanFreeze(&freeze_details); - info->cannot_freeze_reasons = freeze_details.GetFailureReasonStrings(); resource_coordinator::DecisionDetails discard_details; info->cannot_discard_reasons = discard_details.GetFailureReasonStrings(); info->discard_reason = lifecycle_unit->GetDiscardReason(); @@ -193,12 +191,6 @@ class DiscardsDetailsProviderImpl : public discards::mojom::DetailsProvider { std::move(callback).Run(); } - void FreezeById(int32_t id) override { - auto* lifecycle_unit = GetLifecycleUnitById(id); - if (lifecycle_unit) - lifecycle_unit->Freeze(); - } - void LoadById(int32_t id) override { auto* lifecycle_unit = GetLifecycleUnitById(id); if (lifecycle_unit) @@ -225,7 +217,8 @@ DiscardsUI::DiscardsUI(content::WebUI* web_ui) std::unique_ptr<content::WebUIDataSource> source( content::WebUIDataSource::Create(chrome::kChromeUIDiscardsHost)); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); source->AddResourcePath("discards.js", IDR_DISCARDS_JS); diff --git a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc index 2cb540e1ebb..9351afb96c9 100644 --- a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc +++ b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.cc @@ -12,7 +12,6 @@ #include "base/json/json_string_value_serializer.h" #include "base/macros.h" #include "base/task/cancelable_task_tracker.h" -#include "base/task/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" #include "chrome/browser/favicon/favicon_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -193,31 +192,18 @@ void DiscardsGraphDumpImpl::SubscribeToChanges( } // Send creation notifications for all existing nodes. - for (const performance_manager::ProcessNode* process_node : - graph_->GetAllProcessNodes()) - SendProcessNotification(process_node, true); - - for (const performance_manager::PageNode* page_node : - graph_->GetAllPageNodes()) { - SendPageNotification(page_node, true); - StartPageFaviconRequest(page_node); - - // Dispatch preorder frame notifications. - for (const performance_manager::FrameNode* main_frame_node : - page_node->GetMainFrameNodes()) { - ForFrameAndOffspring( - main_frame_node, - [this](const performance_manager::FrameNode* frame_node) { - this->SendFrameNotification(frame_node, true); - this->StartFrameFaviconRequest(frame_node); - }); - } - } - - for (const performance_manager::WorkerNode* worker_node : - graph_->GetAllWorkerNodes()) { - SendWorkerNotification(worker_node, true); - } + SendNotificationToAllNodes(/* created = */ true); + + // It is entirely possible for there to be circular link references between + // nodes that already existed at the point this object was created (the loop + // was closed after the two nodes themselves were created). We don't have the + // exact order of historical events that led to the current graph state, so we + // simply fire off a node changed notification for all nodes after the node + // creation. This ensures that all targets exist the second time through, and + // any loops are closed. Afterwards any newly created loops will be properly + // maintained as node creation/destruction/link events will be fed to the + // graph in the proper order. + SendNotificationToAllNodes(/* created = */ false); // Subscribe to subsequent notifications. graph_->AddFrameNodeObserver(this); @@ -265,8 +251,8 @@ void DiscardsGraphDumpImpl::OnTakenFromGraph( // The favicon helper must be deleted on the UI thread. if (favicon_request_helper_) { - base::DeleteSoon(FROM_HERE, {content::BrowserThread::UI}, - std::move(favicon_request_helper_)); + content::GetUIThreadTaskRunner({})->DeleteSoon( + FROM_HERE, std::move(favicon_request_helper_)); } graph_ = nullptr; @@ -305,6 +291,14 @@ void DiscardsGraphDumpImpl::OnBeforePageNodeRemoved( RemoveNode(page_node); } +void DiscardsGraphDumpImpl::OnOpenerFrameNodeChanged( + const performance_manager::PageNode* page_node, + const performance_manager::FrameNode*, + OpenedType) { + DCHECK(HasNode(page_node)); + SendPageNotification(page_node, false); +} + void DiscardsGraphDumpImpl::OnFaviconUpdated( const performance_manager::PageNode* page_node) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -391,13 +385,19 @@ void DiscardsGraphDumpImpl::RemoveNode(const performance_manager::Node* node) { DCHECK_EQ(1u, erased); } +bool DiscardsGraphDumpImpl::HasNode( + const performance_manager::Node* node) const { + return node_ids_.find(node) != node_ids_.end(); +} + int64_t DiscardsGraphDumpImpl::GetNodeId( - const performance_manager::Node* node) { + const performance_manager::Node* node) const { if (node == nullptr) return 0; - DCHECK(node_ids_.find(node) != node_ids_.end()); - return node_ids_[node].GetUnsafeValue(); + auto it = node_ids_.find(node); + DCHECK(it != node_ids_.end()); + return it->second.GetUnsafeValue(); } DiscardsGraphDumpImpl::FaviconRequestHelper* @@ -416,8 +416,8 @@ void DiscardsGraphDumpImpl::StartPageFaviconRequest( if (!page_node->GetMainFrameUrl().is_valid()) return; - base::PostTask( - FROM_HERE, {content::BrowserThread::UI}, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&FaviconRequestHelper::RequestFavicon, base::Unretained(EnsureFaviconRequestHelper()), page_node->GetMainFrameUrl(), @@ -429,14 +429,44 @@ void DiscardsGraphDumpImpl::StartFrameFaviconRequest( if (!frame_node->GetURL().is_valid()) return; - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&FaviconRequestHelper::RequestFavicon, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&FaviconRequestHelper::RequestFavicon, base::Unretained(EnsureFaviconRequestHelper()), frame_node->GetURL(), frame_node->GetPageNode()->GetContentsProxy(), GetNodeId(frame_node))); } +void DiscardsGraphDumpImpl::SendNotificationToAllNodes(bool created) { + for (const performance_manager::ProcessNode* process_node : + graph_->GetAllProcessNodes()) + SendProcessNotification(process_node, created); + + for (const performance_manager::PageNode* page_node : + graph_->GetAllPageNodes()) { + SendPageNotification(page_node, created); + if (created) + StartPageFaviconRequest(page_node); + + // Dispatch preorder frame notifications. + for (const performance_manager::FrameNode* main_frame_node : + page_node->GetMainFrameNodes()) { + ForFrameAndOffspring( + main_frame_node, + [this, created](const performance_manager::FrameNode* frame_node) { + this->SendFrameNotification(frame_node, created); + if (created) + this->StartFrameFaviconRequest(frame_node); + }); + } + } + + for (const performance_manager::WorkerNode* worker_node : + graph_->GetAllWorkerNodes()) { + SendWorkerNotification(worker_node, created); + } +} + void DiscardsGraphDumpImpl::SendFrameNotification( const performance_manager::FrameNode* frame, bool created) { @@ -459,10 +489,11 @@ void DiscardsGraphDumpImpl::SendFrameNotification( frame_info->description_json = ToJSON(graph_->GetNodeDataDescriberRegistry()->DescribeNodeData(frame)); - if (created) + if (created) { change_subscriber_->FrameCreated(std::move(frame_info)); - else + } else { change_subscriber_->FrameChanged(std::move(frame_info)); + } } void DiscardsGraphDumpImpl::SendPageNotification( @@ -474,6 +505,7 @@ void DiscardsGraphDumpImpl::SendPageNotification( page_info->id = GetNodeId(page_node); page_info->main_frame_url = page_node->GetMainFrameUrl(); + page_info->opener_frame_id = GetNodeId(page_node->GetOpenerFrameNode()); page_info->description_json = ToJSON( graph_->GetNodeDataDescriberRegistry()->DescribeNodeData(page_node)); diff --git a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h index 893d7f3faec..de771acc112 100644 --- a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h +++ b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl.h @@ -99,6 +99,9 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump, void OnHadFormInteractionChanged( const performance_manager::FrameNode* frame_node) override {} // Ignored. + void OnIsAudibleChanged( + const performance_manager::FrameNode* frame_node) override {} + // Ignored. void OnFirstContentfulPaint( const performance_manager::FrameNode* frame_node, base::TimeDelta time_since_navigation_start) override {} @@ -107,6 +110,10 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump, void OnPageNodeAdded(const performance_manager::PageNode* page_node) override; void OnBeforePageNodeRemoved( const performance_manager::PageNode* page_node) override; + void OnOpenerFrameNodeChanged( + const performance_manager::PageNode* page_node, + const performance_manager::FrameNode* previous_opener, + OpenedType previous_opened_type) override; void OnIsVisibleChanged( const performance_manager::PageNode* page_node) override {} // Ignored. void OnIsAudibleChanged( @@ -186,7 +193,8 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump, void AddNode(const performance_manager::Node* node); void RemoveNode(const performance_manager::Node* node); - int64_t GetNodeId(const performance_manager::Node* node); + bool HasNode(const performance_manager::Node* node) const; + int64_t GetNodeId(const performance_manager::Node* node) const; FaviconRequestHelper* EnsureFaviconRequestHelper(); @@ -194,6 +202,7 @@ class DiscardsGraphDumpImpl : public discards::mojom::GraphDump, void StartFrameFaviconRequest( const performance_manager::FrameNode* frame_node); + void SendNotificationToAllNodes(bool created); void SendFrameNotification(const performance_manager::FrameNode* frame, bool created); void SendPageNotification(const performance_manager::PageNode* page, diff --git a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc index 32c220349fb..e554f7d7a8d 100644 --- a/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc +++ b/chromium/chrome/browser/ui/webui/discards/graph_dump_impl_unittest.cc @@ -212,8 +212,9 @@ TEST_F(DiscardsGraphDumpImplTest, ChangeStream) { task_environment.RunUntilIdle(); - // Validate that the initial graph state dump is complete. - EXPECT_EQ(0u, change_stream.num_changes()); + // Validate that the initial graph state dump is complete. Note that there is + // an update for each node as part of the initial state dump. + EXPECT_EQ(8u, change_stream.num_changes()); EXPECT_EQ(8u, change_stream.id_set().size()); EXPECT_EQ(2u, change_stream.process_map().size()); @@ -277,7 +278,7 @@ TEST_F(DiscardsGraphDumpImplTest, ChangeStream) { task_environment.RunUntilIdle(); // Main frame navigation results in a notification for the url. - EXPECT_EQ(1u, change_stream.num_changes()); + EXPECT_EQ(9u, change_stream.num_changes()); EXPECT_FALSE(base::Contains(change_stream.id_set(), child_frame_id)); const auto main_page_it = change_stream.page_map().find( diff --git a/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc b/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc index 2a2e43e6b6b..a37d09a30f4 100644 --- a/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/domain_reliability_internals_ui.cc @@ -13,6 +13,7 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" DomainReliabilityInternalsUI::DomainReliabilityInternalsUI( @@ -20,7 +21,8 @@ DomainReliabilityInternalsUI::DomainReliabilityInternalsUI( : content::WebUIController(web_ui) { content::WebUIDataSource* html_source = content::WebUIDataSource::Create( chrome::kChromeUIDomainReliabilityInternalsHost); - html_source->OverrideContentSecurityPolicyScriptSrc( + html_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); html_source->AddResourcePath("domain_reliability_internals.css", IDR_DOMAIN_RELIABILITY_INTERNALS_CSS); diff --git a/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc b/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc index e63f09137ac..7ca1ee5e2e3 100644 --- a/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/download_internals/download_internals_ui.cc @@ -13,13 +13,15 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" DownloadInternalsUI::DownloadInternalsUI(content::WebUI* web_ui) : content::WebUIController(web_ui) { // chrome://download-internals source. content::WebUIDataSource* html_source = content::WebUIDataSource::Create(chrome::kChromeUIDownloadInternalsHost); - html_source->OverrideContentSecurityPolicyScriptSrc( + html_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); // Required resources. diff --git a/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc b/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc index 1bc52afd2e8..c63615e731e 100644 --- a/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc +++ b/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc @@ -16,8 +16,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" -#include "base/value_conversions.h" -#include "base/values.h" #include "chrome/browser/download/download_crx_util.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_query.h" diff --git a/chromium/chrome/browser/ui/webui/extensions/extensions_internals_source.cc b/chromium/chrome/browser/ui/webui/extensions/extensions_internals_source.cc index c60227d8226..e93f7e8c7aa 100644 --- a/chromium/chrome/browser/ui/webui/extensions/extensions_internals_source.cc +++ b/chromium/chrome/browser/ui/webui/extensions/extensions_internals_source.cc @@ -20,8 +20,10 @@ #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/activity.h" +#include "extensions/browser/disable_reason.h" #include "extensions/browser/event_listener_map.h" #include "extensions/browser/event_router.h" +#include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/process_manager.h" #include "extensions/common/manifest_handlers/permissions_parser.h" @@ -121,6 +123,46 @@ base::Value CreationFlagsToList(int creation_flags) { return flags_value; } +base::Value DisableReasonsToList(int disable_reasons) { + base::Value disable_reasons_value(base::Value::Type::LIST); + if (disable_reasons & + extensions::disable_reason::DISABLE_PERMISSIONS_INCREASE) { + disable_reasons_value.Append("DISABLE_PERMISSIONS_INCREASE"); + } + if (disable_reasons & extensions::disable_reason::DISABLE_RELOAD) + disable_reasons_value.Append("DISABLE_RELOAD"); + if (disable_reasons & + extensions::disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT) { + disable_reasons_value.Append("DISABLE_UNSUPPORTED_REQUIREMENT"); + } + if (disable_reasons & extensions::disable_reason::DISABLE_SIDELOAD_WIPEOUT) + disable_reasons_value.Append("DISABLE_SIDELOAD_WIPEOUT"); + if (disable_reasons & extensions::disable_reason::DISABLE_NOT_VERIFIED) + disable_reasons_value.Append("DISABLE_NOT_VERIFIED"); + if (disable_reasons & extensions::disable_reason::DISABLE_GREYLIST) + disable_reasons_value.Append("DISABLE_GREYLIST"); + if (disable_reasons & extensions::disable_reason::DISABLE_CORRUPTED) + disable_reasons_value.Append("DISABLE_CORRUPTED"); + if (disable_reasons & extensions::disable_reason::DISABLE_REMOTE_INSTALL) + disable_reasons_value.Append("DISABLE_REMOTE_INSTALL"); + if (disable_reasons & extensions::disable_reason::DISABLE_EXTERNAL_EXTENSION) + disable_reasons_value.Append("DISABLE_EXTERNAL_EXTENSION"); + if (disable_reasons & + extensions::disable_reason::DISABLE_UPDATE_REQUIRED_BY_POLICY) { + disable_reasons_value.Append("DISABLE_UPDATE_REQUIRED_BY_POLICY"); + } + if (disable_reasons & + extensions::disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED) { + disable_reasons_value.Append("DISABLE_CUSTODIAN_APPROVAL_REQUIRED"); + } + if (disable_reasons & extensions::disable_reason::DISABLE_BLOCKED_BY_POLICY) + disable_reasons_value.Append("DISABLE_BLOCKED_BY_POLICY"); + if (disable_reasons & + extensions::disable_reason::DISABLE_REMOTELY_FOR_MALWARE) { + disable_reasons_value.Append("DISABLE_REMOTELY_FOR_MALWARE"); + } + return disable_reasons_value; +} // The JSON we generate looks like this: // Note: // - tab_specific permissions can have 0 or more DICT entries with each tab id @@ -133,6 +175,7 @@ base::Value CreationFlagsToList(int creation_flags) { // // [ { // "creation_flags": [ "ALLOW_FILE_ACCESS", "FROM_WEBSTORE" ], +// "disable_reasons": ["DISABLE_USER_ACTION"], // "event_listeners": { // "count": 2, // "events": [ { @@ -190,6 +233,8 @@ base::Value CreationFlagsToList(int creation_flags) { // DICT // "creation_flags": LIST // STRING +// "disable_reasons": LIST +// STRING // "event_listeners": DICT // "count": INT // "listeners": LIST @@ -251,6 +296,7 @@ constexpr base::StringPiece kEventsListenersKey = "event_listeners"; constexpr base::StringPiece kExtraDataKey = "extra_data"; constexpr base::StringPiece kFilterKey = "filter"; constexpr base::StringPiece kInternalsCreationFlagsKey = "creation_flags"; +constexpr base::StringPiece kInternalsDisableReasonsKey = "disable_reasons"; constexpr base::StringPiece kInternalsIdKey = "id"; constexpr base::StringPiece kInternalsNameKey = "name"; constexpr base::StringPiece kInternalsVersionKey = "version"; @@ -389,7 +435,7 @@ void AddEventListenerData(extensions::EventRouter* event_router, base::Value(listener_entry->listener_url().spec())); // Add the filter if one exists. base::Value* const filter = listener_entry->filter(); - if (filter != nullptr) { + if (filter) { listener_data.SetKey(kFilterKey, filter->Clone()); } listeners_list.Append(std::move(listener_data)); @@ -448,6 +494,7 @@ std::string ExtensionsInternalsSource::WriteToString() const { ->GenerateInstalledExtensionsSet(); extensions::ProcessManager* process_manager = extensions::ProcessManager::Get(profile_); + extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); base::Value data(base::Value::Type::LIST); for (const auto& extension : *extensions) { base::Value extension_data(base::Value::Type::DICTIONARY); @@ -455,6 +502,9 @@ std::string ExtensionsInternalsSource::WriteToString() const { extension_data.SetKey(kInternalsCreationFlagsKey, CreationFlagsToList(extension->creation_flags())); extension_data.SetKey( + kInternalsDisableReasonsKey, + DisableReasonsToList(prefs->GetDisableReasons(extension->id()))); + extension_data.SetKey( kKeepaliveKey, FormatKeepaliveData(process_manager, extension.get())); extension_data.SetKey(kLocationKey, base::Value(LocationToString(extension->location()))); diff --git a/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc index 2f41efa7f34..0b8e0ffe833 100644 --- a/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chromium/chrome/browser/ui/webui/extensions/extensions_ui.cc @@ -40,6 +40,7 @@ #include "extensions/common/extension_features.h" #include "extensions/common/extension_urls.h" #include "extensions/grit/extensions_browser_resources.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/web_ui_util.h" @@ -382,7 +383,8 @@ ExtensionsUI::ExtensionsUI(content::WebUI* web_ui) // Need to allow <object> elements so that the <extensionoptions> browser // plugin can be loaded within chrome://extensions. - source->OverrideContentSecurityPolicyObjectSrc("object-src 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ObjectSrc, "object-src 'self';"); content::WebUIDataSource::Add(profile, source); diff --git a/chromium/chrome/browser/ui/webui/flags_ui.cc b/chromium/chrome/browser/ui/webui/flags_ui.cc index 92050e17926..9cfe2e6ab37 100644 --- a/chromium/chrome/browser/ui/webui/flags_ui.cc +++ b/chromium/chrome/browser/ui/webui/flags_ui.cc @@ -33,6 +33,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" @@ -62,7 +63,8 @@ namespace { content::WebUIDataSource* CreateFlagsUIHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIFlagsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->AddString(flags_ui::kVersion, version_info::GetVersionNumber()); diff --git a/chromium/chrome/browser/ui/webui/help/test_version_updater.cc b/chromium/chrome/browser/ui/webui/help/test_version_updater.cc index d10cc076fae..b159078b28a 100644 --- a/chromium/chrome/browser/ui/webui/help/test_version_updater.cc +++ b/chromium/chrome/browser/ui/webui/help/test_version_updater.cc @@ -10,5 +10,6 @@ TestVersionUpdater::~TestVersionUpdater() = default; void TestVersionUpdater::CheckForUpdate(const StatusCallback& callback, const PromoteCallback&) { - callback.Run(status_, progress_, rollback_, version_, update_size_, message_); + callback.Run(status_, progress_, rollback_, powerwash_, version_, + update_size_, message_); } diff --git a/chromium/chrome/browser/ui/webui/help/test_version_updater.h b/chromium/chrome/browser/ui/webui/help/test_version_updater.h index 2db702d317a..e07e61a3ae2 100644 --- a/chromium/chrome/browser/ui/webui/help/test_version_updater.h +++ b/chromium/chrome/browser/ui/webui/help/test_version_updater.h @@ -42,6 +42,7 @@ class TestVersionUpdater : public VersionUpdater { Status status_ = Status::UPDATED; int progress_ = 0; bool rollback_ = false; + bool powerwash_ = false; std::string version_; int64_t update_size_ = 0; base::string16 message_; diff --git a/chromium/chrome/browser/ui/webui/help/version_updater.h b/chromium/chrome/browser/ui/webui/help/version_updater.h index de48fe833ee..34f7adaa37d 100644 --- a/chromium/chrome/browser/ui/webui/help/version_updater.h +++ b/chromium/chrome/browser/ui/webui/help/version_updater.h @@ -58,6 +58,7 @@ class VersionUpdater { // |progress| should only be non-zero for the UPDATING state. // |rollback| indicates whether the update is actually a rollback, which // requires wiping the device upon reboot. + // |powerwash| indicates whether the device will be wiped on reboot. // |version| is the version of the available update and should be empty string // when update is not available. // |update_size| is the size of the available update in bytes and should be 0 @@ -66,6 +67,7 @@ class VersionUpdater { typedef base::Callback<void(Status status, int progress, bool rollback, + bool powerwash, const std::string& version, int64_t update_size, const base::string16& message)> diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_basic.cc b/chromium/chrome/browser/ui/webui/help/version_updater_basic.cc index 93e3f41a76d..2a4c334e2ea 100644 --- a/chromium/chrome/browser/ui/webui/help/version_updater_basic.cc +++ b/chromium/chrome/browser/ui/webui/help/version_updater_basic.cc @@ -13,7 +13,8 @@ void VersionUpdaterBasic::CheckForUpdate( const Status status = UpgradeDetector::GetInstance()->notify_upgrade() ? NEARLY_UPDATED : DISABLED; - status_callback.Run(status, 0, false, std::string(), 0, base::string16()); + status_callback.Run(status, 0, false, false, std::string(), 0, + base::string16()); } VersionUpdater* VersionUpdater::Create(content::WebContents* web_contents) { diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc b/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc index 23166d7d304..0a0225fee0c 100644 --- a/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/help/version_updater_chromeos.cc @@ -51,12 +51,12 @@ enum NetworkStatus { const bool kDefaultAutoUpdateDisabled = false; NetworkStatus GetNetworkStatus(bool interactive, - const chromeos::NetworkState* network) { + const chromeos::NetworkState* network, + bool metered) { if (!network || !network->IsConnectedState()) // Offline state. return NETWORK_STATUS_OFFLINE; - // Treats tethered networks as cellular networks. - if (network->IsUsingMobileData() && + if (metered && !help_utils_chromeos::IsUpdateOverCellularAllowed(interactive)) { return NETWORK_STATUS_DISALLOWED; } @@ -76,10 +76,11 @@ bool IsAutoUpdateDisabled() { return update_disabled; } -base::string16 GetConnectionTypeAsUTF16(const chromeos::NetworkState* network) { +base::string16 GetConnectionTypeAsUTF16(const chromeos::NetworkState* network, + bool metered) { const std::string type = network->type(); if (chromeos::NetworkTypePattern::WiFi().MatchesType(type)) { - if (network->IsUsingMobileData()) + if (metered) return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_METERED_WIFI); return l10n_util::GetStringUTF16(IDS_NETWORK_TYPE_WIFI); } @@ -99,7 +100,8 @@ base::string16 GetConnectionTypeAsUTF16(const chromeos::NetworkState* network) { bool EnsureCanUpdate(bool interactive, const VersionUpdater::StatusCallback& callback) { if (IsAutoUpdateDisabled()) { - callback.Run(VersionUpdater::DISABLED_BY_ADMIN, 0, false, std::string(), 0, + callback.Run(VersionUpdater::DISABLED_BY_ADMIN, 0, false, false, + std::string(), 0, l10n_util::GetStringUTF16(IDS_UPGRADE_DISABLED_BY_POLICY)); return false; } @@ -108,19 +110,19 @@ bool EnsureCanUpdate(bool interactive, chromeos::NetworkHandler::Get()->network_state_handler(); const chromeos::NetworkState* network = network_state_handler->DefaultNetwork(); - + const bool metered = network_state_handler->default_network_is_metered(); // Don't allow an update if we're currently offline or connected // to a network for which updates are disallowed. - NetworkStatus status = GetNetworkStatus(interactive, network); + NetworkStatus status = GetNetworkStatus(interactive, network, metered); if (status == NETWORK_STATUS_OFFLINE) { - callback.Run(VersionUpdater::FAILED_OFFLINE, 0, false, std::string(), 0, - l10n_util::GetStringUTF16(IDS_UPGRADE_OFFLINE)); + callback.Run(VersionUpdater::FAILED_OFFLINE, 0, false, false, std::string(), + 0, l10n_util::GetStringUTF16(IDS_UPGRADE_OFFLINE)); return false; } else if (status == NETWORK_STATUS_DISALLOWED) { base::string16 message = l10n_util::GetStringFUTF16( - IDS_UPGRADE_DISALLOWED, GetConnectionTypeAsUTF16(network)); + IDS_UPGRADE_DISALLOWED, GetConnectionTypeAsUTF16(network, metered)); callback.Run(VersionUpdater::FAILED_CONNECTION_TYPE_DISALLOWED, 0, false, - std::string(), 0, message); + false, std::string(), 0, message); return false; } @@ -214,7 +216,7 @@ void VersionUpdaterCros::OnSetUpdateOverCellularOneTimePermission( // TODO(https://crbug.com/927452): invoke callback to signal about page to // show appropriate error message. LOG(ERROR) << "Error setting update over cellular one time permission."; - callback_.Run(VersionUpdater::FAILED, 0, false, std::string(), 0, + callback_.Run(VersionUpdater::FAILED, 0, false, false, std::string(), 0, base::string16()); } } @@ -318,8 +320,8 @@ void VersionUpdaterCros::UpdateStatusChanged( NOTREACHED(); } - callback_.Run(my_status, progress, status.is_enterprise_rollback(), version, - size, message); + callback_.Run(my_status, progress, status.is_enterprise_rollback(), + status.will_powerwash_after_reboot(), version, size, message); last_operation_ = status.current_operation(); if (check_for_update_when_idle_ && @@ -333,5 +335,5 @@ void VersionUpdaterCros::OnUpdateCheck( // If version updating is not implemented, this binary is the most up-to-date // possible with respect to automatic updating. if (result == UpdateEngineClient::UPDATE_RESULT_NOTIMPLEMENTED) - callback_.Run(UPDATED, 0, false, std::string(), 0, base::string16()); + callback_.Run(UPDATED, 0, false, false, std::string(), 0, base::string16()); } diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc b/chromium/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc index 5115ce9c60a..999a1a67722 100644 --- a/chromium/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc +++ b/chromium/chrome/browser/ui/webui/help/version_updater_chromeos_unittest.cc @@ -33,6 +33,7 @@ namespace { void CheckNotification(VersionUpdater::Status /* status */, int /* progress */, bool /* rollback */, + bool /* powerwash */, const std::string& /* version */, int64_t /* size */, const base::string16& /* message */) {} diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm b/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm index 4550497b5ab..6680e23b73e 100644 --- a/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm +++ b/chromium/chrome/browser/ui/webui/help/version_updater_mac.mm @@ -108,7 +108,7 @@ void VersionUpdaterMac::CheckForUpdate( } else { // There is no glue, or the application is on a read-only filesystem. // Updates and promotions are impossible. - status_callback_.Run(DISABLED, 0, false, std::string(), 0, + status_callback_.Run(DISABLED, 0, false, false, std::string(), 0, base::string16()); } } @@ -231,7 +231,7 @@ void VersionUpdaterMac::UpdateStatus(NSDictionary* dictionary) { } if (!status_callback_.is_null()) - status_callback_.Run(status, 0, false, std::string(), 0, message); + status_callback_.Run(status, 0, false, false, std::string(), 0, message); PromotionState promotion_state; if (!promote_callback_.is_null()) { diff --git a/chromium/chrome/browser/ui/webui/help/version_updater_win.cc b/chromium/chrome/browser/ui/webui/help/version_updater_win.cc index f77d46664fd..be910614a29 100644 --- a/chromium/chrome/browser/ui/webui/help/version_updater_win.cc +++ b/chromium/chrome/browser/ui/webui/help/version_updater_win.cc @@ -31,7 +31,7 @@ void VersionUpdaterWin::CheckForUpdate(const StatusCallback& callback, // There is no supported integration with Google Update for Chromium. callback_ = callback; - callback_.Run(CHECKING, 0, false, std::string(), 0, base::string16()); + callback_.Run(CHECKING, 0, false, false, std::string(), 0, base::string16()); DoBeginUpdateCheck(false /* !install_update_if_possible */); } @@ -52,18 +52,20 @@ void VersionUpdaterWin::OnUpdateCheckComplete( // Notify the caller that the update is now beginning and initiate it. DoBeginUpdateCheck(true /* install_update_if_possible */); - callback_.Run(UPDATING, 0, false, std::string(), 0, base::string16()); + callback_.Run(UPDATING, 0, false, false, std::string(), 0, base::string16()); } void VersionUpdaterWin::OnUpgradeProgress(int progress, const base::string16& new_version) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - callback_.Run(UPDATING, progress, false, std::string(), 0, base::string16()); + callback_.Run(UPDATING, progress, false, false, std::string(), 0, + base::string16()); } void VersionUpdaterWin::OnUpgradeComplete(const base::string16& new_version) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - callback_.Run(NEARLY_UPDATED, 0, false, std::string(), 0, base::string16()); + callback_.Run(NEARLY_UPDATED, 0, false, false, std::string(), 0, + base::string16()); } void VersionUpdaterWin::OnError(GoogleUpdateErrorCode error_code, @@ -94,7 +96,7 @@ void VersionUpdaterWin::OnError(GoogleUpdateErrorCode error_code, } break; } - callback_.Run(status, 0, false, std::string(), 0, message); + callback_.Run(status, 0, false, false, std::string(), 0, message); } void VersionUpdaterWin::DoBeginUpdateCheck(bool install_update_if_possible) { @@ -107,7 +109,7 @@ void VersionUpdaterWin::DoBeginUpdateCheck(bool install_update_if_possible) { void VersionUpdaterWin::OnPendingRestartCheck(bool is_update_pending_restart) { callback_.Run(is_update_pending_restart ? NEARLY_UPDATED : UPDATED, 0, false, - std::string(), 0, base::string16()); + false, std::string(), 0, base::string16()); } VersionUpdater* VersionUpdater::Create(content::WebContents* web_contents) { diff --git a/chromium/chrome/browser/ui/webui/internals/internals_ui.cc b/chromium/chrome/browser/ui/webui/internals/internals_ui.cc new file mode 100644 index 00000000000..4a5abeb02fc --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/internals_ui.cc @@ -0,0 +1,59 @@ +// Copyright 2020 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/internals/internals_ui.h" + +#include "chrome/common/url_constants.h" +#include "chrome/grit/dev_ui_browser_resources.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_controller.h" +#include "content/public/browser/web_ui_data_source.h" + +#if defined(OS_ANDROID) +#include "chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.h" +#else +#include "chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h" +#include "mojo/public/cpp/bindings/self_owned_receiver.h" +#endif // defined(OS_ANDROID) + +InternalsUI::InternalsUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) { + profile_ = Profile::FromWebUI(web_ui); + source_ = content::WebUIDataSource::Create(chrome::kChromeUIInternalsHost); + + // Add your sub-URL internals WebUI here. +#if defined(OS_ANDROID) + // chrome://internals/query-tiles + AddQueryTilesInternals(web_ui); +#else + // chrome://internals/web-app + WebAppInternalsPageHandlerImpl::AddPageResources(source_); +#endif // defined(OS_ANDROID) + + content::WebUIDataSource::Add(profile_, source_); +} + +InternalsUI::~InternalsUI() = default; + +#if defined(OS_ANDROID) +void InternalsUI::AddQueryTilesInternals(content::WebUI* web_ui) { + source_->AddResourcePath("query_tiles_internals.js", + IDR_QUERY_TILES_INTERNALS_JS); + source_->AddResourcePath("query_tiles_internals_browser_proxy.js", + IDR_QUERY_TILES_INTERNALS_BROWSER_PROXY_JS); + source_->AddResourcePath("query-tiles", IDR_QUERY_TILES_INTERNALS_HTML); + web_ui->AddMessageHandler( + std::make_unique<QueryTilesInternalsUIMessageHandler>(profile_)); +} +#else // defined(OS_ANDROID) +void InternalsUI::BindInterface( + mojo::PendingReceiver<mojom::web_app_internals::WebAppInternalsPageHandler> + receiver) { + mojo::MakeSelfOwnedReceiver( + std::make_unique<WebAppInternalsPageHandlerImpl>(profile_), + std::move(receiver)); +} +#endif // defined(OS_ANDROID) + +WEB_UI_CONTROLLER_TYPE_IMPL(InternalsUI) diff --git a/chromium/chrome/browser/ui/webui/internals/internals_ui.h b/chromium/chrome/browser/ui/webui/internals/internals_ui.h new file mode 100644 index 00000000000..7339b46df97 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/internals_ui.h @@ -0,0 +1,48 @@ +// Copyright 2020 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_INTERNALS_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_INTERNALS_INTERNALS_UI_H_ + +#include "build/build_config.h" +#include "chrome/browser/profiles/profile.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/webui/mojo_web_ui_controller.h" + +#if !defined(OS_ANDROID) +// gn check doesn't understand "#if !defined(OS_ANDROID)" and fails this +// non-Android include on Android. +#include "chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom.h" // nogncheck +#endif + +namespace content { +class WebUI; +} // namespace content + +// Client could put debug WebUI as sub-URL under chrome://internals/. +// e.g. chrome://internals/your-feature. +class InternalsUI : public ui::MojoWebUIController { + public: + explicit InternalsUI(content::WebUI* web_ui); + ~InternalsUI() override; + +#if !defined(OS_ANDROID) + void BindInterface( + mojo::PendingReceiver< + mojom::web_app_internals::WebAppInternalsPageHandler> receiver); +#endif // !defined(OS_ANDROID) + + private: + WEB_UI_CONTROLLER_TYPE_DECL(); + +#if defined(OS_ANDROID) + // Add resources and message handler for chrome://internals/query-tiles. + void AddQueryTilesInternals(content::WebUI* web_ui); +#endif // defined(OS_ANDROID) + + Profile* profile_; + content::WebUIDataSource* source_; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_INTERNALS_INTERNALS_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/internals/query_tiles/OWNERS b/chromium/chrome/browser/ui/webui/internals/query_tiles/OWNERS new file mode 100644 index 00000000000..593e722800d --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/query_tiles/OWNERS @@ -0,0 +1 @@ +file://components/query_tiles/OWNERS diff --git a/chromium/chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.cc b/chromium/chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.cc new file mode 100644 index 00000000000..c0bbb708bd5 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.cc @@ -0,0 +1,70 @@ +// Copyright 2020 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/internals/query_tiles/query_tiles_internals_ui_message_handler.h" + +#include <memory> +#include <string> +#include <utility> + +#include "base/bind.h" +#include "base/values.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_key.h" +#include "chrome/browser/query_tiles/tile_service_factory.h" +#include "components/query_tiles/tile_service.h" +#include "content/public/browser/web_ui.h" + +QueryTilesInternalsUIMessageHandler::QueryTilesInternalsUIMessageHandler( + Profile* profile) + : tile_service_(query_tiles::TileServiceFactory::GetForKey( + profile->GetProfileKey())) { + DCHECK(tile_service_); +} + +QueryTilesInternalsUIMessageHandler::~QueryTilesInternalsUIMessageHandler() = + default; + +void QueryTilesInternalsUIMessageHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "startFetch", base::BindRepeating( + &QueryTilesInternalsUIMessageHandler::HandleStartFetch, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "purgeDb", + base::BindRepeating(&QueryTilesInternalsUIMessageHandler::HandlePurgeDb, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "getServiceStatus", + base::Bind(&QueryTilesInternalsUIMessageHandler::HandleGetServiceStatus, + weak_ptr_factory_.GetWeakPtr())); + + web_ui()->RegisterMessageCallback( + "getTileData", + base::Bind(&QueryTilesInternalsUIMessageHandler::HandleGetTileData, + weak_ptr_factory_.GetWeakPtr())); +} + +void QueryTilesInternalsUIMessageHandler::HandleGetTileData( + const base::ListValue* args) { + NOTIMPLEMENTED(); +} + +void QueryTilesInternalsUIMessageHandler::HandleGetServiceStatus( + const base::ListValue* args) { + NOTIMPLEMENTED(); +} + +void QueryTilesInternalsUIMessageHandler::HandleStartFetch( + const base::ListValue* args) { + AllowJavascript(); + tile_service_->StartFetchForTiles(false /*is_from_reduce_mode*/, + base::BindOnce([](bool reschedule) {})); +} + +void QueryTilesInternalsUIMessageHandler::HandlePurgeDb( + const base::ListValue* args) { + tile_service_->PurgeDb(); +} diff --git a/chromium/chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.h b/chromium/chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.h new file mode 100644 index 00000000000..1bd47eb5935 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/query_tiles/query_tiles_internals_ui_message_handler.h @@ -0,0 +1,43 @@ +// Copyright 2020 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_INTERNALS_QUERY_TILES_QUERY_TILES_INTERNALS_UI_MESSAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_INTERNALS_QUERY_TILES_QUERY_TILES_INTERNALS_UI_MESSAGE_HANDLER_H_ + +#include "base/macros.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace base { +class ListValue; +} // namespace base + +class Profile; + +namespace query_tiles { +class TileService; +} + +class QueryTilesInternalsUIMessageHandler + : public content::WebUIMessageHandler { + public: + explicit QueryTilesInternalsUIMessageHandler(Profile* profile); + ~QueryTilesInternalsUIMessageHandler() override; + + // content::WebUIMessageHandler implementation. + void RegisterMessages() override; + + private: + void HandleGetServiceStatus(const base::ListValue* args); + void HandleGetTileData(const base::ListValue* args); + void HandleStartFetch(const base::ListValue* args); + void HandlePurgeDb(const base::ListValue* args); + + query_tiles::TileService* tile_service_; + + base::WeakPtrFactory<QueryTilesInternalsUIMessageHandler> weak_ptr_factory_{ + this}; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_INTERNALS_QUERY_TILES_QUERY_TILES_INTERNALS_UI_MESSAGE_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/internals/web_app/BUILD.gn b/chromium/chrome/browser/ui/webui/internals/web_app/BUILD.gn new file mode 100644 index 00000000000..70ca6d1bce8 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/web_app/BUILD.gn @@ -0,0 +1,9 @@ +# Copyright 2020 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("mojo_bindings") { + sources = [ "web_app_internals.mojom" ] +} diff --git a/chromium/chrome/browser/ui/webui/internals/web_app/OWNERS b/chromium/chrome/browser/ui/webui/internals/web_app/OWNERS new file mode 100644 index 00000000000..a74f1031167 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/web_app/OWNERS @@ -0,0 +1,4 @@ +file://chrome/browser/web_applications/OWNERS + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS diff --git a/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom b/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom new file mode 100644 index 00000000000..0a05fcafaca --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom @@ -0,0 +1,30 @@ +// Copyright 2020 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 mojom.web_app_internals; + +struct WebApp { + // The web app's ID. + string id; + + // The web app's name. + string name; + + // Debugging info about the web app's internal state. + string debug_info; +}; + +// Provides access to browser side internal information about installed web apps +// (also known as PWAs) for chrome://internals/web-app. +interface WebAppInternalsPageHandler { + // Whether the BMO web app backend is enabled. + IsBmoEnabled() => (bool is_bmo_enabled); + + // Returns details of all the installed web apps for the current profile. + GetWebApps() => (array<WebApp> web_app_list); + + // Returns the prefs used for keeping track of non-user installed web apps. + GetExternallyInstalledWebAppPrefs() => + (string externally_installed_web_app_prefs); +}; diff --git a/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc b/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc new file mode 100644 index 00000000000..79a536d5d9b --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.cc @@ -0,0 +1,68 @@ +// Copyright 2017 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 <sstream> + +#include "chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/components/web_app_provider_base.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_registrar.h" +#include "chrome/common/chrome_features.h" +#include "chrome/common/pref_names.h" +#include "chrome/grit/dev_ui_browser_resources.h" +#include "components/prefs/pref_service.h" +#include "content/public/browser/web_ui_data_source.h" + +WebAppInternalsPageHandlerImpl::WebAppInternalsPageHandlerImpl(Profile* profile) + : profile_(profile) {} + +WebAppInternalsPageHandlerImpl::~WebAppInternalsPageHandlerImpl() = default; + +void WebAppInternalsPageHandlerImpl::AddPageResources( + content::WebUIDataSource* source) { + source->AddResourcePath("web_app_internals.mojom-lite.js", + IDR_WEB_APP_INTERNALS_MOJOM_LITE_JS); + source->AddResourcePath("web_app_internals.js", IDR_WEB_APP_INTERNALS_JS); + source->AddResourcePath("web-app", IDR_WEB_APP_INTERNALS_HTML); +} + +void WebAppInternalsPageHandlerImpl::IsBmoEnabled( + IsBmoEnabledCallback callback) { + std::move(callback).Run( + base::FeatureList::IsEnabled(features::kDesktopPWAsWithoutExtensions)); +} + +void WebAppInternalsPageHandlerImpl::GetWebApps(GetWebAppsCallback callback) { + auto* provider = web_app::WebAppProviderBase::GetProviderBase(profile_); + if (!provider) + std::move(callback).Run({}); + + web_app::AppRegistrar& registrar_base = provider->registrar(); + web_app::WebAppRegistrar* registrar = registrar_base.AsWebAppRegistrar(); + if (!registrar) + std::move(callback).Run({}); + + std::vector<mojom::web_app_internals::WebAppPtr> result; + for (const web_app::WebApp& web_app : registrar->AllApps()) { + mojom::web_app_internals::WebAppPtr info( + mojom::web_app_internals::WebApp::New()); + info->name = web_app.name(); + info->id = web_app.app_id(); + std::stringstream ss; + ss << web_app; + info->debug_info = ss.str(); + result.push_back(std::move(info)); + } + + std::move(callback).Run(std::move(result)); +} + +void WebAppInternalsPageHandlerImpl::GetExternallyInstalledWebAppPrefs( + GetExternallyInstalledWebAppPrefsCallback callback) { + std::stringstream ss; + ss << *profile_->GetPrefs()->GetDictionary(prefs::kWebAppsExtensionIDs); + std::move(callback).Run(ss.str()); +} diff --git a/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h b/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h new file mode 100644 index 00000000000..ac2d034f03d --- /dev/null +++ b/chromium/chrome/browser/ui/webui/internals/web_app/web_app_internals_page_handler_impl.h @@ -0,0 +1,39 @@ +// Copyright 2020 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_INTERNALS_WEB_APP_WEB_APP_INTERNALS_PAGE_HANDLER_IMPL_H_ +#define CHROME_BROWSER_UI_WEBUI_INTERNALS_WEB_APP_WEB_APP_INTERNALS_PAGE_HANDLER_IMPL_H_ + +#include "chrome/browser/ui/webui/internals/web_app/web_app_internals.mojom.h" + +class Profile; + +namespace content { +class WebUIDataSource; +} + +// Handles API requests from chrome://internals/web-app. +class WebAppInternalsPageHandlerImpl + : public mojom::web_app_internals::WebAppInternalsPageHandler { + public: + explicit WebAppInternalsPageHandlerImpl(Profile* profile); + WebAppInternalsPageHandlerImpl(const WebAppInternalsPageHandlerImpl&) = + delete; + WebAppInternalsPageHandlerImpl& operator=( + const WebAppInternalsPageHandlerImpl&) = delete; + ~WebAppInternalsPageHandlerImpl() override; + + static void AddPageResources(content::WebUIDataSource* source); + + // mojom::web_app_internals::WebAppInternalsPageHandler: + void IsBmoEnabled(IsBmoEnabledCallback callback) override; + void GetWebApps(GetWebAppsCallback callback) override; + void GetExternallyInstalledWebAppPrefs( + GetExternallyInstalledWebAppPrefsCallback callback) override; + + private: + Profile* profile_ = nullptr; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_INTERNALS_WEB_APP_WEB_APP_INTERNALS_PAGE_HANDLER_IMPL_H_ diff --git a/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index ec670f5dd01..f0f6eca30f7 100644 --- a/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chromium/chrome/browser/ui/webui/interstitials/interstitial_ui.cc @@ -21,6 +21,7 @@ #include "chrome/browser/safe_browsing/test_safe_browsing_blocking_page_quiet.h" #include "chrome/browser/safe_browsing/ui_manager.h" #include "chrome/browser/ssl/chrome_security_blocking_page_factory.h" +#include "chrome/browser/ssl/insecure_form/insecure_form_controller_client.h" #include "chrome/common/buildflags.h" #include "chrome/common/url_constants.h" #include "components/captive_portal/core/buildflags.h" @@ -29,6 +30,7 @@ #include "components/safe_browsing/core/db/database_manager.h" #include "components/security_interstitials/content/bad_clock_blocking_page.h" #include "components/security_interstitials/content/blocked_interception_blocking_page.h" +#include "components/security_interstitials/content/insecure_form_blocking_page.h" #include "components/security_interstitials/content/legacy_tls_blocking_page.h" #include "components/security_interstitials/content/mitm_software_blocking_page.h" #include "components/security_interstitials/content/origin_policy_ui.h" @@ -51,6 +53,7 @@ #include "net/ssl/ssl_info.h" #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/network/public/cpp/origin_policy.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/web_ui_util.h" @@ -98,9 +101,8 @@ class InterstitialHTMLSource : public content::URLDataSource { // content::URLDataSource: std::string GetMimeType(const std::string& mime_type) override; std::string GetSource() override; - std::string GetContentSecurityPolicyScriptSrc() override; - std::string GetContentSecurityPolicyStyleSrc() override; - std::string GetContentSecurityPolicyImgSrc() override; + std::string GetContentSecurityPolicy( + const network::mojom::CSPDirectiveName directive) override; void StartDataRequest( const GURL& url, const content::WebContents::Getter& wc_getter, @@ -264,14 +266,27 @@ std::unique_ptr<LookalikeUrlBlockingPage> CreateLookalikeInterstitialPage( content::WebContents* web_contents) { GURL request_url("https://example.net"); GURL safe_url("https://example.com"); - + std::string url_param; + if (net::GetValueForKeyInQuery(web_contents->GetURL(), "no-safe-url", + &url_param)) { + safe_url = GURL(); + } return std::make_unique<LookalikeUrlBlockingPage>( - web_contents, safe_url, ukm::kInvalidSourceId, + web_contents, safe_url, request_url, ukm::kInvalidSourceId, LookalikeUrlMatchType::kNone, std::make_unique<LookalikeUrlControllerClient>(web_contents, request_url, safe_url)); } +std::unique_ptr<security_interstitials::InsecureFormBlockingPage> +CreateInsecureFormPage(content::WebContents* web_contents) { + GURL request_url("http://example.com"); + return std::make_unique<security_interstitials::InsecureFormBlockingPage>( + web_contents, request_url, + std::make_unique<InsecureFormControllerClient>(web_contents, + request_url)); +} + std::unique_ptr<safe_browsing::SafeBrowsingBlockingPage> CreateSafeBrowsingBlockingPage(content::WebContents* web_contents) { safe_browsing::SBThreatType threat_type = @@ -451,17 +466,18 @@ std::string InterstitialHTMLSource::GetSource() { return chrome::kChromeUIInterstitialHost; } -std::string InterstitialHTMLSource::GetContentSecurityPolicyScriptSrc() { - // 'unsafe-inline' is added to script-src. - return "script-src chrome://resources 'self' 'unsafe-inline';"; -} - -std::string InterstitialHTMLSource::GetContentSecurityPolicyStyleSrc() { - return "style-src 'self' 'unsafe-inline';"; -} +std::string InterstitialHTMLSource::GetContentSecurityPolicy( + const network::mojom::CSPDirectiveName directive) { + if (directive == network::mojom::CSPDirectiveName::ScriptSrc) { + // 'unsafe-inline' is added to script-src. + return "script-src chrome://resources 'self' 'unsafe-inline';"; + } else if (directive == network::mojom::CSPDirectiveName::StyleSrc) { + return "style-src 'self' 'unsafe-inline';"; + } else if (directive == network::mojom::CSPDirectiveName::ImgSrc) { + return "img-src data:;"; + } -std::string InterstitialHTMLSource::GetContentSecurityPolicyImgSrc() { - return "img-src data:;"; + return content::URLDataSource::GetContentSecurityPolicy(directive); } void InterstitialHTMLSource::StartDataRequest( @@ -506,6 +522,8 @@ void InterstitialHTMLSource::StartDataRequest( #endif } else if (path_without_query == "/origin_policy") { interstitial_delegate = CreateOriginPolicyInterstitialPage(web_contents); + } else if (path_without_query == "/insecure_form") { + interstitial_delegate = CreateInsecureFormPage(web_contents); } if (path_without_query == "/quietsafebrowsing") { diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom index 061c1e82179..4b4101df90b 100644 --- a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom +++ b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom @@ -60,10 +60,10 @@ interface InterventionsInternalsPageHandler { // Inject the client side page object. SetClientPage(pending_remote<InterventionsInternalsPage> page); - // Change the status of ignoring blacklist to |ignored|. |ignored| will - // indicate whether the blacklist decision would be ignored when deciding if a + // Change the status of ignoring blocklist to |ignored|. |ignored| will + // indicate whether the blocklist decision would be ignored when deciding if a // preview should be shown or not. - SetIgnorePreviewsBlacklistDecision(bool ignored); + SetIgnorePreviewsBlocklistDecision(bool ignored); }; interface InterventionsInternalsPage { @@ -72,20 +72,20 @@ interface InterventionsInternalsPage { // publishes it on the javscript side. LogNewMessage(MessageLog log); - // Notify the page that |host| has been blacklisted at |time|. The method is + // Notify the page that |host| has been blocklisted at |time|. The method is // called by InterventionsInternalsPageHandler when PreviewsUIService receives - // new blacklisted host. - OnBlacklistedHost(string host, int64 time); + // new blocklisted host. + OnBlocklistedHost(string host, int64 time); - // Notify the page that user blacklisted status has changed to |blacklisted|. + // Notify the page that user blocklisted status has changed to |blocklisted|. // The method is called by InterventionsInternalsPageHandler when user's - // blacklist status changes. - OnUserBlacklistedStatusChange(bool blacklisted); + // blocklist status changes. + OnUserBlocklistedStatusChange(bool blocklisted); - // Notify the page that the blacklist is cleared at |time|. The method is + // Notify the page that the blocklist is cleared at |time|. The method is // called by InterventionsInternalsPageHandler when PreviewsUIService clears - // the blacklist. - OnBlacklistCleared(int64 time); + // the blocklist. + OnBlocklistCleared(int64 time); // Notify the page on the new estimated effective connection type is |type|. // Also reports the session's maximum intervention effective connection type @@ -94,8 +94,8 @@ interface InterventionsInternalsPage { // changes. UpdateEffectiveConnectionType(string type, string max_intervention_type); - // Notify the page on whether the blacklist decision is considered or ignored. + // Notify the page on whether the blocklist decision is considered or ignored. // This method is called by InterventionsInternalsPageHandler when the status - // of ignore blacklist decision is updated to |ignored|. - OnIgnoreBlacklistDecisionStatusChanged(bool ignored); + // of ignore blocklist decision is updated to |ignored|. + OnIgnoreBlocklistDecisionStatusChanged(bool ignored); }; diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc index a956bd2e948..fbce5852614 100644 --- a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc +++ b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc @@ -62,7 +62,7 @@ const char kResourceLoadingHintsFlagHtmlId[] = "resource-loading-hints-flag"; const char kDeferAllScriptFlagHtmlId[] = "defer-all-script-flag"; const char kNoScriptFlagHtmlId[] = "noscript-flag"; const char kEctFlagHtmlId[] = "ect-flag"; -const char kIgnorePreviewsBlacklistFlagHtmlId[] = "ignore-previews-blacklist"; +const char kIgnorePreviewsBlocklistFlagHtmlId[] = "ignore-previews-blocklist"; const char kDataSaverAltConfigHtmlId[] = "data-reduction-proxy-server-experiment"; @@ -76,8 +76,8 @@ const char kDeferAllScriptFlagLink[] = "chrome://flags/#enable-defer-all-script"; const char kNoScriptFlagLink[] = "chrome://flags/#enable-noscript-previews"; const char kEctFlagLink[] = "chrome://flags/#force-effective-connection-type"; -const char kIgnorePreviewsBlacklistLink[] = - "chrome://flags/#ignore-previews-blacklist"; +const char kIgnorePreviewsBlocklistLink[] = + "chrome://flags/#ignore-previews-blocklist"; const char kDataSaverAltConfigLink[] = "chrome://flags/#enable-data-reduction-proxy-server-experiment"; @@ -184,35 +184,35 @@ void InterventionsInternalsPageHandler::OnNewMessageLogAdded( page_->LogNewMessage(std::move(mojo_message_ptr)); } -void InterventionsInternalsPageHandler::SetIgnorePreviewsBlacklistDecision( +void InterventionsInternalsPageHandler::SetIgnorePreviewsBlocklistDecision( bool ignored) { - previews_ui_service_->SetIgnorePreviewsBlacklistDecision(ignored); + previews_ui_service_->SetIgnorePreviewsBlocklistDecision(ignored); } void InterventionsInternalsPageHandler::OnLastObserverRemove() { - // Reset the status of ignoring PreviewsBlackList decisions to default value. - previews_ui_service_->SetIgnorePreviewsBlacklistDecision( - previews::switches::ShouldIgnorePreviewsBlacklist()); + // Reset the status of ignoring PreviewsBlockList decisions to default value. + previews_ui_service_->SetIgnorePreviewsBlocklistDecision( + previews::switches::ShouldIgnorePreviewsBlocklist()); } -void InterventionsInternalsPageHandler::OnIgnoreBlacklistDecisionStatusChanged( +void InterventionsInternalsPageHandler::OnIgnoreBlocklistDecisionStatusChanged( bool ignored) { - page_->OnIgnoreBlacklistDecisionStatusChanged(ignored); + page_->OnIgnoreBlocklistDecisionStatusChanged(ignored); } -void InterventionsInternalsPageHandler::OnNewBlacklistedHost( +void InterventionsInternalsPageHandler::OnNewBlocklistedHost( const std::string& host, base::Time time) { - page_->OnBlacklistedHost(host, time.ToJavaTime()); + page_->OnBlocklistedHost(host, time.ToJavaTime()); } -void InterventionsInternalsPageHandler::OnUserBlacklistedStatusChange( - bool blacklisted) { - page_->OnUserBlacklistedStatusChange(blacklisted); +void InterventionsInternalsPageHandler::OnUserBlocklistedStatusChange( + bool blocklisted) { + page_->OnUserBlocklistedStatusChange(blocklisted); } -void InterventionsInternalsPageHandler::OnBlacklistCleared(base::Time time) { - page_->OnBlacklistCleared(time.ToJavaTime()); +void InterventionsInternalsPageHandler::OnBlocklistCleared(base::Time time) { + page_->OnBlocklistCleared(time.ToJavaTime()); } void InterventionsInternalsPageHandler::GetPreviewsEnabled( @@ -317,14 +317,14 @@ void InterventionsInternalsPageHandler::GetPreviewsFlagsDetails( ect_status->htmlId = kEctFlagHtmlId; flags.push_back(std::move(ect_status)); - auto ignore_previews_blacklist = mojom::PreviewsFlag::New(); - ignore_previews_blacklist->description = - flag_descriptions::kIgnorePreviewsBlacklistName; - ignore_previews_blacklist->link = kIgnorePreviewsBlacklistLink; - ignore_previews_blacklist->value = - GetEnabledStateForSwitch(previews::switches::kIgnorePreviewsBlacklist); - ignore_previews_blacklist->htmlId = kIgnorePreviewsBlacklistFlagHtmlId; - flags.push_back(std::move(ignore_previews_blacklist)); + auto ignore_previews_blocklist = mojom::PreviewsFlag::New(); + ignore_previews_blocklist->description = + flag_descriptions::kIgnorePreviewsBlocklistName; + ignore_previews_blocklist->link = kIgnorePreviewsBlocklistLink; + ignore_previews_blocklist->value = + GetEnabledStateForSwitch(previews::switches::kIgnorePreviewsBlocklist); + ignore_previews_blocklist->htmlId = kIgnorePreviewsBlocklistFlagHtmlId; + flags.push_back(std::move(ignore_previews_blocklist)); auto alt_config_status = mojom::PreviewsFlag::New(); alt_config_status->description = diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h index b892a1efe74..c47656ccd0e 100644 --- a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h +++ b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h @@ -37,15 +37,15 @@ class InterventionsInternalsPageHandler GetPreviewsFlagsDetailsCallback callback) override; void SetClientPage( mojo::PendingRemote<mojom::InterventionsInternalsPage> page) override; - void SetIgnorePreviewsBlacklistDecision(bool ignore) override; + void SetIgnorePreviewsBlocklistDecision(bool ignore) override; // previews::PreviewsLoggerObserver: void OnNewMessageLogAdded( const previews::PreviewsLogger::MessageLog& message) override; - void OnNewBlacklistedHost(const std::string& host, base::Time time) override; - void OnUserBlacklistedStatusChange(bool blacklisted) override; - void OnBlacklistCleared(base::Time time) override; - void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override; + void OnNewBlocklistedHost(const std::string& host, base::Time time) override; + void OnUserBlocklistedStatusChange(bool blocklisted) override; + void OnBlocklistCleared(base::Time time) override; + void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override; void OnLastObserverRemove() override; private: diff --git a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc index b5a0ddeb2ff..f61271fc5fd 100644 --- a/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc @@ -30,7 +30,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" -#include "components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h" +#include "components/blocklist/opt_out_blocklist/opt_out_blocklist_data.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/previews/content/previews_decider_impl.h" #include "components/previews/content/previews_ui_service.h" @@ -74,8 +74,8 @@ constexpr char kResourceLoadingHintsFlagHtmlId[] = constexpr char kDeferAllScriptFlagHtmlId[] = "defer-all-script-flag"; constexpr char kNoScriptFlagHtmlId[] = "noscript-flag"; constexpr char kEctFlagHtmlId[] = "ect-flag"; -constexpr char kIgnorePreviewsBlacklistFlagHtmlId[] = - "ignore-previews-blacklist"; +constexpr char kIgnorePreviewsBlocklistFlagHtmlId[] = + "ignore-previews-blocklist"; constexpr char kDataSaverAltConfigHtmlId[] = "data-reduction-proxy-server-experiment"; @@ -89,8 +89,8 @@ constexpr char kDeferAllScriptFlagLink[] = constexpr char kNoScriptFlagLink[] = "chrome://flags/#enable-noscript-previews"; constexpr char kEctFlagLink[] = "chrome://flags/#force-effective-connection-type"; -constexpr char kIgnorePreviewsBlacklistLink[] = - "chrome://flags/#ignore-previews-blacklist"; +constexpr char kIgnorePreviewsBlocklistLink[] = + "chrome://flags/#ignore-previews-blocklist"; constexpr char kDataSaverAltConfigLink[] = "chrome://flags/#enable-data-reduction-proxy-server-experiment"; @@ -141,23 +141,23 @@ class TestInterventionsInternalsPage public: TestInterventionsInternalsPage( mojo::PendingReceiver<mojom::InterventionsInternalsPage> receiver) - : receiver_(this, std::move(receiver)), blacklist_ignored_(false) {} + : receiver_(this, std::move(receiver)), blocklist_ignored_(false) {} - ~TestInterventionsInternalsPage() override {} + ~TestInterventionsInternalsPage() override = default; // mojom::InterventionsInternalsPage: void LogNewMessage(mojom::MessageLogPtr message) override { message_ = std::make_unique<mojom::MessageLogPtr>(std::move(message)); } - void OnBlacklistedHost(const std::string& host, int64_t time) override { - host_blacklisted_ = host; - host_blacklisted_time_ = time; + void OnBlocklistedHost(const std::string& host, int64_t time) override { + host_blocklisted_ = host; + host_blocklisted_time_ = time; } - void OnUserBlacklistedStatusChange(bool blacklisted) override { - user_blacklisted_ = blacklisted; + void OnUserBlocklistedStatusChange(bool blocklisted) override { + user_blocklisted_ = blocklisted; } - void OnBlacklistCleared(int64_t time) override { - blacklist_cleared_time_ = time; + void OnBlocklistCleared(int64_t time) override { + blocklist_cleared_time_ = time; } void UpdateEffectiveConnectionType( const std::string& type, @@ -166,21 +166,21 @@ class TestInterventionsInternalsPage // TODO(thanhdle): Add integration test to test behavior of the pipeline end // to end. crbug.com/777936 } - void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override { - blacklist_ignored_ = ignored; + void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override { + blocklist_ignored_ = ignored; } // Expose passed in message in LogNewMessage for testing. mojom::MessageLogPtr* message() const { return message_.get(); } - // Expose passed in blacklist events info for testing. - std::string host_blacklisted() const { return host_blacklisted_; } - int64_t host_blacklisted_time() const { return host_blacklisted_time_; } - bool user_blacklisted() const { return user_blacklisted_; } - int64_t blacklist_cleared_time() const { return blacklist_cleared_time_; } + // Expose passed in blocklist events info for testing. + std::string host_blocklisted() const { return host_blocklisted_; } + int64_t host_blocklisted_time() const { return host_blocklisted_time_; } + bool user_blocklisted() const { return user_blocklisted_; } + int64_t blocklist_cleared_time() const { return blocklist_cleared_time_; } - // Expose the passed in blacklist ignore status for testing. - bool blacklist_ignored() const { return blacklist_ignored_; } + // Expose the passed in blocklist ignore status for testing. + bool blocklist_ignored() const { return blocklist_ignored_; } private: mojo::Receiver<mojom::InterventionsInternalsPage> receiver_; @@ -188,14 +188,14 @@ class TestInterventionsInternalsPage // The MessageLogPtr passed in LogNewMessage method. std::unique_ptr<mojom::MessageLogPtr> message_; - // Received blacklist events info. - std::string host_blacklisted_; - int64_t host_blacklisted_time_; - int64_t user_blacklisted_; - int64_t blacklist_cleared_time_; + // Received blocklist events info. + std::string host_blocklisted_; + int64_t host_blocklisted_time_; + int64_t user_blocklisted_; + int64_t blocklist_cleared_time_; - // Whether to ignore previews blacklist decisions. - bool blacklist_ignored_; + // Whether to ignore previews blocklist decisions. + bool blocklist_ignored_; }; // Mock class to test interaction between the PageHandler and the @@ -224,10 +224,10 @@ class TestPreviewsDeciderImpl : public previews::PreviewsDeciderImpl { // previews::PreviewsDeciderImpl: void Initialize( previews::PreviewsUIService* previews_ui_service, - std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store, + std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store, std::unique_ptr<previews::PreviewsOptimizationGuide> previews_opt_guide, const previews::PreviewsIsEnabledCallback& is_enabled_callback, - blacklist::BlacklistData::AllowedTypesAndVersions allowed_previews) + blocklist::BlocklistData::AllowedTypesAndVersions allowed_previews) override {} }; @@ -244,22 +244,22 @@ class TestPreviewsUIService : public previews::PreviewsUIService { nullptr, /* previews_opt_guide */ base::BindRepeating(&MockedPreviewsIsEnabled), std::move(logger), - blacklist::BlacklistData::AllowedTypesAndVersions(), + blocklist::BlocklistData::AllowedTypesAndVersions(), test_network_quality_tracker), - blacklist_ignored_(false) {} - ~TestPreviewsUIService() override {} + blocklist_ignored_(false) {} + ~TestPreviewsUIService() override = default; // previews::PreviewsUIService: - void SetIgnorePreviewsBlacklistDecision(bool ignored) override { - blacklist_ignored_ = ignored; + void SetIgnorePreviewsBlocklistDecision(bool ignored) override { + blocklist_ignored_ = ignored; } - // Exposed blacklist ignored state. - bool blacklist_ignored() const { return blacklist_ignored_; } + // Exposed blocklist ignored state. + bool blocklist_ignored() const { return blocklist_ignored_; } private: - // Whether the blacklist decisions are ignored or not. - bool blacklist_ignored_; + // Whether the blocklist decisions are ignored or not. + bool blocklist_ignored_; }; class InterventionsInternalsPageHandlerTest : public testing::Test { @@ -534,33 +534,33 @@ TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsEctForceFieldtrialValue) { } TEST_F(InterventionsInternalsPageHandlerTest, - GetFlagsIgnorePreviewsBlacklistDisabledValue) { + GetFlagsIgnorePreviewsBlocklistDisabledValue) { // Disabled by default. page_handler_->GetPreviewsFlagsDetails( base::BindOnce(&MockGetPreviewsFlagsCallback)); - auto ignore_previews_blacklist = - passed_in_flags.find(kIgnorePreviewsBlacklistFlagHtmlId); + auto ignore_previews_blocklist = + passed_in_flags.find(kIgnorePreviewsBlocklistFlagHtmlId); - ASSERT_NE(passed_in_flags.end(), ignore_previews_blacklist); - EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlacklistName, - ignore_previews_blacklist->second->description); - EXPECT_EQ(kDisabledFlagValue, ignore_previews_blacklist->second->value); - EXPECT_EQ(kIgnorePreviewsBlacklistLink, - ignore_previews_blacklist->second->link); + ASSERT_NE(passed_in_flags.end(), ignore_previews_blocklist); + EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlocklistName, + ignore_previews_blocklist->second->description); + EXPECT_EQ(kDisabledFlagValue, ignore_previews_blocklist->second->value); + EXPECT_EQ(kIgnorePreviewsBlocklistLink, + ignore_previews_blocklist->second->link); } TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDisabledValue) { page_handler_->GetPreviewsFlagsDetails( base::BindOnce(&MockGetPreviewsFlagsCallback)); - auto ignore_previews_blacklist = - passed_in_flags.find(kIgnorePreviewsBlacklistFlagHtmlId); + auto ignore_previews_blocklist = + passed_in_flags.find(kIgnorePreviewsBlocklistFlagHtmlId); - ASSERT_NE(passed_in_flags.end(), ignore_previews_blacklist); - EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlacklistName, - ignore_previews_blacklist->second->description); - EXPECT_EQ(kDisabledFlagValue, ignore_previews_blacklist->second->value); - EXPECT_EQ(kIgnorePreviewsBlacklistLink, - ignore_previews_blacklist->second->link); + ASSERT_NE(passed_in_flags.end(), ignore_previews_blocklist); + EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlocklistName, + ignore_previews_blocklist->second->description); + EXPECT_EQ(kDisabledFlagValue, ignore_previews_blocklist->second->value); + EXPECT_EQ(kIgnorePreviewsBlocklistLink, + ignore_previews_blocklist->second->link); } TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDefaultValue) { @@ -844,7 +844,7 @@ TEST_F(InterventionsInternalsPageHandlerTest, ObserverIsRemovedWhenDestroyed) { EXPECT_TRUE(logger_->RemovedObserverIsCalled()); } -TEST_F(InterventionsInternalsPageHandlerTest, OnNewBlacklistedHostPostToPage) { +TEST_F(InterventionsInternalsPageHandlerTest, OnNewBlocklistedHostPostToPage) { const std::string hosts[] = { "example_0.com", "example_1.com", @@ -853,75 +853,75 @@ TEST_F(InterventionsInternalsPageHandlerTest, OnNewBlacklistedHostPostToPage) { for (auto expected_host : hosts) { base::Time expected_time = base::Time::Now(); - page_handler_->OnNewBlacklistedHost(expected_host, expected_time); + page_handler_->OnNewBlocklistedHost(expected_host, expected_time); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(expected_host, page_->host_blacklisted()); - EXPECT_EQ(expected_time.ToJavaTime(), page_->host_blacklisted_time()); + EXPECT_EQ(expected_host, page_->host_blocklisted()); + EXPECT_EQ(expected_time.ToJavaTime(), page_->host_blocklisted_time()); } } -TEST_F(InterventionsInternalsPageHandlerTest, OnUserBlacklistedPostToPage) { - page_handler_->OnUserBlacklistedStatusChange(true /* blacklisted */); +TEST_F(InterventionsInternalsPageHandlerTest, OnUserBlocklistedPostToPage) { + page_handler_->OnUserBlocklistedStatusChange(true /* blocklisted */); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(page_->user_blacklisted()); + EXPECT_TRUE(page_->user_blocklisted()); - page_handler_->OnUserBlacklistedStatusChange(false /* blacklisted */); + page_handler_->OnUserBlocklistedStatusChange(false /* blocklisted */); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(page_->user_blacklisted()); + EXPECT_FALSE(page_->user_blocklisted()); } -TEST_F(InterventionsInternalsPageHandlerTest, OnBlacklistClearedPostToPage) { +TEST_F(InterventionsInternalsPageHandlerTest, OnBlocklistClearedPostToPage) { base::Time times[] = { base::Time::FromJsTime(-413696806000), // Nov 21 1956 20:13:14 UTC base::Time::FromJsTime(758620800000), // Jan 15 1994 08:00:00 UTC base::Time::FromJsTime(1581696550000), // Feb 14 2020 16:09:10 UTC }; for (auto expected_time : times) { - page_handler_->OnBlacklistCleared(expected_time); + page_handler_->OnBlocklistCleared(expected_time); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(expected_time.ToJavaTime(), page_->blacklist_cleared_time()); + EXPECT_EQ(expected_time.ToJavaTime(), page_->blocklist_cleared_time()); } } TEST_F(InterventionsInternalsPageHandlerTest, - SetIgnorePreviewsBlacklistDecisionCallsUIServiceCorrectly) { - page_handler_->SetIgnorePreviewsBlacklistDecision(true /* ignored */); - EXPECT_TRUE(previews_ui_service_->blacklist_ignored()); + SetIgnorePreviewsBlocklistDecisionCallsUIServiceCorrectly) { + page_handler_->SetIgnorePreviewsBlocklistDecision(true /* ignored */); + EXPECT_TRUE(previews_ui_service_->blocklist_ignored()); - page_handler_->SetIgnorePreviewsBlacklistDecision(false /* ignored */); - EXPECT_FALSE(previews_ui_service_->blacklist_ignored()); + page_handler_->SetIgnorePreviewsBlocklistDecision(false /* ignored */); + EXPECT_FALSE(previews_ui_service_->blocklist_ignored()); } TEST_F(InterventionsInternalsPageHandlerTest, - PageUpdateOnBlacklistIgnoredChange) { - page_handler_->OnIgnoreBlacklistDecisionStatusChanged(true /* ignored */); + PageUpdateOnBlocklistIgnoredChange) { + page_handler_->OnIgnoreBlocklistDecisionStatusChanged(true /* ignored */); base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(page_->blacklist_ignored()); + EXPECT_TRUE(page_->blocklist_ignored()); - page_handler_->OnIgnoreBlacklistDecisionStatusChanged(false /* ignored */); + page_handler_->OnIgnoreBlocklistDecisionStatusChanged(false /* ignored */); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(page_->blacklist_ignored()); + EXPECT_FALSE(page_->blocklist_ignored()); } TEST_F(InterventionsInternalsPageHandlerTest, - IgnoreBlacklistReversedOnLastObserverRemovedCalled) { - ASSERT_FALSE(previews::switches::ShouldIgnorePreviewsBlacklist()); + IgnoreBlocklistReversedOnLastObserverRemovedCalled) { + ASSERT_FALSE(previews::switches::ShouldIgnorePreviewsBlocklist()); page_handler_->OnLastObserverRemove(); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(page_->blacklist_ignored()); + EXPECT_FALSE(page_->blocklist_ignored()); } TEST_F(InterventionsInternalsPageHandlerTest, - IgnoreBlacklistReversedOnLastObserverRemovedCalledIgnoreViaFlag) { + IgnoreBlocklistReversedOnLastObserverRemovedCalledIgnoreViaFlag) { base::test::ScopedCommandLine scoped_command_line; base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine(); - command_line->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist); - ASSERT_TRUE(previews::switches::ShouldIgnorePreviewsBlacklist()); + command_line->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist); + ASSERT_TRUE(previews::switches::ShouldIgnorePreviewsBlocklist()); page_handler_->OnLastObserverRemove(); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(page_->blacklist_ignored()); + EXPECT_FALSE(page_->blocklist_ignored()); } } // namespace diff --git a/chromium/chrome/browser/ui/webui/invalidations_ui.cc b/chromium/chrome/browser/ui/webui/invalidations_ui.cc index 092f8425c2e..4846cedb319 100644 --- a/chromium/chrome/browser/ui/webui/invalidations_ui.cc +++ b/chromium/chrome/browser/ui/webui/invalidations_ui.cc @@ -13,13 +13,15 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" content::WebUIDataSource* CreateInvalidationsHTMLSource() { // This is done once per opening of the page // This method does not fire when refreshing the page content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIInvalidationsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->AddResourcePath("about_invalidations.js", IDR_ABOUT_INVALIDATIONS_JS); source->SetDefaultResource(IDR_ABOUT_INVALIDATIONS_HTML); diff --git a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc index 69169417236..40ac82d0f33 100644 --- a/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc @@ -351,7 +351,12 @@ class LocalDiscoveryUITest : public WebUIBrowserTest { // a DCHECK during TestServiceDiscoveryClient construction. media_router::DualMediaSinkService::SetInstanceForTest( new media_router::NoopDualMediaSinkService()); - feature_list_.InitAndDisableFeature(media_router::kDialMediaRouteProvider); + // The Media Route Providers must be disabled because they rely on the + // presence of a valid DualMediaSinkService. + // TODO(crbug.com/1028753): Enable the Media Route Provider features. + feature_list_.InitWithFeatures( + {}, /* disabled_features */ {media_router::kDialMediaRouteProvider, + media_router::kCastMediaRouteProvider}); WebUIBrowserTest::SetUp(); } diff --git a/chromium/chrome/browser/ui/webui/management_ui.cc b/chromium/chrome/browser/ui/webui/management_ui.cc index 4254c9ddf6b..17da74ee390 100644 --- a/chromium/chrome/browser/ui/webui/management_ui.cc +++ b/chromium/chrome/browser/ui/webui/management_ui.cc @@ -59,6 +59,8 @@ content::WebUIDataSource* CreateManagementUIHtmlSource(Profile* profile) { IDS_MANAGEMENT_REPORT_DEVICE_NETWORK_INTERFACES}, {kManagementReportUsers, IDS_MANAGEMENT_REPORT_DEVICE_USERS}, {kManagementReportCrashReports, IDS_MANAGEMENT_REPORT_DEVICE_CRASH_REPORTS}, + {kManagementReportAppInfoAndActivity, + IDS_MANAGEMENT_REPORT_APP_INFO_AND_ACTIVITY}, {kManagementPrinting, IDS_MANAGEMENT_REPORT_PRINTING}, {kManagementCrostini, IDS_MANAGEMENT_CROSTINI}, {kManagementCrostiniContainerConfiguration, @@ -95,17 +97,21 @@ content::WebUIDataSource* CreateManagementUIHtmlSource(Profile* profile) { {kManagementExtensionReportUserBrowsingData, IDS_MANAGEMENT_EXTENSION_REPORT_USER_BROWSING_DATA}, {kThreatProtectionTitle, IDS_MANAGEMENT_THREAT_PROTECTION}, - {kManagementDataLossPreventionName, - IDS_MANAGEMENT_DATA_LOSS_PREVENTION_NAME}, - {kManagementDataLossPreventionPermissions, - IDS_MANAGEMENT_DATA_LOSS_PREVENTION_PERMISSIONS}, - {kManagementMalwareScanningName, IDS_MANAGEMENT_MALWARE_SCANNING_NAME}, - {kManagementMalwareScanningPermissions, - IDS_MANAGEMENT_MALWARE_SCANNING_PERMISSIONS}, - {kManagementEnterpriseReportingName, - IDS_MANAGEMENT_ENTERPRISE_REPORTING_NAME}, - {kManagementEnterpriseReportingPermissions, - IDS_MANAGEMENT_ENTERPRISE_REPORTING_PERMISSIONS}, + {"connectorEvent", IDS_MANAGEMENT_CONNECTORS_EVENT}, + {"connectorVisibleData", IDS_MANAGEMENT_CONNECTORS_VISIBLE_DATA}, + {kManagementEnterpriseReportingEvent, + IDS_MANAGEMENT_ENTERPRISE_REPORTING_EVENT}, + {kManagementEnterpriseReportingVisibleData, + IDS_MANAGEMENT_ENTERPRISE_REPORTING_VISIBLE_DATA}, + {kManagementOnFileAttachedEvent, IDS_MANAGEMENT_FILE_ATTACHED_EVENT}, + {kManagementOnFileAttachedVisibleData, + IDS_MANAGEMENT_FILE_ATTACHED_VISIBLE_DATA}, + {kManagementOnFileDownloadedEvent, IDS_MANAGEMENT_FILE_DOWNLOADED_EVENT}, + {kManagementOnFileDownloadedVisibleData, + IDS_MANAGEMENT_FILE_DOWNLOADED_VISIBLE_DATA}, + {kManagementOnBulkDataEntryEvent, IDS_MANAGEMENT_TEXT_ENTERED_EVENT}, + {kManagementOnBulkDataEntryVisibleData, + IDS_MANAGEMENT_TEXT_ENTERED_VISIBLE_DATA}, }; AddLocalizedStringsBulk(source, kLocalizedStrings); diff --git a/chromium/chrome/browser/ui/webui/management_ui_handler.cc b/chromium/chrome/browser/ui/webui/management_ui_handler.cc index e8dff0d2dc4..f5aeff7fa6b 100644 --- a/chromium/chrome/browser/ui/webui/management_ui_handler.cc +++ b/chromium/chrome/browser/ui/webui/management_ui_handler.cc @@ -113,10 +113,21 @@ const char kManagementDataLossPreventionPermissions[] = const char kManagementMalwareScanningName[] = "managementMalwareScanningName"; const char kManagementMalwareScanningPermissions[] = "managementMalwareScanningPermissions"; -const char kManagementEnterpriseReportingName[] = - "managementEnterpriseReportingName"; -const char kManagementEnterpriseReportingPermissions[] = - "managementEnterpriseReportingPermissions"; +const char kManagementEnterpriseReportingEvent[] = + "managementEnterpriseReportingEvent"; +const char kManagementEnterpriseReportingVisibleData[] = + "managementEnterpriseReportingVisibleData"; + +const char kManagementOnFileAttachedEvent[] = "managementOnFileAttachedEvent"; +const char kManagementOnFileAttachedVisibleData[] = + "managementOnFileAttachedVisibleData"; +const char kManagementOnFileDownloadedEvent[] = + "managementOnFileDownloadedEvent"; +const char kManagementOnFileDownloadedVisibleData[] = + "managementOnFileDownloadedVisibleData"; +const char kManagementOnBulkDataEntryEvent[] = "managementOnBulkDataEntryEvent"; +const char kManagementOnBulkDataEntryVisibleData[] = + "managementOnBulkDataEntryVisibleData"; const char kReportingTypeDevice[] = "device"; const char kReportingTypeExtensions[] = "extensions"; @@ -140,6 +151,8 @@ const char kManagementReportNetworkInterfaces[] = "managementReportNetworkInterfaces"; const char kManagementReportUsers[] = "managementReportUsers"; const char kManagementReportCrashReports[] = "managementReportCrashReports"; +const char kManagementReportAppInfoAndActivity[] = + "managementReportAppInfoAndActivity"; const char kManagementReportExtensions[] = "managementReportExtensions"; const char kManagementReportAndroidApplications[] = "managementReportAndroidApplications"; @@ -186,6 +199,7 @@ enum class DeviceReportingType { kDeviceStatistics, kDevice, kCrashReport, + kAppInfoAndActivity, kLogs, kPrint, kCrostini, @@ -208,6 +222,8 @@ std::string ToJSDeviceReportingType(const DeviceReportingType& type) { return "device"; case DeviceReportingType::kCrashReport: return "crash report"; + case DeviceReportingType::kAppInfoAndActivity: + return "app info and activity"; case DeviceReportingType::kLogs: return "logs"; case DeviceReportingType::kPrint: @@ -538,6 +554,11 @@ void ManagementUIHandler::AddDeviceReportingInfo( AddDeviceReportingElement(report_sources, kManagementReportCrashReports, DeviceReportingType::kCrashReport); } + if (collector->ShouldReportAppInfoAndActivity()) { + AddDeviceReportingElement(report_sources, + kManagementReportAppInfoAndActivity, + DeviceReportingType::kAppInfoAndActivity); + } if (uploader->upload_enabled()) { AddDeviceReportingElement(report_sources, kManagementLogUploadEnabled, DeviceReportingType::kLogs); @@ -578,8 +599,10 @@ void ManagementUIHandler::AddDeviceReportingInfo( chromeos::NetworkHandler* network_handler = chromeos::NetworkHandler::Get(); base::Value proxy_settings(base::Value::Type::DICTIONARY); - // |ui_proxy_config_service| may be missing in tests. - if (network_handler->has_ui_proxy_config_service()) { + // |ui_proxy_config_service| may be missing in tests. If the device is offline + // (no network connected) the |DefaultNetwork| is null. + if (network_handler->has_ui_proxy_config_service() && + network_handler->network_state_handler()->DefaultNetwork()) { // Check if proxy is enforced by user policy, a forced install extension or // ONC policies. This will only read managed settings. network_handler->ui_proxy_config_service()->MergeEnforcedProxyConfig( @@ -682,41 +705,44 @@ base::Value ManagementUIHandler::GetThreatProtectionInfo( const policy::PolicyService* policy_service = GetPolicyService(); const auto& chrome_policies = policy_service->GetPolicies( policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string())); - // CheckContentCompliance is a int-enum policy. The accepted values are - // defined in the enum CheckContentComplianceValues. - auto* check_content_compliance_value = - chrome_policies.GetValue(policy::key::kCheckContentCompliance); - if (check_content_compliance_value && - check_content_compliance_value->GetInt() > safe_browsing::CHECK_NONE && - check_content_compliance_value->GetInt() <= - safe_browsing::CHECK_CONTENT_COMPLIANCE_MAX) { + + auto* on_file_attached = + chrome_policies.GetValue(policy::key::kOnFileAttachedEnterpriseConnector); + if (on_file_attached && on_file_attached->is_list() && + !on_file_attached->GetList().empty()) { + base::Value value(base::Value::Type::DICTIONARY); + value.SetStringKey("title", kManagementOnFileAttachedEvent); + value.SetStringKey("permission", kManagementOnFileAttachedVisibleData); + info.Append(std::move(value)); + } + + auto* on_file_downloaded = chrome_policies.GetValue( + policy::key::kOnFileDownloadedEnterpriseConnector); + if (on_file_downloaded && on_file_downloaded->is_list() && + !on_file_downloaded->GetList().empty()) { base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("title", kManagementDataLossPreventionName); - value.SetStringKey("permission", kManagementDataLossPreventionPermissions); + value.SetStringKey("title", kManagementOnFileDownloadedEvent); + value.SetStringKey("permission", kManagementOnFileDownloadedVisibleData); info.Append(std::move(value)); } - // SendFilesForMalwareCheck is a int-enum policy. The accepted values are - // defined in the enum SendFilesForMalwareCheckValues. - auto* send_files_for_malware_check_value = - chrome_policies.GetValue(policy::key::kSendFilesForMalwareCheck); - if (send_files_for_malware_check_value && - send_files_for_malware_check_value->GetInt() > - safe_browsing::DO_NOT_SCAN && - send_files_for_malware_check_value->GetInt() <= - safe_browsing::SEND_FILES_FOR_MALWARE_CHECK_MAX) { + auto* on_bulk_data_entry = chrome_policies.GetValue( + policy::key::kOnBulkDataEntryEnterpriseConnector); + if (on_bulk_data_entry && on_bulk_data_entry->is_list() && + !on_bulk_data_entry->GetList().empty()) { base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("title", kManagementMalwareScanningName); - value.SetStringKey("permission", kManagementMalwareScanningPermissions); + value.SetStringKey("title", kManagementOnBulkDataEntryEvent); + value.SetStringKey("permission", kManagementOnBulkDataEntryVisibleData); info.Append(std::move(value)); } - auto* unsafe_event_reporting_value = - chrome_policies.GetValue(policy::key::kUnsafeEventsReportingEnabled); - if (unsafe_event_reporting_value && unsafe_event_reporting_value->GetBool()) { + auto* on_security_event = chrome_policies.GetValue( + policy::key::kOnSecurityEventEnterpriseConnector); + if (on_security_event && on_security_event->is_list() && + !on_security_event->GetList().empty()) { base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("title", kManagementEnterpriseReportingName); - value.SetStringKey("permission", kManagementEnterpriseReportingPermissions); + value.SetStringKey("title", kManagementEnterpriseReportingEvent); + value.SetStringKey("permission", kManagementEnterpriseReportingVisibleData); info.Append(std::move(value)); } diff --git a/chromium/chrome/browser/ui/webui/management_ui_handler.h b/chromium/chrome/browser/ui/webui/management_ui_handler.h index 188d8d417a2..5612c90b3ac 100644 --- a/chromium/chrome/browser/ui/webui/management_ui_handler.h +++ b/chromium/chrome/browser/ui/webui/management_ui_handler.h @@ -33,6 +33,7 @@ extern const char kManagementReportHardwareStatus[]; extern const char kManagementReportNetworkInterfaces[]; extern const char kManagementReportUsers[]; extern const char kManagementReportCrashReports[]; +extern const char kManagementReportAppInfoAndActivity[]; extern const char kManagementPrinting[]; extern const char kManagementCrostini[]; extern const char kManagementCrostiniContainerConfiguration[]; @@ -59,8 +60,14 @@ extern const char kManagementDataLossPreventionName[]; extern const char kManagementDataLossPreventionPermissions[]; extern const char kManagementMalwareScanningName[]; extern const char kManagementMalwareScanningPermissions[]; -extern const char kManagementEnterpriseReportingName[]; -extern const char kManagementEnterpriseReportingPermissions[]; +extern const char kManagementEnterpriseReportingEvent[]; +extern const char kManagementEnterpriseReportingVisibleData[]; +extern const char kManagementOnFileAttachedEvent[]; +extern const char kManagementOnFileAttachedVisibleData[]; +extern const char kManagementOnFileDownloadedEvent[]; +extern const char kManagementOnFileDownloadedVisibleData[]; +extern const char kManagementOnBulkDataEntryEvent[]; +extern const char kManagementOnBulkDataEntryVisibleData[]; extern const char kPolicyKeyReportMachineIdData[]; extern const char kPolicyKeyReportUserIdData[]; diff --git a/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc b/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc index 5da0346aaec..8973b687a5a 100644 --- a/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/management_ui_handler_unittest.cc @@ -7,6 +7,7 @@ #include <string> #include "base/files/file_path.h" +#include "base/json/json_reader.h" #include "base/memory/scoped_refptr.h" #include "base/strings/utf_string_conversions.h" @@ -48,7 +49,9 @@ #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chromeos/cryptohome/async_method_caller.h" +#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/power/power_manager_client.h" +#include "chromeos/dbus/shill/shill_service_client.h" #include "chromeos/network/network_state_handler.h" #include "chromeos/network/proxy/proxy_config_handler.h" #include "chromeos/network/proxy/ui_proxy_config_service.h" @@ -64,6 +67,7 @@ #include "components/proxy_config/proxy_config_pref_names.h" #include "components/sync_preferences/testing_pref_service_syncable.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" +#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" #include "ui/chromeos/devicetype_utils.h" #endif // defined(OS_CHROMEOS) @@ -96,13 +100,15 @@ class TestDeviceStatusCollector : public policy::DeviceStatusCollector { bool report_nics, bool report_users, bool report_hw_status, - bool report_crash_info) + bool report_crash_info, + bool report_app_info_and_activity) : policy::DeviceStatusCollector(local_state, nullptr), report_activity_times_(report_activity_times), report_nics_(report_nics), report_users_(report_users), report_hw_status_(report_hw_status), - report_crash_info_(report_crash_info) {} + report_crash_info_(report_crash_info), + report_app_info_and_activity_(report_app_info_and_activity) {} ~TestDeviceStatusCollector() override = default; bool ShouldReportActivityTimes() const override { @@ -114,8 +120,12 @@ class TestDeviceStatusCollector : public policy::DeviceStatusCollector { bool ShouldReportCrashReportInfo() const override { return report_crash_info_; } + bool ShouldReportAppInfoAndActivity() const override { + return report_app_info_and_activity_; + } - // empty methods that need to be implemented but are of no use for this case. + // empty methods that need to be implemented but are of no use for this + // case. void GetStatusAsync( const policy::StatusCollectorCallback& callback) override {} void OnSubmittedSuccessfully() override {} @@ -126,6 +136,7 @@ class TestDeviceStatusCollector : public policy::DeviceStatusCollector { bool report_users_; bool report_hw_status_; bool report_crash_info_; + bool report_app_info_and_activity_; }; class TestDeviceCloudPolicyManagerChromeOS @@ -242,19 +253,29 @@ class ManagementUIHandlerTests : public TestingBaseClass { std::make_unique<base::Value>(true), nullptr); } void SetPolicyValue(const char* policy_key, - policy::PolicyMap& policies, - int value) { + int value, + policy::PolicyMap& policies) { policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(value), nullptr); } void SetPolicyValue(const char* policy_key, - policy::PolicyMap& policies, - bool value) { + bool value, + policy::PolicyMap& policies) { policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD, std::make_unique<base::Value>(value), nullptr); } + void SetConnectorPolicyValue(const char* policy_key, + const std::string& value, + policy::PolicyMap& policies) { + auto policy_value = base::JSONReader::Read(value); + EXPECT_TRUE(policy_value.has_value()); + policies.Set(policy_key, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_CLOUD, + std::make_unique<base::Value>(std::move(policy_value.value())), + nullptr); + } base::string16 ExtractPathFromDict(const base::Value& data, const std::string path) { @@ -286,6 +307,7 @@ class ManagementUIHandlerTests : public TestingBaseClass { bool report_users; bool report_hw_status; bool report_crash_info; + bool report_app_info_and_activity; bool upload_enabled; bool printing_send_username_and_filename; bool crostini_report_usage; @@ -306,6 +328,7 @@ class ManagementUIHandlerTests : public TestingBaseClass { setup_config_.report_users = default_value; setup_config_.report_hw_status = default_value; setup_config_.report_crash_info = default_value; + setup_config_.report_app_info_and_activity = default_value; setup_config_.upload_enabled = default_value; setup_config_.printing_send_username_and_filename = default_value; setup_config_.crostini_report_usage = default_value; @@ -328,6 +351,11 @@ class ManagementUIHandlerTests : public TestingBaseClass { crostini_features_ = std::make_unique<crostini::FakeCrostiniFeatures>(); SetUpConnectManager(); chromeos::NetworkHandler::Initialize(); + // The |DeviceSettingsTestBase| setup above instantiates + // |FakeShillManagerClient| with a default environment which will post + // tasks on the current thread to setup a initial network configuration with + // a connected default network. + base::RunLoop().RunUntilIdle(); } void TearDown() override { chromeos::NetworkHandler::Shutdown(); @@ -355,8 +383,8 @@ class ManagementUIHandlerTests : public TestingBaseClass { new TestDeviceStatusCollector( &local_state_, GetTestConfig().report_activity_times, GetTestConfig().report_nics, GetTestConfig().report_users, - GetTestConfig().report_hw_status, - GetTestConfig().report_crash_info); + GetTestConfig().report_hw_status, GetTestConfig().report_crash_info, + GetTestConfig().report_app_info_and_activity); settings_.device_settings()->SetTrustedStatus( chromeos::CrosSettingsProvider::TRUSTED); settings_.device_settings()->SetBoolean(chromeos::kSystemLogUploadEnabled, @@ -528,8 +556,8 @@ AssertionResult ReportingElementsToBeEQ( } if (!tmp_expected.empty()) { AssertionResult result = AssertionFailure(); - result - << " the following messageId and reportingTypes could not be matched {"; + result << " the following messageId and reportingTypes could not be " + "matched {"; for (const auto& element : tmp_expected) { result << " messageId: " << element.first << ", reportingType " << element.second; @@ -795,6 +823,7 @@ TEST_F(ManagementUIHandlerTests, AllEnabledDeviceReportingInfo) { {kManagementReportHardwareStatus, "device statistics"}, {kManagementReportNetworkInterfaces, "device"}, {kManagementReportCrashReports, "crash report"}, + {kManagementReportAppInfoAndActivity, "app info and activity"}, {kManagementLogUploadEnabled, "logs"}, {kManagementPrinting, "print"}, {kManagementCrostini, "crostini"}, @@ -816,6 +845,7 @@ TEST_F(ManagementUIHandlerTests, {kManagementReportHardwareStatus, "device statistics"}, {kManagementReportNetworkInterfaces, "device"}, {kManagementReportCrashReports, "crash report"}, + {kManagementReportAppInfoAndActivity, "app info and activity"}, {kManagementLogUploadEnabled, "logs"}, {kManagementPrinting, "print"}, {kManagementCrostiniContainerConfiguration, "crostini"}, @@ -868,6 +898,39 @@ TEST_F(ManagementUIHandlerTests, ProxyServerShowReport) { expected_elements); } +TEST_F(ManagementUIHandlerTests, ProxyServerShowReportDeviceOffline) { + PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry()); + chromeos::NetworkHandler::Get()->InitializePrefServices(&user_prefs_, + &local_state_); + // Simulate network disconnected state. + chromeos::NetworkStateHandler::NetworkStateList networks; + chromeos::NetworkHandler::Get() + ->network_state_handler() + ->GetNetworkListByType(chromeos::NetworkTypePattern::Default(), + true, // configured_only + false, // visible_only, + 0, // no limit to number of results + &networks); + chromeos::ShillServiceClient::TestInterface* service = + chromeos::DBusThreadManager::Get() + ->GetShillServiceClient() + ->GetTestInterface(); + for (const auto* const network : networks) { + service->SetServiceProperty(network->path(), shill::kStateProperty, + base::Value(shill::kStateOffline)); + } + base::RunLoop().RunUntilIdle(); + + ResetTestConfig(false); + const base::Value info = SetUpForReportingInfo(); + + const std::map<std::string, std::string> expected_elements = {}; + + ASSERT_PRED_FORMAT2(ReportingElementsToBeEQ, info.GetList(), + expected_elements); + chromeos::NetworkHandler::Get()->NetworkHandler::ShutdownPrefServices(); +} + TEST_F(ManagementUIHandlerTests, ProxyServerHideReportForDirectProxy) { PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry()); chromeos::NetworkHandler::Get()->InitializePrefServices(&user_prefs_, @@ -885,6 +948,7 @@ TEST_F(ManagementUIHandlerTests, ProxyServerHideReportForDirectProxy) { const std::map<std::string, std::string> expected_elements = {}; ASSERT_PRED_FORMAT2(ReportingElementsToBeEQ, info.GetList(), expected_elements); + chromeos::NetworkHandler::Get()->NetworkHandler::ShutdownPrefServices(); } #endif @@ -918,7 +982,7 @@ TEST_F(ManagementUIHandlerTests, CloudReportingPolicy) { policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string()); EXPECT_CALL(policy_service_, GetPolicies(_)) .WillRepeatedly(ReturnRef(chrome_policies)); - SetPolicyValue(policy::key::kCloudReportingEnabled, chrome_policies, true); + SetPolicyValue(policy::key::kCloudReportingEnabled, true, chrome_policies); const std::set<std::string> expected_messages = { kManagementExtensionReportMachineName, kManagementExtensionReportUsername, @@ -1020,10 +1084,15 @@ TEST_F(ManagementUIHandlerTests, ThreatReportingInfo) { base::UTF8ToUTF16(*threat_protection_info->FindStringKey("description"))); // When policies are set to uninteresting values, nothing to report. - SetPolicyValue(policy::key::kCheckContentCompliance, chrome_policies, 0); - SetPolicyValue(policy::key::kSendFilesForMalwareCheck, chrome_policies, 0); - SetPolicyValue(policy::key::kUnsafeEventsReportingEnabled, chrome_policies, - false); + SetConnectorPolicyValue(policy::key::kOnFileAttachedEnterpriseConnector, "[]", + chrome_policies); + SetConnectorPolicyValue(policy::key::kOnFileDownloadedEnterpriseConnector, + "[]", chrome_policies); + SetConnectorPolicyValue(policy::key::kOnBulkDataEntryEnterpriseConnector, + "[]", chrome_policies); + SetConnectorPolicyValue(policy::key::kOnSecurityEventEnterpriseConnector, + "[]", chrome_policies); + info = handler_.GetThreatProtectionInfo(profile_known_domain.get()); info.GetAsDictionary(&threat_protection_info); EXPECT_TRUE(threat_protection_info->FindListKey("info")->GetList().empty()); @@ -1032,13 +1101,22 @@ TEST_F(ManagementUIHandlerTests, ThreatReportingInfo) { base::UTF8ToUTF16(*threat_protection_info->FindStringKey("description"))); // When policies are set to values that enable the feature, report it. - SetPolicyValue(policy::key::kCheckContentCompliance, chrome_policies, 1); - SetPolicyValue(policy::key::kSendFilesForMalwareCheck, chrome_policies, 2); - SetPolicyValue(policy::key::kUnsafeEventsReportingEnabled, chrome_policies, - true); + SetConnectorPolicyValue(policy::key::kOnFileAttachedEnterpriseConnector, + "[{\"service_provider\":\"google\"}]", + chrome_policies); + SetConnectorPolicyValue(policy::key::kOnFileDownloadedEnterpriseConnector, + "[{\"service_provider\":\"google\"}]", + chrome_policies); + SetConnectorPolicyValue(policy::key::kOnBulkDataEntryEnterpriseConnector, + "[{\"service_provider\":\"google\"}]", + chrome_policies); + SetConnectorPolicyValue(policy::key::kOnSecurityEventEnterpriseConnector, + "[{\"service_provider\":\"google\"}]", + chrome_policies); + info = handler_.GetThreatProtectionInfo(profile_no_domain.get()); info.GetAsDictionary(&threat_protection_info); - EXPECT_EQ(3u, threat_protection_info->FindListKey("info")->GetList().size()); + EXPECT_EQ(4u, threat_protection_info->FindListKey("info")->GetList().size()); EXPECT_EQ( l10n_util::GetStringUTF16(IDS_MANAGEMENT_THREAT_PROTECTION_DESCRIPTION), base::UTF8ToUTF16(*threat_protection_info->FindStringKey("description"))); @@ -1046,20 +1124,26 @@ TEST_F(ManagementUIHandlerTests, ThreatReportingInfo) { base::Value expected_info(base::Value::Type::LIST); { base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("title", kManagementDataLossPreventionName); - value.SetStringKey("permission", kManagementDataLossPreventionPermissions); + value.SetStringKey("title", kManagementOnFileAttachedEvent); + value.SetStringKey("permission", kManagementOnFileAttachedVisibleData); + expected_info.Append(std::move(value)); + } + { + base::Value value(base::Value::Type::DICTIONARY); + value.SetStringKey("title", kManagementOnFileDownloadedEvent); + value.SetStringKey("permission", kManagementOnFileDownloadedVisibleData); expected_info.Append(std::move(value)); } { base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("title", kManagementMalwareScanningName); - value.SetStringKey("permission", kManagementMalwareScanningPermissions); + value.SetStringKey("title", kManagementOnBulkDataEntryEvent); + value.SetStringKey("permission", kManagementOnBulkDataEntryVisibleData); expected_info.Append(std::move(value)); } { base::Value value(base::Value::Type::DICTIONARY); - value.SetStringKey("title", kManagementEnterpriseReportingName); - value.SetStringKey("permission", kManagementEnterpriseReportingPermissions); + value.SetStringKey("title", kManagementEnterpriseReportingEvent); + value.SetStringKey("permission", kManagementEnterpriseReportingVisibleData); expected_info.Append(std::move(value)); } diff --git a/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc index 9fe5e0b04b8..5ef3915cd3f 100644 --- a/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc +++ b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.cc @@ -64,13 +64,16 @@ void MediaFeedsUI::GetMediaFeeds(GetMediaFeedsCallback callback) { void MediaFeedsUI::GetItemsForMediaFeed(int64_t feed_id, GetItemsForMediaFeedCallback callback) { - GetMediaHistoryService()->GetItemsForMediaFeedForDebug(feed_id, - std::move(callback)); + GetMediaHistoryService()->GetMediaFeedItems( + media_history::MediaHistoryKeyedService::GetMediaFeedItemsRequest:: + CreateItemsForDebug(feed_id), + std::move(callback)); } void MediaFeedsUI::FetchMediaFeed(int64_t feed_id, FetchMediaFeedCallback callback) { - GetMediaFeedsService()->FetchMediaFeed(feed_id, std::move(callback)); + GetMediaFeedsService()->FetchMediaFeed(feed_id, /*bypass_cache=*/false, + nullptr, std::move(callback)); } void MediaFeedsUI::GetDebugInformation(GetDebugInformationCallback callback) { @@ -81,6 +84,11 @@ void MediaFeedsUI::GetDebugInformation(GetDebugInformationCallback callback) { info->safe_search_pref_value = GetProfile()->GetPrefs()->GetBoolean(prefs::kMediaFeedsSafeSearchEnabled); + info->background_fetching_feature_enabled = + base::FeatureList::IsEnabled(media::kMediaFeedsBackgroundFetching); + info->background_fetching_pref_value = GetProfile()->GetPrefs()->GetBoolean( + prefs::kMediaFeedsBackgroundFetching); + std::move(callback).Run(std::move(info)); } @@ -93,6 +101,15 @@ void MediaFeedsUI::SetSafeSearchEnabledPref( std::move(callback).Run(); } +void MediaFeedsUI::SetBackgroundFetchingPref( + bool value, + SetBackgroundFetchingPrefCallback callback) { + GetProfile()->GetPrefs()->SetBoolean(prefs::kMediaFeedsBackgroundFetching, + value); + + std::move(callback).Run(); +} + media_history::MediaHistoryKeyedService* MediaFeedsUI::GetMediaHistoryService() { media_history::MediaHistoryKeyedService* service = diff --git a/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h index 73de089c839..dc382578d43 100644 --- a/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h +++ b/chromium/chrome/browser/ui/webui/media/media_feeds_ui.h @@ -40,6 +40,9 @@ class MediaFeedsUI : public ui::MojoWebUIController, void SetSafeSearchEnabledPref( bool value, SetSafeSearchEnabledPrefCallback callback) override; + void SetBackgroundFetchingPref( + bool value, + SetBackgroundFetchingPrefCallback callback) override; private: media_history::MediaHistoryKeyedService* GetMediaHistoryService(); diff --git a/chromium/chrome/browser/ui/webui/memory_internals_ui.cc b/chromium/chrome/browser/ui/webui/memory_internals_ui.cc index a8a4beaa73a..d7564825f8e 100644 --- a/chromium/chrome/browser/ui/webui/memory_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/memory_internals_ui.cc @@ -17,7 +17,6 @@ #include "base/process/process_handle.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/post_task.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiling_host/profiling_process_host.h" @@ -209,8 +208,8 @@ void MemoryInternalsDOMHandler::HandleRequestProcessList( // This is called on the UI thread, the child process iterator must run on // the IO thread, while the render process iterator must run on the UI thread. - base::PostTask( - FROM_HERE, {content::BrowserThread::IO}, + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&MemoryInternalsDOMHandler::GetChildProcessesOnIOThread, weak_factory_.GetWeakPtr(), std::move(callback_id))); } @@ -297,8 +296,8 @@ void MemoryInternalsDOMHandler::GetChildProcessesOnIOThread( } } - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&MemoryInternalsDOMHandler::GetProfiledPids, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&MemoryInternalsDOMHandler::GetProfiledPids, dom_handler, callback_id, std::move(result))); } @@ -311,8 +310,8 @@ void MemoryInternalsDOMHandler::GetProfiledPids( // The supervisor hasn't started, so return an empty list. if (!supervisor->HasStarted()) { - base::PostTask( - FROM_HERE, {content::BrowserThread::UI}, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&MemoryInternalsDOMHandler::ReturnProcessListOnUIThread, weak_factory_.GetWeakPtr(), callback_id, std::move(children), std::vector<base::ProcessId>())); diff --git a/chromium/chrome/browser/ui/webui/nacl_ui.cc b/chromium/chrome/browser/ui/webui/nacl_ui.cc index c3f6b40f6eb..c784e81a33b 100644 --- a/chromium/chrome/browser/ui/webui/nacl_ui.cc +++ b/chromium/chrome/browser/ui/webui/nacl_ui.cc @@ -43,6 +43,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" #include "content/public/common/webplugininfo.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #if defined(OS_WIN) @@ -60,7 +61,8 @@ namespace { content::WebUIDataSource* CreateNaClUIHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUINaClHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->UseStringsJs(); source->AddResourcePath("about_nacl.css", IDR_ABOUT_NACL_CSS); diff --git a/chromium/chrome/browser/ui/webui/nearby_internals/OWNERS b/chromium/chrome/browser/ui/webui/nearby_internals/OWNERS new file mode 100644 index 00000000000..19414dc942a --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_internals/OWNERS @@ -0,0 +1,4 @@ +file://chrome/browser/nearby_sharing/OWNERS +khorimoto@chromium.org + +# COMPONENT: OS>Systems>Multidevice>Nearby diff --git a/chromium/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.cc b/chromium/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.cc new file mode 100644 index 00000000000..bcbd409aa3f --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.cc @@ -0,0 +1,44 @@ +// Copyright 2020 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/nearby_internals/nearby_internals_ui.h" + +#include "base/containers/span.h" +#include "base/feature_list.h" +#include "chrome/browser/browser_features.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/nearby_internals_resources.h" +#include "chrome/grit/nearby_internals_resources_map.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/base/webui/web_ui_util.h" + +namespace { +constexpr char kNearbyInternalsGeneratedPath[] = + "@out_folder@/gen/chrome/browser/resources/nearby_internals/"; +} // namespace + +NearbyInternalsUI::NearbyInternalsUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + // Nearby Sharing is not available to incognito or guest profiles. + DCHECK(profile->IsRegularProfile()); + DCHECK(base::FeatureList::IsEnabled(features::kNearbySharing)); + + content::WebUIDataSource* html_source = + content::WebUIDataSource::Create(chrome::kChromeUINearbyInternalsHost); + + webui::SetupWebUIDataSource( + html_source, + base::make_span(kNearbyInternalsResources, kNearbyInternalsResourcesSize), + kNearbyInternalsGeneratedPath, IDR_NEARBY_INTERNALS_INDEX_HTML); + + content::WebUIDataSource::Add(profile, html_source); +} + +NearbyInternalsUI::~NearbyInternalsUI() = default; + +WEB_UI_CONTROLLER_TYPE_IMPL(NearbyInternalsUI) diff --git a/chromium/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h b/chromium/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h new file mode 100644 index 00000000000..60073afcea2 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_internals/nearby_internals_ui.h @@ -0,0 +1,22 @@ +// Copyright 2020 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_NEARBY_INTERNALS_NEARBY_INTERNALS_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_NEARBY_INTERNALS_NEARBY_INTERNALS_UI_H_ + +#include "ui/webui/mojo_web_ui_controller.h" + +// The WebUI controller for chrome://nearby-sharing-internals. +class NearbyInternalsUI : public ui::MojoWebUIController { + public: + explicit NearbyInternalsUI(content::WebUI* web_ui); + NearbyInternalsUI(const NearbyInternalsUI&) = delete; + NearbyInternalsUI& operator=(const NearbyInternalsUI&) = delete; + ~NearbyInternalsUI() override; + + private: + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_NEARBY_INTERNALS_NEARBY_INTERNALS_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/nearby_share/OWNERS b/chromium/chrome/browser/ui/webui/nearby_share/OWNERS new file mode 100644 index 00000000000..72feb28bcca --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_share/OWNERS @@ -0,0 +1,3 @@ +file://chrome/browser/nearby_sharing/OWNERS + +# COMPONENT: UI>Browser>Sharing>Nearby diff --git a/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc b/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc new file mode 100644 index 00000000000..e058ccdf390 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.cc @@ -0,0 +1,52 @@ +// Copyright 2020 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/nearby_share/nearby_share_dialog_ui.h" + +#include <string> + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/generated_resources.h" +#include "chrome/grit/nearby_share_dialog_resources.h" +#include "chrome/grit/nearby_share_dialog_resources_map.h" +#include "chrome/grit/theme_resources.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/webui/web_ui_util.h" + +namespace { + +constexpr char kNearbyShareGeneratedPath[] = + "@out_folder@/gen/chrome/browser/resources/nearby_share/"; + +} // namespace + +namespace nearby_share { + +NearbyShareDialogUI::NearbyShareDialogUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + // Nearby Share is not available to incognito or guest profiles. + DCHECK(profile->IsRegularProfile()); + + content::WebUIDataSource* html_source = + content::WebUIDataSource::Create(chrome::kChromeUINearbyShareHost); + + webui::SetupWebUIDataSource(html_source, + base::make_span(kNearbyShareDialogResources, + kNearbyShareDialogResourcesSize), + kNearbyShareGeneratedPath, + IDR_NEARBY_SHARE_NEARBY_SHARE_DIALOG_HTML); + + content::WebUIDataSource::Add(profile, html_source); +} + +NearbyShareDialogUI::~NearbyShareDialogUI() = default; + +WEB_UI_CONTROLLER_TYPE_IMPL(NearbyShareDialogUI) + +} // namespace nearby_share diff --git a/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h b/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h new file mode 100644 index 00000000000..5a9ba400ba0 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui.h @@ -0,0 +1,26 @@ +// Copyright 2020 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_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_ + +#include "ui/webui/mojo_web_ui_controller.h" + +namespace nearby_share { + +// The WebUI controller for chrome://nearby. +class NearbyShareDialogUI : public ui::MojoWebUIController { + public: + explicit NearbyShareDialogUI(content::WebUI* web_ui); + NearbyShareDialogUI(const NearbyShareDialogUI&) = delete; + NearbyShareDialogUI& operator=(const NearbyShareDialogUI&) = delete; + ~NearbyShareDialogUI() override; + + private: + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +} // namespace nearby_share + +#endif // CHROME_BROWSER_UI_WEBUI_NEARBY_SHARE_NEARBY_SHARE_DIALOG_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui_browsertest.cc new file mode 100644 index 00000000000..a991a02feb9 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/nearby_share/nearby_share_dialog_ui_browsertest.cc @@ -0,0 +1,50 @@ +// Copyright 2020 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 "base/test/scoped_feature_list.h" +#include "chrome/browser/browser_features.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "url/gurl.h" + +namespace { + +class NearbyShareDialogUITest : public InProcessBrowserTest { + public: + NearbyShareDialogUITest() { + scoped_feature_list_.InitWithFeatures({features::kNearbySharing}, {}); + } + ~NearbyShareDialogUITest() override = default; + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +} // namespace + +IN_PROC_BROWSER_TEST_F(NearbyShareDialogUITest, RendersComponent) { + // First, check that navigation succeeds. + GURL kUrl(content::GetWebUIURL(chrome::kChromeUINearbyShareHost)); + ui_test_utils::NavigateToURL(browser(), kUrl); + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_TRUE(web_contents); + EXPECT_EQ(kUrl, web_contents->GetLastCommittedURL()); + EXPECT_FALSE(web_contents->IsCrashed()); + + // Assert that we render the nearby-share-app component. + int num_nearby_share_app = -1; + ASSERT_TRUE(content::ExecuteScriptAndExtractInt( + web_contents, + "domAutomationController.send(" + "document.getElementsByTagName('nearby-share-app').length)", + &num_nearby_share_app)); + EXPECT_EQ(1, num_nearby_share_app); +} diff --git a/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc index 434c438bb2b..bb8debc7d6e 100644 --- a/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/net_internals/net_internals_ui.cc @@ -12,21 +12,14 @@ #include "base/bind_helpers.h" #include "base/command_line.h" #include "base/files/file_path.h" -#include "base/files/file_util.h" #include "base/memory/weak_ptr.h" -#include "base/task/post_task.h" -#include "base/task/thread_pool.h" #include "base/values.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/download/download_prefs.h" #include "chrome/browser/net/net_export_helper.h" -#include "chrome/browser/policy/chrome_policy_conversions_client.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/net_internals_resources.h" -#include "components/onc/onc_constants.h" -#include "components/policy/core/browser/policy_conversions.h" #include "components/prefs/pref_member.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -38,23 +31,9 @@ #include "content/public/browser/web_ui_message_handler.h" #include "net/log/net_log_util.h" #include "services/network/expect_ct_reporter.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/file_manager/filesystem_api_util.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/chromeos/system_logs/debug_log_writer.h" -#include "chrome/browser/chromeos/system_logs/system_logs_writer.h" -#include "chrome/browser/net/nss_context.h" -#include "chrome/common/logging_chrome.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" -#include "chromeos/network/onc/onc_certificate_importer_impl.h" -#include "chromeos/network/onc/onc_parsed_certificates.h" -#include "chromeos/network/onc/onc_utils.h" -#include "components/policy/core/browser/policy_conversions.h" -#endif - using content::BrowserThread; namespace { @@ -62,7 +41,8 @@ namespace { content::WebUIDataSource* CreateNetInternalsHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUINetInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->SetDefaultResource(IDR_NET_INTERNALS_INDEX_HTML); @@ -73,28 +53,6 @@ content::WebUIDataSource* CreateNetInternalsHTMLSource() { void IgnoreBoolCallback(bool result) {} -#if defined(OS_CHROMEOS) -base::FilePath GetDownloadsDirectory(content::WebUI* web_ui) { - Profile* profile = Profile::FromWebUI(web_ui); - const DownloadPrefs* const prefs = DownloadPrefs::FromBrowserContext(profile); - base::FilePath path = prefs->DownloadPath(); - if (file_manager::util::IsUnderNonNativeLocalPath(profile, path)) - path = prefs->GetDefaultDownloadDirectoryForProfile(); - return path; -} - -std::string GetJsonPolicies(content::WebUI* web_ui) { - auto client = std::make_unique<policy::ChromePolicyConversionsClient>( - web_ui->GetWebContents()->GetBrowserContext()); - return policy::DictionaryPolicyConversions(std::move(client)).ToJSON(); -} - -void WriteTimestampedFile(base::FilePath file_path, std::string contents) { - file_path = logging::GenerateTimestampedName(file_path, base::Time::Now()); - base::WriteFile(file_path, contents.data(), contents.size()); -} -#endif - // This class receives javascript messages from the renderer. // Note that the WebUI infrastructure runs on the UI thread, therefore all of // this class's methods are expected to run on the UI thread. @@ -116,20 +74,6 @@ class NetInternalsMessageHandler // If the renderer is displaying a log file, the message will be ignored. void SendJavascriptCommand(const std::string& command, base::Value arg); -#if defined(OS_CHROMEOS) - // Callback to |GetNSSCertDatabaseForProfile| used to retrieve the database - // to which user's ONC defined certificates should be imported. - // It parses and imports |onc_blob|. - void ImportONCFileToNSSDB(const std::string& onc_blob, - const std::string& passcode, - net::NSSCertDatabase* nssdb); - - // Called back by the CertificateImporter when a certificate import finished. - // |previous_error| contains earlier errors during this import. - void OnCertificatesImported(const std::string& previous_error, - bool cert_import_success); -#endif - void OnExpectCTTestReportCallback(bool success); //-------------------------------- @@ -147,27 +91,6 @@ class NetInternalsMessageHandler void OnExpectCTTestReport(const base::ListValue* list); void OnCloseIdleSockets(const base::ListValue* list); void OnFlushSocketPools(const base::ListValue* list); -#if defined(OS_CHROMEOS) - void OnWritePolicyLogsCompleted(const base::FilePath& path, - bool should_compress, - bool combined, - const char* received_event); - void OnImportONCFile(const base::ListValue* list); - void OnStoreDebugLogs(bool combined, - const char* received_event, - const base::ListValue* list); - void OnStoreDebugLogsCompleted(const char* received_event, - const base::FilePath& log_path, - bool succeeded); - void OnStoreFeedbackSystemLogs(const char* received_event, - const base::ListValue* list); - void OnStoreFeedbackSystemLogsCompleted( - const char* received_event, - base::Optional<base::FilePath> system_logs_path); - void OnSetNetworkDebugMode(const base::ListValue* list); - void OnSetNetworkDebugModeCompleted(const std::string& subsystem, - bool succeeded); -#endif content::WebUI* web_ui_; @@ -223,31 +146,6 @@ void NetInternalsMessageHandler::RegisterMessages() { "flushSocketPools", base::BindRepeating(&NetInternalsMessageHandler::OnFlushSocketPools, base::Unretained(this))); -#if defined(OS_CHROMEOS) - web_ui()->RegisterMessageCallback( - "importONCFile", - base::BindRepeating(&NetInternalsMessageHandler::OnImportONCFile, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( - "storeDebugLogs", - base::BindRepeating(&NetInternalsMessageHandler::OnStoreDebugLogs, - base::Unretained(this), false /* combined */, - "receivedStoreDebugLogs")); - web_ui()->RegisterMessageCallback( - "storeCombinedDebugLogs", - base::BindRepeating(&NetInternalsMessageHandler::OnStoreDebugLogs, - base::Unretained(this), true /* combined */, - "receivedStoreCombinedDebugLogs")); - web_ui()->RegisterMessageCallback( - "storeFeedbackSystemLogs", - base::BindRepeating( - &NetInternalsMessageHandler::OnStoreFeedbackSystemLogs, - base::Unretained(this), "receivedStoreFeedbackSystemLogs")); - web_ui()->RegisterMessageCallback( - "setNetworkDebugMode", - base::BindRepeating(&NetInternalsMessageHandler::OnSetNetworkDebugMode, - base::Unretained(this))); -#endif } void NetInternalsMessageHandler::SendJavascriptCommand( @@ -321,12 +219,17 @@ void NetInternalsMessageHandler::OnHSTSAdd(const base::ListValue* list) { void NetInternalsMessageHandler::OnExpectCTQuery(const base::ListValue* list) { // |list| should be: [<domain to query>]. std::string domain; - bool domain_result = list->GetString(0, &domain); - DCHECK(domain_result); + bool result = list->GetString(0, &domain); + DCHECK(result); + + url::Origin origin = url::Origin::Create(GURL("https://" + domain)); GetNetworkContext()->GetExpectCTState( - domain, base::BindOnce(&NetInternalsMessageHandler::SendJavascriptCommand, - this->AsWeakPtr(), "receivedExpectCTResult")); + domain, + net::NetworkIsolationKey(origin /* top_frame_site */, + origin /* frame_site */), + base::BindOnce(&NetInternalsMessageHandler::SendJavascriptCommand, + this->AsWeakPtr(), "receivedExpectCTResult")); } void NetInternalsMessageHandler::OnExpectCTAdd(const base::ListValue* list) { @@ -339,6 +242,7 @@ void NetInternalsMessageHandler::OnExpectCTAdd(const base::ListValue* list) { // name. return; } + std::string report_uri_str; result = list->GetString(1, &report_uri_str); DCHECK(result); @@ -346,9 +250,14 @@ void NetInternalsMessageHandler::OnExpectCTAdd(const base::ListValue* list) { result = list->GetBoolean(2, &enforce); DCHECK(result); + url::Origin origin = url::Origin::Create(GURL("https://" + domain)); + base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000); - GetNetworkContext()->AddExpectCT(domain, expiry, enforce, - GURL(report_uri_str), base::DoNothing()); + GetNetworkContext()->AddExpectCT( + domain, expiry, enforce, GURL(report_uri_str), + net::NetworkIsolationKey(origin /* top_frame_site */, + origin /* frame_site */), + base::DoNothing()); } void NetInternalsMessageHandler::OnExpectCTTestReport( @@ -383,186 +292,6 @@ void NetInternalsMessageHandler::OnCloseIdleSockets( GetNetworkContext()->CloseIdleConnections(base::NullCallback()); } -#if defined(OS_CHROMEOS) -void NetInternalsMessageHandler::ImportONCFileToNSSDB( - const std::string& onc_blob, - const std::string& passcode, - net::NSSCertDatabase* nssdb) { - const user_manager::User* user = - chromeos::ProfileHelper::Get()->GetUserByProfile( - Profile::FromWebUI(web_ui())); - - if (!user) { - std::string error = "User not found."; - SendJavascriptCommand("receivedONCFileParse", base::Value(error)); - return; - } - - std::string error; - onc::ONCSource onc_source = onc::ONC_SOURCE_USER_IMPORT; - base::ListValue network_configs; - base::DictionaryValue global_network_config; - base::ListValue certificates; - if (!chromeos::onc::ParseAndValidateOncForImport(onc_blob, - onc_source, - passcode, - &network_configs, - &global_network_config, - &certificates)) { - error = "Errors occurred during the ONC parsing. "; - } - - std::string network_error; - chromeos::onc::ImportNetworksForUser(user, network_configs, &network_error); - if (!network_error.empty()) - error += network_error; - - chromeos::onc::CertificateImporterImpl cert_importer( - base::CreateSingleThreadTaskRunner({BrowserThread::IO}), nssdb); - auto certs = - std::make_unique<chromeos::onc::OncParsedCertificates>(certificates); - if (certs->has_error()) - error += "Some certificates couldn't be parsed. "; - cert_importer.ImportAllCertificatesUserInitiated( - certs->server_or_authority_certificates(), certs->client_certificates(), - base::BindOnce(&NetInternalsMessageHandler::OnCertificatesImported, - AsWeakPtr(), error /* previous_error */)); -} - -void NetInternalsMessageHandler::OnCertificatesImported( - const std::string& previous_error, - bool cert_import_success) { - std::string error = previous_error; - if (!cert_import_success) - error += "Some certificates couldn't be imported. "; - - SendJavascriptCommand("receivedONCFileParse", base::Value(error)); -} - -void NetInternalsMessageHandler::OnImportONCFile( - const base::ListValue* list) { - std::string onc_blob; - std::string passcode; - if (list->GetSize() != 2 || - !list->GetString(0, &onc_blob) || - !list->GetString(1, &passcode)) { - NOTREACHED(); - } - - GetNSSCertDatabaseForProfile( - Profile::FromWebUI(web_ui()), - base::Bind(&NetInternalsMessageHandler::ImportONCFileToNSSDB, AsWeakPtr(), - onc_blob, passcode)); -} - -void NetInternalsMessageHandler::OnStoreDebugLogs(bool combined, - const char* received_event, - const base::ListValue* list) { - DCHECK(list); - - SendJavascriptCommand(received_event, base::Value("Creating log file...")); - - base::FilePath path = GetDownloadsDirectory(web_ui()); - std::string json_policies = GetJsonPolicies(web_ui()); - base::ThreadPool::PostTaskAndReply( - FROM_HERE, - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(WriteTimestampedFile, path.Append("policies.json"), - json_policies), - base::BindOnce(&NetInternalsMessageHandler::OnWritePolicyLogsCompleted, - AsWeakPtr(), path, true /* should_compress */, combined, - received_event)); -} - -void NetInternalsMessageHandler::OnWritePolicyLogsCompleted( - const base::FilePath& path, - bool should_compress, - bool combined, - const char* received_event) { - if (combined) { - chromeos::DebugLogWriter::StoreCombinedLogs( - path, - base::BindOnce(&NetInternalsMessageHandler::OnStoreDebugLogsCompleted, - AsWeakPtr(), received_event)); - } else { - chromeos::DebugLogWriter::StoreLogs( - path, should_compress, - base::BindOnce(&NetInternalsMessageHandler::OnStoreDebugLogsCompleted, - AsWeakPtr(), received_event)); - } -} - -void NetInternalsMessageHandler::OnStoreDebugLogsCompleted( - const char* received_event, - const base::FilePath& log_path, - bool succeeded) { - std::string status; - if (succeeded) - status = "Created log file: " + log_path.BaseName().AsUTF8Unsafe(); - else - status = "Failed to create log file"; - SendJavascriptCommand(received_event, base::Value(status)); -} - -void NetInternalsMessageHandler::OnStoreFeedbackSystemLogs( - const char* received_event, - const base::ListValue* list) { - DCHECK(list); - SendJavascriptCommand(received_event, - base::Value("Creating system logs file...")); - - base::FilePath downloads_path = GetDownloadsDirectory(web_ui()); - std::string json_policies = GetJsonPolicies(web_ui()); - - // Write the policies file to disk as a blocking task, then call - // system_logs_writer::WriteSystemLogs to asynchronously write the system - // logs and respond when complete. - base::ThreadPool::PostTaskAndReply( - FROM_HERE, - {base::MayBlock(), base::TaskPriority::BEST_EFFORT, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, - base::BindOnce(WriteTimestampedFile, - downloads_path.Append("policies.json"), json_policies), - base::BindOnce( - chromeos::system_logs_writer::WriteSystemLogs, downloads_path, - base::BindOnce( - &NetInternalsMessageHandler::OnStoreFeedbackSystemLogsCompleted, - AsWeakPtr(), received_event))); -} - -void NetInternalsMessageHandler::OnStoreFeedbackSystemLogsCompleted( - const char* received_event, - base::Optional<base::FilePath> system_logs_path) { - std::string status = system_logs_path - ? "Created system_logs file: " + - system_logs_path->BaseName().AsUTF8Unsafe() - : "Failed to create system logs file."; - SendJavascriptCommand(received_event, base::Value(status)); -} - -void NetInternalsMessageHandler::OnSetNetworkDebugMode( - const base::ListValue* list) { - std::string subsystem; - if (list->GetSize() != 1 || !list->GetString(0, &subsystem)) - NOTREACHED(); - chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()->SetDebugMode( - subsystem, - base::BindOnce( - &NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted, - AsWeakPtr(), subsystem)); -} - -void NetInternalsMessageHandler::OnSetNetworkDebugModeCompleted( - const std::string& subsystem, - bool succeeded) { - std::string status = succeeded ? "Debug mode is changed to " - : "Failed to change debug mode to "; - status += subsystem; - SendJavascriptCommand("receivedSetNetworkDebugMode", base::Value(status)); -} -#endif // defined(OS_CHROMEOS) - network::mojom::NetworkContext* NetInternalsMessageHandler::GetNetworkContext() { return content::BrowserContext::GetDefaultStoragePartition( diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom index a16ed18a086..8be851977a7 100644 --- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom +++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom @@ -194,23 +194,36 @@ enum DoodleImageType { STATIC, }; -// The contents of simple and animated doodles. -struct ImageDoodleContent { +// An image doodle in either dark or light mode. +struct ImageDoodle { // Doodle image encoded as data URL. url.mojom.Url image_url; - // URL opened in new tab when the doodle is clicked. - url.mojom.Url on_click_url; // URL pointing to animated content (e.g. gif). Only set for animated doodles. url.mojom.Url? animation_url; + // Dimensions of the original image in pixels. + uint32 width; + uint32 height; + // Color of the background the doodle was designed for. If the NTP background + // differs from that color we show the doodle in a box of that color. + skia.mojom.SkColor background_color; // Specification of the share button. DoodleShareButton share_button; - // URL displayed to users, which they can use to share the doodle. - url.mojom.Url share_url; // URLs to be pinged when an image has been shown. url.mojom.Url image_impression_log_url; url.mojom.Url? animation_impression_log_url; }; +// The contents of simple and animated doodles. +struct ImageDoodleContent { + // Doodles for respective modes. + ImageDoodle light; + ImageDoodle? dark; + // URL opened in new tab when the doodle is clicked. + url.mojom.Url on_click_url; + // URL displayed to users, which they can use to share the doodle. + url.mojom.Url share_url; +}; + // The contents of interactive doodles. struct InteractiveDoodleContent { // URL pointing to doodle page. @@ -261,6 +274,33 @@ enum CustomizeDialogAction { SHORTCUTS_VISIBILITY_TOGGLE_CLICKED, }; +// Action the user performed while using voice search. Used for metrics logging +// only. Actions correspond to items in NTPLoggingEventType. +enum VoiceSearchAction { + ACTIVATE_SEARCH_BOX, + ACTIVATE_KEYBOARD, + CLOSE_OVERLAY, + QUERY_SUBMITTED, + SUPPORT_LINK_CLICKED, + TRY_AGAIN_LINK, + TRY_AGAIN_MIC_BUTTON, +}; + +// Errors occurred while using voice search. Errors correspond to items in +// NTPLoggingEventType. +enum VoiceSearchError { + ABORTED, + NO_SPEECH, + AUDIO_CAPTURE, + NETWORK, + NOT_ALLOWED, + LANGUAGE_NOT_SUPPORTED, + NO_MATCH, + SERVICE_NOT_ALLOWED, + BAD_GRAMMAR, + OTHER, +}; + // Used by the WebUI page to bootstrap bidirectional communication. interface PageHandlerFactory { // The WebUI page's |BrowserProxy| singleton calls this method when the page @@ -361,6 +401,10 @@ interface PageHandler { string? share_id); // Logs that a link on a promo has been clicked. OnPromoLinkClicked(); + // Logs an action performed while using voice search. + OnVoiceSearchAction(VoiceSearchAction action); + // Logs an error occurred while using voice search. + OnVoiceSearchError(VoiceSearchError error); // ======= REALBOX ======= // Queries autocomplete matches from the browser. diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc index 90498b1ccaa..7ee153fc40a 100644 --- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc +++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc @@ -32,7 +32,6 @@ #include "chrome/browser/search/chrome_colors/chrome_colors_factory.h" #include "chrome/browser/search/chrome_colors/chrome_colors_service.h" #include "chrome/browser/search/instant_service.h" -#include "chrome/browser/search/instant_service_factory.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/search_provider_logos/logo_service_factory.h" @@ -235,6 +234,55 @@ ntp_tiles::NTPTileImpression MakeNTPTileImpression( /*url_for_rappor=*/GURL() /* unused */); } +SkColor ParseHexColor(const std::string& color) { + SkColor result; + if (color.size() == 7 && color[0] == '#' && + base::HexStringToUInt(color.substr(1), &result)) { + return SkColorSetA(result, 255); + } + return SK_ColorTRANSPARENT; +} + +new_tab_page::mojom::ImageDoodlePtr MakeImageDoodle( + search_provider_logos::LogoType type, + const std::string& data, + const std::string& mime_type, + const GURL& animated_url, + int width_px, + int height_px, + const std::string& background_color, + int share_button_x, + int share_button_y, + const std::string& share_button_icon, + const std::string& share_button_bg, + GURL log_url, + GURL cta_log_url) { + auto doodle = new_tab_page::mojom::ImageDoodle::New(); + std::string base64; + base::Base64Encode(data, &base64); + doodle->image_url = GURL(base::StringPrintf( + "data:%s;base64,%s", mime_type.c_str(), base64.c_str())); + if (type == search_provider_logos::LogoType::ANIMATED) { + doodle->animation_url = animated_url; + } + doodle->width = width_px; + doodle->height = height_px; + doodle->background_color = ParseHexColor(background_color); + doodle->share_button = new_tab_page::mojom::DoodleShareButton::New(); + doodle->share_button->x = share_button_x; + doodle->share_button->y = share_button_y; + doodle->share_button->icon_url = GURL(base::StringPrintf( + "data:image/png;base64,%s", share_button_icon.c_str())); + doodle->share_button->background_color = ParseHexColor(share_button_bg); + if (type == search_provider_logos::LogoType::ANIMATED) { + doodle->image_impression_log_url = cta_log_url; + doodle->animation_impression_log_url = log_url; + } else { + doodle->image_impression_log_url = log_url; + } + return doodle; +} + } // namespace NewTabPageHandler::NewTabPageHandler( @@ -242,11 +290,13 @@ NewTabPageHandler::NewTabPageHandler( pending_page_handler, mojo::PendingRemote<new_tab_page::mojom::Page> pending_page, Profile* profile, + InstantService* instant_service, content::WebContents* web_contents, + NTPUserDataLogger* logger, const base::Time& ntp_navigation_start_time) : chrome_colors_service_( chrome_colors::ChromeColorsFactory::GetForProfile(profile)), - instant_service_(InstantServiceFactory::GetForProfile(profile)), + instant_service_(instant_service), ntp_background_service_( NtpBackgroundServiceFactory::GetForProfile(profile)), logo_service_(LogoServiceFactory::GetForProfile(profile)), @@ -263,7 +313,7 @@ NewTabPageHandler::NewTabPageHandler( BitmapFetcherServiceFactory::GetForBrowserContext(profile)), web_contents_(web_contents), ntp_navigation_start_time_(ntp_navigation_start_time), - logger_(NTPUserDataLogger::GetOrCreateFromWebContents(web_contents)), + logger_(logger), page_{std::move(pending_page)}, receiver_{this, std::move(pending_page_handler)} { CHECK(instant_service_); @@ -725,6 +775,73 @@ void NewTabPageHandler::OnPromoLinkClicked() { LogEvent(NTP_MIDDLE_SLOT_PROMO_LINK_CLICKED); } +void NewTabPageHandler::OnVoiceSearchAction( + new_tab_page::mojom::VoiceSearchAction action) { + NTPLoggingEventType event; + switch (action) { + case new_tab_page::mojom::VoiceSearchAction::ACTIVATE_SEARCH_BOX: + event = NTP_VOICE_ACTION_ACTIVATE_SEARCH_BOX; + break; + case new_tab_page::mojom::VoiceSearchAction::ACTIVATE_KEYBOARD: + event = NTP_VOICE_ACTION_ACTIVATE_KEYBOARD; + break; + case new_tab_page::mojom::VoiceSearchAction::CLOSE_OVERLAY: + event = NTP_VOICE_ACTION_CLOSE_OVERLAY; + break; + case new_tab_page::mojom::VoiceSearchAction::QUERY_SUBMITTED: + event = NTP_VOICE_ACTION_QUERY_SUBMITTED; + break; + case new_tab_page::mojom::VoiceSearchAction::SUPPORT_LINK_CLICKED: + event = NTP_VOICE_ACTION_SUPPORT_LINK_CLICKED; + break; + case new_tab_page::mojom::VoiceSearchAction::TRY_AGAIN_LINK: + event = NTP_VOICE_ACTION_TRY_AGAIN_LINK; + break; + case new_tab_page::mojom::VoiceSearchAction::TRY_AGAIN_MIC_BUTTON: + event = NTP_VOICE_ACTION_TRY_AGAIN_MIC_BUTTON; + break; + } + LogEvent(event); +} + +void NewTabPageHandler::OnVoiceSearchError( + new_tab_page::mojom::VoiceSearchError error) { + NTPLoggingEventType event; + switch (error) { + case new_tab_page::mojom::VoiceSearchError::ABORTED: + event = NTP_VOICE_ERROR_ABORTED; + break; + case new_tab_page::mojom::VoiceSearchError::NO_SPEECH: + event = NTP_VOICE_ERROR_NO_SPEECH; + break; + case new_tab_page::mojom::VoiceSearchError::AUDIO_CAPTURE: + event = NTP_VOICE_ERROR_AUDIO_CAPTURE; + break; + case new_tab_page::mojom::VoiceSearchError::NETWORK: + event = NTP_VOICE_ERROR_NETWORK; + break; + case new_tab_page::mojom::VoiceSearchError::NOT_ALLOWED: + event = NTP_VOICE_ERROR_NOT_ALLOWED; + break; + case new_tab_page::mojom::VoiceSearchError::LANGUAGE_NOT_SUPPORTED: + event = NTP_VOICE_ERROR_LANGUAGE_NOT_SUPPORTED; + break; + case new_tab_page::mojom::VoiceSearchError::NO_MATCH: + event = NTP_VOICE_ERROR_NO_MATCH; + break; + case new_tab_page::mojom::VoiceSearchError::SERVICE_NOT_ALLOWED: + event = NTP_VOICE_ERROR_SERVICE_NOT_ALLOWED; + break; + case new_tab_page::mojom::VoiceSearchError::BAD_GRAMMAR: + event = NTP_VOICE_ERROR_BAD_GRAMMAR; + break; + case new_tab_page::mojom::VoiceSearchError::OTHER: + event = NTP_VOICE_ERROR_OTHER; + break; + } + LogEvent(event); +} + void NewTabPageHandler::QueryAutocomplete(const base::string16& input, bool prevent_inline_autocomplete) { if (!autocomplete_controller_) { @@ -879,7 +996,7 @@ void NewTabPageHandler::OpenAutocompleteMatch( web_contents_->OpenURL( content::OpenURLParams(match.destination_url, content::Referrer(), - disposition, ui::PAGE_TRANSITION_LINK, false)); + disposition, match.transition, false)); } void NewTabPageHandler::DeleteAutocompleteMatch(uint8_t line) { @@ -1144,40 +1261,28 @@ void NewTabPageHandler::OnLogoAvailable( std::move(callback).Run(nullptr); return; } - SkColor doodle_share_button_background_color; - if (logo->metadata.share_button_bg.size() != 7 || - logo->metadata.share_button_bg[0] != '#' || - !base::HexStringToUInt(logo->metadata.share_button_bg.substr(1), - &doodle_share_button_background_color)) { - std::move(callback).Run(nullptr); - return; - } auto image_doodle_content = new_tab_page::mojom::ImageDoodleContent::New(); - std::string base64; - base::Base64Encode(logo->encoded_image->data(), &base64); - image_doodle_content->image_url = GURL(base::StringPrintf( - "data:%s;base64,%s", logo->metadata.mime_type.c_str(), base64.c_str())); - image_doodle_content->on_click_url = logo->metadata.on_click_url; - if (logo->metadata.type == search_provider_logos::LogoType::ANIMATED) { - image_doodle_content->animation_url = logo->metadata.animated_url; + image_doodle_content->light = MakeImageDoodle( + logo->metadata.type, logo->encoded_image->data(), + logo->metadata.mime_type, logo->metadata.animated_url, + logo->metadata.width_px, logo->metadata.height_px, "#ffffff", + logo->metadata.share_button_x, logo->metadata.share_button_y, + logo->metadata.share_button_icon, logo->metadata.share_button_bg, + logo->metadata.log_url, logo->metadata.cta_log_url); + if (logo->dark_encoded_image) { + image_doodle_content->dark = MakeImageDoodle( + logo->metadata.type, logo->dark_encoded_image->data(), + logo->metadata.dark_mime_type, logo->metadata.dark_animated_url, + logo->metadata.dark_width_px, logo->metadata.dark_height_px, + logo->metadata.dark_background_color, + logo->metadata.dark_share_button_x, + logo->metadata.dark_share_button_y, + logo->metadata.dark_share_button_icon, + logo->metadata.dark_share_button_bg, logo->metadata.dark_log_url, + logo->metadata.dark_cta_log_url); } - image_doodle_content->share_button = - new_tab_page::mojom::DoodleShareButton::New(); - image_doodle_content->share_button->x = logo->metadata.share_button_x; - image_doodle_content->share_button->y = logo->metadata.share_button_y; - image_doodle_content->share_button->icon_url = GURL(base::StringPrintf( - "data:image/png;base64,%s", logo->metadata.share_button_icon.c_str())); - image_doodle_content->share_button->background_color = - SkColorSetA(doodle_share_button_background_color, 255); + image_doodle_content->on_click_url = logo->metadata.on_click_url; image_doodle_content->share_url = logo->metadata.short_link; - if (logo->metadata.type == search_provider_logos::LogoType::ANIMATED) { - image_doodle_content->image_impression_log_url = - logo->metadata.cta_log_url; - image_doodle_content->animation_impression_log_url = - logo->metadata.log_url; - } else { - image_doodle_content->image_impression_log_url = logo->metadata.log_url; - } doodle->content = new_tab_page::mojom::DoodleContent::NewImageDoodle( std::move(image_doodle_content)); } else if (logo->metadata.type == diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h index 252dda345db..a2d572d868a 100644 --- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h +++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h @@ -60,7 +60,9 @@ class NewTabPageHandler : public new_tab_page::mojom::PageHandler, pending_page_handler, mojo::PendingRemote<new_tab_page::mojom::Page> pending_page, Profile* profile, + InstantService* instant_service, content::WebContents* web_contents, + NTPUserDataLogger* logger, const base::Time& ntp_navigation_start_time); ~NewTabPageHandler() override; @@ -120,6 +122,9 @@ class NewTabPageHandler : public new_tab_page::mojom::PageHandler, const std::string& doodle_id, const base::Optional<std::string>& share_id) override; void OnPromoLinkClicked() override; + void OnVoiceSearchAction( + new_tab_page::mojom::VoiceSearchAction action) override; + void OnVoiceSearchError(new_tab_page::mojom::VoiceSearchError error) override; void QueryAutocomplete(const base::string16& input, bool prevent_inline_autocomplete) override; void StopAutocomplete(bool clear_result) override; diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc new file mode 100644 index 00000000000..7624cacbf63 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler_unittest.cc @@ -0,0 +1,106 @@ +// Copyright 2020 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/new_tab_page/new_tab_page_handler.h" +#include "chrome/browser/search/instant_service.h" +#include "chrome/browser/ui/search/ntp_user_data_logger.h" +#include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h" +#include "chrome/common/search/omnibox.mojom.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" +#include "content/public/test/test_web_contents_factory.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +class MockInstantService : public InstantService { + public: + explicit MockInstantService(Profile* profile) : InstantService(profile) {} + ~MockInstantService() override = default; + + MOCK_METHOD1(AddObserver, void(InstantServiceObserver*)); + MOCK_METHOD0(UpdateNtpTheme, void()); +}; + +class MockNTPUserDataLogger : public NTPUserDataLogger { + public: + MockNTPUserDataLogger() : NTPUserDataLogger(nullptr) {} + ~MockNTPUserDataLogger() override = default; +}; + +class MockPage : public new_tab_page::mojom::Page { + public: + MockPage() = default; + ~MockPage() override = default; + + mojo::PendingRemote<new_tab_page::mojom::Page> BindAndGetRemote() { + DCHECK(!receiver_.is_bound()); + return receiver_.BindNewPipeAndPassRemote(); + } + + MOCK_METHOD1(SetMostVisitedInfo, + void(new_tab_page::mojom::MostVisitedInfoPtr)); + MOCK_METHOD1(SetTheme, void(new_tab_page::mojom::ThemePtr)); + MOCK_METHOD1(SetFakeboxFocused, void(bool)); + MOCK_METHOD1(SetFakeboxVisible, void(bool)); + MOCK_METHOD1(AutocompleteResultChanged, + void(search::mojom::AutocompleteResultPtr)); + MOCK_METHOD3(AutocompleteMatchImageAvailable, + void(uint32_t, const GURL&, const std::string&)); + + mojo::Receiver<new_tab_page::mojom::Page> receiver_{this}; +}; + +} // namespace + +class NewTabPageHandlerTest : public testing::Test { + public: + NewTabPageHandlerTest() + : mock_instant_service_(&profile_), + web_contents_(factory_.CreateWebContents(&profile_)) {} + + ~NewTabPageHandlerTest() override = default; + + void SetUp() override { + EXPECT_CALL(mock_instant_service_, AddObserver) + .WillOnce(DoAll(testing::SaveArg<0>(&instant_service_observer_))); + EXPECT_CALL(mock_instant_service_, UpdateNtpTheme()); + handler_ = std::make_unique<NewTabPageHandler>( + mojo::PendingReceiver<new_tab_page::mojom::PageHandler>(), + mock_page_.BindAndGetRemote(), &profile_, &mock_instant_service_, + web_contents_, &logger_, base::Time::Now()); + EXPECT_EQ(handler_.get(), instant_service_observer_); + } + + void TearDown() override { testing::Test::TearDown(); } + + protected: + testing::NiceMock<MockPage> mock_page_; + // NOTE: The initialization order of these members matters. + content::BrowserTaskEnvironment task_environment_; + TestingProfile profile_; + MockInstantService mock_instant_service_; + content::TestWebContentsFactory factory_; + content::WebContents* web_contents_; // Weak. Owned by factory_. + MockNTPUserDataLogger logger_; + std::unique_ptr<NewTabPageHandler> handler_; + InstantServiceObserver* instant_service_observer_; +}; + +TEST_F(NewTabPageHandlerTest, SetMostVisitedInfo) { + EXPECT_CALL(mock_page_, SetMostVisitedInfo(testing::_)); + InstantMostVisitedInfo info; + instant_service_observer_->MostVisitedInfoChanged(info); +} + +TEST_F(NewTabPageHandlerTest, SetTheme) { + EXPECT_CALL(mock_page_, SetTheme(testing::_)); + NtpTheme theme; + instant_service_observer_->NtpThemeChanged(theme); +} diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index a055b15e57b..f2051be3574 100644 --- a/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chromium/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc @@ -12,6 +12,7 @@ #include "chrome/browser/search/instant_service_factory.h" #include "chrome/browser/search/ntp_features.h" #include "chrome/browser/search_engines/template_url_service_factory.h" +#include "chrome/browser/ui/search/ntp_user_data_logger.h" #include "chrome/browser/ui/search/omnibox_mojo_utils.h" #include "chrome/browser/ui/webui/favicon_source.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h" @@ -25,11 +26,11 @@ #include "chrome/grit/new_tab_page_resources_map.h" #include "components/favicon_base/favicon_url_parser.h" #include "components/google/core/common/google_util.h" -#include "components/omnibox/common/omnibox_features.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/url_data_source.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/accelerators/accelerator.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -63,9 +64,6 @@ content::WebUIDataSource* CreateNewTabPageUiHtmlSource(Profile* profile) { ntp_features::IsRealboxEnabled() && base::FeatureList::IsEnabled(ntp_features::kWebUIRealbox); source->AddBoolean("realboxEnabled", realbox_enabled); - source->AddBoolean("suggestionTransparencyEnabled", - base::FeatureList::IsEnabled( - omnibox::kOmniboxSuggestionTransparencyOptions)); source->AddBoolean( "realboxMatchOmniboxTheme", base::FeatureList::IsEnabled(ntp_features::kRealboxMatchOmniboxTheme)); @@ -78,6 +76,13 @@ content::WebUIDataSource* CreateNewTabPageUiHtmlSource(Profile* profile) { source->AddBoolean( "iframeOneGoogleBarEnabled", base::FeatureList::IsEnabled(ntp_features::kIframeOneGoogleBar)); + source->AddBoolean( + "oneGoogleBarModalOverlaysEnabled", + base::FeatureList::IsEnabled(ntp_features::kOneGoogleBarModalOverlays)); + + source->AddBoolean( + "themeModeDoodlesEnabled", + base::FeatureList::IsEnabled(ntp_features::kWebUIThemeModeDoodles)); static constexpr webui::LocalizedString kStrings[] = { {"doneButton", IDS_DONE}, @@ -188,8 +193,6 @@ content::WebUIDataSource* CreateNewTabPageUiHtmlSource(Profile* profile) { {omnibox::kSearchIconResourceName, IDR_WEBUI_IMAGES_ICON_SEARCH}}; webui::AddResourcePathsBulk(source, kImages); - source->AddResourcePath("skcolor.mojom-lite.js", - IDR_NEW_TAB_PAGE_SKCOLOR_MOJO_LITE_JS); source->AddResourcePath("new_tab_page.mojom-lite.js", IDR_NEW_TAB_PAGE_MOJO_LITE_JS); source->AddResourcePath("omnibox.mojom-lite.js", @@ -206,13 +209,15 @@ content::WebUIDataSource* CreateNewTabPageUiHtmlSource(Profile* profile) { // TODO(crbug.com/1076506): remove when changing to iframed OneGoogleBar. // Needs to happen after |webui::SetupWebUIDataSource()| since also overrides // script-src. - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self' 'unsafe-inline' " "https:;"); // Allow embedding of iframes from the One Google Bar and // chrome-untrusted://new-tab-page for other external content and resources. - source->OverrideContentSecurityPolicyChildSrc( - base::StringPrintf("child-src https://*.google.com/ %s %s;", + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ChildSrc, + base::StringPrintf("child-src https: %s %s;", google_util::CommandLineGoogleBaseURL().spec().c_str(), chrome::kChromeUIUntrustedNewTabPageUrl)); @@ -280,7 +285,9 @@ void NewTabPageUI::CreatePageHandler( DCHECK(pending_page.is_valid()); page_handler_ = std::make_unique<NewTabPageHandler>( std::move(pending_page_handler), std::move(pending_page), profile_, - web_contents_, navigation_start_time_); + instant_service_, web_contents_, + NTPUserDataLogger::GetOrCreateFromWebContents(web_contents_), + navigation_start_time_); } void NewTabPageUI::NtpThemeChanged(const NtpTheme& theme) { diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc index 07e3f7d95de..d4cbd26c6d8 100644 --- a/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc +++ b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.cc @@ -11,6 +11,7 @@ #include "base/files/file_util.h" #include "base/i18n/rtl.h" #include "base/memory/ref_counted_memory.h" +#include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" #include "base/strings/string_piece.h" @@ -19,6 +20,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/ntp_features.h" #include "chrome/browser/search/one_google_bar/one_google_bar_data.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" #include "chrome/browser/search/promos/promo_data.h" @@ -28,6 +30,7 @@ #include "chrome/grit/new_tab_page_resources.h" #include "content/public/common/url_constants.h" #include "net/base/url_util.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/template_expressions.h" #include "url/url_util.h" @@ -39,7 +42,8 @@ constexpr int kMaxUriDecodeLen = 2048; std::string FormatTemplate(int resource_id, const ui::TemplateReplacements& replacements) { ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); - base::RefCountedMemory* bytes = bundle.LoadDataResourceBytes(resource_id); + scoped_refptr<base::RefCountedMemory> bytes = + bundle.LoadDataResourceBytes(resource_id); base::StringPiece string_piece(reinterpret_cast<const char*>(bytes->front()), bytes->size()); return ui::ReplaceTemplateExpressions( @@ -81,12 +85,21 @@ UntrustedSource::UntrustedSource(Profile* profile) UntrustedSource::~UntrustedSource() = default; -std::string UntrustedSource::GetContentSecurityPolicyScriptSrc() { - return "script-src 'self' 'unsafe-inline' https:;"; -} +std::string UntrustedSource::GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) { + if (directive == network::mojom::CSPDirectiveName::ScriptSrc) { + return "script-src 'self' 'unsafe-inline' https:;"; + } else if (directive == network::mojom::CSPDirectiveName::ChildSrc) { + return "child-src https:;"; + } else if (directive == network::mojom::CSPDirectiveName::DefaultSrc) { + // TODO(https://crbug.com/1085325): Audit and tighten CSP. + return std::string(); + } else if (directive == network::mojom::CSPDirectiveName::FrameAncestors) { + return base::StringPrintf("frame-ancestors %s", + chrome::kChromeUINewTabPageURL); + } -std::string UntrustedSource::GetContentSecurityPolicyChildSrc() { - return "child-src https:;"; + return content::URLDataSource::GetContentSecurityPolicy(directive); } std::string UntrustedSource::GetSource() { @@ -135,14 +148,13 @@ void UntrustedSource::StartDataRequest( bundle.LoadDataResourceBytes(IDR_NEW_TAB_PAGE_UNTRUSTED_PROMO_JS)); return; } - if ((path == "image" || path == "iframe") && url_param.is_valid() && + if (path == "image" && url_param.is_valid() && (url_param.SchemeIs(url::kHttpsScheme) || url_param.SchemeIs(content::kChromeUIUntrustedScheme))) { ui::TemplateReplacements replacements; replacements["url"] = url_param.spec(); - int resource_id = path == "image" ? IDR_NEW_TAB_PAGE_UNTRUSTED_IMAGE_HTML - : IDR_NEW_TAB_PAGE_UNTRUSTED_IFRAME_HTML; - std::string html = FormatTemplate(resource_id, replacements); + std::string html = + FormatTemplate(IDR_NEW_TAB_PAGE_UNTRUSTED_IMAGE_HTML, replacements); std::move(callback).Run(base::RefCountedString::TakeString(&html)); return; } @@ -210,11 +222,6 @@ bool UntrustedSource::AllowCaching() { return false; } -std::string UntrustedSource::GetContentSecurityPolicyFrameAncestors() { - return base::StringPrintf("frame-ancestors %s", - chrome::kChromeUINewTabPageURL); -} - bool UntrustedSource::ShouldReplaceExistingSource() { return false; } @@ -230,8 +237,7 @@ bool UntrustedSource::ShouldServiceRequest( return path == "one-google-bar" || path == "one_google_bar.js" || path == "promo" || path == "promo.js" || path == "image" || path == "background_image" || path == "custom_background_image" || - path == "background_image.js" || path == "iframe" || - path == "background.jpg"; + path == "background_image.js" || path == "background.jpg"; } void UntrustedSource::OnOneGoogleBarDataUpdated() { @@ -249,6 +255,10 @@ void UntrustedSource::OnOneGoogleBarDataUpdated() { if (data.has_value()) { ui::TemplateReplacements replacements; replacements["textdirection"] = base::i18n::IsRTL() ? "rtl" : "ltr"; + replacements["modalOverlays"] = + base::FeatureList::IsEnabled(ntp_features::kOneGoogleBarModalOverlays) + ? "modal-overlays" + : ""; replacements["barHtml"] = data->bar_html; replacements["inHeadScript"] = data->in_head_script; replacements["inHeadStyle"] = data->in_head_style; diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h index 5a689dbaf25..ecb0a5bbde5 100644 --- a/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h +++ b/chromium/chrome/browser/ui/webui/new_tab_page/untrusted_source.h @@ -39,8 +39,6 @@ class Profile; // * repeatY: (optional) CSS background-repeat-y property. // * positionX: (optional) CSS background-position-x property. // * positionY: (optional) CSS background-position-y property. -// * chrome-untrusted://new-tab-page/iframe?<url>: Behaves like an iframe with -// src set to <url>. // Each of those helpers only accept URLs with HTTPS or chrome-untrusted:. class UntrustedSource : public content::URLDataSource, public OneGoogleBarServiceObserver, @@ -52,8 +50,8 @@ class UntrustedSource : public content::URLDataSource, UntrustedSource& operator=(const UntrustedSource&) = delete; // content::URLDataSource: - std::string GetContentSecurityPolicyScriptSrc() override; - std::string GetContentSecurityPolicyChildSrc() override; + std::string GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) override; std::string GetSource() override; void StartDataRequest( const GURL& url, @@ -61,7 +59,6 @@ class UntrustedSource : public content::URLDataSource, content::URLDataSource::GotDataCallback callback) override; std::string GetMimeType(const std::string& path) override; bool AllowCaching() override; - std::string GetContentSecurityPolicyFrameAncestors() override; bool ShouldReplaceExistingSource() override; bool ShouldServiceRequest(const GURL& url, content::BrowserContext* browser_context, diff --git a/chromium/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc b/chromium/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc new file mode 100644 index 00000000000..e68b5daa040 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/new_tab_page/webui_ntp_browsertest.cc @@ -0,0 +1,79 @@ +// Copyright 2020 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/search/ntp_features.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "net/dns/mock_host_resolver.h" + +class WebUiNtpBrowserTest : public InProcessBrowserTest { + public: + WebUiNtpBrowserTest() { + feature_list_.InitAndEnableFeature(ntp_features::kWebUI); + } + ~WebUiNtpBrowserTest() override = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + embedded_test_server()->ServeFilesFromSourceDirectory("content/test/data"); + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + } + + void SetUpOnMainThread() override { + host_resolver()->AddRule("*", "127.0.0.1"); + embedded_test_server()->StartAcceptingConnections(); + } + + private: + base::test::ScopedFeatureList feature_list_; +}; + +// Verify that the WebUI NTP commits in a SiteInstance with the WebUI URL. +IN_PROC_BROWSER_TEST_F(WebUiNtpBrowserTest, VerifyWebUiNtpSiteInstance) { + GURL ntp_url(chrome::kChromeUINewTabURL); + ui_test_utils::NavigateToURL(browser(), ntp_url); + + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + ASSERT_EQ(ntp_url, web_contents->GetLastCommittedURL()); + + GURL webui_ntp_url(chrome::kChromeUINewTabPageURL); + ASSERT_EQ(webui_ntp_url, + web_contents->GetMainFrame()->GetSiteInstance()->GetSiteURL()); +} + +// Verify that the WebUI NTP uses process-per-site. +IN_PROC_BROWSER_TEST_F(WebUiNtpBrowserTest, ProcessPerSite) { + std::vector<content::WebContents*> tabs; + + // Open a few NTPs. + for (size_t i = 0; i < 3; i++) { + content::WebContentsAddedObserver tab_observer; + chrome::NewTab(browser()); + + // Wait for the new tab. + auto* tab = tab_observer.GetWebContents(); + ASSERT_TRUE(WaitForLoadStop(tab)); + + // Sanity check: the NTP should be a WebUI NTP (and not chrome://newtab/ or + // some other NTP). + EXPECT_EQ(GURL(chrome::kChromeUINewTabPageURL).spec(), + EvalJs(tab, "window.location.href", + content::EXECUTE_SCRIPT_DEFAULT_OPTIONS, + /*world_id=*/1)); + + tabs.push_back(tab); + } + + // Verify that all NTPs share a process. + for (size_t i = 1; i < tabs.size(); i++) { + EXPECT_EQ(tabs[0]->GetMainFrame()->GetProcess(), + tabs[i]->GetMainFrame()->GetProcess()); + } +} diff --git a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc index 8b3cd017605..b1c4b61fe52 100644 --- a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc +++ b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.cc @@ -22,6 +22,7 @@ #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" #include "base/values.h" #include "chrome/browser/apps/app_service/app_icon_source.h" #include "chrome/browser/apps/app_service/app_launch_params.h" @@ -53,13 +54,12 @@ #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" #include "chrome/browser/web_applications/components/app_registry_controller.h" -#include "chrome/browser/web_applications/components/app_shortcut_manager.h" -#include "chrome/browser/web_applications/components/file_handler_manager.h" #include "chrome/browser/web_applications/components/install_finalizer.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h" #include "chrome/browser/web_applications/extensions/bookmark_app_finalizer_utils.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" +#include "chrome/browser/web_applications/os_integration_manager.h" #include "chrome/browser/web_applications/web_app_icon_manager.h" #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/common/buildflags.h" @@ -969,15 +969,12 @@ void AppLauncherHandler::HandleInstallAppLocally(const base::ListValue* args) { web_app_provider_->registry_controller().SetAppIsLocallyInstalled(app_id, true); - web_app::AppShortcutManager& shortcut_manager = - web_app_provider_->shortcut_manager(); - if (shortcut_manager.CanCreateShortcuts()) { - shortcut_manager.CreateShortcuts( - app_id, /*add_to_desktop=*/true, - base::BindOnce( - &AppLauncherHandler::OnShortcutsCreatedRegisterOsIntegration, - weak_ptr_factory_.GetWeakPtr(), app_id)); - } + web_app_provider_->registry_controller().SetAppInstallTime(app_id, + base::Time::Now()); + web_app_provider_->os_integration_manager().InstallOsHooks( + app_id, base::BindOnce(&AppLauncherHandler::OnOsHooksInstalled, + weak_ptr_factory_.GetWeakPtr(), app_id)); + // Use the appAdded to update the app icon's color to no longer be // greyscale. std::unique_ptr<base::DictionaryValue> app_info = GetWebAppInfo(app_id); @@ -1198,13 +1195,10 @@ void AppLauncherHandler::PromptToEnableApp(const std::string& extension_id) { extension_enable_flow_->StartForWebContents(web_ui()->GetWebContents()); } -void AppLauncherHandler::OnShortcutsCreatedRegisterOsIntegration( - const web_app::AppId& app_id, - bool shortcuts_created) { +void AppLauncherHandler::OnOsHooksInstalled(const web_app::AppId& app_id, + bool shortcuts_created) { LOCAL_HISTOGRAM_BOOLEAN("Apps.Launcher.InstallLocallyShortcutsCreated", shortcuts_created); - web_app_provider_->file_handler_manager().EnableAndRegisterOsFileHandlers( - app_id); } void AppLauncherHandler::OnExtensionUninstallDialogClosed( diff --git a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h index c5d99409710..6efbad522c7 100644 --- a/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h +++ b/chromium/chrome/browser/ui/webui/ntp/app_launcher_handler.h @@ -174,10 +174,8 @@ class AppLauncherHandler // Prompts the user to re-enable the app for |extension_id|. void PromptToEnableApp(const std::string& extension_id); - // Registers file handlers for |app_id|, after shortcuts have been - // created. - void OnShortcutsCreatedRegisterOsIntegration(const web_app::AppId& app_id, - bool shortcuts_created); + // Records result to UMA after OS Hooks are installed. + void OnOsHooksInstalled(const web_app::AppId& app_id, bool shortcuts_created); // ExtensionUninstallDialog::Delegate: void OnExtensionUninstallDialogClosed(bool did_start_uninstall, @@ -264,7 +262,7 @@ class AppLauncherHandler // Used for favicon loading tasks. base::CancelableTaskTracker cancelable_task_tracker_; - // Used to register file handlers after shortcuts have been created. + // Used for passing callbacks. base::WeakPtrFactory<AppLauncherHandler> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(AppLauncherHandler); diff --git a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc index 41fd80239ea..d072d8378c1 100644 --- a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc +++ b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.cc @@ -62,10 +62,9 @@ void CookieControlsHandler::HandleObserveCookieControlsSettingsChanges( SendCookieControlsUIChanges(); } -const char* CookieControlsHandler::GetEnforcementIcon(Profile* profile) { - CookieControlsService* service = - CookieControlsServiceFactory::GetForProfile(profile); - switch (service->GetCookieControlsEnforcement()) { +const char* CookieControlsHandler::GetEnforcementIcon( + CookieControlsEnforcement enforcement) { + switch (enforcement) { case CookieControlsEnforcement::kEnforcedByPolicy: return kPolicyIcon; case CookieControlsEnforcement::kEnforcedByExtension: @@ -86,11 +85,11 @@ void CookieControlsHandler::OnThirdPartyCookieBlockingPolicyChanged() { } void CookieControlsHandler::SendCookieControlsUIChanges() { - Profile* profile = Profile::FromWebUI(web_ui()); base::DictionaryValue dict; dict.SetBoolKey("enforced", service_->ShouldEnforceCookieControls()); dict.SetBoolKey("checked", service_->GetToggleCheckedValue()); - dict.SetStringKey("icon", CookieControlsHandler::GetEnforcementIcon(profile)); + dict.SetStringKey( + "icon", GetEnforcementIcon(service_->GetCookieControlsEnforcement())); bool use_new_cookie_page = base::FeatureList::IsEnabled(features::kPrivacySettingsRedesign); dict.SetString("cookieSettingsUrl", diff --git a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h index f7dbf79d4bd..ff781518a0b 100644 --- a/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h +++ b/chromium/chrome/browser/ui/webui/ntp/cookie_controls_handler.h @@ -16,7 +16,7 @@ namespace base { class ListValue; } // namespace base -// Handles requests for prefs::kCookieControlsMode retrival/update. +// Communicates with the incognito ntp to show a third-party cookie control. class CookieControlsHandler : public content::WebUIMessageHandler, public CookieControlsService::Observer { public: @@ -30,7 +30,7 @@ class CookieControlsHandler : public content::WebUIMessageHandler, void HandleCookieControlsToggleChanged(const base::ListValue* args); void HandleObserveCookieControlsSettingsChanges(const base::ListValue* args); - static const char* GetEnforcementIcon(Profile* profile); + static const char* GetEnforcementIcon(CookieControlsEnforcement enforcement); // CookieControlsService::Observer void OnThirdPartyCookieBlockingPrefChanged() override; diff --git a/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc b/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc index 6d549a735e1..466de0c664d 100644 --- a/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc +++ b/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.cc @@ -30,6 +30,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/native_theme/native_theme.h" #include "url/gurl.h" @@ -59,7 +60,10 @@ NewTabUI::NewTabUI(content::WebUI* web_ui) : content::WebUIController(web_ui) { if (!profile->IsGuestSession()) { web_ui->AddMessageHandler(std::make_unique<ThemeHandler>()); - web_ui->AddMessageHandler(std::make_unique<CookieControlsHandler>(profile)); + if (profile->IsOffTheRecord()) { + web_ui->AddMessageHandler( + std::make_unique<CookieControlsHandler>(profile)); + } } // content::URLDataSource assumes the ownership of the html source. @@ -187,23 +191,23 @@ bool NewTabUI::NewTabHTMLSource::ShouldReplaceExistingSource() { return false; } -std::string NewTabUI::NewTabHTMLSource::GetContentSecurityPolicyScriptSrc() { - // 'unsafe-inline' and google resources are added to script-src. - return "script-src chrome://resources 'self' 'unsafe-eval' 'unsafe-inline' " - "*.google.com *.gstatic.com;"; -} - -std::string NewTabUI::NewTabHTMLSource::GetContentSecurityPolicyStyleSrc() { - return "style-src 'self' chrome://resources 'unsafe-inline' chrome://theme;"; -} - -std::string NewTabUI::NewTabHTMLSource::GetContentSecurityPolicyImgSrc() { - return "img-src chrome-search://thumb chrome-search://thumb2 " - "chrome-search://theme chrome://theme data:;"; -} +std::string NewTabUI::NewTabHTMLSource::GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) { + if (directive == network::mojom::CSPDirectiveName::ScriptSrc) { + // 'unsafe-inline' and google resources are added to script-src. + return "script-src chrome://resources 'self' 'unsafe-eval' 'unsafe-inline' " + "*.google.com *.gstatic.com;"; + } else if (directive == network::mojom::CSPDirectiveName::StyleSrc) { + return "style-src 'self' chrome://resources 'unsafe-inline' " + "chrome://theme;"; + } else if (directive == network::mojom::CSPDirectiveName::ImgSrc) { + return "img-src chrome-search://thumb chrome-search://thumb2 " + "chrome-search://theme chrome://theme data:;"; + } else if (directive == network::mojom::CSPDirectiveName::ChildSrc) { + return "child-src chrome-search://most-visited;"; + } -std::string NewTabUI::NewTabHTMLSource::GetContentSecurityPolicyChildSrc() { - return "child-src chrome-search://most-visited;"; + return content::URLDataSource::GetContentSecurityPolicy(directive); } NewTabUI::NewTabHTMLSource::~NewTabHTMLSource() {} diff --git a/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.h b/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.h index 97e6443b656..fe04e036f11 100644 --- a/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.h +++ b/chromium/chrome/browser/ui/webui/ntp/new_tab_ui.h @@ -62,10 +62,8 @@ class NewTabUI : public content::WebUIController { content::URLDataSource::GotDataCallback callback) override; std::string GetMimeType(const std::string&) override; bool ShouldReplaceExistingSource() override; - std::string GetContentSecurityPolicyScriptSrc() override; - std::string GetContentSecurityPolicyStyleSrc() override; - std::string GetContentSecurityPolicyImgSrc() override; - std::string GetContentSecurityPolicyChildSrc() override; + std::string GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) override; private: // Pointer back to the original profile. diff --git a/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index f796da4afea..89cd233b135 100644 --- a/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chromium/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc @@ -98,8 +98,8 @@ SkColor GetThemeColor(const ui::ThemeProvider& tp, int id) { // If web contents are being inverted because the system is in high-contrast // mode, any system theme colors we use must be inverted too to cancel out. return ui::NativeTheme::GetInstanceForNativeUi() - ->GetHighContrastColorScheme() == - ui::NativeTheme::HighContrastColorScheme::kDark + ->GetPlatformHighContrastColorScheme() == + ui::NativeTheme::PlatformHighContrastColorScheme::kDark ? color_utils::InvertColor(color) : color; } @@ -295,6 +295,13 @@ void NTPResourceCache::CreateNewTabIncognitoHTML() { ? "true" : "false"; + // Ensure passing off-the-record profile; |profile_| is not an OTR profile. + DCHECK(!profile_->IsOffTheRecord()); + DCHECK(profile_->HasPrimaryOTRProfile()); + CookieControlsService* cookie_controls_service = + CookieControlsServiceFactory::GetForProfile( + profile_->GetPrimaryOTRProfile()); + replacements["incognitoTabDescription"] = l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_SUBTITLE); replacements["incognitoTabHeading"] = @@ -308,29 +315,18 @@ void NTPResourceCache::CreateNewTabIncognitoHTML() { replacements["learnMoreLink"] = kLearnMoreIncognitoUrl; replacements["title"] = l10n_util::GetStringUTF8(IDS_NEW_TAB_TITLE); replacements["hideCookieControls"] = - CookieControlsServiceFactory::GetForProfile(profile_) - ->ShouldHideCookieControlsUI() - ? "hidden" - : ""; + cookie_controls_service->ShouldHideCookieControlsUI() ? "hidden" : ""; replacements["cookieControlsTitle"] = l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_THIRD_PARTY_COOKIE); replacements["cookieControlsDescription"] = l10n_util::GetStringUTF8(IDS_NEW_TAB_OTR_THIRD_PARTY_COOKIE_SUBLABEL); - // Ensure passing off-the-record profile; |profile_| might not be incognito. - DCHECK(profile_->HasPrimaryOTRProfile()); replacements["cookieControlsToggleChecked"] = - CookieControlsServiceFactory::GetForProfile( - profile_->GetPrimaryOTRProfile()) - ->GetToggleCheckedValue() - ? "checked" - : ""; + cookie_controls_service->GetToggleCheckedValue() ? "checked" : ""; replacements["hideTooltipIcon"] = - CookieControlsServiceFactory::GetForProfile(profile_) - ->ShouldEnforceCookieControls() - ? "" - : "hidden"; + cookie_controls_service->ShouldEnforceCookieControls() ? "" : "hidden"; replacements["cookieControlsToolTipIcon"] = - CookieControlsHandler::GetEnforcementIcon(profile_); + CookieControlsHandler::GetEnforcementIcon( + cookie_controls_service->GetCookieControlsEnforcement()); replacements["cookieControlsTooltipText"] = l10n_util::GetStringUTF8( IDS_NEW_TAB_OTR_COOKIE_CONTROLS_CONTROLLED_TOOLTIP_TEXT); diff --git a/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc index c2a62bd570c..96de4f8d4c8 100644 --- a/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc @@ -29,6 +29,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/browser/web_ui_message_handler.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" namespace { @@ -125,7 +126,8 @@ void ChromeNTPTilesInternalsMessageHandlerClient::CallJavascriptFunctionVector( content::WebUIDataSource* CreateNTPTilesInternalsHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUINTPTilesInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->AddResourcePath("ntp_tiles_internals.js", IDR_NTP_TILES_INTERNALS_JS); diff --git a/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc b/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc index c6e3c553d56..bb23cde4f20 100644 --- a/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc +++ b/chromium/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc @@ -128,7 +128,7 @@ template <> struct TypeConverter<mojom::AutocompleteMatchPtr, AutocompleteMatch> { static mojom::AutocompleteMatchPtr Convert(const AutocompleteMatch& input) { mojom::AutocompleteMatchPtr result(mojom::AutocompleteMatch::New()); - if (input.provider != NULL) { + if (input.provider) { result->provider_name = std::string(input.provider->GetName()); result->provider_done = input.provider->done(); } @@ -162,7 +162,7 @@ struct TypeConverter<mojom::AutocompleteMatchPtr, AutocompleteMatch> { result->type = AutocompleteMatchType::ToString(input.type); result->is_search_type = AutocompleteMatch::IsSearchType(input.type); result->has_tab_match = input.has_tab_match; - if (input.associated_keyword.get() != NULL) { + if (input.associated_keyword.get()) { result->associated_keyword = base::UTF16ToUTF8(input.associated_keyword->keyword); } diff --git a/chromium/chrome/browser/ui/webui/policy_ui.cc b/chromium/chrome/browser/ui/webui/policy_ui.cc index 7509acf1b70..13d09970fe3 100644 --- a/chromium/chrome/browser/ui/webui/policy_ui.cc +++ b/chromium/chrome/browser/ui/webui/policy_ui.cc @@ -25,6 +25,7 @@ content::WebUIDataSource* CreatePolicyUIHtmlSource() { static constexpr webui::LocalizedString kStrings[] = { // Localized strings (alphabetical order). + {"copyPoliciesJSON", IDS_COPY_POLICIES_JSON}, {"exportPoliciesJSON", IDS_EXPORT_POLICIES_JSON}, {"filterPlaceholder", IDS_POLICY_FILTER_PLACEHOLDER}, {"hideExpandedStatus", IDS_POLICY_HIDE_EXPANDED_STATUS}, @@ -57,6 +58,7 @@ content::WebUIDataSource* CreatePolicyUIHtmlSource() { {"noPoliciesSet", IDS_POLICY_NO_POLICIES_SET}, {"offHoursActive", IDS_POLICY_OFFHOURS_ACTIVE}, {"offHoursNotActive", IDS_POLICY_OFFHOURS_NOT_ACTIVE}, + {"policyCopyValue", IDS_POLICY_COPY_VALUE}, {"policiesPushOff", IDS_POLICY_PUSH_POLICIES_OFF}, {"policiesPushOn", IDS_POLICY_PUSH_POLICIES_ON}, {"policyLearnMore", IDS_POLICY_LEARN_MORE}, @@ -91,5 +93,4 @@ PolicyUI::PolicyUI(content::WebUI* web_ui) : WebUIController(web_ui) { CreatePolicyUIHtmlSource()); } -PolicyUI::~PolicyUI() { -} +PolicyUI::~PolicyUI() = default; diff --git a/chromium/chrome/browser/ui/webui/policy_ui_handler.cc b/chromium/chrome/browser/ui/webui/policy_ui_handler.cc index d649be05f2f..9efd2c88830 100644 --- a/chromium/chrome/browser/ui/webui/policy_ui_handler.cc +++ b/chromium/chrome/browser/ui/webui/policy_ui_handler.cc @@ -68,6 +68,8 @@ #include "content/public/browser/web_contents.h" #include "extensions/buildflags/buildflags.h" #include "google_apis/gaia/gaia_auth_util.h" +#include "ui/base/clipboard/clipboard_buffer.h" +#include "ui/base/clipboard/scoped_clipboard_writer.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/time_format.h" #include "ui/base/webui/web_ui_util.h" @@ -564,6 +566,9 @@ void MachineLevelUserCloudPolicyStatusProvider::GetStatus( refresh_scheduler ? refresh_scheduler->GetActualRefreshDelay() : policy::CloudPolicyRefreshScheduler:: kDefaultRefreshDelayMs))); + dict->SetBoolean( + "policiesPushAvailable", + refresh_scheduler ? refresh_scheduler->invalidations_available() : false); if (dmTokenStorage) { dict->SetString("enrollmentToken", @@ -810,6 +815,7 @@ void PolicyUIHandler::AddCommonLocalizedStringsToSource( {"levelRecommended", IDS_POLICY_LEVEL_RECOMMENDED}, {"error", IDS_POLICY_LABEL_ERROR}, {"deprecated", IDS_POLICY_LABEL_DEPRECATED}, + {"future", IDS_POLICY_LABEL_FUTURE}, {"ignored", IDS_POLICY_LABEL_IGNORED}, {"notSpecified", IDS_POLICY_NOT_SPECIFIED}, {"ok", IDS_POLICY_OK}, @@ -939,6 +945,10 @@ void PolicyUIHandler::RegisterMessages() { "reloadPolicies", base::BindRepeating(&PolicyUIHandler::HandleReloadPolicies, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "copyPoliciesJSON", + base::BindRepeating(&PolicyUIHandler::HandleCopyPoliciesJson, + base::Unretained(this))); } #if BUILDFLAG(ENABLE_EXTENSIONS) @@ -1178,13 +1188,13 @@ void PolicyUIHandler::HandleReloadPolicies(const base::ListValue* args) { &PolicyUIHandler::OnRefreshPoliciesDone, weak_factory_.GetWeakPtr())); } -void DoWritePoliciesToJSONFile(const base::FilePath& path, - const std::string& data) { - base::WriteFile(path, data.c_str(), data.size()); +void PolicyUIHandler::HandleCopyPoliciesJson(const base::ListValue* args) { + std::string policies_json = GetPoliciesAsJson(); + ui::ScopedClipboardWriter scw(ui::ClipboardBuffer::kCopyPaste); + scw.WriteText(base::UTF8ToUTF16(policies_json)); } -void PolicyUIHandler::WritePoliciesToJSONFile( - const base::FilePath& path) const { +std::string PolicyUIHandler::GetPoliciesAsJson() const { auto client = std::make_unique<policy::ChromePolicyConversionsClient>( web_ui()->GetWebContents()->GetBrowserContext()); base::Value dict = @@ -1241,6 +1251,17 @@ void PolicyUIHandler::WritePoliciesToJSONFile( base::JSONWriter::WriteWithOptions( dict, base::JSONWriter::OPTIONS_PRETTY_PRINT, &json_policies); + return json_policies; +} + +void DoWritePoliciesToJSONFile(const base::FilePath& path, + const std::string& data) { + base::WriteFile(path, data.c_str(), data.size()); +} + +void PolicyUIHandler::WritePoliciesToJSONFile( + const base::FilePath& path) const { + std::string json_policies = GetPoliciesAsJson(); base::ThreadPool::PostTask( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT, diff --git a/chromium/chrome/browser/ui/webui/policy_ui_handler.h b/chromium/chrome/browser/ui/webui/policy_ui_handler.h index e73ced252f6..58401981694 100644 --- a/chromium/chrome/browser/ui/webui/policy_ui_handler.h +++ b/chromium/chrome/browser/ui/webui/policy_ui_handler.h @@ -89,6 +89,7 @@ class PolicyUIHandler : public content::WebUIMessageHandler, void HandleExportPoliciesJson(const base::ListValue* args); void HandleListenPoliciesUpdates(const base::ListValue* args); void HandleReloadPolicies(const base::ListValue* args); + void HandleCopyPoliciesJson(const base::ListValue* args); // Send information about the current policy values to the UI. For each policy // whose value has been set, a dictionary containing the value and additional @@ -106,6 +107,9 @@ class PolicyUIHandler : public content::WebUIMessageHandler, // information is sent. void SendStatus(); + // Build a JSON string of all the policies. + std::string GetPoliciesAsJson() const; + void WritePoliciesToJSONFile(const base::FilePath& path) const; void OnRefreshPoliciesDone(); diff --git a/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc b/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc index 366c9e40cb3..dea6997da32 100644 --- a/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc +++ b/chromium/chrome/browser/ui/webui/predictors/predictors_handler.cc @@ -46,7 +46,7 @@ void PredictorsHandler::RegisterMessages() { void PredictorsHandler::RequestAutocompleteActionPredictorDb( const base::ListValue* args) { - const bool enabled = (autocomplete_action_predictor_ != NULL); + const bool enabled = !!autocomplete_action_predictor_; base::DictionaryValue dict; dict.SetBoolean("enabled", enabled); if (enabled) { diff --git a/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc index 1ee0076b9c6..879004c790d 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.cc @@ -36,7 +36,8 @@ void FakePrintRenderFrame::PrintPreview(base::Value settings) {} void FakePrintRenderFrame::OnPrintPreviewDialogClosed() {} void FakePrintRenderFrame::PrintFrameContent( - mojom::PrintFrameContentParamsPtr params) {} + mojom::PrintFrameContentParamsPtr params, + PrintFrameContentCallback callback) {} void FakePrintRenderFrame::PrintingDone(bool success) {} diff --git a/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h index 2bd75746885..10f46664d83 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h +++ b/chromium/chrome/browser/ui/webui/print_preview/fake_print_render_frame.h @@ -33,7 +33,8 @@ class FakePrintRenderFrame : public mojom::PrintRenderFrame { bool has_selection) override; void PrintPreview(base::Value settings) override; void OnPrintPreviewDialogClosed() override; - void PrintFrameContent(mojom::PrintFrameContentParamsPtr params) override; + void PrintFrameContent(mojom::PrintFrameContentParamsPtr params, + PrintFrameContentCallback callback) override; void PrintingDone(bool success) override; void SetPrintingEnabled(bool enabled) override; void PrintNodeUnderContextMenu() override; diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index 13b13ff3ae5..3ea4c1a66ac 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc @@ -13,7 +13,6 @@ #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/values.h" #include "chrome/browser/browser_process.h" @@ -162,8 +161,8 @@ void LocalPrinterHandlerChromeos::GetDefaultPrinter(DefaultPrinterCallback cb) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // TODO(crbug.com/660898): Add default printers to ChromeOS. - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(cb), "")); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(cb), "")); } void LocalPrinterHandlerChromeos::StartGetPrinters( @@ -197,8 +196,8 @@ void LocalPrinterHandlerChromeos::StartGetCapability( printers_manager_->GetPrinter(printer_name); if (!printer) { // If the printer was removed, the lookup will fail. - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(cb), base::Value())); + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(std::move(cb), base::Value())); return; } diff --git a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc index 89955ca893c..5f148db042a 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/local_printer_handler_default.cc @@ -47,9 +47,8 @@ scoped_refptr<base::TaskRunner> CreatePrinterHandlerTaskRunner() { #elif defined(OS_WIN) // Windows drivers are likely not thread-safe and need to be accessed on the // UI thread. - return base::CreateSingleThreadTaskRunner({content::BrowserThread::UI, - base::MayBlock(), - base::TaskPriority::USER_VISIBLE}); + return content::GetUIThreadTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE}); #else // Be conservative on unsupported platforms. return base::ThreadPool::CreateSingleThreadTaskRunner(kTraits); diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index deefb421385..a61439ed8ca 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.cc @@ -83,7 +83,7 @@ #include "chrome/browser/device_identity/device_oauth2_token_service_factory.h" #include "chrome/browser/ui/settings_window_manager_chromeos.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" -#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h" +#include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" #include "chromeos/printing/printer_configuration.h" #include "components/signin/public/identity_manager/scope_set.h" #endif @@ -802,9 +802,8 @@ void PrintPreviewHandler::HandleSignin(const base::ListValue* args) { // account management flows will go through native UIs and not through a // tabbed browser window. if (add_account) { - chromeos::InlineLoginHandlerDialogChromeOS::Show( - chromeos::InlineLoginHandlerDialogChromeOS::Source:: - kPrintPreviewDialog); + chromeos::InlineLoginDialogChromeOS::Show( + chromeos::InlineLoginDialogChromeOS::Source::kPrintPreviewDialog); } else { chrome::SettingsWindowManager::GetInstance()->ShowOSSettings( profile, chromeos::settings::mojom::kMyAccountsSubpagePath); @@ -1385,19 +1384,21 @@ void PrintPreviewHandler::SendManipulateSettingsForTest( #if defined(OS_CHROMEOS) void PrintPreviewHandler::HandleRequestPrinterStatusUpdate( const base::ListValue* args) { - CHECK_EQ(1U, args->GetList().size()); + CHECK_EQ(2U, args->GetSize()); + + const std::string& callback_id = args->GetList()[0].GetString(); + const std::string& printer_id = args->GetList()[1].GetString(); + PrinterHandler* handler = GetPrinterHandler(PrinterType::kLocal); handler->StartPrinterStatusRequest( - args->GetList()[0].GetString(), - base::BindOnce(&PrintPreviewHandler::OnPrinterStatusUpdated, - weak_factory_.GetWeakPtr())); + printer_id, base::BindOnce(&PrintPreviewHandler::OnPrinterStatusUpdated, + weak_factory_.GetWeakPtr(), callback_id)); } void PrintPreviewHandler::OnPrinterStatusUpdated( + const std::string& callback_id, const base::Value& cups_printer_status) { - // "printer-status-update" will also trigger non-PrintPreview UI for - // consuming fresh printer statuses. - FireWebUIListener("printer-status-update", cups_printer_status); + ResolveJavascriptCallback(base::Value(callback_id), cups_printer_status); } #endif diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h index 0250e8bca9b..735f18a95e7 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_handler.h @@ -315,8 +315,9 @@ class PrintPreviewHandler : public content::WebUIMessageHandler, // Called to initiate a status request for a printer. void HandleRequestPrinterStatusUpdate(const base::ListValue* args); - // Invokes Web UI Listener "printer-status-update" with new printer status. - void OnPrinterStatusUpdated(const base::Value& cups_printer_status); + // Resolves callback with printer status. + void OnPrinterStatusUpdated(const std::string& callback_id, + const base::Value& cups_printer_status); #endif // A count of how many requests received to regenerate preview data. diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 43cddc1495e..1d226233cce 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.cc @@ -25,11 +25,11 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/synchronization/lock.h" -#include "base/task/post_task.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" +#include "chrome/browser/pdf/pdf_extension_util.h" #include "chrome/browser/printing/background_printing_manager.h" #include "chrome/browser/printing/print_job_manager.h" #include "chrome/browser/printing/print_preview_data_service.h" @@ -37,6 +37,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/webui/metrics_handler.h" +#include "chrome/browser/ui/webui/plural_string_handler.h" #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h" #include "chrome/browser/ui/webui/theme_source.h" #include "chrome/browser/ui/webui/webui_util.h" @@ -46,6 +47,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/component_extension_resources.h" #include "chrome/grit/generated_resources.h" +#include "chrome/grit/print_preview_pdf_resources.h" #include "chrome/grit/print_preview_resources.h" #include "chrome/grit/print_preview_resources_map.h" #include "chromeos/constants/chromeos_features.h" @@ -59,8 +61,9 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_data_source.h" #include "extensions/common/constants.h" -#include "printing/page_size_margins.h" +#include "printing/mojom/print.mojom.h" #include "printing/print_job_constants.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/gfx/geometry/rect.h" @@ -77,7 +80,6 @@ #include "chrome/browser/ui/webui/managed_ui_handler.h" #endif -using content::BrowserThread; using content::WebContents; namespace printing { @@ -106,8 +108,8 @@ void StopWorker(int document_cookie) { std::unique_ptr<PrinterQuery> printer_query = queue->PopPrinterQuery(document_cookie); if (printer_query) { - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&PrinterQuery::StopWorker, std::move(printer_query))); } } @@ -290,12 +292,6 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { {"printButton", IDS_PRINT_PREVIEW_PRINT_BUTTON}, {"printDestinationsTitle", IDS_PRINT_PREVIEW_PRINT_DESTINATIONS_TITLE}, {"printPagesLabel", IDS_PRINT_PREVIEW_PRINT_PAGES_LABEL}, - {"printPreviewPageLabelPlural", IDS_PRINT_PREVIEW_PAGE_LABEL_PLURAL}, - {"printPreviewPageLabelSingular", IDS_PRINT_PREVIEW_PAGE_LABEL_SINGULAR}, - {"printPreviewSheetsLabelPlural", IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL}, - {"printPreviewSheetsLabelSingular", - IDS_PRINT_PREVIEW_SHEETS_LABEL_SINGULAR}, - {"printPreviewSummaryFormatShort", IDS_PRINT_PREVIEW_SUMMARY_FORMAT_SHORT}, {"printToGoogleDrive", IDS_PRINT_PREVIEW_PRINT_TO_GOOGLE_DRIVE}, {"printToPDF", IDS_PRINT_PREVIEW_PRINT_TO_PDF}, {"printerSharingInviteText", IDS_PRINT_PREVIEW_INVITE_TEXT}, @@ -331,9 +327,25 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { {"pinErrorMessage", IDS_PRINT_PREVIEW_PIN_ERROR_MESSAGE}, {"pinPlaceholder", IDS_PRINT_PREVIEW_PIN_PLACEHOLDER}, {"printerEulaURL", IDS_PRINT_PREVIEW_EULA_URL}, - {"sheetsLimitErrorMessage", IDS_PRINT_PREVIEW_SHEETS_LIMIT_ERROR_MESSAGE}, - {"sheetsLimitLabelSingular", IDS_PRINT_PREVIEW_SHEETS_LIMIT_LABEL_SINGULAR}, - {"sheetsLimitLabelPlural", IDS_PRINT_PREVIEW_SHEETS_LIMIT_LABEL_PLURAL}, + {"printerStatusConnectingToDevice", + IDS_PRINT_PREVIEW_PRINTER_STATUS_CONNECTING_TO_DEVICE}, + {"printerStatusDeviceError", IDS_PRINT_PREVIEW_PRINTER_STATUS_DEVICE_ERROR}, + {"printerStatusDoorOpen", IDS_PRINT_PREVIEW_PRINTER_STATUS_DOOR_OPEN}, + {"printerStatusLowOnInk", IDS_PRINT_PREVIEW_PRINTER_STATUS_LOW_ON_INK}, + {"printerStatusLowOnPaper", IDS_PRINT_PREVIEW_PRINTER_STATUS_LOW_ON_PAPER}, + {"printerStatusOutOfInk", IDS_PRINT_PREVIEW_PRINTER_STATUS_OUT_OF_INK}, + {"printerStatusOutOfPaper", IDS_PRINT_PREVIEW_PRINTER_STATUS_OUT_OF_PAPER}, + {"printerStatusOutputAlmostFull", + IDS_PRINT_PREVIEW_PRINTER_STATUS_OUPUT_ALMOST_FULL}, + {"printerStatusOutputFull", IDS_PRINT_PREVIEW_PRINTER_STATUS_OUPUT_FULL}, + {"printerStatusPaperJam", IDS_PRINT_PREVIEW_PRINTER_STATUS_PAPER_JAM}, + {"printerStatusPaused", IDS_PRINT_PREVIEW_PRINTER_STATUS_PAUSED}, + {"printerStatusPrinterQueueFull", + IDS_PRINT_PREVIEW_PRINTER_STATUS_PRINTER_QUEUE_FULL}, + {"printerStatusPrinterUnreachable", + IDS_PRINT_PREVIEW_PRINTER_STATUS_PRINTER_UNREACHABLE}, + {"printerStatusStopped", IDS_PRINT_PREVIEW_PRINTER_STATUS_STOPPED}, + {"printerStatusTrayMissing", IDS_PRINT_PREVIEW_PRINTER_STATUS_TRAY_MISSING}, #endif #if defined(OS_MACOSX) {"openPdfInPreviewOption", IDS_PRINT_PREVIEW_OPEN_PDF_IN_PREVIEW_APP}, @@ -351,6 +363,13 @@ void AddPrintPreviewStrings(content::WebUIDataSource* source) { l10n_util::GetStringFUTF16( IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION, shortcut_text)); #endif + + // Register strings for the PDF viewer, so that $i18n{} replacements work. + base::Value pdf_strings(base::Value::Type::DICTIONARY); + pdf_extension_util::AddStrings( + pdf_extension_util::PdfViewerContext::kPrintPreview, &pdf_strings); + pdf_extension_util::AddAdditionalData(&pdf_strings); + source->AddLocalizedStrings(base::Value::AsDictionaryValue(pdf_strings)); } void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) { @@ -381,39 +400,41 @@ void AddPrintPreviewFlags(content::WebUIDataSource* source, Profile* profile) { void SetupPrintPreviewPlugin(content::WebUIDataSource* source) { static constexpr webui::ResourcePath kPdfResources[] = { - {"pdf/bookmark_type.js", IDR_PDF_BOOKMARK_TYPE_JS}, - {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS}, - {"pdf/constants.js", IDR_PDF_CONSTANTS_JS}, - {"pdf/controller.js", IDR_PDF_CONTROLLER_JS}, - {"pdf/elements/icons.js", IDR_PDF_ICONS_JS}, - {"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS}, - {"pdf/elements/viewer-error-screen.js", IDR_PDF_VIEWER_ERROR_SCREEN_JS}, - {"pdf/elements/viewer-page-indicator.js", - IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS}, - {"pdf/elements/viewer-zoom-button.js", IDR_PDF_VIEWER_ZOOM_BUTTON_JS}, - {"pdf/elements/viewer-zoom-toolbar.js", IDR_PDF_VIEWER_ZOOM_SELECTOR_JS}, - {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS}, - {"pdf/index.css", IDR_PDF_INDEX_CSS}, - {"pdf/index.html", IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML}, - {"pdf/main_pp.js", IDR_PRINT_PREVIEW_PDF_MAIN_PP_JS}, - {"pdf/main_util.js", IDR_PDF_MAIN_UTIL_JS}, - {"pdf/metrics.js", IDR_PDF_METRICS_JS}, - {"pdf/navigator.js", IDR_PDF_NAVIGATOR_JS}, - {"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS}, - {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS}, - {"pdf/pdf_viewer.js", IDR_PDF_PDF_VIEWER_JS}, - {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS}, - {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS}, - {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS}, - {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS}, + {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS}, + {"pdf/constants.js", IDR_PDF_CONSTANTS_JS}, + {"pdf/controller.js", IDR_PDF_CONTROLLER_JS}, + {"pdf/elements/icons.js", IDR_PDF_ICONS_JS}, + {"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS}, + {"pdf/elements/viewer-error-screen.js", IDR_PDF_VIEWER_ERROR_SCREEN_JS}, + {"pdf/elements/viewer-page-indicator.js", + IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS}, + {"pdf/elements/viewer-zoom-button.js", IDR_PDF_VIEWER_ZOOM_BUTTON_JS}, + {"pdf/elements/viewer-zoom-toolbar.js", IDR_PDF_VIEWER_ZOOM_SELECTOR_JS}, + {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS}, + {"pdf/index.css", IDR_PDF_INDEX_CSS}, + {"pdf/index.html", IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML}, + {"pdf/main.js", IDR_PDF_MAIN_JS}, + {"pdf/metrics.js", IDR_PDF_METRICS_JS}, + {"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS}, + {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS}, + {"pdf/pdf_viewer_base.js", IDR_PDF_PDF_VIEWER_BASE_JS}, + {"pdf/pdf_viewer.js", IDR_PRINT_PREVIEW_PDF_PDF_VIEWER_PP_JS}, + {"pdf/pdf_viewer_shared_style.js", IDR_PDF_PDF_VIEWER_SHARED_STYLE_JS}, + {"pdf/pdf_viewer_utils.js", IDR_PDF_PDF_VIEWER_UTILS_JS}, + {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS}, + {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS}, + {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS}, + {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS}, }; webui::AddResourcePathsBulk(source, kPdfResources); source->SetRequestFilter(base::BindRepeating(&ShouldHandleRequestCallback), base::BindRepeating(&HandleRequestCallback)); - source->OverrideContentSecurityPolicyChildSrc("child-src 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ChildSrc, "child-src 'self';"); source->DisableDenyXFrameOptions(); - source->OverrideContentSecurityPolicyObjectSrc("object-src 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ObjectSrc, "object-src 'self';"); } content::WebUIDataSource* CreatePrintPreviewUISource(Profile* profile) { @@ -440,6 +461,19 @@ PrintPreviewHandler* CreatePrintPreviewHandlers(content::WebUI* web_ui) { PrintPreviewHandler* handler_ptr = handler.get(); web_ui->AddMessageHandler(std::move(handler)); web_ui->AddMessageHandler(std::make_unique<MetricsHandler>()); + + // Add a handler to provide pluralized strings. + auto plural_string_handler = std::make_unique<PluralStringHandler>(); + plural_string_handler->AddLocalizedString( + "printPreviewPageSummaryLabel", IDS_PRINT_PREVIEW_PAGE_SUMMARY_LABEL); + plural_string_handler->AddLocalizedString( + "printPreviewSheetSummaryLabel", IDS_PRINT_PREVIEW_SHEET_SUMMARY_LABEL); +#if defined(OS_CHROMEOS) + plural_string_handler->AddLocalizedString( + "sheetsLimitErrorMessage", IDS_PRINT_PREVIEW_SHEETS_LIMIT_ERROR_MESSAGE); +#endif + web_ui->AddMessageHandler(std::move(plural_string_handler)); + return handler_ptr; } @@ -624,10 +658,6 @@ void PrintPreviewUI::OnInitiatorClosed() { } } -void PrintPreviewUI::OnPrintPreviewCancelled(int request_id) { - handler_->OnPrintPreviewCancelled(request_id); -} - void PrintPreviewUI::OnPrintPreviewRequest(int request_id) { if (!initial_preview_start_time_.is_null()) { base::UmaHistogramTimes( @@ -638,7 +668,7 @@ void PrintPreviewUI::OnPrintPreviewRequest(int request_id) { } void PrintPreviewUI::OnDidStartPreview( - const PrintHostMsg_DidStartPreview_Params& params, + const mojom::DidStartPreviewParams& params, int request_id) { DCHECK_GT(params.page_count, 0); DCHECK(!params.pages_to_render.empty()); @@ -656,7 +686,7 @@ void PrintPreviewUI::OnDidStartPreview( } void PrintPreviewUI::OnDidGetDefaultPageLayout( - const PageSizeMargins& page_layout, + const mojom::PageSizeMargins& page_layout, const gfx::Rect& printable_area, bool has_custom_page_size_style, int request_id) { @@ -729,10 +759,6 @@ void PrintPreviewUI::OnPrintPreviewFailed(int request_id) { handler_->OnPrintPreviewFailed(request_id); } -void PrintPreviewUI::OnInvalidPrinterSettings(int request_id) { - handler_->OnInvalidPrinterSettings(request_id); -} - void PrintPreviewUI::OnHidePreviewDialog() { WebContents* preview_dialog = web_ui()->GetWebContents(); BackgroundPrintingManager* background_printing_manager = @@ -776,6 +802,19 @@ void PrintPreviewUI::PrintPreviewFailed(int32_t document_cookie, OnPrintPreviewFailed(request_id); } +void PrintPreviewUI::PrintPreviewCancelled(int32_t document_cookie, + int32_t request_id) { + // Always need to stop the worker. + StopWorker(document_cookie); + handler_->OnPrintPreviewCancelled(request_id); +} + +void PrintPreviewUI::PrinterSettingsInvalid(int32_t document_cookie, + int32_t request_id) { + StopWorker(document_cookie); + handler_->OnInvalidPrinterSettings(request_id); +} + // static void PrintPreviewUI::SetDelegateForTesting(TestDelegate* delegate) { g_test_delegate = delegate; diff --git a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h index 89ade79356c..32bc87ad8a1 100644 --- a/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h +++ b/chromium/chrome/browser/ui/webui/print_preview/print_preview_ui.h @@ -21,10 +21,10 @@ #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" #include "components/printing/common/print.mojom.h" #include "mojo/public/cpp/bindings/associated_receiver.h" +#include "printing/mojom/print.mojom-forward.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" -struct PrintHostMsg_DidStartPreview_Params; struct PrintHostMsg_PreviewIds; struct PrintHostMsg_RequestPrintPreview_Params; @@ -41,7 +41,6 @@ class Rect; namespace printing { class PrintPreviewHandler; -struct PageSizeMargins; class PrintPreviewUI : public ConstrainedWebDialogUI, public mojom::PrintPreviewUI { @@ -62,6 +61,10 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, void SetOptionsFromDocument(const mojom::OptionsFromDocumentParamsPtr params, int32_t request_id) override; void PrintPreviewFailed(int32_t document_cookie, int32_t request_id) override; + void PrintPreviewCancelled(int32_t document_cookie, + int32_t request_id) override; + void PrinterSettingsInvalid(int32_t document_cookie, + int32_t request_id) override; bool IsBound() const; @@ -138,12 +141,12 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, virtual void OnPrintPreviewRequest(int request_id); // Notifies the Web UI about the properties of the request preview. - void OnDidStartPreview(const PrintHostMsg_DidStartPreview_Params& params, + void OnDidStartPreview(const mojom::DidStartPreviewParams& params, int request_id); // Notifies the Web UI of the default page layout according to the currently // selected printer and page size. - void OnDidGetDefaultPageLayout(const PageSizeMargins& page_layout, + void OnDidGetDefaultPageLayout(const mojom::PageSizeMargins& page_layout, const gfx::Rect& printable_area, bool has_custom_page_size_style, int request_id); @@ -172,18 +175,10 @@ class PrintPreviewUI : public ConstrainedWebDialogUI, // closed, which may occur for several reasons, e.g. tab closure or crash. void OnPrintPreviewDialogClosed(); - // Notifies the Web UI that the preview request identified by |request_id| - // was cancelled. - void OnPrintPreviewCancelled(int request_id); - // Notifies the Web UI that initiator is closed, so we can disable all the // controls that need the initiator for generating the preview data. void OnInitiatorClosed(); - // Notifies the Web UI that the printer is unavailable or its settings are - // invalid. |request_id| is the preview request id with the invalid printer. - void OnInvalidPrinterSettings(int request_id); - // Notifies the Web UI to cancel the pending preview request. virtual void OnCancelPendingPreviewRequest(); diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc index 22ea3e49882..ea3df0ae1a1 100644 --- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc +++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.cc @@ -7,23 +7,37 @@ #include <string> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/feature_list.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/quota_internals/quota_internals_proxy.h" #include "chrome/browser/ui/webui/quota_internals/quota_internals_types.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_ui.h" +#include "content/public/common/content_features.h" using content::BrowserContext; +namespace { + +bool IsStoragePressureEnabled() { +#if defined(OS_ANDROID) + return false; +#else + return base::FeatureList::IsEnabled(features::kStoragePressureUI); +#endif +} + +} // namespace + namespace quota_internals { QuotaInternalsHandler::QuotaInternalsHandler() {} QuotaInternalsHandler::~QuotaInternalsHandler() { if (proxy_.get()) - proxy_->handler_ = NULL; + proxy_->handler_ = nullptr; } void QuotaInternalsHandler::RegisterMessages() { @@ -75,6 +89,13 @@ void QuotaInternalsHandler::ReportStatistics(const Statistics& stats) { SendMessage("StatisticsUpdated", dict); } +void QuotaInternalsHandler::ReportStoragePressureFlag() { + base::DictionaryValue flag_enabled; + flag_enabled.SetBoolean("isStoragePressureEnabled", + IsStoragePressureEnabled()); + SendMessage("StoragePressureFlagUpdated", flag_enabled); +} + void QuotaInternalsHandler::SendMessage(const std::string& message, const base::Value& value) { web_ui()->CallJavascriptFunctionUnsafe("cr.quota.messageHandler", @@ -84,6 +105,7 @@ void QuotaInternalsHandler::SendMessage(const std::string& message, void QuotaInternalsHandler::OnRequestInfo(const base::ListValue*) { if (!proxy_.get()) proxy_ = new QuotaInternalsProxy(this); + ReportStoragePressureFlag(); proxy_->RequestInfo( BrowserContext::GetDefaultStoragePartition( Profile::FromWebUI(web_ui()))->GetQuotaManager()); diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h index 9e74b93ce4d..1469f488491 100644 --- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h +++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_handler.h @@ -42,6 +42,7 @@ class QuotaInternalsHandler : public content::WebUIMessageHandler { void ReportPerHostInfo(const std::vector<PerHostStorageInfo>& hosts); void ReportPerOriginInfo(const std::vector<PerOriginStorageInfo>& origins); void ReportStatistics(const Statistics& stats); + void ReportStoragePressureFlag(); private: void OnRequestInfo(const base::ListValue*); diff --git a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc index db85c160a40..1e06e9b105b 100644 --- a/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc +++ b/chromium/chrome/browser/ui/webui/quota_internals/quota_internals_proxy.cc @@ -8,7 +8,6 @@ #include <string> #include "base/bind.h" -#include "base/task/post_task.h" #include "chrome/browser/ui/webui/quota_internals/quota_internals_handler.h" #include "chrome/browser/ui/webui/quota_internals/quota_internals_types.h" #include "content/public/browser/browser_task_traits.h" @@ -27,8 +26,8 @@ void QuotaInternalsProxy::RequestInfo( scoped_refptr<storage::QuotaManager> quota_manager) { DCHECK(quota_manager.get()); if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - base::PostTask( - FROM_HERE, {BrowserThread::IO}, + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&QuotaInternalsProxy::RequestInfo, this, quota_manager)); return; } @@ -71,8 +70,8 @@ void QuotaInternalsProxy::TriggerStoragePressure( scoped_refptr<storage::QuotaManager> quota_manager) { DCHECK(quota_manager.get()); if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { - base::PostTask(FROM_HERE, {BrowserThread::IO}, - base::BindOnce(&QuotaInternalsProxy::TriggerStoragePressure, + content::GetIOThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&QuotaInternalsProxy::TriggerStoragePressure, this, origin, quota_manager)); return; } @@ -86,8 +85,8 @@ QuotaInternalsProxy::~QuotaInternalsProxy() = default; if (!handler_) \ return; \ if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { \ - base::PostTask(FROM_HERE, {BrowserThread::UI}, \ - base::BindOnce(&QuotaInternalsProxy::func, this, arg)); \ + content::GetUIThreadTaskRunner({})->PostTask( \ + FROM_HERE, base::BindOnce(&QuotaInternalsProxy::func, this, arg)); \ return; \ } \ \ diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc index 186ef33a6d4..747c8494454 100644 --- a/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc +++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_handler.cc @@ -8,7 +8,6 @@ #include "base/bind.h" #include "base/numerics/safe_conversions.h" -#include "base/task/post_task.h" #include "base/values.h" #include "content/public/browser/browser_child_process_host_iterator.h" #include "content/public/browser/browser_task_traits.h" @@ -27,44 +26,6 @@ using content::RenderProcessHost; namespace sandbox_handler { namespace { -// This only includes OS_WIN included SandboxType values. -std::string GetSandboxTypeInEnglish(content::SandboxType sandbox_type) { - switch (sandbox_type) { - case content::SandboxType::kNoSandbox: - return "Unsandboxed"; - case content::SandboxType::kNoSandboxAndElevatedPrivileges: - return "Unsandboxed (Elevated)"; - case content::SandboxType::kXrCompositing: - return "XR Compositing"; - case content::SandboxType::kRenderer: - return "Renderer"; - case content::SandboxType::kUtility: - return "Utility"; - case content::SandboxType::kGpu: - return "GPU"; - case content::SandboxType::kPpapi: - return "PPAPI"; - case content::SandboxType::kNetwork: - return "Network"; - case content::SandboxType::kCdm: - return "CDM"; - case content::SandboxType::kPrintCompositor: - return "Print Compositor"; - case content::SandboxType::kAudio: - return "Audio"; - case content::SandboxType::kSpeechRecognition: - return "Speech Recognition"; - case content::SandboxType::kProxyResolver: - return "Proxy Resolver"; - case content::SandboxType::kPdfConversion: - return "PDF Conversion"; - case content::SandboxType::kSharingService: - return "Sharing"; - case content::SandboxType::kVideoCapture: - return "Video Capture"; - } -} - base::Value FetchBrowserChildProcesses() { // The |BrowserChildProcessHostIterator| must only be used on the IO thread. DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -85,7 +46,8 @@ base::Value FetchBrowserChildProcesses() { proc.SetPath("metricsName", base::Value(process_data.metrics_name)); proc.SetPath( "sandboxType", - base::Value(GetSandboxTypeInEnglish(process_data.sandbox_type))); + base::Value(service_manager::SandboxWin::GetSandboxTypeInEnglish( + process_data.sandbox_type))); browser_processes.Append(std::move(proc)); } @@ -136,9 +98,8 @@ void SandboxHandler::HandleRequestSandboxDiagnostics( AllowJavascript(); - base::PostTaskAndReplyWithResult( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&FetchBrowserChildProcesses), + content::GetIOThreadTaskRunner({})->PostTaskAndReplyWithResult( + FROM_HERE, base::BindOnce(&FetchBrowserChildProcesses), base::BindOnce(&SandboxHandler::FetchBrowserChildProcessesCompleted, weak_ptr_factory_.GetWeakPtr())); } @@ -157,8 +118,8 @@ void SandboxHandler::FetchBrowserChildProcessesCompleted( void SandboxHandler::FetchSandboxDiagnosticsCompleted( base::Value sandbox_policies) { sandbox_policies_ = std::move(sandbox_policies); - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&SandboxHandler::GetRendererProcessesAndFinish, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&SandboxHandler::GetRendererProcessesAndFinish, weak_ptr_factory_.GetWeakPtr())); } diff --git a/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc index 40567210a5a..481b12ba8bf 100644 --- a/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/sandbox/sandbox_internals_ui.cc @@ -25,8 +25,8 @@ #endif #if defined(OS_LINUX) +#include "content/public/browser/zygote_host/zygote_host_linux.h" #include "services/service_manager/sandbox/sandbox.h" -#include "services/service_manager/zygote/zygote_host_linux.h" #endif namespace { @@ -35,7 +35,7 @@ namespace { static void SetSandboxStatusData(content::WebUIDataSource* source) { // Get expected sandboxing status of renderers. const int status = - service_manager::ZygoteHost::GetInstance()->GetRendererSandboxStatus(); + content::ZygoteHost::GetInstance()->GetRendererSandboxStatus(); source->AddBoolean("suid", status & service_manager::SandboxLinux::kSUID); source->AddBoolean("userNs", status & service_manager::SandboxLinux::kUserNS); diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.cc b/chromium/chrome/browser/ui/webui/settings/about_handler.cc index 9f615ac73cb..a1bb190d093 100644 --- a/chromium/chrome/browser/ui/webui/settings/about_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/about_handler.cc @@ -101,15 +101,12 @@ struct RegulatoryLabel { // Returns message that informs user that for update it's better to // connect to a network of one of the allowed types. base::string16 GetAllowedConnectionTypesMessage() { - const chromeos::NetworkState* network = chromeos::NetworkHandler::Get() - ->network_state_handler() - ->DefaultNetwork(); - const bool mobile_data = - network && network->IsConnectedState() && network->IsUsingMobileData(); - if (help_utils_chromeos::IsUpdateOverCellularAllowed( - true /* interactive */)) { - return mobile_data + /*interactive=*/true)) { + const bool metered = chromeos::NetworkHandler::Get() + ->network_state_handler() + ->default_network_is_metered(); + return metered ? l10n_util::GetStringUTF16( IDS_UPGRADE_NETWORK_LIST_CELLULAR_ALLOWED_NOT_AUTOMATIC) : l10n_util::GetStringUTF16( @@ -652,6 +649,7 @@ void AboutHandler::RequestUpdate() { void AboutHandler::SetUpdateStatus(VersionUpdater::Status status, int progress, bool rollback, + bool powerwash, const std::string& version, int64_t size, const base::string16& message) { @@ -663,6 +661,7 @@ void AboutHandler::SetUpdateStatus(VersionUpdater::Status status, event->SetString("message", message); event->SetInteger("progress", progress); event->SetBoolean("rollback", rollback); + event->SetBoolean("powerwash", powerwash); event->SetString("version", version); // DictionaryValue does not support int64_t, so convert to string. event->SetString("size", base::NumberToString(size)); diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.h b/chromium/chrome/browser/ui/webui/settings/about_handler.h index 4b8bf98b5a3..bc71e2da278 100644 --- a/chromium/chrome/browser/ui/webui/settings/about_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/about_handler.h @@ -135,6 +135,7 @@ class AboutHandler : public settings::SettingsPageUIHandler, void SetUpdateStatus(VersionUpdater::Status status, int progress, bool rollback, + bool powerwash, const std::string& version, int64_t size, const base::string16& fail_message); 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 ea9dc60efd8..a90a99bfebb 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.cc @@ -4,11 +4,11 @@ #include "chrome/browser/ui/webui/settings/chromeos/about_section.h" +#include "base/feature_list.h" #include "base/i18n/message_formatter.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" -#include "build/branding_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/arc/arc_util.h" @@ -19,10 +19,13 @@ #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/channel_info.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 "chromeos/constants/chromeos_features.h" #include "chromeos/dbus/constants/dbus_switches.h" +#include "components/prefs/pref_service.h" #include "components/strings/grit/components_chromium_strings.h" #include "components/strings/grit/components_strings.h" #include "components/user_manager/user_manager.h" @@ -44,16 +47,14 @@ const std::vector<SearchConcept>& GetAboutSearchConcepts() { mojom::SearchResultIcon::kChrome, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kDetailedBuildInfo}, - {IDS_OS_SETTINGS_TAG_ABOUT_CHROME_OS_DETAILED_BUILD_ALT1, - SearchConcept::kAltTagEnd}}, - {IDS_OS_SETTINGS_TAG_ABOUT_CHROME_OS, + {.subpage = mojom::Subpage::kDetailedBuildInfo}}, + {IDS_SETTINGS_ABOUT_OS, mojom::kAboutChromeOsDetailsSubpagePath, mojom::SearchResultIcon::kChrome, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kAboutChromeOsDetails}}, - {IDS_OS_SETTINGS_TAG_ABOUT_CHROME_OS_VERSION, + {IDS_OS_SETTINGS_TAG_OS_VERSION, mojom::kAboutChromeOsDetailsSubpagePath, mojom::SearchResultIcon::kChrome, mojom::SearchResultDefaultRank::kMedium, @@ -62,13 +63,67 @@ const std::vector<SearchConcept>& GetAboutSearchConcepts() { {IDS_OS_SETTINGS_TAG_ABOUT_CHROME_OS_CHANNEL, mojom::kDetailedBuildInfoSubpagePath, mojom::SearchResultIcon::kChrome, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kChangeChromeChannel}}, + {IDS_OS_SETTINGS_TAG_ABOUT_OS_UPDATE, + mojom::kAboutChromeOsDetailsSubpagePath, + mojom::SearchResultIcon::kChrome, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kCheckForOsUpdate}}, + {IDS_OS_SETTINGS_TAG_ABOUT_HELP, + mojom::kAboutChromeOsDetailsSubpagePath, + mojom::SearchResultIcon::kChrome, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kGetHelpWithChromeOs}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetAboutReleaseNotesSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_ABOUT_RELEASE_NOTES, + mojom::kAboutChromeOsDetailsSubpagePath, + mojom::SearchResultIcon::kChrome, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kSeeWhatsNew}, + {IDS_OS_SETTINGS_TAG_ABOUT_RELEASE_NOTES_ALT1, + SearchConcept::kAltTagEnd}}, + }); + return *tags; +} + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +const std::vector<SearchConcept>& GetAboutTermsOfServiceSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_ABOUT_TERMS_OF_SERVICE, + mojom::kAboutChromeOsDetailsSubpagePath, + mojom::SearchResultIcon::kChrome, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kTermsOfService}}, }); return *tags; } +const std::vector<SearchConcept>& GetAboutReportIssueSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_ABOUT_REPORT_ISSUE, + mojom::kAboutChromeOsDetailsSubpagePath, + mojom::SearchResultIcon::kChrome, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kReportAnIssue}, + {IDS_OS_SETTINGS_TAG_ABOUT_REPORT_ISSUE_ALT1, + SearchConcept::kAltTagEnd}}, + }); + return *tags; +} +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + // Returns the link to the safety info for the device (if it exists). std::string GetSafetyInfoLink() { const std::vector<std::string> board = @@ -99,10 +154,33 @@ bool IsDeviceManaged() { } // namespace +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +AboutSection::AboutSection(Profile* profile, + SearchTagRegistry* search_tag_registry, + PrefService* pref_service) + : AboutSection(profile, search_tag_registry) { + pref_service_ = pref_service; + + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetAboutTermsOfServiceSearchConcepts()); + + pref_change_registrar_.Init(pref_service_); + pref_change_registrar_.Add( + prefs::kUserFeedbackAllowed, + base::BindRepeating(&AboutSection::UpdateReportIssueSearchTags, + base::Unretained(this))); + UpdateReportIssueSearchTags(); +} +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + AboutSection::AboutSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { - registry()->AddSearchTags(GetAboutSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetAboutSearchConcepts()); + + if (base::FeatureList::IsEnabled(features::kReleaseNotes)) + updater.AddSearchTags(GetAboutReleaseNotesSearchConcepts()); } AboutSection::~AboutSection() = default; @@ -270,5 +348,58 @@ void AboutSection::AddHandlers(content::WebUI* web_ui) { web_ui->AddMessageHandler(std::make_unique<::settings::AboutHandler>()); } +int AboutSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_ABOUT_OS; +} + +mojom::Section AboutSection::GetSection() const { + return mojom::Section::kAboutChromeOs; +} + +mojom::SearchResultIcon AboutSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kChrome; +} + +std::string AboutSection::GetSectionPath() const { + return mojom::kAboutChromeOsSectionPath; +} + +void AboutSection::RegisterHierarchy(HierarchyGenerator* generator) const { + // About Chrome OS. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_ABOUT_OS, mojom::Subpage::kAboutChromeOsDetails, + mojom::SearchResultIcon::kChrome, mojom::SearchResultDefaultRank::kMedium, + mojom::kAboutChromeOsDetailsSubpagePath); + static constexpr mojom::Setting kAboutChromeOsDetailsSettings[] = { + mojom::Setting::kCheckForOsUpdate, mojom::Setting::kSeeWhatsNew, + mojom::Setting::kGetHelpWithChromeOs, mojom::Setting::kReportAnIssue, + mojom::Setting::kTermsOfService}; + RegisterNestedSettingBulk(mojom::Subpage::kAboutChromeOsDetails, + kAboutChromeOsDetailsSettings, generator); + + // Detailed build info. + generator->RegisterNestedSubpage( + IDS_SETTINGS_ABOUT_PAGE_DETAILED_BUILD_INFO, + mojom::Subpage::kDetailedBuildInfo, mojom::Subpage::kAboutChromeOsDetails, + mojom::SearchResultIcon::kChrome, mojom::SearchResultDefaultRank::kMedium, + mojom::kDetailedBuildInfoSubpagePath); + static constexpr mojom::Setting kDetailedBuildInfoSettings[] = { + mojom::Setting::kChangeChromeChannel, + mojom::Setting::kCopyDetailedBuildInfo}; + RegisterNestedSettingBulk(mojom::Subpage::kDetailedBuildInfo, + kDetailedBuildInfoSettings, generator); +} + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) +void AboutSection::UpdateReportIssueSearchTags() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + if (pref_service_->GetBoolean(prefs::kUserFeedbackAllowed)) + updater.AddSearchTags(GetAboutReportIssueSearchConcepts()); + else + updater.RemoveSearchTags(GetAboutReportIssueSearchConcepts()); +} +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.h index 0e619e80d91..506f0b67d56 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/about_section.h @@ -5,7 +5,9 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ABOUT_SECTION_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_ABOUT_SECTION_H_ +#include "build/branding_buildflags.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" +#include "components/prefs/pref_change_registrar.h" namespace content { class WebUIDataSource; @@ -19,6 +21,11 @@ class SearchTagRegistry; // Provides UI strings and search tags for the settings "About Chrome OS" page. class AboutSection : public OsSettingsSection { public: +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + AboutSection(Profile* profile, + SearchTagRegistry* search_tag_registry, + PrefService* pref_service); +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) AboutSection(Profile* profile, SearchTagRegistry* search_tag_registry); ~AboutSection() override; @@ -26,6 +33,18 @@ class AboutSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; + +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + void UpdateReportIssueSearchTags(); + + PrefService* pref_service_; + PrefChangeRegistrar pref_change_registrar_; +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) }; } // namespace settings 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 1e7b9bf8b08..a38be955b4e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc @@ -23,6 +23,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_features.h" #include "media/base/media_switches.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/accessibility_switches.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -82,16 +83,18 @@ const std::vector<SearchConcept>& GetA11ySearchConcepts() { {IDS_OS_SETTINGS_TAG_A11Y_MONO_AUDIO, mojom::kManageAccessibilitySubpagePath, mojom::SearchResultIcon::kA11y, - mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultDefaultRank::kLow, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kMonoAudio}, {IDS_OS_SETTINGS_TAG_A11Y_MONO_AUDIO_ALT1, SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH, - mojom::kManageAccessibilitySubpagePath, + mojom::kTextToSpeechSubpagePath, mojom::SearchResultIcon::kA11y, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kManageAccessibility}}, + {.subpage = mojom::Subpage::kTextToSpeech}, + {IDS_OS_SETTINGS_TAG_A11Y_TEXT_TO_SPEECH_ALT1, + SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_A11Y_CAPTIONS, mojom::kCaptionsSubpagePath, mojom::SearchResultIcon::kA11y, @@ -262,11 +265,43 @@ const std::vector<SearchConcept>& GetA11yLabelsSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetA11yLiveCaptionSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_A11Y_LIVE_CAPTIONS, + mojom::kManageAccessibilitySubpagePath, + mojom::SearchResultIcon::kA11y, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kLiveCaptions}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetA11yCursorColorSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_A11Y_CURSOR_COLOR, + mojom::kManageAccessibilitySubpagePath, + mojom::SearchResultIcon::kA11y, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kEnableCursorColor}}, + }); + return *tags; +} + bool AreExperimentalA11yLabelsAllowed() { return base::FeatureList::IsEnabled( ::features::kExperimentalAccessibilityLabels); } +bool AreLiveCaptionsAllowed() { + return base::FeatureList::IsEnabled(media::kLiveCaption); +} + +bool IsCursorColorAllowed() { + return features::IsAccessibilityCursorColorEnabled(); +} + bool IsSwitchAccessAllowed() { return base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kEnableExperimentalAccessibilitySwitchAccess); @@ -285,7 +320,8 @@ AccessibilitySection::AccessibilitySection( PrefService* pref_service) : OsSettingsSection(profile, search_tag_registry), pref_service_(pref_service) { - registry()->AddSearchTags(GetA11ySearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetA11ySearchConcepts()); pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add( @@ -323,6 +359,13 @@ void AccessibilitySection::AddLoadTimeData( IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_DEFAULT_LABEL}, {"largeMouseCursorSizeLargeLabel", IDS_SETTINGS_LARGE_MOUSE_CURSOR_SIZE_LARGE_LABEL}, + {"cursorColorEnabledLabel", IDS_SETTINGS_CURSOR_COLOR_ENABLED_LABEL}, + {"cursorColorOptionsLabel", IDS_SETTINGS_CURSOR_COLOR_OPTIONS_LABEL}, + {"cursorColorRed", IDS_SETTINGS_CURSOR_COLOR_RED}, + {"cursorColorOrange", IDS_SETTINGS_CURSOR_COLOR_ORANGE}, + {"cursorColorGreen", IDS_SETTINGS_CURSOR_COLOR_GREEN}, + {"cursorColorBlue", IDS_SETTINGS_CURSOR_COLOR_BLUE}, + {"cursorColorPurple", IDS_SETTINGS_CURSOR_COLOR_PURPLE}, {"highContrastLabel", IDS_SETTINGS_HIGH_CONTRAST_LABEL}, {"stickyKeysLabel", IDS_SETTINGS_STICKY_KEYS_LABEL}, {"chromeVoxLabel", IDS_SETTINGS_CHROMEVOX_LABEL}, @@ -473,6 +516,10 @@ void AccessibilitySection::AddLoadTimeData( IDS_SETTINGS_A11Y_TABLET_MODE_SHELF_BUTTONS_LABEL}, {"tabletModeShelfNavigationButtonsSettingDescription", IDS_SETTINGS_A11Y_TABLET_MODE_SHELF_BUTTONS_DESCRIPTION}, + {"captionsEnableLiveCaptionTitle", + IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_TITLE}, + {"captionsEnableLiveCaptionSubtitle", + IDS_SETTINGS_CAPTIONS_ENABLE_LIVE_CAPTION_SUBTITLE}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); @@ -495,8 +542,10 @@ void AccessibilitySection::AddLoadTimeData( html_source->AddString("tabletModeShelfNavigationButtonsLearnMoreUrl", chrome::kTabletModeGesturesLearnMoreURL); - html_source->AddBoolean("enableLiveCaption", - base::FeatureList::IsEnabled(media::kLiveCaption)); + html_source->AddBoolean("enableLiveCaption", AreLiveCaptionsAllowed()); + + html_source->AddBoolean("showExperimentalAccessibilityCursorColor", + IsCursorColorAllowed()); ::settings::AddCaptionSubpageStrings(html_source); } @@ -510,33 +559,132 @@ void AccessibilitySection::AddHandlers(content::WebUI* web_ui) { std::make_unique<::settings::FontHandler>(profile())); } +int AccessibilitySection::GetSectionNameMessageId() const { + return IDS_SETTINGS_ACCESSIBILITY; +} + +mojom::Section AccessibilitySection::GetSection() const { + return mojom::Section::kAccessibility; +} + +mojom::SearchResultIcon AccessibilitySection::GetSectionIcon() const { + return mojom::SearchResultIcon::kA11y; +} + +std::string AccessibilitySection::GetSectionPath() const { + return mojom::kAccessibilitySectionPath; +} + +void AccessibilitySection::RegisterHierarchy( + HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kA11yQuickSettings); + + // Manage accessibility. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES, + mojom::Subpage::kManageAccessibility, mojom::SearchResultIcon::kA11y, + mojom::SearchResultDefaultRank::kMedium, + mojom::kManageAccessibilitySubpagePath); + static constexpr mojom::Setting kManageAccessibilitySettings[] = { + mojom::Setting::kChromeVox, + mojom::Setting::kSelectToSpeak, + mojom::Setting::kHighContrastMode, + mojom::Setting::kFullscreenMagnifier, + mojom::Setting::kDockedMagnifier, + mojom::Setting::kStickyKeys, + mojom::Setting::kOnScreenKeyboard, + mojom::Setting::kDictation, + mojom::Setting::kSpeakToType, + mojom::Setting::kEnableSwitchAccess, + mojom::Setting::kHighlightTextCaret, + mojom::Setting::kAutoClickWhenCursorStops, + mojom::Setting::kLargeCursor, + mojom::Setting::kHighlightCursorWhileMoving, + mojom::Setting::kTabletNavigationButtons, + mojom::Setting::kMonoAudio, + mojom::Setting::kStartupSound, + mojom::Setting::kGetImageDescriptionsFromGoogle, + mojom::Setting::kLiveCaptions, + mojom::Setting::kEnableCursorColor, + }; + RegisterNestedSettingBulk(mojom::Subpage::kManageAccessibility, + kManageAccessibilitySettings, generator); + + // Text-to-Speech. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_MANAGE_TTS_SETTINGS, mojom::Subpage::kTextToSpeech, + mojom::SearchResultIcon::kA11y, mojom::SearchResultDefaultRank::kMedium, + mojom::kTextToSpeechSubpagePath); + static constexpr mojom::Setting kTextToSpeechSettings[] = { + mojom::Setting::kTextToSpeechRate, mojom::Setting::kTextToSpeechPitch, + mojom::Setting::kTextToSpeechVolume, mojom::Setting::kTextToSpeechVoice, + mojom::Setting::kTextToSpeechEngines, + }; + RegisterNestedSettingBulk(mojom::Subpage::kTextToSpeech, + kTextToSpeechSettings, generator); + + // Switch access. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_MANAGE_SWITCH_ACCESS_SETTINGS, + mojom::Subpage::kSwitchAccessOptions, + mojom::SearchResultIcon::kA11y, + mojom::SearchResultDefaultRank::kMedium, + mojom::kSwitchAccessOptionsSubpagePath); + static constexpr mojom::Setting kSwitchAccessSettings[] = { + mojom::Setting::kSwitchActionAssignment, + mojom::Setting::kSwitchActionAutoScan, + mojom::Setting::kSwitchActionAutoScanKeyboard, + }; + RegisterNestedSettingBulk(mojom::Subpage::kSwitchAccessOptions, + kSwitchAccessSettings, generator); + + // Captions. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_CAPTIONS, mojom::Subpage::kCaptions, + mojom::SearchResultIcon::kA11y, mojom::SearchResultDefaultRank::kMedium, + mojom::kCaptionsSubpagePath); +} + void AccessibilitySection::UpdateSearchTags() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (accessibility_state_utils::IsScreenReaderEnabled() && AreExperimentalA11yLabelsAllowed()) { - registry()->AddSearchTags(GetA11yLabelsSearchConcepts()); + updater.AddSearchTags(GetA11yLabelsSearchConcepts()); } else { - registry()->RemoveSearchTags(GetA11yLabelsSearchConcepts()); + updater.RemoveSearchTags(GetA11yLabelsSearchConcepts()); } - registry()->RemoveSearchTags(GetA11ySwitchAccessSearchConcepts()); - registry()->RemoveSearchTags(GetA11ySwitchAccessOnSearchConcepts()); - registry()->RemoveSearchTags(GetA11ySwitchAccessKeyboardSearchConcepts()); + updater.RemoveSearchTags(GetA11ySwitchAccessSearchConcepts()); + updater.RemoveSearchTags(GetA11ySwitchAccessOnSearchConcepts()); + updater.RemoveSearchTags(GetA11ySwitchAccessKeyboardSearchConcepts()); + + if (AreLiveCaptionsAllowed()) { + updater.AddSearchTags(GetA11yLiveCaptionSearchConcepts()); + } else { + updater.RemoveSearchTags(GetA11yLiveCaptionSearchConcepts()); + } + + if (IsCursorColorAllowed()) { + updater.AddSearchTags(GetA11yCursorColorSearchConcepts()); + } else { + updater.RemoveSearchTags(GetA11yCursorColorSearchConcepts()); + } if (!IsSwitchAccessAllowed()) return; - registry()->AddSearchTags(GetA11ySwitchAccessSearchConcepts()); + updater.AddSearchTags(GetA11ySwitchAccessSearchConcepts()); if (!pref_service_->GetBoolean( ash::prefs::kAccessibilitySwitchAccessEnabled)) { return; } - registry()->AddSearchTags(GetA11ySwitchAccessOnSearchConcepts()); + updater.AddSearchTags(GetA11ySwitchAccessOnSearchConcepts()); if (pref_service_->GetBoolean( ash::prefs::kAccessibilitySwitchAccessAutoScanEnabled)) { - registry()->AddSearchTags(GetA11ySwitchAccessKeyboardSearchConcepts()); + updater.AddSearchTags(GetA11ySwitchAccessKeyboardSearchConcepts()); } } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.h index 546454007b1..77f82db40d3 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_section.h @@ -31,6 +31,11 @@ class AccessibilitySection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; void UpdateSearchTags(); 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 0d6b946d6c3..69266feb260 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 @@ -17,10 +17,10 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/webui/chromeos/account_manager_welcome_dialog.h" -#include "chrome/browser/ui/webui/chromeos/account_migration_welcome_dialog.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_dialog.h" +#include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_dialog.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" -#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h" +#include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" #include "chrome/grit/generated_resources.h" #include "chromeos/components/account_manager/account_manager_factory.h" #include "components/signin/public/identity_manager/consent_level.h" @@ -343,8 +343,8 @@ base::ListValue AccountManagerUIHandler::GetSecondaryGaiaAccounts( void AccountManagerUIHandler::HandleAddAccount(const base::ListValue* args) { AllowJavascript(); - InlineLoginHandlerDialogChromeOS::Show( - InlineLoginHandlerDialogChromeOS::Source::kSettingsAddAccountButton); + InlineLoginDialogChromeOS::Show( + InlineLoginDialogChromeOS::Source::kSettingsAddAccountButton); } void AccountManagerUIHandler::HandleReauthenticateAccount( @@ -354,9 +354,9 @@ void AccountManagerUIHandler::HandleReauthenticateAccount( CHECK(!args->GetList().empty()); const std::string& account_email = args->GetList()[0].GetString(); - InlineLoginHandlerDialogChromeOS::Show( + InlineLoginDialogChromeOS::Show( account_email, - InlineLoginHandlerDialogChromeOS::Source::kSettingsReauthAccountButton); + InlineLoginDialogChromeOS::Source::kSettingsReauthAccountButton); } void AccountManagerUIHandler::HandleMigrateAccount( 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 276327a54c8..fd4f14a6d09 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 @@ -4,13 +4,34 @@ #include "chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h" +#include "ash/public/cpp/ambient/ambient_backend_controller.h" +#include "ash/public/cpp/ambient/common/ambient_settings.h" #include "base/bind.h" +#include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/values.h" namespace chromeos { namespace settings { +namespace { + +// Width and height of the preview image for personal album. +constexpr int kBannerWidth = 512; +constexpr int kBannderHeight = 512; + +ash::AmbientModeTopicSource ExtractTopicSource(const base::ListValue* args) { + CHECK_EQ(args->GetSize(), 1U); + ash::AmbientModeTopicSource topic_source = + static_cast<ash::AmbientModeTopicSource>(args->GetList()[0].GetInt()); + // Check the |topic_source| has valid value. + CHECK_GE(topic_source, ash::AmbientModeTopicSource::kMinValue); + CHECK_LE(topic_source, ash::AmbientModeTopicSource::kMaxValue); + return topic_source; +} + +} // namespace + AmbientModeHandler::AmbientModeHandler() = default; AmbientModeHandler::~AmbientModeHandler() = default; @@ -22,36 +43,94 @@ void AmbientModeHandler::RegisterMessages() { base::Unretained(this))); web_ui()->RegisterMessageCallback( - "onTopicSourceSelectedChanged", - base::BindRepeating(&AmbientModeHandler::HandleTopicSourceSelectedChanged, + "setSelectedTopicSource", + base::BindRepeating(&AmbientModeHandler::HandleSetSelectedTopicSource, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "requestPhotosContainers", + base::BindRepeating(&AmbientModeHandler::RequestPhotosContainers, base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "setSelectedPhotosContainers", + base::BindRepeating( + &AmbientModeHandler::HandleSetSelectedPhotosContainers, + base::Unretained(this))); } void AmbientModeHandler::OnJavascriptAllowed() { - if (topic_source_.has_value()) - SendTopicSource(); + GetSettings(); + + // Prefetch albums. + FetchPersonalAlbums(); +} + +void AmbientModeHandler::OnJavascriptDisallowed() { + weak_factory_.InvalidateWeakPtrs(); } void AmbientModeHandler::HandleInitialized(const base::ListValue* args) { CHECK(args); CHECK(args->empty()); + init_from_ambient_mode_page_ = true; AllowJavascript(); - GetSettings(); } -void AmbientModeHandler::HandleTopicSourceSelectedChanged( +void AmbientModeHandler::RequestPhotosContainers(const base::ListValue* args) { + // TODO(b/159747583): Handle deep linking to ambientMode/photos page. + // For now it will not load the page contents if visited directly. + if (!init_from_ambient_mode_page_) + return; + + ash::AmbientModeTopicSource topic_source = ExtractTopicSource(args); + DCHECK_EQ(topic_source, settings_->topic_source); + + if (topic_source == ash::AmbientModeTopicSource::kGooglePhotos) { + FetchPersonalAlbums(); + } + SendPhotosContainers(); +} + +void AmbientModeHandler::HandleSetSelectedTopicSource( const base::ListValue* args) { - CHECK_EQ(args->GetSize(), 1U); - int topic_source; - CHECK(base::StringToInt(args->GetList()[0].GetString(), &topic_source)); - // Check the |topic_source| has valid value. - CHECK_GE(topic_source, - static_cast<int>(ash::AmbientModeTopicSource::kMinValue)); - CHECK_LE(topic_source, - static_cast<int>(ash::AmbientModeTopicSource::kMaxValue)); + ash::AmbientModeTopicSource topic_source = ExtractTopicSource(args); + settings_->topic_source = topic_source; + UpdateSettings(); +} - UpdateSettings(static_cast<ash::AmbientModeTopicSource>(topic_source)); +void AmbientModeHandler::HandleSetSelectedPhotosContainers( + const base::ListValue* args) { + switch (settings_->topic_source) { + case ash::AmbientModeTopicSource::kGooglePhotos: + // For Google Photos, we will populate the |selected_album_ids| with IDs + // of selected albums. + settings_->selected_album_ids.clear(); + for (const auto& value : args->GetList()) { + std::string name = value.GetString(); + auto it = std::find_if( + personal_albums_.albums.begin(), personal_albums_.albums.end(), + [name](const auto& album) { return album.album_name == name; }); + CHECK(it != personal_albums_.albums.end()); + settings_->selected_album_ids.emplace_back(it->album_id); + } + break; + case ash::AmbientModeTopicSource::kArtGallery: + // For Art gallery, we set the corresponding setting to be enabled or not + // based on the selections. + for (auto& art_setting : settings_->art_settings) { + std::string title = art_setting.title; + auto it = std::find_if( + args->GetList().begin(), args->GetList().end(), + [title](const auto& value) { return value.GetString() == title; }); + const bool checked = it != args->GetList().end(); + art_setting.enabled = checked; + } + break; + } + + UpdateSettings(); } void AmbientModeHandler::GetSettings() { @@ -60,37 +139,63 @@ void AmbientModeHandler::GetSettings() { } void AmbientModeHandler::OnGetSettings( - base::Optional<ash::AmbientModeTopicSource> topic_source) { - if (!topic_source.has_value()) { + const base::Optional<ash::AmbientSettings>& settings) { + if (!settings) { // TODO(b/152921891): Retry a small fixed number of times, then only retry // when user confirms in the error message dialog. return; } - topic_source_ = topic_source; - if (!IsJavascriptAllowed()) - return; - + settings_ = settings; SendTopicSource(); } void AmbientModeHandler::SendTopicSource() { + DCHECK(settings_); FireWebUIListener("topic-source-changed", - base::Value( + base::Value(static_cast<int>(settings_->topic_source))); +} - static_cast<int>(topic_source_.value()))); +void AmbientModeHandler::SendPhotosContainers() { + DCHECK(settings_); + + base::Value dictionary(base::Value::Type::DICTIONARY); + base::Value containers(base::Value::Type::LIST); + switch (settings_->topic_source) { + case ash::AmbientModeTopicSource::kGooglePhotos: + for (const auto& album : personal_albums_.albums) { + base::Value value(base::Value::Type::DICTIONARY); + value.SetKey("title", base::Value(album.album_name)); + value.SetKey("checked", + base::Value(base::Contains(settings_->selected_album_ids, + album.album_id))); + containers.Append(std::move(value)); + } + break; + case ash::AmbientModeTopicSource::kArtGallery: + for (const auto& setting : settings_->art_settings) { + base::Value value(base::Value::Type::DICTIONARY); + value.SetKey("title", base::Value(setting.title)); + value.SetKey("checked", base::Value(setting.enabled)); + containers.Append(std::move(value)); + } + break; + } + + dictionary.SetKey("topicSource", + base::Value(static_cast<int>(settings_->topic_source))); + dictionary.SetKey("topicContainers", std::move(containers)); + FireWebUIListener("photos-containers-changed", std::move(dictionary)); } -void AmbientModeHandler::UpdateSettings( - ash::AmbientModeTopicSource topic_source) { +void AmbientModeHandler::UpdateSettings() { + DCHECK(settings_); ash::AmbientBackendController::Get()->UpdateSettings( - topic_source, base::BindOnce(&AmbientModeHandler::OnUpdateSettings, - weak_factory_.GetWeakPtr(), topic_source)); + *settings_, base::BindOnce(&AmbientModeHandler::OnUpdateSettings, + weak_factory_.GetWeakPtr())); } -void AmbientModeHandler::OnUpdateSettings( - ash::AmbientModeTopicSource topic_source, - bool success) { +void AmbientModeHandler::OnUpdateSettings(bool success) { if (success) return; @@ -98,5 +203,31 @@ void AmbientModeHandler::OnUpdateSettings( // when user confirms in the error message dialog. } +void AmbientModeHandler::FetchPersonalAlbums() { + // TODO: Add a helper function to get all the albums. + ash::AmbientBackendController::Get()->FetchPersonalAlbums( + kBannerWidth, kBannderHeight, /*num_albums=*/100, /*resume_token=*/"", + base::BindOnce(&AmbientModeHandler::OnPersonalAlbumsFetched, + weak_factory_.GetWeakPtr())); +} + +void AmbientModeHandler::OnPersonalAlbumsFetched( + ash::PersonalAlbums personal_albums) { + personal_albums_ = std::move(personal_albums); + + // If the |topic_source| is not |kGooglePhotos|, no need to refresh the + // photos subpage. + // |settings_| could be null because we call GetSettings() and + // FetchPersonalAlbums() in OnJavascriptAllowed(). |settings_| is populated by + // OnGetSettings(), which could be called later. The purpose to call + // FetchPersonalAlbums() is to prefetch albums, which takes several seconds, + // This improves the experience when we click into the ambientMode/photos page + // to show the albums list faster. + if (settings_ && + settings_->topic_source == ash::AmbientModeTopicSource::kGooglePhotos) { + SendPhotosContainers(); + } +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h index 8e26f721b60..ac0c6441433 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/ambient_mode_handler.h @@ -12,6 +12,10 @@ #include "base/optional.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +namespace ash { +struct AmbientSettings; +} // namespace ash + namespace base { class ListValue; } // namespace base @@ -31,34 +35,52 @@ class AmbientModeHandler : public ::settings::SettingsPageUIHandler { // settings::SettingsPageUIHandler: void RegisterMessages() override; void OnJavascriptAllowed() override; - void OnJavascriptDisallowed() override {} + void OnJavascriptDisallowed() override; private: // WebUI call to signal js side is ready. void HandleInitialized(const base::ListValue* args); + // WebUI call to request photos containers, e.g. personal albums or art + // categories. + void RequestPhotosContainers(const base::ListValue* args); + // WebUI call to sync topic source with server. - void HandleTopicSourceSelectedChanged(const base::ListValue* args); + void HandleSetSelectedTopicSource(const base::ListValue* args); + + // WebUI call to sync photos containers with server. + void HandleSetSelectedPhotosContainers(const base::ListValue* args); // Retrieve the initial settings from server. void GetSettings(); // Called when the initial settings is retrieved. - void OnGetSettings(base::Optional<ash::AmbientModeTopicSource> topic_source); + void OnGetSettings(const base::Optional<ash::AmbientSettings>& settings); // Send the "topic-source-changed" WebUIListener event when the initial // settings is retrieved. void SendTopicSource(); - // Update the selected topic source to server. - void UpdateSettings(ash::AmbientModeTopicSource topic_source); + // Send the "photos-containers-changed" WebUIListener event when the personal + // albums are retrieved. + void SendPhotosContainers(); + + // Update the local |settings_| to server. + void UpdateSettings(); // Called when the settings is updated. - // |topic_source| is the value to retry if the update was failed. - void OnUpdateSettings(ash::AmbientModeTopicSource topic_source, bool success); + void OnUpdateSettings(bool success); + + void FetchPersonalAlbums(); + + void OnPersonalAlbumsFetched(ash::PersonalAlbums personal_albums); + + // Whether the Javascript is inited from the ambientMode page. + bool init_from_ambient_mode_page_ = false; + + base::Optional<ash::AmbientSettings> settings_; - // The topic source, i.e. from which category the photos will be displayed. - base::Optional<ash::AmbientModeTopicSource> topic_source_; + ash::PersonalAlbums personal_albums_; base::WeakPtrFactory<AmbientModeHandler> weak_factory_{this}; }; 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 7ae2a6a8724..6d8ebbc5421 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.cc @@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/apps_section.h" +#include "base/feature_list.h" #include "base/no_destructor.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h" @@ -17,6 +18,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/os_settings_resources.h" +#include "chromeos/constants/chromeos_features.h" #include "components/arc/arc_prefs.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_ui_data_source.h" @@ -39,7 +41,7 @@ const std::vector<SearchConcept>& GetAppsSearchConcepts() { {IDS_OS_SETTINGS_TAG_APPS_MANAGEMENT, mojom::kAppManagementSubpagePath, mojom::SearchResultIcon::kAppsGrid, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kAppManagement}, {IDS_OS_SETTINGS_TAG_APPS_MANAGEMENT_ALT1, SearchConcept::kAltTagEnd}}, @@ -143,7 +145,8 @@ AppsSection::AppsSection(Profile* profile, : OsSettingsSection(profile, search_tag_registry), pref_service_(pref_service), arc_app_list_prefs_(arc_app_list_prefs) { - registry()->AddSearchTags(GetAppsSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetAppsSearchConcepts()); if (arc::IsArcAllowedForProfile(profile)) { pref_change_registrar_.Init(pref_service_); @@ -179,17 +182,11 @@ void AppsSection::AddLoadTimeData(content::WebUIDataSource* html_source) { "app-management/types.mojom-lite.js", IDR_OS_SETTINGS_APP_MANAGEMENT_TYPES_MOJO_LITE_JS); html_source->AddResourcePath( - "app-management/bitmap.mojom-lite.js", - IDR_OS_SETTINGS_APP_MANAGEMENT_BITMAP_MOJO_LITE_JS); - html_source->AddResourcePath( "app-management/file_path.mojom-lite.js", IDR_OS_SETTINGS_APP_MANAGEMENT_FILE_PATH_MOJO_LITE_JS); html_source->AddResourcePath( "app-management/image.mojom-lite.js", IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_MOJO_LITE_JS); - html_source->AddResourcePath( - "app-management/image_info.mojom-lite.js", - IDR_OS_SETTINGS_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS); // We have 2 variants of Android apps settings. Default case, when the Play // Store app exists we show expandable section that allows as to @@ -220,6 +217,57 @@ void AppsSection::AddHandlers(content::WebUI* web_ui) { } } +int AppsSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_APPS_TITLE; +} + +mojom::Section AppsSection::GetSection() const { + return mojom::Section::kApps; +} + +mojom::SearchResultIcon AppsSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kAppsGrid; +} + +std::string AppsSection::GetSectionPath() const { + return mojom::kAppsSectionPath; +} + +void AppsSection::RegisterHierarchy(HierarchyGenerator* generator) const { + // Manage apps. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_APPS_LINK_TEXT, + mojom::Subpage::kAppManagement, + mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, + mojom::kAppManagementSubpagePath); + // 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( + IDS_SETTINGS_APP_DETAILS_TITLE, mojom::Subpage::kAppDetails, + mojom::Subpage::kAppManagement, mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, mojom::kAppDetailsSubpagePath); + generator->RegisterNestedSubpage(IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS, + mojom::Subpage::kPluginVmSharedPaths, + mojom::Subpage::kAppManagement, + mojom::SearchResultIcon::kAppsGrid, + mojom::SearchResultDefaultRank::kMedium, + mojom::kPluginVmSharedPathsSubpagePath); + + // Google Play Store. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_ANDROID_APPS_LABEL, + mojom::Subpage::kGooglePlayStore, + mojom::SearchResultIcon::kGooglePlay, + mojom::SearchResultDefaultRank::kMedium, + mojom::kGooglePlayStoreSubpagePath); + static constexpr mojom::Setting kGooglePlayStoreSettings[] = { + mojom::Setting::kManageAndroidPreferences, + mojom::Setting::kRemovePlayStore, + mojom::Setting::kTurnOnPlayStore, + }; + RegisterNestedSettingBulk(mojom::Subpage::kGooglePlayStore, + kGooglePlayStoreSettings, generator); +} + void AppsSection::OnAppRegistered(const std::string& app_id, const ArcAppListPrefs::AppInfo& app_info) { UpdateAndroidSearchTags(); @@ -264,34 +312,52 @@ void AppsSection::AddPluginVmLoadTimeData( IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_INSTRUCTIONS_REMOVE}, {"pluginVmSharedPathsRemoveSharing", IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_REMOVE_SHARING}, + {"pluginVmSharedPathsListEmptyMessage", + IDS_SETTINGS_APPS_PLUGIN_VM_SHARED_PATHS_LIST_EMPTY_MESSAGE}, + {"pluginVmPermissionDialogCameraLabel", + IDS_SETTINGS_APPS_PLUGIN_VM_PERMISSION_DIALOG_CAMERA_LABEL}, + {"pluginVmPermissionDialogMicrophoneLabel", + IDS_SETTINGS_APPS_PLUGIN_VM_PERMISSION_DIALOG_MICROPHONE_LABEL}, + {"pluginVmPermissionDialogRelaunchButton", + IDS_SETTINGS_APPS_PLUGIN_VM_PERMISSION_DIALOG_RELAUNCH_BUTTON}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); html_source->AddBoolean("showPluginVm", ShowPluginVm(profile(), *pref_service_)); + html_source->AddBoolean( + "showPluginVmCameraPermissions", + base::FeatureList::IsEnabled( + chromeos::features::kPluginVmShowCameraPermissions)); + html_source->AddBoolean( + "showPluginVmMicrophonePermissions", + base::FeatureList::IsEnabled( + chromeos::features::kPluginVmShowMicrophonePermissions)); } void AppsSection::UpdateAndroidSearchTags() { - registry()->RemoveSearchTags(GetAndroidNoPlayStoreSearchConcepts()); - registry()->RemoveSearchTags(GetAndroidPlayStoreDisabledSearchConcepts()); - registry()->RemoveSearchTags(GetAndroidPlayStoreSearchConcepts()); - registry()->RemoveSearchTags(GetAndroidSettingsSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + updater.RemoveSearchTags(GetAndroidNoPlayStoreSearchConcepts()); + updater.RemoveSearchTags(GetAndroidPlayStoreDisabledSearchConcepts()); + updater.RemoveSearchTags(GetAndroidPlayStoreSearchConcepts()); + updater.RemoveSearchTags(GetAndroidSettingsSearchConcepts()); if (!arc::IsPlayStoreAvailable()) { - registry()->AddSearchTags(GetAndroidNoPlayStoreSearchConcepts()); + updater.AddSearchTags(GetAndroidNoPlayStoreSearchConcepts()); return; } if (!arc::IsArcPlayStoreEnabledForProfile(profile())) { - registry()->AddSearchTags(GetAndroidPlayStoreDisabledSearchConcepts()); + updater.AddSearchTags(GetAndroidPlayStoreDisabledSearchConcepts()); return; } - registry()->AddSearchTags(GetAndroidPlayStoreSearchConcepts()); + updater.AddSearchTags(GetAndroidPlayStoreSearchConcepts()); if (arc_app_list_prefs_ && arc_app_list_prefs_->IsRegistered(arc::kSettingsAppId)) { - registry()->AddSearchTags(GetAndroidSettingsSearchConcepts()); + updater.AddSearchTags(GetAndroidSettingsSearchConcepts()); } } 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 ba926ba1652..d5217f6c693 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/apps_section.h @@ -33,6 +33,11 @@ class AppsSection : public OsSettingsSection, public ArcAppListPrefs::Observer { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // ArcAppListPrefs::Observer: void OnAppRegistered(const std::string& app_id, 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 9b6fad55c74..2de04401ca6 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc @@ -17,6 +17,8 @@ #include "chrome/grit/generated_resources.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/strings/grit/bluetooth_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -28,37 +30,12 @@ namespace { const std::vector<SearchConcept>& GetBluetoothSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_BLUETOOTH_PAIR, - mojom::kBluetoothDevicesSubpagePath, - mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kBluetoothPairDevice}}, - {IDS_OS_SETTINGS_TAG_BLUETOOTH_CONNECT, - mojom::kBluetoothDevicesSubpagePath, - mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kBluetoothConnectToDevice}}, {IDS_OS_SETTINGS_TAG_BLUETOOTH, mojom::kBluetoothDevicesSubpagePath, mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kBluetoothDevices}}, - {IDS_OS_SETTINGS_TAG_BLUETOOTH_DISCONNECT, - mojom::kBluetoothDevicesSubpagePath, - mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kBluetoothDisconnectFromDevice}}, - {IDS_OS_SETTINGS_TAG_BLUETOOTH_UNPAIR, - mojom::kBluetoothDevicesSubpagePath, - mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kBluetoothUnpairDevice}, - {IDS_OS_SETTINGS_TAG_BLUETOOTH_UNPAIR_ALT1, SearchConcept::kAltTagEnd}}, }); return *tags; } @@ -68,7 +45,7 @@ const std::vector<SearchConcept>& GetBluetoothOnSearchConcepts() { {IDS_OS_SETTINGS_TAG_BLUETOOTH_TURN_OFF, mojom::kBluetoothDevicesSubpagePath, mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kBluetoothOnOff}, {IDS_OS_SETTINGS_TAG_BLUETOOTH_TURN_OFF_ALT1, @@ -82,7 +59,7 @@ const std::vector<SearchConcept>& GetBluetoothOffSearchConcepts() { {IDS_OS_SETTINGS_TAG_BLUETOOTH_TURN_ON, mojom::kBluetoothDevicesSubpagePath, mojom::SearchResultIcon::kBluetooth, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kBluetoothOnOff}, {IDS_OS_SETTINGS_TAG_BLUETOOTH_TURN_ON_ALT1, SearchConcept::kAltTagEnd}}, @@ -90,6 +67,55 @@ const std::vector<SearchConcept>& GetBluetoothOffSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetBluetoothConnectableSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_BLUETOOTH_CONNECT, + mojom::kBluetoothDevicesSubpagePath, + mojom::SearchResultIcon::kBluetooth, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kBluetoothConnectToDevice}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetBluetoothConnectedSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_BLUETOOTH_DISCONNECT, + mojom::kBluetoothDevicesSubpagePath, + mojom::SearchResultIcon::kBluetooth, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kBluetoothDisconnectFromDevice}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetBluetoothPairableSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_BLUETOOTH_PAIR, + mojom::kBluetoothDevicesSubpagePath, + mojom::SearchResultIcon::kBluetooth, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kBluetoothPairDevice}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetBluetoothPairedSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_BLUETOOTH_UNPAIR, + mojom::kBluetoothDevicesSubpagePath, + mojom::SearchResultIcon::kBluetooth, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kBluetoothUnpairDevice}, + {IDS_OS_SETTINGS_TAG_BLUETOOTH_UNPAIR_ALT1, SearchConcept::kAltTagEnd}}, + }); + return *tags; +} + } // namespace BluetoothSection::BluetoothSection(Profile* profile, @@ -165,6 +191,40 @@ void BluetoothSection::AddLoadTimeData(content::WebUIDataSource* html_source) { chromeos::bluetooth_dialog::AddLocalizedStrings(html_source); } +int BluetoothSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_BLUETOOTH; +} + +mojom::Section BluetoothSection::GetSection() const { + return mojom::Section::kBluetooth; +} + +mojom::SearchResultIcon BluetoothSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kBluetooth; +} + +std::string BluetoothSection::GetSectionPath() const { + return mojom::kBluetoothSectionPath; +} + +void BluetoothSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSubpage(IDS_SETTINGS_BLUETOOTH, + mojom::Subpage::kBluetoothDevices, + 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); + generator->RegisterTopLevelAltSetting(mojom::Setting::kBluetoothOnOff); +} + void BluetoothSection::AdapterPresentChanged(device::BluetoothAdapter* adapter, bool present) { UpdateSearchTags(); @@ -175,6 +235,21 @@ void BluetoothSection::AdapterPoweredChanged(device::BluetoothAdapter* adapter, UpdateSearchTags(); } +void BluetoothSection::DeviceAdded(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) { + UpdateSearchTags(); +} + +void BluetoothSection::DeviceChanged(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) { + UpdateSearchTags(); +} + +void BluetoothSection::DeviceRemoved(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) { + UpdateSearchTags(); +} + void BluetoothSection::OnFetchBluetoothAdapter( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter) { bluetooth_adapter_ = bluetooth_adapter; @@ -183,20 +258,60 @@ void BluetoothSection::OnFetchBluetoothAdapter( } void BluetoothSection::UpdateSearchTags() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + // Start with no search tags, then add them below if appropriate. - registry()->RemoveSearchTags(GetBluetoothSearchConcepts()); - registry()->RemoveSearchTags(GetBluetoothOnSearchConcepts()); - registry()->RemoveSearchTags(GetBluetoothOffSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothOnSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothOffSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothConnectableSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothConnectedSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothPairableSearchConcepts()); + updater.RemoveSearchTags(GetBluetoothPairedSearchConcepts()); if (!bluetooth_adapter_->IsPresent()) return; - registry()->AddSearchTags(GetBluetoothSearchConcepts()); + updater.AddSearchTags(GetBluetoothSearchConcepts()); + + if (!bluetooth_adapter_->IsPowered()) { + updater.AddSearchTags(GetBluetoothOffSearchConcepts()); + return; + } + + updater.AddSearchTags(GetBluetoothOnSearchConcepts()); + + // Filter devices so that only those shown in the UI are returned. Note that + // passing |max_devices| of 0 indicates that there is no maximum. + device::BluetoothAdapter::DeviceList devices = + device::FilterBluetoothDeviceList(bluetooth_adapter_->GetDevices(), + device::BluetoothFilterType::KNOWN, + /*max_devices=*/0); + + bool connectable_device_exists = false; + bool connected_device_exists = false; + bool pairable_device_exists = false; + bool paired_device_exists = false; + for (const device::BluetoothDevice* device : devices) { + // Note: Device must be paired to be connectable. + if (device->IsPaired() && device->IsConnectable() && !device->IsConnected()) + connectable_device_exists = true; + if (device->IsConnected()) + connected_device_exists = true; + if (device->IsPairable() && !device->IsPaired()) + pairable_device_exists = true; + if (device->IsPaired()) + paired_device_exists = true; + } - if (bluetooth_adapter_->IsPowered()) - registry()->AddSearchTags(GetBluetoothOnSearchConcepts()); - else - registry()->AddSearchTags(GetBluetoothOffSearchConcepts()); + if (connectable_device_exists) + updater.AddSearchTags(GetBluetoothConnectableSearchConcepts()); + if (connected_device_exists) + updater.AddSearchTags(GetBluetoothConnectedSearchConcepts()); + if (pairable_device_exists) + updater.AddSearchTags(GetBluetoothPairableSearchConcepts()); + if (paired_device_exists) + updater.AddSearchTags(GetBluetoothPairedSearchConcepts()); } } // namespace settings 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 0586828bb1f..e187a244e2b 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.h @@ -31,12 +31,23 @@ class BluetoothSection : public OsSettingsSection, private: // OsSettingsSection: void AddLoadTimeData(content::WebUIDataSource* html_source) override; + int GetSectionNameMessageId() const override; + mojom::Section GetSection() const override; + mojom::SearchResultIcon GetSectionIcon() const override; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // device::BluetoothAdapter::Observer: void AdapterPresentChanged(device::BluetoothAdapter* adapter, bool present) override; void AdapterPoweredChanged(device::BluetoothAdapter* adapter, bool powered) override; + void DeviceAdded(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override; + void DeviceChanged(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override; + void DeviceRemoved(device::BluetoothAdapter* adapter, + device::BluetoothDevice* device) override; void OnFetchBluetoothAdapter( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter); 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 7c8d870bb91..5fd2a36e803 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 @@ -17,6 +17,7 @@ #include "chrome/browser/profiles/profile.h" #include "chromeos/cryptohome/cryptohome_util.h" #include "chromeos/dbus/cryptohome/cryptohome_client.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" #include "components/arc/arc_service_manager.h" #include "components/arc/session/arc_bridge_service.h" #include "components/arc/storage_manager/arc_storage_manager.h" @@ -392,6 +393,32 @@ void OtherUsersSizeCalculator::OnGetOtherUserSize( NotifySizeCalculated(other_users_total_bytes); } +DlcsSizeCalculator::DlcsSizeCalculator() + : SizeCalculator(CalculationType::kDlcs) {} + +DlcsSizeCalculator::~DlcsSizeCalculator() = default; + +void DlcsSizeCalculator::PerformCalculation() { + DlcserviceClient::Get()->GetExistingDlcs(base::BindOnce( + &DlcsSizeCalculator::OnGetExistingDlcs, weak_ptr_factory_.GetWeakPtr())); +} + +void DlcsSizeCalculator::OnGetExistingDlcs( + const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content) { + if (err != dlcservice::kErrorNone) { + NotifySizeCalculated(0); + return; + } + base::ListValue dlc_metadata_list; + int64_t dlc_total_size_in_bytes = 0; + for (int i = 0; i < dlcs_with_content.dlc_infos_size(); i++) { + const auto& dlc_info = dlcs_with_content.dlc_infos(i); + dlc_total_size_in_bytes += dlc_info.used_bytes_on_disk(); + } + NotifySizeCalculated(dlc_total_size_in_bytes); +} + } // namespace calculator } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h index 8f483f50b95..23fc718f6f6 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/calculator/size_calculator.h @@ -25,6 +25,10 @@ class Profile; +namespace dlcservice { +class DlcsWithContent; +} // namespace dlcservice + namespace chromeos { namespace settings { namespace calculator { @@ -42,7 +46,8 @@ class SizeCalculator { kAppsExtensions, kCrostini, kOtherUsers, - kLast = kOtherUsers, + kDlcs, + kLast = kDlcs, kSystem, }; @@ -289,6 +294,27 @@ class OtherUsersSizeCalculator : public SizeCalculator { base::WeakPtrFactory<OtherUsersSizeCalculator> weak_ptr_factory_{this}; }; +// Class handling the calculation of all DLC size. +class DlcsSizeCalculator : public SizeCalculator { + public: + DlcsSizeCalculator(); + ~DlcsSizeCalculator() override; + + DlcsSizeCalculator(const DlcsSizeCalculator&) = delete; + DlcsSizeCalculator& operator=(const DlcsSizeCalculator&) = delete; + + private: + friend class DlcsSizeTestAPI; + + void PerformCalculation() override; + + // Callback to update the total size of existing DLCs. + void OnGetExistingDlcs(const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content); + + base::WeakPtrFactory<DlcsSizeCalculator> weak_ptr_factory_{this}; +}; + } // namespace calculator } // namespace settings } // namespace chromeos 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 2e0850df244..4a15d946c26 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 @@ -149,6 +149,25 @@ class OtherUsersSizeTestAPI { OtherUsersSizeCalculator* other_users_size_calculator_; }; +class DlcsSizeTestAPI { + public: + explicit DlcsSizeTestAPI(StorageHandler* handler, + DlcsSizeCalculator* dlcs_size_calculator) { + dlcs_size_calculator_ = dlcs_size_calculator; + dlcs_size_calculator_->AddObserver(handler); + } + + void StartCalculation() { dlcs_size_calculator_->StartCalculation(); } + + void SimulateOnGetExistingDlcs( + const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content) { + dlcs_size_calculator_->OnGetExistingDlcs(err, dlcs_with_content); + } + + private: + DlcsSizeCalculator* dlcs_size_calculator_; +}; } // namespace calculator } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/constants_util.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/constants_util.cc index d5bdaf20d53..263d760b558 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/constants_util.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/constants_util.cc @@ -17,7 +17,7 @@ std::vector<T> All() { int32_t max_value = static_cast<int32_t>(T::kMaxValue); std::vector<T> all; - for (int32_t i = min_value; i < max_value; ++i) { + for (int32_t i = min_value; i <= max_value; ++i) { T current = static_cast<T>(i); // Not every value between the min and max values is valid: 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 b1837490f1c..ecb574c87e6 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom @@ -49,6 +49,7 @@ enum Subpage { // MultiDevice section. kMultiDeviceFeatures = 200, kSmartLock = 201, + kNearbyShare = 202, // People section. kMyAccounts = 300, @@ -61,19 +62,19 @@ enum Subpage { kKerberos = 307, // Device section. - kDevice = 400, - kPointers = 401, - kKeyboard = 402, - kStylus = 403, - kDisplay = 404, - kStorage = 405, - kExternalStorage = 406, - kDlc = 407, - kPower = 408, + kPointers = 400, + kKeyboard = 401, + kStylus = 402, + kDisplay = 403, + kStorage = 404, + kExternalStorage = 405, + kDlc = 406, + kPower = 407, // Personalization section. kChangePicture = 500, kAmbientMode = 501, + kAmbientModePhotos= 502, // Search and Assistant section. kAssistant = 600, @@ -91,7 +92,6 @@ enum Subpage { kCrostiniBackupAndRestore = 803, kCrostiniDevelopAndroidApps = 804, kCrostiniPortForwarding = 805, - kCrostiniDiskResize = 806, // Note: Deprecated Plugin VM section has no subpages. @@ -104,6 +104,7 @@ enum Subpage { kLanguagesAndInputDetails = 1200, kManageInputMethods = 1201, kSmartInputs = 1202, + kInputMethodOptions = 1203, // Files section. kNetworkFileShares = 1300, @@ -143,6 +144,7 @@ const string kBluetoothDevicesSubpagePath = "bluetoothDevices"; const string kMultiDeviceSectionPath = "multidevice"; const string kMultiDeviceFeaturesSubpagePath = "multidevice/features"; const string kSmartLockSubpagePath = "multidevice/features/smartLock"; +const string kNearbyShareSubpagePath = "multidevice/nearbyshare"; // People section. const string kPeopleSectionPath = "osPeople"; @@ -151,7 +153,7 @@ const string kSyncSubpagePath = "osSync"; const string kSyncDeprecatedSubpagePath = "syncSetup"; const string kSyncDeprecatedAdvancedSubpagePath = "syncSetup/advanced"; const string kSecurityAndSignInSubpagePath = "lockScreen"; -const string kFingerprintSubpathPath = "lockScreen/fingerprint"; +const string kFingerprintSubpagePath = "lockScreen/fingerprint"; const string kManageOtherPeopleSubpagePath = "accounts"; const string kKerberosSubpagePath = "kerberosAccounts"; @@ -170,6 +172,7 @@ const string kPowerSubpagePath = "power"; const string kPersonalizationSectionPath = "personalization"; const string kChangePictureSubpagePath = "changePicture"; const string kAmbientModeSubpagePath = "ambientMode"; +const string kAmbientModePhotosSubpagePath = "ambientMode/photos"; // Search and Assistant section. const string kSearchAndAssistantSectionPath = "osSearch"; @@ -191,7 +194,6 @@ const string kCrostiniUsbPreferencesSubpagePath = "crostini/sharedUsbDevices"; const string kCrostiniBackupAndRestoreSubpagePath = "crostini/exportImport"; const string kCrostiniDevelopAndroidAppsSubpagePath = "crostini/androidAdb"; const string kCrostiniPortForwardingSubpagePath = "crostini/portForwarding"; -const string kCrostiniDiskResizeSubpagePath = "crostini/diskResize"; // Date and Time section. const string kDateAndTimeSectionPath = "dateTime"; @@ -204,7 +206,8 @@ const string kPrivacyAndSecuritySectionPath = "osPrivacy"; const string kLanguagesAndInputSectionPath = "osLanguages"; const string kLanguagesAndInputDetailsSubpagePath = "osLanguages/details"; const string kManageInputMethodsSubpagePath = "osLanguages/inputMethods"; -const string kSmartInputsSubagePath = "osLanguages/smartInputs"; +const string kSmartInputsSubpagePath = "osLanguages/smartInputs"; +const string kInputMethodOptionsSubpagePath = "osLanguages/inputMethodOptions"; // Files section. const string kFilesSectionPath = "files"; 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 957b28fd7cc..d2fa7499076 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 @@ -37,13 +37,14 @@ bool IsOSSettingsSubPage(const std::string& sub_page) { chromeos::settings::mojom::kMultiDeviceSectionPath, chromeos::settings::mojom::kMultiDeviceFeaturesSubpagePath, chromeos::settings::mojom::kSmartLockSubpagePath, + chromeos::settings::mojom::kNearbyShareSubpagePath, // People section. chromeos::settings::mojom::kPeopleSectionPath, chromeos::settings::mojom::kMyAccountsSubpagePath, chromeos::settings::mojom::kSyncSubpagePath, chromeos::settings::mojom::kSecurityAndSignInSubpagePath, - chromeos::settings::mojom::kFingerprintSubpathPath, + chromeos::settings::mojom::kFingerprintSubpagePath, chromeos::settings::mojom::kManageOtherPeopleSubpagePath, chromeos::settings::mojom::kKerberosSubpagePath, @@ -82,7 +83,6 @@ bool IsOSSettingsSubPage(const std::string& sub_page) { chromeos::settings::mojom::kCrostiniBackupAndRestoreSubpagePath, chromeos::settings::mojom::kCrostiniDevelopAndroidAppsSubpagePath, chromeos::settings::mojom::kCrostiniPortForwardingSubpagePath, - chromeos::settings::mojom::kCrostiniDiskResizeSubpagePath, // Date and Time section. chromeos::settings::mojom::kDateAndTimeSectionPath, @@ -95,7 +95,8 @@ bool IsOSSettingsSubPage(const std::string& sub_page) { chromeos::settings::mojom::kLanguagesAndInputSectionPath, chromeos::settings::mojom::kLanguagesAndInputDetailsSubpagePath, chromeos::settings::mojom::kManageInputMethodsSubpagePath, - chromeos::settings::mojom::kSmartInputsSubagePath, + chromeos::settings::mojom::kSmartInputsSubpagePath, + chromeos::settings::mojom::kInputMethodOptionsSubpagePath, // Files section. chromeos::settings::mojom::kFilesSectionPath, 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 634b625b075..19339269f3b 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom @@ -16,7 +16,7 @@ enum Setting { kDisconnectWifiNetwork = 5, kPreferWifiNetwork = 6, kForgetWifiNetwork = 7, - kConfigureWifi = 8, + kWifiAddNetwork = 8, kWifiAutoConfigureIp = 9, kWifiDns = 10, kWifiProxy = 11, @@ -31,7 +31,9 @@ enum Setting { kCellularProxy = 20, kCellularAutoConnectToNetwork = 21, kInstantTetheringOnOff = 22, - kDisconnectTetherNetwork = 22, + kDisconnectTetherNetwork = 23, + kWifiMetered = 24, + kCellularMetered = 25, // Bluetooth section. kBluetoothOnOff = 100, @@ -49,11 +51,12 @@ enum Setting { kMessagesSetUp = 205, kMessagesOnOff = 206, kForgetPhone = 207, + kNearbyShareOnOff = 208, // People section. kAddAccount = 300, kRemoveAccount = 301, - kSyncOnOff = 302, + kSplitSyncOnOff = 302, kLockScreen = 303, kChangeAuthPin = 304, kGuestBrowsing = 305, @@ -67,6 +70,10 @@ enum Setting { kAddFingerprint = 313, kRemoveFingerprint = 314, kSetUpParentalControls = 315, + kNonSplitSyncEncryptionOptions = 316, + kAutocompleteSearchesAndUrls = 317, + kMakeSearchesAndBrowsingBetter = 318, + kGoogleDriveSearchSuggestions = 319, // Device section. kTouchpadTapToClick = 400, @@ -91,16 +98,26 @@ enum Setting { kStylusLatestNoteOnLockScreen = 419, kDisplayOrientation = 420, kDisplayArrangement = 421, - kPowerIdleBehavior = 422, + kPowerIdleBehaviorWhileCharging = 422, kPowerSource = 423, kSleepWhenLaptopLidClosed = 424, kDisplayResolution = 425, kDisplayRefreshRate = 426, + kRemoveDlc = 427, + kDisplayMirroring = 428, + kAllowWindowsToSpanDisplays = 429, + kAmbientColors = 430, + kTouchscreenCalibration = 431, + kNightLightColorTemperature = 432, + kPowerIdleBehaviorWhileOnBattery = 433, + kDisplayOverscan = 434, // Personalization section. kOpenWallpaper = 500, kAmbientModeOnOff = 501, kAmbientModeSource = 502, + kChangeDeviceAccountImage = 503, + kAmbientModeUpdatePhotosContainers = 504, // Search and Assistant section. kPreferredSearchEngine = 600, @@ -110,6 +127,7 @@ enum Setting { kAssistantOkGoogle = 604, kAssistantNotifications = 605, kAssistantVoiceInput = 606, + kTrainAssistantVoiceModel = 607, // Apps section. kManageAndroidPreferences = 700, @@ -141,6 +159,7 @@ enum Setting { kAddLanguage = 1200, kShowInputOptionsInShelf = 1201, kShowPersonalInformationSuggestions = 1202, + kShowEmojiSuggestions = 1203, // Files section. kGoogleDriveConnection = 1300, @@ -178,6 +197,8 @@ enum Setting { kSwitchActionAutoScan = 1524, kSwitchActionAutoScanKeyboard = 1525, kGetImageDescriptionsFromGoogle = 1526, + kLiveCaptions = 1527, + kEnableCursorColor = 1528, // Reset section. kPowerwash = 1600, @@ -185,4 +206,9 @@ enum Setting { // About Chrome OS section. kChangeChromeChannel = 1700, kCopyDetailedBuildInfo = 1701, + kCheckForOsUpdate = 1702, + kSeeWhatsNew = 1703, + kGetHelpWithChromeOs = 1704, + kReportAnIssue = 1705, + kTermsOfService = 1706, }; 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 bf1d6db4c78..5c934d15a17 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.cc @@ -104,6 +104,11 @@ void CrostiniHandler::RegisterMessages() { base::BindRepeating(&CrostiniHandler::HandleQueryArcAdbRequest, weak_ptr_factory_.GetWeakPtr())); web_ui()->RegisterMessageCallback( + "getCanChangeArcAdbSideloading", + base::BindRepeating( + &CrostiniHandler::HandleCanChangeArcAdbSideloadingRequest, + weak_ptr_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( "enableArcAdbSideload", base::BindRepeating(&CrostiniHandler::HandleEnableArcAdbRequest, weak_ptr_factory_.GetWeakPtr())); @@ -191,6 +196,20 @@ void CrostiniHandler::OnJavascriptAllowed() { } crostini::CrostiniExportImport::GetForProfile(profile_)->AddObserver(this); crostini::CrostiniPortForwarder::GetForProfile(profile_)->AddObserver(this); + + // Observe ADB sideloading device policy and react to its changes + adb_sideloading_device_policy_subscription_ = + chromeos::CrosSettings::Get()->AddSettingsObserver( + chromeos::kDeviceCrostiniArcAdbSideloadingAllowed, + base::BindRepeating(&CrostiniHandler::FetchCanChangeAdbSideloading, + weak_ptr_factory_.GetWeakPtr())); + + // Observe ADB sideloading user policy and react to its changes + pref_change_registrar_.Init(profile_->GetPrefs()); + pref_change_registrar_.Add( + crostini::prefs::kCrostiniArcAdbSideloadingUserPref, + base::BindRepeating(&CrostiniHandler::FetchCanChangeAdbSideloading, + weak_ptr_factory_.GetWeakPtr())); } void CrostiniHandler::OnJavascriptDisallowed() { @@ -206,6 +225,9 @@ void CrostiniHandler::OnJavascriptDisallowed() { crostini::CrostiniExportImport::GetForProfile(profile_)->RemoveObserver(this); crostini::CrostiniPortForwarder::GetForProfile(profile_)->RemoveObserver( this); + + adb_sideloading_device_policy_subscription_.reset(); + pref_change_registrar_.RemoveAll(); } void CrostiniHandler::HandleRequestCrostiniInstallerView( @@ -437,7 +459,15 @@ void CrostiniHandler::OnQueryAdbSideload( void CrostiniHandler::HandleEnableArcAdbRequest(const base::ListValue* args) { CHECK_EQ(0U, args->GetList().size()); - if (!CheckEligibilityToChangeArcAdbSideloading()) + + crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading( + profile_, base::BindOnce(&CrostiniHandler::OnCanEnableArcAdbSideloading, + weak_ptr_factory_.GetWeakPtr())); +} + +void CrostiniHandler::OnCanEnableArcAdbSideloading( + bool can_change_adb_sideloading) { + if (!can_change_adb_sideloading) return; LogEvent(CrostiniSettingsEvent::kEnableAdbSideloading); @@ -451,7 +481,15 @@ void CrostiniHandler::HandleEnableArcAdbRequest(const base::ListValue* args) { void CrostiniHandler::HandleDisableArcAdbRequest(const base::ListValue* args) { CHECK_EQ(0U, args->GetList().size()); - if (!CheckEligibilityToChangeArcAdbSideloading()) + + crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading( + profile_, base::BindOnce(&CrostiniHandler::OnCanDisableArcAdbSideloading, + weak_ptr_factory_.GetWeakPtr())); +} + +void CrostiniHandler::OnCanDisableArcAdbSideloading( + bool can_change_adb_sideloading) { + if (!can_change_adb_sideloading) return; LogEvent(CrostiniSettingsEvent::kDisableAdbSideloading); @@ -464,10 +502,6 @@ void CrostiniHandler::HandleDisableArcAdbRequest(const base::ListValue* args) { power_manager::REQUEST_RESTART_FOR_USER, "disable adb sideloading"); } -bool CrostiniHandler::CheckEligibilityToChangeArcAdbSideloading() const { - return crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading(profile_); -} - void CrostiniHandler::LaunchTerminal() { crostini::LaunchCrostiniApp( profile_, crostini::GetTerminalId(), @@ -502,6 +536,26 @@ void CrostiniHandler::HandleQueryArcAdbRequest(const base::ListValue* args) { weak_ptr_factory_.GetWeakPtr())); } +void CrostiniHandler::HandleCanChangeArcAdbSideloadingRequest( + const base::ListValue* args) { + AllowJavascript(); + CHECK_EQ(0U, args->GetList().size()); + + FetchCanChangeAdbSideloading(); +} + +void CrostiniHandler::FetchCanChangeAdbSideloading() { + crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading( + profile_, base::BindOnce(&CrostiniHandler::OnCanChangeArcAdbSideloading, + weak_ptr_factory_.GetWeakPtr())); +} + +void CrostiniHandler::OnCanChangeArcAdbSideloading( + bool can_change_arc_adb_sideloading) { + FireWebUIListener("crostini-can-change-arc-adb-sideload-changed", + base::Value(can_change_arc_adb_sideloading)); +} + void CrostiniHandler::HandleCrostiniUpgraderDialogStatusRequest( const base::ListValue* args) { AllowJavascript(); @@ -536,6 +590,11 @@ void CrostiniHandler::HandleAddCrostiniPortForward( int protocol_type = args->GetList()[4].GetInt(); std::string label = args->GetList()[5].GetString(); + if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { + OnPortForwardComplete(callback_id, false); + return; + } + crostini::CrostiniPortForwarder::GetForProfile(profile_)->AddPort( crostini::ContainerId(std::move(vm_name), std::move(container_name)), port_number, @@ -559,6 +618,11 @@ void CrostiniHandler::HandleRemoveCrostiniPortForward( int protocol_type; CHECK(args->GetInteger(4, &protocol_type)); + if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { + OnPortForwardComplete(callback_id, false); + return; + } + crostini::CrostiniPortForwarder::GetForProfile(profile_)->RemovePort( crostini::ContainerId(std::move(vm_name), std::move(container_name)), port_number, @@ -574,6 +638,10 @@ void CrostiniHandler::HandleRemoveAllCrostiniPortForwards( std::string vm_name = args_list[0].GetString(); std::string container_name = args_list[1].GetString(); + if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { + return; + } + crostini::CrostiniPortForwarder::GetForProfile(profile_)->RemoveAllPorts( crostini::ContainerId(std::move(vm_name), std::move(container_name))); } @@ -593,6 +661,11 @@ void CrostiniHandler::HandleActivateCrostiniPortForward( int protocol_type; CHECK(args->GetInteger(4, &protocol_type)); + if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { + OnPortForwardComplete(callback_id, false); + return; + } + crostini::CrostiniPortForwarder::GetForProfile(profile_)->ActivatePort( crostini::ContainerId(std::move(vm_name), std::move(container_name)), port_number, @@ -616,6 +689,11 @@ void CrostiniHandler::HandleDeactivateCrostiniPortForward( int protocol_type; CHECK(args->GetInteger(4, &protocol_type)); + if (!crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile_)) { + OnPortForwardComplete(callback_id, false); + return; + } + crostini::CrostiniPortForwarder::GetForProfile(profile_)->DeactivatePort( crostini::ContainerId(std::move(vm_name), std::move(container_name)), port_number, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h index b1f5b8162bc..5867245850c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_handler.h @@ -11,9 +11,11 @@ #include "chrome/browser/chromeos/crostini/crostini_export_import.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_port_forwarder.h" +#include "chrome/browser/chromeos/settings/cros_settings.h" #include "chrome/browser/chromeos/usb/cros_usb_detector.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chromeos/dbus/session_manager/session_manager_client.h" +#include "components/prefs/pref_change_registrar.h" class Profile; @@ -83,8 +85,14 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler, void HandleQueryArcAdbRequest(const base::ListValue* args); // Handle a request for enabling adb sideloading in ARC. void HandleEnableArcAdbRequest(const base::ListValue* args); + // Called after establishing whether enabling adb sideloading is allowed for + // the user and device + void OnCanEnableArcAdbSideloading(bool can_change_adb_sideloading); // Handle a request for disabling adb sideloading in ARC. void HandleDisableArcAdbRequest(const base::ListValue* args); + // Called after establishing whether disabling adb sideloading is allowed for + // the user and device + void OnCanDisableArcAdbSideloading(bool can_change_adb_sideloading); // Launch the Crostini terminal. void LaunchTerminal(); // Handle a request for showing the container upgrade view. @@ -93,9 +101,6 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler, void OnQueryAdbSideload( SessionManagerClient::AdbSideloadResponseCode response_code, bool enabled); - // Returns whether the current user can change adb sideloading configuration - // on current device. - bool CheckEligibilityToChangeArcAdbSideloading() const; // Handle a request for the CrostiniUpgraderDialog status. void HandleCrostiniUpgraderDialogStatusRequest(const base::ListValue* args); // Handle a request for the availability of a container upgrade. @@ -142,8 +147,17 @@ class CrostiniHandler : public ::settings::SettingsPageUIHandler, void HandleSetCrostiniMicSharingEnabled(const base::ListValue* args); // Handles a request for getting the permissions for Crostini Mic access. void HandleGetCrostiniMicSharingEnabled(const base::ListValue* args); + // Handle a request for checking permission for changing ARC adb sideloading. + void HandleCanChangeArcAdbSideloadingRequest(const base::ListValue* args); + // Get permission of changing ARC adb sideloading + void FetchCanChangeAdbSideloading(); + // Callback of FetchCanChangeAdbSideloading. + void OnCanChangeArcAdbSideloading(bool can_change_arc_adb_sideloading); Profile* profile_; + std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> + adb_sideloading_device_policy_subscription_; + PrefChangeRegistrar pref_change_registrar_; // weak_ptr_factory_ should always be last member. base::WeakPtrFactory<CrostiniHandler> weak_ptr_factory_{this}; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc index f25ce803272..546c2ff9270 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.cc @@ -36,21 +36,15 @@ namespace chromeos { namespace settings { namespace { -const std::vector<SearchConcept>& GetCrostiniSearchConcepts() { +const std::vector<SearchConcept>& GetCrostiniOptedInSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_CROSTINI, mojom::kCrostiniDetailsSubpagePath, mojom::SearchResultIcon::kPenguin, - mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultDefaultRank::kHigh, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kCrostiniDetails}, {IDS_OS_SETTINGS_TAG_CROSTINI_ALT1, SearchConcept::kAltTagEnd}}, - }); - return *tags; -} - -const std::vector<SearchConcept>& GetCrostiniOptedInSearchConcepts() { - static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_CROSTINI_USB_PREFERENCES, mojom::kCrostiniUsbPreferencesSubpagePath, mojom::SearchResultIcon::kPenguin, @@ -88,6 +82,13 @@ const std::vector<SearchConcept>& GetCrostiniOptedInSearchConcepts() { const std::vector<SearchConcept>& GetCrostiniOptedOutSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_CROSTINI, + mojom::kCrostiniSectionPath, + mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSection, + {.section = mojom::Section::kCrostini}, + {IDS_OS_SETTINGS_TAG_CROSTINI_ALT1, SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_CROSTINI_SETUP, mojom::kCrostiniSectionPath, mojom::SearchResultIcon::kPenguin, @@ -205,10 +206,6 @@ bool IsAdbSideloadingAllowed() { return base::FeatureList::IsEnabled(features::kArcAdbSideloadingFeature); } -bool IsPortForwardingAllowed() { - return base::FeatureList::IsEnabled(features::kCrostiniPortForwarding); -} - bool IsDiskResizingAllowed() { return base::FeatureList::IsEnabled(features::kCrostiniDiskResizing); } @@ -320,16 +317,22 @@ void CrostiniSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_BUTTON_DESCRIPTION}, {"crostiniPortForwardingAddPortDialogTitle", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_TITLE}, - {"crostiniPortForwardingAddPortDialogLabel", - IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_LABEL}, + {"crostiniPortForwardingAddPortDialogPortNumberLabel", + IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_PORT_NUMBER_LABEL}, + {"crostiniPortForwardingAddPortDialogLabelLabel", + IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_PORT_DIALOG_LABEL_LABEL}, {"crostiniPortForwardingTCP", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_TCP}, {"crostiniPortForwardingUDP", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_UDP}, {"crostiniPortForwardingAddError", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_ERROR}, + {"crostiniPortForwardingAddExisting", + IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ADD_EXISTING}, {"crostiniPortForwardingRemoveAllPorts", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_REMOVE_ALL_PORTS}, {"crostiniPortForwardingRemovePort", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_REMOVE_PORT}, + {"crostiniPortForwardingActivatePortError", + IDS_SETTINGS_CROSTINI_PORT_FORWARDING_ACTIVATE_PORT_ERROR}, {"crostiniPortForwardingToggleAriaLabel", IDS_SETTINGS_CROSTINI_PORT_FORWARDING_TOGGLE_PORT_ARIA_LABEL}, {"crostiniPortForwardingRemoveAllPortsAriaLabel", @@ -432,9 +435,6 @@ void CrostiniSection::AddLoadTimeData(content::WebUIDataSource* html_source) { chromeos::ProfileHelper::IsOwnerProfile(profile())); html_source->AddBoolean("isEnterpriseManaged", IsDeviceManaged() || IsProfileManaged(profile())); - html_source->AddBoolean( - "canChangeAdbSideloading", - crostini::CrostiniFeatures::Get()->CanChangeAdbSideloading(profile())); html_source->AddBoolean("showCrostiniContainerUpgrade", IsContainerUpgradeAllowed()); html_source->AddBoolean("showCrostiniDiskResize", IsDiskResizingAllowed()); @@ -448,6 +448,89 @@ void CrostiniSection::AddHandlers(content::WebUI* web_ui) { } } +int CrostiniSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_CROSTINI_TITLE; +} + +mojom::Section CrostiniSection::GetSection() const { + return mojom::Section::kCrostini; +} + +mojom::SearchResultIcon CrostiniSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kPenguin; +} + +std::string CrostiniSection::GetSectionPath() const { + return mojom::kCrostiniSectionPath; +} + +void CrostiniSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kSetUpCrostini); + + // Crostini details. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_CROSTINI_LABEL, + mojom::Subpage::kCrostiniDetails, + mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCrostiniDetailsSubpagePath); + static constexpr mojom::Setting kCrostiniDetailsSettings[] = { + mojom::Setting::kCrostiniContainerUpgrade, + mojom::Setting::kCrostiniDiskResize, + mojom::Setting::kCrostiniMicAccess, + mojom::Setting::kUninstallCrostini, + }; + RegisterNestedSettingBulk(mojom::Subpage::kCrostiniDetails, + kCrostiniDetailsSettings, generator); + + // Manage shared folders. + generator->RegisterNestedSubpage( + IDS_SETTINGS_CROSTINI_SHARED_PATHS, + mojom::Subpage::kCrostiniManageSharedFolders, + mojom::Subpage::kCrostiniDetails, mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCrostiniManageSharedFoldersSubpagePath); + + // USB preferences. + generator->RegisterNestedSubpage( + IDS_SETTINGS_CROSTINI_SHARED_USB_DEVICES_LABEL, + mojom::Subpage::kCrostiniUsbPreferences, mojom::Subpage::kCrostiniDetails, + mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCrostiniUsbPreferencesSubpagePath); + + // Backup and restore. + generator->RegisterNestedSubpage(IDS_SETTINGS_CROSTINI_EXPORT_IMPORT_TITLE, + mojom::Subpage::kCrostiniBackupAndRestore, + mojom::Subpage::kCrostiniDetails, + mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCrostiniBackupAndRestoreSubpagePath); + static constexpr mojom::Setting kCrostiniBackupAndRestoreSettings[] = { + mojom::Setting::kBackupLinuxAppsAndFiles, + mojom::Setting::kRestoreLinuxAppsAndFiles, + }; + RegisterNestedSettingBulk(mojom::Subpage::kCrostiniBackupAndRestore, + kCrostiniBackupAndRestoreSettings, generator); + + // Develop Android apps. + generator->RegisterNestedSubpage( + IDS_SETTINGS_CROSTINI_ARC_ADB_TITLE, + mojom::Subpage::kCrostiniDevelopAndroidApps, + mojom::Subpage::kCrostiniDetails, mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCrostiniDevelopAndroidAppsSubpagePath); + generator->RegisterNestedSetting(mojom::Setting::kCrostiniAdbDebugging, + mojom::Subpage::kCrostiniDevelopAndroidApps); + + // Port forwarding. + generator->RegisterNestedSubpage(IDS_SETTINGS_CROSTINI_PORT_FORWARDING, + mojom::Subpage::kCrostiniPortForwarding, + mojom::Subpage::kCrostiniDetails, + mojom::SearchResultIcon::kPenguin, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCrostiniPortForwardingSubpagePath); +} + bool CrostiniSection::IsCrostiniAllowed() { return crostini::CrostiniFeatures::Get()->IsUIAllowed(profile(), /*check_policy=*/false); @@ -461,48 +544,51 @@ bool CrostiniSection::IsContainerUpgradeAllowed() { return crostini::ShouldAllowContainerUpgrade(profile()); } +bool CrostiniSection::IsPortForwardingAllowed() { + return crostini::CrostiniFeatures::Get()->IsPortForwardingAllowed(profile()); +} + void CrostiniSection::UpdateSearchTags() { - registry()->RemoveSearchTags(GetCrostiniSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniOptedInSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniOptedOutSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniExportImportSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniAdbSideloadingSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniPortForwardingSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniContainerUpgradeSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniDiskResizingSearchConcepts()); - registry()->RemoveSearchTags(GetCrostiniMicSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + updater.RemoveSearchTags(GetCrostiniOptedInSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniOptedOutSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniExportImportSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniAdbSideloadingSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniPortForwardingSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniContainerUpgradeSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniDiskResizingSearchConcepts()); + updater.RemoveSearchTags(GetCrostiniMicSearchConcepts()); if (!IsCrostiniAllowed()) return; - registry()->AddSearchTags(GetCrostiniSearchConcepts()); - if (!pref_service_->GetBoolean(crostini::prefs::kCrostiniEnabled)) { - registry()->AddSearchTags(GetCrostiniOptedOutSearchConcepts()); + updater.AddSearchTags(GetCrostiniOptedOutSearchConcepts()); return; } - registry()->AddSearchTags(GetCrostiniOptedInSearchConcepts()); + updater.AddSearchTags(GetCrostiniOptedInSearchConcepts()); if (IsExportImportAllowed()) - registry()->AddSearchTags(GetCrostiniExportImportSearchConcepts()); + updater.AddSearchTags(GetCrostiniExportImportSearchConcepts()); if (IsAdbSideloadingAllowed() && pref_service_->GetBoolean(arc::prefs::kArcEnabled)) { - registry()->AddSearchTags(GetCrostiniAdbSideloadingSearchConcepts()); + updater.AddSearchTags(GetCrostiniAdbSideloadingSearchConcepts()); } if (IsPortForwardingAllowed()) - registry()->AddSearchTags(GetCrostiniPortForwardingSearchConcepts()); + updater.AddSearchTags(GetCrostiniPortForwardingSearchConcepts()); if (IsContainerUpgradeAllowed()) - registry()->AddSearchTags(GetCrostiniContainerUpgradeSearchConcepts()); + updater.AddSearchTags(GetCrostiniContainerUpgradeSearchConcepts()); if (IsDiskResizingAllowed()) - registry()->AddSearchTags(GetCrostiniDiskResizingSearchConcepts()); + updater.AddSearchTags(GetCrostiniDiskResizingSearchConcepts()); if (IsMicSettingAllowed()) - registry()->AddSearchTags(GetCrostiniMicSearchConcepts()); + updater.AddSearchTags(GetCrostiniMicSearchConcepts()); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.h index ee51c4be36f..e7caf6a65ea 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/crostini_section.h @@ -31,10 +31,16 @@ class CrostiniSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; bool IsCrostiniAllowed(); bool IsExportImportAllowed(); bool IsContainerUpgradeAllowed(); + bool IsPortForwardingAllowed(); void UpdateSearchTags(); PrefService* pref_service_; 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 6031f1951fa..74b1ac7cc36 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 @@ -27,6 +27,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/printing/cups_printers_manager.h" #include "chrome/browser/chromeos/printing/ppd_provider_factory.h" +#include "chrome/browser/chromeos/printing/print_management/print_management_uma.h" #include "chrome/browser/chromeos/printing/printer_configurer.h" #include "chrome/browser/chromeos/printing/printer_event_tracker.h" #include "chrome/browser/chromeos/printing/printer_event_tracker_factory.h" @@ -241,15 +242,15 @@ Printer::PpdReference GetPpdReference(const base::Value* info) { Printer::PpdReference ret; - if (user_supplied_ppd_url != nullptr) { + if (user_supplied_ppd_url) { ret.user_supplied_ppd_url = user_supplied_ppd_url->GetString(); } - if (effective_make_and_model != nullptr) { + if (effective_make_and_model) { ret.effective_make_and_model = effective_make_and_model->GetString(); } - if (autoconf != nullptr) { + if (autoconf) { ret.autoconf = autoconf->GetBool(); } @@ -998,6 +999,7 @@ void CupsPrintersHandler::HandleStartDiscovery(const base::ListValue* args) { UMA_HISTOGRAM_COUNTS_100( "Printing.CUPS.PrintersDiscovered", discovered_printers_.size() + automatic_printers_.size()); + printers_manager_->RecordNearbyNetworkPrinterCounts(); // Scan completes immediately right now. Emit done. FireWebUIListener("on-printer-discovery-done"); } @@ -1328,7 +1330,8 @@ void CupsPrintersHandler::HandleOpenPrintManagementApp( DCHECK(args->empty()); DCHECK( base::FeatureList::IsEnabled(chromeos::features::kPrintJobManagementApp)); - chrome::ShowPrintManagementApp(profile_); + chrome::ShowPrintManagementApp(profile_, + PrintManagementAppEntryPoint::kSettings); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc index 36193fc66fa..00cd8e56cb4 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc @@ -10,13 +10,17 @@ #include "base/bind_helpers.h" #include "base/files/file_path.h" #include "base/json/json_string_value_serializer.h" +#include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/values.h" +#include "chrome/browser/chromeos/printing/print_management/print_management_uma.h" #include "chrome/browser/chromeos/printing/printing_stubs.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/ui/chrome_select_file_policy.h" #include "chrome/test/base/testing_profile.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "content/public/test/browser_task_environment.h" @@ -192,6 +196,8 @@ class CupsPrintersHandlerTest : public testing::Test { ~CupsPrintersHandlerTest() override = default; void SetUp() override { + scoped_feature_list_.InitWithFeatures( + {chromeos::features::kPrintJobManagementApp}, {}); printers_handler_ = CupsPrintersHandler::CreateForTesting( &profile_, base::MakeRefCounted<FakePpdProvider>(), std::make_unique<StubPrinterConfigurer>(), &printers_manager_); @@ -201,11 +207,13 @@ class CupsPrintersHandlerTest : public testing::Test { protected: // Must outlive |profile_|. + base::HistogramTester histogram_tester_; content::BrowserTaskEnvironment task_environment_; TestingProfile profile_; content::TestWebUI web_ui_; std::unique_ptr<CupsPrintersHandler> printers_handler_; TestCupsPrintersManager printers_manager_; + base::test::ScopedFeatureList scoped_feature_list_; }; TEST_F(CupsPrintersHandlerTest, RemoveCorrectPrinter) { @@ -253,5 +261,24 @@ TEST_F(CupsPrintersHandlerTest, VerifyOnlyPpdFilesAllowed) { web_ui_.HandleReceivedMessage("selectPPDFile", &base::Value::AsListValue(args)); } + +TEST_F(CupsPrintersHandlerTest, VerifyPrintManagementAppEntryPointHistogram) { + base::Value args(base::Value::Type::LIST); + web_ui_.HandleReceivedMessage("openPrintManagementApp", + &base::Value::AsListValue(args)); + histogram_tester_.ExpectBucketCount( + "Printing.Cups.PrintManagementAppEntryPoint", + PrintManagementAppEntryPoint::kSettings, 1); + histogram_tester_.ExpectBucketCount( + "Printing.Cups.PrintManagementAppEntryPoint", + PrintManagementAppEntryPoint::kNotification, 0); + histogram_tester_.ExpectBucketCount( + "Printing.Cups.PrintManagementAppEntryPoint", + PrintManagementAppEntryPoint::kLauncher, 0); + histogram_tester_.ExpectBucketCount( + "Printing.Cups.PrintManagementAppEntryPoint", + PrintManagementAppEntryPoint::kBrowser, 0); +} + } // namespace settings. } // namespace chromeos. diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc index dac0db6e52d..0c1df37cc1e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_handler.cc @@ -58,7 +58,7 @@ bool IsTimezoneAutomaticDetectionUserEditable() { if (IsSystemTimezoneAutomaticDetectionManaged()) { return GetSystemTimezoneAutomaticDetectionPolicyValue() == - enterprise_management::SystemTimezoneProto::USERS_DECIDE; + enterprise_management::SystemTimezoneProto::USERS_DECIDE; } return true; @@ -156,7 +156,7 @@ void DateTimeHandler::HandleShowParentAccessForTimeZone( base::BindOnce(&DateTimeHandler::OnParentAccessValidation, weak_ptr_factory_.GetWeakPtr()), ash::ParentAccessRequestReason::kChangeTimezone, false /* extra_dimmer */, - base::Time()); + base::Time::Now()); } void DateTimeHandler::OnParentAccessValidation(bool success) { @@ -166,10 +166,9 @@ void DateTimeHandler::OnParentAccessValidation(bool success) { void DateTimeHandler::NotifyTimezoneAutomaticDetectionPolicy() { bool managed = !IsTimezoneAutomaticDetectionUserEditable(); - bool force_enabled = managed && - g_browser_process->platform_part() - ->GetTimezoneResolverManager() - ->ShouldApplyResolvedTimezone(); + bool force_enabled = managed && g_browser_process->platform_part() + ->GetTimezoneResolverManager() + ->ShouldApplyResolvedTimezone(); FireWebUIListener("time-zone-auto-detect-policy", base::Value(managed), base::Value(force_enabled)); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.cc index 529689f68dc..8899d28d0e1 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.cc @@ -19,6 +19,7 @@ #include "chromeos/settings/cros_settings_names.h" #include "chromeos/settings/system_settings_provider.h" #include "chromeos/settings/timezone_settings.h" +#include "components/user_manager/user_manager.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -71,18 +72,23 @@ const std::vector<SearchConcept>& GetNoFineGrainedTimeZoneSearchConcepts() { return *tags; } +bool IsFineGrainedTimeZoneEnabled() { + SystemSettingsProvider provider; + return provider.Get(chromeos::kFineGrainedTimeZoneResolveEnabled)->GetBool(); +} + } // namespace DateTimeSection::DateTimeSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { - registry()->AddSearchTags(GetDateTimeSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetDateTimeSearchConcepts()); - SystemSettingsProvider provider; - if (provider.Get(chromeos::kFineGrainedTimeZoneResolveEnabled)->GetBool()) - registry()->AddSearchTags(GetFineGrainedTimeZoneSearchConcepts()); + if (IsFineGrainedTimeZoneEnabled()) + updater.AddSearchTags(GetFineGrainedTimeZoneSearchConcepts()); else - registry()->AddSearchTags(GetNoFineGrainedTimeZoneSearchConcepts()); + updater.AddSearchTags(GetNoFineGrainedTimeZoneSearchConcepts()); } DateTimeSection::~DateTimeSection() = default; @@ -127,11 +133,49 @@ void DateTimeSection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddBoolean( "timeActionsProtectedForChild", base::FeatureList::IsEnabled(features::kParentAccessCodeForTimeChange)); + + bool is_child = user_manager::UserManager::Get()->GetActiveUser()->IsChild(); + html_source->AddBoolean("isChild", is_child); } void DateTimeSection::AddHandlers(content::WebUI* web_ui) { web_ui->AddMessageHandler(std::make_unique<DateTimeHandler>()); } +int DateTimeSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_DATE_TIME; +} + +mojom::Section DateTimeSection::GetSection() const { + return mojom::Section::kDateAndTime; +} + +mojom::SearchResultIcon DateTimeSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kClock; +} + +std::string DateTimeSection::GetSectionPath() const { + return mojom::kDateAndTimeSectionPath; +} + +void DateTimeSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::k24HourClock); + + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_TIME_ZONE_SUBPAGE_TITLE, mojom::Subpage::kTimeZone, + mojom::SearchResultIcon::kClock, mojom::SearchResultDefaultRank::kMedium, + mojom::kTimeZoneSubpagePath); + + // When fine-grained time zone is enabled, users change the time zone on the + // time zone subpage; otherwise, the setting is directly embedded in the + // section. + if (IsFineGrainedTimeZoneEnabled()) { + generator->RegisterNestedSetting(mojom::Setting::kChangeTimeZone, + mojom::Subpage::kTimeZone); + } else { + generator->RegisterTopLevelSetting(mojom::Setting::kChangeTimeZone); + } +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.h index 2c1d8e0f5c3..7eef9df9516 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/date_time_section.h @@ -26,6 +26,11 @@ class DateTimeSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.cc index 38eb1b57fef..c90f34eff69 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.cc @@ -36,28 +36,32 @@ DlcHandler::~DlcHandler() = default; void DlcHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( - "getDlcList", base::BindRepeating(&DlcHandler::HandleGetDlcList, - weak_ptr_factory_.GetWeakPtr())); + "dlcSubpageReady", base::BindRepeating(&DlcHandler::HandleDlcSubpageReady, + base::Unretained(this))); web_ui()->RegisterMessageCallback( - "purgeDlc", base::BindRepeating(&DlcHandler::HandlePurgeDlc, - weak_ptr_factory_.GetWeakPtr())); + "purgeDlc", + base::BindRepeating(&DlcHandler::HandlePurgeDlc, base::Unretained(this))); +} + +void DlcHandler::OnJavascriptAllowed() { + dlcservice_client_observer_.Add(DlcserviceClient::Get()); } void DlcHandler::OnJavascriptDisallowed() { + dlcservice_client_observer_.RemoveAll(); + // Ensure that pending callbacks do not complete and cause JS to be evaluated. weak_ptr_factory_.InvalidateWeakPtrs(); } -void DlcHandler::HandleGetDlcList(const base::ListValue* args) { - AllowJavascript(); - CHECK_EQ(1U, args->GetSize()); - const base::Value* callback_id; - CHECK(args->Get(0, &callback_id)); +void DlcHandler::OnDlcStateChanged(const dlcservice::DlcState& dlc_state) { + FetchDlcList(); +} - DlcserviceClient::Get()->GetExistingDlcs( - base::BindOnce(&DlcHandler::GetDlcListCallback, - weak_ptr_factory_.GetWeakPtr(), callback_id->Clone())); +void DlcHandler::HandleDlcSubpageReady(const base::ListValue* args) { + AllowJavascript(); + FetchDlcList(); } void DlcHandler::HandlePurgeDlc(const base::ListValue* args) { @@ -74,16 +78,18 @@ void DlcHandler::HandlePurgeDlc(const base::ListValue* args) { weak_ptr_factory_.GetWeakPtr(), callback_id->Clone())); } -void DlcHandler::GetDlcListCallback( - const base::Value& callback_id, +void DlcHandler::FetchDlcList() { + DlcserviceClient::Get()->GetExistingDlcs( + base::BindOnce(&DlcHandler::SendDlcList, weak_ptr_factory_.GetWeakPtr())); +} + +void DlcHandler::SendDlcList( const std::string& err, const dlcservice::DlcsWithContent& dlcs_with_content) { - if (err == dlcservice::kErrorNone) { - ResolveJavascriptCallback(callback_id, - DlcsWithContentToListValue(dlcs_with_content)); - return; - } - ResolveJavascriptCallback(callback_id, base::ListValue()); + FireWebUIListener("dlc-list-changed", + err == dlcservice::kErrorNone + ? DlcsWithContentToListValue(dlcs_with_content) + : base::ListValue()); } void DlcHandler::PurgeDlcCallback(const base::Value& callback_id, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.h index 27afcaf2de6..cbd3f798c74 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_DEVICE_DLC_HANDLER_H_ #include "base/memory/weak_ptr.h" +#include "base/scoped_observer.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chromeos/dbus/dlcservice/dlcservice_client.h" @@ -17,7 +18,8 @@ namespace chromeos { namespace settings { // Chrome OS Downloaded Content settings page UI handler. -class DlcHandler : public ::settings::SettingsPageUIHandler { +class DlcHandler : public ::settings::SettingsPageUIHandler, + public DlcserviceClient::Observer { public: DlcHandler(); DlcHandler(const DlcHandler&) = delete; @@ -26,22 +28,32 @@ class DlcHandler : public ::settings::SettingsPageUIHandler { // SettingsPageUIHandler: void RegisterMessages() override; - void OnJavascriptAllowed() override {} + void OnJavascriptAllowed() override; void OnJavascriptDisallowed() override; + // DlcserviceClient::Observer: + void OnDlcStateChanged(const dlcservice::DlcState& dlc_state) override; + private: - // Handler to get the latest list of DLCs. - void HandleGetDlcList(const base::ListValue* args); + // Handler called when DLC subpage is attached. + void HandleDlcSubpageReady(const base::ListValue* args); // Handler to purge a DLC. void HandlePurgeDlc(const base::ListValue* args); - void GetDlcListCallback(const base::Value& callback_id, - const std::string& err, - const dlcservice::DlcsWithContent& dlcs_with_content); + // Fetches the latest DLC list from DlcserviceClient, passing SendDlcList() as + // the callback. + void FetchDlcList(); + + // Sends DLC list to web UIs listening in on 'dlc-list-changed' events. + void SendDlcList(const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content); void PurgeDlcCallback(const base::Value& callback_id, const std::string& err); + ScopedObserver<DlcserviceClient, DlcserviceClient::Observer> + dlcservice_client_observer_{this}; + base::WeakPtrFactory<DlcHandler> weak_ptr_factory_{this}; }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler_unittest.cc index cb4dbc5dde8..b99ed70fcde 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_dlc_handler_unittest.cc @@ -42,14 +42,14 @@ class DlcHandlerTest : public testing::Test { void SetUp() override { test_web_ui_ = std::make_unique<content::TestWebUI>(); + chromeos::DlcserviceClient::InitializeFake(); + fake_dlcservice_client_ = static_cast<chromeos::FakeDlcserviceClient*>( + chromeos::DlcserviceClient::Get()); + handler_ = std::make_unique<TestDlcHandler>(); handler_->set_web_ui(test_web_ui_.get()); handler_->RegisterMessages(); handler_->AllowJavascriptForTesting(); - - chromeos::DlcserviceClient::InitializeFake(); - fake_dlcservice_client_ = static_cast<chromeos::FakeDlcserviceClient*>( - chromeos::DlcserviceClient::Get()); } void TearDown() override { @@ -70,12 +70,12 @@ class DlcHandlerTest : public testing::Test { return *test_web_ui_->call_data()[index]; } - base::Value::ConstListView CallGetDlcListAndReturnList() { + base::Value::ConstListView NotifyDlcSubpageReadyAndReturnDlcList() { size_t call_data_count_before_call = test_web_ui()->call_data().size(); base::ListValue args; args.AppendString("handlerFunctionName"); - test_web_ui()->HandleReceivedMessage("getDlcList", &args); + test_web_ui()->HandleReceivedMessage("dlcSubpageReady", &args); task_environment_.RunUntilIdle(); EXPECT_EQ(call_data_count_before_call + 1u, @@ -83,9 +83,9 @@ class DlcHandlerTest : public testing::Test { 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()); - return call_data.arg3()->GetList(); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("dlc-list-changed", call_data.arg1()->GetString()); + return call_data.arg2()->GetList(); } bool CallPurgeDlcAndReturnSuccess() { @@ -108,26 +108,45 @@ class DlcHandlerTest : public testing::Test { } }; -TEST_F(DlcHandlerTest, GetDlcList) { +TEST_F(DlcHandlerTest, SendDlcListOnDlcStatusChange) { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + fake_dlcservice_client_->set_dlcs_with_content(CreateDlcModuleListOfSize(2u)); + + dlcservice::DlcState dlc_state; + dlc_state.set_state(dlcservice::DlcState::INSTALLING); + fake_dlcservice_client_->NotifyObserversForTest(dlc_state); + task_environment_.RunUntilIdle(); + + EXPECT_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.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("dlc-list-changed", call_data.arg1()->GetString()); + EXPECT_EQ(call_data.arg2()->GetList().size(), 2u); +} + +TEST_F(DlcHandlerTest, CorrectlyReturnsDlcMetadataListOnSubpageReady) { fake_dlcservice_client_->set_dlcs_with_content(CreateDlcModuleListOfSize(2u)); fake_dlcservice_client_->SetGetExistingDlcsError(dlcservice::kErrorInternal); - EXPECT_EQ(CallGetDlcListAndReturnList().size(), 0u); + EXPECT_EQ(NotifyDlcSubpageReadyAndReturnDlcList().size(), 0u); fake_dlcservice_client_->SetGetExistingDlcsError( dlcservice::kErrorNeedReboot); - EXPECT_EQ(CallGetDlcListAndReturnList().size(), 0u); + EXPECT_EQ(NotifyDlcSubpageReadyAndReturnDlcList().size(), 0u); fake_dlcservice_client_->SetGetExistingDlcsError( dlcservice::kErrorInvalidDlc); - EXPECT_EQ(CallGetDlcListAndReturnList().size(), 0u); + EXPECT_EQ(NotifyDlcSubpageReadyAndReturnDlcList().size(), 0u); fake_dlcservice_client_->SetGetExistingDlcsError( dlcservice::kErrorAllocation); - EXPECT_EQ(CallGetDlcListAndReturnList().size(), 0u); + EXPECT_EQ(NotifyDlcSubpageReadyAndReturnDlcList().size(), 0u); fake_dlcservice_client_->SetGetExistingDlcsError(dlcservice::kErrorNone); - EXPECT_EQ(CallGetDlcListAndReturnList().size(), 2u); + EXPECT_EQ(NotifyDlcSubpageReadyAndReturnDlcList().size(), 2u); } TEST_F(DlcHandlerTest, PurgeDlc) { @@ -157,7 +176,7 @@ TEST_F(DlcHandlerTest, FormattedCorrectly) { fake_dlcservice_client_->set_dlcs_with_content(dlcs_with_content); - auto result_list = CallGetDlcListAndReturnList(); + auto result_list = NotifyDlcSubpageReadyAndReturnDlcList(); EXPECT_EQ(1UL, result_list.size()); EXPECT_EQ("fake id", result_list[0].FindKey("id")->GetString()); EXPECT_EQ("fake name", result_list[0].FindKey("name")->GetString()); 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 440b8feb397..7921e8838dd 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.cc @@ -48,7 +48,7 @@ const std::vector<SearchConcept>& GetDeviceSearchConcepts() { {IDS_OS_SETTINGS_TAG_KEYBOARD, mojom::kKeyboardSubpagePath, mojom::SearchResultIcon::kKeyboard, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kKeyboard}}, {IDS_OS_SETTINGS_TAG_KEYBOARD_AUTO_REPEAT, @@ -81,7 +81,7 @@ const std::vector<SearchConcept>& GetDeviceSearchConcepts() { {IDS_OS_SETTINGS_TAG_STORAGE, mojom::kStorageSubpagePath, mojom::SearchResultIcon::kHardDrive, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kStorage}, {IDS_OS_SETTINGS_TAG_STORAGE_ALT1, IDS_OS_SETTINGS_TAG_STORAGE_ALT2, @@ -89,7 +89,7 @@ const std::vector<SearchConcept>& GetDeviceSearchConcepts() { {IDS_OS_SETTINGS_TAG_DISPLAY_NIGHT_LIGHT, mojom::kDisplaySubpagePath, mojom::SearchResultIcon::kDisplay, - mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultDefaultRank::kLow, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kNightLight}, {IDS_OS_SETTINGS_TAG_DISPLAY_NIGHT_LIGHT_ALT1, @@ -98,7 +98,7 @@ const std::vector<SearchConcept>& GetDeviceSearchConcepts() { {IDS_OS_SETTINGS_TAG_DISPLAY, mojom::kDisplaySubpagePath, mojom::SearchResultIcon::kDisplay, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kDisplay}, {IDS_OS_SETTINGS_TAG_DISPLAY_ALT1, IDS_OS_SETTINGS_TAG_DISPLAY_ALT2, @@ -121,13 +121,22 @@ const std::vector<SearchConcept>& GetDeviceSearchConcepts() { mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kKeyboardFunctionKeys}}, - {IDS_OS_SETTINGS_TAG_POWER_IDLE, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING, mojom::kPowerSubpagePath, mojom::SearchResultIcon::kPower, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kPowerIdleBehavior}, - {IDS_OS_SETTINGS_TAG_POWER_IDLE_ALT1, SearchConcept::kAltTagEnd}}, + {.setting = mojom::Setting::kPowerIdleBehaviorWhileCharging}, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_CHARGING_ALT1, + SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY, + mojom::kPowerSubpagePath, + mojom::SearchResultIcon::kPower, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kPowerIdleBehaviorWhileOnBattery}, + {IDS_OS_SETTINGS_TAG_POWER_IDLE_WHILE_ON_BATTERY_ALT1, + SearchConcept::kAltTagEnd}}, }); return *tags; } @@ -155,7 +164,7 @@ const std::vector<SearchConcept>& GetTouchpadSearchConcepts() { {IDS_OS_SETTINGS_TAG_TOUCHPAD, mojom::kPointersSubpagePath, mojom::SearchResultIcon::kLaptop, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kPointers}, {IDS_OS_SETTINGS_TAG_TOUCHPAD_ALT1, SearchConcept::kAltTagEnd}}, @@ -210,7 +219,7 @@ const std::vector<SearchConcept>& GetMouseSearchConcepts() { {IDS_OS_SETTINGS_TAG_MOUSE, mojom::kPointersSubpagePath, mojom::SearchResultIcon::kMouse, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kPointers}}, {IDS_OS_SETTINGS_TAG_MOUSE_SCROLL_ACCELERATION, @@ -281,36 +290,30 @@ const std::vector<SearchConcept>& GetDisplayArrangementSearchConcepts() { const std::vector<SearchConcept>& GetDisplayMirrorSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display mirror" search concepts. + {IDS_OS_SETTINGS_TAG_MIRRORING, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDisplayMirroring}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayUnifiedDesktopSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display with Unified Desktop" search concepts. - }); - return *tags; -} - -const std::vector<SearchConcept>& GetDisplayMultipleSearchConcepts() { - static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display multiple" search concepts. + {IDS_OS_SETTINGS_TAG_UNIFIED_DESKTOP, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAllowWindowsToSpanDisplays}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayExternalSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION, - mojom::kDisplaySubpagePath, - mojom::SearchResultIcon::kDisplay, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kDisplayOrientation}, - {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1, - IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT2, - SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION, mojom::kDisplaySubpagePath, mojom::SearchResultIcon::kDisplay, @@ -320,6 +323,12 @@ const std::vector<SearchConcept>& GetDisplayExternalSearchConcepts() { {IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION_ALT1, IDS_OS_SETTINGS_TAG_DISPLAY_RESOLUTION_ALT2, SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_DISPLAY_OVERSCAN, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDisplayOverscan}}, }); return *tags; } @@ -342,28 +351,74 @@ GetDisplayExternalWithRefreshSearchConcepts() { const std::vector<SearchConcept>& GetDisplayOrientationSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display orientation" search concepts. + {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kDisplayOrientation}, + {IDS_OS_SETTINGS_TAG_DISPLAY_ORIENTATION_ALT1, + SearchConcept::kAltTagEnd}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayAmbientSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display ambient" search concepts. + {IDS_OS_SETTINGS_TAG_DISPLAY_AMBIENT_COLORS, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAmbientColors}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayTouchCalibrationSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display touch calibration" search concepts. + {IDS_OS_SETTINGS_TAG_DISPLAY_TOUCHSCREEN_CALIBRATION, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kTouchscreenCalibration}}, }); return *tags; } const std::vector<SearchConcept>& GetDisplayNightLightOnSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Display Night Light on" search concepts. + {IDS_OS_SETTINGS_TAG_NIGHT_LIGHT_COLOR_TEMPERATURE, + mojom::kDisplaySubpagePath, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kNightLightColorTemperature}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetDlcSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_DOWNLOADED_CONTENT, + mojom::kDlcSubpagePath, + mojom::SearchResultIcon::kHardDrive, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kDlc}, + {IDS_OS_SETTINGS_TAG_DOWNLOADED_CONTENT_ALT1, + SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_REMOVE_DOWNLOADED_CONTENT, + mojom::kDlcSubpagePath, + mojom::SearchResultIcon::kHardDrive, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kRemoveDlc}, + {IDS_OS_SETTINGS_TAG_REMOVE_DOWNLOADED_CONTENT_ALT1, + IDS_OS_SETTINGS_TAG_REMOVE_DOWNLOADED_CONTENT_ALT2, + IDS_OS_SETTINGS_TAG_REMOVE_DOWNLOADED_CONTENT_ALT3, + SearchConcept::kAltTagEnd}}, }); return *tags; } @@ -694,10 +749,11 @@ DeviceSection::DeviceSection(Profile* profile, PrefService* pref_service) : OsSettingsSection(profile, search_tag_registry), pref_service_(pref_service) { - registry()->AddSearchTags(GetDeviceSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetDeviceSearchConcepts()); if (features::ShouldShowExternalStorageSettings(profile)) - registry()->AddSearchTags(GetExternalStorageSearchConcepts()); + updater.AddSearchTags(GetExternalStorageSearchConcepts()); PowerManagerClient* power_manager_client = PowerManagerClient::Get(); if (power_manager_client) { @@ -739,6 +795,14 @@ DeviceSection::DeviceSection(Profile* profile, OnNightLightEnabledChanged( ash::NightLightController::GetInstance()->GetEnabled()); } + + // DLC settings search tags are added/removed dynamically. + DlcserviceClient* dlcservice_client = DlcserviceClient::Get(); + if (features::ShouldShowDlcSettings() && dlcservice_client) { + dlcservice_client->AddObserver(this); + dlcservice_client->GetExistingDlcs(base::BindOnce( + &DeviceSection::OnGetExistingDlcs, weak_ptr_factory_.GetWeakPtr())); + } } DeviceSection::~DeviceSection() { @@ -753,6 +817,10 @@ DeviceSection::~DeviceSection() { ash::NightLightController::GetInstance(); if (night_light_controller) night_light_controller->RemoveObserver(this); + + DlcserviceClient* dlcservice_client = DlcserviceClient::Get(); + if (features::ShouldShowDlcSettings() && dlcservice_client) + dlcservice_client->RemoveObserver(this); } void DeviceSection::AddLoadTimeData(content::WebUIDataSource* html_source) { @@ -797,18 +865,140 @@ void DeviceSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<chromeos::settings::StylusHandler>()); } +int DeviceSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_DEVICE_TITLE; +} + +mojom::Section DeviceSection::GetSection() const { + return mojom::Section::kDevice; +} + +mojom::SearchResultIcon DeviceSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kLaptop; +} + +std::string DeviceSection::GetSectionPath() const { + return mojom::kDeviceSectionPath; +} + +void DeviceSection::RegisterHierarchy(HierarchyGenerator* generator) const { + // Pointers. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_MOUSE_AND_TOUCHPAD_TITLE, mojom::Subpage::kPointers, + mojom::SearchResultIcon::kMouse, mojom::SearchResultDefaultRank::kMedium, + mojom::kPointersSubpagePath); + static constexpr mojom::Setting kPointersSettings[] = { + mojom::Setting::kTouchpadTapToClick, + mojom::Setting::kTouchpadTapDragging, + mojom::Setting::kTouchpadReverseScrolling, + mojom::Setting::kTouchpadAcceleration, + mojom::Setting::kTouchpadScrollAcceleration, + mojom::Setting::kTouchpadSpeed, + mojom::Setting::kMouseSwapPrimaryButtons, + mojom::Setting::kMouseReverseScrolling, + mojom::Setting::kMouseAcceleration, + mojom::Setting::kMouseScrollAcceleration, + mojom::Setting::kMouseSpeed, + }; + RegisterNestedSettingBulk(mojom::Subpage::kPointers, kPointersSettings, + generator); + + // Keyboard. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_KEYBOARD_TITLE, mojom::Subpage::kKeyboard, + mojom::SearchResultIcon::kKeyboard, + mojom::SearchResultDefaultRank::kMedium, mojom::kKeyboardSubpagePath); + static constexpr mojom::Setting kKeyboardSettings[] = { + mojom::Setting::kKeyboardFunctionKeys, + mojom::Setting::kKeyboardAutoRepeat, + mojom::Setting::kKeyboardShortcuts, + }; + RegisterNestedSettingBulk(mojom::Subpage::kKeyboard, kKeyboardSettings, + generator); + + // Stylus. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_STYLUS_TITLE, mojom::Subpage::kStylus, + mojom::SearchResultIcon::kStylus, mojom::SearchResultDefaultRank::kMedium, + mojom::kStylusSubpagePath); + static constexpr mojom::Setting kStylusSettings[] = { + mojom::Setting::kStylusToolsInShelf, + mojom::Setting::kStylusNoteTakingApp, + mojom::Setting::kStylusNoteTakingFromLockScreen, + mojom::Setting::kStylusLatestNoteOnLockScreen, + }; + RegisterNestedSettingBulk(mojom::Subpage::kStylus, kStylusSettings, + generator); + + // Display. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_DISPLAY_TITLE, mojom::Subpage::kDisplay, + mojom::SearchResultIcon::kDisplay, + mojom::SearchResultDefaultRank::kMedium, mojom::kDisplaySubpagePath); + static constexpr mojom::Setting kDisplaySettings[] = { + mojom::Setting::kDisplaySize, + mojom::Setting::kNightLight, + mojom::Setting::kDisplayOrientation, + mojom::Setting::kDisplayArrangement, + mojom::Setting::kDisplayResolution, + mojom::Setting::kDisplayRefreshRate, + mojom::Setting::kDisplayMirroring, + mojom::Setting::kAllowWindowsToSpanDisplays, + mojom::Setting::kAmbientColors, + mojom::Setting::kTouchscreenCalibration, + mojom::Setting::kNightLightColorTemperature, + mojom::Setting::kDisplayOverscan, + }; + RegisterNestedSettingBulk(mojom::Subpage::kDisplay, kDisplaySettings, + generator); + + // Storage. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_STORAGE_TITLE, mojom::Subpage::kStorage, + mojom::SearchResultIcon::kHardDrive, + mojom::SearchResultDefaultRank::kMedium, mojom::kStorageSubpagePath); + generator->RegisterNestedSubpage( + IDS_SETTINGS_STORAGE_EXTERNAL, mojom::Subpage::kExternalStorage, + mojom::Subpage::kStorage, mojom::SearchResultIcon::kHardDrive, + mojom::SearchResultDefaultRank::kMedium, + mojom::kExternalStorageSubpagePath); + generator->RegisterNestedSubpage( + IDS_SETTINGS_DLC_SUBPAGE_TITLE, mojom::Subpage::kDlc, + mojom::Subpage::kStorage, mojom::SearchResultIcon::kHardDrive, + mojom::SearchResultDefaultRank::kMedium, mojom::kDlcSubpagePath); + generator->RegisterNestedSetting(mojom::Setting::kRemoveDlc, + mojom::Subpage::kDlc); + + // Power. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_POWER_TITLE, mojom::Subpage::kPower, + mojom::SearchResultIcon::kPower, mojom::SearchResultDefaultRank::kMedium, + mojom::kPowerSubpagePath); + static constexpr mojom::Setting kPowerSettings[] = { + mojom::Setting::kPowerIdleBehaviorWhileCharging, + mojom::Setting::kPowerIdleBehaviorWhileOnBattery, + mojom::Setting::kPowerSource, + mojom::Setting::kSleepWhenLaptopLidClosed, + }; + RegisterNestedSettingBulk(mojom::Subpage::kPower, kPowerSettings, generator); +} + void DeviceSection::TouchpadExists(bool exists) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (exists) - registry()->AddSearchTags(GetTouchpadSearchConcepts()); + updater.AddSearchTags(GetTouchpadSearchConcepts()); else - registry()->RemoveSearchTags(GetTouchpadSearchConcepts()); + updater.RemoveSearchTags(GetTouchpadSearchConcepts()); } void DeviceSection::MouseExists(bool exists) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (exists) - registry()->AddSearchTags(GetMouseSearchConcepts()); + updater.AddSearchTags(GetMouseSearchConcepts()); else - registry()->RemoveSearchTags(GetMouseSearchConcepts()); + updater.RemoveSearchTags(GetMouseSearchConcepts()); } void DeviceSection::OnDeviceListsComplete() { @@ -828,12 +1018,32 @@ void DeviceSection::OnDisplayConfigChanged() { void DeviceSection::PowerChanged( const power_manager::PowerSupplyProperties& properties) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (properties.battery_state() != power_manager::PowerSupplyProperties_BatteryState_NOT_PRESENT) { - registry()->AddSearchTags(GetPowerWithBatterySearchConcepts()); + updater.AddSearchTags(GetPowerWithBatterySearchConcepts()); } } +void DeviceSection::OnGetExistingDlcs( + const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + if (err != dlcservice::kErrorNone || + dlcs_with_content.dlc_infos_size() == 0) { + updater.RemoveSearchTags(GetDlcSearchConcepts()); + return; + } + updater.AddSearchTags(GetDlcSearchConcepts()); +} + +void DeviceSection::OnDlcStateChanged(const dlcservice::DlcState& dlc_state) { + DlcserviceClient::Get()->GetExistingDlcs(base::BindOnce( + &DeviceSection::OnGetExistingDlcs, weak_ptr_factory_.GetWeakPtr())); +} + void DeviceSection::OnGetDisplayUnitInfoList( std::vector<ash::mojom::DisplayUnitInfoPtr> display_unit_info_list) { cros_display_config_->GetDisplayLayoutInfo(base::BindOnce( @@ -863,73 +1073,71 @@ void DeviceSection::OnGetDisplayLayoutInfo( ash::mojom::DisplayLayoutMode::kUnified; } + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + // Arrangement UI. if (has_multiple_displays || is_mirrored) - registry()->AddSearchTags(GetDisplayArrangementSearchConcepts()); + updater.AddSearchTags(GetDisplayArrangementSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayArrangementSearchConcepts()); + updater.RemoveSearchTags(GetDisplayArrangementSearchConcepts()); // Mirror toggle. if (is_mirrored || (!unified_desktop_mode && has_multiple_displays)) - registry()->AddSearchTags(GetDisplayMirrorSearchConcepts()); + updater.AddSearchTags(GetDisplayMirrorSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayMirrorSearchConcepts()); + updater.RemoveSearchTags(GetDisplayMirrorSearchConcepts()); // Unified Desktop toggle. if (unified_desktop_mode || (IsUnifiedDesktopAvailable() && has_multiple_displays && !is_mirrored)) { - registry()->AddSearchTags(GetDisplayUnifiedDesktopSearchConcepts()); + updater.AddSearchTags(GetDisplayUnifiedDesktopSearchConcepts()); } else { - registry()->RemoveSearchTags(GetDisplayUnifiedDesktopSearchConcepts()); + updater.RemoveSearchTags(GetDisplayUnifiedDesktopSearchConcepts()); } - // Multiple displays UI. - if (has_multiple_displays) - registry()->AddSearchTags(GetDisplayMultipleSearchConcepts()); - else - registry()->RemoveSearchTags(GetDisplayMultipleSearchConcepts()); - // External display settings. if (has_external_display) - registry()->AddSearchTags(GetDisplayExternalSearchConcepts()); + updater.AddSearchTags(GetDisplayExternalSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayExternalSearchConcepts()); + updater.RemoveSearchTags(GetDisplayExternalSearchConcepts()); // Refresh Rate dropdown. if (has_external_display && IsListAllDisplayModesEnabled()) - registry()->AddSearchTags(GetDisplayExternalWithRefreshSearchConcepts()); + updater.AddSearchTags(GetDisplayExternalWithRefreshSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayExternalWithRefreshSearchConcepts()); + updater.RemoveSearchTags(GetDisplayExternalWithRefreshSearchConcepts()); // Orientation settings. if (!unified_desktop_mode) - registry()->AddSearchTags(GetDisplayOrientationSearchConcepts()); + updater.AddSearchTags(GetDisplayOrientationSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayOrientationSearchConcepts()); + updater.RemoveSearchTags(GetDisplayOrientationSearchConcepts()); // Ambient color settings. if (DoesDeviceSupportAmbientColor() && has_internal_display) - registry()->AddSearchTags(GetDisplayAmbientSearchConcepts()); + updater.AddSearchTags(GetDisplayAmbientSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayAmbientSearchConcepts()); + updater.RemoveSearchTags(GetDisplayAmbientSearchConcepts()); // Touch calibration settings. if (IsTouchCalibrationAvailable()) - registry()->AddSearchTags(GetDisplayTouchCalibrationSearchConcepts()); + updater.AddSearchTags(GetDisplayTouchCalibrationSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayTouchCalibrationSearchConcepts()); + updater.RemoveSearchTags(GetDisplayTouchCalibrationSearchConcepts()); // Night Light on settings. if (ash::NightLightController::GetInstance()->GetEnabled()) - registry()->AddSearchTags(GetDisplayNightLightOnSearchConcepts()); + updater.AddSearchTags(GetDisplayNightLightOnSearchConcepts()); else - registry()->RemoveSearchTags(GetDisplayNightLightOnSearchConcepts()); + updater.RemoveSearchTags(GetDisplayNightLightOnSearchConcepts()); } void DeviceSection::OnGotSwitchStates( base::Optional<PowerManagerClient::SwitchStates> result) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (result && result->lid_state != PowerManagerClient::LidState::NOT_PRESENT) - registry()->AddSearchTags(GetPowerWithLaptopLidSearchConcepts()); + updater.AddSearchTags(GetPowerWithLaptopLidSearchConcepts()); } void DeviceSection::UpdateStylusSearchTags() { @@ -937,13 +1145,15 @@ void DeviceSection::UpdateStylusSearchTags() { if (!ui::DeviceDataManager::GetInstance()->AreDeviceListsComplete()) return; + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + // TODO(https://crbug.com/1071905): Only show stylus settings if a stylus has // been set up. HasStylusInput() will return true for any stylus-compatible // device, even if it doesn't have a stylus. if (ash::stylus_utils::HasStylusInput()) - registry()->AddSearchTags(GetStylusSearchConcepts()); + updater.AddSearchTags(GetStylusSearchConcepts()); else - registry()->RemoveSearchTags(GetStylusSearchConcepts()); + updater.RemoveSearchTags(GetStylusSearchConcepts()); } void DeviceSection::AddDevicePointersStrings( diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.h index 255f63a4963..541b8dbaafc 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_section.h @@ -13,6 +13,7 @@ #include "base/optional.h" #include "chrome/browser/chromeos/system/pointer_device_observer.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" +#include "chromeos/dbus/dlcservice/dlcservice_client.h" #include "chromeos/dbus/power/power_manager_client.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -24,6 +25,10 @@ namespace content { class WebUIDataSource; } // namespace content +namespace dlcservice { +class DlcsWithContent; +} // namespace dlcservice + namespace chromeos { namespace settings { @@ -35,7 +40,8 @@ class DeviceSection : public OsSettingsSection, public ui::InputDeviceEventObserver, public ash::NightLightController::Observer, public ash::mojom::CrosDisplayConfigObserver, - public PowerManagerClient::Observer { + public PowerManagerClient::Observer, + public DlcserviceClient::Observer { public: DeviceSection(Profile* profile, SearchTagRegistry* search_tag_registry, @@ -46,6 +52,11 @@ class DeviceSection : public OsSettingsSection, // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // system::PointerDeviceObserver::Observer: void TouchpadExists(bool exists) override; @@ -63,6 +74,9 @@ class DeviceSection : public OsSettingsSection, // PowerManagerClient::Observer: void PowerChanged(const power_manager::PowerSupplyProperties& proto) override; + // DlcserviceClient::Observer: + void OnDlcStateChanged(const dlcservice::DlcState& dlc_state) override; + void OnGotSwitchStates( base::Optional<PowerManagerClient::SwitchStates> result); @@ -74,6 +88,9 @@ class DeviceSection : public OsSettingsSection, std::vector<ash::mojom::DisplayUnitInfoPtr> display_unit_info_list, ash::mojom::DisplayLayoutInfoPtr display_layout_info); + void OnGetExistingDlcs(const std::string& err, + const dlcservice::DlcsWithContent& dlcs_with_content); + void AddDevicePointersStrings(content::WebUIDataSource* html_source); PrefService* pref_service_; 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 584226636b8..e3961f58389 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 @@ -48,6 +48,8 @@ const char* CalculationTypeToEventName( return "storage-crostini-size-changed"; case calculator::SizeCalculator::CalculationType::kOtherUsers: return "storage-other-users-size-changed"; + case calculator::SizeCalculator::CalculationType::kDlcs: + return "storage-dlcs-size-changed"; } NOTREACHED(); return ""; @@ -63,6 +65,7 @@ StorageHandler::StorageHandler(Profile* profile, apps_size_calculator_(profile), crostini_size_calculator_(profile), other_users_size_calculator_(), + dlcs_size_calculator_(), profile_(profile), source_name_(html_source->GetSource()), arc_observer_(this), @@ -115,6 +118,7 @@ void StorageHandler::OnJavascriptAllowed() { apps_size_calculator_.AddObserver(this); crostini_size_calculator_.AddObserver(this); other_users_size_calculator_.AddObserver(this); + dlcs_size_calculator_.AddObserver(this); } void StorageHandler::OnJavascriptDisallowed() { @@ -133,6 +137,9 @@ int64_t StorageHandler::RoundByteSize(int64_t bytes) { return -1; } + if (bytes == 0) + return 0; + // Subtract one to the original number of bytes. bytes--; // Set all the lower bits to 1. @@ -164,6 +171,7 @@ void StorageHandler::HandleUpdateStorageInfo(const base::ListValue* args) { apps_size_calculator_.StartCalculation(); crostini_size_calculator_.StartCalculation(); other_users_size_calculator_.StartCalculation(); + dlcs_size_calculator_.StartCalculation(); } void StorageHandler::HandleOpenMyFiles(const base::ListValue* unused_args) { @@ -259,6 +267,7 @@ void StorageHandler::StopObservingEvents() { apps_size_calculator_.RemoveObserver(this); crostini_size_calculator_.RemoveObserver(this); other_users_size_calculator_.RemoveObserver(this); + dlcs_size_calculator_.RemoveObserver(this); } void StorageHandler::UpdateStorageItem( @@ -282,6 +291,12 @@ void StorageHandler::UpdateStorageItem( bool no_other_users = (total_bytes == 0); FireWebUIListener(CalculationTypeToEventName(calculation_type), base::Value(message), base::Value(no_other_users)); + } else if (calculation_type == + calculator::SizeCalculator::CalculationType::kDlcs) { + bool dlcs_exist = (total_bytes > 0); + FireWebUIListener(CalculationTypeToEventName(calculation_type), + base::Value(dlcs_exist), base::Value(message)); + } else { FireWebUIListener(CalculationTypeToEventName(calculation_type), base::Value(message)); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h index cdd352797a6..d6b4e79a376 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.h @@ -113,6 +113,7 @@ class StorageHandler : public ::settings::SettingsPageUIHandler, calculator::AppsSizeCalculator apps_size_calculator_; calculator::CrostiniSizeCalculator crostini_size_calculator_; calculator::OtherUsersSizeCalculator other_users_size_calculator_; + calculator::DlcsSizeCalculator dlcs_size_calculator_; // Controls if the size of each storage item has been calculated. std::bitset<calculator::SizeCalculator::kCalculationTypeCount> 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 57c1ab89f3c..86e80c50226 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 @@ -23,6 +23,7 @@ #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/dbus/dlcservice/fake_dlcservice_client.h" #include "components/arc/arc_service_manager.h" #include "components/arc/test/fake_arc_session.h" #include "content/public/browser/web_ui_data_source.h" @@ -96,6 +97,8 @@ class StorageHandlerTest : public testing::Test { other_users_size_test_api_ = std::make_unique<calculator::OtherUsersSizeTestAPI>( handler_.get(), new calculator::OtherUsersSizeCalculator()); + dlcs_size_test_api_ = std::make_unique<calculator::DlcsSizeTestAPI>( + handler_.get(), new calculator::DlcsSizeCalculator()); // Create and register My files directory. // By emulating chromeos running, GetMyFilesFolderForProfile will return the @@ -109,6 +112,10 @@ class StorageHandlerTest : public testing::Test { file_manager::util::GetDownloadsMountPointName(profile_), storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(), my_files_path)); + + chromeos::DlcserviceClient::InitializeFake(); + fake_dlcservice_client_ = static_cast<chromeos::FakeDlcserviceClient*>( + chromeos::DlcserviceClient::Get()); } void TearDown() override { @@ -119,7 +126,9 @@ class StorageHandlerTest : public testing::Test { apps_size_test_api_.reset(); crostini_size_test_api_.reset(); other_users_size_test_api_.reset(); + dlcs_size_test_api_.reset(); chromeos::disks::DiskMountManager::Shutdown(); + chromeos::DlcserviceClient::Shutdown(); storage::ExternalMountPoints::GetSystemInstance()->RevokeAllFileSystems(); } @@ -148,8 +157,11 @@ class StorageHandlerTest : public testing::Test { !data->arg1()->GetAsString(&name)) { continue; } - if (name == event_name) + if (name == event_name) { + if (name == "storage-dlcs-size-changed") + return data->arg3(); return data->arg2(); + } } return nullptr; } @@ -191,6 +203,7 @@ class StorageHandlerTest : public testing::Test { content::BrowserTaskEnvironment task_environment_; std::unique_ptr<TestingProfileManager> profile_manager_; Profile* profile_; + chromeos::FakeDlcserviceClient* fake_dlcservice_client_; std::unique_ptr<calculator::SizeStatTestAPI> size_stat_test_api_; std::unique_ptr<calculator::MyFilesSizeTestAPI> my_files_size_test_api_; std::unique_ptr<calculator::BrowsingDataSizeTestAPI> @@ -198,6 +211,7 @@ class StorageHandlerTest : public testing::Test { std::unique_ptr<calculator::AppsSizeTestAPI> apps_size_test_api_; std::unique_ptr<calculator::CrostiniSizeTestAPI> crostini_size_test_api_; std::unique_ptr<calculator::OtherUsersSizeTestAPI> other_users_size_test_api_; + std::unique_ptr<calculator::DlcsSizeTestAPI> dlcs_size_test_api_; private: std::unique_ptr<arc::ArcServiceManager> arc_service_manager_; @@ -341,6 +355,26 @@ TEST_F(StorageHandlerTest, MyFilesSize) { EXPECT_EQ("81.4 KB", callback->GetString()); } +TEST_F(StorageHandlerTest, DlcsSize) { + dlcservice::DlcsWithContent dlcs_with_content; + auto* dlc_info = dlcs_with_content.add_dlc_infos(); + dlc_info->set_used_bytes_on_disk(1); + dlc_info = dlcs_with_content.add_dlc_infos(); + dlc_info->set_used_bytes_on_disk(2); + fake_dlcservice_client_->set_dlcs_with_content(dlcs_with_content); + + // Calculate DLC size. + dlcs_size_test_api_->StartCalculation(); + task_environment_.RunUntilIdle(); + + const base::Value* callback = + GetWebUICallbackMessage("storage-dlcs-size-changed"); + ASSERT_TRUE(callback) << "No 'storage-dlcs-size-changed' callback"; + + // Check return value. + EXPECT_EQ("3 B", callback->GetString()); +} + TEST_F(StorageHandlerTest, AppsExtensionsSize) { // The data for apps and extensions apps_size_test_api_installed from the // webstore is stored in the Extensions folder. Add data at a random location @@ -449,10 +483,22 @@ TEST_F(StorageHandlerTest, SystemSize) { ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed")); // Simulate crostini size callback. - crostini_size_test_api_->SimulateOnGetCrostiniSize(70 * GB); + crostini_size_test_api_->SimulateOnGetCrostiniSize(50 * GB); callback = GetWebUICallbackMessage("storage-crostini-size-changed"); ASSERT_TRUE(callback) << "No 'storage-crostini-size-changed' callback"; - EXPECT_EQ("70.0 GB", callback->GetString()); + EXPECT_EQ("50.0 GB", callback->GetString()); + ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed")); + + // Simulate DLC size callback + dlcservice::DlcsWithContent dlcs_with_content; + auto* dlc_info = dlcs_with_content.add_dlc_infos(); + dlc_info->set_used_bytes_on_disk(20 * GB); + dlc_info = dlcs_with_content.add_dlc_infos(); + dlcs_size_test_api_->SimulateOnGetExistingDlcs(dlcservice::kErrorNone, + dlcs_with_content); + callback = GetWebUICallbackMessage("storage-dlcs-size-changed"); + ASSERT_TRUE(callback) << "No 'storage-dlcs-size-changed' callback"; + EXPECT_EQ("20.0 GB", callback->GetString()); ASSERT_FALSE(GetWebUICallbackMessage("storage-system-size-changed")); // Simulate other users size callback. No callback message until the sizes of diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.cc new file mode 100644 index 00000000000..3cf8646c001 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.cc @@ -0,0 +1,53 @@ +// Copyright 2020 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/fake_hierarchy.h" + +#include <utility> + +#include "chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.h" + +namespace chromeos { +namespace settings { + +FakeHierarchy::FakeHierarchy(const OsSettingsSections* sections) + : Hierarchy(sections) {} + +FakeHierarchy::~FakeHierarchy() = default; + +void FakeHierarchy::AddSubpageMetadata( + int name_message_id, + mojom::Section section, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters, + base::Optional<mojom::Subpage> parent_subpage) { + auto pair = subpage_map_.emplace( + std::piecewise_construct, std::forward_as_tuple(subpage), + std::forward_as_tuple(name_message_id, section, subpage, icon, + default_rank, url_path_with_parameters, this)); + DCHECK(pair.second); + pair.first->second.parent_subpage = parent_subpage; +} + +void FakeHierarchy::AddSettingMetadata( + mojom::Section section, + mojom::Setting setting, + base::Optional<mojom::Subpage> parent_subpage) { + auto pair = setting_map_.emplace(setting, section); + DCHECK(pair.second); + pair.first->second.primary.second = parent_subpage; +} + +std::string FakeHierarchy::ModifySearchResultUrl( + mojom::Section section, + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const { + return FakeOsSettingsSection::ModifySearchResultUrl(section, url_to_modify); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.h b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.h new file mode 100644 index 00000000000..d0fbf813ff3 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.h @@ -0,0 +1,50 @@ +// Copyright 2020 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_FAKE_HIERARCHY_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FAKE_HIERARCHY_H_ + +#include "base/optional.h" +#include "chrome/browser/ui/webui/settings/chromeos/hierarchy.h" + +namespace chromeos { +namespace settings { + +class OsSettingsSections; + +// Fake Hierarchy implementation. Note that this class currently does not +// provide "alternate settings location" functionality. +class FakeHierarchy : public Hierarchy { + public: + explicit FakeHierarchy(const OsSettingsSections* sections); + FakeHierarchy(const FakeHierarchy& other) = delete; + FakeHierarchy& operator=(const FakeHierarchy& other) = delete; + ~FakeHierarchy() override; + + void AddSubpageMetadata( + int name_message_id, + mojom::Section section, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters, + base::Optional<mojom::Subpage> parent_subpage = base::nullopt); + void AddSettingMetadata( + mojom::Section section, + mojom::Setting setting, + base::Optional<mojom::Subpage> parent_subpage = base::nullopt); + + private: + // Hierarchy: + std::string ModifySearchResultUrl( + mojom::Section section, + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const override; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FAKE_HIERARCHY_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.cc new file mode 100644 index 00000000000..473287ebec0 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.cc @@ -0,0 +1,52 @@ +// Copyright 2020 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/fake_os_settings_section.h" + +#include <sstream> + +#include "chrome/grit/generated_resources.h" + +namespace chromeos { +namespace settings { + +FakeOsSettingsSection::FakeOsSettingsSection(mojom::Section section) + : section_(section) {} + +FakeOsSettingsSection::~FakeOsSettingsSection() = default; + +int FakeOsSettingsSection::GetSectionNameMessageId() const { + return IDS_INTERNAL_APP_SETTINGS; +} + +mojom::Section FakeOsSettingsSection::GetSection() const { + return section_; +} + +mojom::SearchResultIcon FakeOsSettingsSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kWifi; +} + +std::string FakeOsSettingsSection::GetSectionPath() const { + return std::string(); +} + +std::string FakeOsSettingsSection::ModifySearchResultUrl( + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const { + return ModifySearchResultUrl(section_, url_to_modify); +} + +// static +std::string FakeOsSettingsSection::ModifySearchResultUrl( + mojom::Section section, + const std::string& url_to_modify) { + std::stringstream ss; + ss << section << "::" << url_to_modify; + return ss.str(); +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.h new file mode 100644 index 00000000000..4a58417228a --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.h @@ -0,0 +1,56 @@ +// Copyright 2020 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_FAKE_OS_SETTINGS_SECTION_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FAKE_OS_SETTINGS_SECTION_H_ + +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" + +namespace chromeos { +namespace settings { + +// Fake OsSettingsSection implementation. +class FakeOsSettingsSection : public OsSettingsSection { + public: + explicit FakeOsSettingsSection(mojom::Section section); + ~FakeOsSettingsSection() override; + + FakeOsSettingsSection(const FakeOsSettingsSection& other) = delete; + FakeOsSettingsSection& operator=(const FakeOsSettingsSection& other) = delete; + + mojom::Section section() { return section_; } + + // OsSettingsSection: + void AddLoadTimeData(content::WebUIDataSource* html_source) override {} + void RegisterHierarchy(HierarchyGenerator* generator) const override {} + + // Returns the settings app name as a default value. + int GetSectionNameMessageId() const override; + + mojom::Section GetSection() const override; + + // These functions return arbitrary dummy values. + mojom::SearchResultIcon GetSectionIcon() const override; + std::string GetSectionPath() const override; + + // Prepends the section name and "::" to the URL in |concept|. For example, if + // the URL is "networkDetails" and the section is mojom::Section::kNetwork, + // the returned URL is "Section::kNetwork::networkDetails". + std::string ModifySearchResultUrl( + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const override; + + // Static function used to implement the function above. + static std::string ModifySearchResultUrl(mojom::Section section, + const std::string& url_to_modify); + + private: + const mojom::Section section_; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FAKE_OS_SETTINGS_SECTION_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.cc new file mode 100644 index 00000000000..253d965f65e --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.cc @@ -0,0 +1,24 @@ +// Copyright 2020 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/fake_os_settings_sections.h" + +#include "chrome/browser/ui/webui/settings/chromeos/constants/constants_util.h" +#include "chrome/browser/ui/webui/settings/chromeos/fake_os_settings_section.h" + +namespace chromeos { +namespace settings { + +FakeOsSettingsSections::FakeOsSettingsSections() : OsSettingsSections() { + for (const auto& section : constants::AllSections()) { + auto fake_section = std::make_unique<FakeOsSettingsSection>(section); + sections_map_[section] = fake_section.get(); + sections_.push_back(std::move(fake_section)); + } +} + +FakeOsSettingsSections::~FakeOsSettingsSections() = default; + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.h b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.h new file mode 100644 index 00000000000..2c148a72a69 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.h @@ -0,0 +1,26 @@ +// Copyright 2020 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_FAKE_OS_SETTINGS_SECTIONS_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FAKE_OS_SETTINGS_SECTIONS_H_ + +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h" + +namespace chromeos { +namespace settings { + +// Collection of FakeOsSettingsSections. +class FakeOsSettingsSections : public OsSettingsSections { + public: + FakeOsSettingsSections(); + FakeOsSettingsSections(const FakeOsSettingsSections& other) = delete; + FakeOsSettingsSections& operator=(const FakeOsSettingsSections& other) = + delete; + ~FakeOsSettingsSections() override; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FAKE_OS_SETTINGS_SECTIONS_H_ diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.cc index 3b1788101b1..7163b682b59 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.cc @@ -52,7 +52,8 @@ const std::vector<SearchConcept>& GetFilesSearchConcepts() { FilesSection::FilesSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { - registry()->AddSearchTags(GetFilesSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetFilesSearchConcepts()); } FilesSection::~FilesSection() = default; @@ -102,5 +103,31 @@ void FilesSection::AddHandlers(content::WebUI* web_ui) { profile(), base::DoNothing())); } +int FilesSection::GetSectionNameMessageId() const { + return IDS_OS_SETTINGS_FILES; +} + +mojom::Section FilesSection::GetSection() const { + return mojom::Section::kFiles; +} + +mojom::SearchResultIcon FilesSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kFolder; +} + +std::string FilesSection::GetSectionPath() const { + return mojom::kFilesSectionPath; +} + +void FilesSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kGoogleDriveConnection); + + // Network file shares. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_DOWNLOADS_SMB_SHARES, mojom::Subpage::kNetworkFileShares, + mojom::SearchResultIcon::kFolder, mojom::SearchResultDefaultRank::kMedium, + mojom::kNetworkFileSharesSubpagePath); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.h index 635bcb9abc0..38b9dc0b236 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/files_section.h @@ -26,6 +26,11 @@ class FilesSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc index 9ef5ec87581..337e66bd4bb 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc @@ -6,8 +6,8 @@ #include <utility> -#include "ash/public/cpp/assistant/assistant_settings.h" #include "ash/public/cpp/assistant/assistant_setup.h" +#include "ash/public/cpp/assistant/controller/assistant_controller.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/values.h" @@ -74,7 +74,7 @@ void GoogleAssistantHandler::RegisterMessages() { void GoogleAssistantHandler::HandleShowGoogleAssistantSettings( const base::ListValue* args) { CHECK_EQ(0U, args->GetSize()); - ash::OpenAssistantSettings(); + ash::AssistantController::Get()->OpenAssistantSettings(); } void GoogleAssistantHandler::HandleRetrainVoiceModel( diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/hierarchy.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/hierarchy.cc new file mode 100644 index 00000000000..7eef6651e04 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/hierarchy.cc @@ -0,0 +1,318 @@ +// Copyright 2020 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/hierarchy.h" + +#include <utility> + +#include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/webui/settings/chromeos/constants/constants_util.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" + +namespace chromeos { +namespace settings { +namespace { + +// Used to generate localized names. +constexpr double kDummyRelevanceScore = 0; + +} // namespace + +class Hierarchy::PerSectionHierarchyGenerator + : public OsSettingsSection::HierarchyGenerator { + public: + PerSectionHierarchyGenerator(mojom::Section section, + bool* only_contains_link_to_subpage, + Hierarchy* hierarchy) + : section_(section), + only_contains_link_to_subpage_(only_contains_link_to_subpage), + hierarchy_(hierarchy) {} + + void RegisterTopLevelSubpage( + int name_message_id, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters) override { + Hierarchy::SubpageMetadata& metadata = GetSubpageMetadata( + name_message_id, subpage, icon, default_rank, url_path_with_parameters); + CHECK_EQ(section_, metadata.section) + << "Subpage registered in multiple sections: " << subpage; + + ++num_top_level_subpages_so_far_; + + // If there are multiple top-level subpages, the section contains more than + // just a link to a subpage. + if (num_top_level_subpages_so_far_ > 1u) + *only_contains_link_to_subpage_ = false; + } + + void RegisterNestedSubpage( + int name_message_id, + mojom::Subpage subpage, + mojom::Subpage parent_subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters) override { + Hierarchy::SubpageMetadata& metadata = GetSubpageMetadata( + name_message_id, subpage, icon, default_rank, url_path_with_parameters); + CHECK_EQ(section_, metadata.section) + << "Subpage registered in multiple sections: " << subpage; + CHECK(!metadata.parent_subpage) + << "Subpage has multiple registered parent subpages: " << subpage; + metadata.parent_subpage = parent_subpage; + } + + void RegisterTopLevelSetting(mojom::Setting setting) override { + Hierarchy::SettingMetadata& metadata = GetSettingMetadata(setting); + CHECK_EQ(section_, metadata.primary.first) + << "Setting registered in multiple primary sections: " << setting; + CHECK(!metadata.primary.second) + << "Setting registered in multiple primary locations: " << setting; + + // If a top-level setting exists, the section contains more than just a link + // link to a subpage. + *only_contains_link_to_subpage_ = false; + } + + void RegisterNestedSetting(mojom::Setting setting, + mojom::Subpage subpage) override { + Hierarchy::SettingMetadata& metadata = GetSettingMetadata(setting); + CHECK_EQ(section_, metadata.primary.first) + << "Setting registered in multiple primary sections: " << setting; + CHECK(!metadata.primary.second) + << "Setting registered in multiple primary locations: " << setting; + metadata.primary.second = subpage; + } + + void RegisterTopLevelAltSetting(mojom::Setting setting) override { + Hierarchy::SettingMetadata& metadata = GetSettingMetadata(setting); + CHECK(metadata.primary.first != section_ || metadata.primary.second) + << "Setting's primary and alternate locations are identical: " + << setting; + for (const auto& alternate : metadata.alternates) { + CHECK(alternate.first != section_ || alternate.second) + << "Setting has multiple identical alternate locations: " << setting; + } + metadata.alternates.emplace_back(section_, /*subpage=*/base::nullopt); + + // If a top-level setting exists, the section contains more than just a link + // link to a subpage. + *only_contains_link_to_subpage_ = false; + } + + void RegisterNestedAltSetting(mojom::Setting setting, + mojom::Subpage subpage) override { + Hierarchy::SettingMetadata& metadata = GetSettingMetadata(setting); + CHECK(metadata.primary.first != section_ || + metadata.primary.second != subpage) + << "Setting's primary and alternate locations are identical: " + << setting; + for (const auto& alternate : metadata.alternates) { + CHECK(alternate.first != section_ || alternate.second != subpage) + << "Setting has multiple identical alternate locations: " << setting; + } + metadata.alternates.emplace_back(section_, subpage); + } + + private: + Hierarchy::SubpageMetadata& GetSubpageMetadata( + int name_message_id, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters) { + auto& subpage_map = hierarchy_->subpage_map_; + + auto it = subpage_map.find(subpage); + + // Metadata already exists; return it. + if (it != subpage_map.end()) + return it->second; + + // Metadata does not exist yet; insert then return it. + auto pair = subpage_map.emplace( + std::piecewise_construct, std::forward_as_tuple(subpage), + std::forward_as_tuple(name_message_id, section_, subpage, icon, + default_rank, url_path_with_parameters, + hierarchy_)); + CHECK(pair.second); + return pair.first->second; + } + + Hierarchy::SettingMetadata& GetSettingMetadata(mojom::Setting setting) { + auto& settings_map = hierarchy_->setting_map_; + + auto it = settings_map.find(setting); + + // Metadata already exists; return it. + if (it != settings_map.end()) + return it->second; + + // Metadata does not exist yet; insert then return it. + auto pair = settings_map.emplace(setting, section_); + CHECK(pair.second); + return pair.first->second; + } + + size_t num_top_level_subpages_so_far_ = 0u; + mojom::Section section_; + bool* only_contains_link_to_subpage_; + Hierarchy* hierarchy_; +}; + +// Note: |only_contains_link_to_subpage| starts out as true and is set to false +// if other content is added. +Hierarchy::SectionMetadata::SectionMetadata(mojom::Section section, + const Hierarchy* hierarchy) + : only_contains_link_to_subpage(true), + section_(section), + hierarchy_(hierarchy) {} + +Hierarchy::SectionMetadata::~SectionMetadata() = default; + +mojom::SearchResultPtr Hierarchy::SectionMetadata::ToSearchResult( + double relevance_score) const { + return hierarchy_->sections_->GetSection(section_) + ->GenerateSectionSearchResult(relevance_score); +} + +Hierarchy::SubpageMetadata::SubpageMetadata( + int name_message_id, + mojom::Section section, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters, + const Hierarchy* hierarchy) + : section(section), + subpage_(subpage), + name_message_id_(name_message_id), + icon_(icon), + default_rank_(default_rank), + unmodified_url_path_with_parameters_(url_path_with_parameters), + hierarchy_(hierarchy) {} + +Hierarchy::SubpageMetadata::~SubpageMetadata() = default; + +mojom::SearchResultPtr Hierarchy::SubpageMetadata::ToSearchResult( + double relevance_score) const { + return mojom::SearchResult::New( + /*result_text=*/l10n_util::GetStringUTF16(name_message_id_), + /*canonical_result_text=*/l10n_util::GetStringUTF16(name_message_id_), + hierarchy_->ModifySearchResultUrl( + section, mojom::SearchResultType::kSubpage, {.subpage = subpage_}, + unmodified_url_path_with_parameters_), + icon_, relevance_score, + hierarchy_->GenerateAncestorHierarchyStrings(subpage_), default_rank_, + /*was_generated_from_text_match=*/false, + mojom::SearchResultType::kSubpage, + mojom::SearchResultIdentifier::NewSubpage(subpage_)); +} + +Hierarchy::SettingMetadata::SettingMetadata(mojom::Section primary_section) + : primary(primary_section, /*subpage=*/base::nullopt) {} + +Hierarchy::SettingMetadata::~SettingMetadata() = default; + +Hierarchy::Hierarchy(const OsSettingsSections* sections) : sections_(sections) { + for (const auto& section : constants::AllSections()) { + auto pair = section_map_.emplace(std::piecewise_construct, + std::forward_as_tuple(section), + std::forward_as_tuple(section, this)); + CHECK(pair.second); + + PerSectionHierarchyGenerator generator( + section, &pair.first->second.only_contains_link_to_subpage, this); + sections->GetSection(section)->RegisterHierarchy(&generator); + } +} + +Hierarchy::~Hierarchy() = default; + +const Hierarchy::SectionMetadata& Hierarchy::GetSectionMetadata( + mojom::Section section) const { + const auto it = section_map_.find(section); + CHECK(it != section_map_.end()) + << "Section missing from settings hierarchy: " << section; + return it->second; +} + +const Hierarchy::SubpageMetadata& Hierarchy::GetSubpageMetadata( + mojom::Subpage subpage) const { + const auto it = subpage_map_.find(subpage); + CHECK(it != subpage_map_.end()) + << "Subpage missing from settings hierarchy: " << subpage; + return it->second; +} + +const Hierarchy::SettingMetadata& Hierarchy::GetSettingMetadata( + mojom::Setting setting) const { + const auto it = setting_map_.find(setting); + CHECK(it != setting_map_.end()) + << "Setting missing from settings hierarchy: " << setting; + return it->second; +} + +std::string Hierarchy::ModifySearchResultUrl( + mojom::Section section, + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const { + return sections_->GetSection(section)->ModifySearchResultUrl(type, id, + url_to_modify); +} + +std::vector<base::string16> Hierarchy::GenerateAncestorHierarchyStrings( + mojom::Subpage subpage) const { + const SubpageMetadata& subpage_metadata = GetSubpageMetadata(subpage); + + // Top-level subpage; simply return section hierarchy. + if (!subpage_metadata.parent_subpage) + return GenerateHierarchyStrings(subpage_metadata.section); + + // Nested subpage; use recursive call, then append parent subpage name itself. + std::vector<base::string16> hierarchy_strings = + GenerateAncestorHierarchyStrings(*subpage_metadata.parent_subpage); + hierarchy_strings.push_back( + GetSubpageMetadata(*subpage_metadata.parent_subpage) + .ToSearchResult(kDummyRelevanceScore) + ->result_text); + return hierarchy_strings; +} + +std::vector<base::string16> Hierarchy::GenerateAncestorHierarchyStrings( + mojom::Setting setting) const { + const SettingMetadata& setting_metadata = GetSettingMetadata(setting); + + // Top-level setting; simply return section hierarchy. + if (!setting_metadata.primary.second) + return GenerateHierarchyStrings(setting_metadata.primary.first); + + // Nested setting; use subpage ancestors, then append subpage name itself. + std::vector<base::string16> hierarchy_strings = + GenerateAncestorHierarchyStrings(*setting_metadata.primary.second); + hierarchy_strings.push_back( + GetSubpageMetadata(*setting_metadata.primary.second) + .ToSearchResult(kDummyRelevanceScore) + ->result_text); + return hierarchy_strings; +} + +std::vector<base::string16> Hierarchy::GenerateHierarchyStrings( + mojom::Section section) const { + std::vector<base::string16> hierarchy_strings; + hierarchy_strings.push_back( + l10n_util::GetStringUTF16(IDS_INTERNAL_APP_SETTINGS)); + hierarchy_strings.push_back(GetSectionMetadata(section) + .ToSearchResult(kDummyRelevanceScore) + ->result_text); + return hierarchy_strings; +} + +} // namespace settings +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/hierarchy.h b/chromium/chrome/browser/ui/webui/settings/chromeos/hierarchy.h new file mode 100644 index 00000000000..14b915670d4 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/hierarchy.h @@ -0,0 +1,171 @@ +// Copyright 2020 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_HIERARCHY_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_HIERARCHY_H_ + +#include <unordered_map> +#include <utility> +#include <vector> + +#include "base/optional.h" +#include "base/strings/string16.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/os_settings_identifier.h" +#include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom.h" + +namespace chromeos { +namespace settings { + +class OsSettingsSections; + +// Tracks the OS settings page hierarchy. Settings is composed of a group of +// sections containing subpages and/or settings, and this class provides +// metadata for where these subpages/settings reside and what localized strings +// are used to describe them. +// +// A subpage can either be a direct child of a section or can be a nested +// subpage, meaning that its parent is another subpage. +// +// A setting can either be embedded as a direct child of a section or can be +// a child of a subpage. Additionally, some settings appear in multiple places. +// For example, the Wi-Fi on/off toggle appears in both the top-level Network +// section as well as the Wi-Fi subpage. In cases like this, we consider the +// "primary" location as the more-targeted one - in this example, the Wi-Fi +// subpage is the primary location of the toggle since it is more specific to +// Wi-Fi, and the alternate location is the one embedded in the Network section. +class Hierarchy { + public: + explicit Hierarchy(const OsSettingsSections* sections); + Hierarchy(const Hierarchy& other) = delete; + Hierarchy& operator=(const Hierarchy& other) = delete; + virtual ~Hierarchy(); + + class SectionMetadata { + public: + SectionMetadata(mojom::Section section, const Hierarchy* hierarchy); + ~SectionMetadata(); + + // Whether the only contents of the section is a link to a subpage. + bool only_contains_link_to_subpage; + + // Generates a search result for this section, using the canonical search + // tag as the search result text. |relevance_score| must be passed by the + // client, since this result is being created manually instead of via query + // matching. + mojom::SearchResultPtr ToSearchResult(double relevance_score) const; + + private: + mojom::Section section_; + const Hierarchy* hierarchy_; + }; + + class SubpageMetadata { + public: + SubpageMetadata(int name_message_id, + mojom::Section section, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters, + const Hierarchy* hierarchy); + ~SubpageMetadata(); + + // The section in which the subpage appears. + mojom::Section section; + + // The parent subpage, if applicable. Only applies to nested subpages. + base::Optional<mojom::Subpage> parent_subpage; + + // Generates a search result for this subpage, using the canonical search + // tag as the search result text. |relevance_score| must be passed by the + // client, since this result is being created manually instead of via query + // matching. + mojom::SearchResultPtr ToSearchResult(double relevance_score) const; + + private: + mojom::Subpage subpage_; + + // Message ID corresponding to the localized string used to describe this + // subpage. + int name_message_id_; + + // Icon used for this subpage. + mojom::SearchResultIcon icon_; + + // Default rank; used to order returned results. + mojom::SearchResultDefaultRank default_rank_; + + // Static URL path, which may need to be modified via + // |modify_url_callback_|. + std::string unmodified_url_path_with_parameters_; + + const Hierarchy* hierarchy_; + }; + + // The location of a setting, which includes its section and, if applicable, + // its subpage. Some settings are embedded directly into the section and have + // no associated subpage. + using SettingLocation = + std::pair<mojom::Section, base::Optional<mojom::Subpage>>; + + struct SettingMetadata { + explicit SettingMetadata(mojom::Section primary_section); + ~SettingMetadata(); + + // The primary location, as described above. + SettingLocation primary; + + // Alternate locations, as described above. Empty if the setting has no + // alternate location. + std::vector<SettingLocation> alternates; + }; + + const SectionMetadata& GetSectionMetadata(mojom::Section section) const; + const SubpageMetadata& GetSubpageMetadata(mojom::Subpage subpage) const; + const SettingMetadata& GetSettingMetadata(mojom::Setting setting) const; + + // Generates a list of names of the ancestor sections/subpages for |subpage|. + // The list contains the Settings app name, the section name and, if + // applicable, parent subpage names. Names returned in this list are all + // localized string16s which can be displayed in the UI (e.g., as + // breadcrumbs). + // + // Example 1 - Wi-Fi Networks subpage (no parent subpage): + // ["Settings", "Network"] + // Example 2 - External storage (has parent subpage): + // ["Settings", "Device", "Storage management"] + std::vector<base::string16> GenerateAncestorHierarchyStrings( + mojom::Subpage subpage) const; + + // Same as above, but for settings. + std::vector<base::string16> GenerateAncestorHierarchyStrings( + mojom::Setting setting) const; + + protected: + std::unordered_map<mojom::Section, SectionMetadata> section_map_; + std::unordered_map<mojom::Subpage, SubpageMetadata> subpage_map_; + std::unordered_map<mojom::Setting, SettingMetadata> setting_map_; + + private: + class PerSectionHierarchyGenerator; + + // Generates an array with the Settings app name and |section|'s name. + std::vector<base::string16> GenerateHierarchyStrings( + mojom::Section section) const; + + virtual std::string ModifySearchResultUrl( + mojom::Section section, + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const; + + const OsSettingsSections* sections_; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_HIERARCHY_H_ 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 c21b0002fb8..69248ed127e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.cc @@ -8,11 +8,13 @@ #include "ash/public/cpp/network_config_service.h" #include "base/bind.h" #include "base/no_destructor.h" +#include "base/strings/stringprintf.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" #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/chromium_strings.h" @@ -32,7 +34,7 @@ const std::vector<SearchConcept>& GetNetworkSearchConcepts() { {IDS_OS_SETTINGS_TAG_NETWORK_SETTINGS, mojom::kNetworkSectionPath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSection, {.section = mojom::Section::kNetwork}, {IDS_OS_SETTINGS_TAG_NETWORK_SETTINGS_ALT1, SearchConcept::kAltTagEnd}}, @@ -57,7 +59,7 @@ const std::vector<SearchConcept>& GetEthernetConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_CONFIGURE_IP_AUTOMATICALLY, mojom::kEthernetDetailsSubpagePath, mojom::SearchResultIcon::kEthernet, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kEthernetAutoConfigureIp}, {IDS_OS_SETTINGS_TAG_CONFIGURE_IP_AUTOMATICALLY_ALT1, @@ -66,7 +68,7 @@ const std::vector<SearchConcept>& GetEthernetConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_NAME_SERVERS, mojom::kEthernetDetailsSubpagePath, mojom::SearchResultIcon::kEthernet, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kEthernetDns}, {IDS_OS_SETTINGS_TAG_NAME_SERVERS_ALT1, @@ -74,7 +76,7 @@ const std::vector<SearchConcept>& GetEthernetConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_PROXY, mojom::kEthernetDetailsSubpagePath, mojom::SearchResultIcon::kEthernet, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kEthernetProxy}, {IDS_OS_SETTINGS_TAG_PROXY_ALT1, IDS_OS_SETTINGS_TAG_PROXY_ALT2, @@ -92,12 +94,11 @@ const std::vector<SearchConcept>& GetWifiSearchConcepts() { mojom::SearchResultDefaultRank::kHigh, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kWifiNetworks}, - {IDS_OS_SETTINGS_TAG_WIFI_ALT1, IDS_OS_SETTINGS_TAG_WIFI_ALT2, - SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_WIFI_ALT1, SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_KNOWN_NETWORKS, mojom::kKnownNetworksSubpagePath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kKnownNetworks}, {IDS_OS_SETTINGS_TAG_KNOWN_NETWORKS_ALT1, @@ -115,6 +116,12 @@ const std::vector<SearchConcept>& GetWifiOnSearchConcepts() { mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kWifiOnOff}, {IDS_OS_SETTINGS_TAG_WIFI_TURN_OFF_ALT1, SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_ADD_WIFI, + mojom::kWifiNetworksSubpagePath, + mojom::SearchResultIcon::kWifi, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kWifiAddNetwork}}, }); return *tags; } @@ -143,17 +150,11 @@ const std::vector<SearchConcept>& GetWifiConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_PREFER_WIFI_NETWORK, mojom::kWifiDetailsSubpagePath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kPreferWifiNetwork}, {IDS_OS_SETTINGS_TAG_PREFER_WIFI_NETWORK_ALT1, SearchConcept::kAltTagEnd}}, - {IDS_OS_SETTINGS_TAG_WIFI_CONFIGURE, - mojom::kWifiDetailsSubpagePath, - mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kConfigureWifi}}, {IDS_OS_SETTINGS_TAG_FORGET_WIFI, mojom::kWifiDetailsSubpagePath, mojom::SearchResultIcon::kWifi, @@ -163,7 +164,7 @@ const std::vector<SearchConcept>& GetWifiConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_CONFIGURE_IP_AUTOMATICALLY, mojom::kWifiDetailsSubpagePath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kWifiAutoConfigureIp}, {IDS_OS_SETTINGS_TAG_CONFIGURE_IP_AUTOMATICALLY_ALT1, @@ -172,7 +173,7 @@ const std::vector<SearchConcept>& GetWifiConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_NAME_SERVERS, mojom::kWifiDetailsSubpagePath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kWifiDns}, {IDS_OS_SETTINGS_TAG_NAME_SERVERS_ALT1, @@ -180,7 +181,7 @@ const std::vector<SearchConcept>& GetWifiConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_PROXY, mojom::kWifiDetailsSubpagePath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kWifiProxy}, {IDS_OS_SETTINGS_TAG_PROXY_ALT1, IDS_OS_SETTINGS_TAG_PROXY_ALT2, @@ -189,7 +190,7 @@ const std::vector<SearchConcept>& GetWifiConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_AUTO_CONNECT_NETWORK, mojom::kWifiDetailsSubpagePath, mojom::SearchResultIcon::kWifi, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kWifiAutoConnectToNetwork}, {IDS_OS_SETTINGS_TAG_AUTO_CONNECT_NETWORK_ALT1, @@ -198,6 +199,18 @@ const std::vector<SearchConcept>& GetWifiConnectedSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetWifiMeteredSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_SETTINGS_INTERNET_NETWORK_METERED, + mojom::kWifiDetailsSubpagePath, + mojom::SearchResultIcon::kWifi, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kWifiMetered}}, + }); + return *tags; +} + const std::vector<SearchConcept>& GetCellularSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_CELLULAR, @@ -207,14 +220,7 @@ const std::vector<SearchConcept>& GetCellularSearchConcepts() { mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kCellularDetails}, {IDS_OS_SETTINGS_TAG_CELLULAR_ALT1, IDS_OS_SETTINGS_TAG_CELLULAR_ALT2, - IDS_OS_SETTINGS_TAG_CELLULAR_ALT3, IDS_OS_SETTINGS_TAG_CELLULAR_ALT4, - SearchConcept::kAltTagEnd}}, - }); - return *tags; -} - -const std::vector<SearchConcept>& GetCellularOnSearchConcepts() { - static const base::NoDestructor<std::vector<SearchConcept>> tags({ + IDS_OS_SETTINGS_TAG_CELLULAR_ALT3, SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_CELLULAR_SIM_LOCK, mojom::kCellularDetailsSubpagePath, mojom::SearchResultIcon::kCellular, @@ -228,6 +234,18 @@ const std::vector<SearchConcept>& GetCellularOnSearchConcepts() { mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kCellularRoaming}}, + {IDS_OS_SETTINGS_TAG_CELLULAR_APN, + mojom::kCellularDetailsSubpagePath, + mojom::SearchResultIcon::kCellular, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kCellularApn}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetCellularOnSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_CELLULAR_TURN_OFF, mojom::kNetworkSectionPath, mojom::SearchResultIcon::kCellular, @@ -235,12 +253,6 @@ const std::vector<SearchConcept>& GetCellularOnSearchConcepts() { mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kMobileOnOff}, {IDS_OS_SETTINGS_TAG_CELLULAR_TURN_OFF_ALT1, SearchConcept::kAltTagEnd}}, - {IDS_OS_SETTINGS_TAG_CELLULAR_APN, - mojom::kCellularDetailsSubpagePath, - mojom::SearchResultIcon::kCellular, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kCellularApn}}, }); return *tags; } @@ -269,7 +281,7 @@ const std::vector<SearchConcept>& GetCellularConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_CONFIGURE_IP_AUTOMATICALLY, mojom::kCellularDetailsSubpagePath, mojom::SearchResultIcon::kCellular, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kCellularAutoConfigureIp}, {IDS_OS_SETTINGS_TAG_CONFIGURE_IP_AUTOMATICALLY_ALT1, @@ -278,7 +290,7 @@ const std::vector<SearchConcept>& GetCellularConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_NAME_SERVERS, mojom::kCellularDetailsSubpagePath, mojom::SearchResultIcon::kCellular, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kCellularDns}, {IDS_OS_SETTINGS_TAG_NAME_SERVERS_ALT1, @@ -286,7 +298,7 @@ const std::vector<SearchConcept>& GetCellularConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_PROXY, mojom::kCellularDetailsSubpagePath, mojom::SearchResultIcon::kCellular, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kCellularProxy}, {IDS_OS_SETTINGS_TAG_PROXY_ALT1, IDS_OS_SETTINGS_TAG_PROXY_ALT2, @@ -295,7 +307,7 @@ const std::vector<SearchConcept>& GetCellularConnectedSearchConcepts() { {IDS_OS_SETTINGS_TAG_AUTO_CONNECT_NETWORK, mojom::kCellularDetailsSubpagePath, mojom::SearchResultIcon::kCellular, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kCellularAutoConnectToNetwork}, {IDS_OS_SETTINGS_TAG_AUTO_CONNECT_NETWORK_ALT1, @@ -304,6 +316,18 @@ const std::vector<SearchConcept>& GetCellularConnectedSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetCellularMeteredSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_SETTINGS_INTERNET_NETWORK_METERED, + mojom::kCellularDetailsSubpagePath, + mojom::SearchResultIcon::kCellular, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kCellularMetered}}, + }); + return *tags; +} + const std::vector<SearchConcept>& GetInstantTetheringSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_INSTANT_MOBILE_NETWORKS, @@ -374,6 +398,52 @@ const std::vector<SearchConcept>& GetVpnConnectedSearchConcepts() { return *tags; } +const std::vector<mojom::Setting>& GetEthernetDetailsSettings() { + static const base::NoDestructor<std::vector<mojom::Setting>> settings({ + mojom::Setting::kConfigureEthernet, + mojom::Setting::kEthernetAutoConfigureIp, + mojom::Setting::kEthernetDns, + mojom::Setting::kEthernetProxy, + }); + return *settings; +} + +const std::vector<mojom::Setting>& GetWifiDetailsSettings() { + static const base::NoDestructor<std::vector<mojom::Setting>> settings({ + mojom::Setting::kDisconnectWifiNetwork, + mojom::Setting::kPreferWifiNetwork, + mojom::Setting::kForgetWifiNetwork, + mojom::Setting::kWifiAutoConfigureIp, + mojom::Setting::kWifiDns, + mojom::Setting::kWifiProxy, + mojom::Setting::kWifiAutoConnectToNetwork, + mojom::Setting::kWifiMetered, + }); + return *settings; +} + +const std::vector<mojom::Setting>& GetCellularDetailsSettings() { + static const base::NoDestructor<std::vector<mojom::Setting>> settings({ + mojom::Setting::kCellularSimLock, + mojom::Setting::kCellularRoaming, + mojom::Setting::kCellularApn, + mojom::Setting::kDisconnectCellularNetwork, + mojom::Setting::kCellularAutoConfigureIp, + mojom::Setting::kCellularDns, + mojom::Setting::kCellularProxy, + mojom::Setting::kCellularAutoConnectToNetwork, + mojom::Setting::kCellularMetered, + }); + return *settings; +} + +const std::vector<mojom::Setting>& GetTetherDetailsSettings() { + static const base::NoDestructor<std::vector<mojom::Setting>> settings({ + mojom::Setting::kDisconnectTetherNetwork, + }); + return *settings; +} + bool IsConnected(network_config::mojom::ConnectionStateType connection_state) { return connection_state == network_config::mojom::ConnectionStateType::kOnline || @@ -381,13 +451,49 @@ bool IsConnected(network_config::mojom::ConnectionStateType connection_state) { network_config::mojom::ConnectionStateType::kConnected; } +bool IsPartOfDetailsSubpage(mojom::SearchResultType type, + OsSettingsIdentifier id, + mojom::Subpage details_subpage) { + switch (type) { + case mojom::SearchResultType::kSection: + // Applies to a section, not a details subpage. + return false; + + case mojom::SearchResultType::kSubpage: + return id.subpage == details_subpage; + + case mojom::SearchResultType::kSetting: { + const mojom::Setting& setting = id.setting; + switch (details_subpage) { + case mojom::Subpage::kEthernetDetails: + return base::Contains(GetEthernetDetailsSettings(), setting); + case mojom::Subpage::kWifiDetails: + return base::Contains(GetWifiDetailsSettings(), setting); + case mojom::Subpage::kCellularDetails: + return base::Contains(GetCellularDetailsSettings(), setting); + case mojom::Subpage::kTetherDetails: + return base::Contains(GetTetherDetailsSettings(), setting); + default: + return false; + } + } + } +} + +std::string GetDetailsSubpageUrl(const std::string& url_to_modify, + const std::string& guid) { + return base::StringPrintf("%s?guid=%s", url_to_modify.c_str(), guid.c_str()); +} + } // namespace InternetSection::InternetSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + // General network search tags are always added. - registry()->AddSearchTags(GetNetworkSearchConcepts()); + updater.AddSearchTags(GetNetworkSearchConcepts()); // Receive updates when devices (e.g., Ethernet, Wi-Fi) go on/offline. ash::GetNetworkConfigService( @@ -396,7 +502,7 @@ InternetSection::InternetSection(Profile* profile, // Fetch initial list of devices and active networks. FetchDeviceList(); - FetchActiveNetworks(); + FetchNetworkList(); } InternetSection::~InternetSection() = default; @@ -414,6 +520,7 @@ 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}, {"internetJoinType", IDS_SETTINGS_INTERNET_JOIN_TYPE}, {"internetKnownNetworksPageTitle", IDS_SETTINGS_INTERNET_KNOWN_NETWORKS}, @@ -461,6 +568,7 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"networkConnectNotAllowed", IDS_SETTINGS_INTERNET_CONNECT_NOT_ALLOWED}, {"networkIPAddress", IDS_SETTINGS_INTERNET_NETWORK_IP_ADDRESS}, {"networkIPConfigAuto", IDS_SETTINGS_INTERNET_NETWORK_IP_CONFIG_AUTO}, + {"networkMetered", IDS_SETTINGS_INTERNET_NETWORK_METERED}, {"networkNameserversLearnMore", IDS_LEARN_MORE}, {"networkPrefer", IDS_SETTINGS_INTERNET_NETWORK_PREFER}, {"networkPrimaryUserControlled", @@ -477,6 +585,8 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"networkSectionProxyExpandA11yLabel", IDS_SETTINGS_INTERNET_NETWORK_SECTION_PROXY_ACCESSIBILITY_LABEL}, {"networkShared", IDS_SETTINGS_INTERNET_NETWORK_SHARED}, + {"networkSharedOwner", IDS_SETTINGS_INTERNET_NETWORK_SHARED_OWNER}, + {"networkSharedNotOwner", IDS_SETTINGS_INTERNET_NETWORK_SHARED_NOT_OWNER}, {"networkVpnBuiltin", IDS_NETWORK_TYPE_VPN_BUILTIN}, {"networkOutOfRange", IDS_SETTINGS_INTERNET_WIFI_NETWORK_OUT_OF_RANGE}, {"cellularContactSpecificCarrier", @@ -535,14 +645,17 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddBoolean("showTechnologyBadge", !ash::features::IsSeparateNetworkIconsEnabled()); + html_source->AddBoolean( + "showMeteredToggle", + base::FeatureList::IsEnabled(features::kMeteredShowToggle)); html_source->AddString("networkGoogleNameserversLearnMoreUrl", chrome::kGoogleNameserversLearnMoreURL); html_source->AddString( - "networkSyncedShared", + "networkNotSynced", l10n_util::GetStringFUTF16( - IDS_SETTINGS_INTERNET_NETWORK_SYNCED_SHARED, + IDS_SETTINGS_INTERNET_NETWORK_NOT_SYNCED, GetHelpUrlWithBoard(chrome::kWifiSyncLearnMoreURL))); html_source->AddString( "networkSyncedUser", @@ -550,6 +663,11 @@ void InternetSection::AddLoadTimeData(content::WebUIDataSource* html_source) { IDS_SETTINGS_INTERNET_NETWORK_SYNCED_USER, GetHelpUrlWithBoard(chrome::kWifiSyncLearnMoreURL))); html_source->AddString( + "networkSyncedDevice", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_INTERNET_NETWORK_SYNCED_DEVICE, + GetHelpUrlWithBoard(chrome::kWifiSyncLearnMoreURL))); + html_source->AddString( "internetNoNetworksMobileData", l10n_util::GetStringFUTF16( IDS_SETTINGS_INTERNET_LOOKING_FOR_MOBILE_NETWORK, @@ -560,13 +678,140 @@ void InternetSection::AddHandlers(content::WebUI* web_ui) { web_ui->AddMessageHandler(std::make_unique<InternetHandler>(profile())); } +int InternetSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_INTERNET; +} + +mojom::Section InternetSection::GetSection() const { + return mojom::Section::kNetwork; +} + +mojom::SearchResultIcon InternetSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kWifi; +} + +std::string InternetSection::GetSectionPath() const { + return mojom::kNetworkSectionPath; +} + +void InternetSection::RegisterHierarchy(HierarchyGenerator* generator) const { + // Ethernet details. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_INTERNET_ETHERNET_DETAILS, + mojom::Subpage::kEthernetDetails, + mojom::SearchResultIcon::kEthernet, + mojom::SearchResultDefaultRank::kMedium, + mojom::kEthernetDetailsSubpagePath); + RegisterNestedSettingBulk(mojom::Subpage::kEthernetDetails, + GetEthernetDetailsSettings(), generator); + + // Wi-Fi networks. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_INTERNET_WIFI_NETWORKS, mojom::Subpage::kWifiNetworks, + mojom::SearchResultIcon::kWifi, mojom::SearchResultDefaultRank::kMedium, + mojom::kWifiNetworksSubpagePath); + static constexpr mojom::Setting kWifiNetworksSettings[] = { + mojom::Setting::kWifiOnOff, + mojom::Setting::kWifiAddNetwork, + }; + RegisterNestedSettingBulk(mojom::Subpage::kWifiNetworks, + kWifiNetworksSettings, generator); + generator->RegisterTopLevelAltSetting(mojom::Setting::kWifiOnOff); + + // Wi-Fi details. + generator->RegisterNestedSubpage( + IDS_SETTINGS_INTERNET_WIFI_DETAILS, mojom::Subpage::kWifiDetails, + mojom::Subpage::kWifiNetworks, mojom::SearchResultIcon::kWifi, + mojom::SearchResultDefaultRank::kMedium, mojom::kWifiDetailsSubpagePath); + RegisterNestedSettingBulk(mojom::Subpage::kWifiDetails, + GetWifiDetailsSettings(), generator); + + // Known networks. + generator->RegisterNestedSubpage( + IDS_SETTINGS_INTERNET_KNOWN_NETWORKS, mojom::Subpage::kKnownNetworks, + mojom::Subpage::kWifiNetworks, mojom::SearchResultIcon::kWifi, + mojom::SearchResultDefaultRank::kMedium, + mojom::kKnownNetworksSubpagePath); + generator->RegisterNestedAltSetting(mojom::Setting::kPreferWifiNetwork, + mojom::Subpage::kKnownNetworks); + generator->RegisterNestedAltSetting(mojom::Setting::kForgetWifiNetwork, + mojom::Subpage::kKnownNetworks); + + // Mobile data. If Instant Tethering is available, a mobile data subpage is + // available which lists both Cellular and Instant Tethering networks. If + // Instant Tethering is not available, there is no mobile data subpage. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_INTERNET_MOBILE_DATA_NETWORKS, + mojom::Subpage::kMobileDataNetworks, + mojom::SearchResultIcon::kCellular, + mojom::SearchResultDefaultRank::kMedium, + mojom::kMobileDataNetworksSubpagePath); + static constexpr mojom::Setting kMobileDataNetworksSettings[] = { + mojom::Setting::kMobileOnOff, + mojom::Setting::kInstantTetheringOnOff, + }; + RegisterNestedSettingBulk(mojom::Subpage::kMobileDataNetworks, + kMobileDataNetworksSettings, generator); + generator->RegisterTopLevelAltSetting(mojom::Setting::kMobileOnOff); + + // Cellular details. Cellular details are considered a child of the mobile + // data subpage. However, note that if Instant Tethering is not available, + // clicking on "Mobile data" at the Network section navigates users directly + // to the cellular details page and skips over the mobile data subpage. + generator->RegisterNestedSubpage( + IDS_SETTINGS_INTERNET_CELLULAR_DETAILS, mojom::Subpage::kCellularDetails, + mojom::Subpage::kMobileDataNetworks, mojom::SearchResultIcon::kCellular, + mojom::SearchResultDefaultRank::kMedium, + mojom::kCellularDetailsSubpagePath); + RegisterNestedSettingBulk(mojom::Subpage::kCellularDetails, + GetCellularDetailsSettings(), generator); + + // Instant Tethering. Although this is a multi-device feature, its UI resides + // in the network section. + generator->RegisterNestedSubpage( + IDS_SETTINGS_INTERNET_INSTANT_TETHERING_DETAILS, + mojom::Subpage::kTetherDetails, mojom::Subpage::kMobileDataNetworks, + mojom::SearchResultIcon::kInstantTethering, + mojom::SearchResultDefaultRank::kMedium, + mojom::kTetherDetailsSubpagePath); + RegisterNestedSettingBulk(mojom::Subpage::kTetherDetails, + GetTetherDetailsSettings(), generator); + + // VPN. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_INTERNET_VPN_DETAILS, mojom::Subpage::kVpnDetails, + mojom::SearchResultIcon::kWifi, mojom::SearchResultDefaultRank::kMedium, + mojom::kVpnDetailsSubpagePath); +} + +std::string InternetSection::ModifySearchResultUrl( + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const { + if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kEthernetDetails)) + return GetDetailsSubpageUrl(url_to_modify, *connected_ethernet_guid_); + + if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kWifiDetails)) + return GetDetailsSubpageUrl(url_to_modify, *connected_wifi_guid_); + + if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kCellularDetails)) + return GetDetailsSubpageUrl(url_to_modify, *cellular_guid_); + + if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kTetherDetails)) + return GetDetailsSubpageUrl(url_to_modify, *connected_tether_guid_); + + if (IsPartOfDetailsSubpage(type, id, mojom::Subpage::kVpnDetails)) + return GetDetailsSubpageUrl(url_to_modify, *connected_vpn_guid_); + + // URL does not need to be modified; use default implementation. + return OsSettingsSection::ModifySearchResultUrl(type, id, url_to_modify); +} + void InternetSection::OnDeviceStateListChanged() { FetchDeviceList(); } void InternetSection::OnActiveNetworksChanged( std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks) { - OnActiveNetworks(std::move(networks)); + FetchNetworkList(); } void InternetSection::FetchDeviceList() { @@ -579,40 +824,43 @@ void InternetSection::OnDeviceList( using network_config::mojom::DeviceStateType; using network_config::mojom::NetworkType; - registry()->RemoveSearchTags(GetWifiSearchConcepts()); - registry()->RemoveSearchTags(GetWifiOnSearchConcepts()); - registry()->RemoveSearchTags(GetWifiOffSearchConcepts()); - registry()->RemoveSearchTags(GetCellularSearchConcepts()); - registry()->RemoveSearchTags(GetCellularOnSearchConcepts()); - registry()->RemoveSearchTags(GetCellularOffSearchConcepts()); - registry()->RemoveSearchTags(GetInstantTetheringSearchConcepts()); - registry()->RemoveSearchTags(GetInstantTetheringOnSearchConcepts()); - registry()->RemoveSearchTags(GetInstantTetheringOffSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + updater.RemoveSearchTags(GetWifiSearchConcepts()); + updater.RemoveSearchTags(GetWifiOnSearchConcepts()); + updater.RemoveSearchTags(GetWifiOffSearchConcepts()); + updater.RemoveSearchTags(GetCellularOnSearchConcepts()); + updater.RemoveSearchTags(GetCellularOffSearchConcepts()); + updater.RemoveSearchTags(GetInstantTetheringSearchConcepts()); + updater.RemoveSearchTags(GetInstantTetheringOnSearchConcepts()); + updater.RemoveSearchTags(GetInstantTetheringOffSearchConcepts()); for (const auto& device : devices) { switch (device->type) { case NetworkType::kWiFi: - registry()->AddSearchTags(GetWifiSearchConcepts()); + updater.AddSearchTags(GetWifiSearchConcepts()); if (device->device_state == DeviceStateType::kEnabled) - registry()->AddSearchTags(GetWifiOnSearchConcepts()); + updater.AddSearchTags(GetWifiOnSearchConcepts()); else if (device->device_state == DeviceStateType::kDisabled) - registry()->AddSearchTags(GetWifiOffSearchConcepts()); + updater.AddSearchTags(GetWifiOffSearchConcepts()); break; case NetworkType::kCellular: - registry()->AddSearchTags(GetCellularSearchConcepts()); + // Note: Cellular search concepts all point to the cellular details + // page, which is only available if a cellular network exists. This + // check is in OnNetworkList(). if (device->device_state == DeviceStateType::kEnabled) - registry()->AddSearchTags(GetCellularOnSearchConcepts()); + updater.AddSearchTags(GetCellularOnSearchConcepts()); else if (device->device_state == DeviceStateType::kDisabled) - registry()->AddSearchTags(GetCellularOffSearchConcepts()); + updater.AddSearchTags(GetCellularOffSearchConcepts()); break; case NetworkType::kTether: - registry()->AddSearchTags(GetInstantTetheringSearchConcepts()); + updater.AddSearchTags(GetInstantTetheringSearchConcepts()); if (device->device_state == DeviceStateType::kEnabled) - registry()->AddSearchTags(GetInstantTetheringOnSearchConcepts()); + updater.AddSearchTags(GetInstantTetheringOnSearchConcepts()); else if (device->device_state == DeviceStateType::kDisabled) - registry()->AddSearchTags(GetInstantTetheringOffSearchConcepts()); + updater.AddSearchTags(GetInstantTetheringOffSearchConcepts()); break; default: @@ -623,48 +871,76 @@ void InternetSection::OnDeviceList( } } -void InternetSection::FetchActiveNetworks() { +void InternetSection::FetchNetworkList() { cros_network_config_->GetNetworkStateList( network_config::mojom::NetworkFilter::New( - network_config::mojom::FilterType::kActive, + network_config::mojom::FilterType::kVisible, network_config::mojom::NetworkType::kAll, network_config::mojom::kNoLimit), - base::Bind(&InternetSection::OnActiveNetworks, base::Unretained(this))); + base::Bind(&InternetSection::OnNetworkList, base::Unretained(this))); } -void InternetSection::OnActiveNetworks( +void InternetSection::OnNetworkList( std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks) { using network_config::mojom::NetworkType; - registry()->RemoveSearchTags(GetEthernetConnectedSearchConcepts()); - registry()->RemoveSearchTags(GetWifiConnectedSearchConcepts()); - registry()->RemoveSearchTags(GetCellularConnectedSearchConcepts()); - registry()->RemoveSearchTags(GetInstantTetheringConnectedSearchConcepts()); - registry()->RemoveSearchTags(GetVpnConnectedSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + updater.RemoveSearchTags(GetEthernetConnectedSearchConcepts()); + updater.RemoveSearchTags(GetWifiConnectedSearchConcepts()); + updater.RemoveSearchTags(GetWifiMeteredSearchConcepts()); + updater.RemoveSearchTags(GetCellularSearchConcepts()); + updater.RemoveSearchTags(GetCellularConnectedSearchConcepts()); + updater.RemoveSearchTags(GetCellularMeteredSearchConcepts()); + updater.RemoveSearchTags(GetInstantTetheringConnectedSearchConcepts()); + updater.RemoveSearchTags(GetVpnConnectedSearchConcepts()); + + cellular_guid_.reset(); + + connected_ethernet_guid_.reset(); + connected_wifi_guid_.reset(); + connected_tether_guid_.reset(); + connected_vpn_guid_.reset(); for (const auto& network : networks) { + // Special case: Some cellular search functionality is available even if the + // network is not connected. + if (network->type == NetworkType::kCellular) { + cellular_guid_ = network->guid; + updater.AddSearchTags(GetCellularSearchConcepts()); + } + if (!IsConnected(network->connection_state)) continue; switch (network->type) { case NetworkType::kEthernet: - registry()->AddSearchTags(GetEthernetConnectedSearchConcepts()); + connected_ethernet_guid_ = network->guid; + updater.AddSearchTags(GetEthernetConnectedSearchConcepts()); break; case NetworkType::kWiFi: - registry()->AddSearchTags(GetWifiConnectedSearchConcepts()); + connected_wifi_guid_ = network->guid; + updater.AddSearchTags(GetWifiConnectedSearchConcepts()); + if (base::FeatureList::IsEnabled(features::kMeteredShowToggle)) + updater.AddSearchTags(GetWifiMeteredSearchConcepts()); break; case NetworkType::kCellular: - registry()->AddSearchTags(GetCellularConnectedSearchConcepts()); + // Note: GUID is set above. + updater.AddSearchTags(GetCellularConnectedSearchConcepts()); + if (base::FeatureList::IsEnabled(features::kMeteredShowToggle)) + updater.AddSearchTags(GetCellularMeteredSearchConcepts()); break; case NetworkType::kTether: - registry()->AddSearchTags(GetInstantTetheringConnectedSearchConcepts()); + connected_tether_guid_ = network->guid; + updater.AddSearchTags(GetInstantTetheringConnectedSearchConcepts()); break; case NetworkType::kVPN: - registry()->AddSearchTags(GetVpnConnectedSearchConcepts()); + connected_vpn_guid_ = network->guid; + updater.AddSearchTags(GetVpnConnectedSearchConcepts()); break; default: diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.h index f467529b810..cbe35474631 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_section.h @@ -5,8 +5,10 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_SECTION_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_INTERNET_SECTION_H_ +#include <string> #include <vector> +#include "base/optional.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -34,6 +36,15 @@ class InternetSection // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; + std::string ModifySearchResultUrl( + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const override; // network_config::mojom::CrosNetworkConfigObserver: void OnActiveNetworksChanged( @@ -51,10 +62,19 @@ class InternetSection void OnDeviceList( std::vector<network_config::mojom::DeviceStatePropertiesPtr> devices); - void FetchActiveNetworks(); - void OnActiveNetworks( + void FetchNetworkList(); + void OnNetworkList( std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks); + // Null if no cellular network exists. + base::Optional<std::string> cellular_guid_; + + // Note: If not connected, the below fields are null. + base::Optional<std::string> connected_ethernet_guid_; + base::Optional<std::string> connected_wifi_guid_; + base::Optional<std::string> connected_tether_guid_; + base::Optional<std::string> connected_vpn_guid_; + mojo::Receiver<network_config::mojom::CrosNetworkConfigObserver> receiver_{ this}; mojo::Remote<network_config::mojom::CrosNetworkConfig> cros_network_config_; 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 0007f1a6a8b..78321bd8c64 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.cc @@ -7,6 +7,7 @@ #include "base/feature_list.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_features_util.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" #include "chrome/browser/ui/webui/settings/languages_handler.h" @@ -14,6 +15,8 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "chromeos/constants/chromeos_features.h" +#include "chromeos/constants/chromeos_pref_names.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -57,7 +60,7 @@ const std::vector<SearchConcept>& GetLanguagesSearchConcepts() { const std::vector<SearchConcept>& GetSmartInputsSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_LANGUAGES_SMART_INPUTS, - mojom::kSmartInputsSubagePath, + mojom::kSmartInputsSubpagePath, mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, @@ -69,7 +72,7 @@ const std::vector<SearchConcept>& GetSmartInputsSearchConcepts() { const std::vector<SearchConcept>& GetAssistivePersonalInfoSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_LANGUAGES_PERSONAL_INFORMATION_SUGGESTIONS, - mojom::kSmartInputsSubagePath, + mojom::kSmartInputsSubpagePath, mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, @@ -78,13 +81,26 @@ const std::vector<SearchConcept>& GetAssistivePersonalInfoSearchConcepts() { return *tags; } +const std::vector<SearchConcept>& GetEmojiSuggestionSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_LANGUAGES_EMOJI_SUGGESTIONS, + mojom::kSmartInputsSubpagePath, + mojom::SearchResultIcon::kGlobe, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kShowEmojiSuggestions}}, + }); + return *tags; +} + bool IsAssistivePersonalInfoAllowed() { return !features::IsGuestModeActive() && base::FeatureList::IsEnabled( ::chromeos::features::kAssistPersonalInfo); } -void AddSmartInputsStrings(content::WebUIDataSource* html_source) { +void AddSmartInputsStrings(content::WebUIDataSource* html_source, + bool is_emoji_suggestion_allowed) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"smartInputsTitle", IDS_SETTINGS_SMART_INPUTS_TITLE}, {"personalInfoSuggestionTitle", @@ -94,11 +110,71 @@ void AddSmartInputsStrings(content::WebUIDataSource* html_source) { {"showPersonalInfoSuggestion", IDS_SETTINGS_SMART_INPUTS_SHOW_PERSONAL_INFO}, {"managePersonalInfo", IDS_SETTINGS_SMART_INPUTS_MANAGE_PERSONAL_INFO}, + {"emojiSuggestionTitle", + IDS_SETTINGS_SMART_INPUTS_EMOJI_SUGGESTION_TITLE}, + {"emojiSuggestionDescription", + IDS_SETTINGS_SMART_INPUTS_EMOJI_SUGGESTION_DESCRIPTION}, + {"showEmojiSuggestion", IDS_SETTINGS_SMART_INPUTS_SHOW_EMOJI_SUGGESTION}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); html_source->AddBoolean("allowAssistivePersonalInfo", IsAssistivePersonalInfoAllowed()); + html_source->AddBoolean("allowEmojiSuggestion", is_emoji_suggestion_allowed); +} + +void AddInputMethodOptionsStrings(content::WebUIDataSource* html_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"inputMethodOptionsBasicSectionTitle", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_BASIC}, + {"inputMethodOptionsAdvancedSectionTitle", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ADVANCED}, + {"inputMethodOptionsPhysicalKeyboardSectionTitle", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PHYSICAL_KEYBOARD}, + {"inputMethodOptionsVirtualKeyboardSectionTitle", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_VIRTUAL_KEYBOARD}, + {"inputMethodOptionsEnableDoubleSpacePeriod", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ENABLE_DOUBLE_SPACE_PERIOD}, + {"inputMethodOptionsEnableGestureTyping", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ENABLE_GESTURE_TYPING}, + {"inputMethodOptionsEnablePrediction", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ENABLE_PREDICTION}, + {"inputMethodOptionsEnableSoundOnKeypress", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ENABLE_SOUND_ON_KEYPRESS}, + {"inputMethodOptionsEnableCapitalization", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_ENABLE_CAPITALIZATION}, + {"inputMethodOptionsAutoCorrection", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION}, + {"inputMethodOptionsXkbLayout", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_XKB_LAYOUT}, + {"inputMethodOptionsEditUserDict", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_EDIT_USER_DICT}, + {"inputMethodOptionsPinyinChinesePunctuation", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_CHINESE_PUNCTUATION}, + {"inputMethodOptionsPinyinDefaultChinese", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_DEFAULT_CHINESE}, + {"inputMethodOptionsPinyinEnableFuzzy", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_ENABLE_FUZZY}, + {"inputMethodOptionsPinyinEnableLowerPaging", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_ENABLE_LOWER_PAGING}, + {"inputMethodOptionsPinyinEnableUpperPaging", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_ENABLE_UPPER_PAGING}, + {"inputMethodOptionsPinyinFullWidthCharacter", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_PINYIN_FULL_WIDTH_CHARACTER}, + {"inputMethodOptionsAutoCorrectionOff", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION_OFF}, + {"inputMethodOptionsAutoCorrectionModest", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION_MODEST}, + {"inputMethodOptionsAutoCorrectionAggressive", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_AUTO_CORRECTION_AGGRESSIVE}, + {"inputMethodOptionsUsKeyboard", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_US}, + {"inputMethodOptionsDvorakKeyboard", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_DVORAK}, + {"inputMethodOptionsColemakKeyboard", + IDS_SETTINGS_INPUT_METHOD_OPTIONS_KEYBOARD_COLEMAK}, + }; + AddLocalizedStringsBulk(html_source, kLocalizedStrings); } } // namespace @@ -106,11 +182,15 @@ void AddSmartInputsStrings(content::WebUIDataSource* html_source) { LanguagesSection::LanguagesSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { - registry()->AddSearchTags(GetLanguagesSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetLanguagesSearchConcepts()); - if (IsAssistivePersonalInfoAllowed()) { - registry()->AddSearchTags(GetSmartInputsSearchConcepts()); - registry()->AddSearchTags(GetAssistivePersonalInfoSearchConcepts()); + if (IsAssistivePersonalInfoAllowed() || IsEmojiSuggestionAllowed()) { + updater.AddSearchTags(GetSmartInputsSearchConcepts()); + if (IsAssistivePersonalInfoAllowed()) + updater.AddSearchTags(GetAssistivePersonalInfoSearchConcepts()); + if (IsEmojiSuggestionAllowed()) + updater.AddSearchTags(GetEmojiSuggestionSearchConcepts()); } } @@ -149,11 +229,15 @@ void LanguagesSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"moveUp", IDS_SETTINGS_LANGUAGES_LANGUAGES_LIST_MOVE_UP}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); - AddSmartInputsStrings(html_source); + AddSmartInputsStrings(html_source, IsEmojiSuggestionAllowed()); + AddInputMethodOptionsStrings(html_source); html_source->AddString( "languagesLearnMoreURL", base::ASCIIToUTF16(chrome::kLanguageSettingsLearnMoreUrl)); + html_source->AddBoolean("imeOptionsInSettings", + base::FeatureList::IsEnabled( + ::chromeos::features::kImeOptionsInSettings)); } void LanguagesSection::AddHandlers(content::WebUI* web_ui) { @@ -161,5 +245,71 @@ void LanguagesSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<::settings::LanguagesHandler>(profile())); } +int LanguagesSection::GetSectionNameMessageId() const { + return IDS_OS_SETTINGS_LANGUAGES_AND_INPUT_PAGE_TITLE; +} + +mojom::Section LanguagesSection::GetSection() const { + return mojom::Section::kLanguagesAndInput; +} + +mojom::SearchResultIcon LanguagesSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kGlobe; +} + +std::string LanguagesSection::GetSectionPath() const { + return mojom::kLanguagesAndInputSectionPath; +} + +bool LanguagesSection::IsEmojiSuggestionAllowed() const { + return base::FeatureList::IsEnabled( + ::chromeos::features::kEmojiSuggestAddition) && + profile()->GetPrefs()->GetBoolean( + ::chromeos::prefs::kEmojiSuggestionEnterpriseAllowed); +} + +void LanguagesSection::RegisterHierarchy(HierarchyGenerator* generator) const { + // Languages and input details. + generator->RegisterTopLevelSubpage( + IDS_OS_SETTINGS_LANGUAGES_AND_INPUT_PAGE_TITLE, + mojom::Subpage::kLanguagesAndInputDetails, + mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, + mojom::kLanguagesAndInputDetailsSubpagePath); + static constexpr mojom::Setting kLanguagesAndInputDetailsSettings[] = { + mojom::Setting::kAddLanguage, + mojom::Setting::kShowInputOptionsInShelf, + }; + RegisterNestedSettingBulk(mojom::Subpage::kLanguagesAndInputDetails, + kLanguagesAndInputDetailsSettings, generator); + + // Manage input methods. + generator->RegisterNestedSubpage( + IDS_SETTINGS_LANGUAGES_MANAGE_INPUT_METHODS_TITLE, + mojom::Subpage::kManageInputMethods, + mojom::Subpage::kLanguagesAndInputDetails, + mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, + mojom::kManageInputMethodsSubpagePath); + + // Input method options. + generator->RegisterNestedSubpage( + IDS_SETTINGS_LANGUAGES_INPUT_METHOD_OPTIONS_TITLE, + mojom::Subpage::kInputMethodOptions, + mojom::Subpage::kLanguagesAndInputDetails, + mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, + mojom::kInputMethodOptionsSubpagePath); + + // Smart inputs. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_SMART_INPUTS_TITLE, mojom::Subpage::kSmartInputs, + mojom::SearchResultIcon::kGlobe, mojom::SearchResultDefaultRank::kMedium, + mojom::kSmartInputsSubpagePath); + static constexpr mojom::Setting kSmartInputsFeaturesSettings[] = { + mojom::Setting::kShowPersonalInformationSuggestions, + mojom::Setting::kShowEmojiSuggestions, + }; + RegisterNestedSettingBulk(mojom::Subpage::kSmartInputs, + kSmartInputsFeaturesSettings, generator); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.h index d8a742babc2..9236455754d 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/languages_section.h @@ -28,6 +28,13 @@ class LanguagesSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; + + bool IsEmojiSuggestionAllowed() const; }; } // namespace settings 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 9afd5882393..0868f9c866a 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.cc @@ -39,8 +39,6 @@ void AddSearchInSettingsStrings(content::WebUIDataSource* html_source) { {"searchNoResults", IDS_SEARCH_NO_RESULTS}, {"searchResults", IDS_SEARCH_RESULTS}, {"searchResultSelected", IDS_OS_SEARCH_RESULT_ROW_A11Y_RESULT_SELECTED}, - {"searchResultsOne", IDS_OS_SEARCH_BOX_A11Y_ONE_RESULT}, - {"searchResultsNumber", IDS_OS_SEARCH_BOX_A11Y_RESULT_COUNT}, // TODO(dpapad): IDS_DOWNLOAD_CLEAR_SEARCH and IDS_HISTORY_CLEAR_SEARCH // are identical, merge them to one and re-use here. {"clearSearch", IDS_DOWNLOAD_CLEAR_SEARCH}, @@ -98,6 +96,10 @@ void MainSection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"settings", IDS_SETTINGS_SETTINGS}, {"settingsAltPageTitle", IDS_SETTINGS_ALT_PAGE_TITLE}, {"subpageArrowRoleDescription", IDS_SETTINGS_SUBPAGE_BUTTON}, + {"subpageBackButtonAriaLabel", + IDS_SETTINGS_SUBPAGE_BACK_BUTTON_ARIA_LABEL}, + {"subpageBackButtonAriaRoleDescription", + IDS_SETTINGS_SUBPAGE_BACK_BUTTON_ARIA_ROLE_DESCRIPTION}, {"notValidWebAddress", IDS_SETTINGS_NOT_VALID_WEB_ADDRESS}, {"notValidWebAddressForContentType", IDS_SETTINGS_NOT_VALID_WEB_ADDRESS_FOR_CONTENT_TYPE}, @@ -143,11 +145,6 @@ void MainSection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddResourcePath("search/search.mojom-lite.js", IDR_OS_SETTINGS_SEARCH_MOJOM_LITE_JS); - html_source->AddString("browserSettingsBannerText", - l10n_util::GetStringFUTF16( - IDS_SETTINGS_BROWSER_SETTINGS_BANNER, - base::ASCIIToUTF16(chrome::kChromeUISettingsURL))); - AddSearchInSettingsStrings(html_source); AddChromeOSUserStrings(html_source); @@ -162,6 +159,32 @@ void MainSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<::settings::BrowserLifetimeHandler>()); } +int MainSection::GetSectionNameMessageId() const { + NOTIMPLEMENTED(); + return 0; +} + +mojom::Section MainSection::GetSection() const { + NOTIMPLEMENTED(); + return mojom::Section::kMinValue; +} + +mojom::SearchResultIcon MainSection::GetSectionIcon() const { + NOTIMPLEMENTED(); + return mojom::SearchResultIcon::kMinValue; +} + +std::string MainSection::GetSectionPath() const { + NOTIMPLEMENTED(); + return std::string(); +} + +void MainSection::RegisterHierarchy(HierarchyGenerator* generator) const { + // MainSection is a container for common resources/functionality shared + // between sections and does not have its own subpages/settings. + NOTIMPLEMENTED(); +} + void MainSection::AddChromeOSUserStrings( content::WebUIDataSource* html_source) { const user_manager::User* user = diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.h index 7f8d9de7d5c..fab6b9bfdc3 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/main_section.h @@ -26,6 +26,11 @@ class MainSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; void AddChromeOSUserStrings(content::WebUIDataSource* html_source); }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc index 7ce85eaf234..da38e8b2896 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc @@ -4,19 +4,25 @@ #include "chrome/browser/ui/webui/settings/chromeos/multidevice_section.h" +#include "base/feature_list.h" #include "base/no_destructor.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/chromeos/android_sms/android_sms_service.h" +#include "chrome/browser/nearby_sharing/nearby_sharing_prefs.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" +#include "chrome/browser/ui/webui/settings/shared_settings_localized_strings_provider.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/constants/chromeos_features.h" #include "chromeos/services/multidevice_setup/public/cpp/prefs.h" #include "chromeos/services/multidevice_setup/public/cpp/url_provider.h" #include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" @@ -27,8 +33,22 @@ namespace chromeos { namespace settings { namespace { -const std::vector<SearchConcept>& GetMultiDeviceSearchConcepts() { +const std::vector<SearchConcept>& GetMultiDeviceOptedInSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_MULTIDEVICE_SMART_LOCK_OPTIONS, + mojom::kSmartLockSubpagePath, + mojom::SearchResultIcon::kLock, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kSmartLock}}, + {IDS_OS_SETTINGS_TAG_MULTIDEVICE_FORGET, + mojom::kMultiDeviceFeaturesSubpagePath, + mojom::SearchResultIcon::kPhone, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kForgetPhone}, + {IDS_OS_SETTINGS_TAG_MULTIDEVICE_FORGET_ALT1, + SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_MULTIDEVICE_MESSAGES, mojom::kMultiDeviceFeaturesSubpagePath, mojom::SearchResultIcon::kMessages, @@ -40,54 +60,78 @@ const std::vector<SearchConcept>& GetMultiDeviceSearchConcepts() { {IDS_OS_SETTINGS_TAG_MULTIDEVICE, mojom::kMultiDeviceFeaturesSubpagePath, mojom::SearchResultIcon::kPhone, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kMultiDeviceFeatures}, - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_ALT1, - IDS_OS_SETTINGS_TAG_MULTIDEVICE_ALT2, - IDS_OS_SETTINGS_TAG_MULTIDEVICE_ALT3, SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_MULTIDEVICE_ALT1, SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_MULTIDEVICE_SMART_LOCK, mojom::kMultiDeviceFeaturesSubpagePath, mojom::SearchResultIcon::kLock, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kSmartLock}, - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_SMART_LOCK_ALT1, - SearchConcept::kAltTagEnd}}, + {.subpage = mojom::Subpage::kSmartLock}}, }); return *tags; } -const std::vector<SearchConcept>& GetMultiDeviceOptedInSearchConcepts() { +const std::vector<SearchConcept>& GetMultiDeviceOptedOutSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags([] { + // Special-case: The "set up" search tag also includes the names of the + // multi-device features as a way to increase discoverability of these + // features. + SearchConcept set_up_concept{ + IDS_OS_SETTINGS_TAG_MULTIDEVICE_SET_UP, + mojom::kMultiDeviceSectionPath, + mojom::SearchResultIcon::kPhone, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kSetUpMultiDevice}, + {IDS_OS_SETTINGS_TAG_MULTIDEVICE, + IDS_OS_SETTINGS_TAG_MULTIDEVICE_MESSAGES, + IDS_OS_SETTINGS_TAG_MULTIDEVICE_SMART_LOCK, SearchConcept::kAltTagEnd}, + }; + + // If Instant Tethering is available, also include that in the list. + if (base::FeatureList::IsEnabled(features::kInstantTethering)) { + set_up_concept.alt_tag_ids[3] = IDS_OS_SETTINGS_TAG_INSTANT_TETHERING; + set_up_concept.alt_tag_ids[4] = SearchConcept::kAltTagEnd; + } + + return std::vector<SearchConcept>{set_up_concept}; + }()); + return *tags; +} + +const std::vector<SearchConcept>& GetNearbyShareOnSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_SMART_LOCK_OPTIONS, - mojom::kSmartLockSubpagePath, - mojom::SearchResultIcon::kLock, + {IDS_OS_SETTINGS_TAG_MULTIDEVICE_NEARBY_SHARE, + mojom::kNearbyShareSubpagePath, + mojom::SearchResultIcon::kNearbyShare, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kSmartLock}, - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_SMART_LOCK_OPTIONS_ALT1, - SearchConcept::kAltTagEnd}}, - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_FORGET, - mojom::kMultiDeviceFeaturesSubpagePath, - mojom::SearchResultIcon::kPhone, + {.subpage = mojom::Subpage::kNearbyShare}}, + {IDS_OS_SETTINGS_TAG_NEARBY_SHARE_TURN_OFF, + mojom::kNearbyShareSubpagePath, + mojom::SearchResultIcon::kNearbyShare, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kForgetPhone}, - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_FORGET_ALT1, + {.setting = mojom::Setting::kNearbyShareOnOff}, + {IDS_OS_SETTINGS_TAG_NEARBY_SHARE_TURN_OFF_ALT1, SearchConcept::kAltTagEnd}}, }); return *tags; } -const std::vector<SearchConcept>& GetMultiDeviceOptedOutSearchConcepts() { +const std::vector<SearchConcept>& GetNearbyShareOffSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_MULTIDEVICE_SET_UP, + {IDS_OS_SETTINGS_TAG_NEARBY_SHARE_TURN_ON, mojom::kMultiDeviceSectionPath, - mojom::SearchResultIcon::kPhone, + mojom::SearchResultIcon::kNearbyShare, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kSetUpMultiDevice}}, + {.setting = mojom::Setting::kNearbyShareOnOff}, + {IDS_OS_SETTINGS_TAG_NEARBY_SHARE_TURN_ON_ALT1, + SearchConcept::kAltTagEnd}}, }); return *tags; } @@ -121,13 +165,21 @@ MultiDeviceSection::MultiDeviceSection( multidevice_setup_client_(multidevice_setup_client), android_sms_service_(android_sms_service), pref_service_(pref_service) { + if (base::FeatureList::IsEnabled(::features::kNearbySharing)) { + pref_change_registrar_.Init(pref_service_); + pref_change_registrar_.Add( + ::prefs::kNearbySharingEnabledPrefName, + base::BindRepeating(&MultiDeviceSection::OnNearbySharingEnabledChanged, + base::Unretained(this))); + OnNearbySharingEnabledChanged(); + } + // Note: |multidevice_setup_client_| is null when multi-device features are // prohibited by policy. if (!multidevice_setup_client_) return; multidevice_setup_client_->AddObserver(this); - registry()->AddSearchTags(GetMultiDeviceSearchConcepts()); OnHostStatusChanged(multidevice_setup_client_->GetHostStatus()); } @@ -214,6 +266,7 @@ void MultiDeviceSection::AddLoadTimeData( GetHelpUrlWithBoard(chrome::kEasyUnlockLearnMoreUrl))); AddEasyUnlockStrings(html_source); + ::settings::AddNearbyShareData(html_source); } void MultiDeviceSection::AddHandlers(content::WebUI* web_ui) { @@ -231,15 +284,96 @@ void MultiDeviceSection::AddHandlers(content::WebUI* web_ui) { : nullptr)); } +int MultiDeviceSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_MULTIDEVICE; +} + +mojom::Section MultiDeviceSection::GetSection() const { + return mojom::Section::kMultiDevice; +} + +mojom::SearchResultIcon MultiDeviceSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kPhone; +} + +std::string MultiDeviceSection::GetSectionPath() const { + return mojom::kMultiDeviceSectionPath; +} + +void MultiDeviceSection::RegisterHierarchy( + HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kSetUpMultiDevice); + generator->RegisterTopLevelSetting(mojom::Setting::kVerifyMultiDeviceSetup); + + // MultiDevice features. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_MULTIDEVICE, mojom::Subpage::kMultiDeviceFeatures, + mojom::SearchResultIcon::kPhone, mojom::SearchResultDefaultRank::kMedium, + mojom::kMultiDeviceFeaturesSubpagePath); + static constexpr mojom::Setting kMultiDeviceFeaturesSettings[] = { + mojom::Setting::kMultiDeviceOnOff, + mojom::Setting::kMessagesSetUp, + mojom::Setting::kMessagesOnOff, + mojom::Setting::kForgetPhone, + }; + RegisterNestedSettingBulk(mojom::Subpage::kMultiDeviceFeatures, + kMultiDeviceFeaturesSettings, generator); + generator->RegisterTopLevelAltSetting(mojom::Setting::kMultiDeviceOnOff); + // Note: Instant Tethering is part of the Network section, but it has an + // alternate setting within the MultiDevice section. + generator->RegisterNestedAltSetting(mojom::Setting::kInstantTetheringOnOff, + mojom::Subpage::kMultiDeviceFeatures); + + // Smart Lock. + generator->RegisterNestedSubpage( + IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE, mojom::Subpage::kSmartLock, + mojom::Subpage::kMultiDeviceFeatures, mojom::SearchResultIcon::kLock, + mojom::SearchResultDefaultRank::kMedium, mojom::kSmartLockSubpagePath); + static constexpr mojom::Setting kSmartLockSettings[] = { + mojom::Setting::kSmartLockOnOff, + mojom::Setting::kSmartLockUnlockOrSignIn, + }; + RegisterNestedSettingBulk(mojom::Subpage::kSmartLock, kSmartLockSettings, + generator); + generator->RegisterNestedAltSetting(mojom::Setting::kSmartLockOnOff, + mojom::Subpage::kMultiDeviceFeatures); + + // Nearby Share, registered regardless of the flag. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_NEARBY_SHARE_TITLE, mojom::Subpage::kNearbyShare, + mojom::SearchResultIcon::kNearbyShare, + mojom::SearchResultDefaultRank::kMedium, mojom::kNearbyShareSubpagePath); + static constexpr mojom::Setting kNearbyShareSettings[] = { + mojom::Setting::kNearbyShareOnOff, + }; + RegisterNestedSettingBulk(mojom::Subpage::kNearbyShare, kNearbyShareSettings, + generator); + generator->RegisterTopLevelAltSetting(mojom::Setting::kNearbyShareOnOff); +} + void MultiDeviceSection::OnHostStatusChanged( const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice& host_status_with_device) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (IsOptedIn(host_status_with_device.first)) { - registry()->RemoveSearchTags(GetMultiDeviceOptedOutSearchConcepts()); - registry()->AddSearchTags(GetMultiDeviceOptedInSearchConcepts()); + updater.RemoveSearchTags(GetMultiDeviceOptedOutSearchConcepts()); + updater.AddSearchTags(GetMultiDeviceOptedInSearchConcepts()); + } else { + updater.RemoveSearchTags(GetMultiDeviceOptedInSearchConcepts()); + updater.AddSearchTags(GetMultiDeviceOptedOutSearchConcepts()); + } +} + +void MultiDeviceSection::OnNearbySharingEnabledChanged() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + + if (pref_service_->GetBoolean(::prefs::kNearbySharingEnabledPrefName)) { + updater.RemoveSearchTags(GetNearbyShareOffSearchConcepts()); + updater.AddSearchTags(GetNearbyShareOnSearchConcepts()); } else { - registry()->RemoveSearchTags(GetMultiDeviceOptedInSearchConcepts()); - registry()->AddSearchTags(GetMultiDeviceOptedOutSearchConcepts()); + updater.RemoveSearchTags(GetNearbyShareOnSearchConcepts()); + updater.AddSearchTags(GetNearbyShareOffSearchConcepts()); } } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h index d35711a2c9d..2c608c9e03c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_section.h @@ -7,6 +7,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" #include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h" +#include "components/prefs/pref_change_registrar.h" class PrefService; @@ -43,15 +44,24 @@ class MultiDeviceSection // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // multidevice_setup::MultiDeviceSetupClient::Observer: void OnHostStatusChanged( const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice& host_status_with_device) override; + // Nearby Share enabled pref change observer. + void OnNearbySharingEnabledChanged(); + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; android_sms::AndroidSmsService* android_sms_service_; PrefService* pref_service_; + PrefChangeRegistrar pref_change_registrar_; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_identifier.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_identifier.h new file mode 100644 index 00000000000..df287c3a928 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_identifier.h @@ -0,0 +1,24 @@ +// Copyright 2020 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_SETTINGS_IDENTIFIER_H_ +#define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_IDENTIFIER_H_ + +#include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" +#include "chrome/browser/ui/webui/settings/chromeos/constants/setting.mojom.h" + +namespace chromeos { +namespace settings { + +// Uniquely identifies a settings item (section, subpage, or setting). +union OsSettingsIdentifier { + mojom::Section section; + mojom::Subpage subpage; + mojom::Setting setting; +}; + +} // namespace settings +} // namespace chromeos + +#endif // CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_OS_SETTINGS_IDENTIFIER_H_ 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 ce568062640..95cd5692e5c 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/chromeos/local_search_service/local_search_service.h" +#include "chrome/browser/ui/webui/settings/chromeos/hierarchy.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" @@ -40,10 +41,12 @@ OsSettingsManager::OsSettingsManager( arc_app_list_prefs, identity_manager, android_sms_service, - printers_manager)) { + printers_manager)), + hierarchy_(std::make_unique<Hierarchy>(sections_.get())) { if (base::FeatureList::IsEnabled(features::kNewOsSettingsSearch)) { search_handler_ = std::make_unique<SearchHandler>( - search_tag_registry_.get(), local_search_service); + search_tag_registry_.get(), sections_.get(), hierarchy_.get(), + local_search_service); } } @@ -64,6 +67,7 @@ void OsSettingsManager::Shutdown() { // Note: These must be deleted in the opposite order of their creation to // prevent against UAF violations. search_handler_.reset(); + hierarchy_.reset(); sections_.reset(); search_tag_registry_.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 b60dbcbd181..78a9008a482 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 @@ -46,6 +46,7 @@ class MultiDeviceSetupClient; namespace settings { +class Hierarchy; class OsSettingsSections; class SearchHandler; class SearchTagRegistry; @@ -104,14 +105,17 @@ class OsSettingsManager : public KeyedService { // Note: Returns null when the kNewOsSettingsSearch flag is disabled. SearchHandler* search_handler() { return search_handler_.get(); } + const Hierarchy* hierarchy() const { return hierarchy_.get(); } + private: - FRIEND_TEST_ALL_PREFIXES(OsSettingsManagerTest, Sections); + FRIEND_TEST_ALL_PREFIXES(OsSettingsManagerTest, Initialization); // KeyedService: void Shutdown() override; std::unique_ptr<SearchTagRegistry> search_tag_registry_; std::unique_ptr<OsSettingsSections> sections_; + std::unique_ptr<Hierarchy> hierarchy_; std::unique_ptr<SearchHandler> search_handler_; }; 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 a238deaf5fb..71e5abc2b2f 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 @@ -9,6 +9,7 @@ #include "chrome/browser/chromeos/local_search_service/local_search_service_factory.h" #include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h" #include "chrome/browser/chromeos/printing/cups_printers_manager_factory.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/incognito_helpers.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" @@ -53,13 +54,23 @@ OsSettingsManagerFactory::~OsSettingsManagerFactory() = default; KeyedService* OsSettingsManagerFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { Profile* profile = Profile::FromBrowserContext(context); + + // Edge case: KerberosCredentialsManagerFactory::Get(profile) returns the + // instance associated with the primary profile, even if |profile| is not the + // primary profile, which can cause issues in multi-profile environments. + // Only call Get() if the profile is primary; see https://crbug.com/1103140. + KerberosCredentialsManager* kerberos_credentials_manager = + ProfileHelper::IsPrimaryProfile(profile) + ? KerberosCredentialsManagerFactory::Get(profile) + : nullptr; + return new OsSettingsManager( profile, local_search_service::LocalSearchServiceFactory::GetForProfile(profile), multidevice_setup::MultiDeviceSetupClientFactory::GetForProfile(profile), ProfileSyncServiceFactory::GetForProfile(profile), SupervisedUserServiceFactory::GetForProfile(profile), - KerberosCredentialsManagerFactory::Get(profile), + kerberos_credentials_manager, ArcAppListPrefsFactory::GetForBrowserContext(profile), IdentityManagerFactory::GetForProfile(profile), android_sms::AndroidSmsServiceFactory::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 ec50ed54481..dd20db6da77 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 @@ -4,9 +4,12 @@ #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager.h" +#include "base/metrics/histogram_base.h" #include "base/no_destructor.h" +#include "base/test/metrics/histogram_enum_reader.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/constants_util.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" +#include "chrome/browser/ui/webui/settings/chromeos/hierarchy.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_manager_factory.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h" #include "chrome/test/base/testing_browser_process.h" @@ -40,12 +43,55 @@ class OsSettingsManagerTest : public testing::Test { OsSettingsManager* manager_; }; -TEST_F(OsSettingsManagerTest, Sections) { - // For each mojom::Section value, there should be an associated - // OsSettingsSection class registered. +TEST_F(OsSettingsManagerTest, Initialization) { + base::Optional<base::HistogramEnumEntryMap> sections_enum_entry_map = + base::ReadEnumFromEnumsXml("OsSettingsSection"); + ASSERT_TRUE(sections_enum_entry_map); for (const auto& section : constants::AllSections()) { + // For each mojom::Section value, there should be an associated + // OsSettingsSection class registered. EXPECT_TRUE(manager_->sections_->GetSection(section)) << "No OsSettingsSection instance created for " << section << "."; + + // Each mojom::Section should be registered in the hierarchy. + const Hierarchy::SectionMetadata& metadata = + manager_->hierarchy_->GetSectionMetadata(section); + + // Only the "About Chrome OS" section contains only a link to a subpage. + EXPECT_EQ(metadata.only_contains_link_to_subpage, + section == mojom::Section::kAboutChromeOs); + + EXPECT_TRUE( + base::Contains(*sections_enum_entry_map, static_cast<int32_t>(section))) + << "Missing OsSettingsSection enums.xml entry for " << section; + } + + base::Optional<base::HistogramEnumEntryMap> subpages_enum_entry_map = + base::ReadEnumFromEnumsXml("OsSettingsSubpage"); + ASSERT_TRUE(subpages_enum_entry_map); + for (const auto& subpage : constants::AllSubpages()) { + // Each mojom::Subpage should be registered in the hierarchy. Note that + // GetSubpageMetadata() internally CHECK()s that the metadata exists before + // returning it. + manager_->hierarchy_->GetSubpageMetadata(subpage); + + EXPECT_TRUE( + base::Contains(*subpages_enum_entry_map, static_cast<int32_t>(subpage))) + << "Missing OsSettingsSubpage enums.xml entry for " << subpage; + } + + base::Optional<base::HistogramEnumEntryMap> settings_enum_entry_map = + base::ReadEnumFromEnumsXml("OsSetting"); + ASSERT_TRUE(settings_enum_entry_map); + for (const auto& setting : constants::AllSettings()) { + // Each mojom::Setting should be registered in the hierarchy. Note that + // GetSettingMetadata() internally CHECK()s that the metadata exists before + // returning it. + manager_->hierarchy_->GetSettingMetadata(setting); + + EXPECT_TRUE( + base::Contains(*settings_enum_entry_map, static_cast<int32_t>(setting))) + << "Missing OsSetting enums.xml entry for " << setting; } } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.cc index af60b362b5f..02bdc340841 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.cc @@ -7,6 +7,8 @@ #include "base/check.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" +#include "chrome/grit/generated_resources.h" +#include "ui/base/l10n/l10n_util.h" namespace chromeos { namespace settings { @@ -18,6 +20,15 @@ base::string16 OsSettingsSection::GetHelpUrlWithBoard( "&b=" + base::SysInfo::GetLsbReleaseBoard()); } +// static +void OsSettingsSection::RegisterNestedSettingBulk( + mojom::Subpage subpage, + const base::span<const mojom::Setting>& settings, + HierarchyGenerator* generator) { + for (const auto& setting : settings) + generator->RegisterNestedSetting(setting, subpage); +} + OsSettingsSection::~OsSettingsSection() = default; OsSettingsSection::OsSettingsSection(Profile* profile, @@ -27,5 +38,33 @@ OsSettingsSection::OsSettingsSection(Profile* profile, DCHECK(search_tag_registry); } +OsSettingsSection::OsSettingsSection() = default; + +std::string OsSettingsSection::ModifySearchResultUrl( + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const { + // Default case for static URLs which do not need to be modified. + return url_to_modify; +} + +mojom::SearchResultPtr OsSettingsSection::GenerateSectionSearchResult( + double relevance_score) const { + return mojom::SearchResult::New( + /*result_text=*/l10n_util::GetStringUTF16(GetSectionNameMessageId()), + /*canonical_result_text=*/ + l10n_util::GetStringUTF16(GetSectionNameMessageId()), + ModifySearchResultUrl(mojom::SearchResultType::kSection, + {.section = GetSection()}, GetSectionPath()), + GetSectionIcon(), relevance_score, + std::vector<base::string16>{ + l10n_util::GetStringUTF16(IDS_INTERNAL_APP_SETTINGS), + l10n_util::GetStringUTF16(GetSectionNameMessageId())}, + mojom::SearchResultDefaultRank::kMedium, + /*was_generated_from_text_match=*/false, + mojom::SearchResultType::kSection, + mojom::SearchResultIdentifier::NewSection(GetSection())); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.h index 3e8b5b23bcd..b4406ff4c3e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_section.h @@ -8,7 +8,11 @@ #include <string> #include <vector> +#include "base/containers/span.h" #include "base/strings/string16.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" #include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h" class Profile; @@ -38,6 +42,57 @@ class SearchTagRegistry; // (i.e., browser to JS IPC mechanisms) to the page. class OsSettingsSection { public: + // Used to construct a hierarchy of this section (i.e., which settings and + // subpages are part of this section). See RegisterHierarchy() below. + // + // Note on primary vs. alternate setting locations: Some settings are located + // in multiple spots of settings. For example, the Wi-Fi on/off toggle appears + // in both the top-level Network section as well as the Wi-Fi subpage. In + // cases like this, we consider the "primary" location as the more-targeted + // one - in this example, the Wi-Fi subpage is the primary location of the + // toggle since it is more specific to Wi-Fi, and the alternate location is + // the one embedded in the Network section. + class HierarchyGenerator { + public: + virtual ~HierarchyGenerator() = default; + + // Registers a subpage whose parent is this section. + virtual void RegisterTopLevelSubpage( + int name_message_id, + mojom::Subpage subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters) = 0; + + // Registers a subpage whose paernt is another subpage in this section. + virtual void RegisterNestedSubpage( + int name_message_id, + mojom::Subpage subpage, + mojom::Subpage parent_subpage, + mojom::SearchResultIcon icon, + mojom::SearchResultDefaultRank default_rank, + const std::string& url_path_with_parameters) = 0; + + // Registers a setting embedded directly in the section (i.e., not within a + // subpage). This functions is for primary locations (see above). + virtual void RegisterTopLevelSetting(mojom::Setting setting) = 0; + + // Registers a setting embedded within a subpage in this section. This + // function is for primary locations (see above). + virtual void RegisterNestedSetting(mojom::Setting setting, + mojom::Subpage subpage) = 0; + + // Register an alternate location for a setting embedded directly in the + // section (i.e., not within a subpage). This function is for alternate + // locations (see above). + virtual void RegisterTopLevelAltSetting(mojom::Setting setting) = 0; + + // Registers a setting embedded within a subpage in this section. This + // function is for alternate locations (see above). + virtual void RegisterNestedAltSetting(mojom::Setting setting, + mojom::Subpage subpage) = 0; + }; + virtual ~OsSettingsSection(); OsSettingsSection(const OsSettingsSection& other) = delete; @@ -51,12 +106,51 @@ class OsSettingsSection { // derived type requires one or more handlers for this section. virtual void AddHandlers(content::WebUI* web_ui) {} + // Provides the message ID for the name of this section. + virtual int GetSectionNameMessageId() const = 0; + + // Provides the Section enum for this section. + virtual mojom::Section GetSection() const = 0; + + // Provides the icon for this section. + virtual mojom::SearchResultIcon GetSectionIcon() const = 0; + + // Provides the path for this section. + virtual std::string GetSectionPath() const = 0; + + // Registers the subpages and/or settings which reside in this section. + virtual void RegisterHierarchy(HierarchyGenerator* generator) const = 0; + + // Modifies a URL to be used by settings search. Some URLs require dynamic + // content (e.g., network detail settings use the GUID of the network as a URL + // parameter to route to details for a specific network). By default, this + // function simply returns |url_to_modify|, which provides functionality for + // static URLs. + virtual std::string ModifySearchResultUrl( + mojom::SearchResultType type, + OsSettingsIdentifier id, + const std::string& url_to_modify) const; + + // Generates a search result corresponding to this section. |relevance_score| + // must be passed by the client, since this result is being created manually + // instead of via query matching. + mojom::SearchResultPtr GenerateSectionSearchResult( + double relevance_score) const; + protected: static base::string16 GetHelpUrlWithBoard(const std::string& original_url); + static void RegisterNestedSettingBulk( + mojom::Subpage, + const base::span<const mojom::Setting>& settings, + HierarchyGenerator* generator); OsSettingsSection(Profile* profile, SearchTagRegistry* search_tag_registry); + // Used by tests. + OsSettingsSection(); + Profile* profile() { return profile_; } + const Profile* profile() const { return profile_; } SearchTagRegistry* registry() { return search_tag_registry_; } private: 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 6239b2466c5..334128e8509 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 @@ -4,6 +4,7 @@ #include "chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h" +#include "build/branding_buildflags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/settings/chromeos/about_section.h" #include "chrome/browser/ui/webui/settings/chromeos/accessibility_section.h" @@ -125,16 +126,26 @@ OsSettingsSections::OsSettingsSections( sections_map_[mojom::Section::kReset] = reset_section.get(); sections_.push_back(std::move(reset_section)); +#if BUILDFLAG(GOOGLE_CHROME_BRANDING) + auto about_section = std::make_unique<AboutSection>( + profile, search_tag_registry, profile->GetPrefs()); +#else auto about_section = std::make_unique<AboutSection>(profile, search_tag_registry); +#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) sections_map_[mojom::Section::kAboutChromeOs] = about_section.get(); sections_.push_back(std::move(about_section)); } +OsSettingsSections::OsSettingsSections() = default; + OsSettingsSections::~OsSettingsSections() = default; -OsSettingsSection* OsSettingsSections::GetSection(mojom::Section section) { - return sections_map_[section]; +const OsSettingsSection* OsSettingsSections::GetSection( + mojom::Section section) const { + const auto it = sections_map_.find(section); + CHECK(it != sections_map_.end()); + return it->second; } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h index 44ddc68a34d..d1526481464 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h @@ -54,15 +54,18 @@ class OsSettingsSections { CupsPrintersManager* printers_manager); OsSettingsSections(const OsSettingsSections& other) = delete; OsSettingsSections& operator=(const OsSettingsSections& other) = delete; - ~OsSettingsSections(); + virtual ~OsSettingsSections(); - OsSettingsSection* GetSection(mojom::Section section); + const OsSettingsSection* GetSection(mojom::Section section) const; std::vector<std::unique_ptr<OsSettingsSection>>& sections() { return sections_; } - private: + protected: + // Used by tests. + OsSettingsSections(); + std::unordered_map<mojom::Section, OsSettingsSection*> sections_map_; std::vector<std::unique_ptr<OsSettingsSection>> sections_; }; 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 97f2eeab8a9..8bddd59808d 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 @@ -68,6 +68,10 @@ OSSettingsUI::OSSettingsUI(content::WebUI* web_ui) html_source->AddResourcePath("chromeos/lazy_load.html", IDR_OS_SETTINGS_LAZY_LOAD_VULCANIZED_HTML); html_source->SetDefaultResource(IDR_OS_SETTINGS_VULCANIZED_HTML); + html_source->AddResourcePath("chromeos/os_settings_v3.html", + IDR_OS_SETTINGS_OS_SETTINGS_V3_HTML); + html_source->AddResourcePath("chromeos/os_settings.js", + IDR_OS_SETTINGS_SETTINGS_ROLLUP_JS); #else webui::SetupWebUIDataSource( html_source, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc index 273e9456b69..fb9df81bbf4 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/parental_controls_handler.cc @@ -14,10 +14,10 @@ #include "chrome/browser/ui/browser_navigator.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h" -#include "chrome/services/app_service/public/cpp/app_registry_cache.h" -#include "chrome/services/app_service/public/cpp/app_update.h" -#include "chrome/services/app_service/public/mojom/types.mojom.h" #include "chromeos/constants/chromeos_features.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" +#include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/mojom/types.mojom.h" #include "ui/base/page_transition_types.h" #include "ui/base/window_open_disposition.h" #include "ui/display/types/display_constants.h" 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 45486f9eed4..e5bb33b3244 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.cc @@ -47,6 +47,7 @@ #include "components/user_manager/user_manager.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/chromeos/resources/grit/ui_chromeos_resources.h" @@ -68,7 +69,9 @@ const std::vector<SearchConcept>& GetPeopleSearchConcepts() { mojom::SearchResultIcon::kLock, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kChangeAuthPin}}, + {.setting = mojom::Setting::kChangeAuthPin}, + {IDS_OS_SETTINGS_TAG_LOCK_SCREEN_PIN_OR_PASSWORD_ALT1, + SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_USERNAMES_AND_PHOTOS, mojom::kManageOtherPeopleSubpagePath, mojom::SearchResultIcon::kAvatar, @@ -110,12 +113,6 @@ const std::vector<SearchConcept>& GetPeopleSearchConcepts() { {.setting = mojom::Setting::kLockScreen}, {IDS_OS_SETTINGS_TAG_LOCK_SCREEN_WHEN_WAKING_ALT1, SearchConcept::kAltTagEnd}}, - {IDS_OS_SETTINGS_TAG_SYNC, - mojom::kSyncSubpagePath, - mojom::SearchResultIcon::kSync, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSubpage, - {.subpage = mojom::Subpage::kSync}}, {IDS_OS_SETTINGS_TAG_PEOPLE_ACCOUNTS_REMOVE, mojom::kMyAccountsSubpagePath, mojom::SearchResultIcon::kAvatar, @@ -145,27 +142,83 @@ const std::vector<SearchConcept>& GetPeopleSearchConcepts() { return *tags; } -const std::vector<SearchConcept>& GetSyncOnSearchConcepts() { +const std::vector<SearchConcept>& GetNonSplitSyncSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_SYNC_AND_GOOGLE_SERVICES, + mojom::kSyncDeprecatedSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kSyncDeprecated}}, + {IDS_OS_SETTINGS_TAG_SYNC_MANAGEMENT, + mojom::kSyncDeprecatedAdvancedSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kSyncDeprecatedAdvanced}}, + {IDS_OS_SETTINGS_TAG_SYNC_ENCRYPTION_OPTIONS, + mojom::kSyncDeprecatedSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kNonSplitSyncEncryptionOptions}, + {IDS_OS_SETTINGS_TAG_SYNC_ENCRYPTION_OPTIONS_ALT1, + SearchConcept::kAltTagEnd}}, + {IDS_OS_SETTINGS_TAG_AUTOCOMPLETE_SEARCHES_AND_URLS, + mojom::kSyncDeprecatedSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAutocompleteSearchesAndUrls}}, + {IDS_OS_SETTINGS_TAG_MAKE_SEARCHES_AND_BROWSER_BETTER, + mojom::kSyncDeprecatedSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kMakeSearchesAndBrowsingBetter}}, + {IDS_OS_SETTINGS_TAG_GOOGLE_DRIVE_SEARCH_SUGGESTIONS, + mojom::kSyncDeprecatedSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kGoogleDriveSearchSuggestions}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetSplitSyncSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_SYNC, + mojom::kSyncSubpagePath, + mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultType::kSubpage, + {.subpage = mojom::Subpage::kSync}}, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetSplitSyncOnSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_SYNC_TURN_OFF, mojom::kSyncSubpagePath, mojom::SearchResultIcon::kSync, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kSyncOnOff}, + {.setting = mojom::Setting::kSplitSyncOnOff}, {IDS_OS_SETTINGS_TAG_SYNC_TURN_OFF_ALT1, SearchConcept::kAltTagEnd}}, }); return *tags; } -const std::vector<SearchConcept>& GetSyncOffSearchConcepts() { +const std::vector<SearchConcept>& GetSplitSyncOffSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_SYNC_TURN_ON, mojom::kSyncSubpagePath, mojom::SearchResultIcon::kSync, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kSyncOnOff}, + {.setting = mojom::Setting::kSplitSyncOnOff}, {IDS_OS_SETTINGS_TAG_SYNC_TURN_ON_ALT1, SearchConcept::kAltTagEnd}}, }); return *tags; @@ -176,25 +229,25 @@ const std::vector<SearchConcept>& GetKerberosSearchConcepts() { {IDS_OS_SETTINGS_TAG_KERBEROS_ADD, mojom::kKerberosSubpagePath, mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kAddKerberosTicket}}, {IDS_OS_SETTINGS_TAG_KERBEROS_REMOVE, mojom::kKerberosSubpagePath, mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kRemoveKerberosTicket}}, {IDS_OS_SETTINGS_TAG_KERBEROS, mojom::kKerberosSubpagePath, mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kKerberos}}, {IDS_OS_SETTINGS_TAG_KERBEROS_ACTIVE, mojom::kKerberosSubpagePath, mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kSetActiveKerberosTicket}}, }); @@ -204,19 +257,19 @@ const std::vector<SearchConcept>& GetKerberosSearchConcepts() { const std::vector<SearchConcept>& GetFingerprintSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_FINGERPRINT_REMOVE, - mojom::kFingerprintSubpathPath, + mojom::kFingerprintSubpagePath, mojom::SearchResultIcon::kFingerprint, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kRemoveFingerprint}}, {IDS_OS_SETTINGS_TAG_FINGERPRINT_ADD, - mojom::kFingerprintSubpathPath, + mojom::kFingerprintSubpagePath, mojom::SearchResultIcon::kFingerprint, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kAddFingerprint}}, {IDS_OS_SETTINGS_TAG_FINGERPRINT, - mojom::kFingerprintSubpathPath, + mojom::kFingerprintSubpagePath, mojom::SearchResultIcon::kFingerprint, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, @@ -243,7 +296,11 @@ void AddAccountManagerPageStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"accountManagerDescription", IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION}, {"accountManagerChildDescription", - IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_DESCRIPTION_2}, + IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_DESCRIPTION}, + {"accountManagerChildFirstMessage", + IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_FIRST_MESSAGE}, + {"accountManagerChildSecondMessage", + IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_SECOND_MESSAGE}, {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER}, {"accountManagerPrimaryAccountTooltip", IDS_SETTINGS_ACCOUNT_MANAGER_PRIMARY_ACCOUNT_TOOLTIP}, @@ -431,7 +488,8 @@ void AddFingerprintStrings(content::WebUIDataSource* html_source, // lottie animations, this update has to be performed manually. As the usage // increases, set this as the default so manual override is no longer // required. - html_source->OverrideContentSecurityPolicyWorkerSrc( + html_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, "worker-src blob: 'self';"); html_source->AddResourcePath("finger_print.json", IDR_LOGIN_FINGER_PRINT_TABLET_ANIMATION); @@ -531,8 +589,8 @@ void AddSyncControlsStrings(content::WebUIDataSource* html_source) { html_source->AddBoolean("splitSettingsSyncEnabled", chromeos::features::IsSplitSettingsSyncEnabled()); - html_source->AddBoolean("splitSyncConsent", - chromeos::features::IsSplitSyncConsentEnabled()); + html_source->AddBoolean("useBrowserSyncConsent", + chromeos::features::ShouldUseBrowserSyncConsent()); html_source->AddBoolean( "syncSetupFriendlySettings", base::FeatureList::IsEnabled(::features::kSyncSetupFriendlySettings)); @@ -581,6 +639,7 @@ void AddParentalControlStrings(content::WebUIDataSource* html_source, bool is_child = user_manager::UserManager::Get()->IsLoggedInAsChildUser(); html_source->AddBoolean("isChild", is_child); + base::string16 tooltip; if (is_child) { std::string custodian = supervised_user_service->GetCustodianName(); std::string second_custodian = @@ -596,9 +655,10 @@ void AddParentalControlStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_ACCOUNT_MANAGER_CHILD_MANAGED_BY_TWO_PARENTS_TOOLTIP, base::UTF8ToUTF16(custodian), base::UTF8ToUTF16(second_custodian)); } - html_source->AddString("accountManagerPrimaryAccountChildManagedTooltip", - child_managed_tooltip); + tooltip = child_managed_tooltip; } + html_source->AddString("accountManagerPrimaryAccountChildManagedTooltip", + tooltip); } } // namespace @@ -621,7 +681,8 @@ PeopleSection::PeopleSection( if (features::IsGuestModeActive()) return; - registry()->AddSearchTags(GetPeopleSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetPeopleSearchConcepts()); if (kerberos_credentials_manager_) { // Kerberos search tags are added/removed dynamically. @@ -629,28 +690,34 @@ PeopleSection::PeopleSection( OnKerberosEnabledStateChanged(); } - if (sync_service_ && chromeos::features::IsSplitSettingsSyncEnabled()) { - // Sync search tags are added/removed dynamically. - sync_service_->AddObserver(this); - OnStateChanged(sync_service_); + if (chromeos::features::IsSplitSettingsSyncEnabled()) { + if (sync_service_) { + updater.AddSearchTags(GetSplitSyncSearchConcepts()); + + // Sync search tags are added/removed dynamically. + sync_service_->AddObserver(this); + OnStateChanged(sync_service_); + } + } else { + updater.AddSearchTags(GetNonSplitSyncSearchConcepts()); } // Parental control search tags are added if necessary and do not update // dynamically during a user session. if (features::ShouldShowParentalControlSettings(profile)) - registry()->AddSearchTags(GetParentalSearchConcepts()); + updater.AddSearchTags(GetParentalSearchConcepts()); // Fingerprint search tags are added if necessary and do not update // dynamically during a user session. if (AreFingerprintSettingsAllowed()) - registry()->AddSearchTags(GetFingerprintSearchConcepts()); + updater.AddSearchTags(GetFingerprintSearchConcepts()); } PeopleSection::~PeopleSection() { if (kerberos_credentials_manager_) kerberos_credentials_manager_->RemoveObserver(this); - if (sync_service_ && chromeos::features::IsSplitSettingsSyncEnabled()) + if (chromeos::features::IsSplitSettingsSyncEnabled() && sync_service_) sync_service_->RemoveObserver(this); } @@ -678,7 +745,7 @@ void PeopleSection::AddLoadTimeData(content::WebUIDataSource* html_source) { html_source->AddBoolean("isAccountManagerEnabled", chromeos::IsAccountManagerAvailable(profile())); - if (chromeos::features::IsSplitSyncConsentEnabled()) { + if (chromeos::features::ShouldUseBrowserSyncConsent()) { static constexpr webui::LocalizedString kTurnOffStrings[] = { {"syncDisconnect", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF}, {"syncDisconnectTitle", @@ -785,24 +852,144 @@ void PeopleSection::AddHandlers(content::WebUI* web_ui) { } } +int PeopleSection::GetSectionNameMessageId() const { + return IDS_OS_SETTINGS_PEOPLE; +} + +mojom::Section PeopleSection::GetSection() const { + return mojom::Section::kPeople; +} + +mojom::SearchResultIcon PeopleSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kAvatar; +} + +std::string PeopleSection::GetSectionPath() const { + return mojom::kPeopleSectionPath; +} + +void PeopleSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kSetUpParentalControls); + + // My accounts. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE, mojom::Subpage::kMyAccounts, + mojom::SearchResultIcon::kAvatar, mojom::SearchResultDefaultRank::kMedium, + mojom::kMyAccountsSubpagePath); + static constexpr mojom::Setting kMyAccountsSettings[] = { + mojom::Setting::kAddAccount, + mojom::Setting::kRemoveAccount, + }; + RegisterNestedSettingBulk(mojom::Subpage::kMyAccounts, kMyAccountsSettings, + generator); + + // Combined browser/OS sync. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES, + mojom::Subpage::kSyncDeprecated, mojom::SearchResultIcon::kSync, + mojom::SearchResultDefaultRank::kMedium, + mojom::kSyncDeprecatedSubpagePath); + static constexpr mojom::Setting kSyncDeprecatedSettings[] = { + mojom::Setting::kNonSplitSyncEncryptionOptions, + mojom::Setting::kAutocompleteSearchesAndUrls, + mojom::Setting::kMakeSearchesAndBrowsingBetter, + mojom::Setting::kGoogleDriveSearchSuggestions, + }; + RegisterNestedSettingBulk(mojom::Subpage::kSyncDeprecated, + kSyncDeprecatedSettings, generator); + generator->RegisterNestedSubpage( + IDS_SETTINGS_SYNC_ADVANCED_PAGE_TITLE, + mojom::Subpage::kSyncDeprecatedAdvanced, mojom::Subpage::kSyncDeprecated, + mojom::SearchResultIcon::kSync, mojom::SearchResultDefaultRank::kMedium, + mojom::kSyncDeprecatedAdvancedSubpagePath); + + // OS sync. + generator->RegisterTopLevelSubpage( + IDS_OS_SETTINGS_SYNC_PAGE_TITLE, mojom::Subpage::kSync, + mojom::SearchResultIcon::kSync, mojom::SearchResultDefaultRank::kMedium, + mojom::kSyncSubpagePath); + generator->RegisterNestedSetting(mojom::Setting::kSplitSyncOnOff, + mojom::Subpage::kSync); + + // Security and sign-in. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_PEOPLE_LOCK_SCREEN_TITLE_LOGIN_LOCK, + mojom::Subpage::kSecurityAndSignIn, mojom::SearchResultIcon::kLock, + mojom::SearchResultDefaultRank::kMedium, + mojom::kSecurityAndSignInSubpagePath); + static constexpr mojom::Setting kSecurityAndSignInSettings[] = { + mojom::Setting::kLockScreen, + mojom::Setting::kChangeAuthPin, + }; + RegisterNestedSettingBulk(mojom::Subpage::kSecurityAndSignIn, + kSecurityAndSignInSettings, generator); + + // Fingerprint. + generator->RegisterNestedSubpage( + IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SUBPAGE_TITLE, + mojom::Subpage::kFingerprint, mojom::Subpage::kSecurityAndSignIn, + mojom::SearchResultIcon::kFingerprint, + mojom::SearchResultDefaultRank::kMedium, mojom::kFingerprintSubpagePath); + static constexpr mojom::Setting kFingerprintSettings[] = { + mojom::Setting::kAddFingerprint, + mojom::Setting::kRemoveFingerprint, + }; + RegisterNestedSettingBulk(mojom::Subpage::kFingerprint, kFingerprintSettings, + generator); + + // Manage other people. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_PEOPLE_MANAGE_OTHER_PEOPLE, + mojom::Subpage::kManageOtherPeople, + mojom::SearchResultIcon::kAvatar, + mojom::SearchResultDefaultRank::kMedium, + mojom::kManageOtherPeopleSubpagePath); + static constexpr mojom::Setting kManageOtherPeopleSettings[] = { + mojom::Setting::kGuestBrowsing, + mojom::Setting::kShowUsernamesAndPhotosAtSignIn, + mojom::Setting::kRestrictSignIn, + mojom::Setting::kAddToUserWhitelist, + mojom::Setting::kRemoveFromUserWhitelist, + }; + RegisterNestedSettingBulk(mojom::Subpage::kManageOtherPeople, + kManageOtherPeopleSettings, generator); + + // Kerberos. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_KERBEROS_ACCOUNTS_PAGE_TITLE, mojom::Subpage::kKerberos, + mojom::SearchResultIcon::kAvatar, mojom::SearchResultDefaultRank::kMedium, + mojom::kKerberosSubpagePath); + static constexpr mojom::Setting kKerberosSettings[] = { + mojom::Setting::kAddKerberosTicket, + mojom::Setting::kRemoveKerberosTicket, + mojom::Setting::kSetActiveKerberosTicket, + }; + RegisterNestedSettingBulk(mojom::Subpage::kKerberos, kKerberosSettings, + generator); +} + void PeopleSection::OnStateChanged(syncer::SyncService* sync_service) { DCHECK(chromeos::features::IsSplitSettingsSyncEnabled()); DCHECK_EQ(sync_service, sync_service_); + + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (sync_service_->IsEngineInitialized() && sync_service_->GetUserSettings()->IsOsSyncFeatureEnabled()) { - registry()->AddSearchTags(GetSyncOnSearchConcepts()); - registry()->RemoveSearchTags(GetSyncOffSearchConcepts()); + updater.AddSearchTags(GetSplitSyncOnSearchConcepts()); + updater.RemoveSearchTags(GetSplitSyncOffSearchConcepts()); } else { - registry()->RemoveSearchTags(GetSyncOnSearchConcepts()); - registry()->AddSearchTags(GetSyncOffSearchConcepts()); + updater.RemoveSearchTags(GetSplitSyncOnSearchConcepts()); + updater.AddSearchTags(GetSplitSyncOffSearchConcepts()); } } void PeopleSection::OnKerberosEnabledStateChanged() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (kerberos_credentials_manager_->IsKerberosEnabled()) - registry()->AddSearchTags(GetKerberosSearchConcepts()); + updater.AddSearchTags(GetKerberosSearchConcepts()); else - registry()->RemoveSearchTags(GetKerberosSearchConcepts()); + updater.RemoveSearchTags(GetKerberosSearchConcepts()); } void PeopleSection::AddKerberosAccountsPageStrings( @@ -833,8 +1020,10 @@ void PeopleSection::AddKerberosAccountsPageStrings( // Toggles the Chrome OS Kerberos Accounts submenu in the People section. // Note that the handler is also dependent on this pref. - html_source->AddBoolean("isKerberosEnabled", - kerberos_credentials_manager_->IsKerberosEnabled()); + html_source->AddBoolean( + "isKerberosEnabled", + kerberos_credentials_manager_ != nullptr && + kerberos_credentials_manager_->IsKerberosEnabled()); PrefService* local_state = g_browser_process->local_state(); 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 d10c6805d22..51e8a4b3ea8 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/people_section.h @@ -54,6 +54,11 @@ class PeopleSection : public OsSettingsSection, // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // syncer::SyncServiceObserver: void OnStateChanged(syncer::SyncService* sync_service) override; 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 e7b9d760bc5..dfbbaf17853 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.cc @@ -48,7 +48,7 @@ const std::vector<SearchConcept>& GetPersonalizationSearchConcepts() { {IDS_OS_SETTINGS_TAG_CHANGE_DEVICE_ACCOUNT_IMAGE, mojom::kChangePictureSubpagePath, mojom::SearchResultIcon::kAvatar, - mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kChangePicture}, {IDS_OS_SETTINGS_TAG_CHANGE_DEVICE_ACCOUNT_IMAGE_ALT1, @@ -60,6 +60,7 @@ const std::vector<SearchConcept>& GetPersonalizationSearchConcepts() { return *tags; } +// TODO(b/159766700): Add search concepts for |kAmbientModePhotosSubpagePath|. const std::vector<SearchConcept>& GetAmbientModeSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_AMBIENT_MODE, @@ -122,10 +123,11 @@ PersonalizationSection::PersonalizationSection( if (features::IsGuestModeActive()) return; - registry()->AddSearchTags(GetPersonalizationSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetPersonalizationSearchConcepts()); if (IsAmbientModeAllowed()) { - registry()->AddSearchTags(GetAmbientModeSearchConcepts()); + updater.AddSearchTags(GetAmbientModeSearchConcepts()); pref_change_registrar_.Init(pref_service_); pref_change_registrar_.Add( @@ -197,13 +199,69 @@ void PersonalizationSection::AddHandlers(content::WebUI* web_ui) { } } +int PersonalizationSection::GetSectionNameMessageId() const { + return IDS_OS_SETTINGS_PERSONALIZATION; +} + +mojom::Section PersonalizationSection::GetSection() const { + return mojom::Section::kPersonalization; +} + +mojom::SearchResultIcon PersonalizationSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kPaintbrush; +} + +std::string PersonalizationSection::GetSectionPath() const { + return mojom::kPersonalizationSectionPath; +} + +void PersonalizationSection::RegisterHierarchy( + HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kOpenWallpaper); + + // Change picture. + generator->RegisterTopLevelSubpage( + IDS_OS_SETTINGS_CHANGE_PICTURE_TITLE, mojom::Subpage::kChangePicture, + mojom::SearchResultIcon::kAvatar, mojom::SearchResultDefaultRank::kMedium, + mojom::kChangePictureSubpagePath); + generator->RegisterNestedSetting(mojom::Setting::kChangeDeviceAccountImage, + mojom::Subpage::kChangePicture); + + // Ambient mode. + generator->RegisterTopLevelSubpage( + IDS_OS_SETTINGS_AMBIENT_MODE_TITLE, mojom::Subpage::kAmbientMode, + mojom::SearchResultIcon::kWallpaper, + mojom::SearchResultDefaultRank::kMedium, mojom::kAmbientModeSubpagePath); + static constexpr mojom::Setting kAmbientModeSettings[] = { + mojom::Setting::kAmbientModeOnOff, + mojom::Setting::kAmbientModeSource, + }; + RegisterNestedSettingBulk(mojom::Subpage::kAmbientMode, kAmbientModeSettings, + generator); + + // Note: The subpage name in the UI is updated dynamically based on the topic + // source. + // TODO(b/159766700): Create a string for the page title and strings for the + // search. + generator->RegisterNestedSubpage( + IDS_OS_SETTINGS_AMBIENT_MODE_TITLE, mojom::Subpage::kAmbientModePhotos, + mojom::Subpage::kAmbientMode, mojom::SearchResultIcon::kWallpaper, + mojom::SearchResultDefaultRank::kMedium, + mojom::kAmbientModePhotosSubpagePath); + generator->RegisterNestedSetting( + mojom::Setting::kAmbientModeUpdatePhotosContainers, + mojom::Subpage::kAmbientModePhotos); +} + void PersonalizationSection::OnAmbientModeEnabledStateChanged() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + if (pref_service_->GetBoolean(ash::ambient::prefs::kAmbientModeEnabled)) { - registry()->AddSearchTags(GetAmbientModeOnSearchConcepts()); - registry()->RemoveSearchTags(GetAmbientModeOffSearchConcepts()); + updater.AddSearchTags(GetAmbientModeOnSearchConcepts()); + updater.RemoveSearchTags(GetAmbientModeOffSearchConcepts()); } else { - registry()->RemoveSearchTags(GetAmbientModeOnSearchConcepts()); - registry()->AddSearchTags(GetAmbientModeOffSearchConcepts()); + updater.RemoveSearchTags(GetAmbientModeOnSearchConcepts()); + updater.AddSearchTags(GetAmbientModeOffSearchConcepts()); } } 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 b50653c34e6..f704a53d971 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/personalization_section.h @@ -33,6 +33,11 @@ class PersonalizationSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // ash::AmbientModeService::Observer: void OnAmbientModeEnabledStateChanged(); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc index 715782b0b11..38bf2e61ebc 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.cc @@ -27,11 +27,24 @@ void PluginVmHandler::RegisterMessages() { "getPluginVmSharedPathsDisplayText", base::BindRepeating( &PluginVmHandler::HandleGetPluginVmSharedPathsDisplayText, - weak_ptr_factory_.GetWeakPtr())); + base::Unretained(this))); web_ui()->RegisterMessageCallback( "removePluginVmSharedPath", base::BindRepeating(&PluginVmHandler::HandleRemovePluginVmSharedPath, - weak_ptr_factory_.GetWeakPtr())); + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "wouldPermissionChangeRequireRelaunch", + base::BindRepeating( + &PluginVmHandler::HandleWouldPermissionChangeRequireRelaunch, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setPluginVmPermission", + base::BindRepeating(&PluginVmHandler::HandleSetPluginVmPermission, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "relaunchPluginVm", + base::BindRepeating(&PluginVmHandler::HandleRelaunchPluginVm, + base::Unretained(this))); } void PluginVmHandler::HandleGetPluginVmSharedPathsDisplayText( @@ -68,5 +81,42 @@ void PluginVmHandler::HandleRemovePluginVmSharedPath( path)); } +void PluginVmHandler::HandleWouldPermissionChangeRequireRelaunch( + const base::ListValue* args) { + AllowJavascript(); + CHECK_EQ(3U, args->GetSize()); + std::string callback_id = args->GetList()[0].GetString(); + plugin_vm::PermissionType permission_type = + static_cast<plugin_vm::PermissionType>(args->GetList()[1].GetInt()); + DCHECK(permission_type == plugin_vm::PermissionType::kCamera || + permission_type == plugin_vm::PermissionType::kMicrophone); + plugin_vm::PluginVmManager* manager = + plugin_vm::PluginVmManagerFactory::GetForProfile(profile_); + bool current_value = manager->GetPermission(permission_type); + bool proposed_value = args->GetList()[2].GetBool(); + bool requires_relaunch = proposed_value != current_value && + manager->IsRelaunchNeededForNewPermissions(); + + ResolveJavascriptCallback(base::Value(callback_id), + base::Value(requires_relaunch)); +} + +void PluginVmHandler::HandleSetPluginVmPermission(const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + plugin_vm::PermissionType permission_type = + static_cast<plugin_vm::PermissionType>(args->GetList()[0].GetInt()); + bool proposed_value = args->GetList()[1].GetBool(); + DCHECK(permission_type == plugin_vm::PermissionType::kCamera || + permission_type == plugin_vm::PermissionType::kMicrophone); + plugin_vm::PluginVmManagerFactory::GetForProfile(profile_)->SetPermission( + permission_type, proposed_value); +} + +void PluginVmHandler::HandleRelaunchPluginVm(const base::ListValue* args) { + CHECK_EQ(0U, args->GetList().size()); + plugin_vm::PluginVmManagerFactory::GetForProfile(profile_) + ->RelaunchPluginVm(); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h index d57b34da1db..e1d77e24424 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/plugin_vm_handler.h @@ -8,6 +8,8 @@ #include <vector> #include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager.h" +#include "chrome/browser/chromeos/plugin_vm/plugin_vm_manager_factory.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" class Profile; @@ -32,8 +34,16 @@ class PluginVmHandler : public ::settings::SettingsPageUIHandler { void HandleGetPluginVmSharedPathsDisplayText(const base::ListValue* args); // Remove a specified path from being shared. void HandleRemovePluginVmSharedPath(const base::ListValue* args); + // Checks if Plugin VM would need to be relaunched if the proposed changes are + // made. + void HandleWouldPermissionChangeRequireRelaunch(const base::ListValue* args); + // Sets the specified permission to the value proposed. + void HandleSetPluginVmPermission(const base::ListValue* args); + // Relaunches Plugin VM. + void HandleRelaunchPluginVm(const base::ListValue* args); Profile* profile_; + // weak_ptr_factory_ should always be last member. base::WeakPtrFactory<PluginVmHandler> weak_ptr_factory_{this}; 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 3415a894f61..168efe1d2d6 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.cc @@ -28,10 +28,7 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { mojom::SearchResultIcon::kPrinter, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAddPrinter}, - {IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER_ALT1, - IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER_ALT2, - SearchConcept::kAltTagEnd}}, + {.setting = mojom::Setting::kAddPrinter}}, {IDS_OS_SETTINGS_TAG_PRINTING_SAVED_PRINTERS, mojom::kPrintingDetailsSubpagePath, mojom::SearchResultIcon::kPrinter, @@ -41,7 +38,7 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { {IDS_OS_SETTINGS_TAG_PRINTING, mojom::kPrintingDetailsSubpagePath, mojom::SearchResultIcon::kPrinter, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kPrintingDetails}, {IDS_OS_SETTINGS_TAG_PRINTING_ALT1, IDS_OS_SETTINGS_TAG_PRINTING_ALT2, @@ -76,9 +73,10 @@ PrintingSection::PrintingSection(Profile* profile, CupsPrintersManager* printers_manager) : OsSettingsSection(profile, search_tag_registry), printers_manager_(printers_manager) { - registry()->AddSearchTags(GetPrintingSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetPrintingSearchConcepts()); if (IsPrintManagementEnabled()) - registry()->AddSearchTags(GetPrintingManagementSearchConcepts()); + updater.AddSearchTags(GetPrintingManagementSearchConcepts()); } PrintingSection::~PrintingSection() = default; @@ -246,5 +244,38 @@ void PrintingSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<CupsPrintersHandler>(profile(), printers_manager_)); } +int PrintingSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_PRINTING; +} + +mojom::Section PrintingSection::GetSection() const { + return mojom::Section::kPrinting; +} + +mojom::SearchResultIcon PrintingSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kPrinter; +} + +std::string PrintingSection::GetSectionPath() const { + return mojom::kPrintingSectionPath; +} + +void PrintingSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kPrintJobs); + + // Printing details. + generator->RegisterTopLevelSubpage(IDS_SETTINGS_PRINTING_CUPS_PRINTERS, + mojom::Subpage::kPrintingDetails, + mojom::SearchResultIcon::kPrinter, + mojom::SearchResultDefaultRank::kMedium, + mojom::kPrintingDetailsSubpagePath); + static constexpr mojom::Setting kPrintingDetailsSettings[] = { + mojom::Setting::kAddPrinter, + mojom::Setting::kSavedPrinters, + }; + RegisterNestedSettingBulk(mojom::Subpage::kPrintingDetails, + kPrintingDetailsSettings, generator); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.h index b231aeec420..ddef65c546e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/printing_section.h @@ -31,6 +31,11 @@ class PrintingSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; CupsPrintersManager* printers_manager_; }; 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 94e70f481b3..85c6dea6016 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.cc @@ -13,6 +13,7 @@ #include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/constants/chromeos_features.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -32,7 +33,7 @@ const std::vector<SearchConcept>& GetPrivacySearchConcepts() { {IDS_OS_SETTINGS_TAG_PRIVACY, mojom::kPrivacyAndSecuritySectionPath, mojom::SearchResultIcon::kShield, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSection, {.section = mojom::Section::kPrivacyAndSecurity}}, {IDS_OS_SETTINGS_TAG_PRIVACY_WIFI_SLEEP, @@ -68,9 +69,10 @@ const std::vector<SearchConcept>& GetPrivacyGoogleChromeSearchConcepts() { PrivacySection::PrivacySection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { - registry()->AddSearchTags(GetPrivacySearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetPrivacySearchConcepts()); #if BUILDFLAG(GOOGLE_CHROME_BRANDING) - registry()->AddSearchTags(GetPrivacyGoogleChromeSearchConcepts()); + updater.AddSearchTags(GetPrivacyGoogleChromeSearchConcepts()); #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) } @@ -84,6 +86,9 @@ void PrivacySection::AddLoadTimeData(content::WebUIDataSource* html_source) { {"wakeOnWifi", IDS_SETTINGS_WAKE_ON_WIFI_DESCRIPTION}, {"enableContentProtectionAttestation", IDS_SETTINGS_ENABLE_CONTENT_PROTECTION_ATTESTATION}, + {"enableSuggestedContent", IDS_SETTINGS_ENABLE_SUGGESTED_CONTENT_TITLE}, + {"enableSuggestedContentDesc", + IDS_SETTINGS_ENABLE_SUGGESTED_CONTENT_DESC}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); @@ -91,10 +96,40 @@ void PrivacySection::AddLoadTimeData(content::WebUIDataSource* html_source) { "privacySettingsRedesignEnabled", base::FeatureList::IsEnabled(::features::kPrivacySettingsRedesign)); + html_source->AddBoolean("suggestedContentToggleEnabled", + base::FeatureList::IsEnabled( + ::chromeos::features::kSuggestedContentToggle)); + + html_source->AddString("suggestedContentLearnMoreURL", + chrome::kSuggestedContentLearnMoreURL); + html_source->AddString("syncAndGoogleServicesLearnMoreURL", chrome::kSyncAndGoogleServicesLearnMoreURL); ::settings::AddPersonalizationOptionsStrings(html_source); } +int PrivacySection::GetSectionNameMessageId() const { + return IDS_SETTINGS_PRIVACY; +} + +mojom::Section PrivacySection::GetSection() const { + return mojom::Section::kPrivacyAndSecurity; +} + +mojom::SearchResultIcon PrivacySection::GetSectionIcon() const { + return mojom::SearchResultIcon::kShield; +} + +std::string PrivacySection::GetSectionPath() const { + return mojom::kPrivacyAndSecuritySectionPath; +} + +void PrivacySection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kVerifiedAccess); + generator->RegisterTopLevelSetting(mojom::Setting::kKeepWifiOnDuringSleep); + generator->RegisterTopLevelSetting( + mojom::Setting::kUsageStatsAndCrashReports); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.h index 3c5ba842681..4acbc9d465c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/privacy_section.h @@ -26,6 +26,11 @@ class PrivacySection : public OsSettingsSection { private: // OsSettingsSection: void AddLoadTimeData(content::WebUIDataSource* html_source) override; + int GetSectionNameMessageId() const override; + mojom::Section GetSection() const override; + mojom::SearchResultIcon GetSectionIcon() const override; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.cc index 1275fb0e188..21216088ddc 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.cc @@ -56,8 +56,9 @@ bool IsPowerwashAllowed() { ResetSection::ResetSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); if (IsPowerwashAllowed()) - registry()->AddSearchTags(GetResetSearchConcepts()); + updater.AddSearchTags(GetResetSearchConcepts()); } ResetSection::~ResetSection() = default; @@ -94,5 +95,25 @@ void ResetSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<::settings::ResetSettingsHandler>(profile())); } +int ResetSection::GetSectionNameMessageId() const { + return IDS_SETTINGS_RESET; +} + +mojom::Section ResetSection::GetSection() const { + return mojom::Section::kReset; +} + +mojom::SearchResultIcon ResetSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kReset; +} + +std::string ResetSection::GetSectionPath() const { + return mojom::kResetSectionPath; +} + +void ResetSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kPowerwash); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.h b/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.h index ee99e0554c7..90287737e66 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/reset_section.h @@ -28,6 +28,11 @@ class ResetSection : public OsSettingsSection { // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom index 4be5d33c332..d63ae03274c 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search.mojom @@ -30,6 +30,22 @@ enum SearchResultDefaultRank { kLow, }; +// Behavior used when determining whether to return parent results for a query. +// Results are returned based on whether text for those results matches the +// user's query, but we also support returning a result for the parent of the +// original result. In this context, a "parent" refers to a section or subpage +// which contains a child subpage or setting. For example, +// Subpage::kWifiNetworks is a subpage whose parent is Section::kNetwork, and +// Setting::kWifiOnOff is a setting whose parent is Subpage::kWifiNetworks. +enum ParentResultBehavior { + // Returns parent results as long as the number of maximum results is not + // exceeded. + kAllowParentResults, + + // Does not return parent results. + kDoNotIncludeParentResults, +}; + // Identifier for the result; each result describes one section, subpage, or // setting. union SearchResultIdentifier { @@ -44,6 +60,12 @@ struct SearchResult { // directly (i.e., not an ID but rather the actual text). mojo_base.mojom.String16 result_text; + // String for the "canonical" version of this result. Some search results use + // alternate text (e.g., "Monitor" instead of "Display"). Note that it is + // often the case that |result_text| and |canonical_result_text| are the same + // string. + mojo_base.mojom.String16 canonical_result_text; + // The URL path containing the relevant setting, which may or may not contain // URL parameters. For example, the Wi-Fi list settings page is // chrome://os-settings/networks?type=WiFi, so the field would be @@ -57,29 +79,57 @@ struct SearchResult { // string match. double relevance_score; - // List of names of the sections/subpages for this result, which may contain - // names of sections and/or subpages. Names are all localized String16s, ready - // to be displayed directly (e.g., as breadcrumbs). + // List of names of the ancestor sections/subpages for this result. The list + // contains the Settings app name and, if applicable, the ancestor section and + // subpage names. Names are all localized String16s which can be displayed in + // the UI (e.g., as breadcrumbs). // - // Example 1 - Wi-Fi subpage: ["Settings", "Network", "Wi-Fi"] - // Example 2 - External storage: ["Settings", "Device", "Storage management", - // "External storage preferences"] + // Example 1 - Wi-Fi subpage: ["Settings", "Network"] + // Example 2 - External storage: ["Settings", "Device", "Storage management"] array<mojo_base.mojom.String16> settings_page_hierarchy; // Default ranking, which is used to break ties when searching for results. SearchResultDefaultRank default_rank; + // True if this result was generated due to a text match; this field can be + // false if it was constructed due to a ParentResultBehavior. + bool was_generated_from_text_match; + // The type and identifier for this search result. The value of the |type| // field indicates the union member used by |id|. SearchResultType type; SearchResultIdentifier id; }; +// Used to observe changes to search results. +interface SearchResultsObserver { + // Called when the availability of one or more search results has changed. In + // this context, "availability" refers to whether a search result can be + // returned based on the user's current state. E.g., "Cellular" results are + // only shown if the device has an attached modem, so this function would be + // called whenever the user plugs in or unplugs a USB modem. Clients can use + // this function to ensure that they do not show "stale" results which are no + // longer actionable by the user. + OnSearchResultAvailabilityChanged(); +}; + // Provides settings search results. Implemented in the browser process; // intended to be called from settings JS and Launcher C++. interface SearchHandler { // Searches settings for the given query and returns a list of results, sorted // from most relevant to least relevant. An empty array indicates no relevant // results. - Search(mojo_base.mojom.String16 query) => (array<SearchResult> results); + // + // This function returns an array with a maximum size of |max_num_results|, + // but the array may contain fewer elements if there are fewer results. + // Clients should never pass a value of 0 for |max_num_results|, since that + // would return an empty result array. + Search(mojo_base.mojom.String16 query, + uint32 max_num_results, + ParentResultBehavior parent_result_behavior) => + (array<SearchResult> results); + + // Adds an observer of search results. Disconnected observers are discarded; + // to stop observing, close the connection. + Observe(pending_remote<SearchResultsObserver> observer); }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h index b3763fb0fd3..639dc470ce3 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_concept.h @@ -7,6 +7,7 @@ #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/os_settings_identifier.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom.h" @@ -58,7 +59,7 @@ struct SearchConcept { // The type and identifier for this search result. The value of the |type| // field indicates the union member used by |id|. mojom::SearchResultType type; - Identifier id; + OsSettingsIdentifier id; // Alternate message IDs (from os_settings_search_tag_strings.grdp) // corresponding to this concept. These IDs refer to messages which represent diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc index 47c0052bbf0..1bde04057b2 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc @@ -4,12 +4,14 @@ #include "chrome/browser/ui/webui/settings/chromeos/search/search_handler.h" +#include <algorithm> + #include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/local_search_service/local_search_service.h" +#include "chrome/browser/ui/webui/settings/chromeos/hierarchy.h" +#include "chrome/browser/ui/webui/settings/chromeos/os_settings_sections.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_result_icon.mojom.h" -#include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" @@ -17,30 +19,42 @@ namespace chromeos { namespace settings { namespace { -const int32_t kLocalSearchServiceMaxResults = 10; +bool ContainsSectionResult(const std::vector<mojom::SearchResultPtr>& results, + mojom::Section section) { + return std::find_if( + results.begin(), results.end(), [section](const auto& result) { + return result->type == mojom::SearchResultType::kSection && + section == result->id->get_section(); + }) != results.end(); +} -// TODO(https://crbug.com/1071700): Delete this function. -std::vector<base::string16> GenerateDummySettingsHierarchy( - const char* url_path_with_parameters) { - std::vector<base::string16> hierarchy; - hierarchy.push_back(l10n_util::GetStringUTF16(IDS_INTERNAL_APP_SETTINGS)); - hierarchy.push_back(base::ASCIIToUTF16(url_path_with_parameters)); - return hierarchy; +bool ContainsSubpageResult(const std::vector<mojom::SearchResultPtr>& results, + mojom::Subpage subpage) { + return std::find_if( + results.begin(), results.end(), [subpage](const auto& result) { + return result->type == mojom::SearchResultType::kSubpage && + subpage == result->id->get_subpage(); + }) != results.end(); } } // namespace -// static -const size_t SearchHandler::kNumMaxResults = 5; - SearchHandler::SearchHandler( SearchTagRegistry* search_tag_registry, + OsSettingsSections* sections, + Hierarchy* hierarchy, local_search_service::LocalSearchService* local_search_service) : search_tag_registry_(search_tag_registry), + sections_(sections), + hierarchy_(hierarchy), index_(local_search_service->GetIndex( - local_search_service::IndexId::kCrosSettings)) {} + local_search_service::IndexId::kCrosSettings)) { + search_tag_registry_->AddObserver(this); +} -SearchHandler::~SearchHandler() = default; +SearchHandler::~SearchHandler() { + search_tag_registry_->RemoveObserver(this); +} void SearchHandler::BindInterface( mojo::PendingReceiver<mojom::SearchHandler> pending_receiver) { @@ -48,10 +62,19 @@ void SearchHandler::BindInterface( } std::vector<mojom::SearchResultPtr> SearchHandler::Search( - const base::string16& query) { + const base::string16& query, + uint32_t max_num_results, + mojom::ParentResultBehavior parent_result_behavior) { + // Search for 5x the maximum set of results. If there are many matches for + // a query, it may be the case that |index_| returns some matches with higher + // SearchResultDefaultRank values later in the list. Requesting up to 5x the + // maximum number ensures that such results will be returned and can be ranked + // accordingly when sorted. + uint32_t max_local_search_service_results = 5 * max_num_results; + std::vector<local_search_service::Result> local_search_service_results; local_search_service::ResponseStatus response_status = index_->Find( - query, kLocalSearchServiceMaxResults, &local_search_service_results); + query, max_local_search_service_results, &local_search_service_results); if (response_status != local_search_service::ResponseStatus::kSuccess) { LOG(ERROR) << "Cannot search; LocalSearchService returned " @@ -60,41 +83,149 @@ std::vector<mojom::SearchResultPtr> SearchHandler::Search( return {}; } - return GenerateSearchResultsArray(local_search_service_results); + return GenerateSearchResultsArray(local_search_service_results, + max_num_results, parent_result_behavior); } void SearchHandler::Search(const base::string16& query, + uint32_t max_num_results, + mojom::ParentResultBehavior parent_result_behavior, SearchCallback callback) { - std::move(callback).Run(Search(query)); + std::move(callback).Run( + Search(query, max_num_results, parent_result_behavior)); +} + +void SearchHandler::Observe( + mojo::PendingRemote<mojom::SearchResultsObserver> observer) { + observers_.Add(std::move(observer)); +} + +void SearchHandler::OnRegistryUpdated() { + for (auto& observer : observers_) + observer->OnSearchResultAvailabilityChanged(); } std::vector<mojom::SearchResultPtr> SearchHandler::GenerateSearchResultsArray( const std::vector<local_search_service::Result>& - local_search_service_results) { + local_search_service_results, + uint32_t max_num_results, + mojom::ParentResultBehavior parent_result_behavior) const { std::vector<mojom::SearchResultPtr> search_results; for (const auto& result : local_search_service_results) { mojom::SearchResultPtr result_ptr = ResultToSearchResult(result); if (result_ptr) search_results.push_back(std::move(result_ptr)); + } - // Limit the number of results to return. - if (search_results.size() == kNumMaxResults) - break; + std::sort(search_results.begin(), search_results.end(), CompareSearchResults); + + // Now that the results have been sorted, limit the size of to + // |max_num_results|. + search_results.resize( + std::min(static_cast<size_t>(max_num_results), search_results.size())); + + if (parent_result_behavior == + mojom::ParentResultBehavior::kAllowParentResults) { + AddParentResults(max_num_results, &search_results); } return search_results; } -mojom::SearchResultPtr SearchHandler::ResultToSearchResult( - const local_search_service::Result& result) { - int message_id; +void SearchHandler::AddParentResults( + uint32_t max_num_results, + std::vector<mojom::SearchResultPtr>* search_results) const { + auto it = search_results->begin(); + while (search_results->size() < max_num_results && + it != search_results->end()) { + const mojom::SearchResultPtr& result = *it; + switch (result->type) { + case mojom::SearchResultType::kSection: + // Sections have no parents; nothing to do. + break; - // The result's ID is expected to be a stringified int. - if (!base::StringToInt(result.id, &message_id)) - return nullptr; + case mojom::SearchResultType::kSubpage: { + const Hierarchy::SubpageMetadata& metadata = + hierarchy_->GetSubpageMetadata(result->id->get_subpage()); + + // Nested subpage. + if (metadata.parent_subpage) { + it = AddSubpageResultIfPossible(it, *metadata.parent_subpage, + result->relevance_score, + search_results); + break; + } + + // Top-level subpage. + it = AddSectionResultIfPossible(it, result, metadata.section, + search_results); + break; + } + + case mojom::SearchResultType::kSetting: { + const Hierarchy::SettingMetadata& metadata = + hierarchy_->GetSettingMetadata(result->id->get_setting()); + + // Nested setting. + if (metadata.primary.second) { + it = AddSubpageResultIfPossible(it, *metadata.primary.second, + result->relevance_score, + search_results); + break; + } + + // Top-level setting. + it = AddSectionResultIfPossible(it, result, metadata.primary.first, + search_results); + break; + } + } + ++it; + } +} + +std::vector<mojom::SearchResultPtr>::iterator +SearchHandler::AddSectionResultIfPossible( + const std::vector<mojom::SearchResultPtr>::iterator& curr_position, + const mojom::SearchResultPtr& child_result, + mojom::Section section, + std::vector<mojom::SearchResultPtr>* results) const { + // If |results| already includes |section|, do not add it again. + if (ContainsSectionResult(*results, section)) + return curr_position; + + mojom::SearchResultPtr section_result = + hierarchy_->GetSectionMetadata(section).ToSearchResult( + child_result->relevance_score); + + // Don't add a result for a parent section if it has the exact same text as + // the child result, since this results in a broken-looking UI. + if (section_result->result_text == child_result->result_text) + return curr_position; + + return results->insert(curr_position + 1, std::move(section_result)); +} + +std::vector<mojom::SearchResultPtr>::iterator +SearchHandler::AddSubpageResultIfPossible( + const std::vector<mojom::SearchResultPtr>::iterator& curr_position, + mojom::Subpage subpage, + double relevance_score, + std::vector<mojom::SearchResultPtr>* results) const { + // If |results| already includes |subpage|, do not add it again. + if (ContainsSubpageResult(*results, subpage)) + return curr_position; + + return results->insert( + curr_position + 1, + hierarchy_->GetSubpageMetadata(subpage).ToSearchResult(relevance_score)); +} + +mojom::SearchResultPtr SearchHandler::ResultToSearchResult( + const local_search_service::Result& result) const { const SearchConcept* concept = - search_tag_registry_->GetCanonicalTagMetadata(message_id); + search_tag_registry_->GetTagMetadata(result.id); // If the concept was not registered, no metadata is available. This can occur // if the search tag was dynamically unregistered during the asynchronous @@ -102,29 +233,85 @@ mojom::SearchResultPtr SearchHandler::ResultToSearchResult( if (!concept) return nullptr; + // |result| is expected to have one position, whose ID is a stringified int. + DCHECK_EQ(1u, result.positions.size()); + int content_id; + if (!base::StringToInt(result.positions[0].content_id, &content_id)) + return nullptr; + + std::string url; mojom::SearchResultIdentifierPtr result_id; + std::vector<base::string16> hierarchy_strings; switch (concept->type) { - case mojom::SearchResultType::kSection: - result_id = - mojom::SearchResultIdentifier::NewSection(concept->id.section); + case mojom::SearchResultType::kSection: { + mojom::Section section = concept->id.section; + url = GetModifiedUrl(*concept, section); + result_id = mojom::SearchResultIdentifier::NewSection(section); + hierarchy_strings.push_back( + l10n_util::GetStringUTF16(IDS_INTERNAL_APP_SETTINGS)); break; - case mojom::SearchResultType::kSubpage: - result_id = - mojom::SearchResultIdentifier::NewSubpage(concept->id.subpage); + } + case mojom::SearchResultType::kSubpage: { + mojom::Subpage subpage = concept->id.subpage; + url = GetModifiedUrl(*concept, + hierarchy_->GetSubpageMetadata(subpage).section); + result_id = mojom::SearchResultIdentifier::NewSubpage(subpage); + hierarchy_strings = hierarchy_->GenerateAncestorHierarchyStrings(subpage); break; - case mojom::SearchResultType::kSetting: - result_id = - mojom::SearchResultIdentifier::NewSetting(concept->id.setting); + } + case mojom::SearchResultType::kSetting: { + mojom::Setting setting = concept->id.setting; + url = GetModifiedUrl( + *concept, hierarchy_->GetSettingMetadata(setting).primary.first); + result_id = mojom::SearchResultIdentifier::NewSetting(setting); + hierarchy_strings = hierarchy_->GenerateAncestorHierarchyStrings(setting); break; + } } - // TODO(https://crbug.com/1071700): Generate real hierarchy instead of using - // GenerateDummySettingsHierarchy(). return mojom::SearchResult::New( - l10n_util::GetStringUTF16(message_id), concept->url_path_with_parameters, - concept->icon, result.score, - GenerateDummySettingsHierarchy(concept->url_path_with_parameters), - concept->default_rank, concept->type, std::move(result_id)); + /*result_text=*/l10n_util::GetStringUTF16(content_id), + /*canonical_result_text=*/ + l10n_util::GetStringUTF16(concept->canonical_message_id), url, + concept->icon, result.score, hierarchy_strings, concept->default_rank, + /*was_generated_from_text_match=*/true, concept->type, + std::move(result_id)); +} + +std::string SearchHandler::GetModifiedUrl(const SearchConcept& concept, + mojom::Section section) const { + return sections_->GetSection(section)->ModifySearchResultUrl( + concept.type, concept.id, concept.url_path_with_parameters); +} + +// static +bool SearchHandler::CompareSearchResults(const mojom::SearchResultPtr& first, + const mojom::SearchResultPtr& second) { + // Compute the difference between the results' default rankings. Note that + // kHigh is declared before kMedium which is declared before kLow, so a + // negative value indicates that |first| is ranked higher than |second| and a + // positive value indicates that |second| is ranked higher than |first|. + int32_t default_rank_diff = static_cast<int32_t>(first->default_rank) - + static_cast<int32_t>(second->default_rank); + if (default_rank_diff < 0) + return true; + if (default_rank_diff > 0) + return false; + + // At this point, the default ranks are equal, so compare relevance scores. A + // higher relevance score indicates a better text match, so the reverse is + // true this time. + if (first->relevance_score > second->relevance_score) + return true; + if (first->relevance_score < second->relevance_score) + return false; + + // Default rank and relevance scores are equal, so prefer the result which is + // higher on the hierarchy. kSection is declared before kSubpage which is + // declared before kSetting, so follow the same pattern from default ranks + // above. Note that if the types are equal, this will return false, which + // induces a strict weak ordering. + return static_cast<int32_t>(first->type) < static_cast<int32_t>(second->type); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h index 8247cccaa9d..2425c2b56ac 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler.h @@ -7,12 +7,16 @@ #include <vector> +#include "base/gtest_prod_util.h" #include "base/optional.h" #include "chrome/browser/chromeos/local_search_service/index.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom.h" +#include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" #include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "mojo/public/cpp/bindings/remote.h" +#include "mojo/public/cpp/bindings/remote_set.h" namespace local_search_service { class LocalSearchService; @@ -21,7 +25,9 @@ class LocalSearchService; namespace chromeos { namespace settings { -class SearchTagRegistry; +class Hierarchy; +class OsSettingsSections; +struct SearchConcept; // Handles search queries for Chrome OS settings. Search() is expected to be // invoked by the settings UI as well as the the Launcher search UI. Search @@ -29,14 +35,13 @@ class SearchTagRegistry; // indexed in the LocalSearchService and cross-referencing results with // SearchTagRegistry. // -// SearchHandler returns at most |kNumMaxResults| results; searches which do not -// provide any matches result in an empty results array. -class SearchHandler : public mojom::SearchHandler { +// Searches which do not provide any matches result in an empty results array. +class SearchHandler : public mojom::SearchHandler, + public SearchTagRegistry::Observer { public: - // Maximum number of results returned by a Search() call. - static const size_t kNumMaxResults; - SearchHandler(SearchTagRegistry* search_tag_registry, + OsSettingsSections* sections, + Hierarchy* hierarchy, local_search_service::LocalSearchService* local_search_service); ~SearchHandler() override; @@ -47,23 +52,64 @@ class SearchHandler : public mojom::SearchHandler { mojo::PendingReceiver<mojom::SearchHandler> pending_receiver); // Synchronous search implementation (for in-process clients). - std::vector<mojom::SearchResultPtr> Search(const base::string16& query); + std::vector<mojom::SearchResultPtr> Search( + const base::string16& query, + uint32_t max_num_results, + mojom::ParentResultBehavior parent_result_behavior); // mojom::SearchHandler: - void Search(const base::string16& query, SearchCallback callback) override; + void Search(const base::string16& query, + uint32_t max_num_results, + mojom::ParentResultBehavior parent_result_behavior, + SearchCallback callback) override; + void Observe( + mojo::PendingRemote<mojom::SearchResultsObserver> observer) override; private: + FRIEND_TEST_ALL_PREFIXES(SearchHandlerTest, CompareSearchResults); + + // SearchTagRegistry::Observer: + void OnRegistryUpdated() override; + std::vector<mojom::SearchResultPtr> GenerateSearchResultsArray( const std::vector<local_search_service::Result>& - local_search_service_results); + local_search_service_results, + uint32_t max_num_results, + mojom::ParentResultBehavior parent_result_behavior) const; + + void AddParentResults( + uint32_t max_num_results, + std::vector<mojom::SearchResultPtr>* search_results) const; + + std::vector<mojom::SearchResultPtr>::iterator AddSectionResultIfPossible( + const std::vector<mojom::SearchResultPtr>::iterator& position, + const mojom::SearchResultPtr& child_result, + mojom::Section section, + std::vector<mojom::SearchResultPtr>* results) const; + + std::vector<mojom::SearchResultPtr>::iterator AddSubpageResultIfPossible( + const std::vector<mojom::SearchResultPtr>::iterator& position, + mojom::Subpage subpage, + double relevance_score, + std::vector<mojom::SearchResultPtr>* results) const; + mojom::SearchResultPtr ResultToSearchResult( - const local_search_service::Result& result); + const local_search_service::Result& result) const; + std::string GetModifiedUrl(const SearchConcept& concept, + mojom::Section section) const; + + // Returns true if |first| should be ranked before |second|. + static bool CompareSearchResults(const mojom::SearchResultPtr& first, + const mojom::SearchResultPtr& second); SearchTagRegistry* search_tag_registry_; + OsSettingsSections* sections_; + Hierarchy* hierarchy_; local_search_service::Index* index_; - // Note: Expected to have multiple clients, so a ReceiverSet is used. + // Note: Expected to have multiple clients, so ReceiverSet/RemoteSet are used. mojo::ReceiverSet<mojom::SearchHandler> receivers_; + mojo::RemoteSet<mojom::SearchResultsObserver> observers_; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc index f2c9d42af8d..d0ecd2baef6 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_handler_unittest.cc @@ -10,17 +10,41 @@ #include "base/test/task_environment.h" #include "chrome/browser/chromeos/local_search_service/local_search_service.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" +#include "chrome/browser/ui/webui/settings/chromeos/fake_hierarchy.h" +#include "chrome/browser/ui/webui/settings/chromeos/fake_os_settings_sections.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search.mojom-test-utils.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" #include "chrome/grit/generated_resources.h" #include "chromeos/constants/chromeos_features.h" #include "mojo/public/cpp/bindings/remote.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/l10n/l10n_util.h" namespace chromeos { namespace settings { namespace { +class FakeObserver : public mojom::SearchResultsObserver { + public: + FakeObserver() = default; + ~FakeObserver() override = default; + + mojo::PendingRemote<mojom::SearchResultsObserver> GenerateRemote() { + mojo::PendingRemote<mojom::SearchResultsObserver> remote; + receiver_.Bind(remote.InitWithNewPipeAndPassReceiver()); + return remote; + } + + size_t num_calls() const { return num_calls_; } + + private: + // mojom::SearchResultsObserver: + void OnSearchResultAvailabilityChanged() override { ++num_calls_; } + + size_t num_calls_ = 0; + mojo::Receiver<mojom::SearchResultsObserver> receiver_{this}; +}; + // Note: Copied from printing_section.cc but does not need to stay in sync with // it. const std::vector<SearchConcept>& GetPrintingSearchConcepts() { @@ -30,10 +54,7 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { mojom::SearchResultIcon::kPrinter, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAddPrinter}, - {IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER_ALT1, - IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER_ALT2, - SearchConcept::kAltTagEnd}}, + {.setting = mojom::Setting::kAddPrinter}}, {IDS_OS_SETTINGS_TAG_PRINTING_SAVED_PRINTERS, mojom::kPrintingDetailsSubpagePath, mojom::SearchResultIcon::kPrinter, @@ -43,7 +64,7 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { {IDS_OS_SETTINGS_TAG_PRINTING, mojom::kPrintingDetailsSubpagePath, mojom::SearchResultIcon::kPrinter, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kLow, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kPrintingDetails}, {IDS_OS_SETTINGS_TAG_PRINTING_ALT1, IDS_OS_SETTINGS_TAG_PRINTING_ALT2, @@ -52,13 +73,30 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { return *tags; } +// Creates a result with some default values. +mojom::SearchResultPtr CreateDummyResult() { + return mojom::SearchResult::New( + /*result_text=*/base::string16(), + /*canonical_result_text=*/base::string16(), /*url=*/"", + mojom::SearchResultIcon::kPrinter, /*relevance_score=*/0.5, + /*hierarchy_strings=*/std::vector<base::string16>(), + mojom::SearchResultDefaultRank::kMedium, + /*was_generated_from_text_match=*/false, + mojom::SearchResultType::kSection, + mojom::SearchResultIdentifier::NewSection(mojom::Section::kPrinting)); +} + } // namespace class SearchHandlerTest : public testing::Test { protected: SearchHandlerTest() : search_tag_registry_(&local_search_service_), - handler_(&search_tag_registry_, &local_search_service_) {} + fake_hierarchy_(&fake_sections_), + handler_(&search_tag_registry_, + &fake_sections_, + &fake_hierarchy_, + &local_search_service_) {} ~SearchHandlerTest() override = default; // testing::Test: @@ -66,37 +104,209 @@ class SearchHandlerTest : public testing::Test { scoped_feature_list_.InitAndEnableFeature( chromeos::features::kNewOsSettingsSearch); handler_.BindInterface(handler_remote_.BindNewPipeAndPassReceiver()); + + fake_hierarchy_.AddSubpageMetadata( + IDS_SETTINGS_PRINTING_CUPS_PRINTERS, mojom::Section::kPrinting, + mojom::Subpage::kPrintingDetails, mojom::SearchResultIcon::kPrinter, + mojom::SearchResultDefaultRank::kMedium, + mojom::kPrintingDetailsSubpagePath); + fake_hierarchy_.AddSettingMetadata(mojom::Section::kPrinting, + mojom::Setting::kAddPrinter); + fake_hierarchy_.AddSettingMetadata(mojom::Section::kPrinting, + mojom::Setting::kSavedPrinters); + + handler_remote_->Observe(observer_.GenerateRemote()); + handler_remote_.FlushForTesting(); + } + + void AddSearchTags(const std::vector<SearchConcept>& search_tags) { + SearchTagRegistry::ScopedTagUpdater updater = + search_tag_registry_.StartUpdate(); + updater.AddSearchTags(search_tags); + } + + void RemoveSearchTags(const std::vector<SearchConcept>& search_tags) { + SearchTagRegistry::ScopedTagUpdater updater = + search_tag_registry_.StartUpdate(); + updater.RemoveSearchTags(search_tags); } base::test::TaskEnvironment task_environment_; base::test::ScopedFeatureList scoped_feature_list_; local_search_service::LocalSearchService local_search_service_; SearchTagRegistry search_tag_registry_; + FakeOsSettingsSections fake_sections_; + FakeHierarchy fake_hierarchy_; SearchHandler handler_; mojo::Remote<mojom::SearchHandler> handler_remote_; + FakeObserver observer_; }; TEST_F(SearchHandlerTest, AddAndRemove) { - // Add printing search tags to registry and search for "Printing". - search_tag_registry_.AddSearchTags(GetPrintingSearchConcepts()); + // Add printing search tags to registry and search for "Print". + AddSearchTags(GetPrintingSearchConcepts()); + handler_remote_.FlushForTesting(); + EXPECT_EQ(1u, observer_.num_calls()); + std::vector<mojom::SearchResultPtr> search_results; + + // 3 results should be available for a "Print" query. mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) - .Search(base::ASCIIToUTF16("Printing"), &search_results); + .Search(base::ASCIIToUTF16("Print"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kDoNotIncludeParentResults, + &search_results); + EXPECT_EQ(search_results.size(), 3u); - // Multiple results should be available. - EXPECT_GT(search_results.size(), 0u); + // Limit results to 1 max and ensure that only 1 result is returned. + mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) + .Search(base::ASCIIToUTF16("Print"), + /*max_num_results=*/1u, + mojom::ParentResultBehavior::kDoNotIncludeParentResults, + &search_results); + EXPECT_EQ(search_results.size(), 1u); // Search for a query which should return no results. mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) - .Search(base::ASCIIToUTF16("QueryWithNoResults"), &search_results); + .Search(base::ASCIIToUTF16("QueryWithNoResults"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kDoNotIncludeParentResults, + &search_results); EXPECT_TRUE(search_results.empty()); // Remove printing search tags to registry and verify that no results are // returned for "Printing". - search_tag_registry_.RemoveSearchTags(GetPrintingSearchConcepts()); + RemoveSearchTags(GetPrintingSearchConcepts()); mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) - .Search(base::ASCIIToUTF16("Printing"), &search_results); + .Search(base::ASCIIToUTF16("Print"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kDoNotIncludeParentResults, + &search_results); EXPECT_TRUE(search_results.empty()); + EXPECT_EQ(2u, observer_.num_calls()); +} + +TEST_F(SearchHandlerTest, UrlModification) { + // Add printing search tags to registry and search for "Saved". + AddSearchTags(GetPrintingSearchConcepts()); + std::vector<mojom::SearchResultPtr> search_results; + mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) + .Search(base::ASCIIToUTF16("Saved"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kDoNotIncludeParentResults, + &search_results); + + // Only the "saved printers" item should be returned. + EXPECT_EQ(search_results.size(), 1u); + + // The URL should have bee modified according to the FakeOsSettingSection + // scheme. + EXPECT_EQ( + std::string("Section::kPrinting::") + mojom::kPrintingDetailsSubpagePath, + search_results[0]->url_path_with_parameters); +} + +TEST_F(SearchHandlerTest, AltTagMatch) { + // Add printing search tags to registry. + AddSearchTags(GetPrintingSearchConcepts()); + std::vector<mojom::SearchResultPtr> search_results; + + // Search for "CUPS". The IDS_OS_SETTINGS_TAG_PRINTING result has an alternate + // tag "CUPS" (referring to the Unix printing protocol), so we should receive + // one match. + mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) + .Search(base::ASCIIToUTF16("CUPS"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kDoNotIncludeParentResults, + &search_results); + EXPECT_EQ(search_results.size(), 1u); + + // Verify the result text and canonical restult text. + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_OS_SETTINGS_TAG_PRINTING_ALT2), + search_results[0]->result_text); + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_OS_SETTINGS_TAG_PRINTING), + search_results[0]->canonical_result_text); +} + +TEST_F(SearchHandlerTest, AllowParentResult) { + // Add printing search tags to registry. + AddSearchTags(GetPrintingSearchConcepts()); + std::vector<mojom::SearchResultPtr> search_results; + + // Search for "Saved", which should only apply to the "saved printers" item. + // Pass the kAllowParentResults flag, which should also cause its parent + // subpage item to be returned. + mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) + .Search(base::ASCIIToUTF16("Saved"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kAllowParentResults, + &search_results); + EXPECT_EQ(search_results.size(), 2u); + EXPECT_FALSE(search_results[1]->was_generated_from_text_match); +} + +TEST_F(SearchHandlerTest, DefaultRank) { + // Add printing search tags to registry. + AddSearchTags(GetPrintingSearchConcepts()); + std::vector<mojom::SearchResultPtr> search_results; + + // Search for "Print". Only the IDS_OS_SETTINGS_TAG_PRINTING result + // contains the word "Printing", but the other results have the similar word + // "Printer". Thus, "Printing" has a higher relevance score. + mojom::SearchHandlerAsyncWaiter(handler_remote_.get()) + .Search(base::ASCIIToUTF16("Print"), + /*max_num_results=*/3u, + mojom::ParentResultBehavior::kAllowParentResults, + &search_results); + EXPECT_EQ(search_results.size(), 3u); + + // Since the IDS_OS_SETTINGS_TAG_PRINTING result has a default rank of kLow, + // it should be the *last* result returned even though it has a higher + // relevance score. + EXPECT_EQ(l10n_util::GetStringUTF16(IDS_OS_SETTINGS_TAG_PRINTING), + search_results[2]->result_text); +} + +// Regression test for https://crbug.com/1090184. +TEST_F(SearchHandlerTest, CompareSearchResults) { + // Create two equal dummy results. + mojom::SearchResultPtr a = CreateDummyResult(); + mojom::SearchResultPtr b = CreateDummyResult(); + + // CompareSearchResults() returns whether |a| < |b|; since they are equal, it + // should return false regardless of the order of parameters. + EXPECT_FALSE(SearchHandler::CompareSearchResults(a, b)); + EXPECT_FALSE(SearchHandler::CompareSearchResults(b, a)); + + // Differ only on default rank. + a = CreateDummyResult(); + a->default_rank = mojom::SearchResultDefaultRank::kLow; + b = CreateDummyResult(); + b->default_rank = mojom::SearchResultDefaultRank::kHigh; + + // Comparison value should differ. + EXPECT_NE(SearchHandler::CompareSearchResults(b, a), + SearchHandler::CompareSearchResults(a, b)); + + // Differ only on relevance score. + a = CreateDummyResult(); + a->relevance_score = 0; + b = CreateDummyResult(); + b->relevance_score = 1; + + // Comparison value should differ. + EXPECT_NE(SearchHandler::CompareSearchResults(b, a), + SearchHandler::CompareSearchResults(a, b)); + + // Differ only on type. + a = CreateDummyResult(); + a->type = mojom::SearchResultType::kSection; + b = CreateDummyResult(); + b->type = mojom::SearchResultType::kSubpage; + + // Comparison value should differ. + EXPECT_NE(SearchHandler::CompareSearchResults(b, a), + SearchHandler::CompareSearchResults(a, b)); } } // 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 5f5b099b176..6be31452dc6 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 @@ -30,6 +30,7 @@ enum SearchResultIcon { kMagnifyingGlass, kMessages, kMouse, + kNearbyShare, kPaintbrush, kPenguin, kPhone, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc index e3b1b3a7b24..618022b76ba 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc @@ -4,9 +4,11 @@ #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" +#include <algorithm> +#include <sstream> + #include "base/feature_list.h" #include "base/strings/string_number_conversions.h" -#include "chrome/browser/chromeos/local_search_service/index.h" #include "chrome/browser/chromeos/local_search_service/local_search_service.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h" #include "chromeos/constants/chromeos_features.h" @@ -16,36 +18,85 @@ namespace chromeos { namespace settings { namespace { -std::vector<local_search_service::Data> ConceptVectorToDataVector( - const std::vector<SearchConcept>& search_tags) { - std::vector<local_search_service::Data> data_list; - - for (const auto& concept : search_tags) { - std::vector<base::string16> search_tags; - - // Add the canonical tag. - search_tags.push_back( - l10n_util::GetStringUTF16(concept.canonical_message_id)); - - // Add all alternate tags. - for (size_t i = 0; i < SearchConcept::kMaxAltTagsPerConcept; ++i) { - int curr_alt_tag = concept.alt_tag_ids[i]; - if (curr_alt_tag == SearchConcept::kAltTagEnd) - break; - search_tags.push_back(l10n_util::GetStringUTF16(curr_alt_tag)); - } +std::vector<int> GetMessageIds(const SearchConcept* concept) { + // Start with only the canonical ID. + std::vector<int> alt_tag_message_ids{concept->canonical_message_id}; - // Note: A stringified version of the canonical tag message ID is used as - // the identifier for this search data. - data_list.emplace_back(base::NumberToString(concept.canonical_message_id), - search_tags); + // Add alternate IDs, if they exist. + for (size_t i = 0; i < SearchConcept::kMaxAltTagsPerConcept; ++i) { + int curr_alt_tag_message_id = concept->alt_tag_ids[i]; + if (curr_alt_tag_message_id == SearchConcept::kAltTagEnd) + break; + alt_tag_message_ids.push_back(curr_alt_tag_message_id); } - return data_list; + return alt_tag_message_ids; } } // namespace +SearchTagRegistry::ScopedTagUpdater::ScopedTagUpdater( + SearchTagRegistry* registry) + : registry_(registry) {} + +SearchTagRegistry::ScopedTagUpdater::ScopedTagUpdater(ScopedTagUpdater&&) = + default; + +SearchTagRegistry::ScopedTagUpdater::~ScopedTagUpdater() { + std::vector<const SearchConcept*> pending_adds; + std::vector<const SearchConcept*> pending_removals; + + for (const auto& map_entry : pending_updates_) { + const std::string& result_id = map_entry.first; + const SearchConcept* concept = map_entry.second.first; + bool is_pending_add = map_entry.second.second; + + // If tag metadata is present for this tag, it has already been added and is + // present in LocalSearchService. + bool is_concept_already_added = + registry_->GetTagMetadata(result_id) != nullptr; + + // Only add concepts which are intended to be added and have not yet been + // added; only remove concepts which are intended to be removed and have + // already been added. + if (is_pending_add && !is_concept_already_added) + pending_adds.push_back(concept); + if (!is_pending_add && is_concept_already_added) + pending_removals.push_back(concept); + } + + if (!pending_adds.empty()) + registry_->AddSearchTags(pending_adds); + if (!pending_removals.empty()) + registry_->RemoveSearchTags(pending_removals); +} + +void SearchTagRegistry::ScopedTagUpdater::AddSearchTags( + const std::vector<SearchConcept>& search_tags) { + ProcessPendingSearchTags(search_tags, /*is_pending_add=*/true); +} + +void SearchTagRegistry::ScopedTagUpdater::RemoveSearchTags( + const std::vector<SearchConcept>& search_tags) { + ProcessPendingSearchTags(search_tags, /*is_pending_add=*/false); +} + +void SearchTagRegistry::ScopedTagUpdater::ProcessPendingSearchTags( + const std::vector<SearchConcept>& search_tags, + bool is_pending_add) { + for (const auto& concept : search_tags) { + std::string result_id = ToResultId(concept); + auto it = pending_updates_.find(result_id); + if (it == pending_updates_.end()) { + pending_updates_.emplace(std::piecewise_construct, + std::forward_as_tuple(result_id), + std::forward_as_tuple(&concept, is_pending_add)); + } else { + it->second.second = is_pending_add; + } + } +} + SearchTagRegistry::SearchTagRegistry( local_search_service::LocalSearchService* local_search_service) : index_(local_search_service->GetIndex( @@ -53,8 +104,20 @@ SearchTagRegistry::SearchTagRegistry( SearchTagRegistry::~SearchTagRegistry() = default; +void SearchTagRegistry::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void SearchTagRegistry::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +SearchTagRegistry::ScopedTagUpdater SearchTagRegistry::StartUpdate() { + return ScopedTagUpdater(this); +} + void SearchTagRegistry::AddSearchTags( - const std::vector<SearchConcept>& search_tags) { + const std::vector<const SearchConcept*>& search_tags) { if (!base::FeatureList::IsEnabled(features::kNewOsSettingsSearch)) return; @@ -63,31 +126,82 @@ void SearchTagRegistry::AddSearchTags( // Add each concept to the map. Note that it is safe to take the address of // each concept because all concepts are allocated via static // base::NoDestructor objects in the Get*SearchConcepts() helper functions. - for (const auto& concept : search_tags) - canonical_id_to_metadata_map_[concept.canonical_message_id] = &concept; + for (const auto* concept : search_tags) + result_id_to_metadata_list_map_[ToResultId(*concept)] = concept; + + NotifyRegistryUpdated(); } void SearchTagRegistry::RemoveSearchTags( - const std::vector<SearchConcept>& search_tags) { + const std::vector<const SearchConcept*>& search_tags) { if (!base::FeatureList::IsEnabled(features::kNewOsSettingsSearch)) return; - std::vector<std::string> ids; - for (const auto& concept : search_tags) { - canonical_id_to_metadata_map_.erase(concept.canonical_message_id); - ids.push_back(base::NumberToString(concept.canonical_message_id)); + std::vector<std::string> data_ids; + for (const auto* concept : search_tags) { + std::string result_id = ToResultId(*concept); + result_id_to_metadata_list_map_.erase(result_id); + data_ids.push_back(std::move(result_id)); } - index_->Delete(ids); + index_->Delete(data_ids); + + NotifyRegistryUpdated(); } -const SearchConcept* SearchTagRegistry::GetCanonicalTagMetadata( - int canonical_message_id) const { - const auto it = canonical_id_to_metadata_map_.find(canonical_message_id); - if (it == canonical_id_to_metadata_map_.end()) +const SearchConcept* SearchTagRegistry::GetTagMetadata( + const std::string& result_id) const { + const auto it = result_id_to_metadata_list_map_.find(result_id); + if (it == result_id_to_metadata_list_map_.end()) return nullptr; return it->second; } +// static +std::string SearchTagRegistry::ToResultId(const SearchConcept& concept) { + std::stringstream ss; + switch (concept.type) { + case mojom::SearchResultType::kSection: + ss << concept.id.section; + break; + case mojom::SearchResultType::kSubpage: + ss << concept.id.subpage; + break; + case mojom::SearchResultType::kSetting: + ss << concept.id.setting; + break; + } + ss << "," << concept.canonical_message_id; + return ss.str(); +} + +std::vector<local_search_service::Data> +SearchTagRegistry::ConceptVectorToDataVector( + const std::vector<const SearchConcept*>& search_tags) { + std::vector<local_search_service::Data> data_list; + + for (const auto* concept : search_tags) { + // Create a list of Content objects, which use the stringified version of + // message IDs as identifiers. + std::vector<local_search_service::Content> content_list; + for (int message_id : GetMessageIds(concept)) { + content_list.emplace_back( + /*id=*/base::NumberToString(message_id), + /*content=*/l10n_util::GetStringUTF16(message_id)); + } + + // Compute an identifier for this result; the same ID format it used in + // GetTagMetadata(). + data_list.emplace_back(ToResultId(*concept), std::move(content_list)); + } + + return data_list; +} + +void SearchTagRegistry::NotifyRegistryUpdated() { + for (auto& observer : observer_list_) + observer.OnRegistryUpdated(); +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h index c1c7a947f87..abd1f83b1fa 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h @@ -6,8 +6,13 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_SEARCH_SEARCH_TAG_REGISTRY_H_ #include <unordered_map> +#include <utility> #include <vector> +#include "base/gtest_prod_util.h" +#include "base/observer_list.h" +#include "base/observer_list_types.h" +#include "chrome/browser/chromeos/local_search_service/index.h" #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h" namespace local_search_service { @@ -21,27 +26,82 @@ namespace settings { struct SearchConcept; // Processes all registered search tags by adding/removing them from -// LocalSearchService and providing metadata via GetCanonicalTagMetadata(). +// LocalSearchService and providing metadata via GetTagMetadata(). class SearchTagRegistry { public: + class Observer : public base::CheckedObserver { + public: + ~Observer() override = default; + virtual void OnRegistryUpdated() = 0; + }; + + class ScopedTagUpdater { + public: + ScopedTagUpdater(ScopedTagUpdater&&); + ScopedTagUpdater(const ScopedTagUpdater&) = delete; + ScopedTagUpdater& operator=(const ScopedTagUpdater&) = delete; + ~ScopedTagUpdater(); + + void AddSearchTags(const std::vector<SearchConcept>& search_tags); + void RemoveSearchTags(const std::vector<SearchConcept>& search_tags); + + private: + friend class SearchTagRegistry; + + explicit ScopedTagUpdater(SearchTagRegistry* registry); + + void ProcessPendingSearchTags(const std::vector<SearchConcept>& search_tags, + bool is_pending_add); + + SearchTagRegistry* registry_; + + // A SearchConcept along with a bool of the pending update state. If the + // bool is true, the concept should be added; if the bool is false, the + // concept should be removed. + using ConceptWithShouldAddBool = std::pair<const SearchConcept*, bool>; + std::unordered_map<std::string, ConceptWithShouldAddBool> pending_updates_; + }; + SearchTagRegistry( local_search_service::LocalSearchService* local_search_service); SearchTagRegistry(const SearchTagRegistry& other) = delete; SearchTagRegistry& operator=(const SearchTagRegistry& other) = delete; virtual ~SearchTagRegistry(); - void AddSearchTags(const std::vector<SearchConcept>& search_tags); - void RemoveSearchTags(const std::vector<SearchConcept>& search_tags); + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); - // Returns the tag metadata associated with |canonical_message_id|, which must - // be one of the canonical IDS_OS_SETTINGS_TAG_* identifiers used for a search - // tag. If no metadata is available or if |canonical_message_id| instead - // refers to an alternate tag's ID, null is returned. - const SearchConcept* GetCanonicalTagMetadata(int canonical_message_id) const; + // Starts a tag update, which allows clients to add/remove search tags. The + // ScopedTagUpdater object is returned by value and only updates tags when it + // goes out of scope, so clients should not hold onto it outside the scope of + // a function. + ScopedTagUpdater StartUpdate(); + // Returns the tag metadata associated with |result_id|, which is the ID + // returned by the LocalSearchService. If no metadata is available, null is + // returned. + const SearchConcept* GetTagMetadata(const std::string& result_id) const; private: + FRIEND_TEST_ALL_PREFIXES(SearchTagRegistryTest, AddAndRemove); + + static std::string ToResultId(const SearchConcept& concept); + + void AddSearchTags(const std::vector<const SearchConcept*>& search_tags); + void RemoveSearchTags(const std::vector<const SearchConcept*>& search_tags); + + std::vector<local_search_service::Data> ConceptVectorToDataVector( + const std::vector<const SearchConcept*>& search_tags); + void NotifyRegistryUpdated(); + + // Index used by the LocalSearchService for string matching. local_search_service::Index* index_; - std::unordered_map<int, const SearchConcept*> canonical_id_to_metadata_map_; + + // In-memory cache of all results which have been added to the + // LocalSearchService. Contents are kept in sync with |index_|. + std::unordered_map<std::string, const SearchConcept*> + result_id_to_metadata_list_map_; + + base::ObserverList<Observer> observer_list_; }; } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc index 6eff74b2583..1aebe00ce35 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc @@ -5,19 +5,31 @@ #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h" #include "base/no_destructor.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/chromeos/local_search_service/index.h" #include "chrome/browser/chromeos/local_search_service/local_search_service.h" #include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h" #include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h" #include "chrome/grit/generated_resources.h" -#include "chromeos/constants/chromeos_features.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { namespace settings { namespace { +class FakeObserver : public SearchTagRegistry::Observer { + public: + FakeObserver() = default; + ~FakeObserver() override = default; + + size_t num_calls() const { return num_calls_; } + + private: + // SearchTagRegistry::Observer: + void OnRegistryUpdated() override { ++num_calls_; } + + size_t num_calls_ = 0; +}; + // Note: Copied from printing_section.cc but does not need to stay in sync with // it. const std::vector<SearchConcept>& GetPrintingSearchConcepts() { @@ -27,10 +39,7 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { mojom::SearchResultIcon::kPrinter, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAddPrinter}, - {IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER_ALT1, - IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER_ALT2, - SearchConcept::kAltTagEnd}}, + {.setting = mojom::Setting::kAddPrinter}}, {IDS_OS_SETTINGS_TAG_PRINTING_SAVED_PRINTERS, mojom::kPrintingDetailsSubpagePath, mojom::SearchResultIcon::kPrinter, @@ -40,7 +49,7 @@ const std::vector<SearchConcept>& GetPrintingSearchConcepts() { {IDS_OS_SETTINGS_TAG_PRINTING, mojom::kPrintingDetailsSubpagePath, mojom::SearchResultIcon::kPrinter, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kPrintingDetails}, {IDS_OS_SETTINGS_TAG_PRINTING_ALT1, IDS_OS_SETTINGS_TAG_PRINTING_ALT2, @@ -58,37 +67,61 @@ class SearchTagRegistryTest : public testing::Test { // testing::Test: void SetUp() override { - scoped_feature_list_.InitAndEnableFeature( - chromeos::features::kNewOsSettingsSearch); + search_tag_registry_.AddObserver(&observer_); index_ = local_search_service_.GetIndex( local_search_service::IndexId::kCrosSettings); } - base::test::ScopedFeatureList scoped_feature_list_; + void TearDown() override { search_tag_registry_.RemoveObserver(&observer_); } + local_search_service::LocalSearchService local_search_service_; SearchTagRegistry search_tag_registry_; + FakeObserver observer_; local_search_service::Index* index_; }; TEST_F(SearchTagRegistryTest, AddAndRemove) { // Add search tags; size of the index should increase. - search_tag_registry_.AddSearchTags(GetPrintingSearchConcepts()); + { + SearchTagRegistry::ScopedTagUpdater updater = + search_tag_registry_.StartUpdate(); + updater.AddSearchTags(GetPrintingSearchConcepts()); + + // Nothing should have happened yet, since |updater| has not gone out of + // scope. + EXPECT_EQ(0u, index_->GetSize()); + EXPECT_EQ(0u, observer_.num_calls()); + } + // Now that it went out of scope, the update should have occurred. EXPECT_EQ(3u, index_->GetSize()); + EXPECT_EQ(1u, observer_.num_calls()); - // Tags added should be available via GetCanonicalTagMetadata(). + std::string first_tag_id = + SearchTagRegistry::ToResultId(GetPrintingSearchConcepts()[0]); + + // Tags added should be available via GetTagMetadata(). const SearchConcept* add_printer_concept = - search_tag_registry_.GetCanonicalTagMetadata( - IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER); + search_tag_registry_.GetTagMetadata(first_tag_id); ASSERT_TRUE(add_printer_concept); EXPECT_EQ(mojom::Setting::kAddPrinter, add_printer_concept->id.setting); // Remove search tag; size should go back to 0. - search_tag_registry_.RemoveSearchTags(GetPrintingSearchConcepts()); + { + SearchTagRegistry::ScopedTagUpdater updater = + search_tag_registry_.StartUpdate(); + updater.RemoveSearchTags(GetPrintingSearchConcepts()); + + // Tags should not have been removed yet, since |updater| has not gone out + // of scope. + EXPECT_EQ(3u, index_->GetSize()); + EXPECT_EQ(1u, observer_.num_calls()); + } + // Now that it went out of scope, the update should have occurred. EXPECT_EQ(0u, index_->GetSize()); + EXPECT_EQ(2u, observer_.num_calls()); - // The tag should no longer be accessible via GetCanonicalTagMetadata(). - add_printer_concept = search_tag_registry_.GetCanonicalTagMetadata( - IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER); + // The tag should no longer be accessible via GetTagMetadata(). + add_printer_concept = search_tag_registry_.GetTagMetadata(first_tag_id); ASSERT_FALSE(add_printer_concept); } 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 958071d8716..6f8763df333 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.cc @@ -9,6 +9,7 @@ #include "ash/public/cpp/assistant/assistant_state.h" #include "base/no_destructor.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/chromeos/assistant/assistant_util.h" #include "chrome/browser/profiles/profile.h" @@ -19,10 +20,14 @@ #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" +#include "chromeos/components/quick_answers/quick_answers_client.h" #include "chromeos/constants/chromeos_features.h" #include "chromeos/services/assistant/public/cpp/assistant_prefs.h" #include "chromeos/services/assistant/public/cpp/features.h" +#include "components/language/core/browser/pref_names.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/web_ui_data_source.h" +#include "third_party/icu/source/common/unicode/locid.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/chromeos/devicetype_utils.h" @@ -48,60 +53,45 @@ const std::vector<SearchConcept>& GetAssistantSearchConcepts() { {IDS_OS_SETTINGS_TAG_ASSISTANT, mojom::kAssistantSubpagePath, mojom::SearchResultIcon::kAssistant, - mojom::SearchResultDefaultRank::kHigh, + mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSubpage, {.subpage = mojom::Subpage::kAssistant}}, - {IDS_OS_SETTINGS_TAG_ASSISTANT_QUICK_ANSWERS, + }); + return *tags; +} + +const std::vector<SearchConcept>& GetAssistantOnSearchConcepts() { + static const base::NoDestructor<std::vector<SearchConcept>> tags({ + {IDS_OS_SETTINGS_TAG_ASSISTANT_TURN_OFF, mojom::kAssistantSubpagePath, mojom::SearchResultIcon::kAssistant, mojom::SearchResultDefaultRank::kMedium, mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAssistantQuickAnswers}}, + {.setting = mojom::Setting::kAssistantOnOff}, + {IDS_OS_SETTINGS_TAG_ASSISTANT_TURN_OFF_ALT1, + SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_ASSISTANT_PREFERRED_INPUT, mojom::kAssistantSubpagePath, mojom::SearchResultIcon::kAssistant, - mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultDefaultRank::kLow, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kAssistantVoiceInput}}, - {IDS_OS_SETTINGS_TAG_ASSISTANT_OK_GOOGLE, - mojom::kAssistantSubpagePath, - mojom::SearchResultIcon::kAssistant, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAssistantOkGoogle}, - {IDS_OS_SETTINGS_TAG_ASSISTANT_OK_GOOGLE_ALT1, - IDS_OS_SETTINGS_TAG_ASSISTANT_OK_GOOGLE_ALT2, - SearchConcept::kAltTagEnd}}, {IDS_OS_SETTINGS_TAG_ASSISTANT_NOTIFICATIONS, mojom::kAssistantSubpagePath, mojom::SearchResultIcon::kAssistant, - mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultDefaultRank::kLow, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kAssistantNotifications}}, {IDS_OS_SETTINGS_TAG_ASSISTANT_RELATED_INFO, mojom::kAssistantSubpagePath, mojom::SearchResultIcon::kAssistant, - mojom::SearchResultDefaultRank::kMedium, + mojom::SearchResultDefaultRank::kLow, mojom::SearchResultType::kSetting, {.setting = mojom::Setting::kAssistantRelatedInfo}}, }); return *tags; } -const std::vector<SearchConcept>& GetAssistantOnSearchConcepts() { - static const base::NoDestructor<std::vector<SearchConcept>> tags({ - {IDS_OS_SETTINGS_TAG_ASSISTANT_TURN_OFF, - mojom::kAssistantSubpagePath, - mojom::SearchResultIcon::kAssistant, - mojom::SearchResultDefaultRank::kMedium, - mojom::SearchResultType::kSetting, - {.setting = mojom::Setting::kAssistantOnOff}, - {IDS_OS_SETTINGS_TAG_ASSISTANT_TURN_OFF_ALT1, - SearchConcept::kAltTagEnd}}, - }); - return *tags; -} - const std::vector<SearchConcept>& GetAssistantOffSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ {IDS_OS_SETTINGS_TAG_ASSISTANT_TURN_ON, @@ -117,21 +107,39 @@ const std::vector<SearchConcept>& GetAssistantOffSearchConcepts() { const std::vector<SearchConcept>& GetAssistantQuickAnswersSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Assistant Quick Answers" search concepts. + {IDS_OS_SETTINGS_TAG_ASSISTANT_QUICK_ANSWERS, + mojom::kAssistantSubpagePath, + mojom::SearchResultIcon::kAssistant, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAssistantQuickAnswers}}, }); return *tags; } const std::vector<SearchConcept>& GetAssistantHotwordDspSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Assistant hotword DSP" search concepts. + {IDS_OS_SETTINGS_TAG_ASSISTANT_OK_GOOGLE, + mojom::kAssistantSubpagePath, + mojom::SearchResultIcon::kAssistant, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kAssistantOkGoogle}, + {IDS_OS_SETTINGS_TAG_ASSISTANT_OK_GOOGLE_ALT1, + IDS_OS_SETTINGS_TAG_ASSISTANT_OK_GOOGLE_ALT2, + SearchConcept::kAltTagEnd}}, }); return *tags; } const std::vector<SearchConcept>& GetAssistantVoiceMatchSearchConcepts() { static const base::NoDestructor<std::vector<SearchConcept>> tags({ - // TODO(khorimoto): Add "Assistant hotword DSP" search concepts. + {IDS_OS_SETTINGS_TAG_ASSISTANT_TRAIN_VOICE_MODEL, + mojom::kAssistantSubpagePath, + mojom::SearchResultIcon::kAssistant, + mojom::SearchResultDefaultRank::kLow, + mojom::SearchResultType::kSetting, + {.setting = mojom::Setting::kTrainAssistantVoiceModel}}, }); return *tags; } @@ -140,10 +148,6 @@ bool IsVoiceMatchAllowed() { return !assistant::features::IsVoiceMatchDisabled(); } -bool AreQuickAnswersAllowed() { - return features::IsQuickAnswersSettingToggleEnabled(); -} - void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"googleAssistantPageTitle", IDS_SETTINGS_GOOGLE_ASSISTANT}, @@ -186,7 +190,6 @@ void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { html_source->AddBoolean("hotwordDspAvailable", IsHotwordDspAvailable()); html_source->AddBoolean("voiceMatchDisabled", !IsVoiceMatchAllowed()); - html_source->AddBoolean("quickAnswersAvailable", AreQuickAnswersAllowed()); } } // namespace @@ -194,11 +197,12 @@ void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { SearchSection::SearchSection(Profile* profile, SearchTagRegistry* search_tag_registry) : OsSettingsSection(profile, search_tag_registry) { - registry()->AddSearchTags(GetSearchPageSearchConcepts()); + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + updater.AddSearchTags(GetSearchPageSearchConcepts()); ash::AssistantState* assistant_state = ash::AssistantState::Get(); if (IsAssistantAllowed() && assistant_state) { - registry()->AddSearchTags(GetAssistantSearchConcepts()); + updater.AddSearchTags(GetAssistantSearchConcepts()); assistant_state->AddObserver(this); UpdateAssistantSearchTags(); @@ -226,6 +230,7 @@ void SearchSection::AddLoadTimeData(content::WebUIDataSource* html_source) { const bool is_assistant_allowed = IsAssistantAllowed(); html_source->AddBoolean("isAssistantAllowed", is_assistant_allowed); + html_source->AddBoolean("quickAnswersAvailable", IsQuickAnswersAllowed()); html_source->AddLocalizedString("osSearchPageTitle", is_assistant_allowed ? IDS_SETTINGS_SEARCH_AND_ASSISTANT @@ -248,6 +253,44 @@ void SearchSection::AddHandlers(content::WebUI* web_ui) { std::make_unique<chromeos::settings::GoogleAssistantHandler>()); } +int SearchSection::GetSectionNameMessageId() const { + return IsAssistantAllowed() ? IDS_SETTINGS_SEARCH_AND_ASSISTANT + : IDS_SETTINGS_SEARCH; +} + +mojom::Section SearchSection::GetSection() const { + return mojom::Section::kSearchAndAssistant; +} + +mojom::SearchResultIcon SearchSection::GetSectionIcon() const { + return mojom::SearchResultIcon::kMagnifyingGlass; +} + +std::string SearchSection::GetSectionPath() const { + return mojom::kSearchAndAssistantSectionPath; +} + +void SearchSection::RegisterHierarchy(HierarchyGenerator* generator) const { + generator->RegisterTopLevelSetting(mojom::Setting::kPreferredSearchEngine); + + // Assistant. + generator->RegisterTopLevelSubpage( + IDS_SETTINGS_GOOGLE_ASSISTANT, mojom::Subpage::kAssistant, + mojom::SearchResultIcon::kAssistant, + mojom::SearchResultDefaultRank::kMedium, mojom::kAssistantSubpagePath); + static constexpr mojom::Setting kAssistantSettings[] = { + mojom::Setting::kAssistantOnOff, + mojom::Setting::kAssistantRelatedInfo, + mojom::Setting::kAssistantQuickAnswers, + mojom::Setting::kAssistantOkGoogle, + mojom::Setting::kAssistantNotifications, + mojom::Setting::kAssistantVoiceInput, + mojom::Setting::kTrainAssistantVoiceModel, + }; + RegisterNestedSettingBulk(mojom::Subpage::kAssistant, kAssistantSettings, + generator); +} + void SearchSection::OnAssistantConsentStatusChanged(int consent_status) { UpdateAssistantSearchTags(); } @@ -264,19 +307,40 @@ void SearchSection::OnAssistantHotwordEnabled(bool enabled) { UpdateAssistantSearchTags(); } -bool SearchSection::IsAssistantAllowed() { +bool SearchSection::IsAssistantAllowed() const { // NOTE: This will be false when the flag is disabled. return ::assistant::IsAssistantAllowedForProfile(profile()) == chromeos::assistant::AssistantAllowedState::ALLOWED; } +bool SearchSection::IsQuickAnswersAllowed() const { + if (!features::IsQuickAnswersSettingToggleEnabled()) + return false; + + const PrefService* prefs = profile()->GetPrefs(); + std::string pref_locale = + prefs->GetString(language::prefs::kApplicationLocale); + // Also accept runtime locale which maybe an approximation of user's pref + // locale. + const std::string kRuntimeLocale = icu::Locale::getDefault().getName(); + + base::ReplaceChars(pref_locale, "-", "_", &pref_locale); + if (!::chromeos::quick_answers::QuickAnswersClient:: + IsQuickAnswersAllowedForLocale(pref_locale, kRuntimeLocale)) + return false; + + return true; +} + void SearchSection::UpdateAssistantSearchTags() { + SearchTagRegistry::ScopedTagUpdater updater = registry()->StartUpdate(); + // Start without any Assistant search concepts, then add if needed below. - registry()->RemoveSearchTags(GetAssistantOnSearchConcepts()); - registry()->RemoveSearchTags(GetAssistantOffSearchConcepts()); - registry()->RemoveSearchTags(GetAssistantQuickAnswersSearchConcepts()); - registry()->RemoveSearchTags(GetAssistantHotwordDspSearchConcepts()); - registry()->RemoveSearchTags(GetAssistantVoiceMatchSearchConcepts()); + updater.RemoveSearchTags(GetAssistantOnSearchConcepts()); + updater.RemoveSearchTags(GetAssistantOffSearchConcepts()); + updater.RemoveSearchTags(GetAssistantQuickAnswersSearchConcepts()); + updater.RemoveSearchTags(GetAssistantHotwordDspSearchConcepts()); + updater.RemoveSearchTags(GetAssistantVoiceMatchSearchConcepts()); ash::AssistantState* assistant_state = ash::AssistantState::Get(); @@ -284,26 +348,26 @@ void SearchSection::UpdateAssistantSearchTags() { // off, none of the sub-features are enabled. if (!assistant_state->settings_enabled() || !assistant_state->settings_enabled().value()) { - registry()->AddSearchTags(GetAssistantOffSearchConcepts()); + updater.AddSearchTags(GetAssistantOffSearchConcepts()); return; } - registry()->AddSearchTags(GetAssistantOnSearchConcepts()); + updater.AddSearchTags(GetAssistantOnSearchConcepts()); - if (AreQuickAnswersAllowed() && assistant_state->context_enabled() && + if (IsQuickAnswersAllowed() && assistant_state->context_enabled() && assistant_state->context_enabled().value()) { - registry()->AddSearchTags(GetAssistantQuickAnswersSearchConcepts()); + updater.AddSearchTags(GetAssistantQuickAnswersSearchConcepts()); } if (IsHotwordDspAvailable()) - registry()->AddSearchTags(GetAssistantHotwordDspSearchConcepts()); + updater.AddSearchTags(GetAssistantHotwordDspSearchConcepts()); if (IsVoiceMatchAllowed() && assistant_state->hotword_enabled() && assistant_state->hotword_enabled().value() && assistant_state->consent_status() && assistant_state->consent_status().value() == assistant::prefs::ConsentStatus::kActivityControlAccepted) { - registry()->AddSearchTags(GetAssistantVoiceMatchSearchConcepts()); + updater.AddSearchTags(GetAssistantVoiceMatchSearchConcepts()); } } 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 d53c8d0e1ff..1de2bc61d26 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/search_section.h @@ -30,6 +30,11 @@ class SearchSection : public OsSettingsSection, // 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; + std::string GetSectionPath() const override; + void RegisterHierarchy(HierarchyGenerator* generator) const override; // ash::AssistantStateObserver: void OnAssistantConsentStatusChanged(int consent_status) override; @@ -37,7 +42,8 @@ class SearchSection : public OsSettingsSection, void OnAssistantSettingsEnabled(bool enabled) override; void OnAssistantHotwordEnabled(bool enabled) override; - bool IsAssistantAllowed(); + bool IsAssistantAllowed() const; + bool IsQuickAnswersAllowed() const; void UpdateAssistantSearchTags(); }; diff --git a/chromium/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc b/chromium/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc index e2f4c5719c7..b3fd20ec805 100644 --- a/chromium/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc +++ b/chromium/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc @@ -45,9 +45,8 @@ struct CustomHomePagesTableModel::Entry { CustomHomePagesTableModel::CustomHomePagesTableModel(Profile* profile) : profile_(profile), - observer_(NULL), - num_outstanding_title_lookups_(0) { -} + observer_(nullptr), + num_outstanding_title_lookups_(0) {} CustomHomePagesTableModel::~CustomHomePagesTableModel() { } diff --git a/chromium/chrome/browser/ui/webui/settings/recent_site_settings_helper_unittest.cc b/chromium/chrome/browser/ui/webui/settings/recent_site_settings_helper_unittest.cc index 7984c581713..8d765b17cbe 100644 --- a/chromium/chrome/browser/ui/webui/settings/recent_site_settings_helper_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/recent_site_settings_helper_unittest.cc @@ -20,10 +20,8 @@ namespace { ContentSetting kBlocked = ContentSetting::CONTENT_SETTING_BLOCK; ContentSetting kAllowed = ContentSetting::CONTENT_SETTING_ALLOW; ContentSetting kDefault = ContentSetting::CONTENT_SETTING_DEFAULT; -site_settings::SiteSettingSource kEmbargo = - site_settings::SiteSettingSource::kEmbargo; -site_settings::SiteSettingSource kPreference = - site_settings::SiteSettingSource::kPreference; +SiteSettingSource kEmbargo = site_settings::SiteSettingSource::kEmbargo; +SiteSettingSource kPreference = site_settings::SiteSettingSource::kPreference; ContentSettingsType kNotifications = ContentSettingsType::NOTIFICATIONS; ContentSettingsType kPlugins = ContentSettingsType::PLUGINS; ContentSettingsType kPopups = ContentSettingsType::POPUPS; 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 fabe2039537..81877f13bcf 100644 --- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.cc @@ -455,6 +455,9 @@ base::string16 SafetyCheckHandler::GetStringForPasswords( case PasswordsStatus::kError: return l10n_util::GetStringUTF16( IDS_SETTINGS_CHECK_PASSWORDS_ERROR_GENERIC); + case PasswordsStatus::kFeatureUnavailable: + return l10n_util::GetStringUTF16( + IDS_SETTINGS_SAFETY_CHECK_PASSWORDS_FEATURE_UNAVAILABLE); } } @@ -571,6 +574,7 @@ void SafetyCheckHandler::DetermineIfNoPasswordsOrSafe( void SafetyCheckHandler::OnVersionUpdaterResult(VersionUpdater::Status status, int progress, bool rollback, + bool powerwash, const std::string& version, int64_t update_size, const base::string16& message) { @@ -632,6 +636,9 @@ void SafetyCheckHandler::OnStateChanged( Done(0), Total(0)); break; case BulkLeakCheckService::State::kTokenRequestFailure: + OnPasswordsCheckResult(PasswordsStatus::kFeatureUnavailable, + Compromised(0), Done(0), Total(0)); + break; case BulkLeakCheckService::State::kHashingFailure: case BulkLeakCheckService::State::kServiceError: OnPasswordsCheckResult(PasswordsStatus::kError, Compromised(0), Done(0), diff --git a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h index 0c73407ae34..8e6d9336183 100644 --- a/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/safety_check_handler.h @@ -30,7 +30,7 @@ // software. class SafetyCheckHandler : public settings::SettingsPageUIHandler, - public password_manager::BulkLeakCheckService::Observer, + public password_manager::BulkLeakCheckServiceInterface::Observer, public safety_check::SafetyCheck::SafetyCheckHandlerInterface { public: // The following enum represent the state of the safety check parent @@ -70,8 +70,9 @@ class SafetyCheckHandler kSignedOut = 5, kQuotaLimit = 6, kError = 7, + kFeatureUnavailable = 8, // New enum values must go above here. - kMaxValue = kError, + kMaxValue = kFeatureUnavailable, }; enum class ExtensionsStatus { kChecking = 0, @@ -192,6 +193,7 @@ class SafetyCheckHandler void OnVersionUpdaterResult(VersionUpdater::Status status, int progress, bool rollback, + bool powerwash, const std::string& version, int64_t update_size, const base::string16& message); @@ -235,12 +237,12 @@ class SafetyCheckHandler std::unique_ptr<safety_check::UpdateCheckHelper> update_helper_; std::unique_ptr<VersionUpdater> version_updater_; - password_manager::BulkLeakCheckService* leak_service_ = nullptr; + password_manager::BulkLeakCheckServiceInterface* leak_service_ = nullptr; extensions::PasswordsPrivateDelegate* passwords_delegate_ = nullptr; extensions::ExtensionPrefs* extension_prefs_ = nullptr; extensions::ExtensionServiceInterface* extension_service_ = nullptr; - ScopedObserver<password_manager::BulkLeakCheckService, - password_manager::BulkLeakCheckService::Observer> + ScopedObserver<password_manager::BulkLeakCheckServiceInterface, + password_manager::BulkLeakCheckServiceInterface::Observer> observed_leak_check_{this}; base::WeakPtrFactory<SafetyCheckHandler> weak_ptr_factory_{this}; }; 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 c6e18dd2c36..9a790eea198 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 @@ -793,6 +793,25 @@ TEST_F(SafetyCheckHandlerTest, CheckPasswords_Error) { SafetyCheckHandler::PasswordsStatus::kError, 1); } +TEST_F(SafetyCheckHandlerTest, CheckPasswords_FeatureUnavailable) { + safety_check_->PerformSafetyCheck(); + EXPECT_TRUE(test_passwords_delegate_.StartPasswordCheckTriggered()); + static_cast<password_manager::BulkLeakCheckService::Observer*>( + safety_check_.get()) + ->OnStateChanged( + password_manager::BulkLeakCheckService::State::kTokenRequestFailure); + const base::DictionaryValue* event = + GetSafetyCheckStatusChangedWithDataIfExists( + kPasswords, + static_cast<int>( + SafetyCheckHandler::PasswordsStatus::kFeatureUnavailable)); + ASSERT_TRUE(event); + VerifyDisplayString(event, "Password check is not available in Chromium"); + histogram_tester_.ExpectBucketCount( + "Settings.SafetyCheck.PasswordsResult", + SafetyCheckHandler::PasswordsStatus::kFeatureUnavailable, 1); +} + TEST_F(SafetyCheckHandlerTest, CheckPasswords_RunningOneCompromised) { test_passwords_delegate_.SetNumCompromisedCredentials(1); safety_check_->PerformSafetyCheck(); 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 8335deec5b6..831c737b3fa 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 @@ -254,8 +254,8 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData( if (!prefs->GetBoolean(prefs::kClearPluginLSODataEnabled)) site_data_mask &= ~ChromeBrowsingDataRemoverDelegate::DATA_TYPE_PLUGIN_DATA; - int remove_mask = 0; - int origin_mask = 0; + 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)); 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 98dca3b412e..28c96790a03 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 @@ -7,6 +7,7 @@ #include "base/values.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" +#include "chrome/browser/web_applications/test/web_app_test.h" #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" @@ -98,13 +99,10 @@ IN_PROC_BROWSER_TEST_P(ClearBrowsingDataHandlerBrowserTest, GetInstalledApps) { ASSERT_EQ(url.host(), *(installed_app.FindStringKey("registerableDomain"))); } -INSTANTIATE_TEST_SUITE_P( - All, - ClearBrowsingDataHandlerBrowserTest, - ::testing::Values( - web_app::ControllerType::kHostedAppController, - web_app::ControllerType::kUnifiedControllerWithBookmarkApp, - web_app::ControllerType::kUnifiedControllerWithWebApp), - web_app::ControllerTypeParamToString); +INSTANTIATE_TEST_SUITE_P(All, + ClearBrowsingDataHandlerBrowserTest, + ::testing::Values(web_app::ProviderType::kBookmarkApps, + web_app::ProviderType::kWebApps), + web_app::ProviderTypeParamToString); } // namespace settings 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 eff2694ecfd..ccb1ccca58c 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 @@ -99,8 +99,9 @@ #include "components/prefs/pref_service.h" #include "components/user_manager/user_manager.h" #include "ui/chromeos/devicetype_utils.h" -#else +#else // !defined(OS_CHROMEOS) #include "chrome/browser/ui/webui/settings/system_handler.h" +#include "ui/accessibility/accessibility_features.h" #endif #if defined(OS_WIN) @@ -156,6 +157,9 @@ void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) { {"settings", IDS_SETTINGS_SETTINGS}, {"settingsAltPageTitle", IDS_SETTINGS_ALT_PAGE_TITLE}, {"subpageArrowRoleDescription", IDS_SETTINGS_SUBPAGE_BUTTON}, + {"subpageBackButtonAriaLabel", IDS_SETTINGS_SUBPAGE_BACK_BUTTON_ARIA_LABEL}, + {"subpageBackButtonAriaRoleDescription", + IDS_SETTINGS_SUBPAGE_BACK_BUTTON_ARIA_ROLE_DESCRIPTION}, {"notValid", IDS_SETTINGS_NOT_VALID}, {"notValidWebAddress", IDS_SETTINGS_NOT_VALID_WEB_ADDRESS}, {"notValidWebAddressForContentType", @@ -203,6 +207,9 @@ void AddA11yStrings(content::WebUIDataSource* html_source) { {"manageAccessibilityFeatures", IDS_SETTINGS_ACCESSIBILITY_MANAGE_ACCESSIBILITY_FEATURES}, {"androidAppsManageAppLinks", IDS_SETTINGS_ANDROID_APPS_MANAGE_APP_LINKS}, +#else // !defined(OS_CHROMEOS) + {"focusHighlightLabel", + IDS_SETTINGS_ACCESSIBILITY_FOCUS_HIGHLIGHT_DESCRIPTION}, #endif }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); @@ -215,6 +222,12 @@ void AddA11yStrings(content::WebUIDataSource* html_source) { "showExperimentalA11yLabels", base::FeatureList::IsEnabled(features::kExperimentalAccessibilityLabels)); +#if !defined(OS_CHROMEOS) + html_source->AddBoolean( + "showFocusHighlightOption", + base::FeatureList::IsEnabled(features::kAccessibilityFocusHighlight)); +#endif + html_source->AddBoolean("enableLiveCaption", base::FeatureList::IsEnabled(media::kLiveCaption)); @@ -460,7 +473,7 @@ void AddChromeCleanupStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_CURRENTLY_REMOVING}, {"chromeCleanupExplanationScanError", IDS_SETTINGS_RESET_CLEANUP_EXPLANATION_SCAN_ERROR}, - {"chromeCleanupFindButtonLable", + {"chromeCleanupFindButtonLabel", IDS_SETTINGS_RESET_CLEANUP_FIND_BUTTON_LABEL}, {"chromeCleanupLinkShowItems", IDS_SETTINGS_RESET_CLEANUP_LINK_SHOW_FILES}, @@ -769,6 +782,7 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, static constexpr webui::LocalizedString kLocalizedStrings[] = { {"autofillPageTitle", IDS_SETTINGS_AUTOFILL}, {"passwords", IDS_SETTINGS_PASSWORDS}, + {"passwordsDevice", IDS_SETTINGS_DEVICE_PASSWORDS}, {"checkPasswords", IDS_SETTINGS_CHECK_PASSWORDS}, {"checkPasswordsCanceled", IDS_SETTINGS_CHECK_PASSWORDS_CANCELED}, {"checkedPasswords", IDS_SETTINGS_CHECKED_PASSWORDS}, @@ -817,8 +831,7 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_COMPROMISED_EDIT_PASSWORD_APP}, {"alreadyChangedPasswordLink", IDS_SETTINGS_COMPROMISED_ALREADY_CHANGED_PASSWORD}, - {"editDisclaimerTitle", - IDS_SETTINGS_COMPROMISED_EDIT_DISCLAIMER_TITLE}, + {"editDisclaimerTitle", IDS_SETTINGS_COMPROMISED_EDIT_DISCLAIMER_TITLE}, {"editDisclaimerDescription", IDS_SETTINGS_COMPROMISED_EDIT_DISCLAIMER_DESCRIPTION}, {"creditCards", IDS_AUTOFILL_PAYMENT_METHODS}, @@ -846,6 +859,8 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, {"creditCardType", IDS_SETTINGS_AUTOFILL_CREDIT_CARD_TYPE_COLUMN_LABEL}, {"creditCardExpiration", IDS_SETTINGS_CREDIT_CARD_EXPIRATION_DATE}, {"creditCardName", IDS_SETTINGS_NAME_ON_CREDIT_CARD}, + {"creditCardNickname", IDS_SETTINGS_CREDIT_CARD_NICKNAME}, + {"creditCardNicknameInvalid", IDS_SETTINGS_CREDIT_CARD_NICKNAME_INVALID}, {"creditCardNumber", IDS_SETTINGS_CREDIT_CARD_NUMBER}, {"creditCardExpirationMonth", IDS_SETTINGS_CREDIT_CARD_EXPIRATION_MONTH}, {"creditCardExpirationYear", IDS_SETTINGS_CREDIT_CARD_EXPIRATION_YEAR}, @@ -874,6 +889,10 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_PASSWORDS_LEAK_DETECTION_SIGNED_OUT_ENABLED_DESC}, {"savedPasswordsHeading", IDS_SETTINGS_PASSWORDS_SAVED_HEADING}, {"passwordExceptionsHeading", IDS_SETTINGS_PASSWORDS_EXCEPTIONS_HEADING}, + {"deviceOnlyPasswordsHeading", + IDS_SETTINGS_DEVICE_PASSWORDS_ON_DEVICE_ONLY_HEADING}, + {"deviceAndAccountPasswordsHeading", + IDS_SETTINGS_DEVICE_PASSWORDS_ON_DEVICE_AND_ACCOUNT_HEADING}, {"deletePasswordException", IDS_SETTINGS_PASSWORDS_DELETE_EXCEPTION}, {"removePassword", IDS_SETTINGS_PASSWORD_REMOVE}, {"searchPasswords", IDS_SETTINGS_PASSWORD_SEARCH}, @@ -882,6 +901,10 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, {"passwordDetailsTitle", IDS_SETTINGS_PASSWORDS_VIEW_DETAILS_TITLE}, {"passwordViewDetails", IDS_SETTINGS_PASSWORD_DETAILS}, {"copyPassword", IDS_SETTINGS_PASSWORD_COPY}, + {"passwordStoredOnDevice", IDS_SETTINGS_PASSWORD_STORED_ON_DEVICE}, + {"passwordStoredInAccount", IDS_SETTINGS_PASSWORD_STORED_IN_ACCOUNT}, + {"passwordStoredInAccountAndOnDevice", + IDS_SETTINGS_PASSWORD_STORED_IN_ACCOUNT_AND_ON_DEVICE}, {"editPasswordWebsiteLabel", IDS_SETTINGS_PASSWORDS_WEBSITE}, {"editPasswordUsernameLabel", IDS_SETTINGS_PASSWORDS_USERNAME}, {"editPasswordPasswordLabel", IDS_SETTINGS_PASSWORDS_PASSWORD}, @@ -895,11 +918,38 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, {"optOutAccountStorageLabel", IDS_SETTINGS_PASSWORDS_OPT_OUT_ACCOUNT_STORAGE_LABEL}, {"undoRemovePassword", IDS_SETTINGS_PASSWORD_UNDO}, + {"movePasswordToAccount", IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT}, {"passwordDeleted", IDS_SETTINGS_PASSWORD_DELETED_PASSWORD}, {"passwordDeletedFromDevice", IDS_SETTINGS_PASSWORD_DELETED_PASSWORD_FROM_DEVICE}, {"passwordDeletedFromAccount", IDS_SETTINGS_PASSWORD_DELETED_PASSWORD_FROM_ACCOUNT}, + {"passwordDeletedFromAccountAndDevice", + IDS_SETTINGS_PASSWORD_DELETED_PASSWORD_FROM_ACCOUNT_AND_DEVICE}, + {"passwordMoveToAccountDialogTitle", + IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_TITLE}, + {"passwordMoveToAccountDialogBody", + IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_BODY}, + {"passwordMoveToAccountDialogMoveButtonText", + IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_MOVE_BUTTON_TEXT}, + {"passwordMoveToAccountDialogCancelButtonText", + IDS_SETTINGS_PASSWORD_MOVE_TO_ACCOUNT_DIALOG_CANCEL_BUTTON_TEXT}, + {"passwordRemoveDialogTitle", IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_TITLE}, + {"passwordRemoveDialogBody", IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_BODY}, + {"passwordRemoveDialogRemoveButtonText", + IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_REMOVE_BUTTON_TEXT}, + {"passwordRemoveDialogCancelButtonText", + IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_CANCEL_BUTTON_TEXT}, + {"passwordRemoveDialogFromAccountCheckboxLabel", + IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_FROM_ACCOUNT_CHECKBOX_LABEL}, + {"passwordRemoveDialogFromDeviceCheckboxLabel", + IDS_SETTINGS_PASSWORD_REMOVE_DIALOG_FROM_DEVICE_CHECKBOX_LABEL}, + {"devicePasswordsLinkLabelSingular", + IDS_SETTINGS_DEVICE_PASSWORDS_LINK_LABEL_SINGULAR}, + {"devicePasswordsLinkLabelPlural", + IDS_SETTINGS_DEVICE_PASSWORDS_LINK_LABEL_PLURAL}, + {"devicePasswordsLinkSubLabel", + IDS_SETTINGS_DEVICE_PASSWORDS_LINK_SUB_LABEL}, {"passwordRowMoreActionsButton", IDS_SETTINGS_PASSWORD_ROW_MORE_ACTIONS}, {"passwordRowFederatedMoreActionsButton", IDS_SETTINGS_PASSWORD_ROW_FEDERATED_MORE_ACTIONS}, @@ -916,6 +966,8 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_PASSWORDS_EXPORTING_FAILURE_TIP_ENOUGH_SPACE}, {"exportPasswordsFailTipsAnotherFolder", IDS_SETTINGS_PASSWORDS_EXPORTING_FAILURE_TIP_ANOTHER_FOLDER}, + {"managePasswordsPlaintext", + IDS_SETTINGS_PASSWORDS_MANAGE_PASSWORDS_PLAINTEXT}, {"savedToThisDeviceOnly", IDS_SETTINGS_PAYMENTS_SAVED_TO_THIS_DEVICE_ONLY}}; @@ -928,6 +980,16 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_PASSWORDS_MANAGE_PASSWORDS, base::UTF8ToUTF16(google_password_manager_url.spec()))); html_source->AddString( + "optInAccountStorageBody", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_PASSWORDS_OPT_IN_ACCOUNT_STORAGE_BODY, + base::UTF8ToUTF16(google_password_manager_url.spec()))); + html_source->AddString( + "optOutAccountStorageBody", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_PASSWORDS_OPT_OUT_ACCOUNT_STORAGE_BODY, + base::UTF8ToUTF16(google_password_manager_url.spec()))); + html_source->AddString( "checkPasswordsErrorQuotaGoogleAccount", l10n_util::GetStringFUTF16( IDS_SETTINGS_CHECK_PASSWORDS_ERROR_QUOTA_LIMIT_GOOGLE_ACCOUNT, @@ -951,6 +1013,11 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, autofill::payments::GetManageInstrumentsUrl().spec()); html_source->AddString("paymentMethodsLearnMoreURL", chrome::kPaymentMethodsLearnMoreURL); + html_source->AddString( + "siteSettingsFlashWildcardsUnsupported", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_SITE_SETTINGS_FLASH_WILDCARD_UNSUPPORTED, + base::UTF8ToUTF16(chrome::kChromeFlashRoadmapURL))); bool is_guest_mode = false; #if defined(OS_CHROMEOS) @@ -982,6 +1049,10 @@ void AddAutofillStrings(content::WebUIDataSource* html_source, base::FeatureList::IsEnabled( autofill::features::kAutofillSaveAndFillVPA)); + html_source->AddBoolean( + "nicknameManagementEnabled", + base::FeatureList::IsEnabled( + autofill::features::kAutofillEnableCardNicknameManagement)); AddLocalizedStringsBulk(html_source, kLocalizedStrings); } @@ -989,15 +1060,15 @@ void AddSignOutDialogStrings(content::WebUIDataSource* html_source, Profile* profile) { #if defined(OS_CHROMEOS) bool is_dice_enabled = false; - bool is_split_sync_consent_enabled = - chromeos::features::IsSplitSyncConsentEnabled(); + bool use_browser_sync_consent = + chromeos::features::ShouldUseBrowserSyncConsent(); #else bool is_dice_enabled = AccountConsistencyModeManager::IsDiceEnabledForProfile(profile); - bool is_split_sync_consent_enabled = false; + bool use_browser_sync_consent = false; #endif - if (is_split_sync_consent_enabled || is_dice_enabled) { + if (use_browser_sync_consent || is_dice_enabled) { static constexpr webui::LocalizedString kTurnOffStrings[] = { {"syncDisconnect", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF}, {"syncDisconnectTitle", @@ -1136,6 +1207,10 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, static constexpr webui::LocalizedString kLocalizedStrings[] = { {"privacyPageTitle", IDS_SETTINGS_PRIVACY}, {"privacyPageMore", IDS_SETTINGS_PRIVACY_MORE}, + // TODO(crbug.com/1116608): This seemingly unrelated string resource is + // used because it already has a localized version available in M85, so + // we can ship this label in M85 on short notice. + {"discardedPerSiteSetting", IDS_POLICY_LABEL_IGNORED}, {"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. @@ -1293,6 +1368,10 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_PRIMARY_LABEL}, {"safetyCheckExtensionsButtonAriaLabel", IDS_SETTINGS_SAFETY_CHECK_EXTENSIONS_BUTTON_ARIA_LABEL}, + {"safetyCheckChromeCleanerPrimaryLabel", + IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_PRIMARY_LABEL}, + {"safetyCheckChromeCleanerButtonAriaLabel", + IDS_SETTINGS_SAFETY_CHECK_CHROME_CLEANER_BUTTON_ARIA_LABEL}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings); @@ -1401,8 +1480,6 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, Profile* profile) { static constexpr webui::LocalizedString kLocalizedStrings[] = { {"addSite", IDS_SETTINGS_ADD_SITE}, - {"addSiteExceptionPlaceholder", - IDS_SETTINGS_ADD_SITE_EXCEPTION_PLACEHOLDER}, {"addSiteTitle", IDS_SETTINGS_ADD_SITE_TITLE}, #if defined(OS_CHROMEOS) {"androidSmsNote", IDS_SETTINGS_ANDROID_SMS_NOTE}, @@ -1710,6 +1787,7 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, {"siteSettingsSourcePolicyAsk", IDS_PAGE_INFO_PERMISSION_ASK_BY_POLICY}, {"siteSettingsAdsBlockNotBlacklistedSingular", IDS_SETTINGS_SITE_SETTINGS_ADS_BLOCK_NOT_BLACKLISTED_SINGULAR}, + {"siteSettingsAllowlisted", IDS_SETTINGS_SITE_SETTINGS_ALLOWLISTED}, {"siteSettingsAdsBlockBlacklistedSingular", IDS_SETTINGS_SITE_SETTINGS_ADS_BLOCK_BLACKLISTED_SINGULAR}, {"siteSettingsSourceDrmDisabled", @@ -1853,6 +1931,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_WINDOW_PLACEMENT}, {"siteSettingsWindowPlacementAsk", IDS_SETTINGS_SITE_SETTINGS_WINDOW_PLACEMENT_ASK}, + {"siteSettingsWindowPlacementAskRecommended", + IDS_SETTINGS_SITE_SETTINGS_WINDOW_PLACEMENT_ASK_RECOMMENDED}, {"siteSettingsWindowPlacementBlock", IDS_SETTINGS_SITE_SETTINGS_WINDOW_PLACEMENT_BLOCK}, }; @@ -1928,9 +2008,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, base::FeatureList::IsEnabled( features::kWebBluetoothNewPermissionsBackend)); - html_source->AddBoolean( - "enableWebXrContentSetting", - base::FeatureList::IsEnabled(features::kWebXrPermissionsApi)); + // The exception placeholder should not be translated. See crbug.com/1095878. + html_source->AddString("addSiteExceptionPlaceholder", "[*.]example.com"); } #if !defined(OS_CHROMEOS) diff --git a/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc index 83923229636..a06c62efb33 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc @@ -11,7 +11,6 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/value_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/gaia_info_update_service.h" diff --git a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc index b0818ee920f..85887e9be9a 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.cc @@ -8,7 +8,6 @@ #include <utility> #include "base/bind.h" -#include "base/metrics/histogram_macros.h" #include "base/rand_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/net/secure_dns_config.h" @@ -24,10 +23,12 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "net/dns/public/dns_over_https_server_config.h" -#include "net/dns/public/doh_provider_list.h" +#include "net/dns/public/doh_provider_entry.h" #include "net/dns/public/util.h" #include "ui/base/l10n/l10n_util.h" +namespace secure_dns = chrome_browser_net::secure_dns; + namespace settings { namespace { @@ -57,11 +58,7 @@ std::unique_ptr<base::DictionaryValue> CreateSecureDnsSettingDict() { } // namespace -SecureDnsHandler::SecureDnsHandler() - : network_context_getter_( - base::BindRepeating(&SecureDnsHandler::GetNetworkContext, - base::Unretained(this))) {} - +SecureDnsHandler::SecureDnsHandler() = default; SecureDnsHandler::~SecureDnsHandler() = default; void SecureDnsHandler::RegisterMessages() { @@ -111,38 +108,14 @@ void SecureDnsHandler::OnJavascriptDisallowed() { pref_registrar_.RemoveAll(); } -base::Value SecureDnsHandler::GetSecureDnsResolverListForCountry( - int country_id, - const std::vector<net::DohProviderEntry>& providers) { - std::vector<std::string> disabled_providers = - SplitString(features::kDnsOverHttpsDisabledProvidersParam.Get(), ",", - base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); - +base::Value SecureDnsHandler::GetSecureDnsResolverList() { base::Value resolvers(base::Value::Type::LIST); - resolver_histogram_map_.clear(); - // Add all non-disabled resolvers that should be displayed in |country_id|. - for (const auto& entry : providers) { - if (base::Contains(disabled_providers, entry.provider)) - continue; - - if (entry.display_globally || - std::find_if( - entry.display_countries.begin(), entry.display_countries.end(), - [&country_id](const std::string& country_code) { - return country_codes::CountryCharsToCountryID( - country_code[0], country_code[1]) == country_id; - }) != entry.display_countries.end()) { - DCHECK(!entry.ui_name.empty()); - DCHECK(!entry.privacy_policy.empty()); - base::Value dict(base::Value::Type::DICTIONARY); - dict.SetKey("name", base::Value(entry.ui_name)); - dict.SetKey("value", base::Value(entry.dns_over_https_template)); - dict.SetKey("policy", base::Value(entry.privacy_policy)); - resolvers.Append(std::move(dict)); - DCHECK(entry.provider_id_for_histogram.has_value()); - resolver_histogram_map_.insert({entry.dns_over_https_template, - entry.provider_id_for_histogram.value()}); - } + for (const auto* entry : providers_) { + base::Value dict(base::Value::Type::DICTIONARY); + dict.SetStringKey("name", entry->ui_name); + dict.SetStringKey("value", entry->dns_over_https_template); + dict.SetStringKey("policy", entry->privacy_policy); + resolvers.Append(std::move(dict)); } // Randomize the order of the resolvers. @@ -150,13 +123,10 @@ base::Value SecureDnsHandler::GetSecureDnsResolverListForCountry( // Add a custom option to the front of the list base::Value custom(base::Value::Type::DICTIONARY); - custom.SetKey("name", - base::Value(l10n_util::GetStringUTF8(IDS_SETTINGS_CUSTOM))); - custom.SetKey("value", base::Value("custom")); - custom.SetKey("policy", base::Value(std::string())); + custom.SetStringKey("name", l10n_util::GetStringUTF8(IDS_SETTINGS_CUSTOM)); + custom.SetStringKey("value", std::string()); // Empty value means custom. + custom.SetStringKey("policy", std::string()); resolvers.Insert(resolvers.GetList().begin(), std::move(custom)); - resolver_histogram_map_.insert( - {"custom", net::DohProviderIdForHistogram::kCustom}); return resolvers; } @@ -176,15 +146,18 @@ network::mojom::NetworkContext* SecureDnsHandler::GetNetworkContext() { ->GetNetworkContext(); } +void SecureDnsHandler::SetProvidersForTesting( + net::DohProviderEntry::List providers) { + providers_ = std::move(providers); +} + void SecureDnsHandler::HandleGetSecureDnsResolverList( const base::ListValue* args) { AllowJavascript(); std::string callback_id = args->GetList()[0].GetString(); - ResolveJavascriptCallback( - base::Value(callback_id), - GetSecureDnsResolverListForCountry(country_codes::GetCurrentCountryID(), - net::GetDohProviderList())); + ResolveJavascriptCallback(base::Value(callback_id), + GetSecureDnsResolverList()); } void SecureDnsHandler::HandleGetSecureDnsSetting(const base::ListValue* args) { @@ -203,14 +176,12 @@ void SecureDnsHandler::HandleParseCustomDnsEntry(const base::ListValue* args) { // Return all templates in the entry, or none if they are not all valid. base::Value templates(base::Value::Type::LIST); - if (chrome_browser_net::secure_dns::IsValidGroup(custom_entry)) { - for (base::StringPiece t : - chrome_browser_net::secure_dns::SplitGroup(custom_entry)) { + if (secure_dns::IsValidGroup(custom_entry)) { + for (base::StringPiece t : secure_dns::SplitGroup(custom_entry)) { templates.Append(t); } } - UMA_HISTOGRAM_BOOLEAN("Net.DNS.UI.ValidationAttemptSuccess", - !templates.GetList().empty()); + secure_dns::UpdateValidationHistogram(!templates.GetList().empty()); ResolveJavascriptCallback(*callback_id, templates); } @@ -236,7 +207,7 @@ void SecureDnsHandler::HandleProbeCustomDnsTemplate( overrides.attempts = 1; overrides.randomize_ports = false; overrides.secure_dns_mode = net::DnsConfig::SecureDnsMode::SECURE; - chrome_browser_net::secure_dns::ApplyTemplate(&overrides, server_template); + secure_dns::ApplyTemplate(&overrides, server_template); DCHECK(!runner_); runner_ = std::make_unique<chrome_browser_net::DnsProbeRunner>( overrides, network_context_getter_); @@ -251,29 +222,15 @@ void SecureDnsHandler::HandleRecordUserDropdownInteraction( std::string new_provider; CHECK(args->GetString(0, &old_provider)); CHECK(args->GetString(1, &new_provider)); - DCHECK(resolver_histogram_map_.find(old_provider) != - resolver_histogram_map_.end()); - DCHECK(resolver_histogram_map_.find(new_provider) != - resolver_histogram_map_.end()); - for (auto& pair : resolver_histogram_map_) { - if (pair.first == old_provider) { - UMA_HISTOGRAM_ENUMERATION("Net.DNS.UI.DropdownSelectionEvent.Unselected", - pair.second); - } else if (pair.first == new_provider) { - UMA_HISTOGRAM_ENUMERATION("Net.DNS.UI.DropdownSelectionEvent.Selected", - pair.second); - } else { - UMA_HISTOGRAM_ENUMERATION("Net.DNS.UI.DropdownSelectionEvent.Ignored", - pair.second); - } - } + + secure_dns::UpdateDropdownHistograms(providers_, old_provider, new_provider); } void SecureDnsHandler::OnProbeComplete() { bool success = runner_->result() == chrome_browser_net::DnsProbeRunner::CORRECT; runner_.reset(); - UMA_HISTOGRAM_BOOLEAN("Net.DNS.UI.ProbeAttemptSuccess", success); + secure_dns::UpdateProbeHistogram(success); ResolveJavascriptCallback(base::Value(probe_callback_id_), base::Value(success)); probe_callback_id_.clear(); @@ -284,4 +241,12 @@ void SecureDnsHandler::SendSecureDnsSettingUpdatesToJavascript() { *CreateSecureDnsSettingDict()); } +// static +net::DohProviderEntry::List SecureDnsHandler::GetFilteredProviders() { + const auto local_providers = secure_dns::ProvidersForCountry( + net::DohProviderEntry::GetList(), country_codes::GetCurrentCountryID()); + return secure_dns::RemoveDisabledProviders( + local_providers, secure_dns::GetDisabledProviders()); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h index 9f7622ae20d..dddaea2127a 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/settings_secure_dns_handler.h @@ -9,12 +9,13 @@ #include <string> #include <vector> +#include "base/bind.h" #include "base/macros.h" #include "base/values.h" #include "chrome/browser/net/dns_probe_runner.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/prefs/pref_change_registrar.h" -#include "net/dns/public/doh_provider_list.h" +#include "net/dns/public/doh_provider_entry.h" #include "services/network/public/cpp/resolve_host_client_base.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -35,13 +36,15 @@ class SecureDnsHandler : public SettingsPageUIHandler { // as a dictionary with the following keys: "name" (the text to display in the // UI), "value" (the DoH template for this provider), and "policy" (the URL of // the provider's privacy policy). - base::Value GetSecureDnsResolverListForCountry( - int country_id, - const std::vector<net::DohProviderEntry>& providers); + base::Value GetSecureDnsResolverList(); void SetNetworkContextForTesting( network::mojom::NetworkContext* network_context); + // DohProviderEntry cannot be copied, so the entries referenced in |providers| + // must be long-lived. + void SetProvidersForTesting(net::DohProviderEntry::List providers); + protected: // Retrieves all pre-approved secure resolvers and returns them to WebUI. void HandleGetSecureDnsResolverList(const base::ListValue* args); @@ -66,10 +69,14 @@ class SecureDnsHandler : public SettingsPageUIHandler { network::mojom::NetworkContext* GetNetworkContext(); void OnProbeComplete(); - std::map<std::string, net::DohProviderIdForHistogram> resolver_histogram_map_; + static net::DohProviderEntry::List GetFilteredProviders(); + + net::DohProviderEntry::List providers_ = GetFilteredProviders(); std::unique_ptr<chrome_browser_net::DnsProbeRunner> runner_; chrome_browser_net::DnsProbeRunner::NetworkContextGetter - network_context_getter_; + network_context_getter_ = + base::BindRepeating(&SecureDnsHandler::GetNetworkContext, + base::Unretained(this)); // ID of the Javascript callback for the current pending probe, or "" if // there is no probe currently in progress. std::string probe_callback_id_; 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 3ece9212741..81aa1024fc1 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 @@ -27,7 +27,6 @@ #include "base/win/win_util.h" #endif -using net::DohProviderEntry; using testing::_; using testing::IsEmpty; using testing::Return; @@ -43,47 +42,38 @@ constexpr char kRecordUserDropdownInteraction[] = "recordUserDropdownInteraction"; constexpr char kWebUiFunctionName[] = "webUiCallbackName"; -const std::vector<DohProviderEntry>& GetDohProviderListForTesting() { - static const base::NoDestructor<std::vector<DohProviderEntry>> test_providers{ - { - DohProviderEntry( - "Provider_Global1", net::DohProviderIdForHistogram(-1), - {} /*ip_strs */, {} /* dot_hostnames */, - "https://global1.provider/dns-query{?dns}", - "Global Provider 1" /* ui_name */, - "https://global1.provider/privacy_policy/" /* privacy_policy */, - true /* display_globally */, {} /* display_countries */), - DohProviderEntry( - "Provider_NoDisplay", net::DohProviderIdForHistogram(-2), - {} /*ip_strs */, {} /* dot_hostnames */, - "https://nodisplay.provider/dns-query{?dns}", - "No Display Provider" /* ui_name */, - "https://nodisplay.provider/privacy_policy/" /* privacy_policy */, - false /* display_globally */, {} /* display_countries */), - DohProviderEntry( - "Provider_EE_FR", net::DohProviderIdForHistogram(-3), - {} /*ip_strs */, {} /* dot_hostnames */, - "https://ee.fr.provider/dns-query{?dns}", - "EE/FR Provider" /* ui_name */, - "https://ee.fr.provider/privacy_policy/" /* privacy_policy */, - false /* display_globally */, - {"EE", "FR"} /* display_countries */), - DohProviderEntry( - "Provider_FR", net::DohProviderIdForHistogram(-4), - {} /*ip_strs */, {} /* dot_hostnames */, - "https://fr.provider/dns-query{?dns}", - "FR Provider" /* ui_name */, - "https://fr.provider/privacy_policy/" /* privacy_policy */, - false /* display_globally */, {"FR"} /* display_countries */), - DohProviderEntry( - "Provider_Global2", net::DohProviderIdForHistogram(-5), - {} /*ip_strs */, {} /* dot_hostnames */, - "https://global2.provider/dns-query{?dns}", - "Global Provider 2" /* ui_name */, - "https://global2.provider/privacy_policy/" /* privacy_policy */, - true /* display_globally */, {} /* display_countries */), - }}; - return *test_providers; +net::DohProviderEntry::List GetDohProviderListForTesting() { + static const auto global1 = net::DohProviderEntry::ConstructForTesting( + "Provider_Global1", net::DohProviderIdForHistogram(-1), {} /*ip_strs */, + {} /* dot_hostnames */, "https://global1.provider/dns-query{?dns}", + "Global Provider 1" /* ui_name */, + "https://global1.provider/privacy_policy/" /* privacy_policy */, + true /* display_globally */, {} /* display_countries */); + static const auto no_display = net::DohProviderEntry::ConstructForTesting( + "Provider_NoDisplay", net::DohProviderIdForHistogram(-2), {} /*ip_strs */, + {} /* dot_hostnames */, "https://nodisplay.provider/dns-query{?dns}", + "No Display Provider" /* ui_name */, + "https://nodisplay.provider/privacy_policy/" /* privacy_policy */, + false /* display_globally */, {} /* display_countries */); + static const auto ee_fr = net::DohProviderEntry::ConstructForTesting( + "Provider_EE_FR", net::DohProviderIdForHistogram(-3), {} /*ip_strs */, + {} /* dot_hostnames */, "https://ee.fr.provider/dns-query{?dns}", + "EE/FR Provider" /* ui_name */, + "https://ee.fr.provider/privacy_policy/" /* privacy_policy */, + false /* display_globally */, {"EE", "FR"} /* display_countries */); + static const auto fr = net::DohProviderEntry::ConstructForTesting( + "Provider_FR", net::DohProviderIdForHistogram(-4), {} /*ip_strs */, + {} /* dot_hostnames */, "https://fr.provider/dns-query{?dns}", + "FR Provider" /* ui_name */, + "https://fr.provider/privacy_policy/" /* privacy_policy */, + false /* display_globally */, {"FR"} /* display_countries */); + static const auto global2 = net::DohProviderEntry::ConstructForTesting( + "Provider_Global2", net::DohProviderIdForHistogram(-5), {} /*ip_strs */, + {} /* dot_hostnames */, "https://global2.provider/dns-query{?dns}", + "Global Provider 2" /* ui_name */, + "https://global2.provider/privacy_policy/" /* privacy_policy */, + true /* display_globally */, {} /* display_countries */); + return {&global1, &no_display, &ee_fr, &fr, &global2}; } bool FindDropdownItem(const base::Value& resolvers, @@ -315,116 +305,40 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownList) { // Check results. base::Value::ConstListView resolver_list = call_data.arg3()->GetList(); ASSERT_GE(resolver_list.size(), 1U); - EXPECT_EQ("custom", resolver_list[0].FindKey("value")->GetString()); + EXPECT_TRUE(resolver_list[0].FindKey("value")->GetString().empty()); } -IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListForCountry) { - // The 'EE' list should start with the custom entry, followed by the two - // global providers and the 'EE' provider in some random order. - base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry( - country_codes::CountryCharsToCountryID('E', 'E'), - GetDohProviderListForTesting()); - EXPECT_EQ(4u, resolver_list.GetList().size()); - EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString()); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1", - "https://global1.provider/dns-query{?dns}", - "https://global1.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2", - "https://global2.provider/dns-query{?dns}", - "https://global2.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "EE/FR Provider", - "https://ee.fr.provider/dns-query{?dns}", - "https://ee.fr.provider/privacy_policy/")); - - // The 'FR' list should start with the custom entry, followed by the two - // global providers and the two 'FR' providers in some random order. - resolver_list = handler_->GetSecureDnsResolverListForCountry( - country_codes::CountryCharsToCountryID('F', 'R'), - GetDohProviderListForTesting()); - EXPECT_EQ(5u, resolver_list.GetList().size()); - EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString()); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1", - "https://global1.provider/dns-query{?dns}", - "https://global1.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2", - "https://global2.provider/dns-query{?dns}", - "https://global2.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "EE/FR Provider", - "https://ee.fr.provider/dns-query{?dns}", - "https://ee.fr.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "FR Provider", - "https://fr.provider/dns-query{?dns}", - "https://fr.provider/privacy_policy/")); - - // The 'CA' list should start with the custom entry, followed by the two - // global providers. - resolver_list = handler_->GetSecureDnsResolverListForCountry( - country_codes::CountryCharsToCountryID('C', 'A'), - GetDohProviderListForTesting()); - EXPECT_EQ(3u, resolver_list.GetList().size()); - EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString()); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1", - "https://global1.provider/dns-query{?dns}", - "https://global1.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 2", - "https://global2.provider/dns-query{?dns}", - "https://global2.provider/privacy_policy/")); +IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListContents) { + const auto entries = GetDohProviderListForTesting(); + handler_->SetProvidersForTesting(entries); + const base::Value resolver_list = handler_->GetSecureDnsResolverList(); + + EXPECT_EQ(entries.size() + 1, resolver_list.GetList().size()); + EXPECT_TRUE(resolver_list.GetList()[0].FindKey("value")->GetString().empty()); + for (const auto* entry : entries) { + EXPECT_TRUE(FindDropdownItem(resolver_list, entry->ui_name, + entry->dns_over_https_template, + entry->privacy_policy)); + } } IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, DropdownListChange) { - // Populate the map for recording dropdown change metrics. - base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry( - country_codes::CountryCharsToCountryID('E', 'E'), - GetDohProviderListForTesting()); - EXPECT_EQ(4u, resolver_list.GetList().size()); + handler_->SetProvidersForTesting(GetDohProviderListForTesting()); base::HistogramTester histograms; base::ListValue args; - args.AppendString("custom" /* old_provider */); + args.AppendString(std::string() /* old_provider */); args.AppendString( "https://global1.provider/dns-query{?dns}" /* new_provider */); web_ui_.HandleReceivedMessage(kRecordUserDropdownInteraction, &args); - const std::string uma_base("Net.DNS.UI.DropdownSelectionEvent"); - histograms.ExpectTotalCount(uma_base + ".Ignored", 2u); - histograms.ExpectTotalCount(uma_base + ".Selected", 1u); - histograms.ExpectTotalCount(uma_base + ".Unselected", 1u); + const std::string kUmaBase = "Net.DNS.UI.DropdownSelectionEvent"; + histograms.ExpectTotalCount(kUmaBase + ".Ignored", 4u); + histograms.ExpectTotalCount(kUmaBase + ".Selected", 1u); + histograms.ExpectTotalCount(kUmaBase + ".Unselected", 1u); } -class SecureDnsHandlerTestWithDisabledProviders : public SecureDnsHandlerTest { - protected: - SecureDnsHandlerTestWithDisabledProviders() { - scoped_features_.InitAndEnableFeatureWithParameters( - features::kDnsOverHttps, - {{"DisabledProviders", - "Provider_Global2, , Provider_EE_FR,Unexpected"}}); - } - - private: - base::test::ScopedFeatureList scoped_features_; - - DISALLOW_COPY_AND_ASSIGN(SecureDnsHandlerTestWithDisabledProviders); -}; - -IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders, - DropdownListDisabledProviders) { - // The 'FR' list should start with the custom entry, followed by the two - // global providers and the two 'FR' providers in some random order. - base::Value resolver_list = handler_->GetSecureDnsResolverListForCountry( - country_codes::CountryCharsToCountryID('F', 'R'), - GetDohProviderListForTesting()); - EXPECT_EQ(3u, resolver_list.GetList().size()); - EXPECT_EQ("custom", resolver_list.GetList()[0].FindKey("value")->GetString()); - EXPECT_TRUE(FindDropdownItem(resolver_list, "Global Provider 1", - "https://global1.provider/dns-query{?dns}", - "https://global1.provider/privacy_policy/")); - EXPECT_TRUE(FindDropdownItem(resolver_list, "FR Provider", - "https://fr.provider/dns-query{?dns}", - "https://fr.provider/privacy_policy/")); -} - -IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders, - SecureDnsTemplates) { +IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, SecureDnsTemplates) { std::string good_post_template = "https://foo.test/"; std::string good_get_template = "https://bar.test/dns-query{?dns}"; std::string bad_template = "dns-query{?dns}"; @@ -433,6 +347,8 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders, std::vector<std::string> secure_dns_templates; int management_mode; PrefService* local_state = g_browser_process->local_state(); + local_state->SetString(prefs::kDnsOverHttpsMode, + SecureDnsConfig::kModeAutomatic); local_state->SetString(prefs::kDnsOverHttpsTemplates, good_post_template); EXPECT_TRUE(GetLastSettingsChangedMessage( &secure_dns_mode, &secure_dns_templates, &management_mode)); @@ -458,15 +374,6 @@ IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTestWithDisabledProviders, &secure_dns_mode, &secure_dns_templates, &management_mode)); EXPECT_EQ(1u, secure_dns_templates.size()); EXPECT_EQ(good_post_template, secure_dns_templates[0]); - - // Should still return a provider that was disabled. - local_state->SetString(prefs::kDnsOverHttpsTemplates, - "https://global2.provider/dns-query{?dns}"); - EXPECT_TRUE(GetLastSettingsChangedMessage( - &secure_dns_mode, &secure_dns_templates, &management_mode)); - EXPECT_EQ(1u, secure_dns_templates.size()); - EXPECT_EQ("https://global2.provider/dns-query{?dns}", - secure_dns_templates[0]); } IN_PROC_BROWSER_TEST_F(SecureDnsHandlerTest, TemplateValid) { diff --git a/chromium/chrome/browser/ui/webui/settings/settings_ui.cc b/chromium/chrome/browser/ui/webui/settings/settings_ui.cc index 0462890255d..9e29823de46 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_ui.cc @@ -285,11 +285,17 @@ SettingsUI::SettingsUI(content::WebUI* web_ui) "syncSetupFriendlySettings", base::FeatureList::IsEnabled(features::kSyncSetupFriendlySettings)); +#if defined(OS_WIN) + html_source->AddBoolean( + "safetyCheckChromeCleanerChildEnabled", + base::FeatureList::IsEnabled(features::kSafetyCheckChromeCleanerChild)); +#endif + #if defined(OS_CHROMEOS) html_source->AddBoolean("splitSettingsSyncEnabled", chromeos::features::IsSplitSettingsSyncEnabled()); - html_source->AddBoolean("splitSyncConsent", - chromeos::features::IsSplitSyncConsentEnabled()); + html_source->AddBoolean("useBrowserSyncConsent", + chromeos::features::ShouldUseBrowserSyncConsent()); html_source->AddBoolean( "userCannotManuallyEnterPassword", 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 20abed8007e..ae20e5716f0 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 @@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" #include "build/build_config.h" +#include "chrome/browser/browser_features.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -242,4 +243,15 @@ void AddSyncPageStrings(content::WebUIDataSource* html_source) { } } +void AddNearbyShareData(content::WebUIDataSource* html_source) { + static constexpr webui::LocalizedString kLocalizedStrings[] = { + {"nearbyShareTitle", IDS_SETTINGS_NEARBY_SHARE_TITLE}, + }; + AddLocalizedStringsBulk(html_source, kLocalizedStrings); + + html_source->AddBoolean( + "nearbySharingFeatureFlag", + base::FeatureList::IsEnabled(features::kNearbySharing)); +} + } // 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 33dc5c453d4..73333c7fef5 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 @@ -31,6 +31,9 @@ void AddPasswordPromptDialogStrings(content::WebUIDataSource* html_source); // Adds strings used by the <settings-sync-page> element. void AddSyncPageStrings(content::WebUIDataSource* html_source); +// Adds load time data used by the <settings-nearby-share-subpage>. +void AddNearbyShareData(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 e195fcbd936..bcbafdd8e31 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc @@ -95,14 +95,6 @@ constexpr char kPlaceholder[] = "placeholder"; // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. -enum class AllSitesAction { - kLoadPage = 0, - kResetPermissions = 1, - kClearData = 2, - kEnterSiteDetails = 3, - kMaxValue = kEnterSiteDetails, -}; - enum class AllSitesAction2 { kLoadPage = 0, kResetSiteGroupPermissions = 1, @@ -418,11 +410,6 @@ void SiteSettingsHandler::RegisterMessages() { base::BindRepeating(&SiteSettingsHandler::HandleGetAllSites, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "getCookieControlsManagedState", - base::BindRepeating( - &SiteSettingsHandler::HandleGetCookieControlsManagedState, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( "getCookieSettingDescription", base::BindRepeating( &SiteSettingsHandler::HandleGetCookieSettingDescription, @@ -817,34 +804,6 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { ResolveJavascriptCallback(base::Value(callback_id), result); } -void SiteSettingsHandler::HandleGetCookieControlsManagedState( - const base::ListValue* args) { - AllowJavascript(); - CHECK_EQ(1U, args->GetList().size()); - std::string callback_id = args->GetList()[0].GetString(); - - auto managed_states = site_settings::GetCookieControlsManagedState(profile_); - - base::Value result(base::Value::Type::DICTIONARY); - result.SetKey( - site_settings::kAllowAll, - site_settings::GetValueForManagedState(managed_states.allow_all)); - result.SetKey(site_settings::kBlockThirdPartyIncognito, - site_settings::GetValueForManagedState( - managed_states.block_third_party_incognito)); - result.SetKey( - site_settings::kBlockThirdParty, - site_settings::GetValueForManagedState(managed_states.block_third_party)); - result.SetKey( - site_settings::kBlockAll, - site_settings::GetValueForManagedState(managed_states.block_all)); - result.SetKey( - site_settings::kSessionOnly, - site_settings::GetValueForManagedState(managed_states.session_only)); - - ResolveJavascriptCallback(base::Value(callback_id), result); -} - void SiteSettingsHandler::HandleGetCookieSettingDescription( const base::ListValue* args) { AllowJavascript(); 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 0b34a324727..90c8106441b 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h @@ -128,11 +128,13 @@ class SiteSettingsHandler FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies); - FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, CookieControlsManagedState); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, CookieSettingDescription); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, HandleGetFormattedBytes); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, NotificationPermissionRevokeUkm); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ExcludeWebUISchemesInLists); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, + IncludeWebUISchemesInGetOriginPermissions); // Creates the CookiesTreeModel if necessary. void EnsureCookiesTreeModelCreated(); @@ -171,10 +173,6 @@ class SiteSettingsHandler // the front end when fetching finished. void HandleGetAllSites(const base::ListValue* args); - // Returns whether each of the cookie controls is managed and if so what - // the source of that management is. - void HandleGetCookieControlsManagedState(const base::ListValue* args); - // Returns a string for display describing the current cookie settings. void HandleGetCookieSettingDescription(const base::ListValue* args); 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 ee654373208..95b114fb5dc 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 @@ -45,8 +45,6 @@ #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/features.h" #include "components/content_settings/core/common/pref_names.h" -#include "components/content_settings/core/test/content_settings_mock_provider.h" -#include "components/content_settings/core/test/content_settings_test_utils.h" #include "components/history/core/browser/history_service.h" #include "components/infobars/core/infobar.h" #include "components/permissions/chooser_context_base.h" @@ -67,6 +65,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/text/bytes_formatting.h" +#include "ui/webui/webui_allowlist.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/login/users/mock_user_manager.h" @@ -424,9 +423,10 @@ class SiteSettingsHandlerTest : public testing::Test { } virtual void DestroyIncognitoProfile() { - profile_->SetOffTheRecordProfile(nullptr); - ASSERT_FALSE(profile_->HasOffTheRecordProfile()); - incognito_profile_ = nullptr; + if (incognito_profile_) { + profile_->DestroyOffTheRecordProfile(incognito_profile_); + incognito_profile_ = nullptr; + } } // TODO(https://crbug.com/835712): Currently only set up the cookies and local @@ -1877,6 +1877,133 @@ TEST_F(SiteSettingsHandlerTest, BlockAutoplay_Update) { EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled)); } +TEST_F(SiteSettingsHandlerTest, ExcludeWebUISchemesInLists) { + const ContentSettingsType content_settings_type = + ContentSettingsType::NOTIFICATIONS; + // Register WebUIAllowlist auto-granted permissions. + const url::Origin kWebUIOrigins[] = { + url::Origin::Create(GURL("chrome://test")), + url::Origin::Create(GURL("chrome-untrusted://test")), + url::Origin::Create(GURL("devtools://devtools")), + }; + + WebUIAllowlist* allowlist = WebUIAllowlist::GetOrCreate(profile()); + for (const url::Origin& origin : kWebUIOrigins) + allowlist->RegisterAutoGrantedPermission(origin, content_settings_type); + + // Verify the auto-granted permissions are registered, and they are indeed + // provided by WebUIAllowlist. + HostContentSettingsMap* map = + HostContentSettingsMapFactory::GetForProfile(profile()); + content_settings::SettingInfo info; + std::unique_ptr<base::Value> value = map->GetWebsiteSetting( + kWebUIOrigins[0].GetURL(), kWebUIOrigins[0].GetURL(), + content_settings_type, std::string(), &info); + EXPECT_EQ(CONTENT_SETTING_ALLOW, value->GetInt()); + EXPECT_EQ(content_settings::SETTING_SOURCE_ALLOWLIST, info.source); + + // Register an ordinary website permission. + const GURL kWebUrl = GURL("https://example.com"); + map->SetContentSettingDefaultScope(kWebUrl, kWebUrl, content_settings_type, + std::string(), CONTENT_SETTING_ALLOW); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + map->GetContentSetting(kWebUrl, kWebUrl, content_settings_type, + std::string())); + + // 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)); + + handler()->HandleGetAllSites(&get_all_sites_args); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + base::Value::ConstListView site_groups = data.arg3()->GetList(); + EXPECT_EQ(1UL, site_groups.size()); + + const std::string etld_plus1_string = + site_groups[0].FindKey("etldPlus1")->GetString(); + EXPECT_EQ("example.com", etld_plus1_string); + base::Value::ConstListView origin_list = + site_groups[0].FindKey("origins")->GetList(); + EXPECT_EQ(1UL, origin_list.size()); + EXPECT_EQ(kWebUrl.spec(), origin_list[0].FindKey("origin")->GetString()); + } + + // GetExceptionList() only returns website exceptions. + { + base::ListValue get_exception_list_args; + get_exception_list_args.AppendString(kCallbackId); + get_exception_list_args.AppendString(kNotifications); + + handler()->HandleGetExceptionList(&get_exception_list_args); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + base::Value::ConstListView exception_list = data.arg3()->GetList(); + EXPECT_EQ(1UL, exception_list.size()); + EXPECT_EQ("https://example.com:443", + exception_list[0].FindKey("origin")->GetString()); + } + + // 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)); + get_recent_permissions_args.Append(3); + + handler()->HandleGetRecentSitePermissions(&get_recent_permissions_args); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + base::Value::ConstListView recent_permission_list = data.arg3()->GetList(); + EXPECT_EQ(1UL, recent_permission_list.size()); + EXPECT_EQ(kWebUrl.spec(), + recent_permission_list[0].FindKey("origin")->GetString()); + } +} + +// GetOriginPermissions() returns the allowlisted exception. We explicitly +// return this, so developers can easily test things (e.g. by navigating to +// chrome://settings/content/siteDetails?site=chrome://example). +TEST_F(SiteSettingsHandlerTest, IncludeWebUISchemesInGetOriginPermissions) { + const ContentSettingsType content_settings_type = + ContentSettingsType::NOTIFICATIONS; + + // Register WebUIAllowlist auto-granted permissions. + const url::Origin kWebUIOrigins[] = { + url::Origin::Create(GURL("chrome://test")), + url::Origin::Create(GURL("chrome-untrusted://test")), + url::Origin::Create(GURL("devtools://devtools")), + }; + + WebUIAllowlist* allowlist = WebUIAllowlist::GetOrCreate(profile()); + for (const url::Origin& origin : kWebUIOrigins) + 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); + get_origin_permissions_args.Append(std::move(category_list)); + + handler()->HandleGetOriginPermissions(&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()); + + EXPECT_EQ(origin.GetURL().spec(), + exception_list[0].FindKey("origin")->GetString()); + EXPECT_EQ("allowlist", exception_list[0].FindKey("source")->GetString()); + } +} + namespace { constexpr char kUsbPolicySetting[] = R"( @@ -1907,6 +2034,9 @@ GURL ChromiumUrl() { GURL GoogleUrl() { return GURL("https://google.com"); } +GURL WebUIUrl() { + return GURL("chrome://test"); +} } // namespace @@ -1954,6 +2084,7 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest { const auto kAndroidOrigin = url::Origin::Create(AndroidUrl()); const auto kChromiumOrigin = url::Origin::Create(ChromiumUrl()); const auto kGoogleOrigin = url::Origin::Create(GoogleUrl()); + const auto kWebUIOrigin = url::Origin::Create(WebUIUrl()); // Add the user granted permissions for testing. // These two persistent device permissions should be lumped together with @@ -1964,6 +2095,8 @@ class SiteSettingsHandlerChooserExceptionTest : public SiteSettingsHandlerTest { *persistent_device_info_); chooser_context->GrantDevicePermission(kAndroidOrigin, kChromiumOrigin, *persistent_device_info_); + chooser_context->GrantDevicePermission(kWebUIOrigin, kWebUIOrigin, + *persistent_device_info_); chooser_context->GrantDevicePermission(kAndroidOrigin, kAndroidOrigin, *ephemeral_device_info_); chooser_context->GrantDevicePermission(kAndroidOrigin, kAndroidOrigin, @@ -2118,6 +2251,11 @@ TEST_F(SiteSettingsHandlerChooserExceptionTest, const base::Value& exceptions = GetChooserExceptionListFromWebUiCallData( kUsbChooserGroupName, /*expected_total_calls=*/1u); EXPECT_EQ(exceptions.GetList().size(), 5u); + + // Don't include WebUI schemes. + const std::string kWebUIOriginStr = WebUIUrl().GetOrigin().spec(); + EXPECT_FALSE(ChooserExceptionContainsSiteException( + exceptions, "Gizmo", kWebUIOriginStr, kWebUIOriginStr)); } TEST_F(SiteSettingsHandlerChooserExceptionTest, @@ -2338,61 +2476,6 @@ TEST_F(SiteSettingsHandlerTest, HandleClearEtldPlus1DataAndCookies) { EXPECT_EQ(0U, storage_and_cookie_list->GetSize()); } -TEST_F(SiteSettingsHandlerTest, CookieControlsManagedState) { - // Test that the handler correctly wraps the helper result. Helper with - // extensive logic is tested in site_settings_helper_unittest.cc. - const std::string kNone = "none"; - const std::string kDevicePolicy = "devicePolicy"; - const std::vector<std::string> kControlNames = { - "allowAll", "blockAll", "blockThirdParty", "blockThirdPartyIncognito", - "sessionOnly"}; - - // Check that the default cookie control state is handled correctly. - base::ListValue get_args; - get_args.AppendString(kCallbackId); - handler()->HandleGetCookieControlsManagedState(&get_args); - { - const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); - EXPECT_EQ("cr.webUIResponse", data.function_name()); - EXPECT_EQ(kCallbackId, data.arg1()->GetString()); - ASSERT_TRUE(data.arg2()->GetBool()); - for (const auto& control_name : kControlNames) { - auto* control_state = data.arg3()->FindPath(control_name); - ASSERT_FALSE(control_state->FindKey("disabled")->GetBool()); - ASSERT_EQ(kNone, control_state->FindKey("indicator")->GetString()); - } - } - - // Check that a fully managed cookie state is handled correctly. - HostContentSettingsMap* map = - HostContentSettingsMapFactory::GetForProfile(profile()); - auto provider = std::make_unique<content_settings::MockProvider>(); - provider->SetWebsiteSetting( - ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), - ContentSettingsType::COOKIES, std::string(), - std::make_unique<base::Value>(CONTENT_SETTING_ALLOW)); - content_settings::TestUtils::OverrideProvider( - map, std::move(provider), HostContentSettingsMap::POLICY_PROVIDER); - sync_preferences::TestingPrefServiceSyncable* pref_service = - profile()->GetTestingPrefService(); - pref_service->SetManagedPref(prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(true)); - - handler()->HandleGetCookieControlsManagedState(&get_args); - { - const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); - EXPECT_EQ("cr.webUIResponse", data.function_name()); - EXPECT_EQ(kCallbackId, data.arg1()->GetString()); - ASSERT_TRUE(data.arg2()->GetBool()); - for (const auto& control_name : kControlNames) { - auto* control_state = data.arg3()->FindPath(control_name); - ASSERT_TRUE(control_state->FindKey("disabled")->GetBool()); - ASSERT_EQ(kDevicePolicy, - control_state->FindKey("indicator")->GetString()); - } - } -} - TEST_F(SiteSettingsHandlerTest, CookieSettingDescription) { const auto kBlocked = [](int num) { return l10n_util::GetPluralStringFUTF8( 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 5dfef5ee030..28addc32434 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_helper.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_helper.cc @@ -10,8 +10,11 @@ #include <string> #include "base/feature_list.h" +#include "base/no_destructor.h" #include "base/stl_util.h" +#include "base/strings/strcat.h" #include "base/strings/string16.h" +#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/bluetooth/bluetooth_chooser_context.h" @@ -26,12 +29,10 @@ #include "chrome/browser/usb/usb_chooser_context.h" #include "chrome/browser/usb/usb_chooser_context_factory.h" #include "chrome/common/pref_names.h" -#include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_utils.h" -#include "components/content_settings/core/common/pref_names.h" #include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/permissions/permission_manager.h" @@ -42,9 +43,11 @@ #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/url_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/common/constants.h" #include "url/origin.h" +#include "url/url_constants.h" namespace site_settings { @@ -158,6 +161,7 @@ struct SiteSettingSourceStringMapping { }; const SiteSettingSourceStringMapping kSiteSettingSourceStringMapping[] = { + {SiteSettingSource::kAllowlist, "allowlist"}, {SiteSettingSource::kAdsFilterBlacklist, "ads-filter-blacklist"}, {SiteSettingSource::kDefault, "default"}, {SiteSettingSource::kDrmDisabled, "drm-disabled"}, @@ -195,38 +199,49 @@ static_assert(base::size(kPolicyIndicatorTypeStringMapping) == "kPolicyIndicatorStringMapping should have " "PolicyIndicatorType::kNumIndicators elements"); +const std::string& GetDevtoolsPatternPrefix() { + static const base::NoDestructor<std::string> kDevtoolsPatternPrefix( + base::StrCat({content_settings::kChromeDevToolsScheme, + url::kStandardSchemeSeparator})); + return *kDevtoolsPatternPrefix; +} + // Retrieves the corresponding string, according to the following precedence // order from highest to lowest priority: -// 1. Kill-switch. -// 2. Insecure origins (some permissions are denied to insecure origins). -// 3. Enterprise policy. -// 4. Extensions. -// 5. Activated for ads filtering (for Ads ContentSettingsType only). -// 6. DRM disabled (for CrOS's Protected Content ContentSettingsType only). -// 7. User-set per-origin setting. -// 8. Embargo. -// 9. User-set patterns. -// 10. User-set global default for a ContentSettingsType. -// 11. Chrome's built-in default. +// 1. Allowlisted WebUI content setting. +// 2. Kill-switch. +// 3. Insecure origins (some permissions are denied to insecure origins). +// 4. Enterprise policy. +// 5. Extensions. +// 6. Activated for ads filtering (for Ads ContentSettingsType only). +// 7. DRM disabled (for CrOS's Protected Content ContentSettingsType only). +// 8. User-set per-origin setting. +// 9. Embargo. +// 10. User-set patterns. +// 11. User-set global default for a ContentSettingsType. +// 12. Chrome's built-in default. SiteSettingSource CalculateSiteSettingSource( Profile* profile, const ContentSettingsType content_type, const GURL& origin, const content_settings::SettingInfo& info, const permissions::PermissionResult result) { + if (info.source == content_settings::SETTING_SOURCE_ALLOWLIST) + return SiteSettingSource::kAllowlist; // Source #1. + if (result.source == permissions::PermissionStatusSource::KILL_SWITCH) - return SiteSettingSource::kKillSwitch; // Source #1. + return SiteSettingSource::kKillSwitch; // Source #2. if (result.source == permissions::PermissionStatusSource::INSECURE_ORIGIN) - return SiteSettingSource::kInsecureOrigin; // Source #2. + return SiteSettingSource::kInsecureOrigin; // Source #3. if (info.source == content_settings::SETTING_SOURCE_POLICY || info.source == content_settings::SETTING_SOURCE_SUPERVISED) { - return SiteSettingSource::kPolicy; // Source #3. + return SiteSettingSource::kPolicy; // Source #4. } if (info.source == content_settings::SETTING_SOURCE_EXTENSION) - return SiteSettingSource::kExtension; // Source #4. + return SiteSettingSource::kExtension; // Source #5. if (content_type == ContentSettingsType::ADS && base::FeatureList::IsEnabled( @@ -236,14 +251,14 @@ SiteSettingSource CalculateSiteSettingSource( if (map->GetWebsiteSetting(origin, GURL(), ContentSettingsType::ADS_DATA, /*resource_identifier=*/std::string(), /*setting_info=*/nullptr) != nullptr) { - return SiteSettingSource::kAdsFilterBlacklist; // Source #5. + return SiteSettingSource::kAdsFilterBlacklist; // Source #6. } } // Protected Content will be blocked if the |kEnableDRM| pref is off. if (content_type == ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER && !profile->GetPrefs()->GetBoolean(prefs::kEnableDRM)) { - return SiteSettingSource::kDrmDisabled; // Source #6. + return SiteSettingSource::kDrmDisabled; // Source #7. } DCHECK_NE(content_settings::SETTING_SOURCE_NONE, info.source); @@ -252,18 +267,18 @@ SiteSettingSource CalculateSiteSettingSource( permissions::PermissionStatusSource::MULTIPLE_DISMISSALS || result.source == permissions::PermissionStatusSource::MULTIPLE_IGNORES) { - return SiteSettingSource::kEmbargo; // Source #8. + return SiteSettingSource::kEmbargo; // Source #9. } if (info.primary_pattern == ContentSettingsPattern::Wildcard() && info.secondary_pattern == ContentSettingsPattern::Wildcard()) { - return SiteSettingSource::kDefault; // Source #10, #11. + return SiteSettingSource::kDefault; // Source #11, #12. } - // Source #7, #9. When #7 is the source, |result.source| won't - // be set to any of the source #7 enum values, as PermissionManager is - // aware of the difference between these two sources internally. The - // subtlety here should go away when PermissionManager can handle all - // content settings and all possible sources. + // Source #8, #10. When #8 is the source, |result.source| won't be set to + // any of the source #8 enum values, as PermissionManager is aware of the + // difference between these two sources internally. The subtlety here should + // go away when PermissionManager can handle all content settings and all + // possible sources. return SiteSettingSource::kPreference; } @@ -286,6 +301,16 @@ bool PatternAppliesToSingleOrigin(const ContentSettingPatternSource& pattern) { return true; } +bool PatternAppliesToWebUISchemes(const ContentSettingPatternSource& pattern) { + return pattern.primary_pattern.GetScheme() == + ContentSettingsPattern::SchemeType::SCHEME_CHROME || + pattern.primary_pattern.GetScheme() == + ContentSettingsPattern::SchemeType::SCHEME_CHROMEUNTRUSTED || + base::StartsWith(pattern.primary_pattern.ToString(), + GetDevtoolsPatternPrefix(), + base::CompareCase::INSENSITIVE_ASCII); +} + // Retrieves the source of a chooser exception as a string. This method uses the // CalculateSiteSettingSource method above to calculate the correct string to // use. @@ -344,31 +369,12 @@ const ChooserTypeNameEntry kChooserTypeGroupNames[] = { {&GetHidChooserContext, kHidChooserDataGroupType}, {&GetBluetoothChooserContext, kBluetoothChooserDataGroupType}}; -PolicyIndicatorType GetPolicyIndicatorFromSettingSource( - content_settings::SettingSource setting_source) { - switch (setting_source) { - case content_settings::SETTING_SOURCE_POLICY: - return PolicyIndicatorType::kDevicePolicy; - case content_settings::SETTING_SOURCE_SUPERVISED: - return PolicyIndicatorType::kParent; - case content_settings::SETTING_SOURCE_EXTENSION: - return PolicyIndicatorType::kExtension; - case content_settings::SETTING_SOURCE_USER: - case content_settings::SETTING_SOURCE_ALLOWLIST: - case content_settings::SETTING_SOURCE_NONE: - return PolicyIndicatorType::kNone; - case content_settings::SETTING_SOURCE_INSTALLED_WEBAPP: - NOTREACHED(); - return PolicyIndicatorType::kNone; - } -} - } // namespace bool HasRegisteredGroupName(ContentSettingsType type) { for (size_t i = 0; i < base::size(kContentSettingsTypeGroupNames); ++i) { if (type == kContentSettingsTypeGroupNames[i].type && - kContentSettingsTypeGroupNames[i].name != nullptr) { + kContentSettingsTypeGroupNames[i].name) { return true; } } @@ -389,7 +395,7 @@ std::string ContentSettingsTypeToGroupName(ContentSettingsType type) { for (size_t i = 0; i < base::size(kContentSettingsTypeGroupNames); ++i) { if (type == kContentSettingsTypeGroupNames[i].type) { const char* name = kContentSettingsTypeGroupNames[i].name; - if (name != nullptr) + if (name) return name; break; } @@ -455,7 +461,9 @@ std::unique_ptr<base::DictionaryValue> GetExceptionForPage( const std::string& display_name, const ContentSetting& setting, const std::string& provider_name, - bool incognito) { + bool incognito, + bool is_embargoed, + bool is_discarded) { auto exception = std::make_unique<base::DictionaryValue>(); exception->SetString(kOrigin, pattern.ToString()); exception->SetString(kDisplayName, display_name); @@ -471,6 +479,8 @@ std::unique_ptr<base::DictionaryValue> GetExceptionForPage( exception->SetString(kSetting, setting_string); exception->SetString(kSource, provider_name); exception->SetBoolean(kIncognito, incognito); + exception->SetBoolean(kIsEmbargoed, is_embargoed); + exception->SetBoolean(kIsDiscarded, is_discarded); return exception; } @@ -539,6 +549,11 @@ void GetExceptionsForContentType( map->GetSettingsForOneType(type, std::string(), &all_settings); + // Will return only regular settings for a regular profile and only incognito + // settings for an incognito Profile. + ContentSettingsForOneType discarded_settings; + map->GetDiscardedSettingsForOneType(type, std::string(), &discarded_settings); + // Group settings by primary_pattern. AllPatternsSettings all_patterns_settings; for (const auto& setting : all_settings) { @@ -556,6 +571,11 @@ void GetExceptionsForContentType( if (map->IsOffTheRecord() && !setting.incognito) continue; + // Don't add WebUI settings. + if (PatternAppliesToWebUISchemes(setting)) { + continue; + } + all_patterns_settings[std::make_pair( setting.primary_pattern, setting.source)][setting.secondary_pattern] = setting.GetContentSetting(); @@ -569,6 +589,8 @@ void GetExceptionsForContentType( permissions::PermissionsClient::Get()->GetPermissionDecisionAutoBlocker( profile); + std::set<ContentSettingsPattern> origins_under_embargo; + for (const auto& setting : embargo_settings) { // Off-the-record HostContentSettingsMap contains incognito content // settings as well as normal content settings. Here, we use the @@ -582,6 +604,7 @@ void GetExceptionsForContentType( if (auto_blocker ->GetEmbargoResult(GURL(setting.primary_pattern.ToString()), type) .content_setting == CONTENT_SETTING_BLOCK) { + origins_under_embargo.insert(setting.primary_pattern); all_patterns_settings[std::make_pair( setting.primary_pattern, setting.source)][setting.secondary_pattern] = CONTENT_SETTING_BLOCK; @@ -620,9 +643,10 @@ void GetExceptionsForContentType( parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second; const ContentSettingsPattern& secondary_pattern = parent == one_settings.end() ? primary_pattern : parent->first; - this_provider_exceptions.push_back( - GetExceptionForPage(primary_pattern, secondary_pattern, display_name, - parent_setting, source, incognito)); + this_provider_exceptions.push_back(GetExceptionForPage( + primary_pattern, secondary_pattern, display_name, parent_setting, + source, incognito, + base::Contains(origins_under_embargo, primary_pattern))); // Add the "children" for any embedded settings. for (auto j = one_settings.begin(); j != one_settings.end(); ++j) { @@ -631,9 +655,9 @@ void GetExceptionsForContentType( continue; ContentSetting content_setting = j->second; - this_provider_exceptions.push_back( - GetExceptionForPage(primary_pattern, j->first, display_name, - content_setting, source, incognito)); + this_provider_exceptions.push_back(GetExceptionForPage( + primary_pattern, j->first, display_name, content_setting, source, + incognito, base::Contains(origins_under_embargo, primary_pattern))); } } @@ -653,6 +677,15 @@ void GetExceptionsForContentType( for (auto& exception : one_provider_exceptions) exceptions->Append(std::move(exception)); } + + for (auto& discarded_rule : discarded_settings) { + exceptions->Append(GetExceptionForPage( + discarded_rule.primary_pattern, discarded_rule.secondary_pattern, + GetDisplayNameForPattern(discarded_rule.primary_pattern, + extension_registry), + discarded_rule.GetContentSetting(), discarded_rule.source, incognito, + false /*is_embargoed*/, true /*is_discarded*/)); + } } void GetContentCategorySetting(const HostContentSettingsMap* map, @@ -713,7 +746,8 @@ std::vector<ContentSettingPatternSource> GetSiteExceptionsForContentType( map->GetSettingsForOneType(content_type, std::string(), &entries); entries.erase(std::remove_if(entries.begin(), entries.end(), [](const ContentSettingPatternSource& e) { - return !PatternAppliesToSingleOrigin(e); + return !PatternAppliesToSingleOrigin(e) || + PatternAppliesToWebUISchemes(e); }), entries.end()); return entries; @@ -864,6 +898,10 @@ base::Value GetChooserExceptionListFromProfile( std::map<std::pair<base::string16, base::Value>, ChooserExceptionDetails> all_chooser_objects; for (const auto& object : objects) { + // Don't include WebUI settings. + if (content::HasWebUIScheme(object->requesting_origin)) + continue; + base::string16 name = chooser_context->GetObjectDisplayName(object->value); auto& chooser_exception_details = all_chooser_objects[std::make_pair(name, object->value.Clone())]; @@ -893,121 +931,6 @@ base::Value GetChooserExceptionListFromProfile( return exceptions; } -CookieControlsManagedState GetCookieControlsManagedState(Profile* profile) { - // Setup a default unmanaged state that is updated based on the actual - // managed state. - CookieControlsManagedState managed_state; - - HostContentSettingsMap* map = - HostContentSettingsMapFactory::GetForProfile(profile); - std::string content_setting_provider; - auto content_setting = map->GetDefaultContentSetting( - ContentSettingsType::COOKIES, &content_setting_provider); - auto content_setting_source = - HostContentSettingsMap::GetSettingSourceFromProviderName( - content_setting_provider); - bool content_setting_enforced = - content_setting_source != - content_settings::SettingSource::SETTING_SOURCE_USER; - - // Both the content setting and the block_third_party preference can - // be controlled via policy. - const PrefService::Preference* block_third_party_pref = - profile->GetPrefs()->FindPreference(prefs::kBlockThirdPartyCookies); - bool block_third_party_on = block_third_party_pref->GetValue()->GetBool(); - bool block_third_party_enforced = !block_third_party_pref->IsUserModifiable(); - // IsRecommended() cannot be used as we care if a recommended value exists at - // all, even if a user has overwritten it. - bool block_third_party_recommended = - (block_third_party_pref && block_third_party_pref->GetRecommendedValue()); - bool block_third_party_recommended_on = - block_third_party_recommended && - block_third_party_pref->GetRecommendedValue()->GetBool(); - - // kCookieControlsMode == kOn should imply block_third_party is on. - auto control_mode = static_cast<content_settings::CookieControlsMode>( - profile->GetPrefs()->GetInteger(prefs::kCookieControlsMode)); - DCHECK(control_mode != - content_settings::CookieControlsMode::kBlockThirdParty || - block_third_party_on); - - // Get indicators representing each settings source. These may or may not - // be used depending on the determined managed state. - auto content_setting_source_indicator = - GetPolicyIndicatorFromSettingSource(content_setting_source); - auto block_third_party_source_indicator = - GetPolicyIndicatorFromPref(block_third_party_pref); - - if (!content_setting_enforced && !block_third_party_enforced && - !block_third_party_recommended) { - // No cookie controls are managed or recommended. - return managed_state; - } - - if (content_setting_enforced) { - // Block and session only managed state only depend on the content setting. - managed_state.block_all = {/*disabled*/ true, - content_setting_source_indicator}; - managed_state.session_only = {/*disabled*/ true, - content_setting_source_indicator}; - } - - if (content_setting_enforced && content_setting == CONTENT_SETTING_BLOCK) { - // All remaining controls are managed by the content setting source. - managed_state.allow_all = {/*disabled*/ true, - content_setting_source_indicator}; - managed_state.block_third_party_incognito = { - /*disabled*/ true, content_setting_source_indicator}; - managed_state.block_third_party = {/*disabled*/ true, - content_setting_source_indicator}; - return managed_state; - } - if (content_setting_enforced && block_third_party_enforced) { - // All remaining controls are managed by the block_third_party source. - managed_state.allow_all = {/*disabled*/ true, - block_third_party_source_indicator}; - managed_state.block_third_party_incognito = { - /*disabled*/ true, block_third_party_source_indicator}; - managed_state.block_third_party = {/*disabled*/ true, - block_third_party_source_indicator}; - return managed_state; - } - DCHECK(!content_setting_enforced || - content_setting == CONTENT_SETTING_ALLOW || - content_setting == CONTENT_SETTING_SESSION_ONLY); - DCHECK(!content_setting_enforced || !block_third_party_enforced); - // At this stage the content setting is not enforcing a BLOCK state. Given - // this, allow and block_third_party are still valid choices that do not - // contradict the content setting. They can thus be controlled or recommended - // by the block_third_party preference. - if (block_third_party_enforced) { - DCHECK(!content_setting_enforced); - managed_state.block_third_party_incognito = { - true, block_third_party_source_indicator}; - if (block_third_party_on) { - managed_state.allow_all = {/*disabled*/ true, - block_third_party_source_indicator}; - } else { - managed_state.block_third_party = {/*disabled*/ true, - block_third_party_source_indicator}; - } - return managed_state; - } - if (block_third_party_recommended) { - if (block_third_party_recommended_on) { - managed_state.block_third_party = {/*disabled*/ false, - block_third_party_source_indicator}; - } else { - managed_state.allow_all = {/*disabled*/ false, - block_third_party_source_indicator}; - } - return managed_state; - } - DCHECK(content_setting_enforced && !block_third_party_enforced && - !block_third_party_recommended); - return managed_state; -} - std::string PolicyIndicatorTypeToString(const PolicyIndicatorType type) { return kPolicyIndicatorTypeStringMapping[static_cast<int>(type)] .indicator_str; 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 b018f7c63a3..8ac89c83c11 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_helper.h +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_helper.h @@ -53,11 +53,6 @@ typedef std::map<std::pair<ContentSettingsPattern, std::string>, using ChooserExceptionDetails = std::map<std::pair<GURL, std::string>, std::set<std::pair<GURL, bool>>>; -constexpr char kAllowAll[] = "allowAll"; -constexpr char kBlockThirdPartyIncognito[] = "blockThirdPartyIncognito"; -constexpr char kBlockThirdParty[] = "blockThirdParty"; -constexpr char kBlockAll[] = "blockAll"; -constexpr char kSessionOnly[] = "sessionOnly"; constexpr char kChooserType[] = "chooserType"; constexpr char kDisplayName[] = "displayName"; constexpr char kEmbeddingOrigin[] = "embeddingOrigin"; @@ -72,8 +67,11 @@ constexpr char kSites[] = "sites"; constexpr char kPolicyIndicator[] = "indicator"; constexpr char kSource[] = "source"; constexpr char kType[] = "type"; +constexpr char kIsEmbargoed[] = "isEmbargoed"; +constexpr char kIsDiscarded[] = "isDiscarded"; enum class SiteSettingSource { + kAllowlist, kAdsFilterBlacklist, kDefault, kDrmDisabled, @@ -108,15 +106,6 @@ struct ManagedState { PolicyIndicatorType indicator = PolicyIndicatorType::kNone; }; -// Represents the manage states for all of the cookie controls. -struct CookieControlsManagedState { - ManagedState allow_all; - ManagedState block_third_party_incognito; - ManagedState block_third_party; - ManagedState block_all; - ManagedState session_only; -}; - // Returns whether a group name has been registered for the given type. bool HasRegisteredGroupName(ContentSettingsType type); @@ -141,7 +130,9 @@ std::unique_ptr<base::DictionaryValue> GetExceptionForPage( const std::string& display_name, const ContentSetting& setting, const std::string& provider_name, - bool incognito); + bool incognito, + bool is_embargoed = false, + bool is_discarded = false); // Helper function to construct a dictionary for a hosted app exception. void AddExceptionForHostedApp(const std::string& url_pattern, @@ -225,9 +216,6 @@ base::Value GetChooserExceptionListFromProfile( Profile* profile, const ChooserTypeNameEntry& chooser_type); -// Returns the cookie controls manage state for a given profile. -CookieControlsManagedState GetCookieControlsManagedState(Profile* profile); - // Concerts a PolicyIndicatorType to its string identifier. std::string PolicyIndicatorTypeToString(const PolicyIndicatorType type); 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 2a08d0797ee..6b11de46fbe 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 @@ -23,7 +23,6 @@ #include "components/permissions/chooser_context_base.h" #include "components/permissions/permission_decision_auto_blocker.h" #include "components/prefs/pref_service.h" -#include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" #include "extensions/browser/extension_registry.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -75,6 +74,47 @@ class SiteSettingsHelperTest : public testing::Test { content::BrowserTaskEnvironment task_environment_; }; +TEST_F(SiteSettingsHelperTest, ExceptionListWithEmbargoedAndBlockedOrigins) { + TestingProfile profile; + + constexpr char kOriginToEmbargo[] = "https://embargoed.co.uk:443"; + auto* auto_blocker = + PermissionDecisionAutoBlockerFactory::GetForProfile(&profile); + for (size_t i = 0; i < 3; ++i) { + auto_blocker->RecordDismissAndEmbargo(GURL(kOriginToEmbargo), + kContentTypeNotifications, false); + } + + constexpr char kOriginToBlock[] = "https://www.blocked.com:443"; + auto* map = HostContentSettingsMapFactory::GetForProfile(&profile); + map->SetContentSettingDefaultScope(GURL(kOriginToBlock), GURL(kOriginToBlock), + kContentTypeNotifications, std::string(), + CONTENT_SETTING_BLOCK); + + base::ListValue exceptions; + site_settings::GetExceptionsForContentType(kContentTypeNotifications, + &profile, + /*extension_registry=*/nullptr, + /*web_ui=*/nullptr, + /*incognito=*/false, &exceptions); + + // |exceptions| size should be 2. One blocked and one embargoed origins. + ASSERT_EQ(2U, exceptions.GetSize()); + base::Value* value = nullptr; + // Get last added origin. + exceptions.Get(0, &value); + base::Value* is_embargoed = value->FindKey(site_settings::kIsEmbargoed); + ASSERT_NE(nullptr, is_embargoed); + // Last added origin is blocked, |embargo| key should be false. + EXPECT_FALSE(is_embargoed->GetBool()); + + // Get embargoed origin. + exceptions.Get(1, &value); + is_embargoed = value->FindKey(site_settings::kIsEmbargoed); + ASSERT_NE(nullptr, is_embargoed); + EXPECT_TRUE(is_embargoed->GetBool()); +} + TEST_F(SiteSettingsHelperTest, ExceptionListShowsIncognitoEmbargoed) { TestingProfile profile; constexpr char kOriginToBlock[] = "https://www.blocked.com:443"; @@ -816,302 +856,4 @@ TEST_F(SiteSettingsHelperChooserExceptionTest, } } -namespace { - -// All of the possible managed states for a boolean preference that can be -// both enforced and recommended. -enum class PrefSetting { - kEnforcedOff, - kEnforcedOn, - kRecommendedOff, - kRecommendedOn, - kNotSet, -}; - -// Possible preference sources supported by TestingPrefService. -// TODO(crbug.com/1063281): Extend TestingPrefService to support prefs set for -// supervised users. -enum class PrefSource { - kExtension, - kDevicePolicy, - kRecommended, - kNone, -}; - -// Represents a set of settings, preferences and the associated expected -// CookieControlsManagedState. -struct CookiesManagedStateTestCase { - ContentSetting default_content_setting; - content_settings::SettingSource default_content_setting_source; - PrefSetting block_third_party; - PrefSource block_third_party_source; - CookieControlsManagedState expected_result; -}; - -const std::vector<CookiesManagedStateTestCase> test_cases = { - {CONTENT_SETTING_DEFAULT, - content_settings::SETTING_SOURCE_NONE, - PrefSetting::kEnforcedOff, - PrefSource::kExtension, - {{false, PolicyIndicatorType::kNone}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}}}, - {CONTENT_SETTING_DEFAULT, - content_settings::SETTING_SOURCE_NONE, - PrefSetting::kEnforcedOn, - PrefSource::kDevicePolicy, - {{true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}}}, - {CONTENT_SETTING_DEFAULT, - content_settings::SETTING_SOURCE_NONE, - PrefSetting::kRecommendedOff, - PrefSource::kRecommended, - {{false, PolicyIndicatorType::kRecommended}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}}}, - {CONTENT_SETTING_DEFAULT, - content_settings::SETTING_SOURCE_NONE, - PrefSetting::kRecommendedOn, - PrefSource::kRecommended, - {{false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kRecommended}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}}}, - {CONTENT_SETTING_DEFAULT, - content_settings::SETTING_SOURCE_NONE, - PrefSetting::kNotSet, - PrefSource::kNone, - {{false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}}}, - {CONTENT_SETTING_ALLOW, - content_settings::SETTING_SOURCE_POLICY, - PrefSetting::kEnforcedOff, - PrefSource::kExtension, - {{true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}}}, - {CONTENT_SETTING_ALLOW, - content_settings::SETTING_SOURCE_EXTENSION, - PrefSetting::kEnforcedOn, - PrefSource::kDevicePolicy, - {{true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}}}, - {CONTENT_SETTING_ALLOW, - content_settings::SETTING_SOURCE_SUPERVISED, - PrefSetting::kRecommendedOff, - PrefSource::kRecommended, - {{false, PolicyIndicatorType::kRecommended}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}}}, - {CONTENT_SETTING_ALLOW, - content_settings::SETTING_SOURCE_POLICY, - PrefSetting::kRecommendedOn, - PrefSource::kRecommended, - {{false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kRecommended}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}}}, - {CONTENT_SETTING_ALLOW, - content_settings::SETTING_SOURCE_EXTENSION, - PrefSetting::kNotSet, - PrefSource::kNone, - {{false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}}}, - {CONTENT_SETTING_BLOCK, - content_settings::SETTING_SOURCE_SUPERVISED, - PrefSetting::kEnforcedOff, - PrefSource::kDevicePolicy, - {{true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}}}, - {CONTENT_SETTING_BLOCK, - content_settings::SETTING_SOURCE_POLICY, - PrefSetting::kEnforcedOn, - PrefSource::kExtension, - {{true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}}}, - {CONTENT_SETTING_BLOCK, - content_settings::SETTING_SOURCE_EXTENSION, - PrefSetting::kRecommendedOff, - PrefSource::kRecommended, - {{true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}}}, - {CONTENT_SETTING_BLOCK, - content_settings::SETTING_SOURCE_SUPERVISED, - PrefSetting::kRecommendedOn, - PrefSource::kRecommended, - {{true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}}}, - {CONTENT_SETTING_BLOCK, - content_settings::SETTING_SOURCE_POLICY, - PrefSetting::kNotSet, - PrefSource::kNone, - {{true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}}}, - {CONTENT_SETTING_SESSION_ONLY, - content_settings::SETTING_SOURCE_EXTENSION, - PrefSetting::kEnforcedOff, - PrefSource::kDevicePolicy, - {{true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}}}, - {CONTENT_SETTING_SESSION_ONLY, - content_settings::SETTING_SOURCE_SUPERVISED, - PrefSetting::kEnforcedOn, - PrefSource::kExtension, - {{true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}}}, - {CONTENT_SETTING_SESSION_ONLY, - content_settings::SETTING_SOURCE_POLICY, - PrefSetting::kRecommendedOff, - PrefSource::kRecommended, - {{false, PolicyIndicatorType::kRecommended}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {true, PolicyIndicatorType::kDevicePolicy}, - {true, PolicyIndicatorType::kDevicePolicy}}}, - {CONTENT_SETTING_SESSION_ONLY, - content_settings::SETTING_SOURCE_EXTENSION, - PrefSetting::kRecommendedOn, - PrefSource::kRecommended, - {{false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kRecommended}, - {true, PolicyIndicatorType::kExtension}, - {true, PolicyIndicatorType::kExtension}}}, - {CONTENT_SETTING_SESSION_ONLY, - content_settings::SETTING_SOURCE_SUPERVISED, - PrefSetting::kNotSet, - PrefSource::kNone, - {{false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {false, PolicyIndicatorType::kNone}, - {true, PolicyIndicatorType::kParent}, - {true, PolicyIndicatorType::kParent}}}}; - -void SetupTestConditions(HostContentSettingsMap* map, - sync_preferences::TestingPrefServiceSyncable* prefs, - const CookiesManagedStateTestCase& test_case) { - if (test_case.default_content_setting != CONTENT_SETTING_DEFAULT) { - auto provider = std::make_unique<content_settings::MockProvider>(); - provider->SetWebsiteSetting( - ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), - ContentSettingsType::COOKIES, std::string(), - std::make_unique<base::Value>(test_case.default_content_setting)); - HostContentSettingsMap::ProviderType provider_type; - switch (test_case.default_content_setting_source) { - case content_settings::SETTING_SOURCE_POLICY: - provider_type = HostContentSettingsMap::POLICY_PROVIDER; - break; - case content_settings::SETTING_SOURCE_EXTENSION: - provider_type = HostContentSettingsMap::CUSTOM_EXTENSION_PROVIDER; - break; - case content_settings::SETTING_SOURCE_SUPERVISED: - provider_type = HostContentSettingsMap::SUPERVISED_PROVIDER; - break; - case content_settings::SETTING_SOURCE_NONE: - default: - provider_type = HostContentSettingsMap::DEFAULT_PROVIDER; - } - content_settings::TestUtils::OverrideProvider(map, std::move(provider), - provider_type); - } - - if (test_case.block_third_party != PrefSetting::kNotSet) { - bool third_party_value = - test_case.block_third_party == PrefSetting::kRecommendedOn || - test_case.block_third_party == PrefSetting::kEnforcedOn; - if (test_case.block_third_party_source == PrefSource::kExtension) { - prefs->SetExtensionPref(prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(third_party_value)); - } else if (test_case.block_third_party_source == - PrefSource::kDevicePolicy) { - prefs->SetManagedPref(prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(third_party_value)); - } else if (test_case.block_third_party_source == PrefSource::kRecommended) { - prefs->SetRecommendedPref( - prefs::kBlockThirdPartyCookies, - std::make_unique<base::Value>(third_party_value)); - } - } -} - -void AssertManagedCookieStateEqual(const CookieControlsManagedState& a, - const CookieControlsManagedState b) { - ASSERT_EQ(a.allow_all.disabled, b.allow_all.disabled); - ASSERT_EQ(a.allow_all.indicator, b.allow_all.indicator); - ASSERT_EQ(a.block_third_party_incognito.disabled, - b.block_third_party_incognito.disabled); - ASSERT_EQ(a.block_third_party_incognito.indicator, - b.block_third_party_incognito.indicator); - ASSERT_EQ(a.block_third_party.disabled, b.block_third_party.disabled); - ASSERT_EQ(a.block_third_party.indicator, b.block_third_party.indicator); - ASSERT_EQ(a.block_all.disabled, b.block_all.disabled); - ASSERT_EQ(a.block_all.indicator, b.block_all.indicator); - ASSERT_EQ(a.session_only.disabled, b.session_only.disabled); - ASSERT_EQ(a.session_only.indicator, b.session_only.indicator); -} - -TEST_F(SiteSettingsHelperTest, CookiesManagedState) { - for (auto test_case : test_cases) { - TestingProfile profile; - HostContentSettingsMap* map = - HostContentSettingsMapFactory::GetForProfile(&profile); - sync_preferences::TestingPrefServiceSyncable* prefs = - profile.GetTestingPrefService(); - testing::Message scope_message; - scope_message << "Content Setting:" << test_case.default_content_setting - << " Block Third Party:" - << static_cast<int>(test_case.block_third_party); - SCOPED_TRACE(scope_message); - SetupTestConditions(map, prefs, test_case); - AssertManagedCookieStateEqual( - site_settings::GetCookieControlsManagedState(&profile), - test_case.expected_result); - } -} - -} // namespace - } // namespace site_settings diff --git a/chromium/chrome/browser/ui/webui/settings/tts_handler.cc b/chromium/chrome/browser/ui/webui/settings/tts_handler.cc index f17e4b3a742..abf485deba1 100644 --- a/chromium/chrome/browser/ui/webui/settings/tts_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/tts_handler.cc @@ -28,7 +28,7 @@ namespace settings { TtsHandler::TtsHandler() {} TtsHandler::~TtsHandler() { - content::TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); + RemoveTtsControllerDelegates(); } void TtsHandler::HandleGetAllTtsVoiceData(const base::ListValue* args) { @@ -176,8 +176,7 @@ void TtsHandler::OnJavascriptAllowed() { } void TtsHandler::OnJavascriptDisallowed() { - content::TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); - content::TtsController::GetInstance()->RemoveUtteranceEventDelegate(this); + RemoveTtsControllerDelegates(); } int TtsHandler::GetVoiceLangMatchScore(const content::VoiceData* voice, @@ -205,4 +204,9 @@ void TtsHandler::OnTtsEngineAwake(bool success) { OnVoicesChanged(); } +void TtsHandler::RemoveTtsControllerDelegates() { + content::TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); + content::TtsController::GetInstance()->RemoveUtteranceEventDelegate(this); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/tts_handler.h b/chromium/chrome/browser/ui/webui/settings/tts_handler.h index a839dee3c0b..fa1820a32ba 100644 --- a/chromium/chrome/browser/ui/webui/settings/tts_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/tts_handler.h @@ -45,6 +45,7 @@ class TtsHandler : public SettingsPageUIHandler, void OnTtsEngineAwake(bool success); int GetVoiceLangMatchScore(const content::VoiceData* voice, const std::string& app_locale); + void RemoveTtsControllerDelegates(); base::WeakPtrFactory<TtsHandler> weak_factory_{this}; diff --git a/chromium/chrome/browser/ui/webui/settings_utils_linux.cc b/chromium/chrome/browser/ui/webui/settings_utils_linux.cc index d56f9f30684..9043aaf40eb 100644 --- a/chromium/chrome/browser/ui/webui/settings_utils_linux.cc +++ b/chromium/chrome/browser/ui/webui/settings_utils_linux.cc @@ -11,7 +11,6 @@ #include "base/files/file_util.h" #include "base/nix/xdg_util.h" #include "base/process/launch.h" -#include "base/task/post_task.h" #include "base/task/thread_pool.h" #include "base/threading/scoped_blocking_call.h" #include "build/build_config.h" @@ -134,8 +133,8 @@ void DetectAndStartProxyConfigUtil(int render_process_id, if (launched) return; - base::PostTask(FROM_HERE, {BrowserThread::UI}, - base::BindOnce(&ShowLinuxProxyConfigUrl, render_process_id, + content::GetUIThreadTaskRunner({})->PostTask( + FROM_HERE, base::BindOnce(&ShowLinuxProxyConfigUrl, render_process_id, render_view_id)); } diff --git a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc index 948ce452f56..c418b7e5c9c 100644 --- a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc +++ b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.cc @@ -18,15 +18,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/supports_user_data.h" #include "base/threading/sequenced_task_runner_handle.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/policy/chrome_policy_conversions_client.h" #include "chrome/browser/policy/cloud/user_policy_signin_service.h" #include "chrome/browser/policy/cloud/user_policy_signin_service_factory.h" #include "chrome/browser/policy/profile_policy_connector.h" -#include "chrome/browser/profiles/profile_attributes_storage.h" -#include "chrome/browser/profiles/profile_avatar_icon_util.h" -#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/account_id_from_account_info.h" +#include "chrome/browser/signin/dice_signed_in_profile_creator.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/signin_util.h" #include "chrome/browser/sync/profile_sync_service_factory.h" @@ -89,54 +86,6 @@ AccountInfo GetAccountInfo(signin::IdentityManager* identity_manager, : AccountInfo(); } -class TokensLoadedCallbackRunner : public signin::IdentityManager::Observer { - public: - // Calls |callback| when tokens are loaded. - static void RunWhenLoaded(Profile* profile, - base::OnceCallback<void(Profile*)> callback) { - auto* identity_manager = IdentityManagerFactory::GetForProfile(profile); - if (identity_manager->AreRefreshTokensLoaded()) { - std::move(callback).Run(profile); - return; - } - // TokensLoadedCallbackRunner deletes itself after running the callback. - new TokensLoadedCallbackRunner( - identity_manager, - DiceTurnSyncOnHelperShutdownNotifierFactory::GetInstance()->Get( - profile), - base::BindOnce(std::move(callback), profile)); - } - - private: - TokensLoadedCallbackRunner(signin::IdentityManager* identity_manager, - KeyedServiceShutdownNotifier* shutdown_notifier, - base::OnceClosure callback) - : identity_manager_(identity_manager), - callback_(std::move(callback)), - shutdown_subscription_(shutdown_notifier->Subscribe( - base::Bind(&TokensLoadedCallbackRunner::OnShutdown, - base::Unretained(this)))) { - DCHECK(!identity_manager_->AreRefreshTokensLoaded()); - scoped_identity_manager_observer_.Add(identity_manager_); - } - - // signin::IdentityManager::Observer implementation: - void OnRefreshTokensLoaded() override { - std::move(callback_).Run(); - delete this; - } - - void OnShutdown() { delete this; } - - signin::IdentityManager* identity_manager_; - ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer> - scoped_identity_manager_observer_{this}; - base::OnceClosure callback_; - std::unique_ptr<KeyedServiceShutdownNotifier::Subscription> - shutdown_subscription_; - - DISALLOW_COPY_AND_ASSIGN(TokensLoadedCallbackRunner); -}; struct CurrentDiceTurnSyncOnHelperUserData : public base::SupportsUserData::Data { @@ -417,47 +366,13 @@ void DiceTurnSyncOnHelper::OnProviderUpdatePropagated( } void DiceTurnSyncOnHelper::CreateNewSignedInProfile() { - // Create a new profile and have it call back when done so we can start the - // signin flow. - ProfileAttributesStorage& storage = - g_browser_process->profile_manager()->GetProfileAttributesStorage(); - size_t icon_index = storage.ChooseAvatarIconIndexForNewProfile(); - - ProfileManager::CreateMultiProfileAsync( - storage.ChooseNameForNewProfile(icon_index), - profiles::GetDefaultAvatarIconUrl(icon_index), - base::BindRepeating(&DiceTurnSyncOnHelper::OnNewProfileCreated, - weak_pointer_factory_.GetWeakPtr())); -} - -void DiceTurnSyncOnHelper::OnNewProfileCreated(Profile* new_profile, - Profile::CreateStatus status) { - DCHECK_NE(profile_, new_profile); - - // TODO(atwilson): On error, unregister the client to release the DMToken - // and surface a better error for the user. - switch (status) { - case Profile::CREATE_STATUS_LOCAL_FAIL: - NOTREACHED() << "Error creating new profile"; - AbortAndDelete(); - break; - case Profile::CREATE_STATUS_CREATED: - // Ignore this, wait for profile to be initialized. - break; - case Profile::CREATE_STATUS_INITIALIZED: - TokensLoadedCallbackRunner::RunWhenLoaded( - new_profile, - base::BindOnce(&DiceTurnSyncOnHelper::OnNewProfileTokensLoaded, - weak_pointer_factory_.GetWeakPtr())); - break; - case Profile::CREATE_STATUS_REMOTE_FAIL: - case Profile::CREATE_STATUS_CANCELED: - case Profile::MAX_CREATE_STATUS: { - NOTREACHED() << "Invalid profile creation status"; - AbortAndDelete(); - break; - } - } + DCHECK(!dice_signed_in_profile_creator_); + // Unretained is fine because the profile creator is owned by this. + dice_signed_in_profile_creator_ = + std::make_unique<DiceSignedInProfileCreator>( + profile_, account_info_.account_id, + base::BindOnce(&DiceTurnSyncOnHelper::OnNewSignedInProfileCreated, + base::Unretained(this))); } syncer::SyncService* DiceTurnSyncOnHelper::GetSyncService() { @@ -466,14 +381,18 @@ syncer::SyncService* DiceTurnSyncOnHelper::GetSyncService() { : nullptr; } -void DiceTurnSyncOnHelper::OnNewProfileTokensLoaded(Profile* new_profile) { - // This deletes the token locally, even in KEEP_ACCOUNT mode. - auto* accounts_mutator = identity_manager_->GetAccountsMutator(); - auto* new_profile_accounts_mutator = - IdentityManagerFactory::GetForProfile(new_profile)->GetAccountsMutator(); - accounts_mutator->MoveAccount(new_profile_accounts_mutator, - account_info_.account_id); +void DiceTurnSyncOnHelper::OnNewSignedInProfileCreated(Profile* new_profile) { + DCHECK(dice_signed_in_profile_creator_); + dice_signed_in_profile_creator_.reset(); + if (!new_profile) { + // TODO(atwilson): On error, unregister the client to release the DMToken + // and surface a better error for the user. + AbortAndDelete(); + return; + } + + DCHECK_NE(profile_, new_profile); SwitchToProfile(new_profile); DCHECK_EQ(profile_, new_profile); diff --git a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h index 58c0074683d..84c45a4cf8d 100644 --- a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h +++ b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper.h @@ -21,6 +21,7 @@ #include "components/signin/public/identity_manager/account_info.h" class Browser; +class DiceSignedInProfileCreator; namespace signin { class IdentityManager; @@ -171,12 +172,8 @@ class DiceTurnSyncOnHelper // in-progress auth credentials currently stored in this object. void CreateNewSignedInProfile(); - // Callback invoked once a profile is created, so we can transfer the - // credentials. - void OnNewProfileCreated(Profile* new_profile, Profile::CreateStatus status); - - // Callback invoked once the token service is ready for the new profile. - void OnNewProfileTokensLoaded(Profile* new_profile); + // Called when the new profile is created. + void OnNewSignedInProfileCreated(Profile* new_profile); // Returns the SyncService, or nullptr if sync is not allowed. syncer::SyncService* GetSyncService(); @@ -230,6 +227,7 @@ class DiceTurnSyncOnHelper base::ScopedClosureRunner scoped_callback_runner_; std::unique_ptr<SyncStartupTracker> sync_startup_tracker_; + std::unique_ptr<DiceSignedInProfileCreator> dice_signed_in_profile_creator_; std::unique_ptr<KeyedServiceShutdownNotifier::Subscription> shutdown_subscription_; diff --git a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc index 0a6f462ee69..213a2f515cf 100644 --- a/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc +++ b/chromium/chrome/browser/ui/webui/signin/dice_turn_sync_on_helper_unittest.cc @@ -709,9 +709,7 @@ TEST_F(DiceTurnSyncOnHelperTest, ShowSyncDialogForEndConsumerAccount) { std::unique_ptr<unified_consent::UrlKeyedDataCollectionConsentHelper> url_keyed_collection_helper = unified_consent::UrlKeyedDataCollectionConsentHelper:: - NewAnonymizedDataCollectionConsentHelper( - pref_service, - ProfileSyncServiceFactory::GetForProfile(profile())); + NewAnonymizedDataCollectionConsentHelper(pref_service); EXPECT_FALSE(url_keyed_collection_helper->IsEnabled()); // Signin flow. diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.cc index 58d3c73da50..b6f8cc8f089 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h" +#include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" #include <algorithm> #include <string> @@ -36,7 +36,7 @@ namespace chromeos { namespace { -InlineLoginHandlerDialogChromeOS* dialog = nullptr; +InlineLoginDialogChromeOS* dialog = nullptr; constexpr int kSigninDialogWidth = 768; constexpr int kSigninDialogHeight = 640; @@ -66,7 +66,7 @@ GURL GetUrlWithEmailParam(base::StringPiece url_string, } GURL GetInlineLoginUrl(const std::string& email, - const InlineLoginHandlerDialogChromeOS::Source& source) { + const InlineLoginDialogChromeOS::Source& source) { if (IsDeviceAccountEmail(email)) { // It's a device account re-auth. return GetUrlWithEmailParam(chrome::kChromeUIChromeSigninURL, email); @@ -83,21 +83,17 @@ GURL GetInlineLoginUrl(const std::string& email, } // User type is Child. if (!features::IsEduCoexistenceEnabled() || - source == InlineLoginHandlerDialogChromeOS::Source::kArc) { + source == InlineLoginDialogChromeOS::Source::kArc) { return GURL(chrome::kChromeUIAccountManagerErrorURL); } - DCHECK_EQ(std::string(chrome::kChromeUIChromeSigninURL).back(), '/'); - // chrome://chrome-signin/edu - const std::string kEduAccountLoginURL = - std::string(chrome::kChromeUIChromeSigninURL) + "edu"; - return GetUrlWithEmailParam(kEduAccountLoginURL, email); + return GetUrlWithEmailParam(chrome::kChromeUIEDUCoexistenceLoginURL, email); } } // namespace // static -void InlineLoginHandlerDialogChromeOS::Show(const std::string& email, - const Source& source) { +void InlineLoginDialogChromeOS::Show(const std::string& email, + const Source& source) { base::UmaHistogramEnumeration(kAccountAdditionSource, source); // If the dialog was triggered as a response to background request, it could // get displayed on the lock screen. In this case it is safe to ignore it, @@ -112,8 +108,8 @@ void InlineLoginHandlerDialogChromeOS::Show(const std::string& email, } // Will be deleted by |SystemWebDialogDelegate::OnDialogClosed|. - dialog = new InlineLoginHandlerDialogChromeOS( - GetInlineLoginUrl(email, source), source); + dialog = + new InlineLoginDialogChromeOS(GetInlineLoginUrl(email, source), source); dialog->ShowSystemDialog(); // TODO(crbug.com/1016828): Remove/update this after the dialog behavior on @@ -122,73 +118,71 @@ void InlineLoginHandlerDialogChromeOS::Show(const std::string& email, ->SetBackdropType(ash::WindowBackdrop::BackdropType::kSemiOpaque); } -void InlineLoginHandlerDialogChromeOS::Show(const Source& source) { +void InlineLoginDialogChromeOS::Show(const Source& source) { Show(/* email= */ std::string(), source); } // static -void InlineLoginHandlerDialogChromeOS::UpdateEduCoexistenceFlowResult( +void InlineLoginDialogChromeOS::UpdateEduCoexistenceFlowResult( EduCoexistenceFlowResult result) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (dialog) dialog->SetEduCoexistenceFlowResult(result); } -void InlineLoginHandlerDialogChromeOS::AdjustWidgetInitParams( +void InlineLoginDialogChromeOS::AdjustWidgetInitParams( views::Widget::InitParams* params) { params->z_order = ui::ZOrderLevel::kNormal; } -gfx::Size InlineLoginHandlerDialogChromeOS::GetMaximumDialogSize() { +gfx::Size InlineLoginDialogChromeOS::GetMaximumDialogSize() { gfx::Size size; GetDialogSize(&size); return size; } -gfx::NativeView InlineLoginHandlerDialogChromeOS::GetHostView() const { +gfx::NativeView InlineLoginDialogChromeOS::GetHostView() const { return dialog_window(); } -gfx::Point InlineLoginHandlerDialogChromeOS::GetDialogPosition( - const gfx::Size& size) { +gfx::Point InlineLoginDialogChromeOS::GetDialogPosition(const gfx::Size& size) { gfx::Size host_size = GetHostView()->bounds().size(); // Show all sub-dialogs at center-top. return gfx::Point(std::max(0, (host_size.width() - size.width()) / 2), 0); } -void InlineLoginHandlerDialogChromeOS::AddObserver( +void InlineLoginDialogChromeOS::AddObserver( web_modal::ModalDialogHostObserver* observer) {} -void InlineLoginHandlerDialogChromeOS::RemoveObserver( +void InlineLoginDialogChromeOS::RemoveObserver( web_modal::ModalDialogHostObserver* observer) {} -void InlineLoginHandlerDialogChromeOS::SetEduCoexistenceFlowResult( +void InlineLoginDialogChromeOS::SetEduCoexistenceFlowResult( EduCoexistenceFlowResult result) { edu_coexistence_flow_result_ = result; } -InlineLoginHandlerDialogChromeOS::InlineLoginHandlerDialogChromeOS( - const GURL& url, - const Source& source) +InlineLoginDialogChromeOS::InlineLoginDialogChromeOS(const GURL& url, + const Source& source) : SystemWebDialogDelegate(url, base::string16() /* title */), delegate_(this), source_(source), url_(url) {} -InlineLoginHandlerDialogChromeOS::~InlineLoginHandlerDialogChromeOS() { +InlineLoginDialogChromeOS::~InlineLoginDialogChromeOS() { DCHECK_EQ(this, dialog); dialog = nullptr; } -void InlineLoginHandlerDialogChromeOS::GetDialogSize(gfx::Size* size) const { +void InlineLoginDialogChromeOS::GetDialogSize(gfx::Size* size) const { const display::Display display = display::Screen::GetScreen()->GetDisplayNearestWindow(dialog_window()); size->SetSize(std::min(kSigninDialogWidth, display.work_area().width()), std::min(kSigninDialogHeight, display.work_area().height())); } -std::string InlineLoginHandlerDialogChromeOS::GetDialogArgs() const { +std::string InlineLoginDialogChromeOS::GetDialogArgs() const { if (url_.GetWithEmptyPath() != GURL(chrome::kChromeUIAccountManagerErrorURL)) { return std::string(); @@ -211,11 +205,11 @@ std::string InlineLoginHandlerDialogChromeOS::GetDialogArgs() const { return data; } -bool InlineLoginHandlerDialogChromeOS::ShouldShowDialogTitle() const { +bool InlineLoginDialogChromeOS::ShouldShowDialogTitle() const { return false; } -void InlineLoginHandlerDialogChromeOS::OnDialogShown(content::WebUI* webui) { +void InlineLoginDialogChromeOS::OnDialogShown(content::WebUI* webui) { SystemWebDialogDelegate::OnDialogShown(webui); web_modal::WebContentsModalDialogManager::CreateForWebContents( webui->GetWebContents()); @@ -224,8 +218,7 @@ void InlineLoginHandlerDialogChromeOS::OnDialogShown(content::WebUI* webui) { ->SetDelegate(&delegate_); } -void InlineLoginHandlerDialogChromeOS::OnDialogClosed( - const std::string& json_retval) { +void InlineLoginDialogChromeOS::OnDialogClosed(const std::string& json_retval) { if (ProfileManager::GetActiveUserProfile()->IsChild()) { DCHECK(edu_coexistence_flow_result_.has_value()); base::UmaHistogramEnumeration("AccountManager.EduCoexistence.FlowResult", diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h b/chromium/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h index 3f1eed30662..73daeba9d1c 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_DIALOG_CHROMEOS_H_ -#define CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_DIALOG_CHROMEOS_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_DIALOG_CHROMEOS_H_ +#define CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_DIALOG_CHROMEOS_H_ #include <string> @@ -20,9 +20,8 @@ namespace chromeos { // Extends from |SystemWebDialogDelegate| to create an always-on-top but movable // dialog. It is intentionally made movable so that users can copy-paste account // passwords from password managers. -class InlineLoginHandlerDialogChromeOS - : public SystemWebDialogDelegate, - public web_modal::WebContentsModalDialogHost { +class InlineLoginDialogChromeOS : public SystemWebDialogDelegate, + public web_modal::WebContentsModalDialogHost { public: // The source UX surface used for launching the account addition / // re-authentication dialog. This should be as specific as possible. @@ -88,8 +87,8 @@ class InlineLoginHandlerDialogChromeOS void SetEduCoexistenceFlowResult(EduCoexistenceFlowResult result); protected: - InlineLoginHandlerDialogChromeOS(const GURL& url, const Source& source); - ~InlineLoginHandlerDialogChromeOS() override; + InlineLoginDialogChromeOS(const GURL& url, const Source& source); + ~InlineLoginDialogChromeOS() override; // ui::WebDialogDelegate overrides void GetDialogSize(gfx::Size* size) const override; @@ -104,9 +103,9 @@ class InlineLoginHandlerDialogChromeOS const GURL url_; base::Optional<EduCoexistenceFlowResult> edu_coexistence_flow_result_; - DISALLOW_COPY_AND_ASSIGN(InlineLoginHandlerDialogChromeOS); + DISALLOW_COPY_AND_ASSIGN(InlineLoginDialogChromeOS); }; } // namespace chromeos -#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_HANDLER_DIALOG_CHROMEOS_H_ +#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_INLINE_LOGIN_DIALOG_CHROMEOS_H_ diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc index 4d138271eb6..261a5bb84f6 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.cc @@ -60,10 +60,6 @@ void InlineLoginHandler::RegisterMessages() { base::BindRepeating(&InlineLoginHandler::HandleSwitchToFullTabMessage, base::Unretained(this))); web_ui()->RegisterMessageCallback( - "navigationButtonClicked", - base::BindRepeating(&InlineLoginHandler::HandleNavigationButtonClicked, - base::Unretained(this))); - web_ui()->RegisterMessageCallback( "dialogClose", base::BindRepeating(&InlineLoginHandler::HandleDialogClose, base::Unretained(this))); } @@ -170,8 +166,8 @@ void InlineLoginHandler::HandleCompleteLoginMessage( void InlineLoginHandler::HandleCompleteLoginMessageWithCookies( const base::ListValue& args, - const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies) { + const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies) { const base::Value& dict = args.GetList()[0]; const std::string& email = dict.FindKey("email")->GetString(); @@ -179,9 +175,9 @@ void InlineLoginHandler::HandleCompleteLoginMessageWithCookies( const std::string& gaia_id = dict.FindKey("gaiaId")->GetString(); std::string auth_code; - for (const auto& cookie_with_status : cookies) { - if (cookie_with_status.cookie.Name() == "oauth_code") - auth_code = cookie_with_status.cookie.Value(); + for (const auto& cookie_with_access_result : cookies) { + if (cookie_with_access_result.cookie.Name() == "oauth_code") + auth_code = cookie_with_access_result.cookie.Value(); } bool skip_for_now = dict.FindBoolKey("skipForNow").value_or(false); @@ -233,16 +229,6 @@ void InlineLoginHandler::HandleSwitchToFullTabMessage( CloseDialogFromJavascript(); } -void InlineLoginHandler::HandleNavigationButtonClicked( - const base::ListValue* args) { -#if !defined(OS_CHROMEOS) - NOTREACHED() << "The inline login handler is no longer used in a browser " - "or tab modal dialog."; -#else - FireWebUIListener("navigate-back-in-webview"); -#endif -} - void InlineLoginHandler::HandleDialogClose(const base::ListValue* args) { #if !defined(OS_CHROMEOS) // Does nothing if user manager is not showing. diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h index d8e59330c67..ad371ccb5c9 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler.h @@ -66,16 +66,12 @@ class InlineLoginHandler : public content::WebUIMessageHandler { // from the CookieManager. void HandleCompleteLoginMessageWithCookies( const base::ListValue& args, - const net::CookieStatusList& cookies, - const net::CookieStatusList& excluded_cookies); + const net::CookieAccessResultList& cookies, + const net::CookieAccessResultList& excluded_cookies); // JS callback to switch the UI from a constrainted dialog to a full tab. void HandleSwitchToFullTabMessage(const base::ListValue* args); - // Handles the web ui message sent when the navigation button is clicked by - // the user, requesting either a back navigation or closing the dialog. - void HandleNavigationButtonClicked(const base::ListValue* args); - // Handles the web ui message sent when the window is closed from javascript. virtual void HandleDialogClose(const base::ListValue* args); diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc index 1eee7735f97..b02e9de9753 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_chromeos.cc @@ -20,8 +20,8 @@ #include "chrome/browser/signin/chrome_device_id_helper.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/webui/signin/inline_login_dialog_chromeos.h" #include "chrome/browser/ui/webui/signin/inline_login_handler.h" -#include "chrome/browser/ui/webui/signin/inline_login_handler_dialog_chromeos.h" #include "chromeos/components/account_manager/account_manager.h" #include "chromeos/components/account_manager/account_manager_factory.h" #include "chromeos/constants/chromeos_features.h" @@ -319,9 +319,8 @@ void InlineLoginHandlerChromeOS::CompleteLogin(const std::string& email, const std::string* parentId = edu_login_params.FindStringKey("parentObfuscatedGaiaId"); CHECK(parentId); - InlineLoginHandlerDialogChromeOS::UpdateEduCoexistenceFlowResult( - InlineLoginHandlerDialogChromeOS::EduCoexistenceFlowResult:: - kFlowCompleted); + InlineLoginDialogChromeOS::UpdateEduCoexistenceFlowResult( + InlineLoginDialogChromeOS::EduCoexistenceFlowResult::kFlowCompleted); // ChildSigninHelper deletes itself after its work is done. new ChildSigninHelper( account_manager, close_dialog_closure_, diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc index c0cf761b098..39f070896a1 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_handler_impl.cc @@ -380,8 +380,10 @@ void InlineSigninHelper::OnClientOAuthSuccessAndBrowserOpened( } } #endif - if (reason == HandlerSigninReason::UNLOCK) { + DCHECK(!identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync) + .IsEmpty()); + identity_manager->GetAccountsMutator()->AddOrUpdateAccount( gaia_id_, email_, result.refresh_token, result.is_under_advanced_protection, @@ -396,11 +398,9 @@ void InlineSigninHelper::OnClientOAuthSuccessAndBrowserOpened( base::BindOnce(&InlineLoginHandlerImpl::CloseTab, handler_)); } - if (identity_manager->HasPrimaryAccount()) { - identity_manager->GetAccountsCookieMutator()->AddAccountToCookie( - identity_manager->GetPrimaryAccountId(), - gaia::GaiaSource::kPrimaryAccountManager, {}); - } + identity_manager->GetAccountsCookieMutator()->AddAccountToCookie( + identity_manager->GetPrimaryAccountId(), + gaia::GaiaSource::kPrimaryAccountManager, {}); signin_metrics::LogSigninReason( GetSigninReasonFromHandlerSigninReason(reason)); diff --git a/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc b/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc index 1e0b5bff4ad..c00843b7b17 100644 --- a/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc +++ b/chromium/chrome/browser/ui/webui/signin/inline_login_ui.cc @@ -26,6 +26,7 @@ #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_switches.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #if defined(OS_CHROMEOS) #include "chrome/browser/chromeos/profiles/profile_helper.h" @@ -83,23 +84,18 @@ void AddEduStrings(content::WebUIDataSource* source, l10n_util::GetStringFUTF16( IDS_EDU_LOGIN_INFO_BODY, base::ASCIIToUTF16(chrome::kGsuiteTermsEducationPrivacyURL))); - source->AddString( - "parentInfoDataProtectionText", - l10n_util::GetStringFUTF16( - IDS_EDU_LOGIN_INFO_DATA_PROTECTION, - base::ASCIIToUTF16(chrome::kClassroomSigninLearnMoreURL))); - source->AddLocalizedString("parentInfoResourcesAvailabilityText", - IDS_EDU_LOGIN_INFO_RESOURCES_AVAILABILITY); source->AddLocalizedString("coexistenceTitle", - IDS_EDU_LOGIN_COEXISTENCE_TITLE); - source->AddLocalizedString("coexistenceBody", IDS_EDU_LOGIN_COEXISTENCE_BODY); + IDS_EDU_LOGIN_INFO_COEXISTENCE_TITLE); + source->AddLocalizedString("coexistenceBody", + IDS_EDU_LOGIN_INFO_COEXISTENCE_BODY); } #endif // defined(OS_CHROMEOS) content::WebUIDataSource* CreateWebUIDataSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUIChromeSigninHost); - source->OverrideContentSecurityPolicyObjectSrc("object-src chrome:;"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ObjectSrc, "object-src chrome:;"); source->UseStringsJs(); source->SetDefaultResource(IDR_INLINE_LOGIN_HTML); @@ -143,7 +139,8 @@ content::WebUIDataSource* CreateWebUIDataSource() { webui::AddResourcePathsBulk(source, kResources); #if defined(OS_CHROMEOS) - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); webui::SetupWebUIDataSource( source, diff --git a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index fcfe998400d..6f2d76198e2 100644 --- a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.cc @@ -4,6 +4,8 @@ #include "chrome/browser/ui/webui/signin/login_ui_test_utils.h" +#include "base/bind.h" +#include "base/notreached.h" #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/strings/stringprintf.h" @@ -52,9 +54,7 @@ class SignInObserver : public signin::IdentityManager::Observer { SignInObserver() : seen_(false), running_(false), signed_in_(false) {} // Returns whether a GoogleSigninSucceeded event has happened. - bool DidSignIn() { - return signed_in_; - } + bool DidSignIn() { return signed_in_; } // Blocks and waits until the user signs in. Wait() does not block if a // GoogleSigninSucceeded has already occurred. @@ -193,6 +193,8 @@ void WaitUntilAnyElementExistsInSigninFrame( enum class SyncConfirmationDialogAction { kConfirm, kCancel }; +enum class ReauthDialogAction { kConfirm, kCancel }; + #if !defined(OS_CHROMEOS) std::string GetButtonIdForSyncConfirmationDialogAction( SyncConfirmationDialogAction action) { @@ -226,6 +228,16 @@ std::string GetButtonIdForSigninEmailConfirmationDialogAction( } } +std::string GetButtonIdForReauthConfirmationDialogAction( + ReauthDialogAction action) { + switch (action) { + case ReauthDialogAction::kConfirm: + return "confirmButton"; + case ReauthDialogAction::kCancel: + return "cancelButton"; + } +} + std::string GetButtonSelectorForApp(const std::string& app, const std::string& button_id) { return base::StringPrintf( @@ -233,6 +245,23 @@ std::string GetButtonSelectorForApp(const std::string& app, "document.querySelector('%s').shadowRoot.querySelector('#%s'))", app.c_str(), app.c_str(), button_id.c_str()); } + +bool IsElementReady(content::WebContents* web_contents, + const std::string& element_selector) { + std::string message; + std::string find_element_js = base::StringPrintf( + "if (document.readyState != 'complete') {" + " window.domAutomationController.send('DocumentNotReady');" + "} else if (%s == null) {" + " window.domAutomationController.send('NotFound');" + "} else {" + " window.domAutomationController.send('Ok');" + "}", + element_selector.c_str()); + EXPECT_TRUE(content::ExecuteScriptAndExtractString( + web_contents, find_element_js, &message)); + return message == "Ok"; +} #endif // !defined(OS_CHROMEOS) } // namespace @@ -258,19 +287,7 @@ class SigninViewControllerTestUtil { std::string button_selector = GetButtonSelectorForApp( "sync-confirmation-app", GetButtonIdForSyncConfirmationDialogAction(action)); - std::string message; - std::string find_button_js = base::StringPrintf( - "if (document.readyState != 'complete') {" - " window.domAutomationController.send('DocumentNotReady');" - "} else if (%s == null) {" - " window.domAutomationController.send('NotFound');" - "} else {" - " window.domAutomationController.send('Ok');" - "}", - button_selector.c_str()); - EXPECT_TRUE(content::ExecuteScriptAndExtractString( - dialog_web_contents, find_button_js, &message)); - if (message != "Ok") + if (!IsElementReady(dialog_web_contents, button_selector)) return false; // This cannot be a synchronous call, because it closes the window as a side @@ -302,19 +319,7 @@ class SigninViewControllerTestUtil { std::string button_selector = GetButtonSelectorForApp( "signin-email-confirmation-app", GetButtonIdForSigninEmailConfirmationDialogAction(action)); - std::string message; - std::string find_button_js = base::StringPrintf( - "if (document.readyState != 'complete') {" - " window.domAutomationController.send('DocumentNotReady');" - "} else if (%s == null || %s == null) {" - " window.domAutomationController.send('NotFound');" - "} else {" - " window.domAutomationController.send('Ok');" - "}", - radio_button_selector.c_str(), button_selector.c_str()); - EXPECT_TRUE(content::ExecuteScriptAndExtractString( - dialog_web_contents, find_button_js, &message)); - if (message != "Ok") + if (!IsElementReady(dialog_web_contents, button_selector)) return false; // This cannot be a synchronous call, because it closes the window as a side @@ -326,6 +331,35 @@ class SigninViewControllerTestUtil { return true; #endif } + + static bool TryCompleteReauthConfirmationDialog(Browser* browser, + ReauthDialogAction action) { +#if defined(OS_CHROMEOS) + NOTREACHED(); + return false; +#else + SigninViewController* signin_view_controller = + browser->signin_view_controller(); + DCHECK(signin_view_controller); + if (!signin_view_controller->ShowsModalDialog()) + return false; + + content::WebContents* dialog_web_contents = + signin_view_controller->GetModalDialogWebContentsForTesting(); + DCHECK(dialog_web_contents); + std::string button_selector = GetButtonSelectorForApp( + "signin-reauth-app", + GetButtonIdForReauthConfirmationDialogAction(action)); + if (!IsElementReady(dialog_web_contents, button_selector)) + return false; + + // This cannot be a synchronous call, because it closes the window as a side + // effect, which may cause the javascript execution to never finish. + content::ExecuteScriptAsync(dialog_web_contents, + button_selector + ".click();"); + return true; +#endif + } }; void WaitUntilUIReady(Browser* browser) { @@ -472,4 +506,28 @@ bool CompleteSigninEmailConfirmationDialog( return false; } +bool CompleteReauthConfirmationDialog(Browser* browser, + base::TimeDelta timeout, + ReauthDialogAction action) { + const base::Time expire_time = base::Time::Now() + timeout; + while (base::Time::Now() <= expire_time) { + if (SigninViewControllerTestUtil::TryCompleteReauthConfirmationDialog( + browser, action)) + return true; + RunLoopFor(base::TimeDelta::FromMilliseconds(1000)); + } + return false; +} + +bool ConfirmReauthConfirmationDialog(Browser* browser, + base::TimeDelta timeout) { + return CompleteReauthConfirmationDialog(browser, timeout, + ReauthDialogAction::kConfirm); +} + +bool CancelReauthConfirmationDialog(Browser* browser, base::TimeDelta timeout) { + return CompleteReauthConfirmationDialog(browser, timeout, + ReauthDialogAction::kCancel); +} + } // namespace login_ui_test_utils diff --git a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h index b9440eabf6f..5d3833932d7 100644 --- a/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h +++ b/chromium/chrome/browser/ui/webui/signin/login_ui_test_utils.h @@ -60,6 +60,16 @@ bool CompleteSigninEmailConfirmationDialog( base::TimeDelta timeout, SigninEmailConfirmationDialog::Action action); +// Waits for the reauth confirmation dialog to get displayed, then executes +// javascript to click on confirm button. Returns false if dialog wasn't +// dismissed before |timeout|. +bool ConfirmReauthConfirmationDialog(Browser* browser, base::TimeDelta timeout); + +// Waits for the reauth confirmation dialog to get displayed, then executes +// javascript to click on cancel button. Returns false if dialog wasn't +// dismissed before |timeout|. +bool CancelReauthConfirmationDialog(Browser* browser, base::TimeDelta timeout); + } // namespace login_ui_test_utils #endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_LOGIN_UI_TEST_UTILS_H_ diff --git a/chromium/chrome/browser/ui/webui/signin/profile_picker_ui.h b/chromium/chrome/browser/ui/webui/signin/profile_picker_ui.h index 68feea31425..10274bf8cc3 100644 --- a/chromium/chrome/browser/ui/webui/signin/profile_picker_ui.h +++ b/chromium/chrome/browser/ui/webui/signin/profile_picker_ui.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SIGNIN_PROFILE_PICKER_UI_H_ #define CHROME_BROWSER_UI_WEBUI_SIGNIN_PROFILE_PICKER_UI_H_ +#include "base/macros.h" #include "content/public/browser/web_ui_controller.h" // The WebUI controller for chrome://profile-picker/. diff --git a/chromium/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc b/chromium/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc index b08ea973884..7c3861b0d3c 100644 --- a/chromium/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc +++ b/chromium/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc @@ -15,7 +15,6 @@ #include "base/strings/utf_string_conversions.h" #include "base/task_runner_util.h" #include "base/threading/thread_restrictions.h" -#include "base/value_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile_attributes_entry.h" diff --git a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc index 025f5941b5c..d96fffe86d4 100644 --- a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc +++ b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.cc @@ -227,3 +227,8 @@ void SigninEmailConfirmationDialog::ResizeNativeView(int height) { content::WebContents* SigninEmailConfirmationDialog::GetWebContents() { return GetDialogWebContents(); } + +void SigninEmailConfirmationDialog::SetWebContents( + content::WebContents* web_contents) { + NOTIMPLEMENTED(); +} diff --git a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h index 587587a9b95..1e6fab521cf 100644 --- a/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h +++ b/chromium/chrome/browser/ui/webui/signin/signin_email_confirmation_dialog.h @@ -80,6 +80,7 @@ class SigninEmailConfirmationDialog : public ui::WebDialogDelegate, void CloseModalSignin() override; void ResizeNativeView(int height) override; content::WebContents* GetWebContents() override; + void SetWebContents(content::WebContents* web_contents) override; // Shows the dialog and releases ownership of this object. Another object will // take ownership and delete this object. diff --git a/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc b/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc index 480a3eecadf..3c206e17792 100644 --- a/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc +++ b/chromium/chrome/browser/ui/webui/signin/signin_error_handler.cc @@ -89,13 +89,6 @@ void SigninErrorHandler::HandleInitializedWithSize( FireWebUIListener("switch-button-unavailable"); signin::SetInitializedModalHeight(browser_, web_ui(), args); - - // After the dialog is shown, some platforms might have an element focused. - // To be consistent, clear the focused element on all platforms. - // TODO(anthonyvd): Figure out why this is needed on Mac and not other - // platforms and if there's a way to start unfocused while avoiding this - // workaround. - FireWebUIListener("clear-focus"); } void SigninErrorHandler::CloseDialog() { diff --git a/chromium/chrome/browser/ui/webui/signin/signin_reauth_handler.cc b/chromium/chrome/browser/ui/webui/signin/signin_reauth_handler.cc new file mode 100644 index 00000000000..b56edbbdd8b --- /dev/null +++ b/chromium/chrome/browser/ui/webui/signin/signin_reauth_handler.cc @@ -0,0 +1,72 @@ +// Copyright 2020 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/signin/signin_reauth_handler.h" + +#include "base/bind.h" +#include "chrome/browser/ui/signin_reauth_view_controller.h" +#include "content/public/browser/web_ui.h" +#include "ui/base/webui/web_ui_util.h" + +SigninReauthHandler::SigninReauthHandler(SigninReauthViewController* controller) + : controller_(controller) { + DCHECK(controller_); + controller_observer_.Add(controller_); +} + +SigninReauthHandler::~SigninReauthHandler() = default; + +void SigninReauthHandler::RegisterMessages() { + web_ui()->RegisterMessageCallback( + "initialize", base::BindRepeating(&SigninReauthHandler::HandleInitialize, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "confirm", base::BindRepeating(&SigninReauthHandler::HandleConfirm, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "cancel", base::BindRepeating(&SigninReauthHandler::HandleCancel, + base::Unretained(this))); +} + +void SigninReauthHandler::OnJavascriptAllowed() { + if (!controller_) + return; + + SigninReauthViewController::GaiaReauthType gaia_reauth_type = + controller_->gaia_reauth_type(); + if (gaia_reauth_type != + SigninReauthViewController::GaiaReauthType::kUnknown) { + OnGaiaReauthTypeDetermined(gaia_reauth_type); + } +} + +void SigninReauthHandler::OnReauthControllerDestroyed() { + controller_observer_.RemoveAll(); + controller_ = nullptr; +} + +void SigninReauthHandler::OnGaiaReauthTypeDetermined( + SigninReauthViewController::GaiaReauthType reauth_type) { + if (!IsJavascriptAllowed()) + return; + + DCHECK_NE(reauth_type, SigninReauthViewController::GaiaReauthType::kUnknown); + bool is_reauth_required = + reauth_type != SigninReauthViewController::GaiaReauthType::kAutoApproved; + FireWebUIListener("reauth-type-received", base::Value(is_reauth_required)); +} + +void SigninReauthHandler::HandleInitialize(const base::ListValue* args) { + AllowJavascript(); +} + +void SigninReauthHandler::HandleConfirm(const base::ListValue* args) { + if (controller_) + controller_->OnReauthConfirmed(); +} + +void SigninReauthHandler::HandleCancel(const base::ListValue* args) { + if (controller_) + controller_->OnReauthDismissed(); +} diff --git a/chromium/chrome/browser/ui/webui/signin/signin_reauth_handler.h b/chromium/chrome/browser/ui/webui/signin/signin_reauth_handler.h new file mode 100644 index 00000000000..2ab5bd48f7d --- /dev/null +++ b/chromium/chrome/browser/ui/webui/signin/signin_reauth_handler.h @@ -0,0 +1,57 @@ +// Copyright 2020 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_SIGNIN_SIGNIN_REAUTH_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_HANDLER_H_ + +#include "chrome/browser/ui/signin_reauth_view_controller.h" +#include "content/public/browser/web_ui_message_handler.h" + +namespace base { +class ListValue; +} + +// WebUI message handler for the signin reauth dialog. +class SigninReauthHandler : public content::WebUIMessageHandler, + public SigninReauthViewController::Observer { + public: + // Creates a SigninReauthHandler for the |controller|. + explicit SigninReauthHandler(SigninReauthViewController* controller); + ~SigninReauthHandler() override; + + SigninReauthHandler(const SigninReauthHandler&) = delete; + SigninReauthHandler& operator=(const SigninReauthHandler&) = delete; + + // content::WebUIMessageHandler: + void RegisterMessages() override; + void OnJavascriptAllowed() override; + + // SigninReauthViewController::Observer: + void OnReauthControllerDestroyed() override; + void OnGaiaReauthTypeDetermined( + SigninReauthViewController::GaiaReauthType reauth_type) override; + + protected: + // Handles "initialize" message from the page. No arguments. + virtual void HandleInitialize(const base::ListValue* args); + + // Handles "confirm" message from the page. No arguments. + // This message is sent when the user confirms that they want complete the + // reauth flow. + virtual void HandleConfirm(const base::ListValue* args); + + // Handles "cancel" message from the page. No arguments. This message is sent + // when the user cancels the reauth flow. + virtual void HandleCancel(const base::ListValue* args); + + private: + // May be null if |controller_| gets destroyed earlier than |this|. + SigninReauthViewController* controller_; + + ScopedObserver<SigninReauthViewController, + SigninReauthViewController::Observer> + controller_observer_{this}; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/signin/signin_reauth_ui.cc b/chromium/chrome/browser/ui/webui/signin/signin_reauth_ui.cc new file mode 100644 index 00000000000..b2730305e4f --- /dev/null +++ b/chromium/chrome/browser/ui/webui/signin/signin_reauth_ui.cc @@ -0,0 +1,138 @@ +// Copyright 2020 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/signin/signin_reauth_ui.h" + +#include <string> + +#include "base/check.h" +#include "base/optional.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_avatar_icon_util.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/signin/reauth_util.h" +#include "chrome/browser/ui/signin_reauth_view_controller.h" +#include "chrome/browser/ui/webui/signin/signin_reauth_handler.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/grit/browser_resources.h" +#include "chrome/grit/generated_resources.h" +#include "components/signin/public/base/signin_metrics.h" +#include "components/signin/public/identity_manager/account_info.h" +#include "components/signin/public/identity_manager/consent_level.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "content/public/browser/web_ui_data_source.h" +#include "google_apis/gaia/core_account_id.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" +#include "ui/base/webui/web_ui_util.h" +#include "ui/gfx/image/image.h" +#include "ui/resources/grit/webui_resources.h" + +namespace { + +std::string GetAccountImageURL(Profile* profile) { + auto* identity_manager = IdentityManagerFactory::GetForProfile(profile); + // The current version of the reauth only supports the primary account. + // TODO(crbug.com/1083429): generalize for arbitrary accounts by passing an + // account id as a method parameter. + CoreAccountId account_id = + identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kNotRequired); + // Sync shouldn't be enabled. Otherwise, the primary account and the first + // cookie account may diverge. + DCHECK(!identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); + base::Optional<AccountInfo> account_info = + identity_manager + ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId( + account_id); + + return account_info && !account_info->account_image.IsEmpty() + ? webui::GetBitmapDataUrl(account_info->account_image.AsBitmap()) + : profiles::GetPlaceholderAvatarIconUrl(); +} + +int GetReauthTitleStringId(signin_metrics::ReauthAccessPoint access_point) { + switch (access_point) { + case signin_metrics::ReauthAccessPoint::kUnknown: + case signin_metrics::ReauthAccessPoint::kAutofillDropdown: + case signin_metrics::ReauthAccessPoint::kPasswordSettings: + return IDS_ACCOUNT_PASSWORDS_REAUTH_SHOW_TITLE; + case signin_metrics::ReauthAccessPoint::kGeneratePasswordDropdown: + case signin_metrics::ReauthAccessPoint::kGeneratePasswordContextMenu: + case signin_metrics::ReauthAccessPoint::kPasswordSaveBubble: + case signin_metrics::ReauthAccessPoint::kPasswordMoveBubble: + return IDS_ACCOUNT_PASSWORDS_REAUTH_SAVE_TITLE; + } +} + +int GetReauthConfirmButtonLabelStringId( + signin_metrics::ReauthAccessPoint access_point) { + switch (access_point) { + case signin_metrics::ReauthAccessPoint::kUnknown: + case signin_metrics::ReauthAccessPoint::kAutofillDropdown: + case signin_metrics::ReauthAccessPoint::kPasswordSettings: + return IDS_ACCOUNT_PASSWORDS_REAUTH_SHOW_BUTTON_LABEL; + case signin_metrics::ReauthAccessPoint::kGeneratePasswordDropdown: + case signin_metrics::ReauthAccessPoint::kGeneratePasswordContextMenu: + case signin_metrics::ReauthAccessPoint::kPasswordSaveBubble: + case signin_metrics::ReauthAccessPoint::kPasswordMoveBubble: + return IDS_ACCOUNT_PASSWORDS_REAUTH_SAVE_BUTTON_LABEL; + } +} + +} // namespace + +SigninReauthUI::SigninReauthUI(content::WebUI* web_ui) + : SigninWebDialogUI(web_ui) { + Profile* profile = Profile::FromWebUI(web_ui); + signin_metrics::ReauthAccessPoint access_point = + signin::GetReauthAccessPointForReauthConfirmationURL( + web_ui->GetWebContents()->GetVisibleURL()); + + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUISigninReauthHost); + source->UseStringsJs(); + source->EnableReplaceI18nInJS(); + source->SetDefaultResource(IDR_SIGNIN_REAUTH_HTML); + source->AddResourcePath("signin_reauth_app.js", IDR_SIGNIN_REAUTH_APP_JS); + source->AddResourcePath("signin_reauth_browser_proxy.js", + IDR_SIGNIN_REAUTH_BROWSER_PROXY_JS); + source->AddResourcePath("signin_shared_css.js", IDR_SIGNIN_SHARED_CSS_JS); + source->AddString("accountImageUrl", GetAccountImageURL(profile)); + + // Resources for testing. + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, + "script-src chrome://resources chrome://test 'self';"); + source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER); + source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER); + + // Resources for the account passwords reauth. + source->AddResourcePath( + "images/signin_reauth_illustration.svg", + IDR_SIGNIN_REAUTH_IMAGES_ACCOUNT_PASSWORDS_REAUTH_ILLUSTRATION_SVG); + source->AddResourcePath( + "images/signin_reauth_illustration_dark.svg", + IDR_SIGNIN_REAUTH_IMAGES_ACCOUNT_PASSWORDS_REAUTH_ILLUSTRATION_DARK_SVG); + source->AddLocalizedString("signinReauthTitle", + GetReauthTitleStringId(access_point)); + source->AddLocalizedString("signinReauthDesc", + IDS_ACCOUNT_PASSWORDS_REAUTH_DESC); + source->AddLocalizedString("signinReauthConfirmLabel", + GetReauthConfirmButtonLabelStringId(access_point)); + source->AddLocalizedString("signinReauthNextLabel", + IDS_ACCOUNT_PASSWORDS_REAUTH_NEXT_BUTTON_LABEL); + source->AddLocalizedString("signinReauthCloseLabel", + IDS_ACCOUNT_PASSWORDS_REAUTH_CLOSE_BUTTON_LABEL); + + content::WebUIDataSource::Add(profile, source); +} + +SigninReauthUI::~SigninReauthUI() = default; + +void SigninReauthUI::InitializeMessageHandlerWithReauthController( + SigninReauthViewController* controller) { + web_ui()->AddMessageHandler( + std::make_unique<SigninReauthHandler>(controller)); +} + +void SigninReauthUI::InitializeMessageHandlerWithBrowser(Browser* browser) {} diff --git a/chromium/chrome/browser/ui/webui/signin/signin_reauth_ui.h b/chromium/chrome/browser/ui/webui/signin/signin_reauth_ui.h new file mode 100644 index 00000000000..e32947e0548 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/signin/signin_reauth_ui.h @@ -0,0 +1,49 @@ +// Copyright 2020 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_SIGNIN_SIGNIN_REAUTH_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_UI_H_ + +#include "chrome/browser/ui/webui/signin/signin_web_dialog_ui.h" + +class Browser; +class SigninReauthViewController; + +namespace content { +class WebUI; +} + +// WebUI controller for the signin reauth dialog. +// +// The reauth UI currently assumes that the unconsented primary account matches +// the first account in cookies. +// It's a safe assumption only under the following conditions: +// - DICE is enabled +// - Sync in not enabled +// +// Currently this dialog is only used for account password storage opt-in that +// satisfies both of those conditions. +// +// Contact chrome-signin@chromium.org if you want to reuse this dialog for other +// reauth use-cases. +class SigninReauthUI : public SigninWebDialogUI { + public: + explicit SigninReauthUI(content::WebUI* web_ui); + ~SigninReauthUI() override; + + SigninReauthUI(const SigninReauthUI&) = delete; + SigninReauthUI& operator=(const SigninReauthUI&) = delete; + + // Creates a WebUI message handler with the specified |controller| and adds it + // to the web UI. + void InitializeMessageHandlerWithReauthController( + SigninReauthViewController* controller); + + // SigninWebDialogUI: + // This class relies on InitializeMessageHandlerWithReauthController() so this + // method does nothing. + void InitializeMessageHandlerWithBrowser(Browser* browser) override; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_SIGNIN_SIGNIN_REAUTH_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc index eba97fb4b9f..1924e39ce29 100644 --- a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc +++ b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler.cc @@ -239,11 +239,4 @@ void SyncConfirmationHandler::HandleInitializedWithSize( } signin::SetInitializedModalHeight(browser_, web_ui(), args); - - // After the dialog is shown, some platforms might have an element focused. - // To be consistent, clear the focused element on all platforms. - // TODO(anthonyvd): Figure out why this is needed on Mac and not other - // platforms and if there's a way to start unfocused while avoiding this - // workaround. - FireWebUIListener("clear-focus"); } diff --git a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc index f10afde391d..ab71645c8ce 100644 --- a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_handler_unittest.cc @@ -223,10 +223,8 @@ TEST_F(SyncConfirmationHandlerTest, TestSetImageIfPrimaryAccountReady) { args.Set(0, std::make_unique<base::Value>(kDefaultDialogHeight)); handler()->HandleInitializedWithSize(&args); + ASSERT_EQ(1U, web_ui()->call_data().size()); ExpectAccountImageChanged(*web_ui()->call_data()[0]); - EXPECT_EQ("cr.webUIListenerCallback", - web_ui()->call_data()[1]->function_name()); - EXPECT_EQ("clear-focus", web_ui()->call_data()[1]->arg1()->GetString()); } TEST_F(SyncConfirmationHandlerTest, TestSetImageIfPrimaryAccountReadyLater) { @@ -234,19 +232,16 @@ TEST_F(SyncConfirmationHandlerTest, TestSetImageIfPrimaryAccountReadyLater) { args.Set(0, std::make_unique<base::Value>(kDefaultDialogHeight)); handler()->HandleInitializedWithSize(&args); - EXPECT_EQ(2U, web_ui()->call_data().size()); + ASSERT_EQ(1U, web_ui()->call_data().size()); ExpectAccountImageChanged(*web_ui()->call_data()[0]); - EXPECT_EQ("cr.webUIListenerCallback", - web_ui()->call_data()[1]->function_name()); - EXPECT_EQ("clear-focus", web_ui()->call_data()[1]->arg1()->GetString()); identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( account_info_.account_id, account_info_.email, account_info_.gaia, "", "full_name", "given_name", "locale", "http://picture.example.com/picture.jpg"); - EXPECT_EQ(3U, web_ui()->call_data().size()); - ExpectAccountImageChanged(*web_ui()->call_data()[2]); + ASSERT_EQ(2U, web_ui()->call_data().size()); + ExpectAccountImageChanged(*web_ui()->call_data()[1]); } TEST_F(SyncConfirmationHandlerTest, @@ -254,7 +249,7 @@ TEST_F(SyncConfirmationHandlerTest, base::ListValue args; args.Set(0, std::make_unique<base::Value>(kDefaultDialogHeight)); handler()->HandleInitializedWithSize(&args); - EXPECT_EQ(2U, web_ui()->call_data().size()); + EXPECT_EQ(1U, web_ui()->call_data().size()); AccountInfo account_info = identity_test_env()->MakeAccountAvailable("bar@example.com"); @@ -265,7 +260,7 @@ TEST_F(SyncConfirmationHandlerTest, // Updating the account info of a secondary account should not update the // image of the sync confirmation dialog. - EXPECT_EQ(2U, web_ui()->call_data().size()); + EXPECT_EQ(1U, web_ui()->call_data().size()); identity_test_env()->SimulateSuccessfulFetchOfAccountInfo( account_info_.account_id, account_info_.email, account_info_.gaia, "", @@ -274,8 +269,8 @@ TEST_F(SyncConfirmationHandlerTest, // Updating the account info of the primary account should update the // image of the sync confirmation dialog. - EXPECT_EQ(3U, web_ui()->call_data().size()); - ExpectAccountImageChanged(*web_ui()->call_data()[2]); + ASSERT_EQ(2U, web_ui()->call_data().size()); + ExpectAccountImageChanged(*web_ui()->call_data()[1]); } TEST_F(SyncConfirmationHandlerTest, TestHandleUndo) { diff --git a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc index 3ba5023e3c6..cdbfd068fbf 100644 --- a/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc +++ b/chromium/chrome/browser/ui/webui/signin/sync_confirmation_ui.cc @@ -21,6 +21,7 @@ #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" #include "ui/resources/grit/webui_resources.h" @@ -44,7 +45,8 @@ SyncConfirmationUI::SyncConfirmationUI(content::WebUI* web_ui) if (is_sync_allowed) { source->AddResourcePath("test_loader.js", IDR_WEBUI_JS_TEST_LOADER); source->AddResourcePath("test_loader.html", IDR_WEBUI_HTML_TEST_LOADER); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); source->SetDefaultResource(IDR_SYNC_CONFIRMATION_HTML); diff --git a/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc index 2dea17c899c..295468faa44 100644 --- a/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc +++ b/chromium/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc @@ -18,7 +18,7 @@ #include "base/single_thread_task_runner.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_task_runner_handle.h" -#include "base/value_conversions.h" +#include "base/util/values/values_util.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" @@ -314,13 +314,15 @@ void UserManagerScreenHandler::HandleAuthenticatedLaunchUser( if (!args->Get(0, &profile_path_value)) return; - base::FilePath profile_path; - if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) + base::Optional<base::FilePath> profile_path = + util::ValueToFilePath(*profile_path_value); + if (!profile_path) return; ProfileAttributesEntry* entry; - if (!g_browser_process->profile_manager()->GetProfileAttributesStorage(). - GetProfileAttributesWithPath(profile_path, &entry)) { + if (!g_browser_process->profile_manager() + ->GetProfileAttributesStorage() + .GetProfileAttributesWithPath(*profile_path, &entry)) { return; } @@ -332,7 +334,7 @@ void UserManagerScreenHandler::HandleAuthenticatedLaunchUser( if (!args->GetString(2, &password)) return; - authenticating_profile_path_ = profile_path; + authenticating_profile_path_ = *profile_path; email_address_ = base::UTF16ToUTF8(email_address); // Only try to validate locally or check the password change detection @@ -365,13 +367,13 @@ void UserManagerScreenHandler::HandleAuthenticatedLaunchUser( content::BrowserContext* browser_context = web_ui()->GetWebContents()->GetBrowserContext(); - if (!email_address_.empty()) { + if (!email_address_.empty() && entry->IsAuthenticated()) { // In order to support the upgrade case where we have a local hash but no // password token, the user must perform a full online reauth. RecordAuthenticatedLaunchUserEvent( AuthenticatedLaunchUserEvent::GAIA_REAUTH_DIALOG); UserManagerProfileDialog::ShowUnlockDialogWithProfilePath( - browser_context, email_address_, profile_path); + browser_context, email_address_, *profile_path); } else if (entry->IsSigninRequired() && entry->IsSupervised()) { // Supervised profile will only be locked when force-sign-in is enabled // and it shouldn't be unlocked. Display the error message directly via @@ -401,7 +403,7 @@ void UserManagerScreenHandler::HandleAuthenticatedLaunchUser( RecordAuthenticatedLaunchUserEvent( AuthenticatedLaunchUserEvent::FORCED_PRIMARY_SIGNIN_DIALOG); UserManagerProfileDialog::ShowForceSigninDialog(browser_context, - profile_path); + *profile_path); } } @@ -413,8 +415,9 @@ void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) { return; } - base::FilePath profile_path; - if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) { + base::Optional<base::FilePath> profile_path = + util::ValueToFilePath(*profile_path_value); + if (!profile_path) { NOTREACHED(); return; } @@ -432,7 +435,7 @@ void UserManagerScreenHandler::HandleRemoveUser(const base::ListValue* args) { // The callback is run if the only profile has been deleted, and a new // profile has been created to replace it. - webui::DeleteProfileAtPath(profile_path, + webui::DeleteProfileAtPath(*profile_path, ProfileMetrics::DELETE_PROFILE_USER_MANAGER); } @@ -466,13 +469,15 @@ void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) { if (!args->Get(0, &profile_path_value)) return; - base::FilePath profile_path; - if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) + base::Optional<base::FilePath> profile_path = + util::ValueToFilePath(*profile_path_value); + if (!profile_path) return; ProfileAttributesEntry* entry; - if (!g_browser_process->profile_manager()->GetProfileAttributesStorage(). - GetProfileAttributesWithPath(profile_path, &entry)) { + if (!g_browser_process->profile_manager() + ->GetProfileAttributesStorage() + .GetProfileAttributesWithPath(*profile_path, &entry)) { NOTREACHED(); return; } @@ -486,7 +491,7 @@ void UserManagerScreenHandler::HandleLaunchUser(const base::ListValue* args) { return; profiles::SwitchToProfile( - profile_path, false, /* reuse any existing windows */ + *profile_path, false, /* reuse any existing windows */ base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete, weak_ptr_factory_.GetWeakPtr())); } @@ -499,20 +504,20 @@ void UserManagerScreenHandler::HandleRemoveUserWarningLoadStats( return; base::Time start_time = base::Time::Now(); - base::FilePath profile_path; - - if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) + base::Optional<base::FilePath> profile_path = + util::ValueToFilePath(*profile_path_value); + if (!profile_path) return; - base::Value return_profile_path(profile_path.value()); - Profile* profile = g_browser_process->profile_manager()-> - GetProfileByPath(profile_path); + base::Value return_profile_path(profile_path->value()); + Profile* profile = + g_browser_process->profile_manager()->GetProfileByPath(*profile_path); if (profile) { GatherStatistics(start_time, profile); } else { g_browser_process->profile_manager()->LoadProfileByPath( - profile_path, false, + *profile_path, false, base::BindOnce(&UserManagerScreenHandler::GatherStatistics, weak_ptr_factory_.GetWeakPtr(), start_time)); } @@ -796,8 +801,7 @@ void UserManagerScreenHandler::SendUserList() { profile_value->SetString(kKeyEmailAddress, entry->GetUserName()); profile_value->SetString(kKeyDisplayName, profiles::GetAvatarNameForProfile(profile_path)); - profile_value->SetKey(kKeyProfilePath, - base::CreateFilePathValue(profile_path)); + profile_value->SetKey(kKeyProfilePath, util::FilePathToValue(profile_path)); profile_value->SetBoolean(kKeyPublicAccount, false); profile_value->SetBoolean(kKeyLegacySupervisedUser, entry->IsLegacySupervised()); diff --git a/chromium/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc b/chromium/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc index 47070460d08..56594542eac 100644 --- a/chromium/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc +++ b/chromium/chrome/browser/ui/webui/signin/user_manager_ui_browsertest.cc @@ -148,6 +148,8 @@ IN_PROC_BROWSER_TEST_F(UserManagerUIAuthenticatedUserBrowserTest, Reauth) { Init(); signin_util::SetForceSigninForTesting(true); entry_->SetLocalAuthCredentials("1mock_credentials"); + // Consent profile's primary account. + entry_->SetAuthInfo("gaia_id", base::string16(), true); LaunchAuthenticatedUser("email@mock.com"); @@ -162,6 +164,29 @@ IN_PROC_BROWSER_TEST_F(UserManagerUIAuthenticatedUserBrowserTest, Reauth) { } IN_PROC_BROWSER_TEST_F(UserManagerUIAuthenticatedUserBrowserTest, + SigninButUnconsentedUserBlocked) { + Init(); + signin_util::SetForceSigninForTesting(true); + + // Unconsent profile's primary account is used locked due to force sign in. + entry_->SetIsSigninRequired(true); + entry_->SetActiveTimeToNow(); + entry_->SetAuthInfo("gaia_id", base::string16(), false); + + MockLoginUIService* service = static_cast<MockLoginUIService*>( + LoginUIServiceFactory::GetInstance()->SetTestingFactoryAndUse( + profile_, base::BindRepeating(&CreateLoginUIService))); + EXPECT_CALL(*service, SetProfileBlockingErrorMessage()); + + LaunchAuthenticatedUser("email@mock.com"); + + histogram_tester_.ExpectUniqueSample( + kAuthenticatedLaunchUserEventMetricsName, + AuthenticatedLaunchUserEvent::USED_PROFILE_BLOCKED_WARNING, 1); + signin_util::ResetForceSigninForTesting(); +} + +IN_PROC_BROWSER_TEST_F(UserManagerUIAuthenticatedUserBrowserTest, SupervisedUserBlocked) { Init(); entry_->SetIsSigninRequired(true); diff --git a/chromium/chrome/browser/ui/webui/signin_internals_ui.cc b/chromium/chrome/browser/ui/webui/signin_internals_ui.cc index 011dc70c605..84739294f39 100644 --- a/chromium/chrome/browser/ui/webui/signin_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/signin_internals_ui.cc @@ -18,13 +18,15 @@ #include "components/signin/public/identity_manager/identity_manager.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" namespace { content::WebUIDataSource* CreateSignInInternalsHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUISignInInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->UseStringsJs(); diff --git a/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc b/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc index 24cecc6a0dd..498f2d0958a 100644 --- a/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/snippets_internals/snippets_internals_ui.cc @@ -16,6 +16,7 @@ #include "chrome/grit/dev_ui_browser_resources.h" #include "content/public/browser/web_ui_data_source.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #if defined(OS_ANDROID) #include "chrome/browser/flags/android/chrome_feature_list.h" @@ -25,7 +26,8 @@ SnippetsInternalsUI::SnippetsInternalsUI(content::WebUI* web_ui) : ui::MojoWebUIController(web_ui) { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUISnippetsInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->AddResourcePath("snippets_internals.css", IDR_SNIPPETS_INTERNALS_CSS); source->AddResourcePath("snippets_internals.js", IDR_SNIPPETS_INTERNALS_JS); diff --git a/chromium/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc b/chromium/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc index 0811f8b6987..8b2dad324c4 100644 --- a/chromium/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc +++ b/chromium/chrome/browser/ui/webui/supervised_user_internals_message_handler.cc @@ -28,6 +28,7 @@ #include "components/url_formatter/url_fixer.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" using content::BrowserThread; @@ -181,12 +182,23 @@ void SupervisedUserInternalsMessageHandler::HandleTryURL( return; SupervisedUserURLFilter* filter = GetSupervisedUserService()->GetURLFilter(); - std::map<std::string, base::string16> whitelists = + + content::WebContents* web_contents = + web_ui() ? web_ui()->GetWebContents() : nullptr; + bool skip_manual_parent_filter = false; + if (web_contents) { + skip_manual_parent_filter = + filter->ShouldSkipParentManualAllowlistFiltering( + web_contents->GetOutermostWebContents()); + } + + std::map<std::string, base::string16> allowlists = filter->GetMatchingWhitelistTitles(url); filter->GetFilteringBehaviorForURLWithAsyncChecks( url, base::BindOnce(&SupervisedUserInternalsMessageHandler::OnTryURLResult, - weak_factory_.GetWeakPtr(), whitelists)); + weak_factory_.GetWeakPtr(), allowlists), + skip_manual_parent_filter); } void SupervisedUserInternalsMessageHandler::SendBasicInfo() { diff --git a/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc b/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc index 33484a1287b..193582046bb 100644 --- a/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/supervised_user_internals_ui.cc @@ -12,13 +12,15 @@ #include "chrome/grit/dev_ui_browser_resources.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" namespace { content::WebUIDataSource* CreateSupervisedUserInternalsHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create( chrome::kChromeUISupervisedUserInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->AddResourcePath("supervised_user_internals.js", diff --git a/chromium/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc b/chromium/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc index 050b6031de3..38eddc39498 100644 --- a/chromium/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc +++ b/chromium/chrome/browser/ui/webui/sync_file_system_internals/file_metadata_handler.cc @@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/logging.h" #include "base/values.h" #include "chrome/browser/apps/platform_apps/api/sync_file_system/sync_file_system_api_helpers.h" #include "chrome/browser/profiles/profile.h" diff --git a/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js b/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js index a2abe32d002..2be5fd412b0 100644 --- a/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js +++ b/chromium/chrome/browser/ui/webui/sync_internals_browsertest.js @@ -243,7 +243,13 @@ GEN('#if defined(OS_CHROMEOS)'); // Sync should be disabled if there was no primary account set. TEST_F('SyncInternalsWebUITest', 'SyncDisabledByDefaultChromeOS', function() { expectTrue(this.hasInDetails(true, 'Transport State', 'Disabled')); - expectTrue(this.hasInDetails(true, 'Disable Reasons', 'Not signed in')); + // We don't check 'Disable Reasons' here because the string depends on the + // flag SplitSettingsSync. There's not a good way to check a C++ flag value + // in the middle of a JS test, nor is there a simple way to enable or disable + // platform-specific flags in a cross-platform JS test suite. + // TODO(crbug.com/1087165): When SplitSettingsSync is the default, delete this + // test and use SyncInternalsWebUITest.SyncDisabledByDefault on all + // platforms. expectTrue(this.hasInDetails(true, 'Username', '')); }); diff --git a/chromium/chrome/browser/ui/webui/sync_internals_ui.cc b/chromium/chrome/browser/ui/webui/sync_internals_ui.cc index 89dd520d430..ac5b655e00f 100644 --- a/chromium/chrome/browser/ui/webui/sync_internals_ui.cc +++ b/chromium/chrome/browser/ui/webui/sync_internals_ui.cc @@ -14,13 +14,15 @@ #include "components/sync/driver/about_sync_util.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" namespace { content::WebUIDataSource* CreateSyncInternalsHTMLSource() { content::WebUIDataSource* source = content::WebUIDataSource::Create(chrome::kChromeUISyncInternalsHost); - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); source->UseStringsJs(); @@ -65,4 +67,3 @@ SyncInternalsUI::SyncInternalsUI(content::WebUI* web_ui) } SyncInternalsUI::~SyncInternalsUI() {} - diff --git a/chromium/chrome/browser/ui/webui/tab_search/BUILD.gn b/chromium/chrome/browser/ui/webui/tab_search/BUILD.gn new file mode 100644 index 00000000000..092303f6942 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/BUILD.gn @@ -0,0 +1,9 @@ +# Copyright 2020 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("mojo_bindings") { + sources = [ "tab_search.mojom" ] +} diff --git a/chromium/chrome/browser/ui/webui/tab_search/OWNERS b/chromium/chrome/browser/ui/webui/tab_search/OWNERS new file mode 100644 index 00000000000..6716085b93d --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/OWNERS @@ -0,0 +1,7 @@ +robliao@chromium.org +tluk@chromium.org + +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS + +# COMPONENT: UI>Browser>TabSearch diff --git a/chromium/chrome/browser/ui/webui/tab_search/tab_search.mojom b/chromium/chrome/browser/ui/webui/tab_search/tab_search.mojom new file mode 100644 index 00000000000..26a6d8c5165 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/tab_search.mojom @@ -0,0 +1,70 @@ +// Copyright 2020 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 tab_search.mojom; + +// Collection of WindowTabs of a profile. +struct ProfileTabs { + array<WindowTabs> windows; +}; + +// Collection of Tab of a window. +struct WindowTabs { + bool active; + array<Tab> tabs; +}; + +// Information about an existing open tab. +struct Tab { + bool active; + int32 index; + int32 tab_id; + string? group_id; + bool pinned; + string title; + string url; + string? fav_icon_url; + bool is_default_favicon; + bool show_icon; +}; + +// Collection of tab groups. +struct TabGroups { + map<string, TabGroup> groups; +}; + +// Information about a tab group. +struct TabGroup { + string color; + string text_color; + string title; +}; + +// Information about switching to a tab. +struct SwitchToTabInfo { + int32 tab_id; +}; + +// Used by the WebUI page to bootstrap bidirectional communication. +interface PageHandlerFactory { + // The WebUI calls this method when the page is first initialized. + CreatePageHandler(pending_remote<Page> page, + pending_receiver<PageHandler> handler); +}; + +// Browser-side handler for requests from WebUI page. +interface PageHandler { + // Get tabs grouped by windows for the current profile + GetProfileTabs() => (ProfileTabs profile_tabs); + + // Get tab groups for the current profile. + GetTabGroups() => (TabGroups tab_groups); + + // Switch to a specific tab. + SwitchToTab(SwitchToTabInfo switch_to_tab_info); +}; + +// WebUI-side handler for requests from the browser. +interface Page { +}; diff --git a/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc new file mode 100644 index 00000000000..23e90c900b6 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc @@ -0,0 +1,115 @@ +// Copyright 2020 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/tab_search/tab_search_page_handler.h" + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/base64.h" +#include "chrome/browser/extensions/extension_tab_util.h" +#include "chrome/browser/favicon/favicon_utils.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_finder.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_renderer_data.h" +#include "chrome/browser/ui/webui/util/image_util.h" + +TabSearchPageHandler::TabSearchPageHandler( + mojo::PendingReceiver<tab_search::mojom::PageHandler> receiver, + mojo::PendingRemote<tab_search::mojom::Page> page, + content::WebUI* web_ui) + : receiver_(this, std::move(receiver)), + page_(std::move(page)), + browser_(chrome::FindLastActive()), + web_ui_(web_ui) { + DCHECK(browser_); +} + +TabSearchPageHandler::~TabSearchPageHandler() = default; + +void TabSearchPageHandler::GetProfileTabs(GetProfileTabsCallback callback) { + auto profile_tabs = tab_search::mojom::ProfileTabs::New(); + Profile* profile = browser_->profile(); + for (auto* browser : *BrowserList::GetInstance()) { + if (browser->profile() != profile) { + continue; + } + TabStripModel* tab_strip_model = browser->tab_strip_model(); + auto window_tabs = tab_search::mojom::WindowTabs::New(); + window_tabs->active = (browser == browser_); + for (int i = 0; i < tab_strip_model->count(); ++i) { + window_tabs->tabs.push_back( + GetTabData(browser, tab_strip_model->GetWebContentsAt(i), i)); + } + profile_tabs->windows.push_back(std::move(window_tabs)); + } + + std::move(callback).Run(std::move(profile_tabs)); +} + +void TabSearchPageHandler::GetTabGroups(GetTabGroupsCallback callback) { + // TODO(crbug.com/1096120): Implement this when we can get theme color from + // browser + NOTIMPLEMENTED(); +} + +void TabSearchPageHandler::SwitchToTab( + tab_search::mojom::SwitchToTabInfoPtr switch_to_tab_info) { + Profile* profile = browser_->profile(); + for (auto* browser : *BrowserList::GetInstance()) { + if (browser->profile() != profile) { + continue; + } + TabStripModel* tab_strip_model = browser->tab_strip_model(); + for (int index = 0; index < tab_strip_model->count(); ++index) { + content::WebContents* contents = tab_strip_model->GetWebContentsAt(index); + if (extensions::ExtensionTabUtil::GetTabId(contents) == + switch_to_tab_info->tab_id) { + tab_strip_model->ActivateTabAt(index); + browser->window()->Activate(); + return; + } + } + } +} + +tab_search::mojom::TabPtr TabSearchPageHandler::GetTabData( + Browser* browser, + content::WebContents* contents, + int index) { + auto tab_data = tab_search::mojom::Tab::New(); + + tab_data->active = browser->tab_strip_model()->active_index() == index; + tab_data->tab_id = extensions::ExtensionTabUtil::GetTabId(contents); + tab_data->index = index; + + const base::Optional<tab_groups::TabGroupId> group_id = + browser->tab_strip_model()->GetTabGroupForTab(index); + if (group_id.has_value()) { + tab_data->group_id = group_id.value().ToString(); + } + + TabRendererData tab_renderer_data = + TabRendererData::FromTabInModel(browser->tab_strip_model(), index); + tab_data->pinned = tab_renderer_data.pinned; + tab_data->title = base::UTF16ToUTF8(tab_renderer_data.title); + tab_data->url = tab_renderer_data.visible_url.GetContent(); + + if (tab_renderer_data.favicon.isNull()) { + tab_data->is_default_favicon = true; + } else { + tab_data->fav_icon_url = webui::EncodePNGAndMakeDataURI( + tab_renderer_data.favicon, web_ui_->GetDeviceScaleFactor()); + tab_data->is_default_favicon = + tab_renderer_data.favicon.BackedBySameObjectAs( + favicon::GetDefaultFavicon().AsImageSkia()); + } + tab_data->show_icon = tab_renderer_data.show_icon; + + return tab_data; +} diff --git a/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h b/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h new file mode 100644 index 00000000000..6c8ff9cb68f --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler.h @@ -0,0 +1,47 @@ +// Copyright 2020 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_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_ + +#include "chrome/browser/ui/tabs/tab_group.h" +#include "chrome/browser/ui/tabs/tab_group_model.h" +#include "chrome/browser/ui/tabs/tab_group_theme.h" +#include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" +#include "ui/webui/mojo_web_ui_controller.h" + +class Browser; + +class TabSearchPageHandler : public tab_search::mojom::PageHandler { + public: + TabSearchPageHandler( + mojo::PendingReceiver<tab_search::mojom::PageHandler> receiver, + mojo::PendingRemote<tab_search::mojom::Page> page, + content::WebUI* web_ui); + TabSearchPageHandler(const TabSearchPageHandler&) = delete; + TabSearchPageHandler& operator=(const TabSearchPageHandler&) = delete; + ~TabSearchPageHandler() override; + + // tab_search::mojom::PageHandler: + void GetProfileTabs(GetProfileTabsCallback callback) override; + void GetTabGroups(GetTabGroupsCallback callback) override; + void SwitchToTab( + tab_search::mojom::SwitchToTabInfoPtr switch_to_tab_info) override; + + private: + tab_search::mojom::TabPtr GetTabData(Browser* browser, + content::WebContents* contents, + int index); + + mojo::Receiver<tab_search::mojom::PageHandler> receiver_; + mojo::Remote<tab_search::mojom::Page> page_; + Browser* const browser_; + content::WebUI* const web_ui_; +}; + +#endif // CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_PAGE_HANDLER_H_ diff --git a/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc b/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc new file mode 100644 index 00000000000..7d884291ffd --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc @@ -0,0 +1,203 @@ +// Copyright 2020 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/tab_search/tab_search_page_handler.h" + +#include "base/test/bind_test_util.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_list.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "chrome/test/base/test_browser_window.h" +#include "content/public/test/test_web_ui.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/gfx/color_utils.h" + +namespace { + +constexpr char kTabUrl1[] = "http://foo/1"; +constexpr char kTabUrl2[] = "http://foo/2"; +constexpr char kTabUrl3[] = "http://foo/3"; +constexpr char kTabUrl4[] = "http://foo/4"; + +constexpr char kTabUrlName1[] = "foo/1"; +constexpr char kTabUrlName2[] = "foo/2"; +constexpr char kTabUrlName3[] = "foo/3"; + +constexpr char kTabName1[] = "Tab 1"; +constexpr char kTabName2[] = "Tab 2"; +constexpr char kTabName3[] = "Tab 3"; +constexpr char kTabName4[] = "Tab 4"; + +class MockPage : public tab_search::mojom::Page { + public: + MockPage() = default; + ~MockPage() override = default; + + mojo::PendingRemote<tab_search::mojom::Page> BindAndGetRemote() { + DCHECK(!receiver_.is_bound()); + return receiver_.BindNewPipeAndPassRemote(); + } + mojo::Receiver<tab_search::mojom::Page> receiver_{this}; +}; + +void ExpectNewTab(const tab_search::mojom::Tab* tab, + const std::string url, + const std::string title, + int index) { + EXPECT_EQ(index, tab->index); + EXPECT_LT(0, tab->tab_id); + EXPECT_FALSE(tab->group_id.has_value()); + EXPECT_FALSE(tab->pinned); + EXPECT_EQ(title, tab->title); + EXPECT_EQ(url, tab->url); + EXPECT_TRUE(tab->fav_icon_url.has_value()); + EXPECT_TRUE(tab->is_default_favicon); + EXPECT_TRUE(tab->show_icon); +} + +void ExpectProfileTabs(tab_search::mojom::ProfileTabs* profile_tabs) { + ASSERT_EQ(2u, profile_tabs->windows.size()); + auto* window1 = profile_tabs->windows[0].get(); + ASSERT_EQ(2u, window1->tabs.size()); + ASSERT_FALSE(window1->tabs[0]->active); + ASSERT_TRUE(window1->tabs[1]->active); + auto* window2 = profile_tabs->windows[1].get(); + ASSERT_EQ(1u, window2->tabs.size()); + ASSERT_TRUE(window2->tabs[0]->active); +} + +class TestTabSearchPageHandler : public TabSearchPageHandler { + public: + TestTabSearchPageHandler(mojo::PendingRemote<tab_search::mojom::Page> page, + content::WebUI* web_ui) + : TabSearchPageHandler( + mojo::PendingReceiver<tab_search::mojom::PageHandler>(), + std::move(page), + web_ui) {} +}; + +class TabSearchPageHandlerTest : public BrowserWithTestWindowTest { + public: + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + browser2_ = CreateTestBrowser(false, false); + browser3_ = CreateTestBrowser(true, false); + BrowserList::SetLastActive(browser1()); + handler_ = std::make_unique<TestTabSearchPageHandler>( + page_.BindAndGetRemote(), web_ui()); + } + + void TearDown() override { + browser1()->tab_strip_model()->CloseAllTabs(); + browser2()->tab_strip_model()->CloseAllTabs(); + browser3()->tab_strip_model()->CloseAllTabs(); + browser2_.reset(); + browser3_.reset(); + BrowserWithTestWindowTest::TearDown(); + } + + content::TestWebUI* web_ui() { return &web_ui_; } + Browser* browser1() { return browser(); } + Browser* browser2() { return browser2_.get(); } + Browser* browser3() { return browser3_.get(); } + TestTabSearchPageHandler* handler() { return handler_.get(); } + + protected: + void AddTabWithTitle(Browser* browser, + const GURL url, + const std::string title) { + AddTab(browser, url); + NavigateAndCommitActiveTabWithTitle(browser, url, + base::ASCIIToUTF16(title)); + } + + private: + std::unique_ptr<Browser> CreateTestBrowser(bool incognito, bool popup) { + auto window = std::make_unique<TestBrowserWindow>(); + Profile* profile = incognito ? browser()->profile()->GetPrimaryOTRProfile() + : browser()->profile(); + Browser::Type type = popup ? Browser::TYPE_POPUP : Browser::TYPE_NORMAL; + + std::unique_ptr<Browser> browser = + CreateBrowser(profile, type, false, window.get()); + BrowserList::SetLastActive(browser.get()); + new TestBrowserWindowOwner(window.release()); + return browser; + } + + testing::StrictMock<MockPage> page_; + content::TestWebUI web_ui_; + std::unique_ptr<Browser> browser2_; + std::unique_ptr<Browser> browser3_; + std::unique_ptr<TestTabSearchPageHandler> handler_; +}; + +TEST_F(TabSearchPageHandlerTest, GetTabs) { + // Browser3 is in incognito mode, thus its tab should not be accessible. + AddTabWithTitle(browser3(), GURL(kTabUrl4), kTabName4); + AddTabWithTitle(browser2(), GURL(kTabUrl3), kTabName3); + AddTabWithTitle(browser1(), GURL(kTabUrl2), kTabName2); + AddTabWithTitle(browser1(), GURL(kTabUrl1), kTabName1); + + int32_t tab_id2 = 0; + int32_t tab_id3 = 0; + + // Get Tabs. + tab_search::mojom::PageHandler::GetProfileTabsCallback callback1 = + base::BindLambdaForTesting( + [&](tab_search::mojom::ProfileTabsPtr profile_tabs) { + ASSERT_EQ(2u, profile_tabs->windows.size()); + auto* window1 = profile_tabs->windows[0].get(); + ASSERT_TRUE(window1->active); + ASSERT_EQ(2u, window1->tabs.size()); + + auto* tab1 = window1->tabs[0].get(); + ExpectNewTab(tab1, kTabUrlName1, kTabName1, 0); + ASSERT_TRUE(tab1->active); + + auto* tab2 = window1->tabs[1].get(); + ExpectNewTab(tab2, kTabUrlName2, kTabName2, 1); + ASSERT_FALSE(tab2->active); + + auto* window2 = profile_tabs->windows[1].get(); + ASSERT_FALSE(window2->active); + ASSERT_EQ(1u, window2->tabs.size()); + + auto* tab3 = window2->tabs[0].get(); + ExpectNewTab(tab3, kTabUrlName3, kTabName3, 0); + ASSERT_TRUE(tab3->active); + + tab_id2 = tab2->tab_id; + tab_id3 = tab3->tab_id; + }); + handler()->GetProfileTabs(std::move(callback1)); + + // Switch to 2nd tab. + auto switch_to_tab_info = tab_search::mojom::SwitchToTabInfo::New(); + switch_to_tab_info->tab_id = tab_id2; + handler()->SwitchToTab(std::move(switch_to_tab_info)); + + // Get Tabs again to verify tab switch. + tab_search::mojom::PageHandler::GetProfileTabsCallback callback2 = + base::BindLambdaForTesting( + [&](tab_search::mojom::ProfileTabsPtr profile_tabs) { + ExpectProfileTabs(profile_tabs.get()); + }); + handler()->GetProfileTabs(std::move(callback2)); + + // Switch to 3rd tab. + switch_to_tab_info = tab_search::mojom::SwitchToTabInfo::New(); + switch_to_tab_info->tab_id = tab_id3; + handler()->SwitchToTab(std::move(switch_to_tab_info)); + + // Get Tabs again to verify tab switch. + tab_search::mojom::PageHandler::GetProfileTabsCallback callback3 = + base::BindLambdaForTesting( + [&](tab_search::mojom::ProfileTabsPtr profile_tabs) { + ExpectProfileTabs(profile_tabs.get()); + }); + handler()->GetProfileTabs(std::move(callback3)); +} + +} // namespace diff --git a/chromium/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chromium/chrome/browser/ui/webui/tab_search/tab_search_ui.cc new file mode 100644 index 00000000000..812960da8ec --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/tab_search_ui.cc @@ -0,0 +1,38 @@ +// Copyright 2020 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/tab_search/tab_search_ui.h" + +#include "chrome/browser/ui/webui/tab_search/tab_search_page_handler.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/common/webui_url_constants.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" + +TabSearchUI::TabSearchUI(content::WebUI* web_ui) + : ui::MojoWebUIController(web_ui) { + content::WebUIDataSource* source = + content::WebUIDataSource::Create(chrome::kChromeUITabSearchHost); + content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), + source); +} + +TabSearchUI::~TabSearchUI() = default; + +WEB_UI_CONTROLLER_TYPE_IMPL(TabSearchUI) + +void TabSearchUI::BindInterface( + mojo::PendingReceiver<tab_search::mojom::PageHandlerFactory> receiver) { + page_factory_receiver_.reset(); + page_factory_receiver_.Bind(std::move(receiver)); +} + +void TabSearchUI::CreatePageHandler( + mojo::PendingRemote<tab_search::mojom::Page> page, + mojo::PendingReceiver<tab_search::mojom::PageHandler> receiver) { + DCHECK(page); + page_handler_ = std::make_unique<TabSearchPageHandler>( + std::move(receiver), std::move(page), web_ui()); +} diff --git a/chromium/chrome/browser/ui/webui/tab_search/tab_search_ui.h b/chromium/chrome/browser/ui/webui/tab_search/tab_search_ui.h new file mode 100644 index 00000000000..ba03a58edeb --- /dev/null +++ b/chromium/chrome/browser/ui/webui/tab_search/tab_search_ui.h @@ -0,0 +1,52 @@ +// Copyright 2020 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_TAB_SEARCH_TAB_SEARCH_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_UI_H_ + +#include <memory> + +#include "base/macros.h" +#include "chrome/browser/ui/webui/tab_search/tab_search.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "ui/webui/mojo_web_ui_controller.h" + +class Browser; +class TabSearchUIEmbedder; +class TabSearchPageHandler; + +class TabSearchUI : public ui::MojoWebUIController, + public tab_search::mojom::PageHandlerFactory { + public: + explicit TabSearchUI(content::WebUI* web_ui); + TabSearchUI(const TabSearchUI&) = delete; + TabSearchUI& operator=(const TabSearchUI&) = delete; + ~TabSearchUI() override; + + // Initialize TabSearchUI by passing in the current browser and the + // current embedder, the WebUI won't work until this is called. + void Initialize(Browser* browser, TabSearchUIEmbedder* embedder); + + // Instantiates the implementor of the mojom::PageHandlerFactory mojo + // interface passing the pending receiver that will be internally bound. + void BindInterface( + mojo::PendingReceiver<tab_search::mojom::PageHandlerFactory> receiver); + + private: + // tab_search::mojom::PageHandlerFactory + void CreatePageHandler( + mojo::PendingRemote<tab_search::mojom::Page> page, + mojo::PendingReceiver<tab_search::mojom::PageHandler> receiver) override; + + std::unique_ptr<TabSearchPageHandler> page_handler_; + + mojo::Receiver<tab_search::mojom::PageHandlerFactory> page_factory_receiver_{ + this}; + + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +#endif // CHROME_BROWSER_UI_WEBUI_TAB_SEARCH_TAB_SEARCH_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc index 6c8774f3bb4..52033f6f5bb 100644 --- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc +++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc @@ -5,7 +5,6 @@ #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.h" #include <memory> -#include "base/base64.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/optional.h" @@ -28,12 +27,13 @@ #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_embedder.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_util.h" +#include "chrome/browser/ui/webui/util/image_util.h" #include "chrome/grit/generated_resources.h" #include "components/tab_groups/tab_group_color.h" #include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" -#include "third_party/skia/include/core/SkStream.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/models/list_selection_model.h" #include "ui/base/models/simple_menu_model.h" #include "ui/base/theme_provider.h" #include "ui/gfx/color_utils.h" @@ -71,48 +71,6 @@ std::string ConvertAlertStateToString(TabAlertState alert_state) { } } -// Writes bytes to a std::vector that can be fetched. This is used to record the -// output of skia image encoding. -class BufferWStream : public SkWStream { - public: - BufferWStream() = default; - ~BufferWStream() override = default; - - // Returns the output buffer by moving. - std::vector<unsigned char> GetBuffer() { return std::move(result_); } - - // SkWStream: - bool write(const void* buffer, size_t size) override { - const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer); - result_.insert(result_.end(), bytes, bytes + size); - return true; - } - - size_t bytesWritten() const override { return result_.size(); } - - private: - std::vector<unsigned char> result_; -}; - -std::string MakeDataURIForImage(base::span<const uint8_t> image_data, - base::StringPiece mime_subtype) { - std::string result = "data:image/"; - result.append(mime_subtype.begin(), mime_subtype.end()); - result += ";base64,"; - result += base::Base64Encode(image_data); - return result; -} - -std::string EncodePNGAndMakeDataURI(gfx::ImageSkia image, float scale_factor) { - const SkBitmap& bitmap = image.GetRepresentation(scale_factor).GetBitmap(); - BufferWStream stream; - const bool encoding_succeeded = - SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100); - DCHECK(encoding_succeeded); - return MakeDataURIForImage( - base::as_bytes(base::make_span(stream.GetBuffer())), "png"); -} - class WebUIBackgroundMenuModel : public ui::SimpleMenuModel { public: explicit WebUIBackgroundMenuModel(ui::SimpleMenuModel::Delegate* delegate) @@ -297,8 +255,6 @@ void TabStripUIHandler::OnTabStripModelChanged( case TabStripModelChange::kMoved: { auto* move = change.GetMove(); - // TODO(johntlee): Investigate if this is still needed, when - // TabGroupChange::kMoved exists. base::Optional<tab_groups::TabGroupId> tab_group_id = tab_strip_model->GetTabGroupForTab(move->to_index); if (tab_group_id.has_value()) { @@ -309,16 +265,9 @@ void TabStripUIHandler::OnTabStripModelChanged( if (tabs_in_group == selection.new_model.selected_indices()) { // If the selection includes all the tabs within the changed tab's // group, it is an indication that the entire group is being moved. - // To prevent sending multiple events for the same batch move, fire a - // separate single tab-group-moved event once all tabs have been - // moved. All tabs have moved only after all the indices in the group - // are in the correct continuous order. - if (tabs_in_group.back() - tabs_in_group.front() + 1 == - static_cast<int>(tabs_in_group.size())) { - FireWebUIListener("tab-group-moved", - base::Value(tab_group_id.value().ToString()), - base::Value(tabs_in_group[0])); - } + // To prevent sending multiple events for each tab in the group, + // ignore these tabs moving as entire group moves will be handled by + // TabGroupChange::kMoved. break; } } @@ -326,7 +275,8 @@ void TabStripUIHandler::OnTabStripModelChanged( FireWebUIListener( "tab-moved", base::Value(extensions::ExtensionTabUtil::GetTabId(move->contents)), - base::Value(move->to_index)); + base::Value(move->to_index), + base::Value(tab_strip_model->IsTabPinned(move->to_index))); break; } case TabStripModelChange::kReplaced: { @@ -467,7 +417,7 @@ base::DictionaryValue TabStripUIHandler::GetTabData( tab_data.SetString("url", tab_renderer_data.visible_url.GetContent()); if (!tab_renderer_data.favicon.isNull()) { - tab_data.SetString("favIconUrl", EncodePNGAndMakeDataURI( + tab_data.SetString("favIconUrl", webui::EncodePNGAndMakeDataURI( tab_renderer_data.favicon, web_ui()->GetDeviceScaleFactor())); tab_data.SetBoolean("isDefaultFavicon", @@ -662,7 +612,17 @@ void TabStripUIHandler::HandleMoveGroup(const base::ListValue* args) { return; } - // If moving within the same browser, just do a simple move. + // When a group is moved, all the tabs in it need to be selected at the same + // time. This mimics the way the native tab strip works and also allows + // this handler to ignore the events for each individual tab moving. + int active_index = + target_browser->tab_strip_model()->selection_model().active(); + ui::ListSelectionModel group_selection; + group_selection.SetSelectedIndex(group->ListTabs().front()); + group_selection.SetSelectionFromAnchorTo(group->ListTabs().back()); + group_selection.set_active(active_index); + target_browser->tab_strip_model()->SetSelectionFromModel(group_selection); + target_browser->tab_strip_model()->MoveGroupTo(group_id.value(), to_index); return; } @@ -874,7 +834,7 @@ void TabStripUIHandler::HandleThumbnailUpdate( ThumbnailTracker::CompressedThumbnailData image) { // Send base-64 encoded image to JS side. std::string data_uri = - MakeDataURIForImage(base::make_span(image->data), "jpeg"); + webui::MakeDataURIForImage(base::make_span(image->data), "jpeg"); const int tab_id = extensions::ExtensionTabUtil::GetTabId(tab); FireWebUIListener("tab-thumbnail-updated", base::Value(tab_id), diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc index 1e37827a132..34a12411ad9 100644 --- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler_unittest.cc @@ -133,55 +133,6 @@ TEST_F(TabStripUIHandlerTest, GroupStateChangedEvents) { EXPECT_EQ(nullptr, ungrouped_call_data.arg4()); } -TEST_F(TabStripUIHandlerTest, GroupMovedEvents) { - // Create a tab group and a few other tabs to allow the group to move. - AddTab(browser(), GURL("http://foo/1")); - AddTab(browser(), GURL("http://foo/2")); - AddTab(browser(), GURL("http://foo/3")); - AddTab(browser(), GURL("http://foo/4")); - tab_groups::TabGroupId expected_group_id = - browser()->tab_strip_model()->AddToNewGroup({0, 1}); - - // Select all the tabs in the group. - ui::ListSelectionModel selection; - selection.AddIndexToSelection(0); - selection.AddIndexToSelection(1); - selection.set_active(0); - browser()->tab_strip_model()->SetSelectionFromModel(selection); - - web_ui()->ClearTrackedCalls(); - - // Move the selected tabs to later in the tab strip. This should result in - // a single event that is fired to indicate the entire group has moved. - int expected_index = 2; - browser()->tab_strip_model()->MoveSelectedTabsTo(expected_index); - - EXPECT_EQ(1U, web_ui()->call_data().size()); - - const content::TestWebUI::CallData& call_data = *web_ui()->call_data().back(); - EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); - EXPECT_EQ("tab-group-moved", call_data.arg1()->GetString()); - EXPECT_EQ(expected_group_id.ToString(), call_data.arg2()->GetString()); - EXPECT_EQ(expected_index, call_data.arg3()->GetInt()); - - web_ui()->ClearTrackedCalls(); - - // Move the selected tabs to earlier in the tab strip. This should also - // result in a single event that is fired to indicate the entire group has - // moved. - expected_index = 1; - browser()->tab_strip_model()->MoveSelectedTabsTo(expected_index); - - EXPECT_EQ(1U, web_ui()->call_data().size()); - - const content::TestWebUI::CallData& call_data2 = - *web_ui()->call_data().back(); - EXPECT_EQ("cr.webUIListenerCallback", call_data2.function_name()); - EXPECT_EQ("tab-group-moved", call_data2.arg1()->GetString()); - EXPECT_EQ(expected_group_id.ToString(), call_data2.arg2()->GetString()); - EXPECT_EQ(expected_index, call_data2.arg3()->GetInt()); -} - TEST_F(TabStripUIHandlerTest, GetGroupVisualData) { AddTab(browser(), GURL("http://foo/1")); AddTab(browser(), GURL("http://foo/2")); @@ -269,6 +220,7 @@ TEST_F(TabStripUIHandlerTest, MoveGroup) { AddTab(browser(), GURL("http://foo/2")); tab_groups::TabGroupId group_id = browser()->tab_strip_model()->AddToNewGroup({0}); + web_ui()->ClearTrackedCalls(); // Move the group to index 1. int new_index = 1; @@ -284,6 +236,13 @@ TEST_F(TabStripUIHandlerTest, MoveGroup) { ->ListTabs(); ASSERT_EQ(new_index, tabs_in_group.front()); ASSERT_EQ(new_index, tabs_in_group.back()); + + EXPECT_EQ(1U, web_ui()->call_data().size()); + const content::TestWebUI::CallData& call_data = + *web_ui()->call_data().front(); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("tab-group-moved", call_data.arg1()->GetString()); + EXPECT_EQ(group_id.ToString(), call_data.arg2()->GetString()); } TEST_F(TabStripUIHandlerTest, MoveGroupAcrossWindows) { @@ -503,6 +462,38 @@ TEST_F(TabStripUIHandlerTest, TabMoved) { EXPECT_EQ("tab-moved", call_data.arg1()->GetString()); EXPECT_EQ(expected_tab_id, call_data.arg2()->GetInt()); EXPECT_EQ(expected_to_index, call_data.arg3()->GetInt()); + EXPECT_EQ(false, call_data.arg4()->GetBool()); +} + +TEST_F(TabStripUIHandlerTest, TabMovedAndPinned) { + AddTab(browser(), GURL("http://foo")); + AddTab(browser(), GURL("http://foo")); + web_ui()->ClearTrackedCalls(); + + int from_index = 1; + int expected_to_index = 0; + int expected_tab_id = extensions::ExtensionTabUtil::GetTabId( + browser()->tab_strip_model()->GetWebContentsAt(from_index)); + + browser()->tab_strip_model()->SetTabPinned(from_index, true); + + const content::TestWebUI::CallData& moved_event = + *web_ui()->call_data().front(); + EXPECT_EQ("cr.webUIListenerCallback", moved_event.function_name()); + EXPECT_EQ("tab-moved", moved_event.arg1()->GetString()); + EXPECT_EQ(expected_tab_id, moved_event.arg2()->GetInt()); + EXPECT_EQ(expected_to_index, moved_event.arg3()->GetInt()); + EXPECT_EQ(true, moved_event.arg4()->GetBool()); + + const content::TestWebUI::CallData& updated_event = + *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", updated_event.function_name()); + EXPECT_EQ("tab-updated", updated_event.arg1()->GetString()); + const base::DictionaryValue* updated_data; + ASSERT_TRUE(updated_event.arg2()->GetAsDictionary(&updated_data)); + bool pinned; + ASSERT_TRUE(updated_data->GetBoolean("pinned", &pinned)); + ASSERT_TRUE(pinned); } TEST_F(TabStripUIHandlerTest, TabReplaced) { diff --git a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h index 356c7162646..66d548f412c 100644 --- a/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h +++ b/chromium/chrome/browser/ui/webui/tab_strip/tab_strip_ui_metrics.h @@ -18,9 +18,12 @@ enum class TabStripUIOpenAction { enum class TabStripUICloseAction { kTapOnTabCounter = 0, - kTapOutsideTabStrip = 1, + // No longer used + // kTapOutsideTabStrip = 1, kTabSelected = 2, - kMaxValue = kTabSelected, + kTapInTabContent = 3, + kOmniboxFocusedOrNewTabOpened = 4, + kMaxValue = kOmniboxFocusedOrNewTabOpened, }; void RecordTabStripUIOpenHistogram(TabStripUIOpenAction action); diff --git a/chromium/chrome/browser/ui/webui/test_data_source.cc b/chromium/chrome/browser/ui/webui/test_data_source.cc index 35e02e89a23..e6ba2efac9c 100644 --- a/chromium/chrome/browser/ui/webui/test_data_source.cc +++ b/chromium/chrome/browser/ui/webui/test_data_source.cc @@ -21,6 +21,7 @@ #include "chrome/common/webui_url_constants.h" #include "content/public/browser/url_data_source.h" #include "content/public/common/url_constants.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" namespace { const char kModuleQuery[] = "module="; @@ -76,12 +77,15 @@ bool TestDataSource::AllowCaching() { return false; } -std::string TestDataSource::GetContentSecurityPolicyScriptSrc() { - return "script-src chrome://* 'self';"; -} +std::string TestDataSource::GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) { + if (directive == network::mojom::CSPDirectiveName::ScriptSrc) { + return "script-src chrome://* 'self';"; + } else if (directive == network::mojom::CSPDirectiveName::WorkerSrc) { + return "worker-src blob: 'self';"; + } -std::string TestDataSource::GetContentSecurityPolicyWorkerSrc() { - return "worker-src blob: 'self';"; + return content::URLDataSource::GetContentSecurityPolicy(directive); } GURL TestDataSource::GetURLForPath(const std::string& path) { diff --git a/chromium/chrome/browser/ui/webui/test_data_source.h b/chromium/chrome/browser/ui/webui/test_data_source.h index 33990d62b4d..5048d07d7d7 100644 --- a/chromium/chrome/browser/ui/webui/test_data_source.h +++ b/chromium/chrome/browser/ui/webui/test_data_source.h @@ -32,9 +32,8 @@ class TestDataSource : public content::URLDataSource { std::string GetSource() override; - std::string GetContentSecurityPolicyScriptSrc() override; - - std::string GetContentSecurityPolicyWorkerSrc() override; + std::string GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) override; GURL GetURLForPath(const std::string& path); diff --git a/chromium/chrome/browser/ui/webui/theme_source.cc b/chromium/chrome/browser/ui/webui/theme_source.cc index 060ba3f5a3a..c9539ab1bdb 100644 --- a/chromium/chrome/browser/ui/webui/theme_source.cc +++ b/chromium/chrome/browser/ui/webui/theme_source.cc @@ -8,7 +8,6 @@ #include "base/memory/ref_counted_memory.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" -#include "base/task/post_task.h" #include "build/branding_buildflags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/resources_util.h" @@ -28,6 +27,7 @@ #include "content/public/browser/url_data_source.h" #include "content/public/common/url_constants.h" #include "net/url_request/url_request.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/layout.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/web_ui_util.h" @@ -222,8 +222,8 @@ void ThemeSource::SendThemeImage( DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // Fetching image data in ResourceBundle should happen on the UI thread. See // crbug.com/449277 - base::PostTaskAndReply( - FROM_HERE, {content::BrowserThread::UI}, + content::GetUIThreadTaskRunner({})->PostTaskAndReply( + FROM_HERE, base::BindOnce(&ProcessResourceOnUiThread, resource_id, scale, data), base::BindOnce(std::move(callback), data)); } @@ -240,3 +240,14 @@ std::string ThemeSource::GetAccessControlAllowOriginForOrigin( return content::URLDataSource::GetAccessControlAllowOriginForOrigin(origin); } + +std::string ThemeSource::GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) { + if (directive == network::mojom::CSPDirectiveName::DefaultSrc && + serve_untrusted_) { + // TODO(https://crbug.com/1085327): Audit and tighten CSP. + return std::string(); + } + + return content::URLDataSource::GetContentSecurityPolicy(directive); +} diff --git a/chromium/chrome/browser/ui/webui/theme_source.h b/chromium/chrome/browser/ui/webui/theme_source.h index aaf58a12cce..fb32e98575a 100644 --- a/chromium/chrome/browser/ui/webui/theme_source.h +++ b/chromium/chrome/browser/ui/webui/theme_source.h @@ -34,6 +34,8 @@ class ThemeSource : public content::URLDataSource { int render_process_id) override; std::string GetAccessControlAllowOriginForOrigin( const std::string& origin) override; + std::string GetContentSecurityPolicy( + network::mojom::CSPDirectiveName directive) override; private: // Fetches and sends the theme bitmap. diff --git a/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc b/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc deleted file mode 100644 index 1eba436b9a3..00000000000 --- a/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.cc +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2018 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/ukm/ukm_internals_ui.h" - -#include <stddef.h> - -#include <memory> -#include <string> -#include <utility> - -#include "base/bind.h" -#include "chrome/browser/browser_process.h" -#include "chrome/common/url_constants.h" -#include "chrome/grit/dev_ui_browser_resources.h" -#include "components/metrics_services_manager/metrics_services_manager.h" -#include "components/ukm/debug/ukm_debug_data_extractor.h" -#include "components/ukm/ukm_service.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/web_contents.h" -#include "content/public/browser/web_ui.h" -#include "content/public/browser/web_ui_data_source.h" -#include "content/public/browser/web_ui_message_handler.h" - -namespace { - -content::WebUIDataSource* CreateUkmHTMLSource() { - content::WebUIDataSource* source = - content::WebUIDataSource::Create(chrome::kChromeUIUkmHost); - - source->AddResourcePath("ukm_internals.js", IDR_UKM_INTERNALS_JS); - source->AddResourcePath("ukm_internals.css", IDR_UKM_INTERNALS_CSS); - source->SetDefaultResource(IDR_UKM_INTERNALS_HTML); - return source; -} - -// This class receives javascript messages from the renderer. -// Note that the WebUI infrastructure runs on the UI thread, therefore all of -// this class's methods are expected to run on the UI thread. -class UkmMessageHandler : public content::WebUIMessageHandler { - public: - explicit UkmMessageHandler(const ukm::UkmService* ukm_service); - ~UkmMessageHandler() override; - - // WebUIMessageHandler: - void RegisterMessages() override; - - private: - void HandleRequestUkmData(const base::ListValue* args); - - const ukm::UkmService* ukm_service_; - - DISALLOW_COPY_AND_ASSIGN(UkmMessageHandler); -}; - -UkmMessageHandler::UkmMessageHandler(const ukm::UkmService* ukm_service) - : ukm_service_(ukm_service) {} - -UkmMessageHandler::~UkmMessageHandler() {} - -void UkmMessageHandler::HandleRequestUkmData(const base::ListValue* args) { - AllowJavascript(); - - // Identifies the callback, used for when resolving. - std::string callback_id; - args->GetString(0, &callback_id); - - base::Value ukm_debug_data = - ukm::debug::UkmDebugDataExtractor::GetStructuredData(ukm_service_); - - ResolveJavascriptCallback(base::Value(callback_id), - std::move(ukm_debug_data)); -} - -void UkmMessageHandler::RegisterMessages() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - // We can use base::Unretained() here, as both the callback and this class are - // owned by UkmInternalsUI. - web_ui()->RegisterMessageCallback( - "requestUkmData", - base::BindRepeating(&UkmMessageHandler::HandleRequestUkmData, - base::Unretained(this))); -} - -} // namespace - -// Changes to this class should be in sync with its iOS equivalent -// ios/chrome/browser/ui/webui/ukm_internals_ui.cc -UkmInternalsUI::UkmInternalsUI(content::WebUI* web_ui) - : content::WebUIController(web_ui) { - ukm::UkmService* ukm_service = - g_browser_process->GetMetricsServicesManager()->GetUkmService(); - web_ui->AddMessageHandler(std::make_unique<UkmMessageHandler>(ukm_service)); - - // Set up the chrome://ukm/ source. - content::BrowserContext* browser_context = - web_ui->GetWebContents()->GetBrowserContext(); - content::WebUIDataSource::Add(browser_context, CreateUkmHTMLSource()); -} diff --git a/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.h b/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.h deleted file mode 100644 index 16055360210..00000000000 --- a/chromium/chrome/browser/ui/webui/ukm/ukm_internals_ui.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2018 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_UKM_UKM_INTERNALS_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_UKM_UKM_INTERNALS_UI_H_ - -#include "base/macros.h" -#include "content/public/browser/web_ui_controller.h" - -// Handles serving the chrome://ukm HTML and JS. -class UkmInternalsUI : public content::WebUIController { - public: - explicit UkmInternalsUI(content::WebUI* web_ui); - - private: - DISALLOW_COPY_AND_ASSIGN(UkmInternalsUI); -}; - -#endif // CHROME_BROWSER_UI_WEBUI_UKM_UKM_INTERNALS_UI_H_ diff --git a/chromium/chrome/browser/ui/webui/util/OWNERS b/chromium/chrome/browser/ui/webui/util/OWNERS new file mode 100644 index 00000000000..13b837bc5f2 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/util/OWNERS @@ -0,0 +1,6 @@ +dpapad@chromium.org +johntlee@chromium.org +robliao@chromium.org +tluk@chromium.org + +# COMPONENT: UI>Browser>WebUI
\ No newline at end of file diff --git a/chromium/chrome/browser/ui/webui/util/image_util.cc b/chromium/chrome/browser/ui/webui/util/image_util.cc new file mode 100644 index 00000000000..f914194ee67 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/util/image_util.cc @@ -0,0 +1,57 @@ +// Copyright (c) 2020 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/util/image_util.h" + +#include "base/base64.h" +#include "third_party/skia/include/core/SkStream.h" +#include "ui/gfx/image/image_skia.h" + +namespace { +// Writes bytes to a std::vector that can be fetched. This is used to record the +// output of skia image encoding. +class BufferWStream : public SkWStream { + public: + BufferWStream() = default; + ~BufferWStream() override = default; + + // Returns the output buffer by moving. + std::vector<unsigned char> GetBuffer() { return std::move(result_); } + + // SkWStream: + bool write(const void* buffer, size_t size) override { + const unsigned char* bytes = reinterpret_cast<const unsigned char*>(buffer); + result_.insert(result_.end(), bytes, bytes + size); + return true; + } + + size_t bytesWritten() const override { return result_.size(); } + + private: + std::vector<unsigned char> result_; +}; +} // namespace + +namespace webui { + +std::string MakeDataURIForImage(base::span<const uint8_t> image_data, + base::StringPiece mime_subtype) { + std::string result = "data:image/"; + result.append(mime_subtype.begin(), mime_subtype.end()); + result += ";base64,"; + result += base::Base64Encode(image_data); + return result; +} + +std::string EncodePNGAndMakeDataURI(gfx::ImageSkia image, float scale_factor) { + const SkBitmap& bitmap = image.GetRepresentation(scale_factor).GetBitmap(); + BufferWStream stream; + const bool encoding_succeeded = + SkEncodeImage(&stream, bitmap, SkEncodedImageFormat::kPNG, 100); + DCHECK(encoding_succeeded); + return MakeDataURIForImage( + base::as_bytes(base::make_span(stream.GetBuffer())), "png"); +} + +} // namespace webui diff --git a/chromium/chrome/browser/ui/webui/util/image_util.h b/chromium/chrome/browser/ui/webui/util/image_util.h new file mode 100644 index 00000000000..fd25a1769eb --- /dev/null +++ b/chromium/chrome/browser/ui/webui/util/image_util.h @@ -0,0 +1,22 @@ +// Copyright 2020 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_UTIL_IMAGE_UTIL_H_ +#define CHROME_BROWSER_UI_WEBUI_UTIL_IMAGE_UTIL_H_ + +#include "base/containers/span.h" +#include "base/strings/string_piece_forward.h" + +namespace gfx { +class ImageSkia; +} // namespace gfx + +namespace webui { +std::string MakeDataURIForImage(base::span<const uint8_t> image_data, + base::StringPiece mime_subtype); + +std::string EncodePNGAndMakeDataURI(gfx::ImageSkia image, float scale_factor); +} // namespace webui + +#endif // CHROME_BROWSER_UI_WEBUI_UTIL_IMAGE_UTIL_H_ diff --git a/chromium/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc b/chromium/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc index 09e80f92cd5..c55cb5a7cce 100644 --- a/chromium/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc +++ b/chromium/chrome/browser/ui/webui/web_dialog_web_contents_delegate_unittest.cc @@ -66,7 +66,8 @@ TEST_F(WebDialogWebContentsDelegateTest, DoNothingMethodsTest) { // None of the following calls should do anything. history::HistoryAddPageArgs should_add_args( GURL(), base::Time::Now(), 0, 0, GURL(), history::RedirectList(), - ui::PAGE_TRANSITION_TYPED, false, history::SOURCE_SYNCED, false, true); + ui::PAGE_TRANSITION_TYPED, false, history::SOURCE_SYNCED, false, true, + false); test_web_contents_delegate_->NavigationStateChanged( nullptr, content::InvalidateTypes(0)); test_web_contents_delegate_->ActivateContents(nullptr); diff --git a/chromium/chrome/browser/ui/webui/webui_util.cc b/chromium/chrome/browser/ui/webui/webui_util.cc index 2398fea5171..4fd3152fbda 100644 --- a/chromium/chrome/browser/ui/webui/webui_util.cc +++ b/chromium/chrome/browser/ui/webui/webui_util.cc @@ -6,6 +6,7 @@ #include "chrome/common/buildflags.h" #include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" #include "ui/base/webui/web_ui_util.h" #include "ui/resources/grit/webui_resources.h" #include "ui/resources/grit/webui_resources_map.h" @@ -15,7 +16,8 @@ namespace webui { namespace { void SetupPolymer3Defaults(content::WebUIDataSource* source) { - source->OverrideContentSecurityPolicyScriptSrc( + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources chrome://test 'self';"); source->UseStringsJs(); source->EnableReplaceI18nInJS(); diff --git a/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc b/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc index e27ea67e305..78991207d00 100644 --- a/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc +++ b/chromium/chrome/browser/ui/webui/welcome/welcome_handler.cc @@ -23,15 +23,11 @@ const char kWelcomeReturningUserUrl[] = "chrome://welcome/returning-user"; WelcomeHandler::WelcomeHandler(content::WebUI* web_ui) : profile_(Profile::FromWebUI(web_ui)), - login_ui_service_(LoginUIServiceFactory::GetForProfile(profile_)), result_(WelcomeResult::DEFAULT), is_redirected_welcome_impression_(false) { - login_ui_service_->AddObserver(this); } WelcomeHandler::~WelcomeHandler() { - login_ui_service_->RemoveObserver(this); - // If this instance is spawned due to being redirected back to welcome page // by the onboarding logic, there's no need to log sign-in metrics again. if (is_redirected_welcome_impression_) { @@ -55,24 +51,9 @@ bool WelcomeHandler::isValidRedirectUrl() { return current_url == kWelcomeReturningUserUrl; } -// Override from LoginUIService::Observer. -void WelcomeHandler::OnSyncConfirmationUIClosed( - LoginUIService::SyncConfirmationUIClosedResult result) { - if (result != LoginUIService::ABORT_SIGNIN) { - result_ = WelcomeResult::SIGNED_IN; - - // When signed in from welcome flow, it's possible to come back to - // chrome://welcome/... after closing sync-confirmation UI. If current URL - // matches such a case, do not navigate away. - if (!is_redirected_welcome_impression_) { - GoToNewTabPage(); - } - } -} - // Handles backend events necessary when user clicks "Sign in." void WelcomeHandler::HandleActivateSignIn(const base::ListValue* args) { - result_ = WelcomeResult::ATTEMPTED; + result_ = WelcomeResult::STARTED_SIGN_IN; base::RecordAction(base::UserMetricsAction("WelcomePage_SignInClicked")); if (IdentityManagerFactory::GetForProfile(profile_)->HasPrimaryAccount()) { @@ -97,14 +78,9 @@ void WelcomeHandler::HandleActivateSignIn(const base::ListValue* args) { } } -// Handles backend events necessary when user clicks "No thanks." +// Handles backend events necessary when user clicks "Get started." void WelcomeHandler::HandleUserDecline(const base::ListValue* args) { - // Set the appropriate decline result, based on whether or not the user - // attempted to sign in. - result_ = (result_ == WelcomeResult::ATTEMPTED) - ? WelcomeResult::ATTEMPTED_DECLINED - : WelcomeResult::DECLINED; - + result_ = WelcomeResult::DECLINED_SIGN_IN; GoToNewTabPage(); } diff --git a/chromium/chrome/browser/ui/webui/welcome/welcome_handler.h b/chromium/chrome/browser/ui/webui/welcome/welcome_handler.h index e34e4b8ac67..430f3790d9c 100644 --- a/chromium/chrome/browser/ui/webui/welcome/welcome_handler.h +++ b/chromium/chrome/browser/ui/webui/welcome/welcome_handler.h @@ -14,16 +14,11 @@ class Profile; class GURL; // Handles actions on Welcome page. -class WelcomeHandler : public content::WebUIMessageHandler, - public LoginUIService::Observer { +class WelcomeHandler : public content::WebUIMessageHandler { public: explicit WelcomeHandler(content::WebUI* web_ui); ~WelcomeHandler() override; - // LoginUIService::Observer: - void OnSyncConfirmationUIClosed( - LoginUIService::SyncConfirmationUIClosedResult result) override; - // content::WebUIMessageHandler: void RegisterMessages() override; @@ -31,17 +26,18 @@ class WelcomeHandler : public content::WebUIMessageHandler, enum WelcomeResult { // User navigated away from page. DEFAULT = 0, - // User clicked the "No Thanks" button. - DECLINED = 1, - // User completed sign-in flow. - SIGNED_IN = 2, - // User attempted sign-in flow, then navigated away. - ATTEMPTED = 3, - // User attempted sign-in flow, then clicked "No Thanks." - ATTEMPTED_DECLINED = 4, - + // User clicked the "Get Started" button. + DECLINED_SIGN_IN = 1, + // DEPRECATED: User completed sign-in flow. + // SIGNED_IN = 2, + // DEPRECATED: User attempted sign-in flow, then navigated away. + // ATTEMPTED = 3, + // DEPRECATED: User attempted sign-in flow, then clicked "No Thanks." + // ATTEMPTED_DECLINED = 4, + // User started the sign-in flow. + STARTED_SIGN_IN = 5, // New results must be added before this line, and should correspond to - // values in tools/metrics/histograms/histograms.xml. + // values in tools/metrics/histograms/enums.xml. WELCOME_RESULT_MAX }; @@ -54,7 +50,6 @@ class WelcomeHandler : public content::WebUIMessageHandler, Browser* GetBrowser(); Profile* profile_; - LoginUIService* login_ui_service_; WelcomeResult result_; // Indicates whether this WelcomeHandler instance is spawned due to users |