// Copyright 2014 The Chromium Authors. All rights reserved.
// 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.notifications;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.os.StrictMode;
import android.os.SystemClock;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.Log;

import org.chromium.base.CommandLine;
import org.chromium.base.FieldTrialList;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.preferences.Preferences;
import org.chromium.chrome.browser.preferences.PreferencesLauncher;
import org.chromium.chrome.browser.preferences.website.SingleCategoryPreferences;
import org.chromium.chrome.browser.preferences.website.SingleWebsitePreferences;
import org.chromium.chrome.browser.preferences.website.SiteSettingsCategory;
import org.chromium.chrome.browser.util.UrlUtilities;
import org.chromium.chrome.browser.widget.RoundedIconGenerator;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;

import javax.annotation.Nullable;

/**
 * Provides the ability for the NotificationUIManagerAndroid to talk to the Android platform
 * notification manager.
 *
 * This class should only be used on the UI thread.
 */
public class NotificationUIManager {
    private static final String TAG = NotificationUIManager.class.getSimpleName();

    // We always use the same integer id when showing and closing notifications. The notification
    // tag is always set, which is a safe and sufficient way of identifying a notification, so the
    // integer id is not needed anymore except it must not vary in an uncontrolled way.
    @VisibleForTesting static final int PLATFORM_ID = -1;

    // Prefix for platform tags generated by this class. This allows us to verify when reading a tag
    // that it was set by us.
    private static final String PLATFORM_TAG_PREFIX = NotificationUIManager.class.getSimpleName();

    private static final int NOTIFICATION_ICON_BG_COLOR = 0xFF969696;
    private static final int NOTIFICATION_TEXT_SIZE_DP = 28;

    // We always use the same request code for pending intents. We use other ways to force
    // uniqueness of pending intents when necessary.
    private static final int PENDING_INTENT_REQUEST_CODE = 0;

    private static NotificationUIManager sInstance;
    private static NotificationManagerProxy sNotificationManagerOverride;

    private final long mNativeNotificationManager;

    private final Context mAppContext;
    private final NotificationManagerProxy mNotificationManager;

    @VisibleForTesting public RoundedIconGenerator mIconGenerator;
    private final int mLargeIconWidthPx;
    private final int mLargeIconHeightPx;
    private final float mDensity;

    private long mLastNotificationClickMs = 0L;

    /**
     * Creates a new instance of the NotificationUIManager.
     *
     * @param nativeNotificationManager Instance of the NotificationUIManagerAndroid class.
     * @param context Application context for this instance of Chrome.
     */
    @CalledByNative
    private static NotificationUIManager create(long nativeNotificationManager, Context context) {
        if (sInstance != null) {
            throw new IllegalStateException("There must only be a single NotificationUIManager.");
        }

        sInstance = new NotificationUIManager(nativeNotificationManager, context);
        return sInstance;
    }

    /**
     * Returns the current instance of the NotificationUIManager.
     *
     * @return The instance of the NotificationUIManager, if any.
     */
    @Nullable
    @VisibleForTesting
    static NotificationUIManager getInstanceForTests() {
        return sInstance;
    }

    /**
     * Overrides the notification manager which is to be used for displaying Notifications on the
     * Android framework. Should only be used for testing. Tests are expected to clean up after
     * themselves by setting this to NULL again.
     *
     * @param proxy The notification manager instance to use instead of the system's.
     */
    @VisibleForTesting
    public static void overrideNotificationManagerForTesting(
            NotificationManagerProxy notificationManager) {
        sNotificationManagerOverride = notificationManager;
    }

    private NotificationUIManager(long nativeNotificationManager, Context context) {
        mNativeNotificationManager = nativeNotificationManager;
        mAppContext = context.getApplicationContext();

        if (sNotificationManagerOverride != null) {
            mNotificationManager = sNotificationManagerOverride;
        } else {
            mNotificationManager = new NotificationManagerProxyImpl(
                    (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE));
        }

        Resources resources = mAppContext.getResources();

        mLargeIconWidthPx =
                resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_width);
        mLargeIconHeightPx =
                resources.getDimensionPixelSize(android.R.dimen.notification_large_icon_height);
        mDensity = resources.getDisplayMetrics().density;
    }

    /**
     * Marks the current instance as being freed, allowing for a new NotificationUIManager
     * object to be initialized.
     */
    @CalledByNative
    private void destroy() {
        assert sInstance == this;
        sInstance = null;
    }

    /**
     * Invoked by the NotificationService when a Notification intent has been received. There may
     * not be an active instance of the NotificationUIManager at this time, so inform the native
     * side through a static method, initializing the manager if needed.
     *
     * @param intent The intent as received by the Notification service.
     * @return Whether the event could be handled by the native Notification manager.
     */
    public static boolean dispatchNotificationEvent(Intent intent) {
        if (sInstance == null) {
            nativeInitializeNotificationUIManager();
            if (sInstance == null) {
                Log.e(TAG, "Unable to initialize the native NotificationUIManager.");
                return false;
            }
        }

        long persistentNotificationId =
                intent.getLongExtra(NotificationConstants.EXTRA_PERSISTENT_NOTIFICATION_ID, -1);
        String origin = intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN);
        String profileId =
                intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID);
        boolean incognito = intent.getBooleanExtra(
                NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, false);
        String tag = intent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG);

        Log.i(TAG, "Dispatching notification event to native: " + persistentNotificationId);

        if (NotificationConstants.ACTION_CLICK_NOTIFICATION.equals(intent.getAction())) {
            int actionIndex = intent.getIntExtra(
                    NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, -1);
            sInstance.onNotificationClicked(
                    persistentNotificationId, origin, profileId, incognito, tag, actionIndex);
            return true;
        } else if (NotificationConstants.ACTION_CLOSE_NOTIFICATION.equals(intent.getAction())) {
            // Notification deleteIntent is executed only "when the notification is explicitly
            // dismissed by the user, either with the 'Clear All' button or by swiping it away
            // individually" (though a third-party NotificationListenerService may also trigger it).
            sInstance.onNotificationClosed(
                    persistentNotificationId, origin, profileId, incognito, tag, true /* byUser */);
            return true;
        }

        Log.e(TAG, "Unrecognized Notification action: " + intent.getAction());
        return false;
    }

    /**
     * Launches the notifications preferences screen. If the received intent indicates it came
     * from the gear button on a flipped notification, this launches the site specific preferences
     * screen.
     *
     * @param context The context that received the intent.
     * @param incomingIntent The received intent.
     */
    public static void launchNotificationPreferences(Context context, Intent incomingIntent) {
        // Use the application context because it lives longer. When using he given context, it
        // may be stopped before the preferences intent is handled.
        Context applicationContext = context.getApplicationContext();

        // If we can read an origin from the intent, use it to open the settings screen for that
        // origin.
        String origin = getOriginFromTag(
                incomingIntent.getStringExtra(NotificationConstants.EXTRA_NOTIFICATION_TAG));
        boolean launchSingleWebsitePreferences = origin != null;

        String fragmentName = launchSingleWebsitePreferences
                ? SingleWebsitePreferences.class.getName()
                : SingleCategoryPreferences.class.getName();
        Intent preferencesIntent =
                PreferencesLauncher.createIntentForSettingsPage(applicationContext, fragmentName);

        Bundle fragmentArguments;
        if (launchSingleWebsitePreferences) {
            // Record that the user has clicked on the [Site Settings] button.
            RecordUserAction.record("Notifications.ShowSiteSettings");

            // All preferences for a specific origin.
            fragmentArguments = SingleWebsitePreferences.createFragmentArgsForSite(origin);
        } else {
            // Notification preferences for all origins.
            fragmentArguments = new Bundle();
            fragmentArguments.putString(SingleCategoryPreferences.EXTRA_CATEGORY,
                    SiteSettingsCategory.CATEGORY_NOTIFICATIONS);
            fragmentArguments.putString(SingleCategoryPreferences.EXTRA_TITLE,
                    applicationContext.getResources().getString(
                            R.string.push_notifications_permission_title));
        }
        preferencesIntent.putExtra(Preferences.EXTRA_SHOW_FRAGMENT_ARGUMENTS, fragmentArguments);

        // We need to ensure that no existing preference tasks are being re-used in order for the
        // new activity to appear on top.
        preferencesIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);

        applicationContext.startActivity(preferencesIntent);
    }

    /**
     * Returns a bogus Uri used to make each intent unique according to Intent#filterEquals.
     * Without this, the pending intents derived from the intent may be reused, because extras are
     * not taken into account for the filterEquals comparison.
     *
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin The origin to whom the notification belongs.
     * @param actionIndex The zero-based index of the action button, or -1 if not applicable.
     */
    private Uri makeIntentData(long persistentNotificationId, String origin, int actionIndex) {
        return Uri.parse(origin).buildUpon().fragment(
                persistentNotificationId + "," + actionIndex).build();
    }

    /**
     * Returns the PendingIntent for completing |action| on the notification identified by the data
     * in the other parameters.
     *
     * @param action The action this pending intent will represent.
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin The origin to whom the notification belongs.
     * @param tag The tag of the notification. May be NULL.
     * @param actionIndex The zero-based index of the action button, or -1 if not applicable.
     */
    private PendingIntent makePendingIntent(String action, long persistentNotificationId,
            String origin, String profileId, boolean incognito, @Nullable String tag,
            int actionIndex) {
        Uri intentData = makeIntentData(persistentNotificationId, origin, actionIndex);
        Intent intent = new Intent(action, intentData);
        intent.setClass(mAppContext, NotificationService.Receiver.class);

        intent.putExtra(NotificationConstants.EXTRA_PERSISTENT_NOTIFICATION_ID,
                persistentNotificationId);
        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, origin);
        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID, profileId);
        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_INCOGNITO, incognito);
        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG, tag);
        intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_INDEX, actionIndex);

        return PendingIntent.getBroadcast(mAppContext, PENDING_INTENT_REQUEST_CODE, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);
    }

    /**
     * Generates the tag to be passed to the notification manager.
     *
     * If the generated tag is the same as that of a previous notification, a new notification shown
     * with this tag will replace it.
     *
     * If the input tag is not empty the output is: PREFIX + SEPARATOR + ORIGIN + SEPARATOR + TAG.
     * This output will be the same for notifications from the same origin that have the same input
     * tag.
     *
     * If the input tag is empty the output is PREFIX + SEPARATOR + ORIGIN + SEPARATOR +
     * NOTIFICATION_ID.
     *
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin The origin for which the notification is shown.
     * @param tag A string identifier for this notification.
     * @return The generated platform tag.
     */
    private static String makePlatformTag(long persistentNotificationId, String origin,
                                          @Nullable String tag) {
        // The given tag may contain the separator character, so add it last to make reading the
        // preceding origin token reliable. If no tag was specified (it is the default empty
        // string), make the platform tag unique by appending the notification id.
        StringBuilder builder = new StringBuilder();
        builder.append(PLATFORM_TAG_PREFIX)
                .append(NotificationConstants.NOTIFICATION_TAG_SEPARATOR)
                .append(origin)
                .append(NotificationConstants.NOTIFICATION_TAG_SEPARATOR);

        if (TextUtils.isEmpty(tag)) {
            builder.append(persistentNotificationId);
        } else {
            builder.append(tag);
        }

        return builder.toString();
    }

    /**
     * Attempts to extract an origin from the tag extra in the given intent.
     *
     * See {@link #makePlatformTag} for details about the format of the tag.
     *
     * @param tag The tag from the intent extra. May be null.
     * @return The origin string. Returns null if there was no tag extra in the given intent, or if
     *         the tag value did not match the expected format.
     */
    @Nullable
    @VisibleForTesting
    static String getOriginFromTag(@Nullable String tag) {
        // If the user touched the settings cog on a flipped notification originating from this
        // class, there will be a notification tag extra in a specific format. From the tag we can
        // read the origin of the notification.
        if (tag == null || !tag.startsWith(PLATFORM_TAG_PREFIX)) return null;

        String[] parts = tag.split(NotificationConstants.NOTIFICATION_TAG_SEPARATOR);
        assert parts.length >= 3;
        try {
            URI uri = new URI(parts[1]);
            if (uri.getHost() != null) return parts[1];
        } catch (URISyntaxException e) {
            Log.e(TAG, "Expected to find a valid url in the notification tag extra.", e);
            return null;
        }
        return null;
    }

    /**
     * Generates the notfiication defaults from vibrationPattern's size and silent.
     *
     * Use the system's default ringtone, vibration and indicator lights unless the notification
     * has been marked as being silent.
     * If a vibration pattern is set, the notification should use the provided pattern
     * rather than the defaulting to system settings.
     *
     * @param vibrationPatternLength Vibration pattern's size for the Notification.
     * @param silent Whether the default sound, vibration and lights should be suppressed.
     * @return The generated notification's default value.
    */
    @VisibleForTesting
    static int makeDefaults(int vibrationPatternLength, boolean silent) {
        assert !silent || vibrationPatternLength == 0;

        if (silent) return 0;

        int defaults = Notification.DEFAULT_ALL;
        if (vibrationPatternLength > 0) {
            defaults &= ~Notification.DEFAULT_VIBRATE;
        }
        return defaults;
    }

    /**
     * Generates the vibration pattern used in Android notification.
     *
     * Android takes a long array where the first entry indicates the number of milliseconds to wait
     * prior to starting the vibration, whereas Chrome follows the syntax of the Web Vibration API.
     *
     * @param vibrationPattern Vibration pattern following the Web Vibration API syntax.
     * @return Vibration pattern following the Android syntax.
    */
    @VisibleForTesting
    static long[] makeVibrationPattern(int[] vibrationPattern) {
        long[] pattern = new long[vibrationPattern.length + 1];
        for (int i = 0; i < vibrationPattern.length; ++i) {
            pattern[i + 1] = vibrationPattern[i];
        }
        return pattern;
    }

    /**
     * Displays a notification with the given details.
     *
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin Full text of the origin, including the protocol, owning this notification.
     * @param profileId Id of the profile that showed the notification.
     * @param incognito if the session of the profile is an off the record one.
     * @param tag A string identifier for this notification. If the tag is not empty, the new
     *            notification will replace the previous notification with the same tag and origin,
     *            if present. If no matching previous notification is present, the new one will just
     *            be added.
     * @param title Title to be displayed in the notification.
     * @param body Message to be displayed in the notification. Will be trimmed to one line of
     *             text by the Android notification system.
     * @param icon Icon to be displayed in the notification. Valid Bitmap icons will be scaled to
     *             the platforms, whereas a default icon will be generated for invalid Bitmaps.
     * @param vibrationPattern Vibration pattern following the Web Vibration syntax.
     * @param timestamp The timestamp of the event for which the notification is being shown.
     * @param silent Whether the default sound, vibration and lights should be suppressed.
     * @param actionTitles Titles of actions to display alongside the notification.
     * @see https://developer.android.com/reference/android/app/Notification.html
     */
    @CalledByNative
    private void displayNotification(long persistentNotificationId, String origin, String profileId,
            boolean incognito, String tag, String title, String body, Bitmap icon,
            int[] vibrationPattern, long timestamp, boolean silent, String[] actionTitles) {
        Resources res = mAppContext.getResources();

        // Record whether it's known whether notifications can be shown to the user at all.
        RecordHistogram.recordEnumeratedHistogram(
                "Notifications.AppNotificationStatus",
                NotificationSystemStatusUtil.determineAppNotificationStatus(mAppContext),
                NotificationSystemStatusUtil.APP_NOTIFICATIONS_STATUS_BOUNDARY);

        // Set up a pending intent for going to the settings screen for |origin|.
        Intent settingsIntent = PreferencesLauncher.createIntentForSettingsPage(
                mAppContext, SingleWebsitePreferences.class.getName());
        settingsIntent.setData(
                makeIntentData(persistentNotificationId, origin, -1 /* actionIndex */));
        settingsIntent.putExtra(Preferences.EXTRA_SHOW_FRAGMENT_ARGUMENTS,
                SingleWebsitePreferences.createFragmentArgsForSite(origin));

        PendingIntent pendingSettingsIntent = PendingIntent.getActivity(mAppContext,
                PENDING_INTENT_REQUEST_CODE, settingsIntent, PendingIntent.FLAG_UPDATE_CURRENT);

        PendingIntent clickIntent = makePendingIntent(
                NotificationConstants.ACTION_CLICK_NOTIFICATION, persistentNotificationId, origin,
                profileId, incognito, tag, -1 /* actionIndex */);
        PendingIntent closeIntent = makePendingIntent(
                NotificationConstants.ACTION_CLOSE_NOTIFICATION, persistentNotificationId, origin,
                profileId, incognito, tag, -1 /* actionIndex */);

        NotificationBuilderBase notificationBuilder =
                createNotificationBuilder()
                        .setTitle(title)
                        .setBody(body)
                        .setLargeIcon(ensureNormalizedIcon(icon, origin))
                        .setSmallIcon(R.drawable.ic_chrome)
                        .setContentIntent(clickIntent)
                        .setDeleteIntent(closeIntent)
                        .setTicker(createTickerText(title, body))
                        .setTimestamp(timestamp)
                        .setOrigin(UrlUtilities.formatUrlForSecurityDisplay(
                                origin, false /* showScheme */));

        for (int actionIndex = 0; actionIndex < actionTitles.length; actionIndex++) {
            notificationBuilder.addAction(0 /* actionIcon */, actionTitles[actionIndex],
                    makePendingIntent(NotificationConstants.ACTION_CLICK_NOTIFICATION,
                                                  persistentNotificationId, origin, profileId,
                                                  incognito, tag, actionIndex));
        }

        // If action buttons are displayed, there isn't room for the full Site Settings button
        // label and icon, so abbreviate it. This has the unfortunate side-effect of unnecessarily
        // abbreviating it on Android Wear also (crbug.com/576656). If custom layouts are enabled,
        // the label and icon provided here only affect Android Wear, so don't abbreviate them.
        boolean abbreviateSiteSettings = actionTitles.length > 0 && !useCustomLayouts();
        int settingsIconId = abbreviateSiteSettings ? 0 : R.drawable.settings_cog;
        CharSequence settingsTitle = abbreviateSiteSettings
                                     ? res.getString(R.string.notification_site_settings_button)
                                     : res.getString(R.string.page_info_site_settings_button);
        // If the settings button is displayed together with the other buttons it has to be the last
        // one, so add it after the other actions.
        notificationBuilder.addSettingsAction(settingsIconId, settingsTitle, pendingSettingsIntent);

        notificationBuilder.setDefaults(makeDefaults(vibrationPattern.length, silent));
        if (vibrationPattern.length > 0) {
            notificationBuilder.setVibrate(makeVibrationPattern(vibrationPattern));
        }

        String platformTag = makePlatformTag(persistentNotificationId, origin, tag);
        // Temporarily allowing disk access. TODO: Fix. See http://crbug.com/577185
        StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
        StrictMode.allowThreadDiskWrites();
        try {
            long time = SystemClock.elapsedRealtime();
            mNotificationManager.notify(platformTag, PLATFORM_ID, notificationBuilder.build());
            RecordHistogram.recordTimesHistogram("Android.StrictMode.NotificationUIBuildTime",
                    SystemClock.elapsedRealtime() - time, TimeUnit.MILLISECONDS);
        } finally {
            StrictMode.setThreadPolicy(oldPolicy);
        }
    }

    private NotificationBuilderBase createNotificationBuilder() {
        if (useCustomLayouts()) {
            return new CustomNotificationBuilder(mAppContext);
        }
        return new StandardNotificationBuilder(mAppContext);
    }

    /**
     * Creates the ticker text for a notification having |title| and |body|. The notification's
     * title will be printed in bold, followed by the text of the body.
     *
     * @param title Title of the notification.
     * @param body Textual contents of the notification.
     * @return A character sequence containing the ticker's text.
     */
    private CharSequence createTickerText(String title, String body) {
        SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();

        spannableStringBuilder.append(title);
        spannableStringBuilder.append("\n");
        spannableStringBuilder.append(body);

        // Mark the title of the notification as being bold.
        spannableStringBuilder.setSpan(new StyleSpan(android.graphics.Typeface.BOLD),
                0, title.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

        return spannableStringBuilder;
    }

    /**
     * Ensures the availability of an icon for the notification.
     *
     * If |icon| is a valid, non-empty Bitmap, the bitmap will be scaled to be of an appropriate
     * size for the current Android device. Otherwise, a default icon will be created based on the
     * origin the notification is being displayed for.
     *
     * @param icon The developer-provided icon they intend to use for the notification.
     * @param origin The origin the notification is being displayed for.
     * @return An appropriately sized icon to use for the notification.
     */
    @VisibleForTesting
    public Bitmap ensureNormalizedIcon(Bitmap icon, String origin) {
        if (icon == null || icon.getWidth() == 0) {
            if (mIconGenerator == null) {
                int cornerRadiusPx = Math.min(mLargeIconWidthPx, mLargeIconHeightPx) / 2;
                mIconGenerator =
                        new RoundedIconGenerator(mLargeIconWidthPx, mLargeIconHeightPx,
                                                 cornerRadiusPx,
                                                 NOTIFICATION_ICON_BG_COLOR,
                                                 NOTIFICATION_TEXT_SIZE_DP * mDensity);
            }

            return mIconGenerator.generateIconForUrl(origin, true);
        }

        if (icon.getWidth() > mLargeIconWidthPx || icon.getHeight() > mLargeIconHeightPx) {
            return icon.createScaledBitmap(icon, mLargeIconWidthPx, mLargeIconHeightPx,
                                           false /* not filtered */);
        }

        return icon;
    }

    /**
     * Determines whether to use standard notification layouts, using NotificationCompat.Builder,
     * or custom layouts using Chrome's own templates.
     *
     * The --{enable,disable}-web-notification-custom-layouts
     * command line flags take precedence over a running Finch trial.
     *
     * @return Whether custom layouts should be used.
     */
    @VisibleForTesting
    static boolean useCustomLayouts() {
        // Query the field trial state first to ensure correct UMA reporting.
        String groupName = FieldTrialList.findFullName("WebNotificationCustomLayouts");
        CommandLine commandLine = CommandLine.getInstance();
        if (commandLine.hasSwitch(ChromeSwitches.DISABLE_WEB_NOTIFICATION_CUSTOM_LAYOUTS)) {
            return false;
        }
        if (commandLine.hasSwitch(ChromeSwitches.ENABLE_WEB_NOTIFICATION_CUSTOM_LAYOUTS)) {
            return true;
        }
        return !groupName.equals("Disabled");
    }

    /**
     * Returns whether a notification has been clicked in the last 5 seconds.
     * Used for Startup.BringToForegroundReason UMA histogram.
     */
    public static boolean wasNotificationRecentlyClicked() {
        if (sInstance == null) return false;
        long now = System.currentTimeMillis();
        return now - sInstance.mLastNotificationClickMs < 5 * 1000;
    }

    /**
     * Closes the notification associated with the given parameters.
     *
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin The origin to which the notification belongs.
     * @param tag The tag of the notification. May be NULL.
     */
    @CalledByNative
    private void closeNotification(long persistentNotificationId, String origin, String tag) {
        String platformTag = makePlatformTag(persistentNotificationId, origin, tag);
        mNotificationManager.cancel(platformTag, PLATFORM_ID);
    }

    /**
     * Calls NotificationUIManagerAndroid::OnNotificationClicked in native code to indicate that
     * the notification with the given parameters has been clicked on.
     *
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin The origin of the notification.
     * @param profileId Id of the profile that showed the notification.
     * @param incognito if the profile session was an off the record one.
     * @param tag The tag of the notification. May be NULL.
     */
    private void onNotificationClicked(long persistentNotificationId, String origin,
            String profileId, boolean incognito, String tag, int actionIndex) {
        mLastNotificationClickMs = System.currentTimeMillis();
        nativeOnNotificationClicked(mNativeNotificationManager, persistentNotificationId, origin,
                profileId, incognito, tag, actionIndex);
    }

    /**
     * Calls NotificationUIManagerAndroid::OnNotificationClosed in native code to indicate that
     * the notification with the given parameters has been closed.
     *
     * @param persistentNotificationId The persistent id of the notification.
     * @param origin The origin of the notification.
     * @param profileId Id of the profile that showed the notification.
     * @param incognito if the profile session was an off the record one.
     * @param tag The tag of the notification. May be NULL.
     * @param byUser Whether the notification was closed by a user gesture.
     */
    private void onNotificationClosed(long persistentNotificationId, String origin,
            String profileId, boolean incognito, String tag, boolean byUser) {
        nativeOnNotificationClosed(mNativeNotificationManager, persistentNotificationId, origin,
                profileId, incognito, tag, byUser);
    }

    private static native void nativeInitializeNotificationUIManager();

    private native void nativeOnNotificationClicked(long nativeNotificationUIManagerAndroid,
            long persistentNotificationId, String origin, String profileId, boolean incognito,
            String tag, int actionIndex);
    private native void nativeOnNotificationClosed(long nativeNotificationUIManagerAndroid,
            long persistentNotificationId, String origin, String profileId, boolean incognito,
            String tag, boolean byUser);
}
