| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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.notifications; | 5 package org.chromium.chrome.browser.notifications; |
| 6 | 6 |
| 7 import android.app.Notification; | 7 import android.app.Notification; |
| 8 import android.app.NotificationManager; | 8 import android.app.NotificationManager; |
| 9 import android.app.PendingIntent; | 9 import android.app.PendingIntent; |
| 10 import android.content.Context; | 10 import android.content.Context; |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 * @param persistentNotificationId The persistent id of the notification. | 298 * @param persistentNotificationId The persistent id of the notification. |
| 299 * @param origin The origin to whom the notification belongs. | 299 * @param origin The origin to whom the notification belongs. |
| 300 * @param actionIndex The zero-based index of the action button, or -1 if no
t applicable. | 300 * @param actionIndex The zero-based index of the action button, or -1 if no
t applicable. |
| 301 */ | 301 */ |
| 302 private Uri makeIntentData(long persistentNotificationId, String origin, int
actionIndex) { | 302 private Uri makeIntentData(long persistentNotificationId, String origin, int
actionIndex) { |
| 303 return Uri.parse(origin).buildUpon().fragment( | 303 return Uri.parse(origin).buildUpon().fragment( |
| 304 persistentNotificationId + "," + actionIndex).build(); | 304 persistentNotificationId + "," + actionIndex).build(); |
| 305 } | 305 } |
| 306 | 306 |
| 307 /** | 307 /** |
| 308 * Returns the Intent to create a PendingIntent for completing |action| on t
he notification | 308 * Returns the PendingIntent for completing |action| on the notification ide
ntified by the data |
| 309 * identified by the data in the other parameters. | 309 * in the other parameters. |
| 310 * | 310 * |
| 311 * @param action The action this pending intent will represent. | 311 * @param action The action this pending intent will represent. |
| 312 * @param persistentNotificationId The persistent id of the notification. | 312 * @param persistentNotificationId The persistent id of the notification. |
| 313 * @param origin The origin to whom the notification belongs. | 313 * @param origin The origin to whom the notification belongs. |
| 314 * @param profileId | 314 * @param profileId |
| 315 * @param incognito | 315 * @param incognito |
| 316 * @param webApkPackage The package of the WebAPK associated with the notifi
cation. | 316 * @param webApkPackage The package of the WebAPK associated with the notifi
cation. Empty if |
| 317 * Empty if the notification is not associated with a WebAPK. | 317 * the notification is not associated with a WebAPK. |
| 318 * @param tag The tag of the notification. May be NULL. | 318 * @param tag The tag of the notification. May be NULL. |
| 319 * @param actionIndex The zero-based index of the action button, or -1 if no
t applicable. | 319 * @param actionIndex The zero-based index of the action button, or -1 if no
t applicable. |
| 320 */ | 320 */ |
| 321 private Intent makeIntent(String action, long persistentNotificationId, Stri
ng origin, | 321 private PendingIntent makePendingIntent(String action, long persistentNotifi
cationId, |
| 322 String profileId, boolean incognito, @Nullable String webApkPackage, | 322 String origin, String profileId, boolean incognito, @Nullable String
webApkPackage, |
| 323 @Nullable String tag, int actionIndex) { | 323 @Nullable String tag, int actionIndex) { |
| 324 Uri intentData = makeIntentData(persistentNotificationId, origin, action
Index); | 324 Uri intentData = makeIntentData(persistentNotificationId, origin, action
Index); |
| 325 Intent intent = new Intent(action, intentData); | 325 Intent intent = new Intent(action, intentData); |
| 326 intent.setClass(mAppContext, NotificationService.Receiver.class); | 326 intent.setClass(mAppContext, NotificationService.Receiver.class); |
| 327 | 327 |
| 328 intent.putExtra(NotificationConstants.EXTRA_PERSISTENT_NOTIFICATION_ID, | 328 intent.putExtra(NotificationConstants.EXTRA_PERSISTENT_NOTIFICATION_ID, |
| 329 persistentNotificationId); | 329 persistentNotificationId); |
| 330 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, or
igin); | 330 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ORIGIN, or
igin); |
| 331 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID
, profileId); | 331 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_ID
, profileId); |
| 332 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_IN
COGNITO, incognito); | 332 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_PROFILE_IN
COGNITO, incognito); |
| 333 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG, tag); | 333 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_TAG, tag); |
| 334 intent.putExtra( | 334 intent.putExtra( |
| 335 NotificationConstants.EXTRA_NOTIFICATION_INFO_WEB_APK_PACKAGE, w
ebApkPackage); | 335 NotificationConstants.EXTRA_NOTIFICATION_INFO_WEB_APK_PACKAGE, w
ebApkPackage); |
| 336 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_IND
EX, actionIndex); | 336 intent.putExtra(NotificationConstants.EXTRA_NOTIFICATION_INFO_ACTION_IND
EX, actionIndex); |
| 337 | 337 |
| 338 return intent; | |
| 339 } | |
| 340 /** | |
| 341 * Returns the PendingIntent for completing |action| on the notification ide
ntified by the data | |
| 342 * in the other parameters. | |
| 343 * | |
| 344 * @param action The action this pending intent will represent. | |
| 345 * @param persistentNotificationId The persistent id of the notification. | |
| 346 * @param origin The origin to whom the notification belongs. | |
| 347 * @param tag The tag of the notification. May be NULL. | |
| 348 * @param actionIndex The zero-based index of the action button, or -1 if no
t applicable. | |
| 349 */ | |
| 350 private PendingIntent makePendingIntent(String action, long persistentNotifi
cationId, | |
| 351 String origin, String profileId, boolean incognito, @Nullable String
tag, | |
| 352 int actionIndex) { | |
| 353 Intent intent = makeIntent(action, persistentNotificationId, origin, pro
fileId, incognito, | |
| 354 null, tag, actionIndex); | |
| 355 | |
| 356 return PendingIntent.getBroadcast(mAppContext, PENDING_INTENT_REQUEST_CO
DE, intent, | 338 return PendingIntent.getBroadcast(mAppContext, PENDING_INTENT_REQUEST_CO
DE, intent, |
| 357 PendingIntent.FLAG_UPDATE_CURRENT); | 339 PendingIntent.FLAG_UPDATE_CURRENT); |
| 358 } | 340 } |
| 359 | 341 |
| 360 /** | 342 /** |
| 361 * Generates the tag to be passed to the notification manager. | 343 * Generates the tag to be passed to the notification manager. |
| 362 * | 344 * |
| 363 * If the generated tag is the same as that of a previous notification, a ne
w notification shown | 345 * If the generated tag is the same as that of a previous notification, a ne
w notification shown |
| 364 * with this tag will replace it. | 346 * with this tag will replace it. |
| 365 * | 347 * |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 497 */ | 479 */ |
| 498 @CalledByNative | 480 @CalledByNative |
| 499 private void displayNotification(long persistentNotificationId, String origi
n, String profileId, | 481 private void displayNotification(long persistentNotificationId, String origi
n, String profileId, |
| 500 boolean incognito, String tag, String webApkPackage, String title, S
tring body, | 482 boolean incognito, String tag, String webApkPackage, String title, S
tring body, |
| 501 Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp, b
oolean renotify, | 483 Bitmap icon, Bitmap badge, int[] vibrationPattern, long timestamp, b
oolean renotify, |
| 502 boolean silent, String[] actionTitles, Bitmap[] actionIcons) { | 484 boolean silent, String[] actionTitles, Bitmap[] actionIcons) { |
| 503 if (actionTitles.length != actionIcons.length) { | 485 if (actionTitles.length != actionIcons.length) { |
| 504 throw new IllegalArgumentException("The number of action titles and
icons must match."); | 486 throw new IllegalArgumentException("The number of action titles and
icons must match."); |
| 505 } | 487 } |
| 506 | 488 |
| 507 final NotificationBuilderBase notificationBuilder = createNotificationBu
ilder(); | 489 Resources res = mAppContext.getResources(); |
| 508 final String platformTag = makePlatformTag(persistentNotificationId, ori
gin, tag); | |
| 509 | 490 |
| 510 // Record whether it's known whether notifications can be shown to the u
ser at all. | 491 // Record whether it's known whether notifications can be shown to the u
ser at all. |
| 511 RecordHistogram.recordEnumeratedHistogram( | 492 RecordHistogram.recordEnumeratedHistogram( |
| 512 "Notifications.AppNotificationStatus", | 493 "Notifications.AppNotificationStatus", |
| 513 NotificationSystemStatusUtil.determineAppNotificationStatus(mApp
Context), | 494 NotificationSystemStatusUtil.determineAppNotificationStatus(mApp
Context), |
| 514 NotificationSystemStatusUtil.APP_NOTIFICATIONS_STATUS_BOUNDARY); | 495 NotificationSystemStatusUtil.APP_NOTIFICATIONS_STATUS_BOUNDARY); |
| 515 | 496 |
| 516 buildNotification(notificationBuilder, | 497 // Set up a pending intent for going to the settings screen for |origin|
. |
| 517 true /* hasSettings */, actionTitles != null ? actionTitles.leng
th : 0, | 498 Intent settingsIntent = PreferencesLauncher.createIntentForSettingsPage( |
| 518 persistentNotificationId, origin, profileId, incognito, tag, | 499 mAppContext, SingleWebsitePreferences.class.getName()); |
| 519 title, body, icon, badge, vibrationPattern, timestamp, renotify,
silent); | 500 settingsIntent.setData( |
| 501 makeIntentData(persistentNotificationId, origin, -1 /* actionInd
ex */)); |
| 502 settingsIntent.putExtra(Preferences.EXTRA_SHOW_FRAGMENT_ARGUMENTS, |
| 503 SingleWebsitePreferences.createFragmentArgsForSite(origin)); |
| 520 | 504 |
| 521 if (!webApkPackage.isEmpty()) { | 505 PendingIntent pendingSettingsIntent = PendingIntent.getActivity(mAppCont
ext, |
| 522 displayNotificationInWebAPK(notificationBuilder, persistentNotificat
ionId, origin, | 506 PENDING_INTENT_REQUEST_CODE, settingsIntent, PendingIntent.FLAG_
UPDATE_CURRENT); |
| 523 profileId, incognito, tag, webApkPackage, actionTitles, acti
onIcons, | |
| 524 platformTag); | |
| 525 return; | |
| 526 } else { | |
| 527 PendingIntent clickIntent = makePendingIntent( | |
| 528 NotificationConstants.ACTION_CLICK_NOTIFICATION, persistentN
otificationId, | |
| 529 origin, profileId, incognito, tag, -1 /* actionIndex */); | |
| 530 PendingIntent closeIntent = makePendingIntent( | |
| 531 NotificationConstants.ACTION_CLOSE_NOTIFICATION, persistentN
otificationId, | |
| 532 origin, profileId, incognito, tag, -1 /* actionIndex */); | |
| 533 notificationBuilder.setContentIntent(clickIntent) | |
| 534 .setDeleteIntent(closeIntent); | |
| 535 | 507 |
| 536 PendingIntent[] actionIntents = null; | 508 PendingIntent clickIntent = makePendingIntent( |
| 537 if (actionTitles.length > 0) { | 509 NotificationConstants.ACTION_CLICK_NOTIFICATION, persistentNotif
icationId, origin, |
| 538 actionIntents = new PendingIntent[actionTitles.length]; | 510 profileId, incognito, webApkPackage, tag, -1 /* actionIndex */); |
| 539 for (int actionIndex = 0; actionIndex < actionTitles.length; | 511 PendingIntent closeIntent = makePendingIntent( |
| 540 actionIndex++) { | 512 NotificationConstants.ACTION_CLOSE_NOTIFICATION, persistentNotif
icationId, |
| 541 notificationBuilder.addAction(actionIcons[actionIndex], | 513 origin, profileId, incognito, webApkPackage, tag, -1 /* actionIn
dex */); |
| 542 actionTitles[actionIndex], | |
| 543 makePendingIntent(NotificationConstants.ACTION_CLICK
_NOTIFICATION, | |
| 544 persistentNotificationId, origin, profileId, | |
| 545 incognito, tag, actionIndex)); | |
| 546 } | |
| 547 } | |
| 548 mNotificationManager.notify(platformTag, PLATFORM_ID, notificationBu
ilder.build()); | |
| 549 } | |
| 550 } | |
| 551 | 514 |
| 552 /** | 515 NotificationBuilderBase notificationBuilder = |
| 553 * Build and format a notification to display. Every fields (except PendingI
ntents) are set | 516 createNotificationBuilder() |
| 554 * to the notification builder within this function. | 517 .setTitle(title) |
| 555 */ | 518 .setBody(body) |
| 556 private void buildNotification(NotificationBuilderBase notificationBuilder, | 519 .setLargeIcon(ensureNormalizedIcon(icon, origin)) |
| 557 boolean hasSettings, int actionLength, | 520 .setSmallIcon(R.drawable.ic_chrome) |
| 558 long persistentNotificationId, String origin, String profileId, | 521 .setSmallIcon(badge) |
| 559 boolean incognito, String tag, String title, String body, Bitmap ico
n, Bitmap badge, | 522 .setContentIntent(clickIntent) |
| 560 int[] vibrationPattern, long timestamp, boolean renotify, boolean si
lent) { | 523 .setDeleteIntent(closeIntent) |
| 561 Resources res = mAppContext.getResources(); | 524 .setTicker(createTickerText(title, body)) |
| 562 PendingIntent pendingSettingsIntent = null; | 525 .setTimestamp(timestamp) |
| 563 if (hasSettings) { | 526 .setRenotify(renotify) |
| 564 // Set up a pending intent for going to the settings screen for |ori
gin|. | 527 .setOrigin(UrlUtilities.formatUrlForSecurityDisplay( |
| 565 Intent settingsIntent = PreferencesLauncher.createIntentForSettingsP
age( | 528 origin, false /* showScheme */)); |
| 566 mAppContext, SingleWebsitePreferences.class.getName()); | |
| 567 settingsIntent.setData( | |
| 568 makeIntentData(persistentNotificationId, origin, -1 /* actio
nIndex */)); | |
| 569 settingsIntent.putExtra(Preferences.EXTRA_SHOW_FRAGMENT_ARGUMENTS, | |
| 570 SingleWebsitePreferences.createFragmentArgsForSite(origin)); | |
| 571 | 529 |
| 572 pendingSettingsIntent = PendingIntent.getActivity(mAppContext, | 530 for (int actionIndex = 0; actionIndex < actionTitles.length; actionIndex
++) { |
| 573 PENDING_INTENT_REQUEST_CODE, settingsIntent, PendingIntent.F
LAG_UPDATE_CURRENT); | 531 notificationBuilder.addAction(actionIcons[actionIndex], actionTitles
[actionIndex], |
| 574 | 532 makePendingIntent(NotificationConstants.ACTION_CLICK_NOTIFIC
ATION, |
| 533 persistentNotificationId, orig
in, profileId, |
| 534 incognito, webApkPackage, tag,
actionIndex)); |
| 575 } | 535 } |
| 576 | 536 |
| 577 notificationBuilder.setTitle(title) | 537 // If action buttons are displayed, there isn't room for the full Site S
ettings button |
| 578 .setBody(body) | 538 // label and icon, so abbreviate it. This has the unfortunate side-effec
t of unnecessarily |
| 579 .setLargeIcon(ensureNormalizedIcon(icon, origin)) | 539 // abbreviating it on Android Wear also (crbug.com/576656). If custom la
youts are enabled, |
| 580 .setSmallIcon(R.drawable.ic_chrome) | 540 // the label and icon provided here only affect Android Wear, so don't a
bbreviate them. |
| 581 .setSmallIcon(badge) | 541 boolean abbreviateSiteSettings = actionTitles.length > 0 && !useCustomLa
youts(); |
| 582 .setTicker(createTickerText(title, body)) | 542 int settingsIconId = abbreviateSiteSettings ? 0 : R.drawable.settings_co
g; |
| 583 .setTimestamp(timestamp) | 543 CharSequence settingsTitle = abbreviateSiteSettings |
| 584 .setRenotify(renotify) | 544 ? res.getString(R.string.notification_site_
settings_button) |
| 585 .setOrigin(UrlUtilities.formatUrlForSecurityDisplay( | 545 : res.getString(R.string.page_info_site_set
tings_button); |
| 586 origin, false /* showScheme */)); | 546 // If the settings button is displayed together with the other buttons i
t has to be the last |
| 587 if (hasSettings) { | 547 // one, so add it after the other actions. |
| 588 // If action buttons are displayed, there isn't room for the full Si
te Settings button | 548 notificationBuilder.addSettingsAction(settingsIconId, settingsTitle, pen
dingSettingsIntent); |
| 589 // label and icon, so abbreviate it. This has the unfortunate side-e
ffect of | |
| 590 // unnecessarily abbreviating it on Android Wear also (crbug.com/576
656). | |
| 591 // If custom layouts are enabled, the label and icon provided here o
nly affect | |
| 592 // Android Wear, so don't abbreviate them. | |
| 593 boolean abbreviateSiteSettings = actionLength > 0 && !useCustomLayou
ts(); | |
| 594 int settingsIconId = abbreviateSiteSettings ? 0 : R.drawable.setting
s_cog; | |
| 595 CharSequence settingsTitle = abbreviateSiteSettings | |
| 596 ? res.getString(R.string.notification_site_settings_
button) | |
| 597 : res.getString(R.string.page_info_site_settings_but
ton); | |
| 598 // If the settings button is displayed together with the other butto
ns it has to | |
| 599 // be the last one, so add it after the other actions. | |
| 600 notificationBuilder.addSettingsAction(settingsIconId, settingsTitle, | |
| 601 pendingSettingsIntent); | |
| 602 } | |
| 603 | 549 |
| 604 notificationBuilder.setDefaults(makeDefaults(vibrationPattern.length, si
lent)); | 550 notificationBuilder.setDefaults(makeDefaults(vibrationPattern.length, si
lent)); |
| 605 if (vibrationPattern.length > 0) { | 551 if (vibrationPattern.length > 0) { |
| 606 notificationBuilder.setVibrate(makeVibrationPattern(vibrationPattern
)); | 552 notificationBuilder.setVibrate(makeVibrationPattern(vibrationPattern
)); |
| 607 } | 553 } |
| 608 } | |
| 609 | 554 |
| 610 /** | 555 String platformTag = makePlatformTag(persistentNotificationId, origin, t
ag); |
| 611 * Bind to the Service of required WebAPK, create an notification and displa
y. | 556 if (webApkPackage.isEmpty()) { |
| 612 */ | 557 mNotificationManager.notify(platformTag, PLATFORM_ID, notificationBu
ilder.build()); |
| 613 private void displayNotificationInWebAPK(NotificationBuilderBase notificatio
nBuilder, | 558 } else { |
| 614 long persistentNotificationId, String origin, String profileId, | 559 new NotificationClient().displayNotification( |
| 615 boolean incognito, String tag, String webApkPackage, String[] action
Titles, | 560 notificationBuilder, platformTag, PLATFORM_ID, webApkPackage
); |
| 616 Bitmap[] actionIcons, String platformTag) { | |
| 617 Intent clickIntent = makeIntent(NotificationConstants.ACTION_CLICK_NOTIF
ICATION, | |
| 618 persistentNotificationId, origin, | |
| 619 profileId, incognito, webApkPackage, tag, -1 /* actionIndex */); | |
| 620 Intent closeIntent = makeIntent(NotificationConstants.ACTION_CLOSE_NOTIF
ICATION, | |
| 621 persistentNotificationId, origin, profileId, incognito, webApkPa
ckage, | |
| 622 tag, -1 /* actionIndex */); | |
| 623 Intent[] actionIntents = null; | |
| 624 if (actionTitles.length > 0) { | |
| 625 actionIntents = new Intent[actionTitles.length]; | |
| 626 for (int actionIndex = 0; actionIndex < actionTitles.length; | |
| 627 actionIndex++) { | |
| 628 actionIntents[actionIndex] = makeIntent( | |
| 629 NotificationConstants.ACTION_CLICK_NOTIFICATION, persist
entNotificationId, | |
| 630 origin, profileId, incognito, webApkPackage, tag, action
Index); | |
| 631 } | |
| 632 } | 561 } |
| 633 NotificationClient client = new NotificationClient(); | |
| 634 client.displayNotification(PENDING_INTENT_REQUEST_CODE, notificationBuil
der, clickIntent, | |
| 635 closeIntent, actionIntents, actionTitles, actionIcons, | |
| 636 PendingIntent.FLAG_UPDATE_CURRENT, platformTag, PLATFORM_ID, web
ApkPackage); | |
| 637 } | 562 } |
| 638 | 563 |
| 639 private NotificationBuilderBase createNotificationBuilder() { | 564 private NotificationBuilderBase createNotificationBuilder() { |
| 640 if (useCustomLayouts()) { | 565 if (useCustomLayouts()) { |
| 641 return new CustomNotificationBuilder(mAppContext); | 566 return new CustomNotificationBuilder(mAppContext); |
| 642 } | 567 } |
| 643 return new StandardNotificationBuilder(mAppContext); | 568 return new StandardNotificationBuilder(mAppContext); |
| 644 } | 569 } |
| 645 | 570 |
| 646 /** | 571 /** |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 796 | 721 |
| 797 private static native void nativeInitializeNotificationPlatformBridge(); | 722 private static native void nativeInitializeNotificationPlatformBridge(); |
| 798 | 723 |
| 799 private native void nativeOnNotificationClicked(long nativeNotificationPlatf
ormBridgeAndroid, | 724 private native void nativeOnNotificationClicked(long nativeNotificationPlatf
ormBridgeAndroid, |
| 800 long persistentNotificationId, String origin, String profileId, bool
ean incognito, | 725 long persistentNotificationId, String origin, String profileId, bool
ean incognito, |
| 801 String webApkPackage, String tag, int actionIndex); | 726 String webApkPackage, String tag, int actionIndex); |
| 802 private native void nativeOnNotificationClosed(long nativeNotificationPlatfo
rmBridgeAndroid, | 727 private native void nativeOnNotificationClosed(long nativeNotificationPlatfo
rmBridgeAndroid, |
| 803 long persistentNotificationId, String origin, String profileId, bool
ean incognito, | 728 long persistentNotificationId, String origin, String profileId, bool
ean incognito, |
| 804 String tag, boolean byUser); | 729 String tag, boolean byUser); |
| 805 } | 730 } |
| OLD | NEW |