OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.chrome.browser.ntp; | 5 package org.chromium.chrome.browser.ntp; |
6 | 6 |
7 import android.app.AlarmManager; | 7 import android.app.AlarmManager; |
8 import android.app.Notification; | 8 import android.app.Notification; |
9 import android.app.NotificationManager; | 9 import android.app.NotificationManager; |
10 import android.app.PendingIntent; | 10 import android.app.PendingIntent; |
(...skipping 12 matching lines...) Expand all Loading... | |
23 import org.chromium.chrome.R; | 23 import org.chromium.chrome.R; |
24 import org.chromium.chrome.browser.ChromeFeatureList; | 24 import org.chromium.chrome.browser.ChromeFeatureList; |
25 import org.chromium.chrome.browser.IntentHandler; | 25 import org.chromium.chrome.browser.IntentHandler; |
26 import org.chromium.chrome.browser.ShortcutHelper; | 26 import org.chromium.chrome.browser.ShortcutHelper; |
27 import org.chromium.chrome.browser.document.ChromeLauncherActivity; | 27 import org.chromium.chrome.browser.document.ChromeLauncherActivity; |
28 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder; | 28 import org.chromium.chrome.browser.notifications.ChromeNotificationBuilder; |
29 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; | 29 import org.chromium.chrome.browser.notifications.NotificationBuilderFactory; |
30 import org.chromium.chrome.browser.notifications.NotificationConstants; | 30 import org.chromium.chrome.browser.notifications.NotificationConstants; |
31 import org.chromium.chrome.browser.notifications.NotificationUmaTracker; | 31 import org.chromium.chrome.browser.notifications.NotificationUmaTracker; |
32 import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsNotificationAc tion; | 32 import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsNotificationAc tion; |
33 import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsNotificationAc tion.ContentSuggestionsNotificationActionEnum; | |
34 import org.chromium.chrome.browser.ntp.snippets.ContentSuggestionsNotificationOp tOut.ContentSuggestionsNotificationOptOutEnum; | |
33 import org.chromium.chrome.browser.preferences.ContentSuggestionsPreferences; | 35 import org.chromium.chrome.browser.preferences.ContentSuggestionsPreferences; |
34 import org.chromium.chrome.browser.preferences.PreferencesLauncher; | |
35 | 36 |
36 import java.util.Collection; | 37 import java.util.Collection; |
37 import java.util.Collections; | 38 import java.util.Collections; |
38 import java.util.HashSet; | 39 import java.util.HashSet; |
39 import java.util.Set; | 40 import java.util.Set; |
40 | 41 |
41 /** | 42 /** |
42 * Provides functionality needed for content suggestion notifications. | 43 * Provides functionality needed for content suggestion notifications. |
43 * | 44 * |
44 * Exposes helper functions to native C++ code. | 45 * Exposes helper functions to native C++ code. |
(...skipping 21 matching lines...) Expand all Loading... | |
66 "ntp.content_suggestions.notification.cached_action_hide_shutdown"; | 67 "ntp.content_suggestions.notification.cached_action_hide_shutdown"; |
67 private static final String PREF_CACHED_CONSECUTIVE_IGNORED = | 68 private static final String PREF_CACHED_CONSECUTIVE_IGNORED = |
68 "ntp.content_suggestions.notification.cached_consecutive_ignored"; | 69 "ntp.content_suggestions.notification.cached_consecutive_ignored"; |
69 | 70 |
70 // Tracks which URIs there is an active notification for. | 71 // Tracks which URIs there is an active notification for. |
71 private static final String PREF_ACTIVE_NOTIFICATIONS = | 72 private static final String PREF_ACTIVE_NOTIFICATIONS = |
72 "ntp.content_suggestions.notification.active"; | 73 "ntp.content_suggestions.notification.active"; |
73 | 74 |
74 private ContentSuggestionsNotificationHelper() {} // Prevent instantiation | 75 private ContentSuggestionsNotificationHelper() {} // Prevent instantiation |
75 | 76 |
77 public static void recordNotificationOptOut( | |
78 @ContentSuggestionsNotificationOptOutEnum int reason) { | |
79 nativeRecordNotificationOptOut(reason); | |
80 } | |
81 public static void recordNotificationAction( | |
Michael van Ouwerkerk
2017/04/05 15:47:31
nit: empty line between methods, and docs for publ
dgn
2017/04/05 16:53:54
Done.
| |
82 @ContentSuggestionsNotificationActionEnum int action) { | |
83 nativeRecordNotificationAction(action); | |
84 } | |
85 | |
76 /** | 86 /** |
77 * Opens the content suggestion when notification is tapped. | 87 * Opens the content suggestion when notification is tapped. |
78 */ | 88 */ |
79 public static final class OpenUrlReceiver extends BroadcastReceiver { | 89 public static final class OpenUrlReceiver extends BroadcastReceiver { |
80 @Override | 90 @Override |
81 public void onReceive(Context context, Intent intent) { | 91 public void onReceive(Context context, Intent intent) { |
82 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); | 92 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); |
83 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); | 93 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); |
84 openUrl(intent.getData()); | 94 openUrl(intent.getData()); |
85 recordCachedActionMetric(ContentSuggestionsNotificationAction.CONTEN T_SUGGESTIONS_TAP); | 95 recordCachedActionMetric(ContentSuggestionsNotificationAction.TAP); |
86 removeActiveNotification(category, idWithinCategory); | 96 removeActiveNotification(category, idWithinCategory); |
87 } | 97 } |
88 } | 98 } |
89 | 99 |
90 /** | 100 /** |
91 * Records dismissal when notification is swiped away. | 101 * Records dismissal when notification is swiped away. |
92 */ | 102 */ |
93 public static final class DeleteReceiver extends BroadcastReceiver { | 103 public static final class DeleteReceiver extends BroadcastReceiver { |
94 @Override | 104 @Override |
95 public void onReceive(Context context, Intent intent) { | 105 public void onReceive(Context context, Intent intent) { |
96 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); | 106 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); |
97 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); | 107 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); |
98 recordCachedActionMetric( | 108 recordCachedActionMetric(ContentSuggestionsNotificationAction.DISMIS SAL); |
99 ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_DIS MISSAL); | |
100 removeActiveNotification(category, idWithinCategory); | 109 removeActiveNotification(category, idWithinCategory); |
101 } | 110 } |
102 } | 111 } |
103 | 112 |
104 /** | 113 /** |
105 * Removes the notification after a timeout period. | 114 * Removes the notification after a timeout period. |
106 */ | 115 */ |
107 public static final class TimeoutReceiver extends BroadcastReceiver { | 116 public static final class TimeoutReceiver extends BroadcastReceiver { |
108 @Override | 117 @Override |
109 public void onReceive(Context context, Intent intent) { | 118 public void onReceive(Context context, Intent intent) { |
110 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); | 119 int category = intent.getIntExtra(NOTIFICATION_CATEGORY_EXTRA, -1); |
111 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); | 120 String idWithinCategory = intent.getStringExtra(NOTIFICATION_ID_WITH IN_CATEGORY_EXTRA); |
112 if (findActiveNotification(category, idWithinCategory) == null) { | 121 if (findActiveNotification(category, idWithinCategory) == null) { |
113 return; // tapped or swiped | 122 return; // tapped or swiped |
114 } | 123 } |
115 | 124 |
116 hideNotification(category, idWithinCategory, | 125 hideNotification( |
117 ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HID E_DEADLINE); | 126 category, idWithinCategory, ContentSuggestionsNotificationAc tion.HIDE_DEADLINE); |
118 } | 127 } |
119 } | 128 } |
120 | 129 |
121 private static void openUrl(Uri uri) { | 130 private static void openUrl(Uri uri) { |
122 Context context = ContextUtils.getApplicationContext(); | 131 Context context = ContextUtils.getApplicationContext(); |
123 Intent intent = new Intent() | 132 Intent intent = new Intent() |
124 .setAction(Intent.ACTION_VIEW) | 133 .setAction(Intent.ACTION_VIEW) |
125 .setData(uri) | 134 .setData(uri) |
126 .setClass(context, ChromeLauncherActivity.class) | 135 .setClass(context, ChromeLauncherActivity.class) |
127 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) | 136 .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
166 .setContentIntent(contentIntent) | 175 .setContentIntent(contentIntent) |
167 .setDeleteIntent(deleteIntent) | 176 .setDeleteIntent(deleteIntent) |
168 .setContentTitle(title) | 177 .setContentTitle(title) |
169 .setContentText(text) | 178 .setContentText(text) |
170 .setGroup(NOTIFICATION_TAG) | 179 .setGroup(NOTIFICATION_TAG) |
171 .setPriority(priority) | 180 .setPriority(priority) |
172 .setLargeIcon(image) | 181 .setLargeIcon(image) |
173 .setSmallIcon(R.drawable.ic_chrome); | 182 .setSmallIcon(R.drawable.ic_chrome); |
174 if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_SE TTINGS)) { | 183 if (ChromeFeatureList.isEnabled(ChromeFeatureList.CONTENT_SUGGESTIONS_SE TTINGS)) { |
175 PendingIntent settingsIntent = PendingIntent.getActivity(context, 0, | 184 PendingIntent settingsIntent = PendingIntent.getActivity(context, 0, |
176 PreferencesLauncher.createIntentForSettingsPage( | 185 ContentSuggestionsPreferences.createLaunchIntent( |
177 context, ContentSuggestionsPreferences.class.getName ()), | 186 context, ContentSuggestionsPreferences.LAUNCH_SOURCE _NOTIFICATION), |
178 0); | 187 0); |
179 builder.addAction(R.drawable.settings_cog, context.getString(R.strin g.preferences), | 188 builder.addAction(R.drawable.settings_cog, context.getString(R.strin g.preferences), |
180 settingsIntent); | 189 settingsIntent); |
181 } | 190 } |
182 if (priority >= 0) { | 191 if (priority >= 0) { |
183 builder.setDefaults(Notification.DEFAULT_ALL); | 192 builder.setDefaults(Notification.DEFAULT_ALL); |
184 } | 193 } |
185 manager.notify(NOTIFICATION_TAG, nextId, builder.build()); | 194 manager.notify(NOTIFICATION_TAG, nextId, builder.build()); |
186 NotificationUmaTracker.getInstance().onNotificationShown( | 195 NotificationUmaTracker.getInstance().onNotificationShown( |
187 NotificationUmaTracker.CONTENT_SUGGESTION); | 196 NotificationUmaTracker.CONTENT_SUGGESTION); |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
342 Uri notificationUri = Uri.parse(serialized); | 351 Uri notificationUri = Uri.parse(serialized); |
343 ActiveNotification activeNotification = ActiveNotification.fromUri(n otificationUri); | 352 ActiveNotification activeNotification = ActiveNotification.fromUri(n otificationUri); |
344 if ((activeNotification != null) && (activeNotification.mId >= nextI d)) { | 353 if ((activeNotification != null) && (activeNotification.mId >= nextI d)) { |
345 nextId = activeNotification.mId + 1; | 354 nextId = activeNotification.mId + 1; |
346 } | 355 } |
347 } | 356 } |
348 return nextId; | 357 return nextId; |
349 } | 358 } |
350 | 359 |
351 private static String cachedMetricNameForAction( | 360 private static String cachedMetricNameForAction( |
352 @ContentSuggestionsNotificationAction.ContentSuggestionsNotification ActionEnum | 361 @ContentSuggestionsNotificationActionEnum int action) { |
353 int action) { | |
354 switch (action) { | 362 switch (action) { |
355 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_TAP: | 363 case ContentSuggestionsNotificationAction.TAP: |
356 return PREF_CACHED_ACTION_TAP; | 364 return PREF_CACHED_ACTION_TAP; |
357 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_DISMIS SAL: | 365 case ContentSuggestionsNotificationAction.DISMISSAL: |
358 return PREF_CACHED_ACTION_DISMISSAL; | 366 return PREF_CACHED_ACTION_DISMISSAL; |
359 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_D EADLINE: | 367 case ContentSuggestionsNotificationAction.HIDE_DEADLINE: |
360 return PREF_CACHED_ACTION_HIDE_DEADLINE; | 368 return PREF_CACHED_ACTION_HIDE_DEADLINE; |
361 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_E XPIRY: | 369 case ContentSuggestionsNotificationAction.HIDE_EXPIRY: |
362 return PREF_CACHED_ACTION_HIDE_EXPIRY; | 370 return PREF_CACHED_ACTION_HIDE_EXPIRY; |
363 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_F RONTMOST: | 371 case ContentSuggestionsNotificationAction.HIDE_FRONTMOST: |
364 return PREF_CACHED_ACTION_HIDE_FRONTMOST; | 372 return PREF_CACHED_ACTION_HIDE_FRONTMOST; |
365 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_D ISABLED: | 373 case ContentSuggestionsNotificationAction.HIDE_DISABLED: |
366 return PREF_CACHED_ACTION_HIDE_DISABLED; | 374 return PREF_CACHED_ACTION_HIDE_DISABLED; |
367 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_S HUTDOWN: | 375 case ContentSuggestionsNotificationAction.HIDE_SHUTDOWN: |
368 return PREF_CACHED_ACTION_HIDE_SHUTDOWN; | 376 return PREF_CACHED_ACTION_HIDE_SHUTDOWN; |
369 } | 377 } |
370 return ""; | 378 return ""; |
371 } | 379 } |
372 | 380 |
373 /** | 381 /** |
374 * Records that an action was performed on a notification. | 382 * Records that an action was performed on a notification. |
375 * | 383 * |
376 * Also tracks the number of consecutively-ignored notifications, resetting it on a tap or | 384 * Also tracks the number of consecutively-ignored notifications, resetting it on a tap or |
377 * otherwise incrementing it. | 385 * otherwise incrementing it. |
378 * | 386 * |
379 * This method may be called when the native library is not loaded. If it is loaded, the metrics | 387 * This method may be called when the native library is not loaded. If it is loaded, the metrics |
380 * will immediately be sent to C++. If not, it will cache them for a later c all to | 388 * will immediately be sent to C++. If not, it will cache them for a later c all to |
381 * flushCachedMetrics(). | 389 * flushCachedMetrics(). |
382 * | 390 * |
383 * @param action The action to update the pref for. | 391 * @param action The action to update the pref for. |
384 */ | 392 */ |
385 private static void recordCachedActionMetric( | 393 private static void recordCachedActionMetric( |
386 @ContentSuggestionsNotificationAction.ContentSuggestionsNotification ActionEnum | 394 @ContentSuggestionsNotificationActionEnum int action) { |
387 int action) { | |
388 String prefName = cachedMetricNameForAction(action); | 395 String prefName = cachedMetricNameForAction(action); |
389 assert !prefName.isEmpty(); | 396 assert !prefName.isEmpty(); |
390 | 397 |
391 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); | 398 SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); |
392 int currentValue = prefs.getInt(prefName, 0); | 399 int currentValue = prefs.getInt(prefName, 0); |
393 | 400 |
394 int consecutiveIgnored = prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0 ); | 401 int consecutiveIgnored = prefs.getInt(PREF_CACHED_CONSECUTIVE_IGNORED, 0 ); |
395 switch (action) { | 402 switch (action) { |
396 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_TAP: | 403 case ContentSuggestionsNotificationAction.TAP: |
397 consecutiveIgnored = 0; | 404 consecutiveIgnored = 0; |
398 break; | 405 break; |
399 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_DISMIS SAL: | 406 case ContentSuggestionsNotificationAction.DISMISSAL: |
400 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_D EADLINE: | 407 case ContentSuggestionsNotificationAction.HIDE_DEADLINE: |
401 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_E XPIRY: | 408 case ContentSuggestionsNotificationAction.HIDE_EXPIRY: |
402 ++consecutiveIgnored; | 409 ++consecutiveIgnored; |
403 break; | 410 break; |
404 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_F RONTMOST: | 411 case ContentSuggestionsNotificationAction.HIDE_FRONTMOST: |
405 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_D ISABLED: | 412 case ContentSuggestionsNotificationAction.HIDE_DISABLED: |
406 case ContentSuggestionsNotificationAction.CONTENT_SUGGESTIONS_HIDE_S HUTDOWN: | 413 case ContentSuggestionsNotificationAction.HIDE_SHUTDOWN: |
407 break; // no change | 414 break; // no change |
408 } | 415 } |
409 | 416 |
410 prefs.edit() | 417 prefs.edit() |
411 .putInt(prefName, currentValue + 1) | 418 .putInt(prefName, currentValue + 1) |
412 .putInt(PREF_CACHED_CONSECUTIVE_IGNORED, consecutiveIgnored) | 419 .putInt(PREF_CACHED_CONSECUTIVE_IGNORED, consecutiveIgnored) |
413 .apply(); | 420 .apply(); |
414 | 421 |
415 if (LibraryLoader.isInitialized()) { | 422 if (LibraryLoader.isInitialized()) { |
416 flushCachedMetrics(); | 423 flushCachedMetrics(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
450 .remove(PREF_CACHED_ACTION_HIDE_DISABLED) | 457 .remove(PREF_CACHED_ACTION_HIDE_DISABLED) |
451 .remove(PREF_CACHED_ACTION_HIDE_SHUTDOWN) | 458 .remove(PREF_CACHED_ACTION_HIDE_SHUTDOWN) |
452 .remove(PREF_CACHED_CONSECUTIVE_IGNORED) | 459 .remove(PREF_CACHED_CONSECUTIVE_IGNORED) |
453 .apply(); | 460 .apply(); |
454 } | 461 } |
455 } | 462 } |
456 | 463 |
457 private static native void nativeReceiveFlushedMetrics(int tapCount, int dis missalCount, | 464 private static native void nativeReceiveFlushedMetrics(int tapCount, int dis missalCount, |
458 int hideDeadlineCount, int hideExpiryCount, int hideFrontmostCount, | 465 int hideDeadlineCount, int hideExpiryCount, int hideFrontmostCount, |
459 int hideDisabledCount, int hideShutdownCount, int consecutiveIgnored ); | 466 int hideDisabledCount, int hideShutdownCount, int consecutiveIgnored ); |
467 private static native void nativeRecordNotificationOptOut( | |
468 @ContentSuggestionsNotificationOptOutEnum int reason); | |
469 private static native void nativeRecordNotificationAction( | |
470 @ContentSuggestionsNotificationActionEnum int action); | |
460 } | 471 } |
OLD | NEW |