diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-24 11:30:15 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-10-30 12:56:19 +0000 |
commit | 6036726eb981b6c4b42047513b9d3f4ac865daac (patch) | |
tree | 673593e70678e7789766d1f732eb51f613a2703b /chromium/chrome/browser/ui/webui/settings | |
parent | 466052c4e7c052268fd931888cd58961da94c586 (diff) |
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser/ui/webui/settings')
39 files changed, 2022 insertions, 439 deletions
diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.cc b/chromium/chrome/browser/ui/webui/settings/about_handler.cc index 6a343a20086..06c2c95e34e 100644 --- a/chromium/chrome/browser/ui/webui/settings/about_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/about_handler.cc @@ -20,7 +20,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/task_scheduler/post_task.h" +#include "base/task/post_task.h" #include "base/time/time.h" #include "base/values.h" #include "build/build_config.h" @@ -30,14 +30,14 @@ #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/chrome_pages.h" -#include "chrome/browser/upgrade_detector.h" +#include "chrome/browser/upgrade_detector/upgrade_detector.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" -#include "components/google/core/browser/google_util.h" +#include "components/google/core/common/google_util.h" #include "components/policy/core/common/policy_namespace.h" #include "components/policy/policy_constants.h" #include "components/strings/grit/components_chromium_strings.h" @@ -284,11 +284,9 @@ AboutHandler* AboutHandler::Create(content::WebUIDataSource* html_source, ? IDS_VERSION_UI_OFFICIAL : IDS_VERSION_UI_UNOFFICIAL), base::UTF8ToUTF16(chrome::GetChannelName()), -#if defined(ARCH_CPU_64_BITS) - l10n_util::GetStringUTF16(IDS_VERSION_UI_64BIT))); -#else - l10n_util::GetStringUTF16(IDS_VERSION_UI_32BIT))); -#endif + l10n_util::GetStringUTF16(sizeof(void*) == 8 + ? IDS_VERSION_UI_64BIT + : IDS_VERSION_UI_32BIT))); html_source->AddString( "aboutProductCopyright", diff --git a/chromium/chrome/browser/ui/webui/settings/about_handler.h b/chromium/chrome/browser/ui/webui/settings/about_handler.h index 4c8ae08a292..6395f3060ef 100644 --- a/chromium/chrome/browser/ui/webui/settings/about_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/about_handler.h @@ -15,7 +15,7 @@ #include "build/build_config.h" #include "chrome/browser/ui/webui/help/version_updater.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" -#include "chrome/browser/upgrade_observer.h" +#include "chrome/browser/upgrade_detector/upgrade_observer.h" #include "components/policy/core/common/policy_service.h" #include "content/public/browser/web_ui_message_handler.h" diff --git a/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc b/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc index dd9e351b7e1..5d5acfd7aed 100644 --- a/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/browser_lifetime_handler.cc @@ -30,9 +30,8 @@ void TriggerTPMFirmwareUpdate( using chromeos::tpm_firmware_update::Mode; // Decide which update mode to use. - // TODO(crbug.com/854576): Re-add Mode::kPreserveDeviceState after fixing - // interrupted update flow issue described in the bug. - for (Mode mode : {Mode::kPowerwash}) { + for (Mode mode : + {Mode::kPreserveDeviceState, Mode::kPowerwash, Mode::kCleanup}) { if (available_modes.count(mode) == 0) { continue; } diff --git a/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc b/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc index 090962aebcf..01225cba2aa 100644 --- a/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/change_password_handler.cc @@ -52,12 +52,11 @@ void ChangePasswordHandler::HandleInitialize(const base::ListValue* args) { } void ChangePasswordHandler::HandleChangePassword(const base::ListValue* args) { - service_->OnUserAction( - web_ui()->GetWebContents(), - safe_browsing::LoginReputationClientRequest::PasswordReuseEvent:: - SIGN_IN_PASSWORD, - safe_browsing::PasswordProtectionService::CHROME_SETTINGS, - safe_browsing::PasswordProtectionService::CHANGE_PASSWORD); + service_->OnUserAction(web_ui()->GetWebContents(), + safe_browsing::LoginReputationClientRequest:: + PasswordReuseEvent::SIGN_IN_PASSWORD, + safe_browsing::WarningUIType::CHROME_SETTINGS, + safe_browsing::WarningAction::CHANGE_PASSWORD); } void ChangePasswordHandler::UpdateChangePasswordCardVisibility() { diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc index 44240697552..56f573121d0 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" @@ -37,6 +38,14 @@ void AccessibilityHandler::RegisterMessages() { "showSwitchAccessSettings", base::BindRepeating(&AccessibilityHandler::HandleShowSwitchAccessSettings, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getStartupSoundEnabled", + base::BindRepeating(&AccessibilityHandler::HandleGetStartupSoundEnabled, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setStartupSoundEnabled", + base::BindRepeating(&AccessibilityHandler::HandleSetStartupSoundEnabled, + base::Unretained(this))); } void AccessibilityHandler::HandleShowChromeVoxSettings( @@ -54,6 +63,22 @@ void AccessibilityHandler::HandleShowSwitchAccessSettings( OpenExtensionOptionsPage(extension_misc::kSwitchAccessExtensionId); } +void AccessibilityHandler::HandleGetStartupSoundEnabled( + const base::ListValue* args) { + AllowJavascript(); + FireWebUIListener( + "startup-sound-enabled-updated", + base::Value(AccessibilityManager::Get()->GetStartupSoundEnabled())); +} + +void AccessibilityHandler::HandleSetStartupSoundEnabled( + const base::ListValue* args) { + DCHECK_EQ(1U, args->GetSize()); + bool enabled; + args->GetBoolean(0, &enabled); + AccessibilityManager::Get()->SetStartupSoundEnabled(enabled); +} + void AccessibilityHandler::OpenExtensionOptionsPage(const char extension_id[]) { const extensions::Extension* extension = extensions::ExtensionRegistry::Get(profile_)->GetExtensionById( diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h index d03c83e2ea6..26f284ad260 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h @@ -37,6 +37,8 @@ class AccessibilityHandler : public ::settings::SettingsPageUIHandler { void HandleShowChromeVoxSettings(const base::ListValue* args); void HandleShowSelectToSpeakSettings(const base::ListValue* args); void HandleShowSwitchAccessSettings(const base::ListValue* args); + void HandleGetStartupSoundEnabled(const base::ListValue* args); + void HandleSetStartupSoundEnabled(const base::ListValue* args); void OpenExtensionOptionsPage(const char extension_id[]); 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 66d0c0748cd..125e1427992 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 @@ -25,11 +25,36 @@ namespace chromeos { namespace settings { +namespace { + +AccountManager::AccountKey GetAccountKeyFromJsCallback( + const base::DictionaryValue* const dictionary) { + const base::Value* id_value = dictionary->FindKey("id"); + DCHECK(id_value); + const std::string id = id_value->GetString(); + DCHECK(!id.empty()); + + const base::Value* account_type_value = dictionary->FindKey("accountType"); + DCHECK(account_type_value); + const int account_type_int = account_type_value->GetInt(); + DCHECK((account_type_int >= + account_manager::AccountType::ACCOUNT_TYPE_UNSPECIFIED) && + (account_type_int <= + account_manager::AccountType::ACCOUNT_TYPE_ACTIVE_DIRECTORY)); + const account_manager::AccountType account_type = + static_cast<account_manager::AccountType>(account_type_int); + + return AccountManager::AccountKey{id, account_type}; +} + +} // namespace + AccountManagerUIHandler::AccountManagerUIHandler( AccountManager* account_manager, AccountTrackerService* account_tracker_service) : account_manager_(account_manager), account_tracker_service_(account_tracker_service), + account_mapper_util_(account_tracker_service_), weak_factory_(this) { DCHECK(account_manager_); DCHECK(account_tracker_service_); @@ -52,6 +77,10 @@ void AccountManagerUIHandler::RegisterMessages() { "addAccount", base::BindRepeating(&AccountManagerUIHandler::HandleAddAccount, weak_factory_.GetWeakPtr())); + web_ui()->RegisterMessageCallback( + "removeAccount", + base::BindRepeating(&AccountManagerUIHandler::HandleRemoveAccount, + weak_factory_.GetWeakPtr())); } void AccountManagerUIHandler::HandleGetAccounts(const base::ListValue* args) { @@ -92,23 +121,25 @@ void AccountManagerUIHandler::GetAccountsCallbackHandler( } base::DictionaryValue account; + account.SetString("id", account_key.id); + account.SetInteger("accountType", account_key.account_type); + account.SetBoolean("isDeviceAccount", false); account.SetString("fullName", account_info.full_name); account.SetString("email", account_info.email); gfx::Image icon = account_tracker_service_->GetAccountImage(account_info.account_id); account.SetString("pic", webui::GetBitmapDataUrl(icon.AsBitmap())); - // |account_key| is a GAIA account and hence |id| is the obfuscated GAIA id - // (see |AccountManager::AccountKey|) - if (account_key.id != device_account_id.GetGaiaId()) { - accounts.GetList().push_back(std::move(account)); - } else { + if (account_mapper_util_.IsEqual(account_key, device_account_id)) { device_account = std::move(account); + } else { + accounts.GetList().push_back(std::move(account)); } } // Device account must show up at the top. if (!device_account.empty()) { + device_account.SetBoolean("isDeviceAccount", true); accounts.GetList().insert(accounts.GetList().begin(), std::move(device_account)); } @@ -121,6 +152,27 @@ void AccountManagerUIHandler::HandleAddAccount(const base::ListValue* args) { InlineLoginHandlerDialogChromeOS::Show(); } +void AccountManagerUIHandler::HandleRemoveAccount(const base::ListValue* args) { + AllowJavascript(); + + const base::DictionaryValue* dictionary = nullptr; + args->GetList()[0].GetAsDictionary(&dictionary); + DCHECK(dictionary); + + const AccountId device_account_id = + ProfileHelper::Get() + ->GetUserByProfile(Profile::FromWebUI(web_ui())) + ->GetAccountId(); + const AccountManager::AccountKey account_key = + GetAccountKeyFromJsCallback(dictionary); + if (account_mapper_util_.IsEqual(account_key, device_account_id)) { + // It should not be possible to remove a device account. + return; + } + + account_manager_->RemoveAccount(account_key); +} + void AccountManagerUIHandler::OnJavascriptAllowed() {} void AccountManagerUIHandler::OnJavascriptDisallowed() {} diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h index 078a51cb189..b1b0b4a6a00 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h @@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "chrome/browser/chromeos/account_mapper_util.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chromeos/account_manager/account_manager.h" #include "components/signin/core/browser/account_tracker_service.h" @@ -51,6 +52,9 @@ class AccountManagerUIHandler : public ::settings::SettingsPageUIHandler, // WebUI "addAccount" message callback. void HandleAddAccount(const base::ListValue* args); + // WebUI "removeAccount" message callback. + void HandleRemoveAccount(const base::ListValue* args); + // |AccountManager::GetAccounts| callback. void GetAccountsCallbackHandler( base::Value callback_id, @@ -65,6 +69,8 @@ class AccountManagerUIHandler : public ::settings::SettingsPageUIHandler, // A non-owning pointer to |AccountTrackerService|. AccountTrackerService* const account_tracker_service_; + chromeos::AccountMapperUtil account_mapper_util_; + base::WeakPtrFactory<AccountManagerUIHandler> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AccountManagerUIHandler); }; 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 3c61e3ba330..cb6f001014e 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 @@ -15,7 +15,7 @@ #include "base/metrics/histogram_macros.h" #include "base/path_service.h" #include "base/strings/string_util.h" -#include "base/task_scheduler/post_task.h" +#include "base/task/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/values.h" #include "chrome/browser/browser_process.h" @@ -322,7 +322,8 @@ void CupsPrintersHandler::HandleUpdateCupsPrinter(const base::ListValue* args) { "kUserNativePrintersAllowed is set to false"; // Used to log UMA metrics. OnAddedPrinterCommon(printer, - PrinterSetupResult::kNativePrintersNotAllowed); + PrinterSetupResult::kNativePrintersNotAllowed, + false); // Used to fire the web UI listener. OnAddPrinterError(PrinterSetupResult::kNativePrintersNotAllowed); return; @@ -495,7 +496,8 @@ void CupsPrintersHandler::HandleAddCupsPrinter(const base::ListValue* args) { "kUserNativePrintersAllowed is set to false"; // Used to log UMA metrics. OnAddedPrinterCommon(*printer, - PrinterSetupResult::kNativePrintersNotAllowed); + PrinterSetupResult::kNativePrintersNotAllowed, + false); // Used to fire the web UI listener. OnAddPrinterError(PrinterSetupResult::kNativePrintersNotAllowed); return; @@ -588,7 +590,8 @@ void CupsPrintersHandler::HandleAddCupsPrinter(const base::ListValue* args) { } void CupsPrintersHandler::OnAddedPrinterCommon(const Printer& printer, - PrinterSetupResult result_code) { + PrinterSetupResult result_code, + bool is_automatic) { UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PrinterSetupResult", result_code, PrinterSetupResult::kMaxValue); switch (result_code) { @@ -596,7 +599,7 @@ void CupsPrintersHandler::OnAddedPrinterCommon(const Printer& printer, UMA_HISTOGRAM_ENUMERATION("Printing.CUPS.PrinterAdded", printer.GetProtocol(), Printer::kProtocolMax); PRINTER_LOG(USER) << "Performing printer setup"; - printers_manager_->PrinterInstalled(printer); + printers_manager_->PrinterInstalled(printer, is_automatic); printers_manager_->UpdateConfiguredPrinter(printer); return; case PrinterSetupResult::kPpdNotFound: @@ -641,7 +644,7 @@ void CupsPrintersHandler::OnAddedPrinterCommon(const Printer& printer, void CupsPrintersHandler::OnAddedDiscoveredPrinter( const Printer& printer, PrinterSetupResult result_code) { - OnAddedPrinterCommon(printer, result_code); + OnAddedPrinterCommon(printer, result_code, true); if (result_code == PrinterSetupResult::kSuccess) { FireWebUIListener("on-add-cups-printer", base::Value(result_code), base::Value(printer.display_name())); @@ -657,7 +660,7 @@ void CupsPrintersHandler::OnAddedSpecifiedPrinter( const Printer& printer, PrinterSetupResult result_code) { PRINTER_LOG(EVENT) << "Add manual printer: " << result_code; - OnAddedPrinterCommon(printer, result_code); + OnAddedPrinterCommon(printer, result_code, false); FireWebUIListener("on-add-cups-printer", base::Value(result_code), base::Value(printer.display_name())); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h index 447eecb1d69..741b87e13db 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h @@ -138,7 +138,8 @@ class CupsPrintersHandler : public ::settings::SettingsPageUIHandler, // Code common between the discovered and manual add printer code paths. void OnAddedPrinterCommon(const Printer& printer, - PrinterSetupResult result_code); + PrinterSetupResult result_code, + bool is_automatic); // CupsPrintersManager::Observer override: void OnPrintersChanged(CupsPrintersManager::PrinterClass printer_class, diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc index a54f351b8b7..be85dd83362 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler.cc @@ -14,18 +14,32 @@ #include "content/public/browser/web_ui.h" #include "content/public/common/service_manager_connection.h" #include "services/service_manager/public/cpp/connector.h" +#include "ui/chromeos/events/event_rewriter_chromeos.h" #include "ui/events/devices/input_device_manager.h" namespace { -bool HasExternalKeyboard() { +struct KeyboardsStateResult { + bool has_external_non_apple_keyboard = false; + bool has_apple_keyboard = false; +}; + +KeyboardsStateResult GetKeyboardsState() { + KeyboardsStateResult result; for (const ui::InputDevice& keyboard : ui::InputDeviceManager::GetInstance()->GetKeyboardDevices()) { - if (keyboard.type == ui::InputDeviceType::INPUT_DEVICE_EXTERNAL) - return true; + const ui::EventRewriterChromeOS::DeviceType type = + ui::EventRewriterChromeOS::GetDeviceType(keyboard); + if (type == ui::EventRewriterChromeOS::kDeviceAppleKeyboard) { + result.has_apple_keyboard = true; + } else if (type == + ui::EventRewriterChromeOS::kDeviceExternalNonAppleKeyboard || + type == ui::EventRewriterChromeOS::kDeviceExternalUnknown) { + result.has_external_non_apple_keyboard = true; + } } - return false; + return result; } } // namespace @@ -115,14 +129,25 @@ void KeyboardHandler::UpdateKeyboards() { void KeyboardHandler::UpdateShowKeys() { // kHasChromeOSKeyboard will be unset on Chromebooks that have standalone Caps // Lock keys. - const base::Value has_caps_lock( - HasExternalKeyboard() || - !base::CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kHasChromeOSKeyboard)); - const base::Value has_diamond_key( + const KeyboardsStateResult keyboards_state = GetKeyboardsState(); + const bool has_caps_lock = keyboards_state.has_apple_keyboard || + keyboards_state.has_external_non_apple_keyboard || + !base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kHasChromeOSKeyboard); + const bool has_diamond_key = base::CommandLine::ForCurrentProcess()->HasSwitch( - chromeos::switches::kHasChromeOSDiamondKey)); - FireWebUIListener(kShowKeysChangedName, has_caps_lock, has_diamond_key); + chromeos::switches::kHasChromeOSDiamondKey); + + base::Value keyboard_params(base::Value::Type::DICTIONARY); + keyboard_params.SetKey("showCapsLock", base::Value(has_caps_lock)); + keyboard_params.SetKey("showDiamondKey", base::Value(has_diamond_key)); + keyboard_params.SetKey( + "showExternalMetaKey", + base::Value(keyboards_state.has_external_non_apple_keyboard)); + keyboard_params.SetKey("showAppleCommandKey", + base::Value(keyboards_state.has_apple_keyboard)); + + FireWebUIListener(kShowKeysChangedName, keyboard_params); } } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc index c875a4480ff..7fd0854ab0a 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_keyboard_handler_unittest.cc @@ -12,7 +12,7 @@ #include "base/observer_list.h" #include "chromeos/chromeos_switches.h" #include "content/public/test/test_web_ui.h" -#include "services/ui/public/cpp/input_devices/input_device_client_test_api.h" +#include "services/ws/public/cpp/input_devices/input_device_client_test_api.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/events/devices/input_device.h" @@ -45,7 +45,9 @@ class KeyboardHandlerTest : public testing::Test { // which keys should be shown. False is returned if the message was invalid or // not found. bool GetLastShowKeysChangedMessage(bool* has_caps_lock_out, - bool* has_diamond_key_out) + bool* has_diamond_key_out, + bool* has_external_meta_key_out, + bool* has_apple_command_key_out) WARN_UNUSED_RESULT { for (auto it = web_ui_.call_data().rbegin(); it != web_ui_.call_data().rend(); ++it) { @@ -56,8 +58,29 @@ class KeyboardHandlerTest : public testing::Test { name != KeyboardHandler::kShowKeysChangedName) { continue; } - return data->arg2()->GetAsBoolean(has_caps_lock_out) && - data->arg3()->GetAsBoolean(has_diamond_key_out); + + if (!data->arg2() || + data->arg2()->type() != base::Value::Type::DICTIONARY) { + return false; + } + + const base::Value* keyboard_params = data->arg2(); + const std::vector<std::pair<std::string, bool*>> path_to_out_param = { + {"showCapsLock", has_caps_lock_out}, + {"showDiamondKey", has_diamond_key_out}, + {"showExternalMetaKey", has_external_meta_key_out}, + {"showAppleCommandKey", has_apple_command_key_out}, + }; + + for (const auto& pair : path_to_out_param) { + auto* found = keyboard_params->FindKey(pair.first); + if (!found) + return false; + + *(pair.second) = found->GetBool(); + } + + return true; } return false; } @@ -66,8 +89,10 @@ class KeyboardHandlerTest : public testing::Test { // is present and false otherwise. A failure is added if a message wasn't // found. bool HasCapsLock() { - bool has_caps_lock = false, has_diamond_key = false; - if (!GetLastShowKeysChangedMessage(&has_caps_lock, &has_diamond_key)) { + bool has_caps_lock = false; + bool ignored = false; + if (!GetLastShowKeysChangedMessage(&has_caps_lock, &ignored, &ignored, + &ignored)) { ADD_FAILURE() << "Didn't get " << KeyboardHandler::kShowKeysChangedName; return false; } @@ -78,15 +103,45 @@ class KeyboardHandlerTest : public testing::Test { // is present and false otherwise. A failure is added if a message wasn't // found. bool HasDiamondKey() { - bool has_caps_lock = false, has_diamond_key = false; - if (!GetLastShowKeysChangedMessage(&has_caps_lock, &has_diamond_key)) { + bool has_diamond_key = false; + bool ignored = false; + if (!GetLastShowKeysChangedMessage(&ignored, &has_diamond_key, &ignored, + &ignored)) { ADD_FAILURE() << "Didn't get " << KeyboardHandler::kShowKeysChangedName; return false; } return has_diamond_key; } - ui::InputDeviceClientTestApi input_device_client_test_api_; + // Returns true if the last keys-changed message reported that a Meta key on + // an external keyboard is present and false otherwise. A failure is added if + // a message wasn't found. + bool HasExternalMetaKey() { + bool has_external_meta = false; + bool ignored = false; + if (!GetLastShowKeysChangedMessage(&ignored, &ignored, &has_external_meta, + &ignored)) { + ADD_FAILURE() << "Didn't get " << KeyboardHandler::kShowKeysChangedName; + return false; + } + return has_external_meta; + } + + // Returns true if the last keys-changed message reported that a Command key + // on an Apple keyboard is present and false otherwise. A failure is added if + // a message wasn't found. + bool HasAppleCommandKey() { + bool has_apple_command_key = false; + bool ignored = false; + if (!GetLastShowKeysChangedMessage(&ignored, &ignored, &ignored, + &has_apple_command_key)) { + ADD_FAILURE() << "Didn't get " << KeyboardHandler::kShowKeysChangedName; + return false; + } + return has_apple_command_key; + } + + ws::InputDeviceClientTestApi input_device_client_test_api_; content::TestWebUI web_ui_; TestKeyboardHandler handler_; KeyboardHandler::TestAPI handler_test_api_; @@ -101,6 +156,8 @@ TEST_F(KeyboardHandlerTest, DefaultKeys) { handler_test_api_.Initialize(); EXPECT_FALSE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); + EXPECT_FALSE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); } TEST_F(KeyboardHandlerTest, NonChromeOSKeyboard) { @@ -109,6 +166,8 @@ TEST_F(KeyboardHandlerTest, NonChromeOSKeyboard) { handler_test_api_.Initialize(); EXPECT_TRUE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); + EXPECT_FALSE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); } TEST_F(KeyboardHandlerTest, ExternalKeyboard) { @@ -120,18 +179,54 @@ TEST_F(KeyboardHandlerTest, ExternalKeyboard) { handler_test_api_.Initialize(); EXPECT_FALSE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); + EXPECT_FALSE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); // Simulate an external keyboard being connected. We should assume there's a - // Caps Lock key now. + // Caps Lock and Meta keys now. input_device_client_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{ {2, ui::INPUT_DEVICE_EXTERNAL, "external keyboard"}}); EXPECT_TRUE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); + EXPECT_TRUE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); + + // Simulate an external Apple keyboard being connected. Now users can remap + // the command key. + input_device_client_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{ + {3, ui::INPUT_DEVICE_EXTERNAL, "Apple Inc. Apple Keyboard"}}); + EXPECT_TRUE(HasCapsLock()); + EXPECT_FALSE(HasDiamondKey()); + EXPECT_FALSE(HasExternalMetaKey()); + EXPECT_TRUE(HasAppleCommandKey()); + + // Simulate two external keyboards (Apple and non-Apple) are connected at the + // same time. + input_device_client_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{ + {2, ui::INPUT_DEVICE_EXTERNAL, "external keyboard"}, + {3, ui::INPUT_DEVICE_EXTERNAL, "Apple Inc. Apple Keyboard"}}); + EXPECT_TRUE(HasCapsLock()); + EXPECT_FALSE(HasDiamondKey()); + EXPECT_TRUE(HasExternalMetaKey()); + EXPECT_TRUE(HasAppleCommandKey()); + + // Some keyboard devices don't report the string "keyboard" as part of their + // device names. Those should also be detcted as external keyboards, and + // should show the capslock and external meta remapping. + // https://crbug.com/834594. + input_device_client_test_api_.SetKeyboardDevices(std::vector<ui::InputDevice>{ + {4, ui::INPUT_DEVICE_EXTERNAL, "Topre Corporation Realforce 87"}}); + EXPECT_TRUE(HasCapsLock()); + EXPECT_FALSE(HasDiamondKey()); + EXPECT_TRUE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); // Disconnect the external keyboard and check that the key goes away. input_device_client_test_api_.SetKeyboardDevices({}); EXPECT_FALSE(HasCapsLock()); EXPECT_FALSE(HasDiamondKey()); + EXPECT_FALSE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); } TEST_F(KeyboardHandlerTest, DiamondKey) { @@ -142,6 +237,8 @@ TEST_F(KeyboardHandlerTest, DiamondKey) { handler_test_api_.Initialize(); EXPECT_FALSE(HasCapsLock()); EXPECT_TRUE(HasDiamondKey()); + EXPECT_FALSE(HasExternalMetaKey()); + EXPECT_FALSE(HasAppleCommandKey()); } } // namespace settings 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 9b221939c81..cf29c548765 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/device_storage_handler.cc @@ -11,7 +11,7 @@ #include "base/files/file_util.h" #include "base/sys_info.h" -#include "base/task_scheduler/post_task.h" +#include "base/task/post_task.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browsing_data/browsing_data_appcache_helper.h" #include "chrome/browser/browsing_data/browsing_data_cache_storage_helper.h" @@ -187,7 +187,7 @@ void StorageHandler::UpdateDownloadsSize() { file_manager::util::GetDownloadsFolderForProfile(profile_); base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND}, + FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, base::Bind(&base::ComputeDirectorySize, downloads_path), base::Bind(&StorageHandler::OnGetDownloadsSize, weak_ptr_factory_.GetWeakPtr())); @@ -363,7 +363,7 @@ void StorageHandler::UpdateOtherUsersSize() { continue; other_users_.push_back(user); DBusThreadManager::Get()->GetCryptohomeClient()->GetAccountDiskUsage( - cryptohome::Identification(user->GetAccountId()), + cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId()), base::BindOnce(&StorageHandler::OnGetOtherUserSize, weak_ptr_factory_.GetWeakPtr())); } diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc index 95fdc49d9a7..7058fb6c087 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.cc @@ -55,13 +55,13 @@ std::unique_ptr<base::DictionaryValue> GetFingerprintsInfo( } // namespace FingerprintHandler::FingerprintHandler(Profile* profile) - : profile_(profile), binding_(this), weak_ptr_factory_(this) { + : profile_(profile), + binding_(this), + session_observer_(this), + weak_ptr_factory_(this) { service_manager::Connector* connector = content::ServiceManagerConnection::GetForProcess()->GetConnector(); connector->BindInterface(device::mojom::kServiceName, &fp_service_); - device::mojom::FingerprintObserverPtr observer; - binding_.Bind(mojo::MakeRequest(&observer)); - fp_service_->AddFingerprintObserver(std::move(observer)); user_id_ = ProfileHelper::Get()->GetUserIdHashFromProfile(profile); } @@ -110,12 +110,16 @@ void FingerprintHandler::RegisterMessages() { void FingerprintHandler::OnJavascriptAllowed() { // SessionManager may not exist in some tests. if (SessionManager::Get()) - SessionManager::Get()->AddObserver(this); + session_observer_.Add(SessionManager::Get()); + + device::mojom::FingerprintObserverPtr observer; + binding_.Bind(mojo::MakeRequest(&observer)); + fp_service_->AddFingerprintObserver(std::move(observer)); } void FingerprintHandler::OnJavascriptDisallowed() { - if (SessionManager::Get()) - SessionManager::Get()->RemoveObserver(this); + session_observer_.RemoveAll(); + binding_.Close(); } void FingerprintHandler::OnRestarted() {} @@ -123,6 +127,10 @@ void FingerprintHandler::OnRestarted() {} void FingerprintHandler::OnEnrollScanDone(uint32_t 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; auto scan_attempt = std::make_unique<base::DictionaryValue>(); scan_attempt->SetInteger("result", scan_result); scan_attempt->SetBoolean("isComplete", enroll_session_complete); @@ -134,6 +142,8 @@ void FingerprintHandler::OnEnrollScanDone(uint32_t scan_result, void FingerprintHandler::OnAuthScanDone( uint32_t scan_result, const base::flat_map<std::string, std::vector<std::string>>& matches) { + VLOG(1) << "Receive fingerprint auth scan result. scan_result=" + << scan_result; if (SessionManager::Get()->session_state() == SessionState::LOCKED) return; @@ -160,7 +170,9 @@ void FingerprintHandler::OnAuthScanDone( FireWebUIListener("on-fingerprint-attempt-received", *fingerprint_attempt); } -void FingerprintHandler::OnSessionFailed() {} +void FingerprintHandler::OnSessionFailed() { + LOG(ERROR) << "Fingerprint session failed."; +} void FingerprintHandler::OnSessionStateChanged() { SessionState state = SessionManager::Get()->session_state(); @@ -214,6 +226,8 @@ void FingerprintHandler::HandleGetNumFingerprints(const base::ListValue* args) { } void FingerprintHandler::HandleStartEnroll(const base::ListValue* args) { + AllowJavascript(); + // Determines what the newly added fingerprint's name should be. for (int i = 1; i <= kMaxAllowedFingerprints; ++i) { std::string fingerprint_name = l10n_util::GetStringFUTF8( @@ -228,6 +242,7 @@ void FingerprintHandler::HandleStartEnroll(const base::ListValue* args) { void FingerprintHandler::HandleCancelCurrentEnroll( const base::ListValue* args) { + AllowJavascript(); fp_service_->CancelCurrentEnrollSession( base::Bind(&FingerprintHandler::OnCancelCurrentEnrollSession, weak_ptr_factory_.GetWeakPtr())); @@ -307,11 +322,13 @@ void FingerprintHandler::OnSetRecordLabel(const std::string& callback_id, void FingerprintHandler::HandleStartAuthentication( const base::ListValue* args) { + AllowJavascript(); fp_service_->StartAuthSession(); } void FingerprintHandler::HandleEndCurrentAuthentication( const base::ListValue* args) { + AllowJavascript(); fp_service_->EndCurrentAuthSession( base::Bind(&FingerprintHandler::OnEndCurrentAuthSession, weak_ptr_factory_.GetWeakPtr())); diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h index d3518f18970..db0c60aec42 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/fingerprint_handler.h @@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_FINGERPRINT_HANDLER_H_ #include "base/containers/flat_map.h" +#include "base/scoped_observer.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/session_manager/core/session_manager_observer.h" #include "mojo/public/cpp/bindings/binding.h" @@ -17,6 +18,10 @@ namespace base { class ListValue; } // namespace base +namespace session_manager { +class SessionManager; +} // namespace session_manager + namespace chromeos { namespace settings { @@ -76,6 +81,9 @@ class FingerprintHandler : public ::settings::SettingsPageUIHandler, device::mojom::FingerprintPtr fp_service_; mojo::Binding<device::mojom::FingerprintObserver> binding_; + ScopedObserver<session_manager::SessionManager, + session_manager::SessionManagerObserver> + session_observer_; base::WeakPtrFactory<FingerprintHandler> weak_ptr_factory_; 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 f9263067b4a..ee3fc39b648 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,11 +6,16 @@ #include <utility> +#include "ash/public/interfaces/assistant_controller.mojom.h" +#include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" #include "base/values.h" #include "chrome/browser/chromeos/arc/voice_interaction/arc_voice_interaction_framework_service.h" #include "chrome/browser/profiles/profile.h" +#include "chromeos/chromeos_switches.h" #include "components/arc/arc_service_manager.h" +#include "content/public/browser/browser_context.h" +#include "services/service_manager/public/cpp/connector.h" #include "ui/gfx/geometry/rect.h" namespace chromeos { @@ -72,6 +77,16 @@ void GoogleAssistantHandler::HandleSetGoogleAssistantContextEnabled( void GoogleAssistantHandler::HandleShowGoogleAssistantSettings( const base::ListValue* args) { + if (chromeos::switches::IsAssistantEnabled()) { + // Opens Google Assistant settings. + service_manager::Connector* connector = + content::BrowserContext::GetConnectorFor(profile_); + ash::mojom::AssistantControllerPtr assistant_controller; + connector->BindInterface(ash::mojom::kServiceName, &assistant_controller); + assistant_controller->OpenAssistantSettings(); + return; + } + auto* service = arc::ArcVoiceInteractionFrameworkService::GetForBrowserContext(profile_); if (service) diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc index 8dc3a46c55f..7a4c8bed26e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/internet_handler.cc @@ -21,6 +21,7 @@ #include "components/arc/arc_service_manager.h" #include "components/arc/common/net.mojom.h" #include "components/arc/connection_holder.h" +#include "components/arc/metrics/arc_metrics_constants.h" #include "components/onc/onc_constants.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" @@ -186,16 +187,16 @@ void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) { return; } - if (network->vpn_provider_type() == shill::kProviderThirdPartyVpn) { + if (network->GetVpnProviderType() == shill::kProviderThirdPartyVpn) { // Request that the third-party VPN provider used by the |network| show a // configuration dialog for it. VpnServiceFactory::GetForBrowserContext(profile_) - ->SendShowConfigureDialogToExtension(network->vpn_provider_id(), + ->SendShowConfigureDialogToExtension(network->vpn_provider()->id, network->name()); return; } - if (network->vpn_provider_type() == shill::kProviderArcVpn) { + if (network->GetVpnProviderType() == shill::kProviderArcVpn) { auto* net_instance = ARC_GET_INSTANCE_FOR_METHOD( arc::ArcServiceManager::Get()->arc_bridge_service()->net(), ConfigureAndroidVpn); @@ -208,7 +209,7 @@ void InternetHandler::ConfigureThirdPartyVpn(const base::ListValue* args) { } NET_LOG(ERROR) << "ConfigureThirdPartyVpn: Unsupported VPN type: " - << network->vpn_provider_type() << " For: " << guid; + << network->GetVpnProviderType() << " For: " << guid; } void InternetHandler::RequestArcVpnProviders(const base::ListValue* args) { diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc index ca84973cd35..36ef94d7f31 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc @@ -7,24 +7,101 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h" +#include "chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.h" #include "chrome/browser/ui/webui/chromeos/multidevice_setup/multidevice_setup_dialog.h" +#include "chromeos/components/proximity_auth/logging/logging.h" #include "content/public/browser/web_ui.h" namespace chromeos { namespace settings { -MultideviceHandler::MultideviceHandler() = default; -MultideviceHandler::~MultideviceHandler() = default; +namespace { -void MultideviceHandler::OnJavascriptAllowed() {} -void MultideviceHandler::OnJavascriptDisallowed() {} +const char kPageContentDataModeKey[] = "mode"; +const char kPageContentDataHostDeviceNameKey[] = "hostDeviceName"; +const char kPageContentDataBetterTogetherStateKey[] = "betterTogetherState"; +const char kPageContentDataInstantTetheringStateKey[] = "instantTetheringState"; +const char kPageContentDataMessagesStateKey[] = "messagesState"; +const char kPageContentDataSmartLockStateKey[] = "smartLockState"; + +void OnRetrySetHostNowResult(bool success) { + if (success) + return; + + PA_LOG(WARNING) << "OnRetrySetHostNowResult(): Attempt to retry setting the " + << "host device failed."; +} + +} // namespace + +MultideviceHandler::MultideviceHandler( + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, + std::unique_ptr<multidevice_setup::AndroidSmsAppHelperDelegate> + android_sms_app_helper) + : multidevice_setup_client_(multidevice_setup_client), + android_sms_app_helper_(std::move(android_sms_app_helper)), + multidevice_setup_observer_(this), + callback_weak_ptr_factory_(this) {} + +MultideviceHandler::~MultideviceHandler() {} void MultideviceHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( "showMultiDeviceSetupDialog", base::BindRepeating(&MultideviceHandler::HandleShowMultiDeviceSetupDialog, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "getPageContentData", + base::BindRepeating(&MultideviceHandler::HandleGetPageContent, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setFeatureEnabledState", + base::BindRepeating(&MultideviceHandler::HandleSetFeatureEnabledState, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "removeHostDevice", + base::BindRepeating(&MultideviceHandler::HandleRemoveHostDevice, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "retryPendingHostSetup", + base::BindRepeating(&MultideviceHandler::HandleRetryPendingHostSetup, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setUpAndroidSms", + base::BindRepeating(&MultideviceHandler::HandleSetUpAndroidSms, + base::Unretained(this))); +} + +void MultideviceHandler::OnJavascriptAllowed() { + multidevice_setup_observer_.Add(multidevice_setup_client_); +} + +void MultideviceHandler::OnJavascriptDisallowed() { + multidevice_setup_observer_.Remove(multidevice_setup_client_); + + // Ensure that pending callbacks do not complete and cause JS to be evaluated. + callback_weak_ptr_factory_.InvalidateWeakPtrs(); +} + +void MultideviceHandler::OnHostStatusChanged( + const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice& + host_status_with_device) { + UpdatePageContent(); +} + +void MultideviceHandler::OnFeatureStatesChanged( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + UpdatePageContent(); +} + +void MultideviceHandler::UpdatePageContent() { + std::unique_ptr<base::DictionaryValue> page_content_dictionary = + GeneratePageContentDataDictionary(); + DCHECK(page_content_dictionary); + FireWebUIListener("settings.updateMultidevicePageContentData", + *page_content_dictionary); } void MultideviceHandler::HandleShowMultiDeviceSetupDialog( @@ -33,6 +110,113 @@ void MultideviceHandler::HandleShowMultiDeviceSetupDialog( multidevice_setup::MultiDeviceSetupDialog::Show(); } +void MultideviceHandler::HandleGetPageContent(const base::ListValue* args) { + // This callback is expected to be the first one executed when the page is + // loaded, so it should be the one to allow JS calls. + AllowJavascript(); + + std::string callback_id; + bool result = args->GetString(0, &callback_id); + DCHECK(result); + + std::unique_ptr<base::DictionaryValue> page_content_dictionary = + GeneratePageContentDataDictionary(); + DCHECK(page_content_dictionary); + + ResolveJavascriptCallback(base::Value(callback_id), *page_content_dictionary); +} + +void MultideviceHandler::HandleSetFeatureEnabledState( + const base::ListValue* args) { + std::string callback_id; + bool result = args->GetString(0, &callback_id); + DCHECK(result); + + int feature_as_int; + result = args->GetInteger(1, &feature_as_int); + DCHECK(result); + + auto feature = static_cast<multidevice_setup::mojom::Feature>(feature_as_int); + DCHECK(multidevice_setup::mojom::IsKnownEnumValue(feature)); + + bool enabled; + result = args->GetBoolean(2, &enabled); + DCHECK(result); + + base::Optional<std::string> auth_token; + std::string possible_token_value; + if (args->GetString(3, &possible_token_value)) + auth_token = possible_token_value; + + multidevice_setup_client_->SetFeatureEnabledState( + feature, enabled, auth_token, + base::BindOnce(&MultideviceHandler::OnSetFeatureStateEnabledResult, + callback_weak_ptr_factory_.GetWeakPtr(), callback_id)); +} + +void MultideviceHandler::HandleRemoveHostDevice(const base::ListValue* args) { + DCHECK(args->empty()); + multidevice_setup_client_->RemoveHostDevice(); +} + +void MultideviceHandler::HandleRetryPendingHostSetup( + const base::ListValue* args) { + DCHECK(args->empty()); + multidevice_setup_client_->RetrySetHostNow( + base::BindOnce(&OnRetrySetHostNowResult)); +} + +void MultideviceHandler::HandleSetUpAndroidSms(const base::ListValue* args) { + PA_LOG(WARNING) << "HandlingSetupSms"; + DCHECK(args->empty()); + android_sms_app_helper_->LaunchAndroidSmsApp(); +} + +void MultideviceHandler::OnSetFeatureStateEnabledResult( + const std::string& js_callback_id, + bool success) { + ResolveJavascriptCallback(base::Value(js_callback_id), base::Value(success)); +} + +std::unique_ptr<base::DictionaryValue> +MultideviceHandler::GeneratePageContentDataDictionary() { + auto page_content_dictionary = std::make_unique<base::DictionaryValue>(); + + multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice + host_status_with_device = multidevice_setup_client_->GetHostStatus(); + multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap feature_states = + multidevice_setup_client_->GetFeatureStates(); + + page_content_dictionary->SetInteger( + kPageContentDataModeKey, + static_cast<int32_t>(host_status_with_device.first)); + page_content_dictionary->SetInteger( + kPageContentDataBetterTogetherStateKey, + static_cast<int32_t>( + feature_states + [multidevice_setup::mojom::Feature::kBetterTogetherSuite])); + page_content_dictionary->SetInteger( + kPageContentDataInstantTetheringStateKey, + static_cast<int32_t>( + feature_states + [multidevice_setup::mojom::Feature::kInstantTethering])); + page_content_dictionary->SetInteger( + kPageContentDataMessagesStateKey, + static_cast<int32_t>( + feature_states[multidevice_setup::mojom::Feature::kMessages])); + page_content_dictionary->SetInteger( + kPageContentDataSmartLockStateKey, + static_cast<int32_t>( + feature_states[multidevice_setup::mojom::Feature::kSmartLock])); + + if (host_status_with_device.second) { + page_content_dictionary->SetString(kPageContentDataHostDeviceNameKey, + host_status_with_device.second->name()); + } + + return page_content_dictionary; +} + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h index 3ab88522348..cc5e9037e95 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h @@ -6,27 +6,78 @@ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_CHROMEOS_MULTIDEVICE_HANDLER_H_ #include "base/macros.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/services/multidevice_setup/public/cpp/multidevice_setup_client.h" +#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h" +#include "components/cryptauth/remote_device_ref.h" namespace chromeos { +namespace multidevice_setup { +class AndroidSmsAppHelperDelegate; +} // namespace multidevice_setup + namespace settings { // Chrome "Multidevice" (a.k.a. "Connected Devices") settings page UI handler. -class MultideviceHandler : public ::settings::SettingsPageUIHandler { +class MultideviceHandler + : public ::settings::SettingsPageUIHandler, + public multidevice_setup::MultiDeviceSetupClient::Observer { public: - MultideviceHandler(); + explicit MultideviceHandler( + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, + std::unique_ptr<multidevice_setup::AndroidSmsAppHelperDelegate> + android_sms_app_helper); ~MultideviceHandler() override; + protected: // content::WebUIMessageHandler: void RegisterMessages() override; + private: // ::settings::SettingsPageUIHandler: void OnJavascriptAllowed() override; void OnJavascriptDisallowed() override; - private: + // multidevice_setup::MultiDeviceSetupClient::Observer: + void OnHostStatusChanged( + const multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice& + host_status_with_device) override; + void OnFeatureStatesChanged( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) override; + + // Sends the most recent PageContentData dictionary to the WebUI page as an + // update (e.g., not due to a getPageContent() request). + void UpdatePageContent(); + void HandleShowMultiDeviceSetupDialog(const base::ListValue* args); + void HandleGetPageContent(const base::ListValue* args); + void HandleSetFeatureEnabledState(const base::ListValue* args); + void HandleRemoveHostDevice(const base::ListValue* args); + void HandleRetryPendingHostSetup(const base::ListValue* args); + void HandleSetUpAndroidSms(const base::ListValue* args); + + void OnSetFeatureStateEnabledResult(const std::string& js_callback_id, + bool success); + + // Returns null if requisite data has not yet been fetched (i.e., if one or + // both of |last_host_status_update_| and |last_feature_states_update_| is + // null). + std::unique_ptr<base::DictionaryValue> GeneratePageContentDataDictionary(); + + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_; + std::unique_ptr<multidevice_setup::AndroidSmsAppHelperDelegate> + android_sms_app_helper_; + + ScopedObserver<multidevice_setup::MultiDeviceSetupClient, + multidevice_setup::MultiDeviceSetupClient::Observer> + multidevice_setup_observer_; + + // Used to cancel callbacks when JavaScript becomes disallowed. + base::WeakPtrFactory<MultideviceHandler> callback_weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(MultideviceHandler); }; diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc new file mode 100644 index 00000000000..658795d6c18 --- /dev/null +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc @@ -0,0 +1,330 @@ +// 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/settings/chromeos/multidevice_handler.h" + +#include <memory> + +#include "base/macros.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_android_sms_app_helper_delegate.h" +#include "chromeos/services/multidevice_setup/public/cpp/fake_multidevice_setup_client.h" +#include "components/cryptauth/remote_device_test_util.h" +#include "content/public/test/test_web_ui.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { + +namespace settings { + +namespace { + +class TestMultideviceHandler : public MultideviceHandler { + public: + TestMultideviceHandler( + multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client, + std::unique_ptr<multidevice_setup::AndroidSmsAppHelperDelegate> + android_sms_app_helper) + : MultideviceHandler(multidevice_setup_client, + std::move(android_sms_app_helper)) {} + ~TestMultideviceHandler() override = default; + + // Make public for testing. + using MultideviceHandler::AllowJavascript; + using MultideviceHandler::RegisterMessages; + using MultideviceHandler::set_web_ui; +}; + +multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap +GenerateDefaultFeatureStatesMap() { + return multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap{ + {multidevice_setup::mojom::Feature::kBetterTogetherSuite, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}, + {multidevice_setup::mojom::Feature::kInstantTethering, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}, + {multidevice_setup::mojom::Feature::kMessages, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}, + {multidevice_setup::mojom::Feature::kSmartLock, + multidevice_setup::mojom::FeatureState::kUnavailableNoVerifiedHost}}; +} + +void VerifyPageContentDict( + const base::Value* value, + multidevice_setup::mojom::HostStatus expected_host_status, + const base::Optional<cryptauth::RemoteDeviceRef>& expected_host_device, + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + const base::DictionaryValue* page_content_dict; + EXPECT_TRUE(value->GetAsDictionary(&page_content_dict)); + + int mode; + EXPECT_TRUE(page_content_dict->GetInteger("mode", &mode)); + EXPECT_EQ(static_cast<int>(expected_host_status), mode); + + int better_together_state; + EXPECT_TRUE(page_content_dict->GetInteger("betterTogetherState", + &better_together_state)); + auto it = feature_states_map.find( + multidevice_setup::mojom::Feature::kBetterTogetherSuite); + EXPECT_EQ(static_cast<int>(it->second), better_together_state); + + int instant_tethering_state; + EXPECT_TRUE(page_content_dict->GetInteger("instantTetheringState", + &instant_tethering_state)); + it = feature_states_map.find( + multidevice_setup::mojom::Feature::kInstantTethering); + EXPECT_EQ(static_cast<int>(it->second), instant_tethering_state); + + int messages_state; + EXPECT_TRUE(page_content_dict->GetInteger("messagesState", &messages_state)); + it = feature_states_map.find(multidevice_setup::mojom::Feature::kMessages); + EXPECT_EQ(static_cast<int>(it->second), messages_state); + + int smart_lock_state; + EXPECT_TRUE( + page_content_dict->GetInteger("smartLockState", &smart_lock_state)); + it = feature_states_map.find(multidevice_setup::mojom::Feature::kSmartLock); + EXPECT_EQ(static_cast<int>(it->second), smart_lock_state); + + std::string host_device_name; + if (expected_host_device) { + EXPECT_TRUE( + page_content_dict->GetString("hostDeviceName", &host_device_name)); + EXPECT_EQ(expected_host_device->name(), host_device_name); + } else { + EXPECT_FALSE( + page_content_dict->GetString("hostDeviceName", &host_device_name)); + } +} + +} // namespace + +class MultideviceHandlerTest : public testing::Test { + protected: + MultideviceHandlerTest() + : test_device_(cryptauth::CreateRemoteDeviceRefForTest()) {} + ~MultideviceHandlerTest() override = default; + + // testing::Test: + void SetUp() override { + test_web_ui_ = std::make_unique<content::TestWebUI>(); + + fake_multidevice_setup_client_ = + std::make_unique<multidevice_setup::FakeMultiDeviceSetupClient>(); + auto fake_android_sms_app_helper_delegate = + std::make_unique<multidevice_setup::FakeAndroidSmsAppHelperDelegate>(); + fake_android_sms_app_helper_delegate_ = + fake_android_sms_app_helper_delegate.get(); + + handler_ = std::make_unique<TestMultideviceHandler>( + fake_multidevice_setup_client_.get(), + std::move(fake_android_sms_app_helper_delegate)); + handler_->set_web_ui(test_web_ui_.get()); + handler_->RegisterMessages(); + handler_->AllowJavascript(); + } + + void CallGetPageContentData() { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + base::ListValue args; + args.AppendString("handlerFunctionName"); + test_web_ui()->HandleReceivedMessage("getPageContentData", &args); + + 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.webUIResponse", call_data.function_name()); + EXPECT_EQ("handlerFunctionName", call_data.arg1()->GetString()); + EXPECT_TRUE(call_data.arg2()->GetBool()); + VerifyPageContent(call_data.arg3()); + } + + void CallRemoveHostDevice() { + size_t num_remote_host_device_calls_before_call = + fake_multidevice_setup_client()->num_remove_host_device_called(); + base::ListValue empty_args; + test_web_ui()->HandleReceivedMessage("removeHostDevice", &empty_args); + EXPECT_EQ(num_remote_host_device_calls_before_call + 1u, + fake_multidevice_setup_client()->num_remove_host_device_called()); + } + + void SimulateHostStatusUpdate( + multidevice_setup::mojom::HostStatus host_status, + const base::Optional<cryptauth::RemoteDeviceRef>& host_device) { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + fake_multidevice_setup_client_->SetHostStatusWithDevice( + std::make_pair(host_status, host_device)); + 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("settings.updateMultidevicePageContentData", + call_data.arg1()->GetString()); + VerifyPageContent(call_data.arg2()); + } + + void SimulateFeatureStatesUpdate( + const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& + feature_states_map) { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + fake_multidevice_setup_client_->SetFeatureStates(feature_states_map); + 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("settings.updateMultidevicePageContentData", + call_data.arg1()->GetString()); + VerifyPageContent(call_data.arg2()); + } + + void CallRetryPendingHostSetup(bool success) { + base::ListValue empty_args; + test_web_ui()->HandleReceivedMessage("retryPendingHostSetup", &empty_args); + fake_multidevice_setup_client()->InvokePendingRetrySetHostNowCallback( + success); + } + + void CallSetUpAndroidSms() { + base::ListValue empty_args; + test_web_ui()->HandleReceivedMessage("setUpAndroidSms", &empty_args); + } + + void CallSetFeatureEnabledState(multidevice_setup::mojom::Feature feature, + bool enabled, + const base::Optional<std::string>& auth_token, + bool success) { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + base::ListValue args; + args.AppendString("handlerFunctionName"); + args.AppendInteger(static_cast<int>(feature)); + args.AppendBoolean(enabled); + if (auth_token) + args.AppendString(*auth_token); + + base::ListValue empty_args; + test_web_ui()->HandleReceivedMessage("setFeatureEnabledState", &args); + fake_multidevice_setup_client() + ->InvokePendingSetFeatureEnabledStateCallback( + feature /* expected_feature */, enabled /* expected_enabled */, + auth_token /* expected_auth_token */, success); + + 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.webUIResponse", call_data.function_name()); + EXPECT_EQ("handlerFunctionName", call_data.arg1()->GetString()); + EXPECT_TRUE(call_data.arg2()->GetBool()); + EXPECT_EQ(success, call_data.arg3()->GetBool()); + } + + const content::TestWebUI::CallData& CallDataAtIndex(size_t index) { + return *test_web_ui_->call_data()[index]; + } + + content::TestWebUI* test_web_ui() { return test_web_ui_.get(); } + + multidevice_setup::FakeMultiDeviceSetupClient* + fake_multidevice_setup_client() { + return fake_multidevice_setup_client_.get(); + } + + multidevice_setup::FakeAndroidSmsAppHelperDelegate* + fake_android_sms_app_helper_delegate() { + return fake_android_sms_app_helper_delegate_; + } + + const cryptauth::RemoteDeviceRef test_device_; + + private: + void VerifyPageContent(const base::Value* value) { + VerifyPageContentDict( + value, fake_multidevice_setup_client_->GetHostStatus().first, + fake_multidevice_setup_client_->GetHostStatus().second, + fake_multidevice_setup_client_->GetFeatureStates()); + } + + std::unique_ptr<content::TestWebUI> test_web_ui_; + std::unique_ptr<multidevice_setup::FakeMultiDeviceSetupClient> + fake_multidevice_setup_client_; + std::unique_ptr<TestMultideviceHandler> handler_; + + multidevice_setup::MultiDeviceSetupClient::HostStatusWithDevice + host_status_with_device_; + multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap + feature_states_map_; + multidevice_setup::FakeAndroidSmsAppHelperDelegate* + fake_android_sms_app_helper_delegate_; + + DISALLOW_COPY_AND_ASSIGN(MultideviceHandlerTest); +}; + +TEST_F(MultideviceHandlerTest, PageContentData) { + CallGetPageContentData(); + CallGetPageContentData(); + + SimulateHostStatusUpdate( + multidevice_setup::mojom::HostStatus::kEligibleHostExistsButNoHostSet, + base::nullopt /* host_device */); + SimulateHostStatusUpdate(multidevice_setup::mojom::HostStatus:: + kHostSetLocallyButWaitingForBackendConfirmation, + test_device_); + SimulateHostStatusUpdate( + multidevice_setup::mojom::HostStatus::kHostSetButNotYetVerified, + test_device_); + SimulateHostStatusUpdate(multidevice_setup::mojom::HostStatus::kHostVerified, + test_device_); + + multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap + feature_states_map = GenerateDefaultFeatureStatesMap(); + feature_states_map[multidevice_setup::mojom::Feature::kBetterTogetherSuite] = + multidevice_setup::mojom::FeatureState::kEnabledByUser; + SimulateFeatureStatesUpdate(feature_states_map); + + feature_states_map[multidevice_setup::mojom::Feature::kBetterTogetherSuite] = + multidevice_setup::mojom::FeatureState::kDisabledByUser; + SimulateFeatureStatesUpdate(feature_states_map); +} + +TEST_F(MultideviceHandlerTest, RetryPendingHostSetup) { + CallRetryPendingHostSetup(true /* success */); + CallRetryPendingHostSetup(false /* success */); +} + +TEST_F(MultideviceHandlerTest, SetUpAndroidSms) { + EXPECT_FALSE(fake_android_sms_app_helper_delegate()->HasLaunchedApp()); + CallSetUpAndroidSms(); + EXPECT_TRUE(fake_android_sms_app_helper_delegate()->HasLaunchedApp()); +} + +TEST_F(MultideviceHandlerTest, SetFeatureEnabledState) { + CallSetFeatureEnabledState( + multidevice_setup::mojom::Feature::kBetterTogetherSuite, + true /* enabled */, "authToken" /* auth_token */, true /* success */); + CallSetFeatureEnabledState( + multidevice_setup::mojom::Feature::kBetterTogetherSuite, + false /* enabled */, "authToken" /* auth_token */, false /* success */); + CallSetFeatureEnabledState( + multidevice_setup::mojom::Feature::kBetterTogetherSuite, + false /* enabled */, "authToken" /* auth_token */, true /* success */); +} + +TEST_F(MultideviceHandlerTest, RemoveHostDevice) { + CallRemoveHostDevice(); + CallRemoveHostDevice(); + CallRemoveHostDevice(); +} + +} // namespace settings + +} // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/chromeos/smb_handler.cc b/chromium/chrome/browser/ui/webui/settings/chromeos/smb_handler.cc index 8a5af4ee012..ff52076ee4e 100644 --- a/chromium/chrome/browser/ui/webui/settings/chromeos/smb_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/chromeos/smb_handler.cc @@ -20,11 +20,17 @@ namespace { smb_client::SmbService* GetSmbService(Profile* profile) { smb_client::SmbService* const service = smb_client::SmbService::Get(profile); - DCHECK(service); - return service; } +base::Value BuildShareList(const std::vector<smb_client::SmbUrl>& shares) { + base::Value shares_list(base::Value::Type::LIST); + for (const auto& share : shares) { + shares_list.GetList().push_back(base::Value(share.ToString())); + } + return shares_list; +} + } // namespace SmbHandler::SmbHandler(Profile* profile) @@ -54,6 +60,9 @@ void SmbHandler::HandleSmbMount(const base::ListValue* args) { CHECK(args->GetString(3, &password)); smb_client::SmbService* const service = GetSmbService(profile_); + if (!service) { + return; + } chromeos::file_system_provider::MountOptions mo; mo.display_name = mount_name.empty() ? mount_url : mount_name; @@ -79,6 +88,9 @@ void SmbHandler::HandleSmbMountResponse(SmbMountResult result) { void SmbHandler::HandleStartDiscovery(const base::ListValue* args) { smb_client::SmbService* const service = GetSmbService(profile_); + if (!service) { + return; + } service->GatherSharesInNetwork(base::BindRepeating( &SmbHandler::HandleGatherSharesResponse, weak_ptr_factory_.GetWeakPtr())); @@ -91,9 +103,10 @@ void SmbHandler::HandleGatherSharesResponse( std::move(stored_mount_call_).Run(); } - // TODO(zentaro): Pass the shares discovered back to the UI. - // https://crbug.com/852199. + AllowJavascript(); + FireWebUIListener("on-shares-found", BuildShareList(shares_gathered)); } + } // namespace settings } // namespace chromeos diff --git a/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc b/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc index 4e45994d152..61d21286ab9 100644 --- a/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/downloads_handler.cc @@ -18,6 +18,10 @@ #include "content/public/browser/web_ui.h" #include "ui/base/l10n/l10n_util.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/file_manager/path_util.h" +#endif + using base::UserMetricsAction; namespace settings { @@ -44,6 +48,12 @@ void DownloadsHandler::RegisterMessages() { "selectDownloadLocation", base::BindRepeating(&DownloadsHandler::HandleSelectDownloadLocation, base::Unretained(this))); +#if defined(OS_CHROMEOS) + web_ui()->RegisterMessageCallback( + "getDownloadLocationText", + base::BindRepeating(&DownloadsHandler::HandleGetDownloadLocationText, + base::Unretained(this))); +#endif } void DownloadsHandler::OnJavascriptAllowed() { @@ -105,4 +115,20 @@ void DownloadsHandler::FileSelected(const base::FilePath& path, pref_service->SetFilePath(prefs::kSaveFileDefaultDirectory, path); } +#if defined(OS_CHROMEOS) +void DownloadsHandler::HandleGetDownloadLocationText( + const base::ListValue* args) { + AllowJavascript(); + CHECK_EQ(2U, args->GetSize()); + std::string callback_id; + std::string path; + CHECK(args->GetString(0, &callback_id)); + CHECK(args->GetString(1, &path)); + + ResolveJavascriptCallback( + base::Value(callback_id), + base::Value(file_manager::util::GetDownloadLocationText(profile_, path))); +} +#endif + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/downloads_handler.h b/chromium/chrome/browser/ui/webui/settings/downloads_handler.h index 289cf74ab82..503455691e0 100644 --- a/chromium/chrome/browser/ui/webui/settings/downloads_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/downloads_handler.h @@ -51,6 +51,13 @@ class DownloadsHandler : public SettingsPageUIHandler, int index, void* params) override; +#if defined(OS_CHROMEOS) + // Callback for the "getDownloadLocationText" message. Converts actual + // paths in chromeos to values suitable to display to users. + // E.g. /home/chronos/u-<hash>/Downloads => "Downloads". + void HandleGetDownloadLocationText(const base::ListValue* args); +#endif + Profile* profile_; PrefChangeRegistrar pref_registrar_; diff --git a/chromium/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc b/chromium/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc index 65230a3aea7..2c30e7fc48e 100644 --- a/chromium/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc +++ b/chromium/chrome/browser/ui/webui/settings/md_settings_localized_strings_provider.cc @@ -13,13 +13,13 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "build/buildflag.h" +#include "chrome/browser/autofill/personal_data_manager_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/plugins/plugin_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_shortcut_manager.h" #include "chrome/browser/signin/account_consistency_mode_manager.h" -#include "chrome/browser/signin/unified_consent_helper.h" #include "chrome/browser/ui/webui/policy_indicator_localized_strings_provider.h" #include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" @@ -28,17 +28,21 @@ #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" #include "components/autofill/core/browser/payments/payments_service_url.h" +#include "components/autofill/core/browser/payments/payments_util.h" #include "components/autofill/core/common/autofill_constants.h" +#include "components/autofill/core/common/autofill_features.h" #include "components/content_settings/core/common/features.h" -#include "components/google/core/browser/google_util.h" +#include "components/google/core/common/google_util.h" #include "components/omnibox/browser/omnibox_field_trial.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" #include "components/signin/core/browser/signin_buildflags.h" #include "components/strings/grit/components_strings.h" #include "components/subresource_filter/core/browser/subresource_filter_features.h" +#include "components/unified_consent/feature.h" #include "content/public/browser/web_ui_data_source.h" #include "content/public/common/content_features.h" +#include "media/base/media_switches.h" #include "services/device/public/cpp/device_features.h" #include "ui/base/l10n/l10n_util.h" @@ -57,6 +61,7 @@ #include "chrome/browser/ui/webui/chromeos/network_element_localized_strings_provider.h" #include "chromeos/chromeos_features.h" #include "chromeos/chromeos_switches.h" +#include "chromeos/services/multidevice_setup/public/cpp/url_provider.h" #include "components/arc/arc_util.h" #include "components/user_manager/user_manager.h" #include "ui/chromeos/devicetype_utils.h" @@ -134,6 +139,9 @@ void AddCommonStrings(content::WebUIDataSource* html_source, Profile* profile) { {"moreActions", IDS_SETTINGS_MORE_ACTIONS}, {"ok", IDS_OK}, {"restart", IDS_SETTINGS_RESTART}, +#if !defined(OS_CHROMEOS) + {"restartToApplyChanges", IDS_SETTINGS_RESTART_TO_APPLY_CHANGES}, +#endif {"retry", IDS_SETTINGS_RETRY}, {"save", IDS_SAVE}, {"settings", IDS_SETTINGS_SETTINGS}, @@ -203,6 +211,7 @@ void AddA11yStrings(content::WebUIDataSource* html_source) { {"dictationLabel", IDS_SETTINGS_ACCESSIBILITY_DICTATION_LABEL}, {"onScreenKeyboardLabel", IDS_SETTINGS_ON_SCREEN_KEYBOARD_LABEL}, {"monoAudioLabel", IDS_SETTINGS_MONO_AUDIO_LABEL}, + {"startupSoundLabel", IDS_SETTINGS_STARTUP_SOUND_LABEL}, {"a11yExplanation", IDS_SETTINGS_ACCESSIBILITY_EXPLANATION}, {"caretHighlightLabel", IDS_SETTINGS_ACCESSIBILITY_CARET_HIGHLIGHT_DESCRIPTION}, @@ -492,6 +501,8 @@ void AddBluetoothStrings(content::WebUIDataSource* html_source) { {"bluetoothPairDevicePageTitle", IDS_SETTINGS_BLUETOOTH_PAIR_DEVICE_TITLE}, {"bluetoothRemove", IDS_SETTINGS_BLUETOOTH_REMOVE}, + {"bluetoothPrimaryUserControlled", + IDS_SETTINGS_BLUETOOTH_PRIMARY_USER_CONTROLLED}, }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); @@ -513,9 +524,18 @@ void AddClearBrowsingDataStrings(content::WebUIDataSource* html_source, Profile* profile) { LocalizedString localized_strings[] = { {"clearTimeRange", IDS_SETTINGS_CLEAR_PERIOD_TITLE}, + {"clearBrowsingDataWithSync", IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC}, + {"clearBrowsingDataWithSyncError", + IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC_ERROR}, + {"clearBrowsingDataWithSyncPassphraseError", + IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC_PASSPHRASE_ERROR}, + {"clearBrowsingDataWithSyncPaused", + IDS_SETTINGS_CLEAR_BROWSING_DATA_WITH_SYNC_PAUSED}, {"clearBrowsingHistory", IDS_SETTINGS_CLEAR_BROWSING_HISTORY}, {"clearBrowsingHistorySummary", IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY}, + {"clearBrowsingHistorySummarySignedIn", + IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNC_ERROR}, {"clearDownloadHistory", IDS_SETTINGS_CLEAR_DOWNLOAD_HISTORY}, {"clearCache", IDS_SETTINGS_CLEAR_CACHE}, {"clearCookies", IDS_SETTINGS_CLEAR_COOKIES}, @@ -541,11 +561,6 @@ void AddClearBrowsingDataStrings(content::WebUIDataSource* html_source, }; html_source->AddString( - "clearBrowsingHistorySummarySignedIn", - l10n_util::GetStringFUTF16( - IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SIGNED_IN, - base::ASCIIToUTF16(chrome::kMyActivityUrlInClearBrowsingData))); - html_source->AddString( "clearBrowsingHistorySummarySynced", l10n_util::GetStringFUTF16( IDS_SETTINGS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED, @@ -617,6 +632,9 @@ void AddDeviceStrings(content::WebUIDataSource* html_source) { {"keyboardKeyEscape", IDS_SETTINGS_KEYBOARD_KEY_ESCAPE}, {"keyboardKeyBackspace", IDS_SETTINGS_KEYBOARD_KEY_BACKSPACE}, {"keyboardKeyDisabled", IDS_SETTINGS_KEYBOARD_KEY_DISABLED}, + {"keyboardKeyExternalCommand", + IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_COMMAND}, + {"keyboardKeyExternalMeta", IDS_SETTINGS_KEYBOARD_KEY_EXTERNAL_META}, {"keyboardSendFunctionKeys", IDS_SETTINGS_KEYBOARD_SEND_FUNCTION_KEYS}, {"keyboardSendFunctionKeysDescription", ui::DeviceUsesKeyboardLayout2() @@ -737,9 +755,6 @@ void AddDeviceStrings(content::WebUIDataSource* html_source) { base::CommandLine::ForCurrentProcess()->HasSwitch( chromeos::switches::kEnableTouchCalibrationSetting)); - html_source->AddBoolean("enableDisplayZoomSetting", - features::IsDisplayZoomSettingEnabled()); - html_source->AddBoolean("hasExternalTouchDevice", display::HasExternalTouchscreenDevice()); @@ -832,6 +847,8 @@ void AddDownloadsStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_UNSUPPORTED_DEVICE_MESSAGE}, {"smbShareAddedMountExistsMessage", IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_EXISTS_MESSAGE}, + {"smbShareAddedInvalidURLMessage", + IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE}, #endif }; AddLocalizedStringsBulk(html_source, localized_strings, @@ -840,6 +857,8 @@ void AddDownloadsStrings(content::WebUIDataSource* html_source) { #if defined(OS_CHROMEOS) html_source->AddBoolean("enableNativeSmbSetting", base::FeatureList::IsEnabled(features::kNativeSmb)); + html_source->AddString("smbSharesLearnMoreURL", + GetHelpUrlWithBoard(chrome::kSmbSharesLearnMoreURL)); #endif } @@ -1374,18 +1393,20 @@ void AddOnStartupStrings(content::WebUIDataSource* html_source) { arraysize(localized_strings)); } -void AddPasswordsAndFormsStrings(content::WebUIDataSource* html_source) { +void AddPasswordsAndFormsStrings(content::WebUIDataSource* html_source, + Profile* profile) { LocalizedString localized_strings[] = { {"passwordsAndAutofillPageTitle", IDS_SETTINGS_PASSWORDS_AND_AUTOFILL_PAGE_TITLE}, {"googlePayments", IDS_SETTINGS_GOOGLE_PAYMENTS}, {"googlePaymentsCached", IDS_SETTINGS_GOOGLE_PAYMENTS_CACHED}, - {"autofillFormsLabel", IDS_SETTINGS_AUTOFILL_TOGGLE_LABEL}, - {"enableProfilesLabel", - IDS_SETTINGS_AUTOFILL_ENABLE_PROFILES_TOGGLE_LABEL}, - {"enableCreditCardsLabel", - IDS_SETTINGS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL}, - {"addresses", IDS_SETTINGS_AUTOFILL_ADDRESSES_HEADING}, + {"enableProfilesLabel", IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_LABEL}, + {"enableProfilesSublabel", IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_SUBLABEL}, + {"enableCreditCardsLabel", IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL}, + {"enableCreditCardsSublabel", + IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_SUBLABEL}, + {"addresses", IDS_AUTOFILL_ADDRESSES}, + {"addressesTitle", IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE}, {"addAddressTitle", IDS_SETTINGS_AUTOFILL_ADDRESSES_ADD_TITLE}, {"editAddressTitle", IDS_SETTINGS_AUTOFILL_ADDRESSES_EDIT_TITLE}, {"addressCountry", IDS_SETTINGS_AUTOFILL_ADDRESSES_COUNTRY}, @@ -1394,6 +1415,7 @@ void AddPasswordsAndFormsStrings(content::WebUIDataSource* html_source) { {"removeAddress", IDS_SETTINGS_ADDRESS_REMOVE}, {"removeCreditCard", IDS_SETTINGS_CREDIT_CARD_REMOVE}, {"clearCreditCard", IDS_SETTINGS_CREDIT_CARD_CLEAR}, + {"creditCardsDetail", IDS_SETTINGS_AUTOFILL_CREDIT_CARD_DETAIL}, {"creditCardType", IDS_SETTINGS_AUTOFILL_CREDIT_CARD_TYPE_COLUMN_LABEL}, {"creditCardExpiration", IDS_SETTINGS_CREDIT_CARD_EXPIRATION_DATE}, {"creditCardName", IDS_SETTINGS_NAME_ON_CREDIT_CARD}, @@ -1403,6 +1425,13 @@ void AddPasswordsAndFormsStrings(content::WebUIDataSource* html_source) { {"creditCardExpired", IDS_SETTINGS_CREDIT_CARD_EXPIRED}, {"editCreditCardTitle", IDS_SETTINGS_EDIT_CREDIT_CARD_TITLE}, {"addCreditCardTitle", IDS_SETTINGS_ADD_CREDIT_CARD_TITLE}, + {"migrateCreditCardsLabelSingle", + IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_LABEL}, + {"migrateCreditCardsLabelMultiple", + IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_LABEL}, + {"migratableCardsInfoSingle", IDS_SETTINGS_SINGLE_MIGRATABLE_CARD_INFO}, + {"migratableCardsInfoMultiple", + IDS_SETTINGS_MULTIPLE_MIGRATABLE_CARDS_INFO}, {"canMakePaymentToggleLabel", IDS_SETTINGS_CAN_MAKE_PAYMENT_TOGGLE_LABEL}, {"autofillDetail", IDS_SETTINGS_AUTOFILL_DETAIL}, {"passwordsSavePasswordsLabel", @@ -1452,11 +1481,11 @@ void AddPasswordsAndFormsStrings(content::WebUIDataSource* html_source) { // |localized_strings| array once Autofill Home is fully launched. if (base::FeatureList::IsEnabled(password_manager::features::kAutofillHome)) { html_source->AddLocalizedString("autofill", - IDS_SETTINGS_AUTOFILL_AUTOFILL_HOME); + IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE); html_source->AddLocalizedString("passwords", IDS_SETTINGS_PASSWORDS_AUTOFILL_HOME); html_source->AddLocalizedString("creditCards", - IDS_SETTINGS_AUTOFILL_PAYMENT_METHODS); + IDS_AUTOFILL_PAYMENT_METHODS); html_source->AddLocalizedString("noCreditCardsFound", IDS_SETTINGS_PAYMENT_METHODS_NONE); } else { @@ -1479,9 +1508,25 @@ void AddPasswordsAndFormsStrings(content::WebUIDataSource* html_source) { autofill::payments::GetManageAddressesUrl(0).spec()); html_source->AddString("manageCreditCardsUrl", autofill::payments::GetManageInstrumentsUrl(0).spec()); + html_source->AddBoolean( + "migrationEnabled", + autofill::features::GetLocalCardMigrationExperimentalFlag() == + autofill::features::LocalCardMigrationExperimentalFlag:: + kMigrationIncludeSettingsPage); + + autofill::PersonalDataManager* personal_data_manager_ = + autofill::PersonalDataManagerFactory::GetForProfile(profile); + html_source->AddBoolean( + "hasGooglePaymentsAccount", + autofill::payments::GetBillingCustomerId(personal_data_manager_, + profile->GetPrefs()) != 0); AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); + + html_source->AddBoolean("EnableCompanyName", + base::FeatureList::IsEnabled( + autofill::features::kAutofillEnableCompanyName)); } void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { @@ -1489,29 +1534,21 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { {"peoplePageTitle", IDS_SETTINGS_PEOPLE}, {"manageOtherPeople", IDS_SETTINGS_PEOPLE_MANAGE_OTHER_PEOPLE}, #if defined(OS_CHROMEOS) - {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE}, {"accountManagerDescription", IDS_SETTINGS_ACCOUNT_MANAGER_DESCRIPTION}, + {"accountManagerPageTitle", IDS_SETTINGS_ACCOUNT_MANAGER_PAGE_TITLE}, + {"accountManagerSubMenuLabel", IDS_SETTINGS_ACCOUNT_MANAGER_SUBMENU_LABEL}, {"accountListHeader", IDS_SETTINGS_ACCOUNT_MANAGER_LIST_HEADER}, {"addAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_ADD_ACCOUNT_LABEL}, + {"removeAccountLabel", IDS_SETTINGS_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LABEL}, {"configureFingerprintTitle", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TITLE}, {"configureFingerprintInstructionLocateScannerStep", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER}, - {"configureFingerprintInstructionMoveFingerStep", - IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_MOVE_FINGER}, {"configureFingerprintInstructionReadyStep", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_READY}, {"configureFingerprintLiftFinger", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_LIFT_FINGER}, - {"configureFingerprintPartialData", - IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_PARTIAL_DATA}, - {"configureFingerprintInsufficientData", - IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSUFFICIENT_DATA}, - {"configureFingerprintSensorDirty", - IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_SENSOR_DIRTY}, - {"configureFingerprintTooSlow", - IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_FINGER_TOO_SLOW}, - {"configureFingerprintTooFast", - IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_FINGER_TOO_FAST}, + {"configureFingerprintTryAgain", + IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_TRY_AGAIN}, {"configureFingerprintImmobile", IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_FINGER_IMMOBILE}, {"configureFingerprintAddAnotherButton", @@ -1540,14 +1577,20 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { {"lockScreenNumberFingerprints", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NUM_FINGERPRINTS}, {"lockScreenNone", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NONE}, - {"lockScreenFingerprintEnable", - IDS_SETTINGS_PEOPLE_LOCK_SCREEN_ENABLE_FINGERPRINT_CHECKBOX_LABEL}, {"lockScreenFingerprintNewName", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME}, {"lockScreenFingerprintTitle", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_SUBPAGE_TITLE}, {"lockScreenFingerprintWarning", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_FINGERPRINT_LESS_SECURE}, + {"lockScreenNotificationHide", + IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE}, + {"lockScreenNotificationHideSensitive", + IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_HIDE_SENSITIVE}, + {"lockScreenNotificationShow", + IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_SHOW}, + {"lockScreenNotificationTitle", + IDS_ASH_SETTINGS_LOCK_SCREEN_NOTIFICATION_TITLE}, {"lockScreenOptionsLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOCK}, {"lockScreenOptionsLoginLock", IDS_SETTINGS_PEOPLE_LOCK_SCREEN_OPTIONS_LOGIN_LOCK}, @@ -1601,15 +1644,14 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { {"cancelSync", IDS_SETTINGS_SYNC_SETTINGS_CANCEL_SYNC}, #endif // defined(OS_CHROMEOS) #if BUILDFLAG(ENABLE_DICE_SUPPORT) - {"peopleSignIn", IDS_SETTINGS_PEOPLE_SIGN_IN}, + {"peopleSignIn", IDS_PROFILES_DICE_SIGNIN_BUTTON}, {"peopleSignOut", IDS_SETTINGS_PEOPLE_SIGN_OUT}, {"peopleSignInPrompt", IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT}, {"peopleSignInPromptSecondaryWithNoAccount", - IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_NO_ACCOUNT}, + IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT}, {"peopleSignInPromptSecondaryWithAccount", IDS_SETTINGS_PEOPLE_SIGN_IN_PROMPT_SECONDARY_WITH_ACCOUNT}, {"useAnotherAccount", IDS_SETTINGS_PEOPLE_SYNC_ANOTHER_ACCOUNT}, - {"syncAsName", IDS_SETTINGS_PEOPLE_SYNC_AS_NAME}, {"syncingTo", IDS_SETTINGS_PEOPLE_SYNCING_TO_ACCOUNT}, {"turnOffSync", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF}, {"signInAgain", IDS_SYNC_ERROR_USER_MENU_SIGNIN_AGAIN_BUTTON}, @@ -1640,10 +1682,10 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { {"deleteProfileWarningWithoutCounts", IDS_SETTINGS_SYNC_DISCONNECT_DELETE_PROFILE_WARNING_WITHOUT_COUNTS}, {"syncDisconnectConfirm", IDS_SETTINGS_SYNC_DISCONNECT_CONFIRM}, - {"sync", IsUnifiedConsentEnabled(profile) + {"sync", unified_consent::IsUnifiedConsentFeatureEnabled() ? IDS_SETTINGS_SYNC_UNIFIED_CONSENT : IDS_SETTINGS_SYNC}, - {"syncDescription", IsUnifiedConsentEnabled(profile) + {"syncDescription", unified_consent::IsUnifiedConsentFeatureEnabled() ? IDS_SETTINGS_SYNC_DESCRIPTION_UNIFIED_CONSENT : IDS_SETTINGS_SYNC_DESCRIPTION}, {"nonPersonalizedServicesSectionLabel", @@ -1655,7 +1697,7 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { {"syncExpandA11yLabel", IDS_SETTINGS_SYNC_SECTION_ACCESSIBILITY_LABEL}, {"syncAndNonPersonalizedServices", IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES}, - {"syncPageTitle", IsUnifiedConsentEnabled(profile) + {"syncPageTitle", unified_consent::IsUnifiedConsentFeatureEnabled() ? IDS_SETTINGS_SYNC_SYNC_AND_NON_PERSONALIZED_SERVICES : IDS_SETTINGS_SYNC_PAGE_TITLE}, {"syncLoading", IDS_SETTINGS_SYNC_LOADING}, @@ -1696,12 +1738,12 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); - // TODO(https://crbug.com/854562): Integrate these strings into the - // |localized_strings| array once Autofill Home is fully launched. if (base::FeatureList::IsEnabled(password_manager::features::kAutofillHome)) { + // TODO(https://crbug.com/854562): Integrate this string into the + // |localized_strings| array once Autofill Home is fully launched. html_source->AddLocalizedString( "enablePaymentsIntegrationCheckboxLabel", - IDS_SETTINGS_ENABLE_PAYMENTS_INTEGRATION_CHECKBOX_LABEL_AUTOFILL_HOME); + IDS_AUTOFILL_ENABLE_PAYMENTS_INTEGRATION_CHECKBOX_LABEL); } else { html_source->AddLocalizedString( "enablePaymentsIntegrationCheckboxLabel", @@ -1746,12 +1788,13 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_EXPLANATION_TEXT, base::ASCIIToUTF16(sync_dashboard_url))); html_source->AddString( - "passphraseResetHint", - l10n_util::GetStringFUTF8( - IsUnifiedConsentEnabled(profile) - ? IDS_SETTINGS_PASSPHRASE_RESET_HINT_UNIFIED_CONSENT - : IDS_SETTINGS_PASSPHRASE_RESET_HINT, - base::ASCIIToUTF16(sync_dashboard_url))); + "passphraseResetHintEncryption", + l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RESET_HINT_ENCRYPTION, + base::ASCIIToUTF16(sync_dashboard_url))); + html_source->AddString( + "passphraseResetHintToggle", + l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RESET_HINT_TOGGLE, + base::ASCIIToUTF16(sync_dashboard_url))); html_source->AddString( "passphraseRecover", l10n_util::GetStringFUTF8(IDS_SETTINGS_PASSPHRASE_RECOVER, @@ -1773,7 +1816,7 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { LocalizedString sync_disconnect_strings[] = { {"syncDisconnect", IDS_SETTINGS_PEOPLE_SYNC_TURN_OFF}, {"syncDisconnectTitle", - IsUnifiedConsentEnabled(profile) + unified_consent::IsUnifiedConsentFeatureEnabled() ? IDS_SETTINGS_TURN_OFF_SYNC_AND_SIGN_OUT_DIALOG_TITLE_UNIFIED_CONSENT : IDS_SETTINGS_TURN_OFF_SYNC_AND_SIGN_OUT_DIALOG_TITLE}, {"syncDisconnectDeleteProfile", @@ -1784,7 +1827,7 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { AddLocalizedStringsBulk(html_source, sync_disconnect_strings, arraysize(sync_disconnect_strings)); - if (IsUnifiedConsentEnabled(profile)) { + if (unified_consent::IsUnifiedConsentFeatureEnabled()) { html_source->AddLocalizedString( "syncDisconnectExplanation", IDS_SETTINGS_SYNC_DISCONNECT_AND_SIGN_OUT_EXPLANATION_UNIFIED_CONSENT); @@ -1813,6 +1856,13 @@ void AddPeopleStrings(content::WebUIDataSource* html_source, Profile* profile) { html_source->AddBoolean( "driveSuggestAvailable", base::FeatureList::IsEnabled(omnibox::kDocumentProvider)); + +#if defined(OS_CHROMEOS) + // Used to control the display of Chrome OS Account Manager submenu in the + // People section. + html_source->AddBoolean("isAccountManagerEnabled", + chromeos::switches::IsAccountManagerEnabled()); +#endif } void AddPrintingStrings(content::WebUIDataSource* html_source) { @@ -1924,6 +1974,8 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, Profile* profile) { LocalizedString localized_strings[] = { {"privacyPageTitle", IDS_SETTINGS_PRIVACY}, + {"signinAllowedTitle", IDS_SETTINGS_SIGNIN_ALLOWED}, + {"signinAllowedDescription", IDS_SETTINGS_SIGNIN_ALLOWED_DESC}, {"doNotTrack", IDS_SETTINGS_ENABLE_DO_NOT_TRACK}, {"doNotTrackDialogTitle", IDS_SETTINGS_ENABLE_DO_NOT_TRACK_DIALOG_TITLE}, {"enableContentProtectionAttestation", @@ -1956,7 +2008,8 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, arraysize(localized_strings)); // Select strings depending on unified-consent enabledness. - bool is_unified_consent_enabled = IsUnifiedConsentEnabled(profile); + bool is_unified_consent_enabled = + unified_consent::IsUnifiedConsentFeatureEnabled(); if (is_unified_consent_enabled) { LocalizedString conditional_localized_strings[] = { {"searchSuggestPref", IDS_SETTINGS_SUGGEST_PREF_UNIFIED_CONSENT}, @@ -2003,7 +2056,7 @@ void AddPrivacyStrings(content::WebUIDataSource* html_source, } html_source->AddString("syncAndGoogleServicesLearnMoreURL", - IsUnifiedConsentEnabled(profile) + unified_consent::IsUnifiedConsentFeatureEnabled() ? chrome::kSyncAndGoogleServicesLearnMoreURL : ""); html_source->AddString( @@ -2125,6 +2178,10 @@ void AddGoogleAssistantStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD}, {"googleAssistantEnableHotwordDescription", IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_HOTWORD_DESCRIPTION}, + {"googleAssistantEnableNotification", + IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION}, + {"googleAssistantEnableNotificationDescription", + IDS_SETTINGS_GOOGLE_ASSISTANT_ENABLE_NOTIFICATION_DESCRIPTION}, {"googleAssistantSettings", IDS_SETTINGS_GOOGLE_ASSISTANT_SETTINGS}, }; AddLocalizedStringsBulk(html_source, localized_strings, @@ -2215,6 +2272,10 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_DESCRIPTION}, {"siteSettingsAllSitesSearch", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SEARCH}, {"siteSettingsAllSitesSort", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT}, + {"siteSettingsAllSitesSortMethodMostVisited", + IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_MOST_VISITED}, + {"siteSettingsAllSitesSortMethodStorage", + IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_STORAGE}, {"siteSettingsAllSitesSortMethodName", IDS_SETTINGS_SITE_SETTINGS_ALL_SITES_SORT_METHOD_NAME}, {"siteSettingsSiteRepresentationSeparator", @@ -2337,11 +2398,16 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_ASK_DEFAULT_MENU}, {"siteSettingsActionAllowDefault", IDS_SETTINGS_SITE_SETTINGS_ALLOW_DEFAULT_MENU}, + {"siteSettingsActionAutomaticDefault", + IDS_SETTINGS_SITE_SETTINGS_AUTOMATIC_DEFAULT_MENU}, {"siteSettingsActionBlockDefault", IDS_SETTINGS_SITE_SETTINGS_BLOCK_DEFAULT_MENU}, + {"siteSettingsActionMuteDefault", + IDS_SETTINGS_SITE_SETTINGS_MUTE_DEFAULT_MENU}, {"siteSettingsActionAllow", IDS_SETTINGS_SITE_SETTINGS_ALLOW_MENU}, {"siteSettingsActionBlock", IDS_SETTINGS_SITE_SETTINGS_BLOCK_MENU}, {"siteSettingsActionAsk", IDS_SETTINGS_SITE_SETTINGS_ASK_MENU}, + {"siteSettingsActionMute", IDS_SETTINGS_SITE_SETTINGS_MUTE_MENU}, {"siteSettingsActionReset", IDS_SETTINGS_SITE_SETTINGS_RESET_MENU}, {"siteSettingsActionSessionOnly", IDS_SETTINGS_SITE_SETTINGS_SESSION_ONLY_MENU}, @@ -2427,6 +2493,8 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, IDS_SETTINGS_SITE_SETTINGS_PAYMENT_HANDLER_ALLOW_RECOMMENDED}, {"siteSettingsPaymentHandlerBlock", IDS_SETTINGS_SITE_SETTINGS_PAYMENT_HANDLER_BLOCK}, + {"siteSettingsBlockAutoplaySetting", + IDS_SETTINGS_SITE_SETTINGS_BLOCK_AUTOPLAY}, }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); @@ -2443,6 +2511,10 @@ void AddSiteSettingsStrings(content::WebUIDataSource* html_source, base::FeatureList::IsEnabled(features::kSoundContentSetting)); html_source->AddBoolean( + "enableBlockAutoplayContentSetting", + base::FeatureList::IsEnabled(media::kAutoplaySoundSettings)); + + html_source->AddBoolean( "enableClipboardContentSetting", base::FeatureList::IsEnabled(features::kClipboardContentSetting)); @@ -2568,11 +2640,13 @@ void AddMultideviceStrings(content::WebUIDataSource* html_source) { IDS_SETTINGS_MULTIDEVICE_INSTANT_TETHERING}, {"multideviceAndroidMessagesItemTitle", IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES}, - {"multideviceAndroidMessagesItemSummary", - IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY}, {"multideviceForgetDevice", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE}, {"multideviceForgetDeviceSummary", IDS_SETTINGS_MULTIDEVICE_FORGET_THIS_DEVICE_EXPLANATION}, + {"multideviceForgetDeviceDialogHeading", + IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_HEADING}, + {"multideviceForgetDeviceDialogMessage", + IDS_SETTINGS_MULTIDEVICE_FORGET_DEVICE_DIALOG_MESSAGE}, }; AddLocalizedStringsBulk(html_source, localized_strings, arraysize(localized_strings)); @@ -2585,22 +2659,40 @@ void AddMultideviceStrings(content::WebUIDataSource* html_source) { "multideviceVerificationText", l10n_util::GetStringFUTF16( IDS_SETTINGS_MULTIDEVICE_VERIFICATION_TEXT, - GetHelpUrlWithBoard(chrome::kMultiDeviceLearnMoreURL))); + base::UTF8ToUTF16( + chromeos::multidevice_setup::GetBoardSpecificLearnMoreUrl() + .spec()))); html_source->AddString( "multideviceCouldNotConnect", l10n_util::GetStringFUTF16( IDS_SETTINGS_MULTIDEVICE_COULD_NOT_CONNECT, - GetHelpUrlWithBoard(chrome::kMultiDeviceLearnMoreURL))); + base::UTF8ToUTF16( + chromeos::multidevice_setup::GetBoardSpecificLearnMoreUrl() + .spec()))); html_source->AddString( "multideviceSetupSummary", l10n_util::GetStringFUTF16( IDS_SETTINGS_MULTIDEVICE_SETUP_SUMMARY, - GetHelpUrlWithBoard(chrome::kMultiDeviceLearnMoreURL))); + base::UTF8ToUTF16( + chromeos::multidevice_setup::GetBoardSpecificLearnMoreUrl() + .spec()))); + html_source->AddString( + "multideviceNoHostText", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_MULTIDEVICE_NO_ELIGIBLE_HOSTS, + base::UTF8ToUTF16( + chromeos::multidevice_setup::GetBoardSpecificLearnMoreUrl() + .spec()))); html_source->AddString( "multideviceSmartLockItemSummary", l10n_util::GetStringFUTF16( IDS_SETTINGS_MULTIDEVICE_SMART_LOCK_SUMMARY, GetHelpUrlWithBoard(chrome::kEasyUnlockLearnMoreUrl))); + html_source->AddString( + "multideviceAndroidMessagesItemSummary", + l10n_util::GetStringFUTF16( + IDS_SETTINGS_MULTIDEVICE_ANDROID_MESSAGES_SUMMARY, + GetHelpUrlWithBoard(chrome::kAndroidMessagesLearnMoreURL))); } #endif @@ -2628,7 +2720,7 @@ void AddLocalizedStrings(content::WebUIDataSource* html_source, AddDownloadsStrings(html_source); AddLanguagesStrings(html_source); AddOnStartupStrings(html_source); - AddPasswordsAndFormsStrings(html_source); + AddPasswordsAndFormsStrings(html_source, profile); AddPeopleStrings(html_source, profile); AddPrintingStrings(html_source); AddPrivacyStrings(html_source, profile); diff --git a/chromium/chrome/browser/ui/webui/settings/md_settings_ui.cc b/chromium/chrome/browser/ui/webui/settings/md_settings_ui.cc index e2feea6212e..fa6dd8d8b36 100644 --- a/chromium/chrome/browser/ui/webui/settings/md_settings_ui.cc +++ b/chromium/chrome/browser/ui/webui/settings/md_settings_ui.cc @@ -11,11 +11,11 @@ #include <utility> #include <vector> +#include "ash/public/cpp/ash_features.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/signin/unified_consent_helper.h" #include "chrome/browser/ui/webui/metrics_handler.h" #include "chrome/browser/ui/webui/settings/about_handler.h" #include "chrome/browser/ui/webui/settings/appearance_handler.h" @@ -45,10 +45,12 @@ #include "chrome/grit/settings_resources_map.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/pref_registry/pref_registry_syncable.h" +#include "components/unified_consent/feature.h" #include "content/public/browser/navigation_handle.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/common/content_features.h" #include "printing/buildflags/buildflags.h" #if defined(OS_WIN) @@ -73,7 +75,10 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/crostini/crostini_util.h" +#include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h" +#include "chrome/browser/chromeos/multidevice_setup/android_sms_app_helper_delegate_impl.h" +#include "chrome/browser/chromeos/multidevice_setup/multidevice_setup_client_factory.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/ui/webui/settings/chromeos/accessibility_handler.h" #include "chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h" @@ -96,6 +101,7 @@ #include "chrome/common/chrome_switches.h" #include "chromeos/account_manager/account_manager.h" #include "chromeos/account_manager/account_manager_factory.h" +#include "chromeos/chromeos_features.h" #include "chromeos/chromeos_switches.h" #include "components/arc/arc_util.h" #include "ui/base/ui_base_features.h" @@ -213,8 +219,19 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) } AddSettingsPageUIHandler( std::make_unique<chromeos::settings::KeyboardHandler>()); - AddSettingsPageUIHandler( - std::make_unique<chromeos::settings::MultideviceHandler>()); + if (base::FeatureList::IsEnabled( + chromeos::features::kEnableUnifiedMultiDeviceSetup) && + base::FeatureList::IsEnabled( + chromeos::features::kEnableUnifiedMultiDeviceSettings) && + base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) { + AddSettingsPageUIHandler( + std::make_unique<chromeos::settings::MultideviceHandler>( + chromeos::multidevice_setup::MultiDeviceSetupClientFactory:: + GetForProfile(profile), + std::make_unique< + chromeos::multidevice_setup::AndroidSmsAppHelperDelegateImpl>( + profile))); + } AddSettingsPageUIHandler( std::make_unique<chromeos::settings::PointerHandler>()); AddSettingsPageUIHandler( @@ -297,12 +314,22 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) chromeos::quick_unlock::IsPinDisabledByPolicy(profile->GetPrefs())); html_source->AddBoolean("fingerprintUnlockEnabled", chromeos::quick_unlock::IsFingerprintEnabled()); + html_source->AddBoolean("lockScreenNotificationsEnabled", + ash::features::IsLockScreenNotificationsEnabled()); + html_source->AddBoolean( + "lockScreenHideSensitiveNotificationsSupported", + ash::features::IsLockScreenHideSensitiveNotificationsSupported()); html_source->AddBoolean("hasInternalStylus", ash::stylus_utils::HasInternalStylus()); html_source->AddBoolean("showCrostini", IsCrostiniUIAllowedForProfile(profile)); + // TODO(crbug.com/868747): Show an explanatory message instead of hiding the + // storage management info. + html_source->AddBoolean("hideStorageInfo", + chromeos::DemoSession::IsDeviceInDemoMode()); + // We have 2 variants of Android apps settings. Default case, when the Play // Store app exists we show expandable section that allows as to // enable/disable the Play Store and link to Android settings which is @@ -315,8 +342,8 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) html_source->AddBoolean("androidAppsVisible", androidAppsVisible); html_source->AddBoolean("havePlayStoreApp", arc::IsPlayStoreAvailable()); - // TODO(mash): Support Chrome power settings in Mash. crbug.com/644348 - bool enable_power_settings = features::IsAshInBrowserProcess(); + // TODO(mash): Support Chrome power settings in Mash. https://crbug.com/644348 + bool enable_power_settings = !features::IsMultiProcessMash(); html_source->AddBoolean("enablePowerSettings", enable_power_settings); if (enable_power_settings) { AddSettingsPageUIHandler(std::make_unique<chromeos::settings::PowerHandler>( @@ -329,7 +356,7 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) #endif // defined(OS_CHROMEOS) html_source->AddBoolean("unifiedConsentEnabled", - IsUnifiedConsentEnabled(profile)); + unified_consent::IsUnifiedConsentFeatureEnabled()); // TODO(jdoerrie): https://crbug.com/854562. // Remove once Autofill Home is launched. @@ -350,12 +377,18 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) web_ui->AddMessageHandler(std::make_unique<MetricsHandler>()); #if BUILDFLAG(OPTIMIZE_WEBUI) + const bool use_polymer_2 = + base::FeatureList::IsEnabled(features::kWebUIPolymer2); html_source->AddResourcePath("crisper.js", IDR_MD_SETTINGS_CRISPER_JS); html_source->AddResourcePath("lazy_load.crisper.js", IDR_MD_SETTINGS_LAZY_LOAD_CRISPER_JS); - html_source->AddResourcePath("lazy_load.html", - IDR_MD_SETTINGS_LAZY_LOAD_VULCANIZED_HTML); - html_source->SetDefaultResource(IDR_MD_SETTINGS_VULCANIZED_HTML); + html_source->AddResourcePath( + "lazy_load.html", use_polymer_2 + ? IDR_MD_SETTINGS_LAZY_LOAD_VULCANIZED_P2_HTML + : IDR_MD_SETTINGS_LAZY_LOAD_VULCANIZED_HTML); + html_source->SetDefaultResource(use_polymer_2 + ? IDR_MD_SETTINGS_VULCANIZED_P2_HTML + : IDR_MD_SETTINGS_VULCANIZED_HTML); html_source->UseGzip(exclude_from_gzip); #else // Add all settings resources. @@ -372,8 +405,7 @@ MdSettingsUI::MdSettingsUI(content::WebUI* web_ui) html_source); } -MdSettingsUI::~MdSettingsUI() { -} +MdSettingsUI::~MdSettingsUI() {} void MdSettingsUI::AddSettingsPageUIHandler( std::unique_ptr<content::WebUIMessageHandler> handler) { diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.cc b/chromium/chrome/browser/ui/webui/settings/people_handler.cc index d33f651f224..57fe25578d1 100644 --- a/chromium/chrome/browser/ui/webui/settings/people_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/people_handler.cc @@ -26,7 +26,6 @@ #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_promo.h" #include "chrome/browser/signin/signin_ui_util.h" -#include "chrome/browser/signin/unified_consent_helper.h" #include "chrome/browser/sync/profile_sync_service_factory.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/browser/ui/browser_finder.h" @@ -39,7 +38,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/generated_resources.h" #include "components/autofill/core/common/autofill_constants.h" -#include "components/autofill/core/common/autofill_pref_names.h" +#include "components/autofill/core/common/autofill_prefs.h" #include "components/browser_sync/profile_sync_service.h" #include "components/prefs/pref_service.h" #include "components/signin/core/browser/profile_management_switches.h" @@ -49,8 +48,10 @@ #include "components/signin/core/browser/signin_metrics.h" #include "components/signin/core/browser/signin_pref_names.h" #include "components/strings/grit/components_strings.h" -#include "components/sync/base/passphrase_type.h" +#include "components/sync/base/passphrase_enums.h" #include "components/sync/base/sync_prefs.h" +#include "components/unified_consent/feature.h" +#include "components/unified_consent/unified_consent_metrics.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_delegate.h" @@ -70,6 +71,7 @@ #endif #if BUILDFLAG(ENABLE_DICE_SUPPORT) #include "chrome/browser/profiles/profile_avatar_icon_util.h" +#include "chrome/browser/signin/account_consistency_mode_manager.h" #include "chrome/browser/signin/account_tracker_service_factory.h" #include "components/signin/core/browser/account_tracker_service.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -182,6 +184,27 @@ std::string GetSyncErrorAction(sync_ui_util::ActionType action_type) { } } +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +// Returns the base::Value associated with the account, to use in the stored +// accounts list. +base::Value GetAccountValue(const AccountInfo& account, + AccountTrackerService* account_tracker) { + DCHECK(!account.IsEmpty()); + base::Value dictionary(base::Value::Type::DICTIONARY); + dictionary.SetKey("email", base::Value(account.email)); + dictionary.SetKey("fullName", base::Value(account.full_name)); + dictionary.SetKey("givenName", base::Value(account.given_name)); + const gfx::Image& account_image = + account_tracker->GetAccountImage(account.account_id); + if (!account_image.IsEmpty()) { + dictionary.SetKey( + "avatarImage", + base::Value(webui::GetBitmapDataUrl(account_image.AsBitmap()))); + } + return dictionary; +} +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) + } // namespace namespace settings { @@ -242,6 +265,10 @@ void PeopleHandler::RegisterMessages() { "SyncSetupManageOtherPeople", base::BindRepeating(&PeopleHandler::HandleManageOtherPeople, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "UnifiedConsentToggleChanged", + base::BindRepeating(&PeopleHandler::OnUnifiedConsentToggleChanged, + base::Unretained(this))); #if defined(OS_CHROMEOS) web_ui()->RegisterMessageCallback( "AttemptUserExit", @@ -256,6 +283,9 @@ void PeopleHandler::RegisterMessages() { "SyncSetupSignout", base::BindRepeating(&PeopleHandler::HandleSignout, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "SyncSetupPauseSync", base::BindRepeating(&PeopleHandler::HandlePauseSync, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "SyncSetupStartSignIn", base::BindRepeating(&PeopleHandler::HandleStartSignin, base::Unretained(this))); @@ -330,6 +360,15 @@ void PeopleHandler::DisplayGaiaLoginInNewTabOrWindow( force_new_tab = true; } + ProfileSyncService* service = GetSyncService(); + if (service && service->HasUnrecoverableError()) { + // When the user has an unrecoverable error, they first have to sign out and + // then sign in again. + SigninManagerFactory::GetForProfile(browser->profile()) + ->SignOut(signin_metrics::USER_CLICKED_SIGNOUT_SETTINGS, + signin_metrics::SignoutDelete::IGNORE_METRIC); + } + // If the signin manager already has an authenticated username, this is a // re-auth scenario, and we need to ensure that the user signs in with the // same email address. @@ -442,9 +481,8 @@ void PeopleHandler::HandleSetDatatypes(const base::ListValue* args) { const base::Value* callback_id = nullptr; ParseConfigurationArguments(args, &configuration, &callback_id); - PrefService* pref_service = profile_->GetPrefs(); - pref_service->SetBoolean(autofill::prefs::kAutofillWalletImportEnabled, - configuration.payments_integration_enabled); + autofill::prefs::SetPaymentsIntegrationEnabled( + profile_->GetPrefs(), configuration.payments_integration_enabled); // Start configuring the ProfileSyncService using the configuration passed // to us from the JS layer. @@ -482,32 +520,45 @@ void PeopleHandler::OnAccountUpdated(const AccountInfo& info) { FireWebUIListener("stored-accounts-updated", *GetStoredAccountsList()); } +void PeopleHandler::OnAccountImageUpdated(const std::string& account_id, + const gfx::Image& image) { + FireWebUIListener("stored-accounts-updated", *GetStoredAccountsList()); +} + void PeopleHandler::OnAccountRemoved(const AccountInfo& info) { FireWebUIListener("stored-accounts-updated", *GetStoredAccountsList()); } std::unique_ptr<base::ListValue> PeopleHandler::GetStoredAccountsList() { - std::vector<AccountInfo> accounts = - signin_ui_util::GetAccountsForDicePromos(profile_); + std::unique_ptr<base::ListValue> accounts_list = + std::make_unique<base::ListValue>(); + bool dice_enabled = + AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_); + + // Dice and unified consent both disabled: do not show the list of accounts. + if (!dice_enabled && !unified_consent::IsUnifiedConsentFeatureEnabled()) + return accounts_list; AccountTrackerService* account_tracker = AccountTrackerServiceFactory::GetForProfile(profile_); - std::unique_ptr<base::ListValue> accounts_list(new base::ListValue); - accounts_list->Reserve(accounts.size()); - - for (auto const& account : accounts) { - accounts_list->GetList().push_back( - base::Value(base::Value::Type::DICTIONARY)); - base::Value& acc = accounts_list->GetList().back(); - acc.SetKey("email", base::Value(account.email)); - acc.SetKey("fullName", base::Value(account.full_name)); - acc.SetKey("givenName", base::Value(account.given_name)); - const gfx::Image& account_image = - account_tracker->GetAccountImage(account.account_id); - if (!account_image.IsEmpty()) { - acc.SetKey( - "avatarImage", - base::Value(webui::GetBitmapDataUrl(account_image.AsBitmap()))); + + if (dice_enabled) { + // If dice is enabled, show all the accounts. + std::vector<AccountInfo> accounts = + signin_ui_util::GetAccountsForDicePromos(profile_); + accounts_list->Reserve(accounts.size()); + for (auto const& account : accounts) { + accounts_list->GetList().push_back( + GetAccountValue(account, account_tracker)); + } + } else { + // If dice is disabled (and unified consent enabled), show only the primary + // account. + std::string primary_account = SigninManagerFactory::GetForProfile(profile_) + ->GetAuthenticatedAccountId(); + if (!primary_account.empty()) { + accounts_list->GetList().push_back(GetAccountValue( + account_tracker->GetAccountInfo(primary_account), account_tracker)); } } @@ -515,6 +566,7 @@ std::unique_ptr<base::ListValue> PeopleHandler::GetStoredAccountsList() { } void PeopleHandler::HandleStartSyncingWithEmail(const base::ListValue* args) { + DCHECK(AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_)); const base::Value* email; const base::Value* is_default_promo_account; CHECK(args->Get(0, &email)); @@ -615,19 +667,14 @@ void PeopleHandler::HandleShowSetupUI(const base::ListValue* args) { ProfileSyncService* service = GetSyncService(); - // Just let the page open for now, even when the user's not signed in or sync - // is disabled. - // TODO(scottchen): finish the UI for signed-out users - // (https://crbug.com/800972). - if (IsUnifiedConsentEnabled(profile_) && - (IsProfileAuthNeededOrHasErrors() || !service)) { + if (unified_consent::IsUnifiedConsentFeatureEnabled()) { if (service && !sync_blocker_) sync_blocker_ = service->GetSetupInProgressHandle(); - // Preemptively mark login UI as active, because the user could potentially - // sign-in directly from this UI without triggering handleShowSetupUI again. GetLoginUIService()->SetLoginUI(this); - FireWebUIListener("sync-prefs-changed", base::DictionaryValue()); + + PushSyncPrefs(); + // Always let the page open when unified consent is enabled. return; } @@ -660,11 +707,25 @@ void PeopleHandler::HandleShowSetupUI(const base::ListValue* args) { if (sync_startup_tracker_) return; - if (!service->IsEngineInitialized()) { + if (!service->IsEngineInitialized() || + service->HasDisableReason( + syncer::SyncService::DISABLE_REASON_USER_CHOICE)) { // Requesting the sync service to start may trigger call to PushSyncPrefs. // Setting up the startup tracker beforehand correctly signals the // re-entrant call to early exit. - sync_startup_tracker_.reset(new SyncStartupTracker(profile_, this)); + sync_startup_tracker_ = + std::make_unique<SyncStartupTracker>(profile_, this); + // RequestStart() does two things: + // 1) If DISABLE_REASON_USER_CHOICE is set (meaning that Sync was reset via + // the dashboard), clears it. + // 2) Pokes the sync service to start *immediately*, i.e. bypass deferred + // startup. + // It's possible that both of these are already the case, i.e. the engine is + // already in the process of initializing, in which case RequestStart() will + // effectively do nothing. It's also possible that the sync service is + // already running in standalone transport mode and so the engine is already + // initialized. In that case, this will trigger the service to switch to + // full Sync-the-feature mode. service->RequestStart(); // See if it's even possible to bring up the sync engine - if not @@ -704,9 +765,11 @@ void PeopleHandler::HandleRequestPinLoginState(const base::ListValue* args) { void PeopleHandler::HandleStartSignin(const base::ListValue* args) { AllowJavascript(); - // Should only be called if the user is not already signed in or has an auth - // error. - DCHECK(IsProfileAuthNeededOrHasErrors()); + // Should only be called if the user is not already signed in, has a auth + // error, or a unrecoverable sync error requiring re-auth. + ProfileSyncService* service = GetSyncService(); + DCHECK(IsProfileAuthNeededOrHasErrors() || + (service && service->HasUnrecoverableError())); DisplayGaiaLogin(signin_metrics::AccessPoint::ACCESS_POINT_SETTINGS); } @@ -742,6 +805,15 @@ void PeopleHandler::HandleSignout(const base::ListValue* args) { ProfileMetrics::DELETE_PROFILE_SETTINGS); } } + +void PeopleHandler::HandlePauseSync(const base::ListValue* args) { + DCHECK(AccountConsistencyModeManager::IsDiceEnabledForProfile(profile_)); + SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile_); + DCHECK(signin_manager->IsAuthenticated()); + ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)->UpdateCredentials( + signin_manager->GetAuthenticatedAccountId(), + OAuth2TokenServiceDelegate::kInvalidRefreshToken); +} #endif void PeopleHandler::HandleGetSyncStatus(const base::ListValue* args) { @@ -761,6 +833,15 @@ void PeopleHandler::HandleManageOtherPeople(const base::ListValue* /* args */) { #endif // !defined(OS_CHROMEOS) } +void PeopleHandler::OnUnifiedConsentToggleChanged(const base::ListValue* args) { + bool is_toggle_checked = args->GetList()[0].GetBool(); + if (!is_toggle_checked) { + unified_consent::metrics::RecordUnifiedConsentRevoked( + unified_consent::metrics::UnifiedConsentRevokeReason:: + kUserDisabledSettingsToggle); + } +} + void PeopleHandler::CloseSyncSetup() { // Stop a timer to handle timeout in waiting for checking network connection. engine_start_timer_.reset(); @@ -905,10 +986,9 @@ PeopleHandler::GetSyncStatusDictionary() { base::string16 link_label; sync_ui_util::ActionType action_type = sync_ui_util::NO_ACTION; bool status_has_error = - sync_ui_util::GetStatusLabels(profile_, service, *signin, - sync_ui_util::PLAIN_TEXT, &status_label, - &link_label, &action_type) == - sync_ui_util::SYNC_ERROR; + sync_ui_util::GetStatusLabels(profile_, service, *signin, &status_label, + &link_label, + &action_type) == sync_ui_util::SYNC_ERROR; sync_status->SetString("statusText", status_label); sync_status->SetBoolean("hasError", status_has_error); sync_status->SetString("statusAction", GetSyncErrorAction(action_type)); @@ -976,9 +1056,8 @@ void PeopleHandler::PushSyncPrefs() { PrefService* pref_service = profile_->GetPrefs(); syncer::SyncPrefs sync_prefs(pref_service); args.SetBoolean("syncAllDataTypes", sync_prefs.HasKeepEverythingSynced()); - args.SetBoolean( - "paymentsIntegrationEnabled", - pref_service->GetBoolean(autofill::prefs::kAutofillWalletImportEnabled)); + args.SetBoolean("paymentsIntegrationEnabled", + autofill::prefs::IsPaymentsIntegrationEnabled(pref_service)); args.SetBoolean("encryptAllData", service->IsEncryptEverythingEnabled()); args.SetBoolean("encryptAllDataAllowed", service->IsEncryptEverythingAllowed()); diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler.h b/chromium/chrome/browser/ui/webui/settings/people_handler.h index bfedcdc900e..6652b50d0a1 100644 --- a/chromium/chrome/browser/ui/webui/settings/people_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/people_handler.h @@ -88,7 +88,6 @@ class PeopleHandler : public SettingsPageUIHandler, PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndSyncStartupCompleted); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, HandleSetupUIWhenSyncDisabled); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, SelectCustomEncryption); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, ShowSetupCustomPassphraseRequired); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, ShowSetupEncryptAll); @@ -102,9 +101,7 @@ class PeopleHandler : public SettingsPageUIHandler, FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, ShowSigninOnAuthError); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, ShowSyncSetup); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, ShowSyncSetupWhenNotSignedIn); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, SuccessfullySetPassphrase); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncEverything); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncNothing); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncAllManually); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestPassphraseStillRequired); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, TestSyncIndividualTypes); @@ -117,13 +114,15 @@ class PeopleHandler : public SettingsPageUIHandler, FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest, UnrecoverableErrorInitializingSync); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest, HandleCaptcha); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest, HandleGaiaAuthFailure); - FRIEND_TEST_ALL_PREFIXES(PeopleHandlerNonCrosTest, - SubmitAuthWithInvalidUsername); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerFirstSigninTest, DisplayBasicLogin); FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, AcquireSyncBlockerWhenLoadingSyncSettingsSubpage); + FRIEND_TEST_ALL_PREFIXES(PeopleHandlerTest, RestartSyncAfterDashboardClear); + FRIEND_TEST_ALL_PREFIXES( + PeopleHandlerTest, + RestartSyncAfterDashboardClearWithStandaloneTransport); + FRIEND_TEST_ALL_PREFIXES(PeopleHandlerDiceUnifiedConsentTest, + StoredAccountsList); // SettingsPageUIHandler implementation. void RegisterMessages() override; @@ -149,6 +148,8 @@ class PeopleHandler : public SettingsPageUIHandler, #if BUILDFLAG(ENABLE_DICE_SUPPORT) // AccountTrackerService::Observer implementation. void OnAccountUpdated(const AccountInfo& info) override; + void OnAccountImageUpdated(const std::string& account_id, + const gfx::Image& image) override; void OnAccountRemoved(const AccountInfo& info) override; #endif @@ -173,10 +174,14 @@ class PeopleHandler : public SettingsPageUIHandler, #if defined(OS_CHROMEOS) void HandleRequestPinLoginState(const base::ListValue* args); #endif +#if !defined(OS_CHROMEOS) void HandleStartSignin(const base::ListValue* args); void HandleSignout(const base::ListValue* args); + void HandlePauseSync(const base::ListValue* args); +#endif void HandleGetSyncStatus(const base::ListValue* args); void HandleManageOtherPeople(const base::ListValue* args); + void OnUnifiedConsentToggleChanged(const base::ListValue* args); #if !defined(OS_CHROMEOS) // Displays the GAIA login form. diff --git a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc index 58a9f2b000a..d2f47257478 100644 --- a/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc +++ b/chromium/chrome/browser/ui/webui/settings/people_handler_unittest.cc @@ -14,7 +14,10 @@ #include "base/stl_util.h" #include "base/values.h" #include "build/build_config.h" +#include "chrome/browser/signin/account_tracker_service_factory.h" #include "chrome/browser/signin/fake_signin_manager_builder.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/scoped_account_consistency.h" #include "chrome/browser/signin/signin_error_controller_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" @@ -31,10 +34,13 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "components/prefs/pref_service.h" +#include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/fake_auth_status_provider.h" +#include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" #include "components/sync/base/sync_prefs.h" #include "components/sync_preferences/pref_service_syncable.h" +#include "components/unified_consent/scoped_unified_consent.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_controller.h" @@ -182,10 +188,9 @@ class TestingPeopleHandler : public PeopleHandler { class TestWebUIProvider : public TestChromeWebUIControllerFactory::WebUIProvider { public: - content::WebUIController* NewWebUI(content::WebUI* web_ui, - const GURL& url) override { - content::WebUIController* controller = new content::WebUIController(web_ui); - return controller; + std::unique_ptr<content::WebUIController> NewWebUI(content::WebUI* web_ui, + const GURL& url) override { + return std::make_unique<content::WebUIController>(web_ui); } }; @@ -208,7 +213,7 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness { mock_pss_ = static_cast<ProfileSyncServiceMock*>( ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse( profile(), BuildMockProfileSyncService)); - EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_)); + ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error_)); ON_CALL(*mock_pss_, GetPassphraseType()) .WillByDefault(Return(syncer::PassphraseType::IMPLICIT_PASSPHRASE)); ON_CALL(*mock_pss_, GetExplicitPassphraseTime()).WillByDefault( @@ -235,25 +240,26 @@ class PeopleHandlerTest : public ChromeRenderViewHostTestHarness { // Setup the expectations for calls made when displaying the config page. void SetDefaultExpectationsForConfigPage() { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE)); - EXPECT_CALL(*mock_pss_, GetRegisteredDataTypes()) - .WillRepeatedly(Return(GetAllTypes())); - EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()) - .WillRepeatedly(Return(GetAllTypes())); - EXPECT_CALL(*mock_pss_, GetActiveDataTypes()) - .WillRepeatedly(Return(GetAllTypes())); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingEnabled()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, GetRegisteredDataTypes()) + .WillByDefault(Return(GetAllTypes())); + ON_CALL(*mock_pss_, GetPreferredDataTypes()) + .WillByDefault(Return(GetAllTypes())); + ON_CALL(*mock_pss_, GetActiveDataTypes()) + .WillByDefault(Return(GetAllTypes())); + ON_CALL(*mock_pss_, IsEncryptEverythingAllowed()) + .WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsEncryptEverythingEnabled()) + .WillByDefault(Return(false)); } void SetupInitializedProfileSyncService() { // An initialized ProfileSyncService will have already completed sync setup // and will have an initialized sync engine. ASSERT_TRUE(mock_signin_->IsInitialized()); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(true)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE)); } void ExpectPageStatusResponse(const std::string& expected_status) { @@ -336,10 +342,9 @@ TEST_F(PeopleHandlerFirstSigninTest, DisplayBasicLogin) { // Test that the HandleStartSignin call enables JavaScript. handler_->DisallowJavascript(); - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly( - Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); // Ensure that the user is not signed in before calling |HandleStartSignin()|. SigninManager* manager = SigninManager::FromSigninManagerBase(mock_signin_); manager->SignOut(signin_metrics::SIGNOUT_TEST, @@ -361,10 +366,9 @@ TEST_F(PeopleHandlerFirstSigninTest, DisplayBasicLogin) { } TEST_F(PeopleHandlerTest, ShowSyncSetupWhenNotSignedIn) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly( - Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); handler_->HandleShowSetupUI(nullptr); ExpectPageStatusChanged(PeopleHandler::kDonePageStatus); @@ -379,8 +383,8 @@ TEST_F(PeopleHandlerTest, ShowSyncSetupWhenNotSignedIn) { // Verifies that the sync setup is terminated correctly when the // sync is disabled. TEST_F(PeopleHandlerTest, HandleSetupUIWhenSyncDisabled) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly( + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault( Return(syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY)); handler_->HandleShowSetupUI(nullptr); @@ -394,11 +398,12 @@ TEST_F(PeopleHandlerTest, HandleSetupUIWhenSyncDisabled) { // Verifies that the handler correctly handles a cancellation when // it is displaying the spinner to the user. TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING)); EXPECT_CALL(*mock_pss_, RequestStart()); // We're simulating a user setting up sync, which would cause the engine to @@ -419,12 +424,14 @@ TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancel) { // to showing a configuration page when sync setup completes successfully. TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndSyncStartupCompleted) { - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); error_ = GoogleServiceAuthError::AuthErrorNone(); // Sync engine is stopped initially, and will start up. - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return( + syncer::SyncService::TransportState::WAITING_FOR_START_REQUEST)); EXPECT_CALL(*mock_pss_, RequestStart()); SetDefaultExpectationsForConfigPage(); @@ -436,9 +443,10 @@ TEST_F(PeopleHandlerTest, Mock::VerifyAndClearExpectations(mock_pss_); // Now, act as if the ProfileSyncService has started up. SetDefaultExpectationsForConfigPage(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(true)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE)); error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_)); + ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error_)); handler_->SyncStartupCompleted(); EXPECT_EQ(2U, web_ui_.call_data().size()); @@ -457,13 +465,13 @@ TEST_F(PeopleHandlerTest, // user has continued on. TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndCancelAfterSigninSuccess) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()) - .WillOnce(Return(false)) - .WillRepeatedly(Return(true)); + EXPECT_CALL(*mock_pss_, GetTransportState()) + .WillOnce(Return(syncer::SyncService::TransportState::INITIALIZING)) + .WillRepeatedly(Return(syncer::SyncService::TransportState::ACTIVE)); EXPECT_CALL(*mock_pss_, RequestStart()); SetDefaultExpectationsForConfigPage(); handler_->HandleShowSetupUI(nullptr); @@ -481,11 +489,12 @@ TEST_F(PeopleHandlerTest, } TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndSigninFailed) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); error_ = GoogleServiceAuthError::AuthErrorNone(); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING)); EXPECT_CALL(*mock_pss_, RequestStart()); handler_->HandleShowSetupUI(nullptr); @@ -493,7 +502,7 @@ TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndSigninFailed) { Mock::VerifyAndClearExpectations(mock_pss_); error_ = GoogleServiceAuthError( GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS); - EXPECT_CALL(*mock_pss_, GetAuthError()).WillRepeatedly(ReturnRef(error_)); + ON_CALL(*mock_pss_, GetAuthError()).WillByDefault(ReturnRef(error_)); NotifySyncListeners(); // On failure, the dialog will be closed. @@ -502,10 +511,61 @@ TEST_F(PeopleHandlerTest, DisplayConfigureWithEngineDisabledAndSigninFailed) { LoginUIServiceFactory::GetForProfile(profile())->current_login_ui()); } +TEST_F(PeopleHandlerTest, RestartSyncAfterDashboardClear) { + // Clearing sync from the dashboard results in DISABLE_REASON_USER_CHOICE + // being set. + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_USER_CHOICE)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::DISABLED)); + + // Attempting to open the setup UI should restart sync. + EXPECT_CALL(*mock_pss_, RequestStart()).WillOnce([&]() { + // RequestStart() clears DISABLE_REASON_USER_CHOICE, and immediately starts + // initialzing the engine. + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault( + Return(syncer::SyncService::TransportState::INITIALIZING)); + }); + + handler_->HandleShowSetupUI(nullptr); + ExpectPageStatusChanged(PeopleHandler::kSpinnerPageStatus); +} + +TEST_F(PeopleHandlerTest, + RestartSyncAfterDashboardClearWithStandaloneTransport) { + // Clearing sync from the dashboard results in DISABLE_REASON_USER_CHOICE + // being set. However, the sync engine has restarted in standalone transport + // mode. + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_USER_CHOICE)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::ACTIVE)); + + // Attempting to open the setup UI should re-enable sync-the-feature. + EXPECT_CALL(*mock_pss_, RequestStart()).WillOnce([&]() { + // RequestStart() clears DISABLE_REASON_USER_CHOICE. Since the engine is + // already running, it just gets reconfigured. + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault( + Return(syncer::SyncService::TransportState::CONFIGURING)); + }); + + handler_->HandleShowSetupUI(nullptr); + ExpectPageStatusChanged(PeopleHandler::kSpinnerPageStatus); +} + // Tests that signals not related to user intention to configure sync don't // trigger sync engine start. TEST_F(PeopleHandlerTest, OnlyStartEngineWhenConfiguringSync) { - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING)); EXPECT_CALL(*mock_pss_, RequestStart()).Times(0); NotifySyncStateChanged(); } @@ -541,10 +601,10 @@ class PeopleHandlerNonCrosTest : public PeopleHandlerTest { // TODO(kochi): We need equivalent tests for ChromeOS. TEST_F(PeopleHandlerNonCrosTest, UnrecoverableErrorInitializingSync) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly( + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault( Return(syncer::SyncService::DISABLE_REASON_UNRECOVERABLE_ERROR)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); // Open the web UI. handler_->HandleShowSetupUI(nullptr); @@ -552,10 +612,9 @@ TEST_F(PeopleHandlerNonCrosTest, UnrecoverableErrorInitializingSync) { } TEST_F(PeopleHandlerNonCrosTest, GaiaErrorInitializingSync) { - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly( - Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN)); - EXPECT_CALL(*mock_pss_, IsFirstSetupComplete()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NOT_SIGNED_IN)); + ON_CALL(*mock_pss_, IsFirstSetupComplete()).WillByDefault(Return(false)); // Open the web UI. handler_->HandleShowSetupUI(nullptr); @@ -570,10 +629,9 @@ TEST_F(PeopleHandlerTest, TestSyncEverything) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); SetupInitializedProfileSyncService(); EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(true, _)); handler_->HandleSetDatatypes(&list_args); @@ -587,12 +645,11 @@ TEST_F(PeopleHandlerTest, TestPassphraseStillRequired) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); @@ -612,10 +669,10 @@ TEST_F(PeopleHandlerTest, EnterExistingFrozenImplicitPassword) { // Act as if an encryption passphrase is required the first time, then never // again after that. EXPECT_CALL(*mock_pss_, IsPassphraseRequired()).WillOnce(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("oldGaiaPassphrase")) .WillOnce(Return(true)); @@ -632,12 +689,11 @@ TEST_F(PeopleHandlerTest, SetNewCustomPassphrase) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); EXPECT_CALL(*mock_pss_, SetEncryptionPassphrase("custom_passphrase", @@ -655,12 +711,11 @@ TEST_F(PeopleHandlerTest, EnterWrongExistingPassphrase) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); EXPECT_CALL(*mock_pss_, SetDecryptionPassphrase("invalid_passphrase")). WillOnce(Return(false)); @@ -683,12 +738,11 @@ TEST_F(PeopleHandlerTest, EnterBlankExistingPassphrase) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); @@ -702,10 +756,9 @@ TEST_F(PeopleHandlerTest, EnterBlankExistingPassphrase) { // data type. TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) { syncer::ModelTypeSet user_selectable_types = GetAllTypes(); - syncer::ModelTypeSet::Iterator it; - for (it = user_selectable_types.First(); it.Good(); it.Inc()) { + for (syncer::ModelType type : user_selectable_types) { syncer::ModelTypeSet type_to_set; - type_to_set.Put(it.Get()); + type_to_set.Put(type); std::string args = GetConfiguration(NULL, CHOOSE_WHAT_TO_SYNC, type_to_set, @@ -714,10 +767,9 @@ TEST_F(PeopleHandlerTest, TestSyncIndividualTypes) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); SetupInitializedProfileSyncService(); EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(false, ModelTypeSetMatches(type_to_set))); @@ -737,10 +789,9 @@ TEST_F(PeopleHandlerTest, TestSyncAllManually) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); SetupInitializedProfileSyncService(); EXPECT_CALL(*mock_pss_, OnUserChoseDatatypes(false, ModelTypeSetMatches(GetAllTypes()))); @@ -750,10 +801,9 @@ TEST_F(PeopleHandlerTest, TestSyncAllManually) { } TEST_F(PeopleHandlerTest, ShowSyncSetup) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); // This should display the sync setup dialog (not login). SetDefaultExpectationsForConfigPage(); @@ -773,13 +823,13 @@ TEST_F(PeopleHandlerTest, ShowSigninOnAuthError) { FakeAuthStatusProvider provider( SigninErrorControllerFactory::GetForProfile(profile())); provider.SetAuthError(kTestUser, error_); - EXPECT_CALL(*mock_pss_, GetDisableReasons()) - .WillRepeatedly(Return(syncer::SyncService::DISABLE_REASON_NONE)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsEngineInitialized()).WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, GetDisableReasons()) + .WillByDefault(Return(syncer::SyncService::DISABLE_REASON_NONE)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, GetTransportState()) + .WillByDefault(Return(syncer::SyncService::TransportState::INITIALIZING)); #if defined(OS_CHROMEOS) // On ChromeOS, auth errors are ignored - instead we just try to start the @@ -806,10 +856,9 @@ TEST_F(PeopleHandlerTest, ShowSigninOnAuthError) { } TEST_F(PeopleHandlerTest, ShowSetupSyncEverything) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); // This should display the sync setup dialog (not login). @@ -835,10 +884,9 @@ TEST_F(PeopleHandlerTest, ShowSetupSyncEverything) { } TEST_F(PeopleHandlerTest, ShowSetupManuallySyncAll) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); syncer::SyncPrefs sync_prefs(profile()->GetPrefs()); sync_prefs.SetKeepEverythingSynced(false); @@ -852,20 +900,17 @@ TEST_F(PeopleHandlerTest, ShowSetupManuallySyncAll) { TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) { syncer::ModelTypeSet user_selectable_types = GetAllTypes(); - syncer::ModelTypeSet::Iterator it; - for (it = user_selectable_types.First(); it.Good(); it.Inc()) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + for (syncer::ModelType type : user_selectable_types) { + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); syncer::SyncPrefs sync_prefs(profile()->GetPrefs()); sync_prefs.SetKeepEverythingSynced(false); SetDefaultExpectationsForConfigPage(); syncer::ModelTypeSet types; - types.Put(it.Get()); - EXPECT_CALL(*mock_pss_, GetPreferredDataTypes()). - WillRepeatedly(Return(types)); + types.Put(type); + ON_CALL(*mock_pss_, GetPreferredDataTypes()).WillByDefault(Return(types)); // This should display the sync setup dialog (not login). handler_->HandleShowSetupUI(nullptr); @@ -883,10 +928,9 @@ TEST_F(PeopleHandlerTest, ShowSetupSyncForAllTypesIndividually) { } TEST_F(PeopleHandlerTest, ShowSetupOldGaiaPassphraseRequired) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, GetPassphraseType()) - .WillRepeatedly( + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, GetPassphraseType()) + .WillByDefault( Return(syncer::PassphraseType::FROZEN_IMPLICIT_PASSPHRASE)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); @@ -900,10 +944,9 @@ TEST_F(PeopleHandlerTest, ShowSetupOldGaiaPassphraseRequired) { } TEST_F(PeopleHandlerTest, ShowSetupCustomPassphraseRequired) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(*mock_pss_, GetPassphraseType()) - .WillRepeatedly(Return(syncer::PassphraseType::CUSTOM_PASSPHRASE)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(true)); + ON_CALL(*mock_pss_, GetPassphraseType()) + .WillByDefault(Return(syncer::PassphraseType::CUSTOM_PASSPHRASE)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); @@ -916,14 +959,12 @@ TEST_F(PeopleHandlerTest, ShowSetupCustomPassphraseRequired) { } TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingEnabled()) - .WillRepeatedly(Return(true)); + ON_CALL(*mock_pss_, IsEncryptEverythingEnabled()).WillByDefault(Return(true)); // This should display the sync setup dialog (not login). handler_->HandleShowSetupUI(nullptr); @@ -933,14 +974,13 @@ TEST_F(PeopleHandlerTest, ShowSetupEncryptAll) { } TEST_F(PeopleHandlerTest, ShowSetupEncryptAllDisallowed) { - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsUsingSecondaryPassphrase()) + .WillByDefault(Return(false)); SetupInitializedProfileSyncService(); SetDefaultExpectationsForConfigPage(); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsEncryptEverythingAllowed()) + .WillByDefault(Return(false)); // This should display the sync setup dialog (not login). handler_->HandleShowSetupUI(nullptr); @@ -956,17 +996,75 @@ TEST_F(PeopleHandlerTest, TurnOnEncryptAllDisallowed) { base::ListValue list_args; list_args.AppendString(kTestCallbackId); list_args.AppendString(args); - EXPECT_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) - .WillRepeatedly(Return(false)); - EXPECT_CALL(*mock_pss_, IsPassphraseRequired()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequiredForDecryption()) + .WillByDefault(Return(false)); + ON_CALL(*mock_pss_, IsPassphraseRequired()).WillByDefault(Return(false)); SetupInitializedProfileSyncService(); - EXPECT_CALL(*mock_pss_, IsEncryptEverythingAllowed()) - .WillRepeatedly(Return(false)); + ON_CALL(*mock_pss_, IsEncryptEverythingAllowed()) + .WillByDefault(Return(false)); EXPECT_CALL(*mock_pss_, EnableEncryptEverything()).Times(0); handler_->HandleSetEncryption(&list_args); ExpectPageStatusResponse(PeopleHandler::kConfigurePageStatus); } +#if BUILDFLAG(ENABLE_DICE_SUPPORT) +class PeopleHandlerDiceUnifiedConsentTest + : public ::testing::TestWithParam<std::tuple<bool, bool>> {}; + +TEST_P(PeopleHandlerDiceUnifiedConsentTest, StoredAccountsList) { + content::TestBrowserThreadBundle test_browser_thread_bundle; + + // Decode test parameters. + bool dice_enabled; + bool unified_consent_enabled; + std::tie(dice_enabled, unified_consent_enabled) = GetParam(); + unified_consent::ScopedUnifiedConsent unified_consent( + unified_consent_enabled + ? unified_consent::UnifiedConsentFeatureState::kEnabledWithBump + : unified_consent::UnifiedConsentFeatureState::kDisabled); + ScopedAccountConsistency dice( + dice_enabled ? signin::AccountConsistencyMethod::kDice + : signin::AccountConsistencyMethod::kDiceFixAuthErrors); + + // Setup the profile. + TestingProfile profile; + AccountTrackerService* account_tracker = + AccountTrackerServiceFactory::GetForProfile(&profile); + SigninManager* signin_manager = SigninManagerFactory::GetForProfile(&profile); + ProfileOAuth2TokenService* token_service = + ProfileOAuth2TokenServiceFactory::GetForProfile(&profile); + std::string account_1 = + account_tracker->SeedAccountInfo("1234", "a@gmail.com"); + std::string account_2 = + account_tracker->SeedAccountInfo("5678", "b@gmail.com"); + token_service->UpdateCredentials(account_1, "token"); + token_service->UpdateCredentials(account_2, "token"); + signin_manager->SetAuthenticatedAccountInfo("1234", "a@gmail.com"); + + PeopleHandler handler(&profile); + std::unique_ptr<base::ListValue> accounts_list = + handler.GetStoredAccountsList(); + + if (dice_enabled) { + EXPECT_EQ(2u, accounts_list->GetSize()); + EXPECT_EQ("a@gmail.com", + accounts_list->GetList()[0].FindKey("email")->GetString()); + EXPECT_EQ("b@gmail.com", + accounts_list->GetList()[1].FindKey("email")->GetString()); + } else if (unified_consent_enabled) { + EXPECT_EQ(1u, accounts_list->GetSize()); + EXPECT_EQ("a@gmail.com", + accounts_list->GetList()[0].FindKey("email")->GetString()); + } else { + EXPECT_EQ(0u, accounts_list->GetSize()); + } +} + +INSTANTIATE_TEST_CASE_P(Test, + PeopleHandlerDiceUnifiedConsentTest, + ::testing::Combine(::testing::Bool(), + ::testing::Bool())); +#endif // BUILDFLAG(ENABLE_DICE_SUPPORT) + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc b/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc index 1f486d9b882..e91b7de825c 100644 --- a/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/protocol_handlers_handler.cc @@ -17,7 +17,7 @@ #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/url_constants.h" -#include "components/google/core/browser/google_util.h" +#include "components/google/core/common/google_util.h" #include "components/prefs/pref_service.h" #include "content/public/browser/web_ui.h" 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 871a956100d..908a8d324a7 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 @@ -18,8 +18,11 @@ #include "chrome/browser/browsing_data/counters/browsing_data_counter_factory.h" #include "chrome/browser/browsing_data/counters/browsing_data_counter_utils.h" #include "chrome/browser/history/web_history_service_factory.h" +#include "chrome/browser/signin/account_reconcilor_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/sync/profile_sync_service_factory.h" +#include "chrome/browser/sync/sync_ui_util.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" @@ -28,11 +31,11 @@ #include "components/feature_engagement/buildflags.h" #include "components/prefs/pref_member.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browsing_data_filter_builder.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui.h" +#include "services/identity/public/cpp/identity_manager.h" #include "ui/base/text/bytes_formatting.h" #if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP) @@ -248,15 +251,27 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData( checked_other_types); } + // If Sync is running, prevent it from being paused during the operation. + // However, if Sync is in error, clearing cookies should pause it. + std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion> + scoped_data_deletion; + sync_ui_util::MessageType sync_status = sync_ui_util::GetStatus( + profile_, sync_service_, *SigninManagerFactory::GetForProfile(profile_)); + if (sync_status == sync_ui_util::SYNCED) { + scoped_data_deletion = AccountReconcilorFactory::GetForProfile(profile_) + ->GetScopedSyncDataDeletion(); + } + int period_selected; CHECK(args->GetInteger(2, &period_selected)); content::BrowsingDataRemover* remover = content::BrowserContext::GetBrowsingDataRemover(profile_); - base::OnceClosure callback = base::BindOnce( - &ClearBrowsingDataHandler::OnClearingTaskFinished, - weak_ptr_factory_.GetWeakPtr(), webui_callback_id, std::move(data_types)); + base::OnceClosure callback = + base::BindOnce(&ClearBrowsingDataHandler::OnClearingTaskFinished, + weak_ptr_factory_.GetWeakPtr(), webui_callback_id, + std::move(data_types), std::move(scoped_data_deletion)); browsing_data::TimePeriod time_period = static_cast<browsing_data::TimePeriod>(period_selected); @@ -275,7 +290,8 @@ void ClearBrowsingDataHandler::HandleClearBrowsingData( void ClearBrowsingDataHandler::OnClearingTaskFinished( const std::string& webui_callback_id, - const base::flat_set<BrowsingDataType>& data_types) { + const base::flat_set<BrowsingDataType>& data_types, + std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion> deletion) { PrefService* prefs = profile_->GetPrefs(); int notice_shown_times = prefs->GetInteger( browsing_data::prefs::kClearBrowsingDataHistoryNoticeShownTimes); @@ -327,10 +343,11 @@ void ClearBrowsingDataHandler::OnStateChanged(syncer::SyncService* sync) { } void ClearBrowsingDataHandler::UpdateSyncState() { - auto* signin_manager = SigninManagerFactory::GetForProfile(profile_); + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile_); CallJavascriptFunction( "cr.webUIListenerCallback", base::Value("update-sync-state"), - base::Value(signin_manager && signin_manager->IsAuthenticated()), + base::Value(identity_manager && identity_manager->HasPrimaryAccount()), base::Value(sync_service_ && sync_service_->IsSyncActive() && sync_service_->GetActiveDataTypes().Has( syncer::HISTORY_DELETE_DIRECTIVES)), diff --git a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h index 40fcfa0b06f..96e239934ac 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/settings_clear_browsing_data_handler.h @@ -17,6 +17,7 @@ #include "components/browser_sync/profile_sync_service.h" #include "components/browsing_data/core/browsing_data_utils.h" #include "components/browsing_data/core/counters/browsing_data_counter.h" +#include "components/signin/core/browser/account_reconcilor.h" namespace base { class ListValue; @@ -47,12 +48,14 @@ class ClearBrowsingDataHandler : public SettingsPageUIHandler, // Clears browsing data, called by Javascript. void HandleClearBrowsingData(const base::ListValue* value); - // Called when a clearing task finished. |webui_callback_id| is provided // by the WebUI action that initiated it. + // The ScopedSyncedDataDeletion is passed here to ensure that the Sync token + // is not invalidated before this function is run. void OnClearingTaskFinished( const std::string& webui_callback_id, - const base::flat_set<browsing_data::BrowsingDataType>& data_types); + const base::flat_set<browsing_data::BrowsingDataType>& data_types, + std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion> deletion); // Initializes the dialog UI. Called by JavaScript when the DOM is ready. void HandleInitialize(const base::ListValue* args); diff --git a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc index 9150748cdba..12b0a2a44ee 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.cc @@ -45,6 +45,9 @@ class FileSystemContext; namespace { +constexpr char kEffectiveTopLevelDomainPlus1Name[] = "etldPlus1"; +constexpr char kNumCookies[] = "numCookies"; + int GetCategoryLabelID(CookieTreeNode::DetailedInfo::NodeType node_type) { constexpr struct { CookieTreeNode::DetailedInfo::NodeType node_type; @@ -174,6 +177,10 @@ void CookiesViewHandler::RegisterMessages() { base::BindRepeating(&CookiesViewHandler::HandleGetCookieDetails, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "localData.getNumCookiesList", + base::BindRepeating(&CookiesViewHandler::HandleGetNumCookiesList, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "localData.getNumCookiesString", base::BindRepeating(&CookiesViewHandler::HandleGetNumCookiesString, base::Unretained(this))); @@ -309,53 +316,73 @@ void CookiesViewHandler::HandleGetCookieDetails(const base::ListValue* args) { SendCookieDetails(node); } -void CookiesViewHandler::HandleGetNumCookiesString( - const base::ListValue* args) { +void CookiesViewHandler::HandleGetNumCookiesList(const base::ListValue* args) { CHECK_EQ(2U, args->GetSize()); std::string callback_id; CHECK(args->GetString(0, &callback_id)); - base::string16 etld_plus1; - CHECK(args->GetString(1, &etld_plus1)); + const base::ListValue* etld_plus1_list; + CHECK(args->GetList(1, &etld_plus1_list)); AllowJavascript(); CHECK(cookies_tree_model_.get()); - // This method is only interested in the number of cookies, so don't save the - // filter and keep the existing |sorted_sites_| list. - if (etld_plus1 != filter_) - cookies_tree_model_->UpdateSearchResults(etld_plus1); - int num_cookies = 0; - const CookieTreeNode* root = cookies_tree_model_->GetRoot(); - for (int i = 0; i < root->child_count(); ++i) { - const CookieTreeNode* site = root->GetChild(i); - const base::string16& title = site->GetTitle(); - if (!base::EndsWith(title, etld_plus1, - base::CompareCase::INSENSITIVE_ASCII)) { - continue; - } + base::string16 etld_plus1; + base::Value result(base::Value::Type::LIST); + for (size_t i = 0; i < etld_plus1_list->GetSize(); ++i) { + etld_plus1_list->GetString(i, &etld_plus1); + // This method is only interested in the number of cookies, so don't save + // |etld_plus1| as a new filter and keep the existing |sorted_sites_| list. + cookies_tree_model_->UpdateSearchResults(etld_plus1); - for (int j = 0; j < site->child_count(); ++j) { - const CookieTreeNode* category = site->GetChild(j); - if (category->GetDetailedInfo().node_type != - CookieTreeNode::DetailedInfo::TYPE_COOKIES) { + int num_cookies = 0; + const CookieTreeNode* root = cookies_tree_model_->GetRoot(); + for (int i = 0; i < root->child_count(); ++i) { + const CookieTreeNode* site = root->GetChild(i); + const base::string16& title = site->GetTitle(); + if (!base::EndsWith(title, etld_plus1, + base::CompareCase::INSENSITIVE_ASCII)) { continue; } - for (int k = 0; k < category->child_count(); ++k) { - if (category->GetChild(k)->GetDetailedInfo().node_type != - CookieTreeNode::DetailedInfo::TYPE_COOKIE) { + for (int j = 0; j < site->child_count(); ++j) { + const CookieTreeNode* category = site->GetChild(j); + if (category->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIES) { continue; } - ++num_cookies; + for (int k = 0; k < category->child_count(); ++k) { + if (category->GetChild(k)->GetDetailedInfo().node_type != + CookieTreeNode::DetailedInfo::TYPE_COOKIE) { + continue; + } + + ++num_cookies; + } } } - } - if (etld_plus1 != filter_) { - // Restore the original |filter_|. - cookies_tree_model_->UpdateSearchResults(filter_); + base::Value cookies_per_etld_plus1(base::Value::Type::DICTIONARY); + cookies_per_etld_plus1.SetKey(kEffectiveTopLevelDomainPlus1Name, + base::Value(etld_plus1)); + cookies_per_etld_plus1.SetKey(kNumCookies, base::Value(num_cookies)); + result.GetList().emplace_back(std::move(cookies_per_etld_plus1)); } + ResolveJavascriptCallback(base::Value(callback_id), result); + + // Restore the original |filter_|. + cookies_tree_model_->UpdateSearchResults(filter_); +} + +void CookiesViewHandler::HandleGetNumCookiesString( + const base::ListValue* args) { + CHECK_EQ(2U, args->GetSize()); + std::string callback_id; + CHECK(args->GetString(0, &callback_id)); + int num_cookies; + CHECK(args->GetInteger(1, &num_cookies)); + + AllowJavascript(); const base::string16 string = num_cookies > 0 ? l10n_util::GetPluralStringFUTF16( IDS_SETTINGS_SITE_SETTINGS_NUM_COOKIES, num_cookies) diff --git a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h index 0b742577c16..bba06ea179a 100644 --- a/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/settings_cookies_view_handler.h @@ -61,7 +61,12 @@ class CookiesViewHandler : public SettingsPageUIHandler, // Retrieve cookie details for a specific site. void HandleGetCookieDetails(const base::ListValue* args); - // Gets the number of cookies formatted in a plural string, given a site. + // Gets a list containing the number of cookies for each domain (eTLD+1 names) + // given in |siteList|. This will always return a result array the same length + // and in the same order as |siteList|. + void HandleGetNumCookiesList(const base::ListValue* args); + + // Gets a plural string for the given number of cookies. void HandleGetNumCookiesString(const base::ListValue* args); // Remove all sites data. 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 721518a1f17..1ea37913233 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 @@ -192,6 +192,7 @@ void ManageProfileHandler::HandleSetProfileIconToDefaultAvatar( PrefService* pref_service = profile_->GetPrefs(); pref_service->SetInteger(prefs::kProfileAvatarIndex, new_icon_index); + pref_service->SetInteger(prefs::kProfileLocalAvatarIndex, new_icon_index); pref_service->SetBoolean(prefs::kProfileUsingDefaultAvatar, false); pref_service->SetBoolean(prefs::kProfileUsingGAIAAvatar, false); 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 fa89523712c..04422c787f8 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.cc @@ -17,11 +17,12 @@ #include "base/macros.h" #include "base/metrics/user_metrics.h" #include "base/values.h" -#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/content_settings/web_site_settings_uma_util.h" +#include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/infobars/infobar_service.h" +#include "chrome/browser/media/unified_autoplay_config.h" #include "chrome/browser/permissions/chooser_context_base.h" #include "chrome/browser/permissions/permission_decision_auto_blocker.h" #include "chrome/browser/permissions/permission_manager.h" @@ -34,11 +35,14 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/webui/site_settings_helper.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" +#include "chrome/common/pref_names.h" #include "chrome/grit/generated_resources.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/crx_file/id_util.h" +#include "components/prefs/pref_change_registrar.h" +#include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/web_contents.h" @@ -54,9 +58,6 @@ #include "ui/base/text/bytes_formatting.h" #if defined(OS_CHROMEOS) -#include "chrome/common/pref_names.h" -#include "components/prefs/pref_change_registrar.h" -#include "components/prefs/pref_service.h" #include "components/user_manager/user_manager.h" #endif @@ -66,6 +67,7 @@ namespace { constexpr char kEffectiveTopLevelDomainPlus1Name[] = "etldPlus1"; constexpr char kOriginList[] = "origins"; +constexpr char kNumCookies[] = "numCookies"; constexpr char kZoom[] = "zoom"; // Return an appropriate API Permission ID for the given string name. @@ -149,12 +151,44 @@ void CreateOrAppendSiteGroupEntry( } } -} // namespace +// Converts a given |site_group_map| to a list of base::DictionaryValues, adding +// the site engagement score for each origin. +void ConvertSiteGroupMapToListValue( + const std::map<std::string, std::set<std::string>>& site_group_map, + base::Value* list_value, + Profile* profile) { + DCHECK_EQ(base::Value::Type::LIST, list_value->type()); + DCHECK(profile); + SiteEngagementService* engagement_service = + SiteEngagementService::Get(profile); + for (const auto& entry : site_group_map) { + // eTLD+1 is the effective top level domain + 1. + base::Value site_group(base::Value::Type::DICTIONARY); + site_group.SetKey(kEffectiveTopLevelDomainPlus1Name, + base::Value(entry.first)); + base::Value origin_list(base::Value::Type::LIST); + for (const std::string& origin : entry.second) { + base::Value origin_object(base::Value::Type::DICTIONARY); + origin_object.SetKey("origin", base::Value(origin)); + origin_object.SetKey( + "engagement", + base::Value(engagement_service->GetScore(GURL(origin)))); + origin_object.SetKey("usage", base::Value(0)); + origin_list.GetList().emplace_back(std::move(origin_object)); + } + site_group.SetKey(kNumCookies, base::Value(0)); + site_group.SetKey(kOriginList, std::move(origin_list)); + list_value->GetList().push_back(std::move(site_group)); + } +} +} // namespace SiteSettingsHandler::SiteSettingsHandler(Profile* profile) - : profile_(profile), observer_(this) { -} + : profile_(profile), + observer_(this), + pref_change_registrar_(nullptr), + local_storage_helper_(nullptr) {} SiteSettingsHandler::~SiteSettingsHandler() { } @@ -190,6 +224,10 @@ void SiteSettingsHandler::RegisterMessages() { base::BindRepeating(&SiteSettingsHandler::HandleGetAllSites, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "getFormattedBytes", + base::BindRepeating(&SiteSettingsHandler::HandleGetFormattedBytes, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "getExceptionList", base::BindRepeating(&SiteSettingsHandler::HandleGetExceptionList, base::Unretained(this))); @@ -235,6 +273,14 @@ void SiteSettingsHandler::RegisterMessages() { "removeZoomLevel", base::BindRepeating(&SiteSettingsHandler::HandleRemoveZoomLevel, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "setBlockAutoplayEnabled", + base::BindRepeating(&SiteSettingsHandler::HandleSetBlockAutoplayEnabled, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "fetchBlockAutoplayStatus", + base::BindRepeating(&SiteSettingsHandler::HandleFetchBlockAutoplayStatus, + base::Unretained(this))); } void SiteSettingsHandler::OnJavascriptAllowed() { @@ -263,9 +309,16 @@ void SiteSettingsHandler::OnJavascriptAllowed() { base::Bind(&SiteSettingsHandler::OnZoomLevelChanged, base::Unretained(this))); -#if defined(OS_CHROMEOS) pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); pref_change_registrar_->Init(profile_->GetPrefs()); + + // If the block autoplay pref changes send the new status. + pref_change_registrar_->Add( + prefs::kBlockAutoplayEnabled, + base::Bind(&SiteSettingsHandler::SendBlockAutoplayStatus, + base::Unretained(this))); + +#if defined(OS_CHROMEOS) pref_change_registrar_->Add( prefs::kEnableDRM, base::Bind(&SiteSettingsHandler::OnPrefEnableDrmChanged, @@ -277,6 +330,7 @@ void SiteSettingsHandler::OnJavascriptDisallowed() { observer_.RemoveAll(); notification_registrar_.RemoveAll(); host_zoom_map_subscription_.reset(); + pref_change_registrar_->Remove(prefs::kBlockAutoplayEnabled); #if defined(OS_CHROMEOS) pref_change_registrar_->Remove(prefs::kEnableDRM); #endif @@ -342,6 +396,14 @@ void SiteSettingsHandler::OnContentSettingChanged( ? "" : secondary_pattern.ToString())); } + + // If the default sound content setting changed then we should send block + // autoplay status. + if (primary_pattern == ContentSettingsPattern() && + secondary_pattern == ContentSettingsPattern() && + content_type == CONTENT_SETTINGS_TYPE_SOUND) { + SendBlockAutoplayStatus(); + } } void SiteSettingsHandler::Observe( @@ -425,9 +487,7 @@ void SiteSettingsHandler::HandleClearUsage( base::Unretained(this), barrier)); // Also clear the *local* storage data. - scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper = - new BrowsingDataLocalStorageHelper(profile_); - local_storage_helper->DeleteOrigin(url, barrier); + GetLocalStorageHelper()->DeleteOrigin(url, barrier); } } @@ -560,6 +620,10 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { // TODO(https://crbug.com/835712): Assess performance of this method for // unusually large numbers of stored content settings. + // Add sites that are using any local storage to the list. + GetLocalStorageHelper()->StartFetching(base::BindRepeating( + &SiteSettingsHandler::OnLocalStorageFetched, base::Unretained(this))); + // Retrieve a list of embargoed settings to check separately. This ensures // that only settings included in |content_types| will be listed in all sites. ContentSettingsForOneType embargo_settings; @@ -584,9 +648,6 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { // Convert |types| to a list of ContentSettingsTypes. for (ContentSettingsType content_type : content_types) { - // TODO(https://crbug.com/835712): Add extension content settings, plus - // sites that use any non-zero amount of storage. - ContentSettingsForOneType entries; map->GetSettingsForOneType(content_type, std::string(), &entries); for (const ContentSettingPatternSource& e : entries) { @@ -596,21 +657,51 @@ void SiteSettingsHandler::HandleGetAllSites(const base::ListValue* args) { } } - // Convert |all_sites_map| to a list of base::DictionaryValues. base::Value result(base::Value::Type::LIST); - for (const auto& entry : all_sites_map) { - // eTLD+1 is the effective top level domain + 1. - base::Value site_group(base::Value::Type::DICTIONARY); - site_group.SetKey(kEffectiveTopLevelDomainPlus1Name, - base::Value(entry.first)); - base::Value origin_list(base::Value::Type::LIST); - for (const std::string& origin : entry.second) { - origin_list.GetList().emplace_back(origin); + ConvertSiteGroupMapToListValue(all_sites_map, &result, profile); + ResolveJavascriptCallback(*callback_id, result); +} + +void SiteSettingsHandler::OnLocalStorageFetched( + const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>& + local_storage_info) { + std::map<std::string, int> origin_size_map; + std::map<std::string, std::set<std::string>> all_sites_map; + for (const BrowsingDataLocalStorageHelper::LocalStorageInfo& info : + local_storage_info) { + origin_size_map.emplace(info.origin_url.spec(), info.size); + CreateOrAppendSiteGroupEntry(&all_sites_map, info.origin_url); + } + base::Value result(base::Value::Type::LIST); + ConvertSiteGroupMapToListValue(all_sites_map, &result, profile_); + + // Merge the origin usage number into |result|. + for (size_t i = 0; i < result.GetList().size(); ++i) { + base::Value* site_group = &result.GetList()[i]; + base::Value* origin_list = site_group->FindKey(kOriginList); + + for (size_t i = 0; i < origin_list->GetList().size(); ++i) { + base::Value* origin_info = &origin_list->GetList()[i]; + const std::string& origin = origin_info->FindKey("origin")->GetString(); + const auto& size_info = origin_size_map.find(origin); + if (size_info != origin_size_map.end()) + origin_info->SetKey("usage", base::Value(size_info->second)); } - site_group.SetKey(kOriginList, std::move(origin_list)); - result.GetList().push_back(std::move(site_group)); } - ResolveJavascriptCallback(*callback_id, result); + FireWebUIListener("onLocalStorageListFetched", result); +} + +void SiteSettingsHandler::HandleGetFormattedBytes(const base::ListValue* args) { + AllowJavascript(); + + CHECK_EQ(2U, args->GetSize()); + const base::Value* callback_id; + CHECK(args->Get(0, &callback_id)); + int num_bytes; + CHECK(args->GetInteger(1, &num_bytes)); + + const base::string16 string = ui::FormatBytes(num_bytes); + ResolveJavascriptCallback(*callback_id, base::Value(string)); } void SiteSettingsHandler::HandleGetExceptionList(const base::ListValue* args) { @@ -1053,4 +1144,59 @@ void SiteSettingsHandler::HandleRemoveZoomLevel(const base::ListValue* args) { host_zoom_map->SetZoomLevelForHost(origin, default_level); } +void SiteSettingsHandler::HandleFetchBlockAutoplayStatus( + const base::ListValue* args) { + AllowJavascript(); + SendBlockAutoplayStatus(); +} + +void SiteSettingsHandler::SendBlockAutoplayStatus() { + if (!IsJavascriptAllowed()) + return; + + base::DictionaryValue status; + + // Whether the block autoplay toggle should be checked. + base::DictionaryValue pref; + pref.SetKey( + "value", + base::Value( + UnifiedAutoplayConfig::ShouldBlockAutoplay(profile_) && + UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable(profile_))); + status.SetKey("pref", std::move(pref)); + + // Whether the block autoplay toggle should be enabled. + status.SetKey("enabled", + base::Value(UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable( + profile_))); + + FireWebUIListener("onBlockAutoplayStatusChanged", status); +} + +void SiteSettingsHandler::HandleSetBlockAutoplayEnabled( + const base::ListValue* args) { + AllowJavascript(); + + if (!UnifiedAutoplayConfig::IsBlockAutoplayUserModifiable(profile_)) + return; + + CHECK_EQ(1U, args->GetSize()); + bool value; + CHECK(args->GetBoolean(0, &value)); + + profile_->GetPrefs()->SetBoolean(prefs::kBlockAutoplayEnabled, value); +} + +void SiteSettingsHandler::SetBrowsingDataLocalStorageHelperForTesting( + scoped_refptr<BrowsingDataLocalStorageHelper> helper) { + DCHECK(!local_storage_helper_); + local_storage_helper_ = helper; +} + +BrowsingDataLocalStorageHelper* SiteSettingsHandler::GetLocalStorageHelper() { + if (!local_storage_helper_) + local_storage_helper_ = new BrowsingDataLocalStorageHelper(profile_); + return local_storage_helper_.get(); +} + } // namespace settings 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 3f5b4a470ad..7a5f9c9b787 100644 --- a/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/site_settings_handler.h @@ -10,6 +10,7 @@ #include <vector> #include "base/scoped_observer.h" +#include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h" #include "chrome/browser/storage/storage_info_fetcher.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "components/content_settings/core/browser/content_settings_observer.h" @@ -22,9 +23,7 @@ class HostContentSettingsMap; class Profile; -#if defined(OS_CHROMEOS) class PrefChangeRegistrar; -#endif namespace base { class ListValue; @@ -85,12 +84,16 @@ class SiteSettingsHandler : public SettingsPageUIHandler, FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAndSetForInvalidURLs); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Incognito); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAllSites); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, GetAllSitesLocalStorage); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Origins); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, Patterns); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, ZoomLevels); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerInfobarTest, SettingPermissionsTriggersInfobar); FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, SessionOnlyException); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, + BlockAutoplay_SendOnRequest); + FRIEND_TEST_ALL_PREFIXES(SiteSettingsHandlerTest, BlockAutoplay_Update); // Asynchronously fetches the usage for a given origin. Replies back with // OnGetUsageInfo above. @@ -113,6 +116,16 @@ class SiteSettingsHandler : public SettingsPageUIHandler, // 1, affected by any of the content settings specified in |args|. void HandleGetAllSites(const base::ListValue* args); + // Called when the list of origins using local storage has been fetched, and + // sends this list back to the front end. + void OnLocalStorageFetched( + const std::list<BrowsingDataLocalStorageHelper::LocalStorageInfo>& + local_storage_info); + + // Converts a given number of bytes into a human-readable format, with data + // units. + void HandleGetFormattedBytes(const base::ListValue* args); + // Returns the list of site exceptions for a given content settings type. void HandleGetExceptionList(const base::ListValue* args); @@ -151,6 +164,20 @@ class SiteSettingsHandler : public SettingsPageUIHandler, // Removes a particular zoom level for a given host. void HandleRemoveZoomLevel(const base::ListValue* args); + // Handles the request to send block autoplay state. + void HandleFetchBlockAutoplayStatus(const base::ListValue* args); + + // Notifies the JS side about the state of the block autoplay toggle. + void SendBlockAutoplayStatus(); + + // Updates the block autoplay enabled pref when the UI is toggled. + void HandleSetBlockAutoplayEnabled(const base::ListValue* args); + + void SetBrowsingDataLocalStorageHelperForTesting( + scoped_refptr<BrowsingDataLocalStorageHelper> helper); + + BrowsingDataLocalStorageHelper* GetLocalStorageHelper(); + Profile* profile_; content::NotificationRegistrar notification_registrar_; @@ -168,10 +195,10 @@ class SiteSettingsHandler : public SettingsPageUIHandler, // Change observer for content settings. ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_; -#if defined(OS_CHROMEOS) // Change observer for prefs. std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; -#endif + + scoped_refptr<BrowsingDataLocalStorageHelper> local_storage_helper_; DISALLOW_COPY_AND_ASSIGN(SiteSettingsHandler); }; 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 2b1e3700934..301b05f54d6 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 @@ -9,6 +9,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/simple_test_clock.h" +#include "chrome/browser/browsing_data/mock_browsing_data_local_storage_helper.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/extensions/extension_service.h" @@ -18,6 +19,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/webui/site_settings_helper.h" +#include "chrome/common/pref_names.h" #include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/testing_profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" @@ -151,6 +153,36 @@ class SiteSettingsHandlerTest : public testing::Test { content::TestWebUI* web_ui() { return &web_ui_; } SiteSettingsHandler* handler() { return &handler_; } + void ValidateBlockAutoplay(bool expected_value, bool expected_enabled) { + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); + + std::string event_name; + ASSERT_TRUE(data.arg1()->GetAsString(&event_name)); + EXPECT_EQ("onBlockAutoplayStatusChanged", event_name); + + const base::DictionaryValue* event_data = nullptr; + ASSERT_TRUE(data.arg2()->GetAsDictionary(&event_data)); + + bool enabled; + ASSERT_TRUE(event_data->GetBoolean("enabled", &enabled)); + EXPECT_EQ(expected_enabled, enabled); + + const base::DictionaryValue* pref_data = nullptr; + ASSERT_TRUE(event_data->GetDictionary("pref", &pref_data)); + + bool value; + ASSERT_TRUE(pref_data->GetBoolean("value", &value)); + EXPECT_EQ(expected_value, value); + } + + void SetSoundContentSettingDefault(ContentSetting value) { + HostContentSettingsMap* content_settings = + HostContentSettingsMapFactory::GetForProfile(profile()); + content_settings->SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_SOUND, + value); + } + void ValidateDefault(const ContentSetting expected_setting, const site_settings::SiteSettingSource expected_source, size_t expected_total_calls) { @@ -407,8 +439,10 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { site_group.FindKey("origins")->GetList(); EXPECT_EQ("example.com", etld_plus1_string); EXPECT_EQ(2UL, origin_list.size()); - EXPECT_EQ(url1.spec(), origin_list[0].GetString()); - EXPECT_EQ(url2.spec(), origin_list[1].GetString()); + EXPECT_EQ(url1.spec(), origin_list[0].FindKey("origin")->GetString()); + EXPECT_EQ(0, origin_list[0].FindKey("engagement")->GetDouble()); + EXPECT_EQ(url2.spec(), origin_list[1].FindKey("origin")->GetString()); + EXPECT_EQ(0, origin_list[1].FindKey("engagement")->GetDouble()); } } @@ -434,7 +468,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { site_group.FindKey("origins")->GetList(); if (etld_plus1_string == "example2.net") { EXPECT_EQ(1UL, origin_list.size()); - EXPECT_EQ(url3.spec(), origin_list[0].GetString()); + EXPECT_EQ(url3.spec(), origin_list[0].FindKey("origin")->GetString()); } else { EXPECT_EQ("example.com", etld_plus1_string); } @@ -444,6 +478,9 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { // Test embargoed settings also appear. PermissionDecisionAutoBlocker* auto_blocker = PermissionDecisionAutoBlocker::GetForProfile(profile()); + base::SimpleTestClock clock; + clock.SetNow(base::Time::Now()); + auto_blocker->SetClockForTesting(&clock); const GURL url4("https://example2.co.uk"); for (int i = 0; i < 3; ++i) { auto_blocker->RecordDismissAndEmbargo(url4, @@ -465,11 +502,24 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { EXPECT_EQ(3UL, site_groups.size()); } - // Add an expired embargo setting to a) an existing eTLD+1 group and b) a new - // eTLD+1 group. - base::SimpleTestClock clock; - clock.SetNow(base::Time::Now()); - auto_blocker->SetClockForTesting(&clock); + // Check |url4| disappears from the list when its embargo expires. + clock.Advance(base::TimeDelta::FromDays(8)); + handler()->HandleGetAllSites(&get_all_sites_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()); + + const base::Value::ListStorage& site_groups = data.arg3()->GetList(); + EXPECT_EQ(2UL, site_groups.size()); + EXPECT_EQ("example.com", site_groups[0].FindKey("etldPlus1")->GetString()); + EXPECT_EQ("example2.net", site_groups[1].FindKey("etldPlus1")->GetString()); + } + + // Add an expired embargo setting to an existing eTLD+1 group and make sure it + // still appears. for (int i = 0; i < 3; ++i) { auto_blocker->RecordDismissAndEmbargo(url3, CONTENT_SETTINGS_TYPE_NOTIFICATIONS); @@ -484,6 +534,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { auto_blocker->GetEmbargoResult(url3, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) .content_setting); + handler()->HandleGetAllSites(&get_all_sites_args); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -491,10 +542,12 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { ASSERT_TRUE(data.arg2()->GetBool()); const base::Value::ListStorage& site_groups = data.arg3()->GetList(); - EXPECT_EQ(3UL, site_groups.size()); + EXPECT_EQ(2UL, site_groups.size()); + EXPECT_EQ("example.com", site_groups[0].FindKey("etldPlus1")->GetString()); + EXPECT_EQ("example2.net", site_groups[1].FindKey("etldPlus1")->GetString()); } - clock.SetNow(base::Time::Now()); + // Add an expired embargo to a new eTLD+1 and make sure it doesn't appear. const GURL url5("http://test.example5.com"); for (int i = 0; i < 3; ++i) { auto_blocker->RecordDismissAndEmbargo(url5, @@ -510,6 +563,7 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { auto_blocker->GetEmbargoResult(url5, CONTENT_SETTINGS_TYPE_NOTIFICATIONS) .content_setting); + handler()->HandleGetAllSites(&get_all_sites_args); { const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); EXPECT_EQ("cr.webUIResponse", data.function_name()); @@ -517,8 +571,71 @@ TEST_F(SiteSettingsHandlerTest, GetAllSites) { ASSERT_TRUE(data.arg2()->GetBool()); const base::Value::ListStorage& site_groups = data.arg3()->GetList(); - EXPECT_EQ(3UL, site_groups.size()); + EXPECT_EQ(2UL, site_groups.size()); + EXPECT_EQ("example.com", site_groups[0].FindKey("etldPlus1")->GetString()); + EXPECT_EQ("example2.net", site_groups[1].FindKey("etldPlus1")->GetString()); } + + // Each call to HandleGetAllSites() above added a callback to the profile's + // BrowsingDataLocalStorageHelper, so make sure these aren't stuck waiting to + // run at the end of the test. + base::RunLoop run_loop; + run_loop.RunUntilIdle(); +} + +TEST_F(SiteSettingsHandlerTest, GetAllSitesLocalStorage) { + scoped_refptr<MockBrowsingDataLocalStorageHelper> + mock_browsing_data_local_storage_helper = + new MockBrowsingDataLocalStorageHelper(profile()); + handler()->SetBrowsingDataLocalStorageHelperForTesting( + mock_browsing_data_local_storage_helper); + + // Add local storage for |origin|. + const GURL origin("https://example.com:12378"); + mock_browsing_data_local_storage_helper->AddLocalStorageForOrigin(origin, 1); + + // Check these sites are included in the callback. + base::ListValue get_all_sites_args; + get_all_sites_args.AppendString(kCallbackId); + base::Value category_list(base::Value::Type::LIST); + get_all_sites_args.GetList().push_back(std::move(category_list)); + + // Wait for the fetch handler to finish, then check it includes |origin| in + // its result. + handler()->HandleGetAllSites(&get_all_sites_args); + EXPECT_EQ(1U, web_ui()->call_data().size()); + mock_browsing_data_local_storage_helper->Notify(); + EXPECT_EQ(2U, web_ui()->call_data().size()); + base::RunLoop run_loop; + run_loop.RunUntilIdle(); + + const content::TestWebUI::CallData& data = *web_ui()->call_data().back(); + EXPECT_EQ("cr.webUIListenerCallback", data.function_name()); + + std::string callback_id; + ASSERT_TRUE(data.arg1()->GetAsString(&callback_id)); + EXPECT_EQ("onLocalStorageListFetched", callback_id); + + const base::ListValue* local_storage_list; + ASSERT_TRUE(data.arg2()->GetAsList(&local_storage_list)); + EXPECT_EQ(1U, local_storage_list->GetSize()); + + const base::DictionaryValue* site_group; + ASSERT_TRUE(local_storage_list->GetDictionary(0, &site_group)); + + std::string etld_plus1_string; + ASSERT_TRUE(site_group->GetString("etldPlus1", &etld_plus1_string)); + ASSERT_EQ("example.com", etld_plus1_string); + + const base::ListValue* origin_list; + ASSERT_TRUE(site_group->GetList("origins", &origin_list)); + EXPECT_EQ(1U, origin_list->GetSize()); + + const base::DictionaryValue* origin_info; + ASSERT_TRUE(origin_list->GetDictionary(0, &origin_info)); + EXPECT_EQ(origin.spec(), origin_info->FindKey("origin")->GetString()); + EXPECT_EQ(0, origin_info->FindKey("engagement")->GetDouble()); + EXPECT_EQ(1, origin_info->FindKey("usage")->GetDouble()); } TEST_F(SiteSettingsHandlerTest, Origins) { @@ -1147,4 +1264,50 @@ TEST_F(SiteSettingsHandlerTest, SessionOnlyException) { histograms.ExpectTotalCount(uma_base + ".SessionOnly", 1); } +TEST_F(SiteSettingsHandlerTest, BlockAutoplay_SendOnRequest) { + base::ListValue args; + handler()->HandleFetchBlockAutoplayStatus(&args); + + // Check that we are checked and enabled. + ValidateBlockAutoplay(true, true); +} + +TEST_F(SiteSettingsHandlerTest, BlockAutoplay_SoundSettingUpdate) { + SetSoundContentSettingDefault(CONTENT_SETTING_BLOCK); + base::RunLoop().RunUntilIdle(); + + // Check that we are not checked or enabled. + ValidateBlockAutoplay(false, false); + + SetSoundContentSettingDefault(CONTENT_SETTING_ALLOW); + base::RunLoop().RunUntilIdle(); + + // Check that we are checked and enabled. + ValidateBlockAutoplay(true, true); +} + +TEST_F(SiteSettingsHandlerTest, BlockAutoplay_PrefUpdate) { + profile()->GetPrefs()->SetBoolean(prefs::kBlockAutoplayEnabled, false); + base::RunLoop().RunUntilIdle(); + + // Check that we are not checked but are enabled. + ValidateBlockAutoplay(false, true); + + profile()->GetPrefs()->SetBoolean(prefs::kBlockAutoplayEnabled, true); + base::RunLoop().RunUntilIdle(); + + // Check that we are checked and enabled. + ValidateBlockAutoplay(true, true); +} + +TEST_F(SiteSettingsHandlerTest, BlockAutoplay_Update) { + EXPECT_TRUE(profile()->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled)); + + base::ListValue data; + data.AppendBoolean(false); + + handler()->HandleSetBlockAutoplayEnabled(&data); + EXPECT_FALSE(profile()->GetPrefs()->GetBoolean(prefs::kBlockAutoplayEnabled)); +} + } // namespace settings diff --git a/chromium/chrome/browser/ui/webui/settings/tts_handler.cc b/chromium/chrome/browser/ui/webui/settings/tts_handler.cc index 0984278d7eb..d4298910124 100644 --- a/chromium/chrome/browser/ui/webui/settings/tts_handler.cc +++ b/chromium/chrome/browser/ui/webui/settings/tts_handler.cc @@ -18,12 +18,18 @@ #include "content/public/browser/web_ui.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/process_manager.h" #include "extensions/common/extension.h" #include "extensions/common/extension_set.h" #include "extensions/common/manifest_handlers/options_page_info.h" #include "ui/base/l10n/l10n_util.h" namespace settings { +TtsHandler::TtsHandler() : weak_factory_(this) {} + +TtsHandler::~TtsHandler() { + TtsController::GetInstance()->RemoveVoicesChangedDelegate(this); +} void TtsHandler::HandleGetAllTtsVoiceData(const base::ListValue* args) { OnVoicesChanged(); @@ -31,8 +37,8 @@ void TtsHandler::HandleGetAllTtsVoiceData(const base::ListValue* args) { void TtsHandler::HandleGetTtsExtensions(const base::ListValue* args) { // Ensure the built in tts engine is loaded to be able to respond to messages. - TtsExtensionEngine::GetInstance()->LoadBuiltInTtsExtension( - Profile::FromWebUI(web_ui())); + WakeTtsEngine(nullptr); + base::ListValue responses; Profile* profile = Profile::FromWebUI(web_ui()); extensions::ExtensionRegistry* registry = @@ -141,6 +147,9 @@ void TtsHandler::RegisterMessages() { web_ui()->RegisterMessageCallback( "previewTtsVoice", base::BindRepeating(&TtsHandler::HandlePreviewTtsVoice, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + "wakeTtsEngine", + base::BindRepeating(&TtsHandler::WakeTtsEngine, base::Unretained(this))); } void TtsHandler::OnJavascriptAllowed() { @@ -163,4 +172,17 @@ int TtsHandler::GetVoiceLangMatchScore(const VoiceData* voice, : 0; } +void TtsHandler::WakeTtsEngine(const base::ListValue* args) { + Profile* profile = Profile::FromWebUI(web_ui()); + TtsExtensionEngine::GetInstance()->LoadBuiltInTtsExtension(profile); + extensions::ProcessManager::Get(profile)->WakeEventPage( + extension_misc::kSpeechSynthesisExtensionId, + base::BindRepeating(&TtsHandler::OnTtsEngineAwake, + weak_factory_.GetWeakPtr())); +} + +void TtsHandler::OnTtsEngineAwake(bool success) { + OnVoicesChanged(); +} + } // 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 94dfef0c727..0f9d26426d8 100644 --- a/chromium/chrome/browser/ui/webui/settings/tts_handler.h +++ b/chromium/chrome/browser/ui/webui/settings/tts_handler.h @@ -5,16 +5,19 @@ #ifndef CHROME_BROWSER_UI_WEBUI_SETTINGS_TTS_HANDLER_H_ #define CHROME_BROWSER_UI_WEBUI_SETTINGS_TTS_HANDLER_H_ +#include "base/memory/weak_ptr.h" #include "chrome/browser/speech/tts_controller.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" +class Profile; + namespace settings { // Chrome "/manageAccessibility/tts/*" settings page UI handler. class TtsHandler : public SettingsPageUIHandler, public VoicesChangedDelegate { public: - TtsHandler() = default; - ~TtsHandler() override = default; + TtsHandler(); + ~TtsHandler() override; void HandleGetAllTtsVoiceData(const base::ListValue* args); void HandleGetTtsExtensions(const base::ListValue* args); @@ -29,9 +32,13 @@ class TtsHandler : public SettingsPageUIHandler, public VoicesChangedDelegate { void OnVoicesChanged() override; private: + void WakeTtsEngine(const base::ListValue* args); + void OnTtsEngineAwake(bool success); int GetVoiceLangMatchScore(const VoiceData* voice, const std::string& app_locale); + base::WeakPtrFactory<TtsHandler> weak_factory_; + DISALLOW_COPY_AND_ASSIGN(TtsHandler); }; |