diff --git a/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.test.ts b/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.test.ts index 164ab168b4..c6e40da885 100644 --- a/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.test.ts +++ b/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.test.ts @@ -580,6 +580,59 @@ describe('user-storage/user-storage-controller - syncInternalAccountsWithUserSto ); }); + it('fires the onAccountAdded callback when adding an account', async () => { + const mockUserStorageAccountsResponse = async () => { + return { + status: 200, + body: await createMockUserStorageEntries( + MOCK_USER_STORAGE_ACCOUNTS.SAME_AS_INTERNAL_ALL, + ), + }; + }; + + const arrangeMocksForAccounts = async () => { + return { + messengerMocks: mockUserStorageMessenger({ + accounts: { + accountsList: MOCK_INTERNAL_ACCOUNTS.ONE as InternalAccount[], + }, + }), + mockAPI: { + mockEndpointGetUserStorage: + await mockEndpointGetUserStorageAllFeatureEntries( + 'accounts', + await mockUserStorageAccountsResponse(), + ), + }, + }; + }; + + const onAccountAdded = jest.fn(); + + const { messengerMocks, mockAPI } = await arrangeMocksForAccounts(); + const controller = new UserStorageController({ + messenger: messengerMocks.messenger, + config: { + accountSyncing: { + onAccountAdded, + }, + }, + env: { + isAccountSyncingEnabled: true, + }, + getMetaMetricsState: () => true, + }); + + await controller.syncInternalAccountsWithUserStorage(); + + mockAPI.mockEndpointGetUserStorage.done(); + + expect(onAccountAdded).toHaveBeenCalledTimes( + MOCK_USER_STORAGE_ACCOUNTS.SAME_AS_INTERNAL_ALL.length - + MOCK_INTERNAL_ACCOUNTS.ONE.length, + ); + }); + it('does not create internal accounts if user storage has less accounts', async () => { const mockUserStorageAccountsResponse = async () => { return { @@ -893,6 +946,48 @@ describe('user-storage/user-storage-controller - syncInternalAccountsWithUserSto messengerMocks.mockAccountsUpdateAccountMetadata, ).not.toHaveBeenCalled(); }); + + it('fires the onAccountNameUpdated callback when renaming an internal account', async () => { + const arrangeMocksForAccounts = async () => { + return { + messengerMocks: mockUserStorageMessenger({ + accounts: { + accountsList: + MOCK_INTERNAL_ACCOUNTS.ONE_DEFAULT_NAME as InternalAccount[], + }, + }), + mockAPI: { + mockEndpointGetUserStorage: + await mockEndpointGetUserStorageAllFeatureEntries( + 'accounts', + await mockUserStorageAccountsResponse(), + ), + }, + }; + }; + + const onAccountNameUpdated = jest.fn(); + + const { messengerMocks, mockAPI } = await arrangeMocksForAccounts(); + const controller = new UserStorageController({ + messenger: messengerMocks.messenger, + config: { + accountSyncing: { + onAccountNameUpdated, + }, + }, + env: { + isAccountSyncingEnabled: true, + }, + getMetaMetricsState: () => true, + }); + + await controller.syncInternalAccountsWithUserStorage(); + + mockAPI.mockEndpointGetUserStorage.done(); + + expect(onAccountNameUpdated).toHaveBeenCalledTimes(1); + }); }); describe('User storage name is a custom name with last updated', () => { diff --git a/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.ts b/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.ts index 5af28ab924..c7de6cedf0 100644 --- a/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.ts +++ b/packages/profile-sync-controller/src/controllers/user-storage/UserStorageController.ts @@ -119,6 +119,22 @@ const metadata: StateMetadata = { }, }; +type ControllerConfig = { + accountSyncing?: { + /** + * Callback that fires when account sync adds an account. + * This is used for analytics. + */ + onAccountAdded?: (profileId: string) => void; + + /** + * Callback that fires when account sync updates the name of an account. + * This is used for analytics. + */ + onAccountNameUpdated?: (profileId: string) => void; + }; +}; + // Messenger Actions type CreateActionsObj = { [K in Controller]: { @@ -347,6 +363,8 @@ export default class UserStorageController extends BaseController< }, }; + #config?: ControllerConfig; + #notificationServices = { disableNotificationServices: async () => { return await this.messagingSystem.call( @@ -387,11 +405,13 @@ export default class UserStorageController extends BaseController< messenger, state, env, + config, getMetaMetricsState, nativeScryptCrypto, }: { messenger: UserStorageControllerMessenger; state?: UserStorageControllerState; + config?: ControllerConfig; env?: { isAccountSyncingEnabled?: boolean; isNetworkSyncingEnabled?: boolean; @@ -406,6 +426,8 @@ export default class UserStorageController extends BaseController< state: { ...defaultState, ...state }, }); + this.#config = config; + this.#accounts.isAccountSyncingEnabled = Boolean( env?.isAccountSyncingEnabled, ); @@ -722,6 +744,8 @@ export default class UserStorageController extends BaseController< try { this.#accounts.isAccountSyncingInProgress = true; + const profileId = await this.#auth.getProfileId(); + const userStorageAccountsList = await this.#accounts.getUserStorageAccountsList(); @@ -752,6 +776,7 @@ export default class UserStorageController extends BaseController< length: numberOfAccountsToAdd, }).map(async () => { await this.messagingSystem.call('KeyringController:addNewAccount'); + this.#config?.accountSyncing?.onAccountAdded?.(profileId); }); await Promise.all(addNewAccountsPromises); @@ -791,6 +816,8 @@ export default class UserStorageController extends BaseController< name: userStorageAccount.n, }, ); + + this.#config?.accountSyncing?.onAccountNameUpdated?.(profileId); } continue; } @@ -830,6 +857,8 @@ export default class UserStorageController extends BaseController< }, ); + this.#config?.accountSyncing?.onAccountNameUpdated?.(profileId); + continue; } else if (internalAccount.metadata.nameLastUpdatedAt !== undefined) { await this.#accounts.saveInternalAccountToUserStorage(