diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index d771c5319..55a50803e 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -18,6 +18,9 @@ import { TRAITS, } from '../../../shared/constants/metametrics'; import { SECOND } from '../../../shared/constants/time'; +import { isManifestV3 } from '../../../shared/modules/mv3.utils'; +import { METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM } from '../../../shared/constants/alarms'; +import { checkAlarmExists } from '../lib/util'; const EXTENSION_UNINSTALL_URL = 'https://metamask.io/uninstalled'; @@ -144,16 +147,49 @@ export default class MetaMetricsController { // within the fragment's timeout window. When creating a new event fragment // a timeout can be specified that will cause an abandoned event to be // tracked if the event isn't progressed within that amount of time. - setInterval(() => { - Object.values(this.store.getState().fragments).forEach((fragment) => { - if ( - fragment.timeout && - Date.now() - fragment.lastUpdated / 1000 > fragment.timeout - ) { - this.finalizeEventFragment(fragment.id, { abandoned: true }); + if (isManifestV3) { + /* eslint-disable no-undef */ + chrome.alarms.getAll((alarms) => { + const hasAlarm = checkAlarmExists( + alarms, + METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, + ); + + if (!hasAlarm) { + chrome.alarms.create(METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, { + delayInMinutes: 1, + periodInMinutes: 1, + }); } }); - }, SECOND * 30); + chrome.alarms.onAlarm.addListener(() => { + chrome.alarms.getAll((alarms) => { + const hasAlarm = checkAlarmExists( + alarms, + METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM, + ); + + if (hasAlarm) { + this.finalizeAbandonedFragments(); + } + }); + }); + } else { + setInterval(() => { + this.finalizeAbandonedFragments(); + }, SECOND * 30); + } + } + + finalizeAbandonedFragments() { + Object.values(this.store.getState().fragments).forEach((fragment) => { + if ( + fragment.timeout && + Date.now() - fragment.lastUpdated / 1000 > fragment.timeout + ) { + this.finalizeEventFragment(fragment.id, { abandoned: true }); + } + }); } generateMetaMetricsId() { diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 2d454d4b5..6539e1f23 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -152,6 +152,17 @@ function getChainType(chainId) { return 'custom'; } +/** + * Checks if the alarmname exists in the list + * + * @param {Array} alarmList + * @param alarmName + * @returns + */ +function checkAlarmExists(alarmList, alarmName) { + return alarmList.some((alarm) => alarm.name === alarmName); +} + export { getPlatform, getEnvironmentType, @@ -161,4 +172,5 @@ export { addHexPrefix, bnToHex, getChainType, + checkAlarmExists, }; diff --git a/shared/constants/alarms.js b/shared/constants/alarms.js index c0dbbcf7e..730fdd826 100644 --- a/shared/constants/alarms.js +++ b/shared/constants/alarms.js @@ -1 +1,3 @@ export const AUTO_LOCK_TIMEOUT_ALARM = 'AUTO_LOCK_TIMEOUT_ALARM'; +export const METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM = + 'METAMETRICS_FINALIZE_EVENT_FRAGMENT_ALARM';