blob: 6391d432321d20e7e83ab90e85184f7317142459 [file] [log] [blame]
// Copyright 2022 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 "ash/system/camera/autozoom_nudge_controller.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/system/camera/autozoom_controller_impl.h"
#include "ash/system/camera/autozoom_nudge.h"
#include "base/json/values_util.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
namespace ash {
namespace {
// Keys for autozoom nudge sub-preferences for shown count and last time shown.
constexpr char kShownCount[] = "shown_count";
constexpr char kLastTimeShown[] = "last_time_shown";
constexpr char kHadEnabled[] = "had_enabled";
constexpr int kNotificationLimit = 3;
constexpr base::TimeDelta kMinInterval = base::Days(1);
} // namespace
AutozoomNudgeController::AutozoomNudgeController(
AutozoomControllerImpl* autozoom_controller)
: autozoom_controller_(autozoom_controller) {
autozoom_controller_->AddObserver(this);
auto* camera_hal_dispatcher = media::CameraHalDispatcherImpl::GetInstance();
if (camera_hal_dispatcher)
camera_hal_dispatcher->AddActiveClientObserver(this);
if (base::FeatureList::IsEnabled(features::kAutozoomNudgeSessionReset))
Shell::Get()->session_controller()->AddObserver(this);
}
AutozoomNudgeController::~AutozoomNudgeController() {
autozoom_controller_->RemoveObserver(this);
auto* camera_hal_dispatcher = media::CameraHalDispatcherImpl::GetInstance();
if (camera_hal_dispatcher)
camera_hal_dispatcher->RemoveActiveClientObserver(this);
if (base::FeatureList::IsEnabled(features::kAutozoomNudgeSessionReset))
Shell::Get()->session_controller()->RemoveObserver(this);
}
// static
void AutozoomNudgeController::RegisterProfilePrefs(
PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kAutozoomNudges);
}
void AutozoomNudgeController::OnActiveUserPrefServiceChanged(
PrefService* prefs) {
// Reset the nudge prefs so that the nudge can be shown again. This observer
// callback is only registered and called when
// features::kAutozoomNudgeSessionReset is enabled.
DictionaryPrefUpdate update(prefs, prefs::kAutozoomNudges);
update->SetIntPath(kShownCount, 0);
update->SetPath(kLastTimeShown, base::TimeToValue(base::Time()));
update->SetBoolPath(kHadEnabled, false);
}
base::Time AutozoomNudgeController::GetTime() {
return base::Time::Now();
}
void AutozoomNudgeController::HandleNudgeShown() {
PrefService* prefs =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
if (!prefs)
return;
const int shown_count = GetShownCount(prefs);
DictionaryPrefUpdate update(prefs, prefs::kAutozoomNudges);
update->SetIntPath(kShownCount, shown_count + 1);
update->SetPath(kLastTimeShown, base::TimeToValue(GetTime()));
}
bool AutozoomNudgeController::GetHadEnabled(PrefService* prefs) {
const base::Value* dictionary = prefs->GetDictionary(prefs::kAutozoomNudges);
if (!dictionary)
return false;
return dictionary->FindBoolPath(kHadEnabled).value_or(false);
}
int AutozoomNudgeController::GetShownCount(PrefService* prefs) {
const base::Value* dictionary = prefs->GetDictionary(prefs::kAutozoomNudges);
if (!dictionary)
return 0;
return dictionary->FindIntPath(kShownCount).value_or(0);
}
base::Time AutozoomNudgeController::GetLastShownTime(PrefService* prefs) {
const base::Value* dictionary = prefs->GetDictionary(prefs::kAutozoomNudges);
if (!dictionary)
return base::Time();
absl::optional<base::Time> last_shown_time =
base::ValueToTime(dictionary->FindPath(kLastTimeShown));
return last_shown_time.value_or(base::Time());
}
bool AutozoomNudgeController::ShouldShowNudge(PrefService* prefs) {
if (!prefs)
return false;
bool had_enabled = GetHadEnabled(prefs);
// We should not show more nudge after user had enabled autozoom before.
if (had_enabled)
return false;
int nudge_shown_count = GetShownCount(prefs);
// We should not show more nudges after hitting the limit.
if (nudge_shown_count >= kNotificationLimit)
return false;
base::Time last_shown_time = GetLastShownTime(prefs);
// If the nudge has yet to be shown, we should return true.
if (last_shown_time.is_null())
return true;
// We should show the nudge if enough time has passed since the nudge was last
// shown.
return (base::Time::Now() - last_shown_time) > kMinInterval;
}
void AutozoomNudgeController::OnActiveClientChange(
cros::mojom::CameraClientType type,
bool is_active) {
if (!is_active)
return;
PrefService* prefs =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
if (!ShouldShowNudge(prefs))
return;
ShowNudge();
HandleNudgeShown();
}
void AutozoomNudgeController::OnAutozoomStateChanged(
cros::mojom::CameraAutoFramingState state) {
if (state != cros::mojom::CameraAutoFramingState::OFF) {
PrefService* prefs =
Shell::Get()->session_controller()->GetLastActiveUserPrefService();
if (!prefs)
return;
DictionaryPrefUpdate update(prefs, prefs::kAutozoomNudges);
update->SetBoolPath(kHadEnabled, true);
}
}
std::unique_ptr<SystemNudge> AutozoomNudgeController::CreateSystemNudge() {
return std::make_unique<AutozoomNudge>();
}
} // namespace ash