blob: 0120165a1b70452c6d93b027bdb5666e8ade542c [file]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/components/phonehub/notification_access_manager_impl.h"
#include "chromeos/components/multidevice/logging/logging.h"
#include "chromeos/components/phonehub/connection_scheduler.h"
#include "chromeos/components/phonehub/message_sender.h"
#include "chromeos/components/phonehub/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
namespace chromeos {
namespace phonehub {
// static
void NotificationAccessManagerImpl::RegisterPrefs(
PrefRegistrySimple* registry) {
registry->RegisterIntegerPref(
prefs::kNotificationAccessStatus,
static_cast<int>(AccessStatus::kAvailableButNotGranted));
registry->RegisterBooleanPref(prefs::kHasDismissedSetupRequiredUi, false);
}
NotificationAccessManagerImpl::NotificationAccessManagerImpl(
PrefService* pref_service,
FeatureStatusProvider* feature_status_provider,
MessageSender* message_sender,
ConnectionScheduler* connection_scheduler)
: pref_service_(pref_service),
feature_status_provider_(feature_status_provider),
message_sender_(message_sender),
connection_scheduler_(connection_scheduler) {
DCHECK(feature_status_provider_);
DCHECK(message_sender_);
current_feature_status_ = feature_status_provider_->GetStatus();
feature_status_provider_->AddObserver(this);
}
NotificationAccessManagerImpl::~NotificationAccessManagerImpl() {
feature_status_provider_->RemoveObserver(this);
}
bool NotificationAccessManagerImpl::HasNotificationSetupUiBeenDismissed()
const {
return pref_service_->GetBoolean(prefs::kHasDismissedSetupRequiredUi);
}
void NotificationAccessManagerImpl::DismissSetupRequiredUi() {
pref_service_->SetBoolean(prefs::kHasDismissedSetupRequiredUi, true);
}
NotificationAccessManagerImpl::AccessStatus
NotificationAccessManagerImpl::GetAccessStatus() const {
int status = pref_service_->GetInteger(prefs::kNotificationAccessStatus);
return static_cast<AccessStatus>(status);
}
void NotificationAccessManagerImpl::SetAccessStatusInternal(
AccessStatus access_status) {
if (access_status == GetAccessStatus())
return;
PA_LOG(INFO) << "Notification access: " << GetAccessStatus() << " => "
<< access_status;
pref_service_->SetInteger(prefs::kNotificationAccessStatus,
static_cast<int>(access_status));
NotifyNotificationAccessChanged();
if (!IsSetupOperationInProgress())
return;
switch (access_status) {
case AccessStatus::kProhibited:
SetNotificationSetupOperationStatus(
NotificationAccessSetupOperation::Status::
kProhibitedFromProvidingAccess);
break;
case AccessStatus::kAccessGranted:
SetNotificationSetupOperationStatus(
NotificationAccessSetupOperation::Status::kCompletedSuccessfully);
break;
case AccessStatus::kAvailableButNotGranted:
// Intentionally blank; the operation status should not change.
break;
}
}
void NotificationAccessManagerImpl::OnSetupRequested() {
PA_LOG(INFO) << "Notification access setup flow started.";
switch (feature_status_provider_->GetStatus()) {
// We're already connected, so request that the UI be shown on the phone.
case FeatureStatus::kEnabledAndConnected:
SendShowNotificationAccessSetupRequest();
break;
// We're already connecting, so wait until a connection succeeds before
// trying to send a message
case FeatureStatus::kEnabledAndConnecting:
break;
// We are not connected, so schedule a connection; once the
// connection succeeds, we'll send the message in OnFeatureStatusChanged().
case FeatureStatus::kEnabledButDisconnected:
connection_scheduler_->ScheduleConnectionNow();
break;
default:
NOTREACHED();
break;
}
}
void NotificationAccessManagerImpl::OnFeatureStatusChanged() {
if (!IsSetupOperationInProgress())
return;
const FeatureStatus previous_feature_status = current_feature_status_;
current_feature_status_ = feature_status_provider_->GetStatus();
if (previous_feature_status == current_feature_status_)
return;
// If we were previously connecting and could not establish a connection,
// send a timeout state.
if (previous_feature_status == FeatureStatus::kEnabledAndConnecting &&
current_feature_status_ != FeatureStatus::kEnabledAndConnected) {
SetNotificationSetupOperationStatus(
NotificationAccessSetupOperation::Status::kTimedOutConnecting);
return;
}
// If we were previously connected and are now no longer connected, send a
// connection disconnected state.
if (previous_feature_status == FeatureStatus::kEnabledAndConnected &&
current_feature_status_ != FeatureStatus::kEnabledAndConnected) {
SetNotificationSetupOperationStatus(
NotificationAccessSetupOperation::Status::kConnectionDisconnected);
return;
}
if (current_feature_status_ == FeatureStatus::kEnabledAndConnected) {
SendShowNotificationAccessSetupRequest();
return;
}
}
void NotificationAccessManagerImpl::SendShowNotificationAccessSetupRequest() {
message_sender_->SendShowNotificationAccessSetupRequest();
SetNotificationSetupOperationStatus(
NotificationAccessSetupOperation::Status::
kSentMessageToPhoneAndWaitingForResponse);
}
} // namespace phonehub
} // namespace chromeos