diff options
Diffstat (limited to 'mobile/android/base/java/org/mozilla/gecko/notifications/NotificationHelper.java')
-rw-r--r-- | mobile/android/base/java/org/mozilla/gecko/notifications/NotificationHelper.java | 366 |
1 files changed, 0 insertions, 366 deletions
diff --git a/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationHelper.java b/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationHelper.java deleted file mode 100644 index 1e33031b5..000000000 --- a/mobile/android/base/java/org/mozilla/gecko/notifications/NotificationHelper.java +++ /dev/null @@ -1,366 +0,0 @@ -/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*- - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -package org.mozilla.gecko.notifications; - -import java.util.HashMap; -import java.util.Iterator; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.mozilla.gecko.AppConstants; -import org.mozilla.gecko.EventDispatcher; -import org.mozilla.gecko.GeckoAppShell; -import org.mozilla.gecko.R; -import org.mozilla.gecko.gfx.BitmapUtils; -import org.mozilla.gecko.mozglue.SafeIntent; -import org.mozilla.gecko.util.GeckoEventListener; - -import android.app.PendingIntent; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.support.v4.app.NotificationCompat; -import android.util.Log; - -public final class NotificationHelper implements GeckoEventListener { - public static final String HELPER_BROADCAST_ACTION = AppConstants.ANDROID_PACKAGE_NAME + ".helperBroadcastAction"; - - public static final String NOTIFICATION_ID = "NotificationHelper_ID"; - private static final String LOGTAG = "GeckoNotificationHelper"; - private static final String HELPER_NOTIFICATION = "helperNotif"; - - // Attributes mandatory to be used while sending a notification from js. - private static final String TITLE_ATTR = "title"; - private static final String TEXT_ATTR = "text"; - /* package */ static final String ID_ATTR = "id"; - private static final String SMALLICON_ATTR = "smallIcon"; - - // Attributes that can be used while sending a notification from js. - private static final String PROGRESS_VALUE_ATTR = "progress_value"; - private static final String PROGRESS_MAX_ATTR = "progress_max"; - private static final String PROGRESS_INDETERMINATE_ATTR = "progress_indeterminate"; - private static final String LIGHT_ATTR = "light"; - private static final String ONGOING_ATTR = "ongoing"; - private static final String WHEN_ATTR = "when"; - private static final String PRIORITY_ATTR = "priority"; - private static final String LARGE_ICON_ATTR = "largeIcon"; - private static final String ACTIONS_ATTR = "actions"; - private static final String ACTION_ID_ATTR = "buttonId"; - private static final String ACTION_TITLE_ATTR = "title"; - private static final String ACTION_ICON_ATTR = "icon"; - private static final String PERSISTENT_ATTR = "persistent"; - private static final String HANDLER_ATTR = "handlerKey"; - private static final String COOKIE_ATTR = "cookie"; - static final String EVENT_TYPE_ATTR = "eventType"; - - private static final String NOTIFICATION_SCHEME = "moz-notification"; - - private static final String BUTTON_EVENT = "notification-button-clicked"; - private static final String CLICK_EVENT = "notification-clicked"; - static final String CLEARED_EVENT = "notification-cleared"; - - static final String ORIGINAL_EXTRA_COMPONENT = "originalComponent"; - - private final Context mContext; - - // Holds a list of notifications that should be cleared if the Fennec Activity is shut down. - // Will not include ongoing or persistent notifications that are tied to Gecko's lifecycle. - private HashMap<String, String> mClearableNotifications; - - private boolean mInitialized; - private static NotificationHelper sInstance; - - private NotificationHelper(Context context) { - mContext = context; - } - - public void init() { - if (mInitialized) { - return; - } - - mClearableNotifications = new HashMap<String, String>(); - EventDispatcher.getInstance().registerGeckoThreadListener(this, - "Notification:Show", - "Notification:Hide"); - mInitialized = true; - } - - public static NotificationHelper getInstance(Context context) { - // If someone else created this singleton, but didn't initialize it, something has gone wrong. - if (sInstance != null && !sInstance.mInitialized) { - throw new IllegalStateException("NotificationHelper was created by someone else but not initialized"); - } - - if (sInstance == null) { - sInstance = new NotificationHelper(context.getApplicationContext()); - } - return sInstance; - } - - @Override - public void handleMessage(String event, JSONObject message) { - if (event.equals("Notification:Show")) { - showNotification(message); - } else if (event.equals("Notification:Hide")) { - hideNotification(message); - } - } - - public boolean isHelperIntent(Intent i) { - return i.getBooleanExtra(HELPER_NOTIFICATION, false); - } - - public static void getArgsAndSendNotificationIntent(SafeIntent intent) { - final JSONObject args = new JSONObject(); - final Uri data = intent.getData(); - - final String notificationType = data.getQueryParameter(EVENT_TYPE_ATTR); - - try { - args.put(ID_ATTR, data.getQueryParameter(ID_ATTR)); - args.put(EVENT_TYPE_ATTR, notificationType); - args.put(HANDLER_ATTR, data.getQueryParameter(HANDLER_ATTR)); - args.put(COOKIE_ATTR, intent.getStringExtra(COOKIE_ATTR)); - - if (BUTTON_EVENT.equals(notificationType)) { - final String actionName = data.getQueryParameter(ACTION_ID_ATTR); - args.put(ACTION_ID_ATTR, actionName); - } - - Log.i(LOGTAG, "Send " + args.toString()); - GeckoAppShell.notifyObservers("Notification:Event", args.toString()); - } catch (JSONException e) { - Log.e(LOGTAG, "Error building JSON notification arguments.", e); - } - } - - public void handleNotificationIntent(SafeIntent i) { - final Uri data = i.getData(); - final String notificationType = data.getQueryParameter(EVENT_TYPE_ATTR); - final String id = data.getQueryParameter(ID_ATTR); - if (id == null || notificationType == null) { - Log.e(LOGTAG, "handleNotificationEvent: invalid intent parameters"); - return; - } - - getArgsAndSendNotificationIntent(i); - - // If the notification was clicked, we are closing it. This must be executed after - // sending the event to js side because when the notification is canceled no event can be - // handled. - if (CLICK_EVENT.equals(notificationType) && !i.getBooleanExtra(ONGOING_ATTR, false)) { - // The handler and cookie parameters are optional. - final String handler = data.getQueryParameter(HANDLER_ATTR); - final String cookie = i.getStringExtra(COOKIE_ATTR); - hideNotification(id, handler, cookie); - } - } - - private Uri.Builder getNotificationBuilder(JSONObject message, String type) { - Uri.Builder b = new Uri.Builder(); - b.scheme(NOTIFICATION_SCHEME).appendQueryParameter(EVENT_TYPE_ATTR, type); - - try { - final String id = message.getString(ID_ATTR); - b.appendQueryParameter(ID_ATTR, id); - } catch (JSONException ex) { - Log.i(LOGTAG, "buildNotificationPendingIntent, error parsing", ex); - } - - try { - final String id = message.getString(HANDLER_ATTR); - b.appendQueryParameter(HANDLER_ATTR, id); - } catch (JSONException ex) { - Log.i(LOGTAG, "Notification doesn't have a handler"); - } - - return b; - } - - private Intent buildNotificationIntent(JSONObject message, Uri.Builder builder) { - Intent notificationIntent = new Intent(HELPER_BROADCAST_ACTION); - final boolean ongoing = message.optBoolean(ONGOING_ATTR); - notificationIntent.putExtra(ONGOING_ATTR, ongoing); - - final Uri dataUri = builder.build(); - notificationIntent.setData(dataUri); - notificationIntent.putExtra(HELPER_NOTIFICATION, true); - notificationIntent.putExtra(COOKIE_ATTR, message.optString(COOKIE_ATTR)); - - // All intents get routed through the notificationReceiver. That lets us bail if we don't want to start Gecko - final ComponentName name = new ComponentName(mContext, GeckoAppShell.getGeckoInterface().getActivity().getClass()); - notificationIntent.putExtra(ORIGINAL_EXTRA_COMPONENT, name); - - return notificationIntent; - } - - private PendingIntent buildNotificationPendingIntent(JSONObject message, String type) { - Uri.Builder builder = getNotificationBuilder(message, type); - final Intent notificationIntent = buildNotificationIntent(message, builder); - return PendingIntent.getBroadcast(mContext, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); - } - - private PendingIntent buildButtonClickPendingIntent(JSONObject message, JSONObject action) { - Uri.Builder builder = getNotificationBuilder(message, BUTTON_EVENT); - try { - // Action name must be in query uri, otherwise buttons pending intents - // would be collapsed. - if (action.has(ACTION_ID_ATTR)) { - builder.appendQueryParameter(ACTION_ID_ATTR, action.getString(ACTION_ID_ATTR)); - } else { - Log.i(LOGTAG, "button event with no name"); - } - } catch (JSONException ex) { - Log.i(LOGTAG, "buildNotificationPendingIntent, error parsing", ex); - } - final Intent notificationIntent = buildNotificationIntent(message, builder); - PendingIntent res = PendingIntent.getBroadcast(mContext, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT); - return res; - } - - private void showNotification(JSONObject message) { - NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext); - - // These attributes are required - final String id; - try { - builder.setContentTitle(message.getString(TITLE_ATTR)); - builder.setContentText(message.getString(TEXT_ATTR)); - id = message.getString(ID_ATTR); - } catch (JSONException ex) { - Log.i(LOGTAG, "Error parsing", ex); - return; - } - - Uri imageUri = Uri.parse(message.optString(SMALLICON_ATTR)); - builder.setSmallIcon(BitmapUtils.getResource(mContext, imageUri)); - - JSONArray light = message.optJSONArray(LIGHT_ATTR); - if (light != null && light.length() == 3) { - try { - builder.setLights(light.getInt(0), - light.getInt(1), - light.getInt(2)); - } catch (JSONException ex) { - Log.i(LOGTAG, "Error parsing", ex); - } - } - - boolean ongoing = message.optBoolean(ONGOING_ATTR); - builder.setOngoing(ongoing); - - if (message.has(WHEN_ATTR)) { - long when = message.optLong(WHEN_ATTR); - builder.setWhen(when); - } - - if (message.has(PRIORITY_ATTR)) { - int priority = message.optInt(PRIORITY_ATTR); - builder.setPriority(priority); - } - - if (message.has(LARGE_ICON_ATTR)) { - Bitmap b = BitmapUtils.getBitmapFromDataURI(message.optString(LARGE_ICON_ATTR)); - builder.setLargeIcon(b); - } - - if (message.has(PROGRESS_VALUE_ATTR) && - message.has(PROGRESS_MAX_ATTR) && - message.has(PROGRESS_INDETERMINATE_ATTR)) { - try { - final int progress = message.getInt(PROGRESS_VALUE_ATTR); - final int progressMax = message.getInt(PROGRESS_MAX_ATTR); - final boolean progressIndeterminate = message.getBoolean(PROGRESS_INDETERMINATE_ATTR); - builder.setProgress(progressMax, progress, progressIndeterminate); - } catch (JSONException ex) { - Log.i(LOGTAG, "Error parsing", ex); - } - } - - JSONArray actions = message.optJSONArray(ACTIONS_ATTR); - if (actions != null) { - try { - for (int i = 0; i < actions.length(); i++) { - JSONObject action = actions.getJSONObject(i); - final PendingIntent pending = buildButtonClickPendingIntent(message, action); - final String actionTitle = action.getString(ACTION_TITLE_ATTR); - final Uri actionImage = Uri.parse(action.optString(ACTION_ICON_ATTR)); - builder.addAction(BitmapUtils.getResource(mContext, actionImage), - actionTitle, - pending); - } - } catch (JSONException ex) { - Log.i(LOGTAG, "Error parsing", ex); - } - } - - PendingIntent pi = buildNotificationPendingIntent(message, CLICK_EVENT); - builder.setContentIntent(pi); - PendingIntent deletePendingIntent = buildNotificationPendingIntent(message, CLEARED_EVENT); - builder.setDeleteIntent(deletePendingIntent); - - ((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 - // them when geckoapp is destroyed. - if (!persistent && !mClearableNotifications.containsKey(id)) { - mClearableNotifications.put(id, message.toString()); - } - } - - private void hideNotification(JSONObject message) { - final String id; - final String handler; - final String cookie; - try { - id = message.getString("id"); - handler = message.optString("handlerKey"); - cookie = message.optString("cookie"); - } catch (JSONException ex) { - Log.i(LOGTAG, "Error parsing", ex); - return; - } - - hideNotification(id, handler, cookie); - } - - private void closeNotification(String id, String handlerKey, String cookie) { - ((NotificationClient) GeckoAppShell.getNotificationListener()).remove(id); - } - - public void hideNotification(String id, String handlerKey, String cookie) { - mClearableNotifications.remove(id); - closeNotification(id, handlerKey, cookie); - } - - private void clearAll() { - for (Iterator<String> i = mClearableNotifications.keySet().iterator(); i.hasNext();) { - final String id = i.next(); - final String json = mClearableNotifications.get(id); - i.remove(); - - JSONObject obj; - try { - obj = new JSONObject(json); - } catch (JSONException ex) { - obj = new JSONObject(); - } - - closeNotification(id, obj.optString(HANDLER_ATTR), obj.optString(COOKIE_ATTR)); - } - } - - public static void destroy() { - if (sInstance != null) { - sInstance.clearAll(); - } - } -} |