зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1304145 - 2. Change GeckoAppShell's notification interface; r=nalexander
Instead of using NotificationClient directly from GeckoAppShell, add a NotificationListener interface, which NotificationClient would implement. This isolates NotificationClient (and the notification package) from GeckoAppShell and lets us move the notification package to Fennec. It also makes a cleaner interface for GeckoView consumers to implement notification support.
This commit is contained in:
Родитель
a513529b7c
Коммит
ae3538f775
|
@ -1141,11 +1141,10 @@ public abstract class GeckoApp
|
|||
// When that's fixed, `this` can change to
|
||||
// `(GeckoApplication) getApplication()` here.
|
||||
GeckoAppShell.setContextGetter(this);
|
||||
GeckoAppShell.setApplicationContext(getApplicationContext());
|
||||
GeckoAppShell.setGeckoInterface(this);
|
||||
// We need to set the notification client before launching Gecko, since Gecko could start
|
||||
// sending notifications immediately after startup, which we don't want to lose/crash on.
|
||||
GeckoAppShell.setNotificationClient(makeNotificationClient());
|
||||
GeckoAppShell.setNotificationListener(makeNotificationClient());
|
||||
|
||||
// Tell Stumbler to register a local broadcast listener to listen for preference intents.
|
||||
// We do this via intents since we can't easily access Stumbler directly,
|
||||
|
@ -2394,7 +2393,8 @@ public abstract class GeckoApp
|
|||
// even if Gecko is running but it was restarted since the notification
|
||||
// was created, the notification won't be handled (bug 849653).
|
||||
if (GeckoThread.isRunning()) {
|
||||
GeckoAppShell.handleNotification(action, alertName, alertCookie);
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).onNotificationClick(
|
||||
alertName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -158,6 +158,7 @@ public class GeckoApplication extends Application
|
|||
mRefWatcher = LeakCanary.install(this);
|
||||
|
||||
final Context context = getApplicationContext();
|
||||
GeckoAppShell.setApplicationContext(context);
|
||||
HardwareUtils.init(context);
|
||||
Clipboard.init(context);
|
||||
FilePicker.init(context);
|
||||
|
|
|
@ -269,6 +269,7 @@ gvjar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x
|
|||
'gfx/ViewTransform.java',
|
||||
'InputConnectionListener.java',
|
||||
'InputMethods.java',
|
||||
'NotificationListener.java',
|
||||
'notifications/AppNotificationClient.java',
|
||||
'notifications/NotificationClient.java',
|
||||
'notifications/NotificationHandler.java',
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.mozilla.gecko.AppConstants.Versions;
|
|||
import org.mozilla.gecko.gfx.BitmapUtils;
|
||||
import org.mozilla.gecko.gfx.LayerView;
|
||||
import org.mozilla.gecko.gfx.PanZoomController;
|
||||
import org.mozilla.gecko.notifications.NotificationClient;
|
||||
import org.mozilla.gecko.permissions.Permissions;
|
||||
import org.mozilla.gecko.util.EventCallback;
|
||||
import org.mozilla.gecko.util.GeckoRequest;
|
||||
|
@ -182,13 +181,6 @@ public class GeckoAppShell
|
|||
|
||||
private static volatile boolean locationHighAccuracyEnabled;
|
||||
|
||||
// Accessed by NotificationHelper. This should be encapsulated.
|
||||
/* package */ static NotificationClient notificationClient;
|
||||
|
||||
public static NotificationClient getNotificationClient() {
|
||||
return notificationClient;
|
||||
}
|
||||
|
||||
// See also HardwareUtils.LOW_MEMORY_THRESHOLD_MB.
|
||||
private static final int HIGH_MEMORY_DEVICE_THRESHOLD_MB = 768;
|
||||
|
||||
|
@ -467,7 +459,8 @@ public class GeckoAppShell
|
|||
double altitude, float accuracy,
|
||||
float bearing, float speed, long time);
|
||||
|
||||
private static class DefaultListeners implements SensorEventListener, LocationListener {
|
||||
private static class DefaultListeners
|
||||
implements SensorEventListener, LocationListener, NotificationListener {
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
|
@ -577,18 +570,39 @@ public class GeckoAppShell
|
|||
public void onStatusChanged(String provider, int status, Bundle extras)
|
||||
{
|
||||
}
|
||||
|
||||
@Override // NotificationListener
|
||||
public void showNotification(String name, String cookie, String host,
|
||||
String title, String text, String imageUrl) {
|
||||
// Default is to not show the notification, and immediate send close message.
|
||||
GeckoAppShell.onNotificationClose(name);
|
||||
}
|
||||
|
||||
@Override // NotificationListener
|
||||
public void showPersistentNotification(String name, String cookie, String host,
|
||||
String title, String text, String imageUrl,
|
||||
String data) {
|
||||
// Default is to not show the notification, and immediate send close message.
|
||||
GeckoAppShell.onNotificationClose(name);
|
||||
}
|
||||
|
||||
@Override // NotificationListener
|
||||
public void closeNotification(String name) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
private static final DefaultListeners DEFAULT_LISTENERS = new DefaultListeners();
|
||||
private static SensorEventListener sSensorListener = DEFAULT_LISTENERS;
|
||||
private static LocationListener sLocationListener = DEFAULT_LISTENERS;
|
||||
private static NotificationListener sNotificationListener = DEFAULT_LISTENERS;
|
||||
|
||||
public static SensorEventListener getSensorListener() {
|
||||
return sSensorListener;
|
||||
}
|
||||
|
||||
public static void setSensorListener(final SensorEventListener listener) {
|
||||
sSensorListener = listener;
|
||||
sSensorListener = (listener != null) ? listener : DEFAULT_LISTENERS;
|
||||
}
|
||||
|
||||
public static LocationListener getLocationListener() {
|
||||
|
@ -596,7 +610,15 @@ public class GeckoAppShell
|
|||
}
|
||||
|
||||
public static void setLocationListener(final LocationListener listener) {
|
||||
sLocationListener = listener;
|
||||
sLocationListener = (listener != null) ? listener : DEFAULT_LISTENERS;
|
||||
}
|
||||
|
||||
public static NotificationListener getNotificationListener() {
|
||||
return sNotificationListener;
|
||||
}
|
||||
|
||||
public static void setNotificationListener(final NotificationListener listener) {
|
||||
sNotificationListener = (listener != null) ? listener : DEFAULT_LISTENERS;
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
|
@ -921,97 +943,55 @@ public class GeckoAppShell
|
|||
return geckoInterface.openUriExternal(targetURI, mimeType, packageName, className, action, title);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only called from GeckoApp.
|
||||
*/
|
||||
public static void setNotificationClient(NotificationClient client) {
|
||||
if (notificationClient == null) {
|
||||
notificationClient = client;
|
||||
} else {
|
||||
Log.d(LOGTAG, "Notification client already set");
|
||||
}
|
||||
}
|
||||
|
||||
private static PendingIntent makePersistentNotificationIntent(int notificationID, String type,
|
||||
String persistentData) {
|
||||
final Uri.Builder b = new Uri.Builder();
|
||||
final Uri u = b.scheme("notification-event")
|
||||
.path(Integer.toString(notificationID))
|
||||
.appendQueryParameter("type", type)
|
||||
.build();
|
||||
final Intent intent = GeckoService.getIntentToCreateServices(
|
||||
getApplicationContext(), type, persistentData);
|
||||
intent.setData(u);
|
||||
|
||||
return PendingIntent.getService(getApplicationContext(), 0, intent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
@WrapForJNI(dispatchTo = "gecko")
|
||||
private static native void notifyAlertListener(String name, String topic);
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void showAlertNotification(String imageUrl, String alertTitle, String alertText,
|
||||
String alertCookie, String alertName, String host,
|
||||
String persistentData) {
|
||||
final int notificationID = alertName.hashCode();
|
||||
final PendingIntent clickIntent, closeIntent;
|
||||
|
||||
if (persistentData != null) {
|
||||
clickIntent = makePersistentNotificationIntent(
|
||||
notificationID, "persistent-notification-click", persistentData);
|
||||
closeIntent = makePersistentNotificationIntent(
|
||||
notificationID, "persistent-notification-close", persistentData);
|
||||
|
||||
} else {
|
||||
notifyAlertListener(alertName, "alertshow");
|
||||
|
||||
// The intent to launch when the user clicks the expanded notification
|
||||
final Intent notificationIntent = new Intent(ACTION_ALERT_CALLBACK);
|
||||
notificationIntent.setClassName(AppConstants.ANDROID_PACKAGE_NAME,
|
||||
AppConstants.MOZ_ANDROID_BROWSER_INTENT_CLASS);
|
||||
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
// Put the strings into the intent as an URI
|
||||
// "alert:?name=<alertName>&app=<appName>&cookie=<cookie>"
|
||||
final Uri.Builder b = new Uri.Builder();
|
||||
final Uri dataUri = b.scheme("alert")
|
||||
.path(Integer.toString(notificationID))
|
||||
.appendQueryParameter("name", alertName)
|
||||
.appendQueryParameter("cookie", alertCookie)
|
||||
.build();
|
||||
notificationIntent.setData(dataUri);
|
||||
|
||||
clickIntent = PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
closeIntent = null;
|
||||
/**
|
||||
* Called by the NotificationListener to notify Gecko that a notification has been
|
||||
* shown.
|
||||
*/
|
||||
public static void onNotificationShow(final String name) {
|
||||
if (GeckoThread.isRunning()) {
|
||||
notifyAlertListener(name, "alertshow");
|
||||
}
|
||||
}
|
||||
|
||||
notificationClient.add(notificationID, imageUrl, host, alertTitle,
|
||||
alertText, clickIntent, closeIntent);
|
||||
/**
|
||||
* Called by the NotificationListener to notify Gecko that a previously shown
|
||||
* notification has been closed.
|
||||
*/
|
||||
public static void onNotificationClose(final String name) {
|
||||
if (GeckoThread.isRunning()) {
|
||||
notifyAlertListener(name, "alertfinished");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the NotificationListener to notify Gecko that a previously shown
|
||||
* notification has been clicked on.
|
||||
*/
|
||||
public static void onNotificationClick(final String name) {
|
||||
if (GeckoThread.isRunning()) {
|
||||
notifyAlertListener(name, "alertclickcallback");
|
||||
}
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void closeNotification(String alertName) {
|
||||
notifyAlertListener(alertName, "alertfinished");
|
||||
|
||||
final int notificationID = alertName.hashCode();
|
||||
notificationClient.remove(notificationID);
|
||||
}
|
||||
|
||||
public static void handleNotification(String action, String alertName, String alertCookie) {
|
||||
final int notificationID = alertName.hashCode();
|
||||
|
||||
if (ACTION_ALERT_CALLBACK.equals(action)) {
|
||||
notifyAlertListener(alertName, "alertclickcallback");
|
||||
|
||||
if (notificationClient.isOngoing(notificationID)) {
|
||||
// When clicked, keep the notification if it displays progress
|
||||
return;
|
||||
}
|
||||
private static void showNotification(String name, String cookie, String title,
|
||||
String text, String host, String imageUrl,
|
||||
String persistentData) {
|
||||
if (persistentData == null) {
|
||||
getNotificationListener().showNotification(name, cookie, title, text, host, imageUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
closeNotification(alertName);
|
||||
getNotificationListener().showPersistentNotification(
|
||||
name, cookie, title, text, host, imageUrl, persistentData);
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
private static void closeNotification(String name) {
|
||||
getNotificationListener().closeNotification(name);
|
||||
}
|
||||
|
||||
@WrapForJNI(calledFrom = "gecko")
|
||||
|
|
|
@ -87,8 +87,7 @@ public class GeckoService extends Service {
|
|||
@Override // Service
|
||||
public void onCreate() {
|
||||
GeckoAppShell.ensureCrashHandling();
|
||||
GeckoAppShell.setApplicationContext(getApplicationContext());
|
||||
GeckoAppShell.setNotificationClient(new ServiceNotificationClient(getApplicationContext()));
|
||||
GeckoAppShell.setNotificationListener(new ServiceNotificationClient(getApplicationContext()));
|
||||
GeckoThread.onResume();
|
||||
super.onCreate();
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; 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;
|
||||
|
||||
public interface NotificationListener
|
||||
{
|
||||
void showNotification(String name, String cookie, String title, String text,
|
||||
String host, String imageUrl);
|
||||
|
||||
void showPersistentNotification(String name, String cookie, String title, String text,
|
||||
String host, String imageUrl, String data);
|
||||
|
||||
void closeNotification(String name);
|
||||
}
|
|
@ -303,7 +303,7 @@ public final class NotificationHelper implements GeckoEventListener {
|
|||
PendingIntent deletePendingIntent = buildNotificationPendingIntent(message, CLEARED_EVENT);
|
||||
builder.setDeleteIntent(deletePendingIntent);
|
||||
|
||||
GeckoAppShell.getNotificationClient().add(id.hashCode(), builder.build());
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).add(id.hashCode(), 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) {
|
||||
GeckoAppShell.getNotificationClient().remove(id.hashCode());
|
||||
((NotificationClient) GeckoAppShell.getNotificationListener()).remove(id.hashCode());
|
||||
sendNotificationWasClosed(id, handlerKey, cookie);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,8 +84,8 @@ AndroidAlerts::ShowPersistentNotification(const nsAString& aPersistentData,
|
|||
sAlertInfoMap->Put(name, new AlertInfo{aAlertListener, cookie});
|
||||
}
|
||||
|
||||
java::GeckoAppShell::ShowAlertNotification(
|
||||
imageUrl, title, text, cookie, name, host,
|
||||
java::GeckoAppShell::ShowNotification(
|
||||
name, cookie, title, text, host, imageUrl,
|
||||
!aPersistentData.IsEmpty() ? jni::StringParam(aPersistentData)
|
||||
: jni::StringParam(nullptr));
|
||||
return NS_OK;
|
||||
|
|
Загрузка…
Ссылка в новой задаче