1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 09:57:02 +01:00
metamask-extension/app/scripts/lib/setup-initial-state-hooks.js
Mark Stacey 9cfa9ba6b0
Fix pre-initialization UI error state capture (#20529)
In the case where an error is thrown in the UI before initialization
has finished, we aren't capturing the application state correctly for
Sentry errors. We had a test case for this, but the test case was
broken due to a mistake in how the `network-store` was setup (it was
not matching the behavior of the real `local-tstore` module).

The pre-initialization state capture logic was updated to rely solely
upon the `localStore` instance used by Sentry to determine whether the
user had opted-in to metrics or not. This simplifies the logic a great
deal, removing the need for the `getMostRecentPersistedState` state
hook. It also ensures that state is captured corretly pre-
initialization in both the background and UI.
2023-08-18 16:32:28 -02:30

69 lines
2.1 KiB
JavaScript

import { maskObject } from '../../../shared/modules/object.utils';
import ExtensionPlatform from '../platforms/extension';
import LocalStore from './local-store';
import ReadOnlyNetworkStore from './network-store';
import { SENTRY_BACKGROUND_STATE } from './setupSentry';
const platform = new ExtensionPlatform();
// This instance of `localStore` is used by Sentry to get the persisted state
const sentryLocalStore = process.env.IN_TEST
? new ReadOnlyNetworkStore()
: new LocalStore();
/**
* Get the persisted wallet state.
*
* @returns The persisted wallet state.
*/
globalThis.stateHooks.getPersistedState = async function () {
return await sentryLocalStore.get();
};
const persistedStateMask = {
data: SENTRY_BACKGROUND_STATE,
meta: {
version: true,
},
};
/**
* Get a state snapshot to include with Sentry error reports. This uses the
* persisted state pre-initialization, and the in-memory state post-
* initialization. In both cases the state is anonymized.
*
* @returns A Sentry state snapshot.
*/
globalThis.stateHooks.getSentryState = function () {
const sentryState = {
browser: window.navigator.userAgent,
version: platform.getVersion(),
};
// If `getSentryAppState` is set, it implies that initialization has completed
if (globalThis.stateHooks.getSentryAppState) {
return {
...sentryState,
state: globalThis.stateHooks.getSentryAppState(),
};
} else if (
// This is truthy if Sentry has retrieved state at least once already. This
// should always be true because Sentry calls `getPersistedState` during
// error processing (before this function is called) if `getSentryAppState`
// hasn't been set yet.
sentryLocalStore.mostRecentRetrievedState
) {
return {
...sentryState,
persistedState: maskObject(
sentryLocalStore.mostRecentRetrievedState,
persistedStateMask,
),
};
}
// This branch means that local storage has not yet been read, so we have
// no choice but to omit the application state.
// This should be unreachable, unless an error was encountered during error
// processing.
return sentryState;
};