Skip to content

Commit a3713ad

Browse files
authored
Merge pull request #31111 from MetaMask/Version-v12.14.1
Version v12.14.1 RC
2 parents 6fc1b61 + ab3ec4b commit a3713ad

File tree

18 files changed

+155
-157
lines changed

18 files changed

+155
-157
lines changed

CHANGELOG.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
66

77
## [Unreleased]
88

9-
## [12.14.0]
9+
## [12.14.1]
10+
### Fixed
11+
- Remove `previousUserTraits` property from metametrics controller state ([#30621](https://github.com/MetaMask/metamask-extension/pull/30621))
12+
13+
## [12.14.0] [DEPRECATED]
1014
### Added
1115
- Add Unichain logo ([#30361](https://github.com/MetaMask/metamask-extension/pull/30361))
1216
- Add modal to include metric ID before redirecting to the support page ([#30415](https://github.com/MetaMask/metamask-extension/pull/30415))
@@ -55,6 +59,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5559
- [Beta] Fix Solana snap validation ([#30596](https://github.com/MetaMask/metamask-extension/pull/30596))
5660
- [Beta] Fix swap source token balance on multichain networks ([#30622](https://github.com/MetaMask/metamask-extension/pull/30622))
5761

62+
## [12.13.1]
63+
### Fixed
64+
- fix: Remove previousUserTraits from metametrics controller state ([#30621](https://github.com/MetaMask/metamask-extension/pull/30621))
65+
5866
## [12.13.0]
5967
### Added
6068
- Enable bsc for smart transactions ([#29747](https://github.com/MetaMask/metamask-extension/pull/29747))
@@ -5819,8 +5827,10 @@ Update styles and spacing on the critical error page ([#20350](https://github.c
58195827
- Added the ability to restore accounts from seed words.
58205828

58215829

5822-
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.14.0...HEAD
5823-
[12.14.0]: https://github.com/MetaMask/metamask-extension/compare/v12.13.0...v12.14.0
5830+
[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v12.14.1...HEAD
5831+
[12.14.1]: https://github.com/MetaMask/metamask-extension/compare/v12.14.0...v12.14.1
5832+
[12.14.0]: https://github.com/MetaMask/metamask-extension/compare/v12.13.1...v12.14.0
5833+
[12.13.1]: https://github.com/MetaMask/metamask-extension/compare/v12.13.0...v12.13.1
58245834
[12.13.0]: https://github.com/MetaMask/metamask-extension/compare/v12.12.0...v12.13.0
58255835
[12.12.0]: https://github.com/MetaMask/metamask-extension/compare/v12.11.0...v12.12.0
58265836
[12.11.0]: https://github.com/MetaMask/metamask-extension/compare/v12.10.4...v12.11.0

app/scripts/background.js

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,6 @@ import {
4747
FakeTrezorBridge,
4848
} from '../../test/stub/keyring-bridge';
4949
import { getCurrentChainId } from '../../shared/modules/selectors/networks';
50-
import { addNonceToCsp } from '../../shared/modules/add-nonce-to-csp';
51-
import { checkURLForProviderInjection } from '../../shared/modules/provider-injection';
5250
import { PersistenceManager } from './lib/stores/persistence-manager';
5351
import ExtensionStore from './lib/stores/extension-store';
5452
import ReadOnlyNetworkStore from './lib/stores/read-only-network-store';
@@ -356,40 +354,6 @@ function maybeDetectPhishing(theController) {
356354
);
357355
}
358356

359-
/**
360-
* Overrides the Content-Security-Policy (CSP) header by adding a nonce to the `script-src` directive.
361-
* This is a workaround for [Bug #1446231](https://bugzilla.mozilla.org/show_bug.cgi?id=1446231),
362-
* which involves overriding the page CSP for inline script nodes injected by extension content scripts.
363-
*/
364-
function overrideContentSecurityPolicyHeader() {
365-
// The extension url is unique per install on Firefox, so we can safely add it as a nonce to the CSP header
366-
const nonce = btoa(browser.runtime.getURL('/'));
367-
browser.webRequest.onHeadersReceived.addListener(
368-
({ responseHeaders, url }) => {
369-
// Check whether inpage.js is going to be injected into the page or not.
370-
// There is no reason to modify the headers if we are not injecting inpage.js.
371-
const isInjected = checkURLForProviderInjection(new URL(url));
372-
373-
// Check if the user has enabled the overrideContentSecurityPolicyHeader preference
374-
const isEnabled =
375-
controller.preferencesController.state
376-
.overrideContentSecurityPolicyHeader;
377-
378-
if (isInjected && isEnabled) {
379-
for (const header of responseHeaders) {
380-
if (header.name.toLowerCase() === 'content-security-policy') {
381-
header.value = addNonceToCsp(header.value, nonce);
382-
}
383-
}
384-
}
385-
386-
return { responseHeaders };
387-
},
388-
{ types: ['main_frame', 'sub_frame'], urls: ['http://*/*', 'https://*/*'] },
389-
['blocking', 'responseHeaders'],
390-
);
391-
}
392-
393357
// These are set after initialization
394358
let connectRemote;
395359
let connectExternalExtension;
@@ -536,11 +500,6 @@ async function initialize() {
536500

537501
if (!isManifestV3) {
538502
await loadPhishingWarningPage();
539-
// Workaround for Bug #1446231 to override page CSP for inline script nodes injected by extension content scripts
540-
// https://bugzilla.mozilla.org/show_bug.cgi?id=1446231
541-
if (isFirefox) {
542-
overrideContentSecurityPolicyHeader();
543-
}
544503
}
545504
await sendReadyMessageToTabs();
546505
log.info('MetaMask initialization complete.');

app/scripts/constants/sentry-state.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,6 @@ export const SENTRY_BACKGROUND_STATE = {
188188
fragments: false,
189189
metaMetricsId: true,
190190
participateInMetaMetrics: true,
191-
previousUserTraits: false,
192191
segmentApiCalls: false,
193192
traits: false,
194193
dataCollectionForMarketing: false,

app/scripts/controllers/metametrics-controller.ts

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,6 @@ const controllerMetadata = {
211211
persist: true,
212212
anonymous: false,
213213
},
214-
previousUserTraits: {
215-
persist: true,
216-
anonymous: false,
217-
},
218214
dataCollectionForMarketing: {
219215
persist: true,
220216
anonymous: false,
@@ -239,7 +235,6 @@ const controllerMetadata = {
239235
* @property fragments - Object keyed by UUID with stored fragments as values.
240236
* @property eventsBeforeMetricsOptIn - Array of queued events added before a user opts into metrics.
241237
* @property traits - Traits that are not derived from other state keys.
242-
* @property previousUserTraits - The user traits the last time they were computed.
243238
* @property dataCollectionForMarketing - Flag to determine if data collection for marketing is enabled.
244239
* @property marketingCampaignCookieId - The marketing campaign cookie id.
245240
* @property segmentApiCalls - Object keyed by messageId with segment event type and payload as values.
@@ -251,7 +246,6 @@ export type MetaMetricsControllerState = {
251246
fragments: Record<string, MetaMetricsEventFragment>;
252247
eventsBeforeMetricsOptIn: MetaMetricsEventPayload[];
253248
traits: MetaMetricsUserTraits;
254-
previousUserTraits?: MetaMetricsUserTraits;
255249
dataCollectionForMarketing: boolean | null;
256250
marketingCampaignCookieId: string | null;
257251
segmentApiCalls: Record<
@@ -338,7 +332,6 @@ export const getDefaultMetaMetricsControllerState =
338332
latestNonAnonymousEventTimestamp: 0,
339333
eventsBeforeMetricsOptIn: [],
340334
traits: {},
341-
previousUserTraits: {},
342335
fragments: {},
343336
segmentApiCalls: {},
344337
});
@@ -354,6 +347,8 @@ export default class MetaMetricsController extends BaseController<
354347

355348
locale: string;
356349

350+
previousUserTraits?: MetaMetricsUserTraits;
351+
357352
version: MetaMetricsControllerOptions['version'];
358353

359354
#extension: MetaMetricsControllerOptions['extension'];
@@ -1180,7 +1175,7 @@ export default class MetaMetricsController extends BaseController<
11801175
? Object.keys(metamaskState.custodyAccountDetails)[0]
11811176
: null;
11821177
///: END:ONLY_INCLUDE_IF
1183-
const { traits, previousUserTraits } = this.state;
1178+
const { traits } = this.state;
11841179

11851180
const currentTraits = {
11861181
[MetaMetricsUserTrait.AddressBookEntries]: sum(
@@ -1213,7 +1208,7 @@ export default class MetaMetricsController extends BaseController<
12131208
),
12141209
[MetaMetricsUserTrait.NumberOfHDEntropies]:
12151210
this.#getNumberOfHDEntropies(metamaskState) ??
1216-
previousUserTraits?.number_of_hd_entropies,
1211+
this.previousUserTraits?.number_of_hd_entropies,
12171212
[MetaMetricsUserTrait.OpenSeaApiEnabled]: metamaskState.openSeaEnabled,
12181213
[MetaMetricsUserTrait.ThreeBoxEnabled]: false, // deprecated, hard-coded as false
12191214
[MetaMetricsUserTrait.Theme]: metamaskState.theme || 'default',
@@ -1244,24 +1239,23 @@ export default class MetaMetricsController extends BaseController<
12441239
),
12451240
};
12461241

1247-
if (!previousUserTraits && metamaskState.participateInMetaMetrics) {
1248-
this.update((state) => {
1249-
state.previousUserTraits = currentTraits;
1250-
});
1242+
if (!this.previousUserTraits && metamaskState.participateInMetaMetrics) {
1243+
this.previousUserTraits = currentTraits;
12511244
return currentTraits;
12521245
}
12531246

1254-
if (previousUserTraits && !isEqual(previousUserTraits, currentTraits)) {
1247+
if (
1248+
this.previousUserTraits &&
1249+
!isEqual(this.previousUserTraits, currentTraits)
1250+
) {
12551251
const updates = pickBy(currentTraits, (v, k) => {
1256-
// @ts-expect-error It's okay that `k` may not be a key of `previousUserTraits`, because we assume `isEqual` can handle it
1257-
const previous = previousUserTraits[k];
1252+
// @ts-expect-error It's okay that `k` may not be a key of `this.previousUserTraits`, because we assume `isEqual` can handle it
1253+
const previous = this.previousUserTraits[k];
12581254
return !isEqual(previous, v);
12591255
});
12601256

12611257
if (metamaskState.participateInMetaMetrics) {
1262-
this.update((state) => {
1263-
state.previousUserTraits = currentTraits;
1264-
});
1258+
this.previousUserTraits = currentTraits;
12651259
}
12661260

12671261
return updates;
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { migrate, version } from './143.1';
2+
3+
const oldVersion = 143;
4+
5+
describe(`migration #${version}`, () => {
6+
it('updates the version metadata', async () => {
7+
const oldStorage = {
8+
meta: { version: oldVersion },
9+
data: {},
10+
};
11+
const newStorage = await migrate(oldStorage);
12+
expect(newStorage.meta).toStrictEqual({ version });
13+
});
14+
15+
describe(`migration #${version}`, () => {
16+
it('removes the previousUserTraits property from MetaMetricsController state and does not remove other properties', async () => {
17+
const oldStorage = {
18+
meta: { version: oldVersion },
19+
data: {
20+
MetaMetricsController: {
21+
previousUserTraits: { test: 123 },
22+
foo: 'bar',
23+
},
24+
},
25+
};
26+
const expectedData = {
27+
MetaMetricsController: {
28+
foo: 'bar',
29+
},
30+
};
31+
const newStorage = await migrate(oldStorage);
32+
33+
expect(newStorage.data).toStrictEqual(expectedData);
34+
});
35+
36+
it('has no effect if the previousUserTraits property does not exist', async () => {
37+
const oldStorage = {
38+
meta: { version: oldVersion },
39+
data: {
40+
MetaMetricsController: {
41+
foo: 'bar',
42+
},
43+
},
44+
};
45+
const expectedData = {
46+
MetaMetricsController: {
47+
foo: 'bar',
48+
},
49+
};
50+
const newStorage = await migrate(oldStorage);
51+
52+
expect(newStorage.data).toStrictEqual(expectedData);
53+
});
54+
});
55+
});

app/scripts/migrations/143.1.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { cloneDeep } from 'lodash';
2+
3+
type VersionedData = {
4+
meta: { version: number };
5+
data: Record<string, unknown>;
6+
};
7+
8+
export const version = 143.1;
9+
10+
/**
11+
* This migration deletes the `previousUserTraits` property from the MetaMetrics Controller state
12+
*
13+
* @param originalVersionedData - Versioned MetaMask extension state, exactly
14+
* what we persist to dist.
15+
* @param originalVersionedData.meta - State metadata.
16+
* @param originalVersionedData.meta.version - The current state version.
17+
* @param originalVersionedData.data - The persisted MetaMask state, keyed by
18+
* controller.
19+
* @returns Updated versioned MetaMask extension state.
20+
*/
21+
export async function migrate(
22+
originalVersionedData: VersionedData,
23+
): Promise<VersionedData> {
24+
const versionedData = cloneDeep(originalVersionedData);
25+
versionedData.meta.version = version;
26+
transformState(versionedData.data);
27+
return versionedData;
28+
}
29+
30+
function transformState(state: Record<string, unknown>) {
31+
const metaMetricsControllerState = state?.MetaMetricsController as
32+
| Record<string, unknown>
33+
| undefined;
34+
35+
delete metaMetricsControllerState?.previousUserTraits;
36+
}

app/scripts/migrations/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ const migrations = [
168168
require('./141'),
169169
require('./142'),
170170
require('./143'),
171+
require('./143.1'),
171172
require('./144'),
172173
require('./145'),
173174
require('./146'),

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "metamask-crx",
3-
"version": "12.14.0",
3+
"version": "12.14.1",
44
"private": true,
55
"repository": {
66
"type": "git",

privacy-snapshot.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,6 @@
8383
"unresponsive-rpc.url",
8484
"user-storage.api.cx.metamask.io",
8585
"verify.walletconnect.com",
86-
"www.4byte.directory"
86+
"www.4byte.directory",
87+
"api.web3modal.org"
8788
]

test/e2e/tests/bridge/bridge-test-utils.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { SMART_CONTRACTS } from '../../seeder/smart-contracts';
1010
import { CHAIN_IDS } from '../../../../shared/constants/network';
1111
import { Driver } from '../../webdriver/driver';
1212
import type { FeatureFlagResponse } from '../../../../shared/types/bridge';
13+
import { emptyHtmlPage } from '../../mock-e2e';
1314
import {
1415
DEFAULT_FEATURE_FLAGS_RESPONSE,
1516
ETH_CONVERSION_RATE_USD,
@@ -63,7 +64,7 @@ export class BridgePage {
6364
};
6465

6566
verifyPortfolioTab = async () => {
66-
await this.driver.switchToWindowWithTitle('MetaMask Portfolio - Bridge');
67+
await this.driver.switchToWindowWithTitle('E2E Test Page');
6768
await this.driver.waitForUrlContaining({
6869
url: 'portfolio.metamask.io/bridge',
6970
});
@@ -102,16 +103,15 @@ const mockServer =
102103
};
103104
}),
104105
);
105-
const portfolioMock = async () =>
106-
await mockServer_
107-
.forGet('https://portfolio.metamask.io/bridge')
108-
.always()
109-
.thenCallback(() => {
110-
return {
111-
statusCode: 200,
112-
json: {},
113-
};
114-
});
106+
const portfolioMock = mockServer_
107+
.forGet(`https://portfolio.metamask.io/bridge`)
108+
.always()
109+
.thenCallback(() => {
110+
return {
111+
statusCode: 200,
112+
body: emptyHtmlPage(),
113+
};
114+
});
115115
return Promise.all([...featureFlagMocks, portfolioMock]);
116116
};
117117

0 commit comments

Comments
 (0)