Skip to content

Commit

Permalink
[CrOS SLP] Trigger Managed SIM Lock Notification on policy change.
Browse files Browse the repository at this point in the history
This CL adds the MSLN class which will manage the showing/hiding of the
notification that guides managed users to PIN unlocking their SIM when
the restrict SIM Lock global network configuration policy is set to true.

Currently, the class only surfaces the notification when the policy
changes. Other cases will be added in the next CLs.

screenshot: http://go/tscreen/8fce7c8dc73c864e67e443d38abc6bff79b01533

Bug: b/228093904
Change-Id: I1d438ea17e0b26c917197d56b3243e93308bfa4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3630569
Reviewed-by: Ahmed Mehfooz <amehfooz@chromium.org>
Reviewed-by: Azeem Arshad <azeemarshad@chromium.org>
Commit-Queue: Regan Hsu <hsuregan@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1001789}
  • Loading branch information
Regan Hsu authored and Chromium LUCI CQ committed May 10, 2022
1 parent c9d17d2 commit 7e1964a
Show file tree
Hide file tree
Showing 9 changed files with 377 additions and 0 deletions.
3 changes: 3 additions & 0 deletions ash/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,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/managed_sim_lock_notifier.cc",
"system/network/managed_sim_lock_notifier.h",
"system/network/network_detailed_network_view.cc",
"system/network/network_detailed_network_view.h",
"system/network/network_detailed_network_view_impl.cc",
Expand Down Expand Up @@ -2735,6 +2737,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/managed_sim_lock_notifier_unittest.cc",
"system/network/network_detailed_network_view_unittest.cc",
"system/network/network_detailed_view_controller_unittest.cc",
"system/network/network_detailed_view_unittest.cc",
Expand Down
6 changes: 6 additions & 0 deletions ash/ash_strings.grd
Original file line number Diff line number Diff line change
Expand Up @@ -2111,6 +2111,12 @@ This file contains the strings for ash.
<message name="IDS_ASH_NETWORK_CELLULAR_SETUP_NOTIFICATION_MESSAGE" desc="Message displayed in the system notification shown post-OOBE if a user has no activated mobile networks.">
Tap to complete set up
</message>
<message name="IDS_ASH_NETWORK_MANAGED_SIM_LOCK_NOTIFICATION_TITLE" desc="Title used for the system notification shown when the active SIM is locked when it is enterprise policy restricted.">
Disable your SIM Lock setting
</message>
<message name="IDS_ASH_NETWORK_MANAGED_SIM_LOCK_NOTIFICATION_MESSAGE" desc="Message displayed in the system notification shown when the active SIM is locked when it is enterprise policy restricted.">
Your administrator is requesting that you turn off the Lock SIM setting
</message>
<message name="IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_TITLE" desc="Title used for the system notification shown when the reset euicc operation is initiated.">
eSIM connection unavailable
</message>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8fce7c8dc73c864e67e443d38abc6bff79b01533
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8fce7c8dc73c864e67e443d38abc6bff79b01533
128 changes: 128 additions & 0 deletions ash/system/network/managed_sim_lock_notifier.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
// 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/network/managed_sim_lock_notifier.h"

#include "ash/public/cpp/network_config_service.h"
#include "ash/public/cpp/notification_utils.h"
#include "ash/public/cpp/system_tray_client.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/system/model/system_tray_model.h"
#include "ash/system/tray/tray_popup_utils.h"
#include "base/bind.h"
#include "components/onc/onc_constants.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 {
namespace {

const char kNotifierManagedSimLock[] = "ash.managed-simlock";

} // namespace

// static
const char ManagedSimLockNotifier::kManagedSimLockNotificationId[] =
"cros_managed_sim_lock_notifier_ids.pin_unlock_device";

ManagedSimLockNotifier::ManagedSimLockNotifier() {
GetNetworkConfigService(
remote_cros_network_config_.BindNewPipeAndPassReceiver());
remote_cros_network_config_->AddObserver(
cros_network_config_observer_receiver_.BindNewPipeAndPassRemote());
}

ManagedSimLockNotifier::~ManagedSimLockNotifier() {}

void ManagedSimLockNotifier::OnPoliciesApplied(const std::string& userhash) {
CheckGlobalNetworkConfiguarion();
}

void ManagedSimLockNotifier::CheckGlobalNetworkConfiguarion() {
remote_cros_network_config_->GetGlobalPolicy(
base::BindOnce(&ManagedSimLockNotifier::OnGetGlobalPolicy,
weak_ptr_factory_.GetWeakPtr()));
}

void ManagedSimLockNotifier::OnGetGlobalPolicy(
chromeos::network_config::mojom::GlobalPolicyPtr global_policy) {
if (!global_policy->allow_cellular_sim_lock) {
MaybeShowNotification();
return;
}

RemoveNotification();
}

void ManagedSimLockNotifier::MaybeShowNotification() {
remote_cros_network_config_->GetNetworkStateList(
chromeos::network_config::mojom::NetworkFilter::New(
chromeos::network_config::mojom::FilterType::kAll,
chromeos::network_config::mojom::NetworkType::kCellular,
chromeos::network_config::mojom::kNoLimit),
base::BindOnce(&ManagedSimLockNotifier::OnCellularNetworksList,
weak_ptr_factory_.GetWeakPtr()));
}

void ManagedSimLockNotifier::OnCellularNetworksList(
std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
networks) {
// Check if there are any PIN locked pSIM or eSIM networks.
for (auto& network : networks) {
if (network->type_state->get_cellular()->sim_locked) {
ShowNotification();
return;
}
}

RemoveNotification();
}

void ManagedSimLockNotifier::ShowNotification() {
scoped_refptr<message_center::NotificationDelegate> delegate =
base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
base::BindRepeating([](absl::optional<int> button_index) {
// When clicked, open the SIM Unlock dialog in Cellular settings if
// we can open WebUI settings, otherwise do nothing.
if (TrayPopupUtils::CanOpenWebUISettings()) {
Shell::Get()
->system_tray_model()
->client()
->ShowSettingsSimUnlock();
} else {
LOG(WARNING) << "Cannot open Cellular settings since it's not "
"possible to open OS Settings";
}
}));

std::unique_ptr<message_center::Notification> notification =
ash::CreateSystemNotification(
message_center::NOTIFICATION_TYPE_SIMPLE,
kManagedSimLockNotificationId,
l10n_util::GetStringUTF16(
IDS_ASH_NETWORK_MANAGED_SIM_LOCK_NOTIFICATION_TITLE),
l10n_util::GetStringUTF16(
IDS_ASH_NETWORK_MANAGED_SIM_LOCK_NOTIFICATION_MESSAGE),
/*display_source=*/std::u16string(), GURL(),
message_center::NotifierId(
message_center::NotifierType::SYSTEM_COMPONENT,
kNotifierManagedSimLock),
message_center::RichNotificationData(), std::move(delegate),
/*small_image=*/gfx::VectorIcon(),
message_center::SystemNotificationWarningLevel::WARNING);

message_center::MessageCenter* message_center =
message_center::MessageCenter::Get();
message_center->AddNotification(std::move(notification));
}

void ManagedSimLockNotifier::RemoveNotification() {
message_center::MessageCenter* message_center =
message_center::MessageCenter::Get();
message_center->RemoveNotification(kManagedSimLockNotificationId, false);
}

} // namespace ash
71 changes: 71 additions & 0 deletions ash/system/network/managed_sim_lock_notifier.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// 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.

#ifndef ASH_SYSTEM_NETWORK_MANAGED_SIM_LOCK_NOTIFIER_H_
#define ASH_SYSTEM_NETWORK_MANAGED_SIM_LOCK_NOTIFIER_H_

#include "ash/ash_export.h"
#include "base/gtest_prod_util.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace ash {

// Notifies the user to unlock the currently active PIN locked SIM.
// TODO(b/228093904): Surface notification during the start of each newly active
// session if SIM is locked and policy is set to true.
// TODO(b/228093904): Surface notification if active network changes to network
// with SIM locked and policy is set to true.
// TODO(b/228093904): Remove notification if user successfully unlocks SIM.
// TODO(b/228093904): Remove notification if active network changes to network
// without SIM locked and policy is set to true.
class ASH_EXPORT ManagedSimLockNotifier
: public chromeos::network_config::mojom::CrosNetworkConfigObserver {
public:
ManagedSimLockNotifier();
ManagedSimLockNotifier(const ManagedSimLockNotifier&) = delete;
ManagedSimLockNotifier& operator=(const ManagedSimLockNotifier&) = delete;
~ManagedSimLockNotifier() override;

private:
friend class ManagedSimLockNotifierTest;

// CrosNetworkConfigObserver:
void OnNetworkStateListChanged() override {}
void OnActiveNetworksChanged(
std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
networks) override {}
void OnNetworkStateChanged(
chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
override {}
void OnDeviceStateListChanged() override {}
void OnVpnProvidersChanged() override {}
void OnNetworkCertificatesChanged() override {}
void OnPoliciesApplied(const std::string& userhash) override;

void OnCellularNetworksList(
std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr>
networks);
void OnGetGlobalPolicy(
chromeos::network_config::mojom::GlobalPolicyPtr global_policy);

void RemoveNotification();
void CheckGlobalNetworkConfiguarion();
void MaybeShowNotification();
void ShowNotification();

static const char kManagedSimLockNotificationId[];

mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>
remote_cros_network_config_;
mojo::Receiver<chromeos::network_config::mojom::CrosNetworkConfigObserver>
cros_network_config_observer_receiver_{this};

base::WeakPtrFactory<ManagedSimLockNotifier> weak_ptr_factory_{this};
};

} // namespace ash

#endif // ASH_SYSTEM_NETWORK_MANAGED_SIM_LOCK_NOTIFIER_H_
157 changes: 157 additions & 0 deletions ash/system/network/managed_sim_lock_notifier_unittest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// 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/network/managed_sim_lock_notifier.h"

#include "ash/constants/ash_features.h"
#include "ash/system/system_notification_controller.h"
#include "ash/test/ash_test_base.h"
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_handler_test_helper.h"
#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h"
#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
#include "ui/message_center/message_center.h"
#include "ui/message_center/public/cpp/notification.h"

namespace ash {
namespace {

const char kTestCellularServicePath[] = "cellular_service_path";
const char kTestCellularDevicePath[] = "cellular_path";
const char kTestCellularDevicePathName[] = "stub_cellular_device";
const char kTestIccid[] = "1234567890123456789";
const char kTestCellularGuid[] = "cellular_guid";
const char kTestCellularName[] = "cellular_name";
const char kTestEid[] = "123456789012345678901234567890123";

} // namespace

class ManagedSimLockNotifierTest : public NoSessionAshTestBase {
protected:
ManagedSimLockNotifierTest() {
scoped_feature_list_.InitAndEnableFeature(features::kSimLockPolicy);
}
ManagedSimLockNotifierTest(const ManagedSimLockNotifierTest&) = delete;
ManagedSimLockNotifierTest& operator=(const ManagedSimLockNotifierTest&) =
delete;
~ManagedSimLockNotifierTest() override = default;

void SetUp() override {
network_handler_test_helper_ = std::make_unique<NetworkHandlerTestHelper>();

network_config_helper_ = std::make_unique<
chromeos::network_config::CrosNetworkConfigTestHelper>();
AshTestBase::SetUp();
base::RunLoop().RunUntilIdle();

// User must be logged in for notification to be visible.
SimulateUserLogin("user1@test.com");
}

void TearDown() override {
AshTestBase::TearDown();
network_config_helper_.reset();
network_handler_test_helper_.reset();
}

ManagedNetworkConfigurationHandler* managed_network_configuration_handler() {
return NetworkHandler::Get()->managed_network_configuration_handler();
}

void SetCellularSimLockState(bool should_lock_sim = true) {
// Simulate a locked SIM.
base::Value sim_lock_status(base::Value::Type::DICTIONARY);
sim_lock_status.SetKey(
shill::kSIMLockTypeProperty,
base::Value(should_lock_sim ? shill::kSIMLockPin : ""));
network_config_helper_->network_state_helper()
.device_test()
->SetDeviceProperty(
kTestCellularDevicePath, shill::kSIMLockStatusProperty,
std::move(sim_lock_status), /*notify_changed=*/true);

// Set the cellular service to be the active profile.
base::Value::ListStorage sim_slot_infos;
base::Value slot_info_item(base::Value::Type::DICTIONARY);
slot_info_item.SetKey(shill::kSIMSlotInfoICCID, base::Value(kTestIccid));
slot_info_item.SetBoolKey(shill::kSIMSlotInfoPrimary, true);
sim_slot_infos.push_back(std::move(slot_info_item));
network_config_helper_->network_state_helper()
.device_test()
->SetDeviceProperty(
kTestCellularDevicePath, shill::kSIMSlotInfoProperty,
base::Value(sim_slot_infos), /*notify_changed=*/true);

base::RunLoop().RunUntilIdle();
}

void SetAllowCellularSimLock(bool allow_cellular_sim_lock) {
base::DictionaryValue global_config;
global_config.SetBoolKey(
::onc::global_network_config::kAllowCellularSimLock,
allow_cellular_sim_lock);
managed_network_configuration_handler()->SetPolicy(
::onc::ONC_SOURCE_DEVICE_POLICY, /*userhash=*/std::string(),
base::ListValue(), global_config);
base::RunLoop().RunUntilIdle();
}

void AddCellularDevice() {
network_config_helper_->network_state_helper().AddDevice(
kTestCellularDevicePath, shill::kTypeCellular,
kTestCellularDevicePathName);
}

void AddCellularService(
const std::string& service_path = kTestCellularServicePath,
const std::string& iccid = kTestIccid) {
// Add idle, non-connectable network.
network_config_helper_->network_state_helper().service_test()->AddService(
service_path, kTestCellularGuid, kTestCellularName,
shill::kTypeCellular, shill::kStateIdle, /*visible=*/true);

network_config_helper_->network_state_helper()
.service_test()
->SetServiceProperty(service_path, shill::kEidProperty,
base::Value(kTestEid));

network_config_helper_->network_state_helper()
.service_test()
->SetServiceProperty(service_path, shill::kIccidProperty,
base::Value(iccid));
base::RunLoop().RunUntilIdle();
}

// Returns the managed SIM lock notification if it is shown, and null if it is
// not shown.
message_center::Notification* GetManagedSimLockNotification() {
return message_center::MessageCenter::Get()->FindVisibleNotificationById(
ManagedSimLockNotifier::kManagedSimLockNotificationId);
}

base::test::ScopedFeatureList scoped_feature_list_;
std::unique_ptr<chromeos::network_config::CrosNetworkConfigTestHelper>
network_config_helper_;
std::unique_ptr<NetworkHandlerTestHelper> network_handler_test_helper_;
};

TEST_F(ManagedSimLockNotifierTest, PolicyChanged) {
AddCellularDevice();
AddCellularService();
EXPECT_FALSE(GetManagedSimLockNotification());

SetCellularSimLockState(true);
EXPECT_FALSE(GetManagedSimLockNotification());

SetAllowCellularSimLock(false);
EXPECT_TRUE(GetManagedSimLockNotification());

SetAllowCellularSimLock(true);
EXPECT_FALSE(GetManagedSimLockNotification());
}
} // namespace ash

0 comments on commit 7e1964a

Please sign in to comment.