| Index: chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUIManager.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUIManager.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUIManager.java
|
| deleted file mode 100644
|
| index 7d61b3b69cf65cb46bd96448a5bd4c5979594622..0000000000000000000000000000000000000000
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationUIManager.java
|
| +++ /dev/null
|
| @@ -1,695 +0,0 @@
|
| -// 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.Build;
|
| -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.VisibleForTesting;
|
| -import org.chromium.base.annotations.CalledByNative;
|
| -import org.chromium.base.library_loader.ProcessInitException;
|
| -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.init.ChromeBrowserInitializer;
|
| -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 NotificationPlatformBridge.");
|
| - }
|
| -
|
| - 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) {
|
| - // This method handles an intent fired by the Android system. There is no guarantee that the
|
| - // native library is loaded at this point. The native library is needed for the preferences
|
| - // activity, and it loads the library, but there are some native calls even before that
|
| - // activity is started: from RecordUserAction.record and (indirectly) from
|
| - // UrlUtilities.formatUrlForSecurityDisplay.
|
| - try {
|
| - ChromeBrowserInitializer.getInstance(context).handleSynchronousStartup();
|
| - } catch (ProcessInitException e) {
|
| - Log.e(TAG, "Failed to start browser process.", e);
|
| - // The library failed to initialize and nothing in the application can work, so kill
|
| - // the whole application.
|
| - System.exit(-1);
|
| - return;
|
| - }
|
| -
|
| - // Use the application context because it lives longer. When using the 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.
|
| - */
|
| - @VisibleForTesting
|
| - 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 badge An image to represent the notification in the status bar. It is also displayed
|
| - * inside the notification.
|
| - * @param vibrationPattern Vibration pattern following the Web Vibration syntax.
|
| - * @param timestamp The timestamp of the event for which the notification is being shown.
|
| - * @param renotify Whether the sound, vibration, and lights should be replayed if the
|
| - * notification is replacing another notification.
|
| - * @param silent Whether the default sound, vibration and lights should be suppressed.
|
| - * @param actionTitles Titles of actions to display alongside the notification.
|
| - * @param actionIcons Icons 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, Bitmap badge,
|
| - int[] vibrationPattern, long timestamp, boolean renotify, boolean silent,
|
| - String[] actionTitles, Bitmap[] actionIcons) {
|
| - if (actionTitles.length != actionIcons.length) {
|
| - throw new IllegalArgumentException("The number of action titles and icons must match.");
|
| - }
|
| -
|
| - 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)
|
| - .setSmallIcon(badge)
|
| - .setContentIntent(clickIntent)
|
| - .setDeleteIntent(closeIntent)
|
| - .setTicker(createTickerText(title, body))
|
| - .setTimestamp(timestamp)
|
| - .setRenotify(renotify)
|
| - .setOrigin(UrlUtilities.formatUrlForSecurityDisplay(
|
| - origin, false /* showScheme */));
|
| -
|
| - for (int actionIndex = 0; actionIndex < actionTitles.length; actionIndex++) {
|
| - notificationBuilder.addAction(actionIcons[actionIndex], 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.
|
| - *
|
| - * @return Whether custom layouts should be used.
|
| - */
|
| - @VisibleForTesting
|
| - static boolean useCustomLayouts() {
|
| - CommandLine commandLine = CommandLine.getInstance();
|
| - if (commandLine.hasSwitch(ChromeSwitches.ENABLE_WEB_NOTIFICATION_CUSTOM_LAYOUTS)) {
|
| - return true;
|
| - }
|
| - if (commandLine.hasSwitch(ChromeSwitches.DISABLE_WEB_NOTIFICATION_CUSTOM_LAYOUTS)) {
|
| - return false;
|
| - }
|
| - if (Build.VERSION.CODENAME.equals("N")) {
|
| - return false;
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - /**
|
| - * 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 profileId of the profile whose notification this is for.
|
| - * @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(
|
| - String profileId, long persistentNotificationId, String origin, String tag) {
|
| - // TODO(miguelg) make profile_id part of the 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);
|
| -}
|
|
|