Add native browser notification support for Snaps (#13613)

* Initial native notification implementation

* Simplify implementation

* Implementation based on RateLimitController

* Update controllers package

* Add notification to permission list

* Wire up correctly

* Remove snap_notify from the exclusion list
feature/default_network_editable
Frederik Bolding 3 years ago committed by GitHub
parent 9626793233
commit 8b9b9af13f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      app/_locales/en/messages.json
  2. 32
      app/scripts/metamask-controller.js
  3. 3
      shared/constants/permissions.js
  4. 5
      ui/helpers/utils/permission.js

@ -2362,6 +2362,10 @@
"message": "Store and manage its data on your device.",
"description": "The description for the `snap_manageState` permission"
},
"permission_notifications": {
"message": "Show notifications.",
"description": "The description for the `snap_notify` permission"
},
"permission_unknown": {
"message": "Unknown permission: $1",
"description": "$1 is the name of a requested permission that is not recognized."

@ -40,6 +40,9 @@ import {
CollectibleDetectionController,
PermissionController,
SubjectMetadataController,
///: BEGIN:ONLY_INCLUDE_IN(flask)
RateLimitController,
///: END:ONLY_INCLUDE_IN
} from '@metamask/controllers';
import SmartTransactionsController from '@metamask/smart-transactions-controller';
///: BEGIN:ONLY_INCLUDE_IN(flask)
@ -634,6 +637,27 @@ export default class MetamaskController extends EventEmitter {
state: initState.SnapController,
messenger: snapControllerMessenger,
});
this.rateLimitController = new RateLimitController({
messenger: this.controllerMessenger.getRestricted({
name: 'RateLimitController',
}),
implementations: {
showNativeNotification: (origin, message) => {
const subjectMetadataState = this.controllerMessenger.call(
'SubjectMetadataController:getState',
);
const originMetadata = subjectMetadataState.subjectMetadata[origin];
this.platform._showNotification(
originMetadata?.name ?? origin,
message,
);
return null;
},
},
});
///: END:ONLY_INCLUDE_IN
this.detectTokensController = new DetectTokensController({
@ -1036,6 +1060,14 @@ export default class MetamaskController extends EventEmitter {
type: MESSAGE_TYPE.SNAP_CONFIRM,
requestData: confirmationData,
}),
showNotification: (origin, args) =>
this.controllerMessenger.call(
'RateLimitController:call',
origin,
'showNativeNotification',
origin,
args.message,
),
updateSnapState: this.controllerMessenger.call.bind(
this.controllerMessenger,
'SnapController:updateSnapState',

@ -6,6 +6,7 @@ export const RestrictedMethods = Object.freeze({
eth_accounts: 'eth_accounts',
///: BEGIN:ONLY_INCLUDE_IN(flask)
snap_confirm: 'snap_confirm',
snap_notify: 'snap_notify',
snap_manageState: 'snap_manageState',
'snap_getBip44Entropy_*': 'snap_getBip44Entropy_*',
'wallet_snap_*': 'wallet_snap_*',
@ -23,5 +24,5 @@ export const EndowmentPermissions = Object.freeze({
});
// Methods / permissions in external packages that we are temporarily excluding.
export const ExcludedSnapPermissions = new Set(['snap_notify']);
export const ExcludedSnapPermissions = new Set([]);
///: END:ONLY_INCLUDE_IN

@ -24,6 +24,11 @@ const PERMISSION_DESCRIPTIONS = deepFreeze({
leftIcon: 'fas fa-user-check',
rightIcon: null,
},
[RestrictedMethods.snap_notify]: {
leftIcon: 'fas fa-bell',
label: (t) => t('permission_notifications'),
rightIcon: null,
},
[RestrictedMethods['snap_getBip44Entropy_*']]: {
label: (t, permissionName) => {
const coinType = permissionName.split('_').slice(-1);

Loading…
Cancel
Save