зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1304145 - 4. Use string names instead of integer IDs for notifications; r=nalexander
Use string names instead of integer IDs to identify notifications. The integer IDs came from the hashes of the string names, so they are not guaranteed to be unique. Because the names from Gecko are a combination of the site origin and notification tag, there can be unintentional collisions, or worse, a site can intentionally make its notification collide with and replace another site's notification.
This commit is contained in:
Родитель
0841d97060
Коммит
ea53af2ebc
|
@ -26,15 +26,16 @@ public abstract class NotificationClient {
|
|||
/**
|
||||
* Adds a notification.
|
||||
*
|
||||
* @see NotificationHandler#add(int, String, String, String, String, PendingIntent, PendingIntent)
|
||||
* @see NotificationHandler#add(String, String, String, String, String, PendingIntent, PendingIntent)
|
||||
*/
|
||||
public synchronized void add(final int notificationID, final String aImageUrl, final String aHost,
|
||||
public synchronized void add(final String aName, final String aImageUrl, final String aHost,
|
||||
final String aAlertTitle, final String aAlertText,
|
||||
final PendingIntent contentIntent, final PendingIntent deleteIntent) {
|
||||
mTaskQueue.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mHandler.add(notificationID, aImageUrl, aHost, aAlertTitle, aAlertText, contentIntent, deleteIntent);
|
||||
mHandler.add(aName, aImageUrl, aHost, aAlertTitle,
|
||||
aAlertText, contentIntent, deleteIntent);
|
||||
}
|
||||
});
|
||||
notify();
|
||||
|
@ -47,13 +48,13 @@ public abstract class NotificationClient {
|
|||
/**
|
||||
* Adds a notification.
|
||||
*
|
||||
* @see NotificationHandler#add(int, Notification)
|
||||
* @see NotificationHandler#add(String, Notification)
|
||||
*/
|
||||
public synchronized void add(final int notificationID, final Notification notification) {
|
||||
public synchronized void add(final String name, final Notification notification) {
|
||||
mTaskQueue.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mHandler.add(notificationID, notification);
|
||||
mHandler.add(name, notification);
|
||||
}
|
||||
});
|
||||
notify();
|
||||
|
@ -66,13 +67,13 @@ public abstract class NotificationClient {
|
|||
/**
|
||||
* Removes a notification.
|
||||
*
|
||||
* @see NotificationHandler#remove(int)
|
||||
* @see NotificationHandler#remove(String)
|
||||
*/
|
||||
public synchronized void remove(final int notificationID) {
|
||||
public synchronized void remove(final String name) {
|
||||
mTaskQueue.add(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mHandler.remove(notificationID);
|
||||
mHandler.remove(name);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -90,9 +91,9 @@ public abstract class NotificationClient {
|
|||
*
|
||||
* @see NotificationHandler#isOngoing(int)
|
||||
*/
|
||||
public boolean isOngoing(int notificationID) {
|
||||
public boolean isOngoing(String name) {
|
||||
final NotificationHandler handler = mHandler;
|
||||
return handler != null && handler.isOngoing(notificationID);
|
||||
return handler != null && handler.isOngoing(name);
|
||||
}
|
||||
|
||||
protected void bind() {
|
||||
|
|
|
@ -20,8 +20,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||
|
||||
public class NotificationHandler {
|
||||
private static String LOGTAG = "GeckoNotifHandler";
|
||||
private final ConcurrentHashMap<Integer, Notification>
|
||||
mNotifications = new ConcurrentHashMap<Integer, Notification>();
|
||||
private final ConcurrentHashMap<String, Notification>
|
||||
mNotifications = new ConcurrentHashMap<>();
|
||||
private final Context mContext;
|
||||
private final NotificationManagerCompat mNotificationManager;
|
||||
|
||||
|
@ -36,7 +36,7 @@ public class NotificationHandler {
|
|||
* one download is in progress.
|
||||
*/
|
||||
private Notification mForegroundNotification;
|
||||
private int mForegroundNotificationId;
|
||||
private String mForegroundNotificationName;
|
||||
|
||||
public NotificationHandler(Context context) {
|
||||
mContext = context;
|
||||
|
@ -46,17 +46,17 @@ public class NotificationHandler {
|
|||
/**
|
||||
* Adds a notification.
|
||||
*
|
||||
* @param notificationID the unique ID of the notification
|
||||
* @param aName the unique name of the notification
|
||||
* @param aImageUrl URL of the image to use
|
||||
* @param aAlertTitle title of the notification
|
||||
* @param aAlertText text of the notification
|
||||
* @param contentIntent Intent used when the notification is clicked
|
||||
* @param deleteIntent Intent used when the notification is closed
|
||||
*/
|
||||
public void add(final int notificationID, String aImageUrl, String aHost, String aAlertTitle,
|
||||
public void add(final String aName, String aImageUrl, String aHost, String aAlertTitle,
|
||||
String aAlertText, PendingIntent contentIntent, PendingIntent deleteIntent) {
|
||||
// Remove the old notification with the same ID, if any
|
||||
remove(notificationID);
|
||||
remove(aName);
|
||||
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
|
||||
.setContentTitle(aAlertTitle)
|
||||
|
@ -78,35 +78,46 @@ public class NotificationHandler {
|
|||
builder.setWhen(System.currentTimeMillis());
|
||||
final Notification notification = builder.build();
|
||||
|
||||
mNotificationManager.notify(notificationID, notification);
|
||||
mNotifications.put(notificationID, notification);
|
||||
mNotificationManager.notify(aName, 0, notification);
|
||||
mNotifications.put(aName, notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a notification.
|
||||
*
|
||||
* @param id the unique ID of the notification
|
||||
* @param name the unique name of the notification
|
||||
* @param notification the Notification to add
|
||||
*/
|
||||
public void add(int id, Notification notification) {
|
||||
mNotificationManager.notify(id, notification);
|
||||
mNotifications.put(id, notification);
|
||||
public void add(String name, Notification notification) {
|
||||
if (isOngoing(notification)) {
|
||||
// Cancel any previous non-ongoing notifications with the same name.
|
||||
mNotificationManager.cancel(name, 0);
|
||||
|
||||
if (mForegroundNotification == null && isOngoing(notification)) {
|
||||
setForegroundNotification(id, notification);
|
||||
if (mForegroundNotificationName == null) {
|
||||
setForegroundNotification(name, notification);
|
||||
} else if (name.equals(mForegroundNotificationName)) {
|
||||
mNotificationManager.notify(R.id.foregroundNotification, notification);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Cancel any previous ongoing notifications with the same name.
|
||||
updateForegroundNotification(name);
|
||||
mNotificationManager.notify(name, 0, notification);
|
||||
}
|
||||
|
||||
mNotifications.put(name, notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a notification.
|
||||
*
|
||||
* @param notificationID ID of existing notification
|
||||
* @param aName Name of existing notification
|
||||
* @param aProgress progress of item being updated
|
||||
* @param aProgressMax max progress of item being updated
|
||||
* @param aAlertText text of the notification
|
||||
*/
|
||||
public void update(int notificationID, long aProgress, long aProgressMax, String aAlertText) {
|
||||
Notification notification = mNotifications.get(notificationID);
|
||||
public void update(String aName, long aProgress, long aProgressMax, String aAlertText) {
|
||||
Notification notification = mNotifications.get(aName);
|
||||
if (notification == null) {
|
||||
return;
|
||||
}
|
||||
|
@ -119,20 +130,20 @@ public class NotificationHandler {
|
|||
.setProgress((int) aProgressMax, (int) aProgress, false)
|
||||
.build();
|
||||
|
||||
add(notificationID, notification);
|
||||
add(aName, notification);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a notification.
|
||||
*
|
||||
* @param notificationID ID of existing notification
|
||||
* @param aName Name of existing notification
|
||||
*/
|
||||
public void remove(int notificationID) {
|
||||
final Notification notification = mNotifications.remove(notificationID);
|
||||
public void remove(String aName) {
|
||||
final Notification notification = mNotifications.remove(aName);
|
||||
if (notification != null) {
|
||||
updateForegroundNotification(notificationID, notification);
|
||||
updateForegroundNotification(aName);
|
||||
}
|
||||
mNotificationManager.cancel(notificationID);
|
||||
mNotificationManager.cancel(aName, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -150,11 +161,11 @@ public class NotificationHandler {
|
|||
/**
|
||||
* Determines whether a notification should hold a foreground service to keep Gecko alive
|
||||
*
|
||||
* @param notificationID the id of the notification to check
|
||||
* @param aName the name of the notification to check
|
||||
* @return whether the notification is ongoing
|
||||
*/
|
||||
public boolean isOngoing(int notificationID) {
|
||||
final Notification notification = mNotifications.get(notificationID);
|
||||
public boolean isOngoing(String aName) {
|
||||
final Notification notification = mNotifications.get(aName);
|
||||
return isOngoing(notification);
|
||||
}
|
||||
|
||||
|
@ -171,27 +182,27 @@ public class NotificationHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected void setForegroundNotification(int id, Notification notification) {
|
||||
mForegroundNotificationId = id;
|
||||
protected void setForegroundNotification(String name, Notification notification) {
|
||||
mForegroundNotificationName = name;
|
||||
mForegroundNotification = notification;
|
||||
}
|
||||
|
||||
private void updateForegroundNotification(int oldId, Notification oldNotification) {
|
||||
if (mForegroundNotificationId == oldId) {
|
||||
private void updateForegroundNotification(String oldName) {
|
||||
if (oldName != null && oldName.equals(mForegroundNotificationName)) {
|
||||
// If we're removing the notification associated with the
|
||||
// foreground, we need to pick another active notification to act
|
||||
// as the foreground notification.
|
||||
Notification foregroundNotification = null;
|
||||
int foregroundId = 0;
|
||||
for (final Integer id : mNotifications.keySet()) {
|
||||
final Notification notification = mNotifications.get(id);
|
||||
String foregroundName = null;
|
||||
for (final String name : mNotifications.keySet()) {
|
||||
final Notification notification = mNotifications.get(name);
|
||||
if (isOngoing(notification)) {
|
||||
foregroundNotification = notification;
|
||||
foregroundId = id;
|
||||
foregroundName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
setForegroundNotification(foregroundId, foregroundNotification);
|
||||
setForegroundNotification(foregroundName, foregroundNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ public final class NotificationHelper implements GeckoEventListener {
|
|||
PendingIntent deletePendingIntent = buildNotificationPendingIntent(message, CLEARED_EVENT);
|
||||
builder.setDeleteIntent(deletePendingIntent);
|
||||
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).add(id.hashCode(), builder.build());
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).add(id, builder.build());
|
||||
|
||||
boolean persistent = message.optBoolean(PERSISTENT_ATTR);
|
||||
// We add only not persistent notifications to the list since we want to purge only
|
||||
|
@ -344,7 +344,7 @@ public final class NotificationHelper implements GeckoEventListener {
|
|||
}
|
||||
|
||||
private void closeNotification(String id, String handlerKey, String cookie) {
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).remove(id.hashCode());
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).remove(id);
|
||||
sendNotificationWasClosed(id, handlerKey, cookie);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@ import android.content.Intent;
|
|||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
public class NotificationService extends Service {
|
||||
private final IBinder mBinder = new NotificationBinder();
|
||||
private NotificationHandler mHandler;
|
||||
|
@ -21,13 +23,13 @@ public class NotificationService extends Service {
|
|||
// access the NotificationManager service.
|
||||
mHandler = new NotificationHandler(this) {
|
||||
@Override
|
||||
protected void setForegroundNotification(int id, Notification notification) {
|
||||
super.setForegroundNotification(id, notification);
|
||||
protected void setForegroundNotification(String name, Notification notification) {
|
||||
super.setForegroundNotification(name, notification);
|
||||
|
||||
if (notification == null) {
|
||||
stopForeground(true);
|
||||
} else {
|
||||
startForeground(id, notification);
|
||||
startForeground(R.id.foregroundNotification, notification);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -18,5 +18,6 @@
|
|||
<item type="id" name="pref_header_search"/>
|
||||
<item type="id" name="updateServicePermissionNotification" />
|
||||
<item type="id" name="websiteContentNotification" />
|
||||
<item type="id" name="foregroundNotification" />
|
||||
|
||||
</resources>
|
||||
|
|
Загрузка…
Ссылка в новой задаче