[CrOS Hotspot] Admin restricted and wifi turned off notifications
Changes to support notifications when Hotspot is turned off by administrator and when hotspot is enabled while WiFi is active. Screenshots: https://screenshot.googleplex.com/6t98McbbL79gw6S https://screenshot.googleplex.com/3icxA8KYmkvtHc6 Bug: b/269353987 Change-Id: I1dc7df0673a755d7f963e70db5ec6a960e24f97b Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4312124 Reviewed-by: Jason Zhang <jiajunz@google.com> Commit-Queue: Nikhil Nayunigari <nikhilcn@google.com> Reviewed-by: Xiyuan Xia <xiyuan@chromium.org> Reviewed-by: Andre Le <leandre@chromium.org> Cr-Commit-Position: refs/heads/main@{#1116053}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
3984ce86e9
commit
49b9c3f5d7
@ -1517,6 +1517,8 @@ component("ash") {
|
||||
"system/network/fake_network_list_network_header_view_delegate.h",
|
||||
"system/network/fake_network_list_wifi_header_view.cc",
|
||||
"system/network/fake_network_list_wifi_header_view.h",
|
||||
"system/network/hotspot_notifier.cc",
|
||||
"system/network/hotspot_notifier.h",
|
||||
"system/network/managed_sim_lock_notifier.cc",
|
||||
"system/network/managed_sim_lock_notifier.h",
|
||||
"system/network/network_detailed_network_view.cc",
|
||||
@ -2481,6 +2483,7 @@ component("ash") {
|
||||
"//ash/public/cpp/resources:ash_public_unscaled_resources",
|
||||
"//ash/resources/vector_icons",
|
||||
"//ash/strings",
|
||||
"//chromeos/ash/services/hotspot_config/public/mojom",
|
||||
"//chromeos/ash/services/multidevice_setup/public/mojom",
|
||||
"//chromeos/crosapi/mojom",
|
||||
"//chromeos/services/machine_learning/public/mojom",
|
||||
@ -2582,6 +2585,7 @@ component("ash") {
|
||||
"//chromeos/ash/services/bluetooth_config/public/mojom",
|
||||
"//chromeos/ash/services/federated/public/cpp",
|
||||
"//chromeos/ash/services/federated/public/mojom",
|
||||
"//chromeos/ash/services/hotspot_config/public/cpp",
|
||||
"//chromeos/ash/services/hotspot_config/public/mojom",
|
||||
"//chromeos/ash/services/libassistant/public/cpp:structs",
|
||||
"//chromeos/ash/services/libassistant/public/mojom",
|
||||
@ -3175,6 +3179,7 @@ test("ash_unittests") {
|
||||
"system/network/active_network_icon_unittest.cc",
|
||||
"system/network/auto_connect_notifier_unittest.cc",
|
||||
"system/network/cellular_setup_notifier_unittest.cc",
|
||||
"system/network/hotspot_notifier_unittest.cc",
|
||||
"system/network/managed_sim_lock_notifier_unittest.cc",
|
||||
"system/network/network_detailed_network_view_unittest.cc",
|
||||
"system/network/network_detailed_view_controller_unittest.cc",
|
||||
@ -3498,6 +3503,7 @@ test("ash_unittests") {
|
||||
"//chromeos/ash/services/bluetooth_config:test_support",
|
||||
"//chromeos/ash/services/federated/public/cpp",
|
||||
"//chromeos/ash/services/federated/public/cpp:test_support",
|
||||
"//chromeos/ash/services/hotspot_config:hotspot_config",
|
||||
"//chromeos/ash/services/multidevice_setup/public/cpp:test_support",
|
||||
"//chromeos/ash/services/multidevice_setup/public/mojom",
|
||||
"//chromeos/ash/services/nearby/public/cpp",
|
||||
|
1
ash/DEPS
1
ash/DEPS
@ -92,6 +92,7 @@ include_rules = [
|
||||
"+chromeos/ash/services/assistant/public/cpp" ,
|
||||
"+chromeos/ash/services/assistant/test_support",
|
||||
"+chromeos/ash/services/bluetooth_config",
|
||||
"+chromeos/ash/services/hotspot_config",
|
||||
"+chromeos/ash/services/federated/public",
|
||||
"+chromeos/ash/services/libassistant/public",
|
||||
"+chromeos/ash/services/nearby/public",
|
||||
|
@ -2472,6 +2472,18 @@ Connect your device to power.
|
||||
<message name="IDS_ASH_STATUS_TRAY_BLUETOOTH_DISCOVERABLE" desc="Toast shown when a Bluetooth adapter is discoverable.">
|
||||
"<ph name="NAME">$1<ex>Chromebook</ex></ph>" visible to Bluetooth devices.
|
||||
</message>
|
||||
<message name="IDS_ASH_HOTSPOT_ON_TITLE" desc="Title used for the system notification shown when the hotspot is turned on.">
|
||||
Hotspot is on
|
||||
</message>
|
||||
<message name="IDS_ASH_HOTSPOT_OFF_TITLE" desc="Title used for the system notification shown when the hotspot is turned off.">
|
||||
Hotspot is off
|
||||
</message>
|
||||
<message name="IDS_ASH_HOTSPOT_WIFI_TURNED_OFF_MESSAGE" desc="Message displayed in the system notification shown when WiFi is turned off upon enabling hotspot.">
|
||||
We've turned off the WiFi to start using Hotspot through Mobile data. This may incur data costs.
|
||||
</message>
|
||||
<message name="IDS_ASH_HOTSPOT_ADMIN_RESTRICTED_MESSAGE" desc="Message displayed in the system notification shown when the hotspot is turned off by the administrator.">
|
||||
Your administrator has turned Hotspot off.
|
||||
</message>
|
||||
<message name="IDS_ASH_NETWORK_AUTOCONNECT" desc="Text used for the toast shown when a network has been auto-connected (e.g., when an enterprise policy is applied which initiates a connection to a corporate network like Google-A).">
|
||||
We've switched you to a better network
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
75fbfe3701728a1fce39c3ce3f064b258d456936
|
1
ash/ash_strings_grd/IDS_ASH_HOTSPOT_OFF_TITLE.png.sha1
Normal file
1
ash/ash_strings_grd/IDS_ASH_HOTSPOT_OFF_TITLE.png.sha1
Normal file
@ -0,0 +1 @@
|
||||
75fbfe3701728a1fce39c3ce3f064b258d456936
|
1
ash/ash_strings_grd/IDS_ASH_HOTSPOT_ON_TITLE.png.sha1
Normal file
1
ash/ash_strings_grd/IDS_ASH_HOTSPOT_ON_TITLE.png.sha1
Normal file
@ -0,0 +1 @@
|
||||
dad69cfe3fea482fe4f8016432a7f3f4abeccc50
|
@ -0,0 +1 @@
|
||||
dad69cfe3fea482fe4f8016432a7f3f4abeccc50
|
@ -181,7 +181,8 @@ enum class NotificationCatalogName {
|
||||
kLockScreen = 166,
|
||||
kWebAppSettings = 167,
|
||||
kEOLIncentive = 168,
|
||||
kMaxValue = kEOLIncentive
|
||||
kHotspot = 169,
|
||||
kMaxValue = kHotspot
|
||||
};
|
||||
|
||||
// A living catalog that registers system nudges.
|
||||
|
89
ash/system/network/hotspot_notifier.cc
Normal file
89
ash/system/network/hotspot_notifier.cc
Normal file
@ -0,0 +1,89 @@
|
||||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/network/hotspot_notifier.h"
|
||||
#include "ash/public/cpp/hotspot_config_service.h"
|
||||
#include "ash/public/cpp/notification_utils.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
#include "ui/message_center/public/cpp/message_center_constants.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
// static
|
||||
const char HotspotNotifier::kWiFiTurnedOffNotificationId[] =
|
||||
"cros_hotspot_notifier_ids.wifi_turned_off";
|
||||
|
||||
const char HotspotNotifier::kAdminRestrictedNotificationId[] =
|
||||
"cros_hotspot_notifier_ids.admin_restricted";
|
||||
|
||||
const char kNotifierHotspot[] = "ash.hotspot";
|
||||
|
||||
HotspotNotifier::HotspotNotifier() {
|
||||
GetHotspotConfigService(
|
||||
remote_cros_hotspot_config_.BindNewPipeAndPassReceiver());
|
||||
remote_cros_hotspot_config_->ObserveEnabledStateChanges(
|
||||
hotspot_enabled_state_observer_receiver_.BindNewPipeAndPassRemote());
|
||||
}
|
||||
|
||||
HotspotNotifier::~HotspotNotifier() = default;
|
||||
|
||||
void HotspotNotifier::OnHotspotTurnedOn(bool wifi_turned_off) {
|
||||
if (wifi_turned_off) {
|
||||
std::unique_ptr<message_center::Notification> notification =
|
||||
CreateNotification(IDS_ASH_HOTSPOT_ON_TITLE,
|
||||
IDS_ASH_HOTSPOT_WIFI_TURNED_OFF_MESSAGE,
|
||||
kWiFiTurnedOffNotificationId,
|
||||
/*delegate=*/nullptr);
|
||||
|
||||
message_center::MessageCenter* message_center =
|
||||
message_center::MessageCenter::Get();
|
||||
message_center->RemoveNotification(kWiFiTurnedOffNotificationId,
|
||||
/*by_user=*/false);
|
||||
message_center->AddNotification(std::move(notification));
|
||||
}
|
||||
}
|
||||
|
||||
void HotspotNotifier::OnHotspotTurnedOff(
|
||||
hotspot_config::mojom::DisableReason disable_reason) {
|
||||
if (disable_reason ==
|
||||
hotspot_config::mojom::DisableReason::kProhibitedByPolicy) {
|
||||
std::unique_ptr<message_center::Notification> notification =
|
||||
CreateNotification(IDS_ASH_HOTSPOT_OFF_TITLE,
|
||||
IDS_ASH_HOTSPOT_ADMIN_RESTRICTED_MESSAGE,
|
||||
kAdminRestrictedNotificationId,
|
||||
/*delegate=*/nullptr);
|
||||
|
||||
message_center::MessageCenter* message_center =
|
||||
message_center::MessageCenter::Get();
|
||||
message_center->RemoveNotification(kAdminRestrictedNotificationId,
|
||||
/*by_user=*/false);
|
||||
message_center->AddNotification(std::move(notification));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<message_center::Notification>
|
||||
HotspotNotifier::CreateNotification(
|
||||
const int title_id,
|
||||
const int message_id,
|
||||
const char* notification_id,
|
||||
scoped_refptr<message_center::NotificationDelegate> delegate) {
|
||||
std::unique_ptr<message_center::Notification> notification =
|
||||
ash::CreateSystemNotificationPtr(
|
||||
message_center::NOTIFICATION_TYPE_SIMPLE, notification_id,
|
||||
l10n_util::GetStringUTF16(title_id),
|
||||
l10n_util::GetStringUTF16(message_id),
|
||||
/*display_source=*/std::u16string(), GURL(),
|
||||
message_center::NotifierId(
|
||||
message_center::NotifierType::SYSTEM_COMPONENT, kNotifierHotspot,
|
||||
NotificationCatalogName::kHotspot),
|
||||
message_center::RichNotificationData(), delegate,
|
||||
/*small_image=*/gfx::VectorIcon(),
|
||||
message_center::SystemNotificationWarningLevel::NORMAL);
|
||||
|
||||
return notification;
|
||||
}
|
||||
|
||||
} // namespace ash
|
61
ash/system/network/hotspot_notifier.h
Normal file
61
ash/system/network/hotspot_notifier.h
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ASH_SYSTEM_NETWORK_HOTSPOT_NOTIFIER_H_
|
||||
#define ASH_SYSTEM_NETWORK_HOTSPOT_NOTIFIER_H_
|
||||
|
||||
#include "ash/ash_export.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
|
||||
#include "chromeos/services/network_config/public/cpp/cros_network_config_observer.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "ui/message_center/message_center.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
// Notifies the user about following hotspot events:
|
||||
// - WiFi has been turned off to enable hotspot
|
||||
// - Hotspot has been disabled due to following reasons -
|
||||
// - 1. Internal error
|
||||
// - 2. Admin policy
|
||||
// - 3. WiFi has been enabled
|
||||
// - 4. In activity
|
||||
// - Hotspot is turned on and has 'n' active connections
|
||||
class ASH_EXPORT HotspotNotifier
|
||||
: public hotspot_config::mojom::HotspotEnabledStateObserver {
|
||||
public:
|
||||
HotspotNotifier();
|
||||
HotspotNotifier(const HotspotNotifier&) = delete;
|
||||
HotspotNotifier& operator=(const HotspotNotifier&) = delete;
|
||||
~HotspotNotifier() override;
|
||||
|
||||
static const char kWiFiTurnedOffNotificationId[];
|
||||
static const char kAdminRestrictedNotificationId[];
|
||||
|
||||
private:
|
||||
friend class HotspotNotifierTest;
|
||||
|
||||
// HotspotEnabledStateObserver:
|
||||
void OnHotspotTurnedOn(bool wifi_turned_off) override;
|
||||
void OnHotspotTurnedOff(
|
||||
hotspot_config::mojom::DisableReason disable_reason) override;
|
||||
|
||||
std::unique_ptr<message_center::Notification> CreateNotification(
|
||||
const int title_id,
|
||||
const int message_id,
|
||||
const char* notification_id,
|
||||
scoped_refptr<message_center::NotificationDelegate> delegate);
|
||||
|
||||
mojo::Remote<hotspot_config::mojom::CrosHotspotConfig>
|
||||
remote_cros_hotspot_config_;
|
||||
mojo::Receiver<hotspot_config::mojom::HotspotEnabledStateObserver>
|
||||
hotspot_enabled_state_observer_receiver_{this};
|
||||
|
||||
base::WeakPtrFactory<HotspotNotifier> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace ash
|
||||
|
||||
#endif // ASH_SYSTEM_NETWORK_HOTSPOT_NOTIFIER_H_
|
133
ash/system/network/hotspot_notifier_unittest.cc
Normal file
133
ash/system/network/hotspot_notifier_unittest.cc
Normal file
@ -0,0 +1,133 @@
|
||||
// Copyright 2023 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "ash/system/network/hotspot_notifier.h"
|
||||
#include "ash/constants/ash_features.h"
|
||||
#include "ash/public/cpp/hotspot_config_service.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/test/bind.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "chromeos/ash/components/network/network_handler.h"
|
||||
#include "chromeos/ash/components/network/network_handler_test_helper.h"
|
||||
#include "chromeos/ash/components/network/network_state_test_helper.h"
|
||||
#include "chromeos/ash/services/hotspot_config/cros_hotspot_config.h"
|
||||
#include "chromeos/ash/services/hotspot_config/public/mojom/cros_hotspot_config.mojom.h"
|
||||
#include "chromeos/ash/services/network_config/public/cpp/cros_network_config_test_helper.h"
|
||||
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kCellularServicePath[] = "/service/cellular0";
|
||||
const char kCellularServiceGuid[] = "cellular_guid0";
|
||||
const char kCellularServiceName[] = "cellular_name0";
|
||||
|
||||
} // namespace
|
||||
|
||||
class HotspotNotifierTest : public NoSessionAshTestBase {
|
||||
public:
|
||||
HotspotNotifierTest() {
|
||||
scoped_feature_list_.InitAndEnableFeature(features::kHotspot);
|
||||
}
|
||||
HotspotNotifierTest(const HotspotNotifierTest&) = delete;
|
||||
HotspotNotifierTest& operator=(const HotspotNotifierTest&) = delete;
|
||||
~HotspotNotifierTest() override = default;
|
||||
|
||||
void SetUp() override {
|
||||
network_handler_test_helper_ = std::make_unique<NetworkHandlerTestHelper>();
|
||||
network_handler_test_helper_->AddDefaultProfiles();
|
||||
network_handler_test_helper_->ResetDevicesAndServices();
|
||||
GetHotspotConfigService(cros_hotspot_config_.BindNewPipeAndPassReceiver());
|
||||
hotspot_notifier_ = std::make_unique<ash::HotspotNotifier>();
|
||||
|
||||
NoSessionAshTestBase::SetUp();
|
||||
LogIn();
|
||||
}
|
||||
|
||||
void LogIn() { SimulateUserLogin("user1@test.com"); }
|
||||
|
||||
void TearDown() override {
|
||||
NoSessionAshTestBase::TearDown();
|
||||
network_config_helper_.reset();
|
||||
network_handler_test_helper_.reset();
|
||||
}
|
||||
|
||||
void SetValidHotspotCapabilities() {
|
||||
base::Value::Dict capabilities_dict;
|
||||
base::Value::List upstream_list;
|
||||
upstream_list.Append(shill::kTypeCellular);
|
||||
capabilities_dict.Set(shill::kTetheringCapUpstreamProperty,
|
||||
std::move(upstream_list));
|
||||
// Add WiFi to the downstream technology list in Shill
|
||||
base::Value::List downstream_list;
|
||||
downstream_list.Append(shill::kTypeWifi);
|
||||
capabilities_dict.Set(shill::kTetheringCapDownstreamProperty,
|
||||
std::move(downstream_list));
|
||||
// Add allowed WiFi security mode in Shill
|
||||
base::Value::List security_list;
|
||||
security_list.Append(shill::kSecurityWpa2);
|
||||
security_list.Append(shill::kSecurityWpa3);
|
||||
capabilities_dict.Set(shill::kTetheringCapSecurityProperty,
|
||||
std::move(security_list));
|
||||
network_handler_test_helper_->manager_test()->SetManagerProperty(
|
||||
shill::kTetheringCapabilitiesProperty,
|
||||
base::Value(std::move(capabilities_dict)));
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
void SetReadinessCheckResultReady() {
|
||||
network_handler_test_helper_->manager_test()
|
||||
->SetSimulateCheckTetheringReadinessResult(
|
||||
FakeShillSimulatedResult::kSuccess,
|
||||
shill::kTetheringReadinessReady);
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
NetworkHandlerTestHelper* helper() {
|
||||
return network_handler_test_helper_.get();
|
||||
}
|
||||
|
||||
hotspot_config::mojom::HotspotControlResult EnableHotspot() {
|
||||
base::RunLoop run_loop;
|
||||
hotspot_config::mojom::HotspotControlResult out_result;
|
||||
cros_hotspot_config_->EnableHotspot(base::BindLambdaForTesting(
|
||||
[&](hotspot_config::mojom::HotspotControlResult result) {
|
||||
out_result = result;
|
||||
run_loop.Quit();
|
||||
}));
|
||||
run_loop.Run();
|
||||
return out_result;
|
||||
}
|
||||
|
||||
void AddActiveCellularService() {
|
||||
network_handler_test_helper_->service_test()->AddService(
|
||||
kCellularServicePath, kCellularServiceGuid, kCellularServiceName,
|
||||
shill::kTypeCellular, shill::kStateOnline, /*visible=*/true);
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
base::test::ScopedFeatureList scoped_feature_list_;
|
||||
std::unique_ptr<NetworkHandlerTestHelper> network_handler_test_helper_;
|
||||
std::unique_ptr<network_config::CrosNetworkConfigTestHelper>
|
||||
network_config_helper_;
|
||||
std::unique_ptr<HotspotNotifier> hotspot_notifier_;
|
||||
mojo::Remote<hotspot_config::mojom::CrosHotspotConfig> cros_hotspot_config_;
|
||||
};
|
||||
|
||||
TEST_F(HotspotNotifierTest, WiFiTurnedOff) {
|
||||
SetValidHotspotCapabilities();
|
||||
SetReadinessCheckResultReady();
|
||||
AddActiveCellularService();
|
||||
helper()->manager_test()->SetSimulateTetheringEnableResult(
|
||||
FakeShillSimulatedResult::kSuccess, shill::kTetheringEnableResultSuccess);
|
||||
base::RunLoop().RunUntilIdle();
|
||||
|
||||
EXPECT_EQ(hotspot_config::mojom::HotspotControlResult::kSuccess,
|
||||
EnableHotspot());
|
||||
EXPECT_TRUE(message_center::MessageCenter::Get()->FindVisibleNotificationById(
|
||||
HotspotNotifier::kWiFiTurnedOffNotificationId));
|
||||
}
|
||||
|
||||
} // namespace ash
|
@ -12,6 +12,7 @@
|
||||
#include "ash/system/lock_screen_notification_controller.h"
|
||||
#include "ash/system/network/auto_connect_notifier.h"
|
||||
#include "ash/system/network/cellular_setup_notifier.h"
|
||||
#include "ash/system/network/hotspot_notifier.h"
|
||||
#include "ash/system/network/managed_sim_lock_notifier.h"
|
||||
#include "ash/system/network/wifi_toggle_notification_controller.h"
|
||||
#include "ash/system/power/power_notification_controller.h"
|
||||
@ -62,6 +63,9 @@ SystemNotificationController::SystemNotificationController()
|
||||
managed_sim_lock_notifier_ =
|
||||
std::make_unique<ash::ManagedSimLockNotifier>();
|
||||
}
|
||||
if (features::IsHotspotEnabled()) {
|
||||
hotspot_notifier_ = std::make_unique<ash::HotspotNotifier>();
|
||||
}
|
||||
}
|
||||
|
||||
SystemNotificationController::~SystemNotificationController() = default;
|
||||
|
@ -18,6 +18,7 @@ class CellularSetupNotifier;
|
||||
class DoNotDisturbNotificationController;
|
||||
class LockScreenNotificationController;
|
||||
class ManagedSimLockNotifier;
|
||||
class HotspotNotifier;
|
||||
class PowerNotificationController;
|
||||
class PowerSoundsController;
|
||||
class PrivacyHubNotificationController;
|
||||
@ -63,6 +64,7 @@ class SystemNotificationController {
|
||||
const std::unique_ptr<LockScreenNotificationController> lock_screen_;
|
||||
// TODO(b/228093904): Make |managed_sim_lock_notifier_| const during cleanup.
|
||||
std::unique_ptr<ManagedSimLockNotifier> managed_sim_lock_notifier_;
|
||||
std::unique_ptr<HotspotNotifier> hotspot_notifier_;
|
||||
const std::unique_ptr<PowerNotificationController> power_;
|
||||
const std::unique_ptr<PowerSoundsController> power_sounds_;
|
||||
std::unique_ptr<PrivacyHubNotificationController> privacy_hub_;
|
||||
|
Reference in New Issue
Block a user