mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Allow user to turn off ENS DNS resolution (#20102)
* Allow user to turn off IPFS gateway resolution * Add end to end test for toggle on and off * Fix jest tests and snapshots * Change variable name * Implement provided content * Use MetaMask eth instead * Allow searching for ENS setting * Fix jest --------- Co-authored-by: Brad Decker <bhdecker84@gmail.com>
This commit is contained in:
parent
05b1b19c6f
commit
99c709ff8f
18
app/_locales/en/messages.json
generated
18
app/_locales/en/messages.json
generated
@ -1426,6 +1426,24 @@
|
|||||||
"enhancedTokenDetectionAlertMessage": {
|
"enhancedTokenDetectionAlertMessage": {
|
||||||
"message": "Enhanced token detection is currently available on $1. $2"
|
"message": "Enhanced token detection is currently available on $1. $2"
|
||||||
},
|
},
|
||||||
|
"ensDomainsSettingDescriptionIntro": {
|
||||||
|
"message": "MetaMask lets you see ENS domains like \"https://metamask.eth\" right in your browser's address bar. Here's how it works:"
|
||||||
|
},
|
||||||
|
"ensDomainsSettingDescriptionOutro": {
|
||||||
|
"message": "Regular browsers don't usually handle ENS or IPFS addresses, but MetaMask helps with that. Using this feature might share your IP address with IPFS third-party services."
|
||||||
|
},
|
||||||
|
"ensDomainsSettingDescriptionPoint1": {
|
||||||
|
"message": "MetaMask checks with Ethereum's ENS contract to find the code connected to the ENS name."
|
||||||
|
},
|
||||||
|
"ensDomainsSettingDescriptionPoint2": {
|
||||||
|
"message": "If the code is linked to IPFS, it gets the content from the IPFS network."
|
||||||
|
},
|
||||||
|
"ensDomainsSettingDescriptionPoint3": {
|
||||||
|
"message": "Then, you can see the content, usually a website or something similar."
|
||||||
|
},
|
||||||
|
"ensDomainsSettingTitle": {
|
||||||
|
"message": "Show ENS domains in address bar"
|
||||||
|
},
|
||||||
"ensIllegalCharacter": {
|
"ensIllegalCharacter": {
|
||||||
"message": "Illegal character for ENS."
|
"message": "Illegal character for ENS."
|
||||||
},
|
},
|
||||||
|
@ -466,6 +466,9 @@ export function setupController(
|
|||||||
getIpfsGateway: controller.preferencesController.getIpfsGateway.bind(
|
getIpfsGateway: controller.preferencesController.getIpfsGateway.bind(
|
||||||
controller.preferencesController,
|
controller.preferencesController,
|
||||||
),
|
),
|
||||||
|
getUseAddressBarEnsResolution: () =>
|
||||||
|
controller.preferencesController.store.getState()
|
||||||
|
.useAddressBarEnsResolution,
|
||||||
provider: controller.provider,
|
provider: controller.provider,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ export default class PreferencesController {
|
|||||||
},
|
},
|
||||||
// ENS decentralized website resolution
|
// ENS decentralized website resolution
|
||||||
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,
|
ipfsGateway: IPFS_DEFAULT_GATEWAY_URL,
|
||||||
|
useAddressBarEnsResolution: true,
|
||||||
infuraBlocked: null,
|
infuraBlocked: null,
|
||||||
ledgerTransportType: window.navigator.hid
|
ledgerTransportType: window.navigator.hid
|
||||||
? LedgerTransportTypes.webhid
|
? LedgerTransportTypes.webhid
|
||||||
@ -480,6 +481,15 @@ export default class PreferencesController {
|
|||||||
return domain;
|
return domain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A setter for the `useAddressBarEnsResolution` property
|
||||||
|
*
|
||||||
|
* @param {boolean} useAddressBarEnsResolution - Whether or not user prefers IPFS resolution for domains
|
||||||
|
*/
|
||||||
|
async setUseAddressBarEnsResolution(useAddressBarEnsResolution) {
|
||||||
|
this.store.updateState({ useAddressBarEnsResolution });
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A setter for the `ledgerTransportType` property.
|
* A setter for the `ledgerTransportType` property.
|
||||||
*
|
*
|
||||||
|
@ -13,6 +13,7 @@ export default function setupEnsIpfsResolver({
|
|||||||
provider,
|
provider,
|
||||||
getCurrentChainId,
|
getCurrentChainId,
|
||||||
getIpfsGateway,
|
getIpfsGateway,
|
||||||
|
getUseAddressBarEnsResolution,
|
||||||
}) {
|
}) {
|
||||||
// install listener
|
// install listener
|
||||||
const urlPatterns = supportedTopLevelDomains.map((tld) => `*://*.${tld}/*`);
|
const urlPatterns = supportedTopLevelDomains.map((tld) => `*://*.${tld}/*`);
|
||||||
@ -33,7 +34,12 @@ export default function setupEnsIpfsResolver({
|
|||||||
const { tabId, url } = details;
|
const { tabId, url } = details;
|
||||||
// ignore requests that are not associated with tabs
|
// ignore requests that are not associated with tabs
|
||||||
// only attempt ENS resolution on mainnet
|
// only attempt ENS resolution on mainnet
|
||||||
if (tabId === -1 || getCurrentChainId() !== '0x1') {
|
if (
|
||||||
|
(tabId === -1 || getCurrentChainId() !== '0x1') &&
|
||||||
|
// E2E tests use a chain other than 0x1, so for testing,
|
||||||
|
// allow the reuqest to pass through
|
||||||
|
!process.env.IN_TEST
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// parse ens name
|
// parse ens name
|
||||||
@ -50,9 +56,23 @@ export default function setupEnsIpfsResolver({
|
|||||||
|
|
||||||
async function attemptResolve({ tabId, name, pathname, search, fragment }) {
|
async function attemptResolve({ tabId, name, pathname, search, fragment }) {
|
||||||
const ipfsGateway = getIpfsGateway();
|
const ipfsGateway = getIpfsGateway();
|
||||||
|
const useAddressBarEnsResolution = getUseAddressBarEnsResolution();
|
||||||
|
|
||||||
|
if (!useAddressBarEnsResolution || ipfsGateway === '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
browser.tabs.update(tabId, { url: `loading.html` });
|
browser.tabs.update(tabId, { url: `loading.html` });
|
||||||
|
|
||||||
let url = `https://app.ens.domains/name/${name}`;
|
let url = `https://app.ens.domains/name/${name}`;
|
||||||
|
|
||||||
|
// If we're testing ENS domain resolution support,
|
||||||
|
// we assume the ENS domains URL
|
||||||
|
if (process.env.IN_TEST) {
|
||||||
|
browser.tabs.update(tabId, { url });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { type, hash } = await resolveEnsToIpfsContentId({
|
const { type, hash } = await resolveEnsToIpfsContentId({
|
||||||
provider,
|
provider,
|
||||||
|
@ -2233,6 +2233,10 @@ export default class MetamaskController extends EventEmitter {
|
|||||||
setIpfsGateway: preferencesController.setIpfsGateway.bind(
|
setIpfsGateway: preferencesController.setIpfsGateway.bind(
|
||||||
preferencesController,
|
preferencesController,
|
||||||
),
|
),
|
||||||
|
setUseAddressBarEnsResolution:
|
||||||
|
preferencesController.setUseAddressBarEnsResolution.bind(
|
||||||
|
preferencesController,
|
||||||
|
),
|
||||||
setParticipateInMetaMetrics:
|
setParticipateInMetaMetrics:
|
||||||
metaMetricsController.setParticipateInMetaMetrics.bind(
|
metaMetricsController.setParticipateInMetaMetrics.bind(
|
||||||
metaMetricsController,
|
metaMetricsController,
|
||||||
|
@ -190,7 +190,14 @@ async function withFixtures(options, testSuite) {
|
|||||||
if (phishingPageServer.isRunning()) {
|
if (phishingPageServer.isRunning()) {
|
||||||
await phishingPageServer.quit();
|
await phishingPageServer.quit();
|
||||||
}
|
}
|
||||||
await mockServer.stop();
|
|
||||||
|
// Since mockServer could be stop'd at another location,
|
||||||
|
// use a try/catch to avoid an error
|
||||||
|
try {
|
||||||
|
await mockServer.stop();
|
||||||
|
} catch (e) {
|
||||||
|
console.log('mockServer already stopped');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
79
test/e2e/tests/ipfs-ens-resolution.spec.js
Normal file
79
test/e2e/tests/ipfs-ens-resolution.spec.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
const { strict: assert } = require('assert');
|
||||||
|
const { buildWebDriver } = require('../webdriver');
|
||||||
|
const { withFixtures } = require('../helpers');
|
||||||
|
const FixtureBuilder = require('../fixture-builder');
|
||||||
|
|
||||||
|
describe('Settings', function () {
|
||||||
|
const ENS_NAME = 'metamask.eth';
|
||||||
|
const ENS_NAME_URL = `https://${ENS_NAME}/`;
|
||||||
|
const ENS_DESTINATION_URL = `https://app.ens.domains/name/${ENS_NAME}`;
|
||||||
|
|
||||||
|
it('Redirects to ENS domains when user inputs ENS into address bar', async function () {
|
||||||
|
// Using proxy port that doesn't resolve so that the browser can error out properly
|
||||||
|
// on the ".eth" hostname. The proxy does too much interference with 8000.
|
||||||
|
const { driver } = await buildWebDriver({ proxyUrl: '127.0.0.1:8001' });
|
||||||
|
await driver.navigate();
|
||||||
|
|
||||||
|
// The setting defaults to "on" so we can simply enter an ENS address
|
||||||
|
// into the address bar and listen for address change
|
||||||
|
try {
|
||||||
|
await driver.openNewPage(ENS_NAME_URL);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore ERR_PROXY_CONNECTION_FAILED error
|
||||||
|
// since all we care about is getting to the correct URL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the redirect to ENS Domains has happened
|
||||||
|
const currentUrl = await driver.getCurrentUrl();
|
||||||
|
assert.equal(currentUrl, ENS_DESTINATION_URL);
|
||||||
|
|
||||||
|
await driver.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Does not lookup IPFS data for ENS Domain when switched off', async function () {
|
||||||
|
let server;
|
||||||
|
|
||||||
|
await withFixtures(
|
||||||
|
{
|
||||||
|
fixtures: new FixtureBuilder().build(),
|
||||||
|
title: this.test.title,
|
||||||
|
testSpecificMock: (mockServer) => {
|
||||||
|
server = mockServer;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
async ({ driver }) => {
|
||||||
|
await driver.navigate();
|
||||||
|
await driver.fill('#password', 'correct horse battery staple');
|
||||||
|
await driver.press('#password', driver.Key.ENTER);
|
||||||
|
|
||||||
|
// goes to the settings screen
|
||||||
|
await driver.clickElement(
|
||||||
|
'[data-testid="account-options-menu-button"]',
|
||||||
|
);
|
||||||
|
await driver.clickElement({ text: 'Settings', tag: 'div' });
|
||||||
|
await driver.clickElement({ text: 'Security & privacy', tag: 'div' });
|
||||||
|
|
||||||
|
// turns off IPFS domain resolution
|
||||||
|
await driver.clickElement(
|
||||||
|
'[data-testid="ipfs-gateway-resolution-container"] .toggle-button',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Now that we no longer need the MetaMask UI, and want the browser
|
||||||
|
// to handle the request error, we need to stop the server
|
||||||
|
await server.stop();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await driver.openNewPage(ENS_NAME_URL);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore ERR_PROXY_CONNECTION_FAILED error
|
||||||
|
// since all we care about is getting to the correct URL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the redirect to ENS Domains does not happen
|
||||||
|
// Instead, the domain will be kept which is a 404
|
||||||
|
const currentUrl = await driver.getCurrentUrl();
|
||||||
|
assert.equal(currentUrl, ENS_NAME_URL);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -205,6 +205,13 @@ export const SETTINGS_CONSTANTS = [
|
|||||||
route: `${SECURITY_ROUTE}#price-checker`,
|
route: `${SECURITY_ROUTE}#price-checker`,
|
||||||
icon: 'fa fa-lock',
|
icon: 'fa fa-lock',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
tabMessage: (t) => t('securityAndPrivacy'),
|
||||||
|
sectionMessage: (t) => t('ensDomainsSettingTitle'),
|
||||||
|
descriptionMessage: (t) => t('ensDomainsSettingDescriptionIntro'),
|
||||||
|
route: `${SECURITY_ROUTE}#ens-domains`,
|
||||||
|
icon: 'fa fa-lock',
|
||||||
|
},
|
||||||
{
|
{
|
||||||
tabMessage: (t) => t('alerts'),
|
tabMessage: (t) => t('alerts'),
|
||||||
sectionMessage: (t) => t('alertSettingsUnconnectedAccount'),
|
sectionMessage: (t) => t('alertSettingsUnconnectedAccount'),
|
||||||
|
@ -165,7 +165,7 @@ describe('Settings Search Utils', () => {
|
|||||||
it('should get good security & privacy section number', () => {
|
it('should get good security & privacy section number', () => {
|
||||||
expect(
|
expect(
|
||||||
getNumberOfSettingsInSection(t, t('securityAndPrivacy')),
|
getNumberOfSettingsInSection(t, t('securityAndPrivacy')),
|
||||||
).toStrictEqual(9);
|
).toStrictEqual(10);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should get good alerts section number', () => {
|
it('should get good alerts section number', () => {
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
} from '../../../../shared/lib/ui-utils';
|
} from '../../../../shared/lib/ui-utils';
|
||||||
import {
|
import {
|
||||||
PickerNetwork,
|
PickerNetwork,
|
||||||
|
Text,
|
||||||
TextField,
|
TextField,
|
||||||
} from '../../../components/component-library';
|
} from '../../../components/component-library';
|
||||||
import Box from '../../../components/ui/box/box';
|
import Box from '../../../components/ui/box/box';
|
||||||
@ -22,6 +23,7 @@ import { MetaMetricsContext } from '../../../contexts/metametrics';
|
|||||||
import {
|
import {
|
||||||
FONT_WEIGHT,
|
FONT_WEIGHT,
|
||||||
TextColor,
|
TextColor,
|
||||||
|
TextVariant,
|
||||||
TypographyVariant,
|
TypographyVariant,
|
||||||
} from '../../../helpers/constants/design-system';
|
} from '../../../helpers/constants/design-system';
|
||||||
import { ONBOARDING_PIN_EXTENSION_ROUTE } from '../../../helpers/constants/routes';
|
import { ONBOARDING_PIN_EXTENSION_ROUTE } from '../../../helpers/constants/routes';
|
||||||
@ -35,6 +37,7 @@ import {
|
|||||||
setUseMultiAccountBalanceChecker,
|
setUseMultiAccountBalanceChecker,
|
||||||
setUsePhishDetect,
|
setUsePhishDetect,
|
||||||
setUseTokenDetection,
|
setUseTokenDetection,
|
||||||
|
setUseAddressBarEnsResolution,
|
||||||
showModal,
|
showModal,
|
||||||
toggleNetworkMenu,
|
toggleNetworkMenu,
|
||||||
} from '../../../store/actions';
|
} from '../../../store/actions';
|
||||||
@ -54,6 +57,7 @@ export default function PrivacySettings() {
|
|||||||
setMultiAccountBalanceCheckerEnabled,
|
setMultiAccountBalanceCheckerEnabled,
|
||||||
] = useState(true);
|
] = useState(true);
|
||||||
const [ipfsURL, setIPFSURL] = useState('');
|
const [ipfsURL, setIPFSURL] = useState('');
|
||||||
|
const [addressBarResolution, setAddressBarResolution] = useState(true);
|
||||||
const [ipfsError, setIPFSError] = useState(null);
|
const [ipfsError, setIPFSError] = useState(null);
|
||||||
const trackEvent = useContext(MetaMetricsContext);
|
const trackEvent = useContext(MetaMetricsContext);
|
||||||
|
|
||||||
@ -70,6 +74,7 @@ export default function PrivacySettings() {
|
|||||||
);
|
);
|
||||||
dispatch(setUseCurrencyRateCheck(turnOnCurrencyRateCheck));
|
dispatch(setUseCurrencyRateCheck(turnOnCurrencyRateCheck));
|
||||||
dispatch(setCompletedOnboarding());
|
dispatch(setCompletedOnboarding());
|
||||||
|
dispatch(setUseAddressBarEnsResolution(addressBarResolution));
|
||||||
|
|
||||||
if (ipfsURL && !ipfsError) {
|
if (ipfsURL && !ipfsError) {
|
||||||
const { host } = new URL(addUrlProtocolPrefix(ipfsURL));
|
const { host } = new URL(addUrlProtocolPrefix(ipfsURL));
|
||||||
@ -252,6 +257,38 @@ export default function PrivacySettings() {
|
|||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Setting
|
||||||
|
value={addressBarResolution}
|
||||||
|
setValue={setAddressBarResolution}
|
||||||
|
title={t('ensDomainsSettingTitle')}
|
||||||
|
description={
|
||||||
|
<>
|
||||||
|
<Text variant={TextVariant.inherit}>
|
||||||
|
{t('ensDomainsSettingDescriptionIntro')}
|
||||||
|
</Text>
|
||||||
|
<Box
|
||||||
|
as="ul"
|
||||||
|
marginTop={4}
|
||||||
|
marginBottom={4}
|
||||||
|
paddingInlineStart={4}
|
||||||
|
style={{ listStyleType: 'circle' }}
|
||||||
|
>
|
||||||
|
<Text variant={TextVariant.inherit} as="li">
|
||||||
|
{t('ensDomainsSettingDescriptionPoint1')}
|
||||||
|
</Text>
|
||||||
|
<Text variant={TextVariant.inherit} as="li">
|
||||||
|
{t('ensDomainsSettingDescriptionPoint2')}
|
||||||
|
</Text>
|
||||||
|
<Text variant={TextVariant.inherit} as="li">
|
||||||
|
{t('ensDomainsSettingDescriptionPoint3')}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Text variant={TextVariant.inherit}>
|
||||||
|
{t('ensDomainsSettingDescriptionOutro')}
|
||||||
|
</Text>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
<Setting
|
<Setting
|
||||||
value={turnOnCurrencyRateCheck}
|
value={turnOnCurrencyRateCheck}
|
||||||
setValue={setTurnOnCurrencyRateCheck}
|
setValue={setTurnOnCurrencyRateCheck}
|
||||||
|
@ -28,6 +28,7 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
.fn()
|
.fn()
|
||||||
.mockImplementation(() => Promise.resolve());
|
.mockImplementation(() => Promise.resolve());
|
||||||
const setUseMultiAccountBalanceCheckerStub = jest.fn();
|
const setUseMultiAccountBalanceCheckerStub = jest.fn();
|
||||||
|
const setUseAddressBarEnsResolutionStub = jest.fn();
|
||||||
|
|
||||||
setBackgroundConnection({
|
setBackgroundConnection({
|
||||||
setFeatureFlag: setFeatureFlagStub,
|
setFeatureFlag: setFeatureFlagStub,
|
||||||
@ -37,6 +38,7 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
setIpfsGateway: setIpfsGatewayStub,
|
setIpfsGateway: setIpfsGatewayStub,
|
||||||
completeOnboarding: completeOnboardingStub,
|
completeOnboarding: completeOnboardingStub,
|
||||||
setUseMultiAccountBalanceChecker: setUseMultiAccountBalanceCheckerStub,
|
setUseMultiAccountBalanceChecker: setUseMultiAccountBalanceCheckerStub,
|
||||||
|
setUseAddressBarEnsResolution: setUseAddressBarEnsResolutionStub,
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should update preferences', () => {
|
it('should update preferences', () => {
|
||||||
@ -50,6 +52,7 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(0);
|
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(0);
|
||||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(0);
|
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(0);
|
||||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(0);
|
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(0);
|
||||||
|
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(0);
|
||||||
|
|
||||||
const toggles = container.querySelectorAll('input[type=checkbox]');
|
const toggles = container.querySelectorAll('input[type=checkbox]');
|
||||||
const submitButton = getByText('Done');
|
const submitButton = getByText('Done');
|
||||||
@ -60,6 +63,7 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
fireEvent.click(toggles[2]);
|
fireEvent.click(toggles[2]);
|
||||||
fireEvent.click(toggles[3]);
|
fireEvent.click(toggles[3]);
|
||||||
fireEvent.click(toggles[4]);
|
fireEvent.click(toggles[4]);
|
||||||
|
fireEvent.click(toggles[5]);
|
||||||
fireEvent.click(submitButton);
|
fireEvent.click(submitButton);
|
||||||
|
|
||||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(1);
|
expect(setFeatureFlagStub).toHaveBeenCalledTimes(1);
|
||||||
@ -67,6 +71,7 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(1);
|
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(1);
|
||||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(1);
|
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(1);
|
||||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(1);
|
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(1);
|
||||||
|
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
expect(setFeatureFlagStub.mock.calls[0][1]).toStrictEqual(false);
|
expect(setFeatureFlagStub.mock.calls[0][1]).toStrictEqual(false);
|
||||||
expect(setUsePhishDetectStub.mock.calls[0][0]).toStrictEqual(false);
|
expect(setUsePhishDetectStub.mock.calls[0][0]).toStrictEqual(false);
|
||||||
@ -75,6 +80,9 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
expect(setUseCurrencyRateCheckStub.mock.calls[0][0]).toStrictEqual(false);
|
expect(setUseCurrencyRateCheckStub.mock.calls[0][0]).toStrictEqual(false);
|
||||||
|
expect(setUseAddressBarEnsResolutionStub.mock.calls[0][0]).toStrictEqual(
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
// toggle back to true
|
// toggle back to true
|
||||||
fireEvent.click(toggles[0]);
|
fireEvent.click(toggles[0]);
|
||||||
@ -82,12 +90,14 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
fireEvent.click(toggles[2]);
|
fireEvent.click(toggles[2]);
|
||||||
fireEvent.click(toggles[3]);
|
fireEvent.click(toggles[3]);
|
||||||
fireEvent.click(toggles[4]);
|
fireEvent.click(toggles[4]);
|
||||||
|
fireEvent.click(toggles[5]);
|
||||||
fireEvent.click(submitButton);
|
fireEvent.click(submitButton);
|
||||||
expect(setFeatureFlagStub).toHaveBeenCalledTimes(2);
|
expect(setFeatureFlagStub).toHaveBeenCalledTimes(2);
|
||||||
expect(setUsePhishDetectStub).toHaveBeenCalledTimes(2);
|
expect(setUsePhishDetectStub).toHaveBeenCalledTimes(2);
|
||||||
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(2);
|
expect(setUseTokenDetectionStub).toHaveBeenCalledTimes(2);
|
||||||
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(2);
|
expect(setUseMultiAccountBalanceCheckerStub).toHaveBeenCalledTimes(2);
|
||||||
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(2);
|
expect(setUseCurrencyRateCheckStub).toHaveBeenCalledTimes(2);
|
||||||
|
expect(setUseAddressBarEnsResolutionStub).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
expect(setFeatureFlagStub.mock.calls[1][1]).toStrictEqual(true);
|
expect(setFeatureFlagStub.mock.calls[1][1]).toStrictEqual(true);
|
||||||
expect(setUsePhishDetectStub.mock.calls[1][0]).toStrictEqual(true);
|
expect(setUsePhishDetectStub.mock.calls[1][0]).toStrictEqual(true);
|
||||||
@ -96,6 +106,9 @@ describe('Privacy Settings Onboarding View', () => {
|
|||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
expect(setUseCurrencyRateCheckStub.mock.calls[1][0]).toStrictEqual(true);
|
expect(setUseCurrencyRateCheckStub.mock.calls[1][0]).toStrictEqual(true);
|
||||||
|
expect(setUseAddressBarEnsResolutionStub.mock.calls[1][0]).toStrictEqual(
|
||||||
|
true,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('IPFS', () => {
|
describe('IPFS', () => {
|
||||||
|
@ -405,6 +405,100 @@ exports[`Security Tab should match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
class="settings-page__content-item"
|
||||||
|
id="ens-domains"
|
||||||
|
>
|
||||||
|
Show ENS domains in address bar
|
||||||
|
<div
|
||||||
|
class="settings-page__content-description"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||||
|
>
|
||||||
|
MetaMask lets you see ENS domains like "https://metamask.eth" right in your browser's address bar. Here's how it works:
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
class="mm-box mm-box--margin-top-4 mm-box--margin-bottom-4 mm-box--padding-inline-start-4"
|
||||||
|
style="list-style-type: circle;"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||||
|
>
|
||||||
|
MetaMask checks with Ethereum's ENS contract to find the code connected to the ENS name.
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||||
|
>
|
||||||
|
If the code is linked to IPFS, it gets the content from the IPFS network.
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||||
|
>
|
||||||
|
Then, you can see the content, usually a website or something similar.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<span
|
||||||
|
class="mm-box mm-text mm-text--inherit mm-box--color-inherit"
|
||||||
|
>
|
||||||
|
Regular browsers don't usually handle ENS or IPFS addresses, but MetaMask helps with that. Using this feature might share your IP address with IPFS third-party services.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="settings-page__content-item"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="settings-page__content-item-col"
|
||||||
|
data-testid="ipfs-gateway-resolution-container"
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
class="toggle-button toggle-button--off"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="display: flex; width: 52px; align-items: center; justify-content: flex-start; position: relative; cursor: pointer; background-color: transparent; border: 0px; padding: 0px; user-select: none;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="width: 40px; height: 24px; padding: 0px; border-radius: 26px; display: flex; align-items: center; justify-content: center; background-color: rgb(242, 244, 246);"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgb(250, 250, 250); margin-top: auto; margin-bottom: auto; line-height: 0; opacity: 0; width: 26px; height: 20px; left: 4px;"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
style="font-size: 11px; display: flex; align-items: center; justify-content: center; font-family: 'Helvetica Neue', Helvetica, sans-serif; position: relative; color: rgba(255, 255, 255, 0.6); bottom: 0px; margin-top: auto; margin-bottom: auto; padding-right: 5px; line-height: 0; width: 26px; height: 20px; opacity: 1;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="position: absolute; height: 100%; top: 0px; left: 0px; display: flex; flex: 1; align-self: stretch; align-items: center; justify-content: flex-start;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="width: 18px; height: 18px; display: flex; align-self: center; box-shadow: none; border-radius: 50%; box-sizing: border-box; position: relative; background-color: rgb(106, 115, 125); left: 3px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
style="border: 0px; height: 1px; margin: -1px; overflow: hidden; padding: 0px; position: absolute; width: 1px;"
|
||||||
|
type="checkbox"
|
||||||
|
value="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="toggle-button__status"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="toggle-button__label-off"
|
||||||
|
>
|
||||||
|
Off
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
class="toggle-button__label-on"
|
||||||
|
>
|
||||||
|
On
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
|
@ -31,6 +31,11 @@ import {
|
|||||||
getNumberOfSettingsInSection,
|
getNumberOfSettingsInSection,
|
||||||
handleSettingsRefs,
|
handleSettingsRefs,
|
||||||
} from '../../../helpers/utils/settings-search';
|
} from '../../../helpers/utils/settings-search';
|
||||||
|
import { Box, Text } from '../../../components/component-library';
|
||||||
|
import {
|
||||||
|
TextColor,
|
||||||
|
TextVariant,
|
||||||
|
} from '../../../helpers/constants/design-system';
|
||||||
|
|
||||||
export default class SecurityTab extends PureComponent {
|
export default class SecurityTab extends PureComponent {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -55,6 +60,8 @@ export default class SecurityTab extends PureComponent {
|
|||||||
setUseMultiAccountBalanceChecker: PropTypes.func.isRequired,
|
setUseMultiAccountBalanceChecker: PropTypes.func.isRequired,
|
||||||
useCurrencyRateCheck: PropTypes.bool.isRequired,
|
useCurrencyRateCheck: PropTypes.bool.isRequired,
|
||||||
setUseCurrencyRateCheck: PropTypes.func.isRequired,
|
setUseCurrencyRateCheck: PropTypes.func.isRequired,
|
||||||
|
useAddressBarEnsResolution: PropTypes.bool.isRequired,
|
||||||
|
setUseAddressBarEnsResolution: PropTypes.func.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
@ -309,6 +316,8 @@ export default class SecurityTab extends PureComponent {
|
|||||||
renderIpfsGatewayControl() {
|
renderIpfsGatewayControl() {
|
||||||
const { t } = this.context;
|
const { t } = this.context;
|
||||||
const { ipfsGatewayError } = this.state;
|
const { ipfsGatewayError } = this.state;
|
||||||
|
const { useAddressBarEnsResolution, setUseAddressBarEnsResolution } =
|
||||||
|
this.props;
|
||||||
|
|
||||||
const handleIpfsGatewaySave = (gateway) => {
|
const handleIpfsGatewaySave = (gateway) => {
|
||||||
const url = new URL(addUrlProtocolPrefix(gateway));
|
const url = new URL(addUrlProtocolPrefix(gateway));
|
||||||
@ -370,6 +379,63 @@ export default class SecurityTab extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
className="settings-page__content-item"
|
||||||
|
ref={this.settingsRefs[9]}
|
||||||
|
id="ens-domains"
|
||||||
|
>
|
||||||
|
{t('ensDomainsSettingTitle')}
|
||||||
|
<div className="settings-page__content-description">
|
||||||
|
<Text color={TextColor.inherit} variant={TextVariant.inherit}>
|
||||||
|
{t('ensDomainsSettingDescriptionIntro')}
|
||||||
|
</Text>
|
||||||
|
<Box
|
||||||
|
as="ul"
|
||||||
|
marginTop={4}
|
||||||
|
marginBottom={4}
|
||||||
|
paddingInlineStart={4}
|
||||||
|
style={{ listStyleType: 'circle' }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
as="li"
|
||||||
|
color={TextColor.inherit}
|
||||||
|
variant={TextVariant.inherit}
|
||||||
|
>
|
||||||
|
{t('ensDomainsSettingDescriptionPoint1')}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
as="li"
|
||||||
|
color={TextColor.inherit}
|
||||||
|
variant={TextVariant.inherit}
|
||||||
|
>
|
||||||
|
{t('ensDomainsSettingDescriptionPoint2')}
|
||||||
|
</Text>
|
||||||
|
<Text
|
||||||
|
as="li"
|
||||||
|
color={TextColor.inherit}
|
||||||
|
variant={TextVariant.inherit}
|
||||||
|
>
|
||||||
|
{t('ensDomainsSettingDescriptionPoint3')}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Text color={TextColor.inherit} variant={TextVariant.inherit}>
|
||||||
|
{t('ensDomainsSettingDescriptionOutro')}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="settings-page__content-item">
|
||||||
|
<div
|
||||||
|
className="settings-page__content-item-col"
|
||||||
|
data-testid="ipfs-gateway-resolution-container"
|
||||||
|
>
|
||||||
|
<ToggleButton
|
||||||
|
value={useAddressBarEnsResolution}
|
||||||
|
onToggle={(value) => setUseAddressBarEnsResolution(!value)}
|
||||||
|
offLabel={t('off')}
|
||||||
|
onLabel={t('on')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
setUseMultiAccountBalanceChecker,
|
setUseMultiAccountBalanceChecker,
|
||||||
setUsePhishDetect,
|
setUsePhishDetect,
|
||||||
setUseTokenDetection,
|
setUseTokenDetection,
|
||||||
|
setUseAddressBarEnsResolution,
|
||||||
} from '../../../store/actions';
|
} from '../../../store/actions';
|
||||||
import SecurityTab from './security-tab.component';
|
import SecurityTab from './security-tab.component';
|
||||||
|
|
||||||
@ -25,6 +26,7 @@ const mapStateToProps = (state) => {
|
|||||||
ipfsGateway,
|
ipfsGateway,
|
||||||
useMultiAccountBalanceChecker,
|
useMultiAccountBalanceChecker,
|
||||||
useCurrencyRateCheck,
|
useCurrencyRateCheck,
|
||||||
|
useAddressBarEnsResolution,
|
||||||
} = metamask;
|
} = metamask;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -36,6 +38,7 @@ const mapStateToProps = (state) => {
|
|||||||
ipfsGateway,
|
ipfsGateway,
|
||||||
useMultiAccountBalanceChecker,
|
useMultiAccountBalanceChecker,
|
||||||
useCurrencyRateCheck,
|
useCurrencyRateCheck,
|
||||||
|
useAddressBarEnsResolution,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -56,6 +59,8 @@ const mapDispatchToProps = (dispatch) => {
|
|||||||
setUseMultiAccountBalanceChecker: (value) => {
|
setUseMultiAccountBalanceChecker: (value) => {
|
||||||
return dispatch(setUseMultiAccountBalanceChecker(value));
|
return dispatch(setUseMultiAccountBalanceChecker(value));
|
||||||
},
|
},
|
||||||
|
setUseAddressBarEnsResolution: (value) =>
|
||||||
|
dispatch(setUseAddressBarEnsResolution(value)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3095,6 +3095,19 @@ export function setIpfsGateway(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function setUseAddressBarEnsResolution(
|
||||||
|
val: string,
|
||||||
|
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||||
|
return (dispatch: MetaMaskReduxDispatch) => {
|
||||||
|
log.debug(`background.setUseAddressBarEnsResolution`);
|
||||||
|
callBackgroundMethod('setUseAddressBarEnsResolution', [val], (err) => {
|
||||||
|
if (err) {
|
||||||
|
dispatch(displayWarning(err));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export function updateCurrentLocale(
|
export function updateCurrentLocale(
|
||||||
key: string,
|
key: string,
|
||||||
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user