Commit 5c8b9bec authored by Jeffrey Young's avatar Jeffrey Young Committed by Chromium LUCI CQ

ambient: only update settings when pref enabled

There was a case when |UpdateSettings| could be called the first time
a user opened Ambient mode settings, even when Ambient mode was
disabled. Now, only update settings if pref is enabled.

Additionally, issue an |UpdateSettings| call when the pref is
enabled. This ensures that Ambient settings are synced to server even
when a user does not edit temperature settings or photo albums.

BUG=b:177456397
TEST=unit_tests --gtest_filter=AmbientModeHandlerTest.*
TEST=open settings page, personalization, screen saver, toggle ambient

Cq-Include-Trybots: luci.chrome.try:linux-chromeos-chrome
Change-Id: I924af998954927f0fc38746b34b8fce1ff641509
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2631305Reviewed-by: default avatarJimmy Gong <jimmyxgong@chromium.org>
Reviewed-by: default avatarXiaohui Chen <xiaohuic@chromium.org>
Reviewed-by: default avatarTao Wu <wutao@chromium.org>
Commit-Queue: Jeffrey Young <cowmoo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#845050}
parent 38aeef20
...@@ -119,6 +119,8 @@ void FakeAmbientBackendControllerImpl::GetSettings( ...@@ -119,6 +119,8 @@ void FakeAmbientBackendControllerImpl::GetSettings(
void FakeAmbientBackendControllerImpl::UpdateSettings( void FakeAmbientBackendControllerImpl::UpdateSettings(
const AmbientSettings& settings, const AmbientSettings& settings,
UpdateSettingsCallback callback) { UpdateSettingsCallback callback) {
// |show_weather| should always be set to true.
DCHECK(settings.show_weather);
pending_update_callback_ = std::move(callback); pending_update_callback_ = std::move(callback);
} }
...@@ -162,13 +164,14 @@ FakeAmbientBackendControllerImpl::GetBackupPhotoUrls() const { ...@@ -162,13 +164,14 @@ FakeAmbientBackendControllerImpl::GetBackupPhotoUrls() const {
} }
void FakeAmbientBackendControllerImpl::ReplyFetchSettingsAndAlbums( void FakeAmbientBackendControllerImpl::ReplyFetchSettingsAndAlbums(
bool success) { bool success,
const base::Optional<AmbientSettings>& settings) {
if (!pending_fetch_settings_albums_callback_) if (!pending_fetch_settings_albums_callback_)
return; return;
if (success) { if (success) {
std::move(pending_fetch_settings_albums_callback_) std::move(pending_fetch_settings_albums_callback_)
.Run(CreateFakeSettings(), CreateFakeAlbums()); .Run(settings.value_or(CreateFakeSettings()), CreateFakeAlbums());
} else { } else {
std::move(pending_fetch_settings_albums_callback_) std::move(pending_fetch_settings_albums_callback_)
.Run(/*settings=*/base::nullopt, PersonalAlbums()); .Run(/*settings=*/base::nullopt, PersonalAlbums());
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ash/public/cpp/ambient/ambient_backend_controller.h" #include "ash/public/cpp/ambient/ambient_backend_controller.h"
#include "ash/public/cpp/ash_public_export.h" #include "ash/public/cpp/ash_public_export.h"
#include "base/callback.h" #include "base/callback.h"
#include "base/optional.h"
namespace ash { namespace ash {
...@@ -46,7 +47,11 @@ class ASH_PUBLIC_EXPORT FakeAmbientBackendControllerImpl ...@@ -46,7 +47,11 @@ class ASH_PUBLIC_EXPORT FakeAmbientBackendControllerImpl
// Simulate to reply the request of FetchSettingsAndAlbums(). // Simulate to reply the request of FetchSettingsAndAlbums().
// If |success| is true, will return fake data. // If |success| is true, will return fake data.
// If |success| is false, will return null |settings| data. // If |success| is false, will return null |settings| data.
void ReplyFetchSettingsAndAlbums(bool success); // If |settings| contains a value, that will be used as the argument to
// the pending callback.
void ReplyFetchSettingsAndAlbums(
bool success,
const base::Optional<AmbientSettings>& settings = base::nullopt);
// Whether there is a pending FetchSettingsAndAlbums() request. // Whether there is a pending FetchSettingsAndAlbums() request.
bool IsFetchSettingsAndAlbumsPending() const; bool IsFetchSettingsAndAlbumsPending() const;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "ash/public/cpp/ambient/ambient_backend_controller.h" #include "ash/public/cpp/ambient/ambient_backend_controller.h"
#include "ash/public/cpp/ambient/ambient_metrics.h" #include "ash/public/cpp/ambient/ambient_metrics.h"
#include "ash/public/cpp/ambient/ambient_prefs.h"
#include "ash/public/cpp/ambient/common/ambient_settings.h" #include "ash/public/cpp/ambient/common/ambient_settings.h"
#include "ash/public/cpp/image_downloader.h" #include "ash/public/cpp/image_downloader.h"
#include "base/barrier_closure.h" #include "base/barrier_closure.h"
...@@ -25,6 +26,7 @@ ...@@ -25,6 +26,7 @@
#include "base/values.h" #include "base/values.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_features.h"
#include "components/prefs/pref_service.h"
#include "net/traffic_annotation/network_traffic_annotation.h" #include "net/traffic_annotation/network_traffic_annotation.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
...@@ -124,9 +126,10 @@ base::string16 GetAlbumDescription(const ash::PersonalAlbum& album) { ...@@ -124,9 +126,10 @@ base::string16 GetAlbumDescription(const ash::PersonalAlbum& album) {
} // namespace } // namespace
AmbientModeHandler::AmbientModeHandler() AmbientModeHandler::AmbientModeHandler(PrefService* pref_service)
: fetch_settings_retry_backoff_(&kRetryBackoffPolicy), : fetch_settings_retry_backoff_(&kRetryBackoffPolicy),
update_settings_retry_backoff_(&kRetryBackoffPolicy) {} update_settings_retry_backoff_(&kRetryBackoffPolicy),
pref_service_(pref_service) {}
AmbientModeHandler::~AmbientModeHandler() = default; AmbientModeHandler::~AmbientModeHandler() = default;
...@@ -152,9 +155,30 @@ void AmbientModeHandler::RegisterMessages() { ...@@ -152,9 +155,30 @@ void AmbientModeHandler::RegisterMessages() {
base::Unretained(this))); base::Unretained(this)));
} }
void AmbientModeHandler::OnJavascriptAllowed() {
pref_change_registrar_.Init(pref_service_);
pref_change_registrar_.Add(
ash::ambient::prefs::kAmbientModeEnabled,
base::BindRepeating(&AmbientModeHandler::OnEnabledPrefChanged,
base::Unretained(this)));
}
void AmbientModeHandler::OnJavascriptDisallowed() { void AmbientModeHandler::OnJavascriptDisallowed() {
backend_weak_factory_.InvalidateWeakPtrs(); backend_weak_factory_.InvalidateWeakPtrs();
ui_update_weak_factory_.InvalidateWeakPtrs(); ui_update_weak_factory_.InvalidateWeakPtrs();
pref_change_registrar_.RemoveAll();
}
bool AmbientModeHandler::IsAmbientModeEnabled() {
return pref_service_->GetBoolean(ash::ambient::prefs::kAmbientModeEnabled);
}
void AmbientModeHandler::OnEnabledPrefChanged() {
// Call |UpdateSettings| when Ambient mode is enabled to make sure that
// settings are properly synced to the server even if the user never touches
// the other controls.
if (settings_ && IsAmbientModeEnabled())
UpdateSettings();
} }
void AmbientModeHandler::HandleRequestSettings(const base::ListValue* args) { void AmbientModeHandler::HandleRequestSettings(const base::ListValue* args) {
...@@ -347,6 +371,10 @@ void AmbientModeHandler::SendRecentHighlightsPreviews() { ...@@ -347,6 +371,10 @@ void AmbientModeHandler::SendRecentHighlightsPreviews() {
} }
void AmbientModeHandler::UpdateSettings() { void AmbientModeHandler::UpdateSettings() {
DCHECK(IsAmbientModeEnabled())
<< "Ambient mode must be enabled to update settings";
DCHECK(settings_);
// Prevent fetch settings callback changing |settings_| and |personal_albums_| // Prevent fetch settings callback changing |settings_| and |personal_albums_|
// while updating. // while updating.
ui_update_weak_factory_.InvalidateWeakPtrs(); ui_update_weak_factory_.InvalidateWeakPtrs();
...@@ -359,7 +387,10 @@ void AmbientModeHandler::UpdateSettings() { ...@@ -359,7 +387,10 @@ void AmbientModeHandler::UpdateSettings() {
has_pending_updates_for_backend_ = false; has_pending_updates_for_backend_ = false;
is_updating_backend_ = true; is_updating_backend_ = true;
DCHECK(settings_); // Explicitly set show_weather to true to force server to respond with
// weather information. See: b/158630188.
settings_->show_weather = true;
settings_sent_for_update_ = settings_; settings_sent_for_update_ = settings_;
ash::AmbientBackendController::Get()->UpdateSettings( ash::AmbientBackendController::Get()->UpdateSettings(
*settings_, base::BindOnce(&AmbientModeHandler::OnUpdateSettings, *settings_, base::BindOnce(&AmbientModeHandler::OnUpdateSettings,
...@@ -475,14 +506,9 @@ void AmbientModeHandler::OnSettingsAndAlbumsFetched( ...@@ -475,14 +506,9 @@ void AmbientModeHandler::OnSettingsAndAlbumsFetched(
SendTopicSource(); SendTopicSource();
SendTemperatureUnit(); SendTemperatureUnit();
// Explicitly enable the weather settings if necessary to make sure we // If weather info is disabled, call |UpdateSettings| immediately to force
// can always get weather info in the response. Leaving this settings as // it to true.
// default could result in unpredictable behavior (b/158630188). Note that if (!settings_->show_weather && IsAmbientModeEnabled()) {
// right now the weather info is designed to be always shown on ambient
// screen, so we don't expose an option in ambient Settings for users to
// switch it off.
if (!settings_->show_weather) {
settings_->show_weather = true;
UpdateSettings(); UpdateSettings();
} }
return; return;
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/optional.h" #include "base/optional.h"
#include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h" #include "chrome/browser/ui/webui/settings/settings_page_ui_handler.h"
#include "components/prefs/pref_change_registrar.h"
#include "net/base/backoff_entry.h" #include "net/base/backoff_entry.h"
namespace ash { namespace ash {
...@@ -26,6 +27,8 @@ namespace gfx { ...@@ -26,6 +27,8 @@ namespace gfx {
class ImageSkia; class ImageSkia;
} // namespace gfx } // namespace gfx
class PrefService;
namespace chromeos { namespace chromeos {
namespace settings { namespace settings {
...@@ -33,19 +36,23 @@ namespace settings { ...@@ -33,19 +36,23 @@ namespace settings {
// photo frame and other related functionalities. // photo frame and other related functionalities.
class AmbientModeHandler : public ::settings::SettingsPageUIHandler { class AmbientModeHandler : public ::settings::SettingsPageUIHandler {
public: public:
AmbientModeHandler(); explicit AmbientModeHandler(PrefService* pref_service);
AmbientModeHandler(const AmbientModeHandler&) = delete; AmbientModeHandler(const AmbientModeHandler&) = delete;
AmbientModeHandler& operator=(const AmbientModeHandler&) = delete; AmbientModeHandler& operator=(const AmbientModeHandler&) = delete;
~AmbientModeHandler() override; ~AmbientModeHandler() override;
// settings::SettingsPageUIHandler: // settings::SettingsPageUIHandler:
void RegisterMessages() override; void RegisterMessages() override;
void OnJavascriptAllowed() override {} void OnJavascriptAllowed() override;
void OnJavascriptDisallowed() override; void OnJavascriptDisallowed() override;
private: private:
friend class AmbientModeHandlerTest; friend class AmbientModeHandlerTest;
bool IsAmbientModeEnabled();
void OnEnabledPrefChanged();
// WebUI call to request topic source and temperature unit related data. // WebUI call to request topic source and temperature unit related data.
void HandleRequestSettings(const base::ListValue* args); void HandleRequestSettings(const base::ListValue* args);
...@@ -162,6 +169,10 @@ class AmbientModeHandler : public ::settings::SettingsPageUIHandler { ...@@ -162,6 +169,10 @@ class AmbientModeHandler : public ::settings::SettingsPageUIHandler {
std::vector<gfx::ImageSkia> recent_highlights_preview_images_; std::vector<gfx::ImageSkia> recent_highlights_preview_images_;
PrefService* pref_service_;
PrefChangeRegistrar pref_change_registrar_;
base::WeakPtrFactory<AmbientModeHandler> backend_weak_factory_{this}; base::WeakPtrFactory<AmbientModeHandler> backend_weak_factory_{this};
base::WeakPtrFactory<AmbientModeHandler> ui_update_weak_factory_{this}; base::WeakPtrFactory<AmbientModeHandler> ui_update_weak_factory_{this};
base::WeakPtrFactory<AmbientModeHandler> base::WeakPtrFactory<AmbientModeHandler>
......
...@@ -6,11 +6,14 @@ ...@@ -6,11 +6,14 @@
#include <memory> #include <memory>
#include "ash/public/cpp/ambient/ambient_prefs.h"
#include "ash/public/cpp/ambient/common/ambient_settings.h" #include "ash/public/cpp/ambient/common/ambient_settings.h"
#include "ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h" #include "ash/public/cpp/ambient/fake_ambient_backend_controller_impl.h"
#include "ash/public/cpp/test/test_image_downloader.h" #include "ash/public/cpp/test/test_image_downloader.h"
#include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/histogram_tester.h"
#include "chrome/test/base/browser_with_test_window_test.h" #include "chrome/test/base/browser_with_test_window_test.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/test_web_ui.h" #include "content/public/test/test_web_ui.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -24,7 +27,8 @@ const char kWebCallbackFunctionName[] = "cr.webUIListenerCallback"; ...@@ -24,7 +27,8 @@ const char kWebCallbackFunctionName[] = "cr.webUIListenerCallback";
class TestAmbientModeHandler : public AmbientModeHandler { class TestAmbientModeHandler : public AmbientModeHandler {
public: public:
TestAmbientModeHandler() = default; explicit TestAmbientModeHandler(PrefService* pref_service)
: AmbientModeHandler(pref_service) {}
~TestAmbientModeHandler() override = default; ~TestAmbientModeHandler() override = default;
// Make public for testing. // Make public for testing.
...@@ -42,7 +46,13 @@ class AmbientModeHandlerTest : public testing::Test { ...@@ -42,7 +46,13 @@ class AmbientModeHandlerTest : public testing::Test {
void SetUp() override { void SetUp() override {
web_ui_ = std::make_unique<content::TestWebUI>(); web_ui_ = std::make_unique<content::TestWebUI>();
handler_ = std::make_unique<TestAmbientModeHandler>(); test_pref_service_ = std::make_unique<TestingPrefServiceSimple>();
test_pref_service_->registry()->RegisterBooleanPref(
ash::ambient::prefs::kAmbientModeEnabled, true);
handler_ =
std::make_unique<TestAmbientModeHandler>(test_pref_service_.get());
handler_->set_web_ui(web_ui_.get()); handler_->set_web_ui(web_ui_.get());
handler_->RegisterMessages(); handler_->RegisterMessages();
handler_->AllowJavascript(); handler_->AllowJavascript();
...@@ -51,12 +61,23 @@ class AmbientModeHandlerTest : public testing::Test { ...@@ -51,12 +61,23 @@ class AmbientModeHandlerTest : public testing::Test {
image_downloader_ = std::make_unique<ash::TestImageDownloader>(); image_downloader_ = std::make_unique<ash::TestImageDownloader>();
} }
void TearDown() override { handler_->DisallowJavascript(); }
content::TestWebUI* web_ui() { return web_ui_.get(); } content::TestWebUI* web_ui() { return web_ui_.get(); }
const base::HistogramTester& histogram_tester() const { const base::HistogramTester& histogram_tester() const {
return histogram_tester_; return histogram_tester_;
} }
base::Optional<ash::AmbientSettings>& settings() {
return handler_->settings_;
}
void SetEnabledPref(bool enabled) {
test_pref_service_->SetBoolean(ash::ambient::prefs::kAmbientModeEnabled,
enabled);
}
void SetTopicSource(ash::AmbientModeTopicSource topic_source) { void SetTopicSource(ash::AmbientModeTopicSource topic_source) {
if (!handler_->settings_) if (!handler_->settings_)
handler_->settings_ = ash::AmbientSettings(); handler_->settings_ = ash::AmbientSettings();
...@@ -129,8 +150,11 @@ class AmbientModeHandlerTest : public testing::Test { ...@@ -129,8 +150,11 @@ class AmbientModeHandlerTest : public testing::Test {
return fake_backend_controller_->IsFetchSettingsAndAlbumsPending(); return fake_backend_controller_->IsFetchSettingsAndAlbumsPending();
} }
void ReplyFetchSettingsAndAlbums(bool success) { void ReplyFetchSettingsAndAlbums(
fake_backend_controller_->ReplyFetchSettingsAndAlbums(success); bool success,
base::Optional<ash::AmbientSettings> settings = base::nullopt) {
fake_backend_controller_->ReplyFetchSettingsAndAlbums(success,
std::move(settings));
} }
bool IsUpdateSettingsPendingAtBackend() const { bool IsUpdateSettingsPendingAtBackend() const {
...@@ -234,6 +258,7 @@ class AmbientModeHandlerTest : public testing::Test { ...@@ -234,6 +258,7 @@ class AmbientModeHandlerTest : public testing::Test {
std::unique_ptr<ash::TestImageDownloader> image_downloader_; std::unique_ptr<ash::TestImageDownloader> image_downloader_;
std::unique_ptr<TestAmbientModeHandler> handler_; std::unique_ptr<TestAmbientModeHandler> handler_;
base::HistogramTester histogram_tester_; base::HistogramTester histogram_tester_;
std::unique_ptr<TestingPrefServiceSimple> test_pref_service_;
}; };
TEST_F(AmbientModeHandlerTest, TestSendTemperatureUnitAndTopicSource) { TEST_F(AmbientModeHandlerTest, TestSendTemperatureUnitAndTopicSource) {
...@@ -781,5 +806,49 @@ TEST_F(AmbientModeHandlerTest, TestSameTemperatureUnitSkipsUpdate) { ...@@ -781,5 +806,49 @@ TEST_F(AmbientModeHandlerTest, TestSameTemperatureUnitSkipsUpdate) {
EXPECT_FALSE(IsUpdateSettingsPendingAtBackend()); EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
} }
TEST_F(AmbientModeHandlerTest, TestEnabledPrefChangeUpdatesSettings) {
// Simulate initial page request.
RequestSettings();
ReplyFetchSettingsAndAlbums(/*success=*/true);
EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
// Should not trigger |UpdateSettings|.
SetEnabledPref(/*enabled=*/false);
EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
// Settings this to true should trigger |UpdateSettings|.
SetEnabledPref(/*enabled=*/true);
EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
}
TEST_F(AmbientModeHandlerTest, TestWeatherFalseTriggersUpdateSettings) {
ash::AmbientSettings weather_off_settings;
weather_off_settings.show_weather = false;
// Simulate initial page request with weather settings false. Because Ambient
// mode pref is enabled and |settings.show_weather| is false, this should
// trigger a call to |UpdateSettings| that sets |settings.show_weather| to
// true.
RequestSettings();
ReplyFetchSettingsAndAlbums(/*success=*/true, weather_off_settings);
// A call to |UpdateSettings| should have happened.
EXPECT_TRUE(IsUpdateSettingsPendingAtHandler());
EXPECT_TRUE(IsUpdateSettingsPendingAtBackend());
ReplyUpdateSettings(/*success=*/true);
EXPECT_FALSE(IsUpdateSettingsPendingAtHandler());
EXPECT_FALSE(IsUpdateSettingsPendingAtBackend());
// |settings.show_weather| should now be true after the successful settings
// update.
EXPECT_TRUE(settings()->show_weather);
}
} // namespace settings } // namespace settings
} // namespace chromeos } // namespace chromeos
...@@ -260,7 +260,8 @@ void PersonalizationSection::AddHandlers(content::WebUI* web_ui) { ...@@ -260,7 +260,8 @@ void PersonalizationSection::AddHandlers(content::WebUI* web_ui) {
if (!profile()->IsGuestSession() && if (!profile()->IsGuestSession() &&
chromeos::features::IsAmbientModeEnabled()) { chromeos::features::IsAmbientModeEnabled()) {
web_ui->AddMessageHandler( web_ui->AddMessageHandler(
std::make_unique<chromeos::settings::AmbientModeHandler>()); std::make_unique<chromeos::settings::AmbientModeHandler>(
pref_service_));
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment