chromium/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingNotificationUtil.java

// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package org.chromium.chrome.browser.sharing;

import android.app.Notification;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;

import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationCompat;

import org.chromium.base.ContextUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType;
import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
import org.chromium.components.browser_ui.notifications.BaseNotificationManagerProxyFactory;
import org.chromium.components.browser_ui.notifications.NotificationMetadata;
import org.chromium.components.browser_ui.notifications.NotificationWrapper;
import org.chromium.components.browser_ui.notifications.NotificationWrapperBuilder;
import org.chromium.components.browser_ui.notifications.PendingIntentProvider;

/** Provides common functionality for handling sharing notifications. */
public final class SharingNotificationUtil {
    /**
     * Shows a notification with a configuration common to all sharing notifications.
     *
     * @param type The type of notification.
     * @param group The notification group.
     * @param id The notification id.
     * @param contentIntent The notification content intent.
     * @param deleteIntent The notification delete intent.
     * @param confirmIntent The notification confirm intent.
     * @param cancelIntent The notification cancel intent.
     * @param contentTitle The notification title text.
     * @param contentText The notification content text.
     * @param largeIconId The large notification icon resource id, 0 if not used.
     * @param color The color to be used for the notification.
     * @param startsActivity Whether the {@code contentIntent} starts an Activity.
     */
    public static void showNotification(
            @SystemNotificationType int type,
            String group,
            int id,
            PendingIntentProvider contentIntent,
            PendingIntentProvider deleteIntent,
            PendingIntentProvider confirmIntent,
            PendingIntentProvider cancelIntent,
            String contentTitle,
            String contentText,
            @DrawableRes int smallIconId,
            @DrawableRes int largeIconId,
            int color,
            boolean startsActivity) {
        Context context = ContextUtils.getApplicationContext();
        Resources resources = context.getResources();
        NotificationWrapperBuilder builder =
                NotificationWrapperBuilderFactory.createNotificationWrapperBuilder(
                                ChromeChannelDefinitions.ChannelId.SHARING,
                                new NotificationMetadata(type, group, id))
                        .setContentTitle(contentTitle)
                        .setContentText(contentText)
                        .setBigTextStyle(contentText)
                        .setColor(context.getColor(color))
                        .setGroup(group)
                        .setPriorityBeforeO(NotificationCompat.PRIORITY_HIGH)
                        .setSmallIcon(smallIconId)
                        .setAutoCancel(true)
                        .setDefaults(Notification.DEFAULT_ALL);

        if (contentIntent != null) {
            if (startsActivity && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                // We can't use the NotificationIntentInterceptor to start Activities starting in
                // Android S. Use the unmodified PendingIntent directly instead.
                builder.setContentIntent(contentIntent.getPendingIntent());
            } else {
                builder.setContentIntent(contentIntent);
            }
        }
        if (deleteIntent != null) {
            builder.setDeleteIntent(deleteIntent);
        }
        if (confirmIntent != null) {
            builder.addAction(
                    R.drawable.ic_checkmark_24dp,
                    resources.getString(R.string.submit),
                    confirmIntent,
                    NotificationUmaTracker.ActionType.SHARING_CONFIRM);
        }
        if (cancelIntent != null) {
            builder.addAction(
                    R.drawable.ic_cancel_circle,
                    resources.getString(R.string.cancel),
                    cancelIntent,
                    NotificationUmaTracker.ActionType.SHARING_CANCEL);
        }

        if (largeIconId != 0) {
            Bitmap largeIcon = BitmapFactory.decodeResource(resources, largeIconId);
            if (largeIcon != null) builder.setLargeIcon(largeIcon);
        }
        NotificationWrapper notification = builder.buildNotificationWrapper();

        BaseNotificationManagerProxyFactory.create(context).notify(notification);
        NotificationUmaTracker.getInstance()
                .onNotificationShown(type, notification.getNotification());
    }

    public static void dismissNotification(String tag, int notificationId) {
        Context context = ContextUtils.getApplicationContext();
        BaseNotificationManagerProxyFactory.create(context).cancel(tag, notificationId);
    }

    /**
     * Shows a notification for sending outgoing Sharing messages.
     *
     * @param type The type of notification.
     * @param group The notification group.
     * @param id The notification id.
     * @param targetName The name of target device
     */
    public static void showSendingNotification(
            @SystemNotificationType int type, String group, int id, String targetName) {
        Context context = ContextUtils.getApplicationContext();
        Resources resources = context.getResources();
        String contentTitle =
                resources.getString(R.string.sharing_sending_notification_title, targetName);
        NotificationWrapperBuilder builder =
                NotificationWrapperBuilderFactory.createNotificationWrapperBuilder(
                                ChromeChannelDefinitions.ChannelId.SHARING,
                                new NotificationMetadata(type, group, id))
                        .setContentTitle(contentTitle)
                        .setGroup(group)
                        .setColor(context.getColor(R.color.default_icon_color_accent1_baseline))
                        .setPriorityBeforeO(NotificationCompat.PRIORITY_HIGH)
                        .setSmallIcon(R.drawable.ic_devices_16dp)
                        .setProgress(/* max= */ 0, /* percentage= */ 0, true)
                        .setOngoing(true)
                        .setDefaults(Notification.DEFAULT_ALL);
        NotificationWrapper notification = builder.buildNotificationWrapper();

        BaseNotificationManagerProxyFactory.create(context).notify(notification);
        NotificationUmaTracker.getInstance()
                .onNotificationShown(type, notification.getNotification());
    }

    /**
     * Shows a notification for displaying error after sending outgoing Sharing message.
     *
     * @param type The type of notification.
     * @param group The notification group.
     * @param id The notification id.
     * @param contentTitle The title of the notification.
     * @param contentText The text shown in the notification.
     * @param tryAgainIntent PendingIntent to try sharing to same device again.
     */
    public static void showSendErrorNotification(
            @SystemNotificationType int type,
            String group,
            int id,
            String contentTitle,
            String contentText,
            @Nullable PendingIntentProvider tryAgainIntent) {
        Context context = ContextUtils.getApplicationContext();
        Resources resources = context.getResources();
        NotificationWrapperBuilder builder =
                NotificationWrapperBuilderFactory.createNotificationWrapperBuilder(
                                ChromeChannelDefinitions.ChannelId.SHARING,
                                new NotificationMetadata(type, group, id))
                        .setContentTitle(contentTitle)
                        .setGroup(group)
                        .setColor(context.getColor(R.color.google_red_600))
                        .setPriorityBeforeO(NotificationCompat.PRIORITY_HIGH)
                        .setSmallIcon(R.drawable.ic_error_outline_red_24dp)
                        .setContentText(contentText)
                        .setDefaults(Notification.DEFAULT_ALL)
                        .setAutoCancel(true);

        if (tryAgainIntent != null) {
            builder.setContentIntent(tryAgainIntent)
                    .addAction(
                            R.drawable.ic_cancel_circle,
                            resources.getString(R.string.try_again),
                            tryAgainIntent,
                            NotificationUmaTracker.ActionType.SHARING_TRY_AGAIN);
        }

        NotificationWrapper notification = builder.buildWithBigTextStyle(contentText);

        BaseNotificationManagerProxyFactory.create(context).notify(notification);
        NotificationUmaTracker.getInstance()
                .onNotificationShown(type, notification.getNotification());
    }

    private SharingNotificationUtil() {}
}