Skip to content

Commit

Permalink
Merge branch 'main' into 28610-bug-send-to-ens-emojis-domain---wrong-…
Browse files Browse the repository at this point in the history
…handling-of-emojis-ens-domains
  • Loading branch information
OGPoyraz authored Dec 16, 2024
2 parents bf16c20 + 45c7bfd commit 19536a7
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 83 deletions.
33 changes: 33 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -1678,6 +1678,39 @@ export default class MetamaskController extends EventEmitter {
}),
});

this.controllerMessenger.subscribe(
'MetaMetricsController:stateChange',
previousValueComparator(async (prevState, currState) => {
const { participateInMetaMetrics: prevParticipateInMetaMetrics } =
prevState;
const { participateInMetaMetrics: currParticipateInMetaMetrics } =
currState;

const metaMetricsWasDisabled =
prevParticipateInMetaMetrics && !currParticipateInMetaMetrics;
const metaMetricsWasEnabled =
!prevParticipateInMetaMetrics && currParticipateInMetaMetrics;

if (!metaMetricsWasDisabled && !metaMetricsWasEnabled) {
return;
}

const shouldPerformSignIn =
metaMetricsWasEnabled &&
!this.authenticationController.state.isSignedIn;
const shouldPerformSignOut =
metaMetricsWasDisabled &&
this.authenticationController.state.isSignedIn &&
!this.userStorageController.state.isProfileSyncingEnabled;

if (shouldPerformSignIn) {
await this.authenticationController.performSignIn();
} else if (shouldPerformSignOut) {
await this.authenticationController.performSignOut();
}
}, this.metaMetricsController.state),
);

const notificationServicesPushControllerMessenger =
this.controllerMessenger.getRestricted({
name: 'NotificationServicesPushController',
Expand Down
140 changes: 140 additions & 0 deletions app/scripts/metamask-controller.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2878,4 +2878,144 @@ describe('MetaMaskController', () => {
expect(browserPolyfillMock.storage.session.set).not.toHaveBeenCalled();
});
});

describe('MetaMetrics & authentication dependencies', () => {
let metamaskController;
let mockPerformSignIn;
let mockPerformSignOut;

const arrangeControllerState = (stateOverrides) => {
metamaskController = new MetaMaskController({
showUserConfirmation: noop,
encryptor: mockEncryptor,
initState: { ...cloneDeep(firstTimeState), ...stateOverrides },
initLangCode: 'en_US',
platform: {
showTransactionNotification: () => undefined,
getVersion: () => 'foo',
},
browser: browserPolyfillMock,
infuraProjectId: 'foo',
isFirstMetaMaskControllerSetup: true,
});

mockPerformSignIn = jest
.spyOn(metamaskController.authenticationController, 'performSignIn')
.mockResolvedValue();
mockPerformSignOut = jest
.spyOn(metamaskController.authenticationController, 'performSignOut')
.mockResolvedValue();
};

it('should sign in the user if MetaMetrics is enabled and the user is not signed in', async () => {
arrangeControllerState({
MetaMetricsController: {
participateInMetaMetrics: false,
},
AuthenticationController: {
isSignedIn: false,
},
});

metamaskController.controllerMessenger.publish(
'MetaMetricsController:stateChange',
{
participateInMetaMetrics: true,
},
);

expect(mockPerformSignIn).toHaveBeenCalledTimes(1);
expect(mockPerformSignOut).not.toHaveBeenCalled();
});

it('should sign out the user if MetaMetrics is disabled and the user is signed in but profile syncing is disabled', async () => {
arrangeControllerState({
MetaMetricsController: {
participateInMetaMetrics: true,
},
AuthenticationController: {
isSignedIn: true,
},
UserStorageController: {
isProfileSyncingEnabled: false,
},
});

metamaskController.controllerMessenger.publish(
'MetaMetricsController:stateChange',
{
participateInMetaMetrics: false,
},
);

expect(mockPerformSignIn).not.toHaveBeenCalled();
expect(mockPerformSignOut).toHaveBeenCalledTimes(1);
});

it('should not sign in the user if MetaMetrics is enabled and the user is already signed in', async () => {
arrangeControllerState({
MetaMetricsController: {
participateInMetaMetrics: false,
},
AuthenticationController: {
isSignedIn: true,
},
});

metamaskController.controllerMessenger.publish(
'MetaMetricsController:stateChange',
{
participateInMetaMetrics: true,
},
);

expect(mockPerformSignIn).not.toHaveBeenCalled();
expect(mockPerformSignOut).not.toHaveBeenCalled();
});

it('should not sign out the user if MetaMetrics is disabled and the user is not signed in', async () => {
arrangeControllerState({
MetaMetricsController: {
participateInMetaMetrics: true,
},
AuthenticationController: {
isSignedIn: false,
},
});

metamaskController.controllerMessenger.publish(
'MetaMetricsController:stateChange',
{
participateInMetaMetrics: false,
},
);

expect(mockPerformSignIn).not.toHaveBeenCalled();
expect(mockPerformSignOut).not.toHaveBeenCalled();
});

it('should not sign out the user if MetaMetrics is disabled and profile syncing is enabled', async () => {
arrangeControllerState({
MetaMetricsController: {
participateInMetaMetrics: true,
},
AuthenticationController: {
isSignedIn: true,
},
UserStorageController: {
isProfileSyncingEnabled: true,
},
});

metamaskController.controllerMessenger.publish(
'MetaMetricsController:stateChange',
{
participateInMetaMetrics: false,
},
);

expect(mockPerformSignIn).not.toHaveBeenCalled();
expect(mockPerformSignOut).not.toHaveBeenCalled();
});
});
});
1 change: 1 addition & 0 deletions builds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ buildTypes:
features:
- build-flask
- keyring-snaps
- solana
env:
- INFURA_FLASK_PROJECT_ID
- SEGMENT_FLASK_WRITE_KEY
Expand Down
7 changes: 4 additions & 3 deletions privacy-snapshot.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,18 @@
"on-ramp-content.uat-api.cx.metamask.io",
"phishing-detection.api.cx.metamask.io",
"portfolio.metamask.io",
"price-api.metamask-institutional.io",
"price.api.cx.metamask.io",
"proxy.api.cx.metamask.io",
"proxy.dev-api.cx.metamask.io",
"signature-insights.api.cx.metamask.io",
"raw.githubusercontent.com",
"registry.npmjs.org",
"responsive-rpc.test",
"security-alerts.api.cx.metamask.io",
"security-alerts.dev-api.cx.metamask.io",
"sentry.io",
"sepolia.infura.io",
"signature-insights.api.cx.metamask.io",
"snaps.metamask.io",
"sourcify.dev",
"start.metamask.io",
Expand All @@ -72,6 +73,6 @@
"unresponsive-rpc.test",
"unresponsive-rpc.url",
"user-storage.api.cx.metamask.io",
"www.4byte.directory",
"verify.walletconnect.com"
"verify.walletconnect.com",
"www.4byte.directory"
]
10 changes: 3 additions & 7 deletions ui/hooks/identity/useCreateSession.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { useCallback } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import log from 'loglevel';
import {
selectIsSignedIn,
selectParticipateInMetaMetrics,
} from '../../selectors/identity/authentication';
import { selectIsSignedIn } from '../../selectors/identity/authentication';
import { selectIsProfileSyncingEnabled } from '../../selectors/identity/profile-syncing';
import { performSignIn, disableProfileSyncing } from '../../store/actions';
import { getParticipateInMetaMetrics } from '../../selectors';

/**
* Custom hook to manage the creation of a session based on the user's authentication status,
Expand All @@ -26,9 +24,7 @@ export function useCreateSession(): {

const isSignedIn = useSelector(selectIsSignedIn);
const isProfileSyncingEnabled = useSelector(selectIsProfileSyncingEnabled);
const isParticipateInMetaMetrics = useSelector(
selectParticipateInMetaMetrics,
);
const isParticipateInMetaMetrics = useSelector(getParticipateInMetaMetrics);

const createSession = useCallback(async () => {
const safeDispatchDisableProfileSync = async () => {
Expand Down
22 changes: 22 additions & 0 deletions ui/hooks/identity/useProfileSyncing/profileSyncing.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,26 @@ describe('useDisableProfileSyncing()', () => {

expect(mockDisableProfileSyncingAction).toHaveBeenCalled();
});

it('should sign out the user if MetaMetrics is not enabled and the user is signed in', async () => {
const mockPerformSignOutAction = jest.spyOn(actions, 'performSignOut');

const { result } = renderHookWithProviderTyped(
() => useDisableProfileSyncing(),
{
metamask: {
participateInMetaMetrics: false,
isSignedIn: true,
},
},
undefined,
MetamaskNotificationsProvider,
);

await act(async () => {
await result.current.disableProfileSyncing();
});

expect(mockPerformSignOutAction).toHaveBeenCalled();
});
});
12 changes: 11 additions & 1 deletion ui/hooks/identity/useProfileSyncing/profileSyncing.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import { useState, useCallback } from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import log from 'loglevel';
import { useMetamaskNotificationsContext } from '../../../contexts/metamask-notifications/metamask-notifications';
import { getParticipateInMetaMetrics } from '../../../selectors';
import { selectIsSignedIn } from '../../../selectors/identity/authentication';
import {
disableProfileSyncing as disableProfileSyncingAction,
enableProfileSyncing as enableProfileSyncingAction,
setIsProfileSyncingEnabled as setIsProfileSyncingEnabledAction,
hideLoadingIndication,
performSignOut,
} from '../../../store/actions';

/**
Expand Down Expand Up @@ -53,6 +56,8 @@ export function useDisableProfileSyncing(): {
} {
const dispatch = useDispatch();
const { listNotifications } = useMetamaskNotificationsContext();
const isMetaMetricsEnabled = useSelector(getParticipateInMetaMetrics);
const isSignedIn = useSelector(selectIsSignedIn);

const [error, setError] = useState<string | null>(null);

Expand All @@ -63,6 +68,11 @@ export function useDisableProfileSyncing(): {
// disable profile syncing
await dispatch(disableProfileSyncingAction());

// sign out the user if MetaMetrics is not enabled and the user is signed in
if (!isMetaMetricsEnabled && isSignedIn) {
await dispatch(performSignOut());
}

// list notifications to update the counter
await listNotifications();
} catch (e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,13 @@ import { renderHook, act } from '@testing-library/react-hooks';
import configureStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import type { Store } from 'redux';
import * as actions from '../../store/actions';
import * as actions from '../store/actions';
import { useEnableMetametrics, useDisableMetametrics } from './useMetametrics';

const middlewares = [thunk];
const mockStore = configureStore(middlewares);

jest.mock('../../store/actions', () => ({
performSignOut: jest.fn(),
performSignIn: jest.fn(),
jest.mock('../store/actions', () => ({
setParticipateInMetaMetrics: jest.fn(),
showLoadingIndication: jest.fn(),
hideLoadingIndication: jest.fn(),
Expand All @@ -25,8 +23,6 @@ describe('useMetametrics', () => {
store = mockStore({
metamask: {
participateInMetaMetrics: false,
isProfileSyncingEnabled: false,
isSignedIn: false,
},
});

Expand All @@ -40,12 +36,10 @@ describe('useMetametrics', () => {
jest.clearAllMocks();
});

it('should enable MetaMetrics when user is not signed in and profile syncing enabled', async () => {
it('should enable MetaMetrics', async () => {
store.getState = () => ({
metamask: {
participateInMetaMetrics: true,
isProfileSyncingEnabled: true,
isSignedIn: false,
participateInMetaMetrics: false,
},
});

Expand All @@ -64,18 +58,15 @@ describe('useMetametrics', () => {

await waitForNextUpdate();

expect(actions.performSignIn).toHaveBeenCalled();
expect(actions.setParticipateInMetaMetrics).toHaveBeenCalledWith(true);
expect(store.dispatch).toHaveBeenCalled();
expect(result.current.loading).toBe(false);
});

it('should disable MetaMetrics and sign out if profile syncing is enabled', async () => {
it('should disable MetaMetrics', async () => {
store.getState = () => ({
metamask: {
participateInMetaMetrics: true,
isProfileSyncingEnabled: true,
isSignedIn: true,
},
});

Expand All @@ -94,7 +85,6 @@ describe('useMetametrics', () => {

await waitForNextUpdate();

expect(actions.performSignOut).toHaveBeenCalled();
expect(actions.setParticipateInMetaMetrics).toHaveBeenCalledWith(false);
expect(result.current.loading).toBe(false);
});
Expand Down
Loading

0 comments on commit 19536a7

Please sign in to comment.