// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/push_notification/model/push_notification_profile_service.h"
#import "base/strings/sys_string_conversions.h"
#import "base/task/sequenced_task_runner.h"
#import "components/signin/public/identity_manager/primary_account_change_event.h"
#import "ios/chrome/browser/commerce/model/price_alert_util.h"
#import "ios/chrome/browser/push_notification/model/push_notification_account_context_manager.h"
#import "ios/chrome/browser/push_notification/model/push_notification_service.h"
#import "ios/chrome/browser/push_notification/model/push_notification_util.h"
#import "ios/chrome/browser/shared/model/application_context/application_context.h"
namespace {
// A helper function for removing a signed out user from the push notification
// server.
void OnPrimaryAccountCleared(CoreAccountInfo primary_account) {
PushNotificationService* service =
GetApplicationContext()->GetPushNotificationService();
NSString* gaia = base::SysUTF8ToNSString(primary_account.gaia);
service->UnregisterAccount(gaia, nullptr);
}
// A helper function for adding a signin user to the push notification server.
void OnPrimaryAccountSet(CoreAccountInfo primary_account) {
PushNotificationService* service =
GetApplicationContext()->GetPushNotificationService();
if (!service->DeviceTokenIsSet()) {
[PushNotificationUtil
registerDeviceWithAPNSWithContentNotificationsAvailable:NO];
}
NSString* gaia = base::SysUTF8ToNSString(primary_account.gaia);
service->RegisterAccount(gaia, nullptr);
}
} // namespace
PushNotificationBrowserStateService::PushNotificationBrowserStateService(
signin::IdentityManager* identity_manager,
base::FilePath browser_state_path)
: identity_manager_(identity_manager),
browser_state_path_(browser_state_path) {
identity_manager->AddObserver(this);
}
PushNotificationBrowserStateService::~PushNotificationBrowserStateService() =
default;
void PushNotificationBrowserStateService::Shutdown() {
identity_manager_->RemoveObserver(this);
}
void PushNotificationBrowserStateService::OnPrimaryAccountChanged(
const signin::PrimaryAccountChangeEvent& event) {
// This check prevents registering/unregistering accounts with the
// PushNotificationService when the user has not received an APNS token. The
// user will not have an APNS token if they have not allowed push
// notification permissions on the device. Because the initialization of the
// PushNotificationService's account manager is dependent on the
// initialization of the PushNotificationService with the Push Notification
// server (which only occurs when the user has allowed push notification
// permissions), this check must exist to avoid interacting with an
// uninitialized account manager.
PushNotificationService* service =
GetApplicationContext()->GetPushNotificationService();
if (!service->DeviceTokenIsSet()) {
return;
}
const signin::ConsentLevel consent_level = signin::ConsentLevel::kSignin;
switch (event.GetEventTypeFor(consent_level)) {
case signin::PrimaryAccountChangeEvent::Type::kSet: {
// The PostTask function must be used for the OnPrimaryAccountSet to
// ensure that the appropriate BrowserState has been updated with the
// newly signed in account's gaia id. The class that is responsible for
// updating the BrowserState's gaia ID is SigninBrowserStateInfoUpdater.
// SigninBrowserStateInfoUpdater is also a
// signin::IdentityManager::Observer. Thus, the PostTask() function
// guarantees that the BrowserState's gaia id will have been updated by
// the time PushNotificationBrowserStateService::OnPrimaryAccountSet is
// invoked.
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&OnPrimaryAccountSet,
event.GetCurrentState().primary_account));
break;
}
case signin::PrimaryAccountChangeEvent::Type::kCleared: {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(&OnPrimaryAccountCleared,
event.GetPreviousState().primary_account));
break;
}
case signin::PrimaryAccountChangeEvent::Type::kNone: {
break;
}
}
}