| Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
|
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
|
| index 337a3a997a905b558711614896dae30c57f4c9ae..a149fca21d5ad3db39536bae3edcf76d8bef53c3 100644
|
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
|
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/ContentSuggestionsNotificationHelper.java
|
| @@ -11,6 +11,7 @@ import android.app.PendingIntent;
|
| import android.content.BroadcastReceiver;
|
| import android.content.Context;
|
| import android.content.Intent;
|
| +import android.content.SharedPreferences;
|
| import android.graphics.Bitmap;
|
| import android.net.Uri;
|
| import android.os.Build;
|
| @@ -20,6 +21,8 @@ import android.support.v4.app.NotificationCompat;
|
|
|
| import org.chromium.base.ContextUtils;
|
| import org.chromium.base.annotations.CalledByNative;
|
| +import org.chromium.base.annotations.JNINamespace;
|
| +import org.chromium.base.library_loader.LibraryLoader;
|
| import org.chromium.chrome.R;
|
| import org.chromium.chrome.browser.IntentHandler;
|
| import org.chromium.chrome.browser.ShortcutHelper;
|
| @@ -30,13 +33,42 @@ import org.chromium.chrome.browser.document.ChromeLauncherActivity;
|
| *
|
| * Exposes helper functions to native C++ code.
|
| */
|
| +@JNINamespace("ntp_snippets")
|
| public class ContentSuggestionsNotificationHelper {
|
| private static final String NOTIFICATION_TAG = "ContentSuggestionsNotification";
|
| private static final String NOTIFICATION_ID_EXTRA = "notification_id";
|
|
|
| + private static final String PREF_CACHED_ACTION_TAP =
|
| + "ntp.content_suggestions.notification.cached_action_tap";
|
| + private static final String PREF_CACHED_ACTION_DISMISSAL =
|
| + "ntp.content_suggestions.notification.cached_action_dismissal";
|
| + private static final String PREF_CACHED_ACTION_HIDE_DEADLINE =
|
| + "ntp.content_suggestions.notification.cached_action_hide_deadline";
|
| + private static final String PREF_CACHED_CONSECUTIVE_IGNORED =
|
| + "ntp.content_suggestions.notification.cached_consecutive_ignored";
|
| +
|
| private ContentSuggestionsNotificationHelper() {} // Prevent instantiation
|
|
|
| /**
|
| + * Opens the content suggestion when notification is tapped.
|
| + */
|
| + public static final class OpenUrlReceiver extends BroadcastReceiver {
|
| + public void onReceive(Context context, Intent intent) {
|
| + openUrl(intent.getData());
|
| + recordCachedActionMetric(PREF_CACHED_ACTION_TAP);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Records dismissal when notification is swiped away.
|
| + */
|
| + public static final class DeleteReceiver extends BroadcastReceiver {
|
| + public void onReceive(Context context, Intent intent) {
|
| + recordCachedActionMetric(PREF_CACHED_ACTION_DISMISSAL);
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Removes the notification after a timeout period.
|
| */
|
| public static final class TimeoutReceiver extends BroadcastReceiver {
|
| @@ -44,19 +76,19 @@ public class ContentSuggestionsNotificationHelper {
|
| int id = intent.getIntExtra(NOTIFICATION_ID_EXTRA, -1);
|
| if (id < 0) return;
|
| hideNotification(id);
|
| + recordCachedActionMetric(PREF_CACHED_ACTION_HIDE_DEADLINE);
|
| }
|
| }
|
|
|
| - @CalledByNative
|
| - private static void openUrl(String url) {
|
| + private static void openUrl(Uri uri) {
|
| Context context = ContextUtils.getApplicationContext();
|
| - Intent intent = new Intent();
|
| - intent.setAction(Intent.ACTION_VIEW);
|
| - intent.setData(Uri.parse(url));
|
| - intent.setClass(context, ChromeLauncherActivity.class);
|
| - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
| - intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
| - intent.putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true);
|
| + Intent intent = new Intent()
|
| + .setAction(Intent.ACTION_VIEW)
|
| + .setData(uri)
|
| + .setClass(context, ChromeLauncherActivity.class)
|
| + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
| + .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName())
|
| + .putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true);
|
| IntentHandler.addTrustedIntentExtras(intent);
|
| context.startActivity(intent);
|
| }
|
| @@ -81,16 +113,13 @@ public class ContentSuggestionsNotificationHelper {
|
| }
|
| }
|
|
|
| - Intent intent = new Intent()
|
| - .setAction(Intent.ACTION_VIEW)
|
| - .setData(Uri.parse(url))
|
| - .setClass(context, ChromeLauncherActivity.class)
|
| - .putExtra(ShortcutHelper.REUSE_URL_MATCHING_TAB_ELSE_NEW_TAB, true)
|
| - .putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
|
| + Intent contentIntent = new Intent(context, OpenUrlReceiver.class).setData(Uri.parse(url));
|
| + Intent deleteIntent = new Intent(context, DeleteReceiver.class).setData(Uri.parse(url));
|
| NotificationCompat.Builder builder =
|
| new NotificationCompat.Builder(context)
|
| .setAutoCancel(true)
|
| - .setContentIntent(PendingIntent.getActivity(context, 0, intent, 0))
|
| + .setContentIntent(PendingIntent.getBroadcast(context, 0, contentIntent, 0))
|
| + .setDeleteIntent(PendingIntent.getBroadcast(context, 0, deleteIntent, 0))
|
| .setContentTitle(title)
|
| .setContentText(text)
|
| .setGroup(NOTIFICATION_TAG)
|
| @@ -134,4 +163,65 @@ public class ContentSuggestionsNotificationHelper {
|
| manager.cancel(NOTIFICATION_TAG, 0);
|
| }
|
| }
|
| +
|
| + /**
|
| + * Records that an action was performed on a notification.
|
| + *
|
| + * Also tracks the number of consecutively-ignored notifications, resetting it on a tap or
|
| + * otherwise incrementing it.
|
| + *
|
| + * This method may be called when the native library is not loaded. If it is loaded, the metrics
|
| + * will immediately be sent to C++. If not, it will cache them for a later call to
|
| + * flushCachedMetrics().
|
| + *
|
| + * @param prefName The name of the action metric pref to update (<tt>PREF_CACHED_ACTION_*</tt>)
|
| + */
|
| + private static void recordCachedActionMetric(String prefName) {
|
| + assert prefName.startsWith("ntp.content_suggestions.notification.cached_action_");
|
| +
|
| + SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
|
| + int currentValue = prefs.getInt(prefName, 0);
|
| + int consecutiveIgnored = 0;
|
| + if (!prefName.equals(PREF_CACHED_ACTION_TAP)) {
|
| + consecutiveIgnored = 1 + prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0);
|
| + }
|
| + prefs.edit()
|
| + .putInt(prefName, currentValue + 1)
|
| + .putInt(PREF_CACHED_CONSECUTIVE_IGNORED, consecutiveIgnored)
|
| + .apply();
|
| +
|
| + if (LibraryLoader.isInitialized()) {
|
| + flushCachedMetrics();
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Invokes nativeReceiveFlushedMetrics() with cached metrics and resets them.
|
| + *
|
| + * It may be called from either native or Java code, as long as the native libray is loaded.
|
| + */
|
| + @CalledByNative
|
| + private static void flushCachedMetrics() {
|
| + assert LibraryLoader.isInitialized();
|
| +
|
| + SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
|
| + int tapCount = prefs.getInt(PREF_CACHED_ACTION_TAP, 0);
|
| + int dismissalCount = prefs.getInt(PREF_CACHED_ACTION_DISMISSAL, 0);
|
| + int hideDeadlineCount = prefs.getInt(PREF_CACHED_ACTION_HIDE_DEADLINE, 0);
|
| + int consecutiveIgnored = prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0);
|
| +
|
| + if (tapCount > 0 || dismissalCount > 0 || hideDeadlineCount > 0) {
|
| + nativeReceiveFlushedMetrics(tapCount, dismissalCount, hideDeadlineCount,
|
| + consecutiveIgnored);
|
| + prefs.edit()
|
| + .remove(PREF_CACHED_ACTION_TAP)
|
| + .remove(PREF_CACHED_ACTION_DISMISSAL)
|
| + .remove(PREF_CACHED_ACTION_HIDE_DEADLINE)
|
| + .remove(PREF_CACHED_CONSECUTIVE_IGNORED)
|
| + .apply();
|
| + }
|
| + }
|
| +
|
| + private static native void nativeReceiveFlushedMetrics(
|
| + int tapCount, int dismissalCount, int hideDeadlineCount, int consecutiveIgnored);
|
| }
|
|
|