#include "ash/system/network/auto_connect_notifier.h"
#include <string>
#include "ash/constants/notifier_catalogs.h"
#include "ash/public/cpp/system/toast_data.h"
#include "ash/public/cpp/system/toast_manager.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chromeos/ash/components/network/network_connection_handler.h"
#include "chromeos/ash/components/network/network_event_log.h"
#include "chromeos/ash/components/network/network_state.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/network_type_pattern.h"
#include "ui/base/l10n/l10n_util.h"
namespace ash {
namespace {
constexpr const base::TimeDelta kNetworkConnectionTimeout = base::Seconds(3);
void ShowToast(std::string id,
ToastCatalogName catalog_name,
const std::u16string& text) {
ash::ToastManager::Get()->Show(ToastData(id, catalog_name, text));
}
}
const char AutoConnectNotifier::kAutoConnectToastId[] =
"cros_auto_connect_notifier_ids.connected_to_network";
AutoConnectNotifier::AutoConnectNotifier()
: timer_(std::make_unique<base::OneShotTimer>()) {
if (NetworkHandler::IsInitialized()) {
auto* network_handler = NetworkHandler::Get();
network_handler->network_connection_handler()->AddObserver(this);
network_handler->network_state_handler()->AddObserver(this, FROM_HERE);
if (network_handler->auto_connect_handler())
network_handler->auto_connect_handler()->AddObserver(this);
}
}
AutoConnectNotifier::~AutoConnectNotifier() {
if (NetworkHandler::IsInitialized()) {
auto* network_handler = NetworkHandler::Get();
if (network_handler->auto_connect_handler())
network_handler->auto_connect_handler()->RemoveObserver(this);
network_handler->network_state_handler()->RemoveObserver(this, FROM_HERE);
network_handler->network_connection_handler()->RemoveObserver(this);
}
}
ConnectToNetworkRequestVerdict AutoConnectNotifier::ConnectToNetworkRequested(
const std::string& ) {
has_user_explicitly_requested_connection_ = true;
return ConnectToNetworkRequestVerdict::kProceed;
}
void AutoConnectNotifier::NetworkConnectionStateChanged(
const NetworkState* network) {
if (!network->Matches(NetworkTypePattern::WiFi()))
return;
if (!network->IsConnectedState()) {
if (!network->IsConnectingState() &&
network->guid() == connected_network_guid_) {
connected_network_guid_.clear();
}
return;
}
if (!timer_->IsRunning()) {
connected_network_guid_ = network->guid();
return;
}
if (network->guid() == connected_network_guid_)
return;
DisplayToast(network);
has_user_explicitly_requested_connection_ = false;
}
void AutoConnectNotifier::OnAutoConnectedInitiated(int auto_connect_reasons) {
if (!has_user_explicitly_requested_connection_)
return;
const int kManagedNetworkReasonsBitmask =
AutoConnectHandler::AUTO_CONNECT_REASON_POLICY_APPLIED |
AutoConnectHandler::AUTO_CONNECT_REASON_CERTIFICATE_RESOLVED;
if (!(auto_connect_reasons & kManagedNetworkReasonsBitmask))
return;
if (timer_->IsRunning()) {
timer_->Reset();
return;
}
timer_->Start(FROM_HERE, kNetworkConnectionTimeout, base::DoNothing());
}
void AutoConnectNotifier::set_timer_for_testing(
std::unique_ptr<base::OneShotTimer> test_timer) {
timer_ = std::move(test_timer);
}
void AutoConnectNotifier::DisplayToast(const NetworkState* network) {
NET_LOG(EVENT) << "Show AutoConnect Toast for: " << NetworkId(network);
ash::ToastManager::Get()->Cancel(kAutoConnectToastId);
ShowToast(kAutoConnectToastId, ToastCatalogName::kNetworkAutoConnect,
l10n_util::GetStringUTF16(IDS_ASH_NETWORK_AUTOCONNECT));
}
}