Bug 569402 - Show notifications in the Status Bar on Android r=blassey a=blocking-fennec
This commit is contained in:
@@ -61,10 +61,20 @@
|
|||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<receiver android:enabled="true" android:name="Restarter">
|
|
||||||
<intent-filter>
|
<activity android:name="NotificationHandler"
|
||||||
|
android:label="@MOZ_APP_DISPLAYNAME@ Notification"
|
||||||
|
android:theme="@android:style/Theme.NoTitleBar">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="org.mozilla.gecko.ACTION_ALERT_CLICK" />
|
||||||
|
<action android:name="org.mozilla.gecko.ACTION_ALERT_CLEAR" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
|
||||||
|
<receiver android:enabled="true" android:name="Restarter">
|
||||||
|
<intent-filter>
|
||||||
<action android:name="org.mozilla.gecko.restart@MOZ_APP_NAME@" />
|
<action android:name="org.mozilla.gecko.restart@MOZ_APP_NAME@" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
</application>
|
</application>
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ import android.util.*;
|
|||||||
abstract public class GeckoApp
|
abstract public class GeckoApp
|
||||||
extends Activity
|
extends Activity
|
||||||
{
|
{
|
||||||
|
public static final String ACTION_ALERT_CLICK = "org.mozilla.gecko.ACTION_ALERT_CLICK";
|
||||||
|
public static final String ACTION_ALERT_CLEAR = "org.mozilla.gecko.ACTION_ALERT_CLEAR";
|
||||||
|
|
||||||
public static FrameLayout mainLayout;
|
public static FrameLayout mainLayout;
|
||||||
public static GeckoSurfaceView surfaceView;
|
public static GeckoSurfaceView surfaceView;
|
||||||
public static GeckoApp mAppContext;
|
public static GeckoApp mAppContext;
|
||||||
@@ -431,4 +434,8 @@ abstract public class GeckoApp
|
|||||||
}
|
}
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void handleNotification(String action, String alertName, String alertCookie) {
|
||||||
|
GeckoAppShell.handleNotification(action, alertName, alertCookie);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ class GeckoAppShell
|
|||||||
public static native void setSurfaceView(GeckoSurfaceView sv);
|
public static native void setSurfaceView(GeckoSurfaceView sv);
|
||||||
public static native void putenv(String map);
|
public static native void putenv(String map);
|
||||||
public static native void onResume();
|
public static native void onResume();
|
||||||
|
public static native void callObserver(String observerKey, String topic, String data);
|
||||||
|
public static native void removeObserver(String observerKey);
|
||||||
|
|
||||||
// java-side stuff
|
// java-side stuff
|
||||||
public static void loadGeckoLibs() {
|
public static void loadGeckoLibs() {
|
||||||
@@ -439,4 +441,69 @@ class GeckoAppShell
|
|||||||
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
context.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||||
cm.setText(text);
|
cm.setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void showAlertNotification(String imageUrl, String alertTitle, String alertText,
|
||||||
|
String alertCookie, String alertName) {
|
||||||
|
Log.i("GeckoAppJava", "GeckoAppShell.showAlertNotification\n" +
|
||||||
|
"- image = '" + imageUrl + "'\n" +
|
||||||
|
"- title = '" + alertTitle + "'\n" +
|
||||||
|
"- text = '" + alertText +"'\n" +
|
||||||
|
"- cookie = '" + alertCookie +"'\n" +
|
||||||
|
"- name = '" + alertName + "'");
|
||||||
|
|
||||||
|
int icon = R.drawable.icon; // Just use the app icon by default
|
||||||
|
|
||||||
|
Uri imageUri = Uri.parse(imageUrl);
|
||||||
|
String scheme = imageUri.getScheme();
|
||||||
|
|
||||||
|
if ("drawable".equals(scheme)) {
|
||||||
|
String resource = imageUri.getSchemeSpecificPart();
|
||||||
|
if ("//alertdownloads".equals(resource))
|
||||||
|
icon = R.drawable.alertdownloads;
|
||||||
|
else if ("//alertaddons".equals(resource))
|
||||||
|
icon = R.drawable.alertaddons;
|
||||||
|
}
|
||||||
|
|
||||||
|
int notificationID = alertName.hashCode();
|
||||||
|
|
||||||
|
Notification notification = new Notification(icon, alertTitle, System.currentTimeMillis());
|
||||||
|
|
||||||
|
// The intent to launch when the user clicks the expanded notification
|
||||||
|
Intent notificationIntent = new Intent(GeckoApp.ACTION_ALERT_CLICK);
|
||||||
|
notificationIntent.setClassName(GeckoApp.mAppContext,
|
||||||
|
"org.mozilla." + GeckoApp.mAppContext.getAppName() + ".NotificationHandler");
|
||||||
|
|
||||||
|
// Put the strings into the intent as an URI "alert:<name>#<cookie>"
|
||||||
|
Uri dataUri = Uri.fromParts("alert", alertName, alertCookie);
|
||||||
|
notificationIntent.setData(dataUri);
|
||||||
|
|
||||||
|
PendingIntent contentIntent = PendingIntent.getActivity(GeckoApp.mAppContext, 0, notificationIntent, 0);
|
||||||
|
notification.setLatestEventInfo(GeckoApp.mAppContext, alertTitle, alertText, contentIntent);
|
||||||
|
|
||||||
|
// The intent to execute when the status entry is deleted by the user with the "Clear All Notifications" button
|
||||||
|
Intent clearNotificationIntent = new Intent(GeckoApp.ACTION_ALERT_CLEAR);
|
||||||
|
clearNotificationIntent.setClassName(GeckoApp.mAppContext,
|
||||||
|
"org.mozilla." + GeckoApp.mAppContext.getAppName() + ".NotificationHandler");
|
||||||
|
clearNotificationIntent.setData(dataUri);
|
||||||
|
|
||||||
|
PendingIntent pendingClearIntent = PendingIntent.getActivity(GeckoApp.mAppContext, 0, clearNotificationIntent, 0);
|
||||||
|
notification.deleteIntent = pendingClearIntent;
|
||||||
|
|
||||||
|
// Show the notification
|
||||||
|
NotificationManager notificationManager = (NotificationManager)
|
||||||
|
GeckoApp.mAppContext.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.notify(notificationID, notification);
|
||||||
|
Log.i("GeckoAppJava", "Created notification ID " + notificationID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void handleNotification(String action, String alertName, String alertCookie) {
|
||||||
|
if (GeckoApp.ACTION_ALERT_CLICK.equals(action)) {
|
||||||
|
Log.i("GeckoAppJava", "GeckoAppShell.handleNotification: callObserver(alertclickcallback)");
|
||||||
|
callObserver(alertName, "alertclickcallback", alertCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i("GeckoAppJava", "GeckoAppShell.handleNotification: callObserver(alertfinished)");
|
||||||
|
callObserver(alertName, "alertfinished", alertCookie);
|
||||||
|
removeObserver(alertName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ JAVAFILES = \
|
|||||||
GeckoInputConnection.java \
|
GeckoInputConnection.java \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
|
PROCESSEDJAVAFILES = \
|
||||||
|
App.java \
|
||||||
|
Restarter.java \
|
||||||
|
NotificationHandler.java \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
DEFINES += \
|
DEFINES += \
|
||||||
-DMOZ_APP_DISPLAYNAME=$(MOZ_APP_DISPLAYNAME) \
|
-DMOZ_APP_DISPLAYNAME=$(MOZ_APP_DISPLAYNAME) \
|
||||||
-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
|
-DMOZ_APP_NAME=$(MOZ_APP_NAME) \
|
||||||
@@ -60,8 +66,7 @@ GARBAGE += \
|
|||||||
AndroidManifest.xml \
|
AndroidManifest.xml \
|
||||||
classes.dex \
|
classes.dex \
|
||||||
$(MOZ_APP_NAME).apk \
|
$(MOZ_APP_NAME).apk \
|
||||||
App.java \
|
$(PROCESSEDJAVAFILES) \
|
||||||
Restarter.java \
|
|
||||||
gecko.ap_ \
|
gecko.ap_ \
|
||||||
gecko-unaligned.apk \
|
gecko-unaligned.apk \
|
||||||
gecko-unsigned-unaligned.apk \
|
gecko-unsigned-unaligned.apk \
|
||||||
@@ -74,12 +79,22 @@ DIRS = utils
|
|||||||
# Bug 567884 - Need a way to find appropriate icons during packaging
|
# Bug 567884 - Need a way to find appropriate icons during packaging
|
||||||
ifeq ($(MOZ_APP_NAME),fennec)
|
ifeq ($(MOZ_APP_NAME),fennec)
|
||||||
ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
|
ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_48x48.png
|
||||||
ICON_PATH_HI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
|
ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/fennec_72x72.png
|
||||||
else
|
else
|
||||||
ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
|
ICON_PATH = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon48.png
|
||||||
ICON_PATH_HI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
|
ICON_PATH_HDPI = $(topsrcdir)/$(MOZ_BRANDING_DIRECTORY)/content/icon64.png
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
RES_DRAWABLE = \
|
||||||
|
res/drawable/alertaddons.png \
|
||||||
|
res/drawable/alertdownloads.png \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
|
RES_DRAWABLE_HDPI = \
|
||||||
|
res/drawable-hdpi/alertaddons.png \
|
||||||
|
res/drawable-hdpi/alertdownloads.png \
|
||||||
|
$(NULL)
|
||||||
|
|
||||||
NATIVE_LIBS = $(shell cat $(DIST)/bin/dependentlibs.list) libxpcom.so libnssckbi.so libfreebl3.so libmozutils.so
|
NATIVE_LIBS = $(shell cat $(DIST)/bin/dependentlibs.list) libxpcom.so libnssckbi.so libfreebl3.so libmozutils.so
|
||||||
FULL_LIBS = $(addprefix libs/armeabi/,$(NATIVE_LIBS))
|
FULL_LIBS = $(addprefix libs/armeabi/,$(NATIVE_LIBS))
|
||||||
|
|
||||||
@@ -120,12 +135,12 @@ tools:: $(MOZ_APP_NAME).apk
|
|||||||
|
|
||||||
# Note that we're going to set up a dependency directly between embed_android.dex and the java files
|
# Note that we're going to set up a dependency directly between embed_android.dex and the java files
|
||||||
# Instead of on the .class files, since more than one .class file might be produced per .java file
|
# Instead of on the .class files, since more than one .class file might be produced per .java file
|
||||||
classes.dex: $(JAVAFILES) App.java Restarter.java
|
classes.dex: $(JAVAFILES) $(PROCESSEDJAVAFILES) R.java
|
||||||
$(NSINSTALL) -D classes
|
$(NSINSTALL) -D classes
|
||||||
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(JAVAFILES)) App.java Restarter.java
|
$(JAVAC) $(JAVAC_FLAGS) -d classes $(addprefix $(srcdir)/,$(JAVAFILES)) $(PROCESSEDJAVAFILES) R.java
|
||||||
$(DX) --dex --output=$@ classes
|
$(DX) --dex --output=$@ classes
|
||||||
|
|
||||||
AndroidManifest.xml App.java Restarter.java : % : %.in
|
AndroidManifest.xml $(PROCESSEDJAVAFILES): % : %.in
|
||||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
|
$(PYTHON) $(topsrcdir)/config/Preprocessor.py \
|
||||||
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
|
$(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@
|
||||||
|
|
||||||
@@ -135,9 +150,20 @@ res/drawable/icon.png: $(MOZ_APP_ICON)
|
|||||||
|
|
||||||
res/drawable-hdpi/icon.png: $(MOZ_APP_ICON)
|
res/drawable-hdpi/icon.png: $(MOZ_APP_ICON)
|
||||||
$(NSINSTALL) -D res/drawable-hdpi
|
$(NSINSTALL) -D res/drawable-hdpi
|
||||||
cp $(ICON_PATH_HI) $@
|
cp $(ICON_PATH_HDPI) $@
|
||||||
|
|
||||||
gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png
|
$(RES_DRAWABLE):
|
||||||
|
$(NSINSTALL) -D res/drawable
|
||||||
|
cp $(topsrcdir)/mobile/app/android/drawable/* res/drawable/
|
||||||
|
|
||||||
|
$(RES_DRAWABLE_HDPI):
|
||||||
|
$(NSINSTALL) -D res/drawable-hdpi
|
||||||
|
cp $(topsrcdir)/mobile/app/android/drawable-hdpi/* res/drawable-hdpi/
|
||||||
|
|
||||||
|
R.java: $(MOZ_APP_ICON) $(RES_DRAWABLE) $(RES_DRAWABLE_HDPI)
|
||||||
|
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -J . --custom-package org.mozilla.gecko
|
||||||
|
|
||||||
|
gecko.ap_: AndroidManifest.xml res/drawable/icon.png res/drawable-hdpi/icon.png $(RES_DRAWABLE) $(RES_DRAWABLE_HDPI)
|
||||||
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
|
$(AAPT) package -f -M AndroidManifest.xml -I $(ANDROID_SDK)/android.jar -S res -F $@
|
||||||
|
|
||||||
libs/armeabi/%: $(DIST)/lib/%
|
libs/armeabi/%: $(DIST)/lib/%
|
||||||
|
|||||||
104
embedding/android/NotificationHandler.java.in
Normal file
104
embedding/android/NotificationHandler.java.in
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/* -*- Mode: Java; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||||
|
* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Mozilla Android code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is Mozilla Corporation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Alex Pakhotin <alexp@mozilla.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#filter substitution
|
||||||
|
package org.mozilla.@MOZ_APP_NAME@;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.NotificationManager;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
public class NotificationHandler
|
||||||
|
extends Activity
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
Log.i("GeckoAppJava", "NotificationHandler.onCreate");
|
||||||
|
|
||||||
|
Intent intent = getIntent();
|
||||||
|
if (intent != null)
|
||||||
|
handleIntent(intent);
|
||||||
|
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleIntent(Intent notificationIntent) {
|
||||||
|
String action = notificationIntent.getAction();
|
||||||
|
String alertName = "";
|
||||||
|
String alertCookie = "";
|
||||||
|
Uri data = notificationIntent.getData();
|
||||||
|
if (data != null) {
|
||||||
|
alertName = data.getSchemeSpecificPart();
|
||||||
|
alertCookie = data.getFragment();
|
||||||
|
if (alertCookie == null)
|
||||||
|
alertCookie = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.i("GeckoAppJava", "NotificationHandler.handleIntent\n" +
|
||||||
|
"- action = '" + action + "'\n" +
|
||||||
|
"- alertName = '" + alertName + "'\n" +
|
||||||
|
"- alertCookie = '" + alertCookie + "'");
|
||||||
|
|
||||||
|
int notificationID = alertName.hashCode();
|
||||||
|
|
||||||
|
Log.i("GeckoAppJava", "Handle notification ID " + notificationID);
|
||||||
|
|
||||||
|
NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||||
|
notificationManager.cancel(notificationID);
|
||||||
|
|
||||||
|
if (App.mAppContext != null) {
|
||||||
|
// This should call the observer, if any
|
||||||
|
App.mAppContext.handleNotification(action, alertName, alertCookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (App.ACTION_ALERT_CLICK.equals(action)) {
|
||||||
|
// Start or bring to front the main activity
|
||||||
|
Intent appIntent = new Intent(Intent.ACTION_MAIN);
|
||||||
|
appIntent.setClassName(this, "org.mozilla.@MOZ_APP_NAME@.App");
|
||||||
|
try {
|
||||||
|
startActivity(appIntent);
|
||||||
|
} catch (ActivityNotFoundException e) {
|
||||||
|
Log.e("GeckoAppJava", "NotificationHandler Exception: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,9 +56,11 @@ interface nsIAlertsService : nsISupports
|
|||||||
* consumer during the alert listener callbacks.
|
* consumer during the alert listener callbacks.
|
||||||
* @param alertListener Used for callbacks. May be null if the caller
|
* @param alertListener Used for callbacks. May be null if the caller
|
||||||
* doesn't care about callbacks.
|
* doesn't care about callbacks.
|
||||||
* @param name The name of the notification. This is currently
|
* @param name The name of the notification. This is currently
|
||||||
* only used on OS X with Growl. On OS X with Growl,
|
* only used on OS X with Growl and Android.
|
||||||
* users can disable notifications with a given name.
|
* On OS X with Growl, users can disable notifications
|
||||||
|
* with a given name. On Android the name is hashed
|
||||||
|
* and used as a notification ID.
|
||||||
*
|
*
|
||||||
* @throws NS_ERROR_NOT_AVAILABLE If the notification cannot be displayed.
|
* @throws NS_ERROR_NOT_AVAILABLE If the notification cannot be displayed.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
* Contributor(s):
|
* Contributor(s):
|
||||||
* Scott MacGregor <mscott@netscape.com>
|
* Scott MacGregor <mscott@netscape.com>
|
||||||
* Jens Bannmann <jens.b@web.de>
|
* Jens Bannmann <jens.b@web.de>
|
||||||
|
* Alex Pakhotin <alexp@mozilla.com>
|
||||||
*
|
*
|
||||||
* Alternatively, the contents of this file may be used under the terms of
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
@@ -38,6 +39,11 @@
|
|||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "nsAlertsService.h"
|
#include "nsAlertsService.h"
|
||||||
|
|
||||||
|
#ifdef ANDROID
|
||||||
|
#include "AndroidBridge.h"
|
||||||
|
#else
|
||||||
|
|
||||||
#include "nsISupportsArray.h"
|
#include "nsISupportsArray.h"
|
||||||
#include "nsXPCOM.h"
|
#include "nsXPCOM.h"
|
||||||
#include "nsISupportsPrimitives.h"
|
#include "nsISupportsPrimitives.h"
|
||||||
@@ -53,6 +59,8 @@ static NS_DEFINE_CID(kLookAndFeelCID, NS_LOOKANDFEEL_CID);
|
|||||||
|
|
||||||
#define ALERT_CHROME_URL "chrome://global/content/alerts/alert.xul"
|
#define ALERT_CHROME_URL "chrome://global/content/alerts/alert.xul"
|
||||||
|
|
||||||
|
#endif // !ANDROID
|
||||||
|
|
||||||
NS_IMPL_THREADSAFE_ADDREF(nsAlertsService)
|
NS_IMPL_THREADSAFE_ADDREF(nsAlertsService)
|
||||||
NS_IMPL_THREADSAFE_RELEASE(nsAlertsService)
|
NS_IMPL_THREADSAFE_RELEASE(nsAlertsService)
|
||||||
|
|
||||||
@@ -74,6 +82,11 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
|||||||
nsIObserver * aAlertListener,
|
nsIObserver * aAlertListener,
|
||||||
const nsAString & aAlertName)
|
const nsAString & aAlertName)
|
||||||
{
|
{
|
||||||
|
#ifdef ANDROID
|
||||||
|
mozilla::AndroidBridge::Bridge()->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertCookie,
|
||||||
|
aAlertListener, aAlertName);
|
||||||
|
return NS_OK;
|
||||||
|
#else
|
||||||
// Check if there is an optional service that handles system-level notifications
|
// Check if there is an optional service that handles system-level notifications
|
||||||
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
|
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_SYSTEMALERTSERVICE_CONTRACTID));
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
@@ -156,4 +169,5 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
|||||||
"chrome,dialog=yes,titlebar=no,popup=yes", argsArray,
|
"chrome,dialog=yes,titlebar=no,popup=yes", argsArray,
|
||||||
getter_AddRefs(newWindow));
|
getter_AddRefs(newWindow));
|
||||||
return rv;
|
return rv;
|
||||||
|
#endif // !ANDROID
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@
|
|||||||
#include "nsXPCOMStrings.h"
|
#include "nsXPCOMStrings.h"
|
||||||
|
|
||||||
#include "AndroidBridge.h"
|
#include "AndroidBridge.h"
|
||||||
|
#include "nsAppShell.h"
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
@@ -110,6 +111,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
|
|||||||
jMoveTaskToBack = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "moveTaskToBack", "()V");
|
jMoveTaskToBack = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "moveTaskToBack", "()V");
|
||||||
jGetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getClipboardText", "()Ljava/lang/String;");
|
jGetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getClipboardText", "()Ljava/lang/String;");
|
||||||
jSetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setClipboardText", "(Ljava/lang/String;)V");
|
jSetClipboardText = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setClipboardText", "(Ljava/lang/String;)V");
|
||||||
|
jShowAlertNotification = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showAlertNotification", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
|
||||||
|
|
||||||
|
|
||||||
jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
|
jEGLContextClass = (jclass) jEnv->NewGlobalRef(jEnv->FindClass("javax/microedition/khronos/egl/EGLContext"));
|
||||||
@@ -403,6 +405,30 @@ AndroidBridge::EmptyClipboard()
|
|||||||
mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass, jSetClipboardText, nsnull);
|
mJNIEnv->CallStaticObjectMethod(mGeckoAppShellClass, jSetClipboardText, nsnull);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AndroidBridge::ShowAlertNotification(const nsAString& aImageUrl,
|
||||||
|
const nsAString& aAlertTitle,
|
||||||
|
const nsAString& aAlertText,
|
||||||
|
const nsAString& aAlertCookie,
|
||||||
|
nsIObserver *aAlertListener,
|
||||||
|
const nsAString& aAlertName)
|
||||||
|
{
|
||||||
|
ALOG("ShowAlertNotification");
|
||||||
|
|
||||||
|
AutoLocalJNIFrame jniFrame;
|
||||||
|
|
||||||
|
if (nsAppShell::gAppShell && aAlertListener)
|
||||||
|
nsAppShell::gAppShell->AddObserver(aAlertName, aAlertListener);
|
||||||
|
|
||||||
|
jvalue args[5];
|
||||||
|
args[0].l = mJNIEnv->NewString(nsPromiseFlatString(aImageUrl).get(), aImageUrl.Length());
|
||||||
|
args[1].l = mJNIEnv->NewString(nsPromiseFlatString(aAlertTitle).get(), aAlertTitle.Length());
|
||||||
|
args[2].l = mJNIEnv->NewString(nsPromiseFlatString(aAlertText).get(), aAlertText.Length());
|
||||||
|
args[3].l = mJNIEnv->NewString(nsPromiseFlatString(aAlertCookie).get(), aAlertCookie.Length());
|
||||||
|
args[4].l = mJNIEnv->NewString(nsPromiseFlatString(aAlertName).get(), aAlertName.Length());
|
||||||
|
mJNIEnv->CallStaticVoidMethodA(mGeckoAppShellClass, jShowAlertNotification, args);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AndroidBridge::SetSurfaceView(jobject obj)
|
AndroidBridge::SetSurfaceView(jobject obj)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsIRunnable.h"
|
#include "nsIRunnable.h"
|
||||||
|
#include "nsIObserver.h"
|
||||||
|
|
||||||
#include "AndroidJavaWrappers.h"
|
#include "AndroidJavaWrappers.h"
|
||||||
|
|
||||||
@@ -134,6 +135,13 @@ public:
|
|||||||
|
|
||||||
bool ClipboardHasText();
|
bool ClipboardHasText();
|
||||||
|
|
||||||
|
void ShowAlertNotification(const nsAString& aImageUrl,
|
||||||
|
const nsAString& aAlertTitle,
|
||||||
|
const nsAString& aAlertText,
|
||||||
|
const nsAString& aAlertData,
|
||||||
|
nsIObserver *aAlertListener,
|
||||||
|
const nsAString& aAlertName);
|
||||||
|
|
||||||
struct AutoLocalJNIFrame {
|
struct AutoLocalJNIFrame {
|
||||||
AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) {
|
AutoLocalJNIFrame(int nEntries = 128) : mEntries(nEntries) {
|
||||||
AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries);
|
AndroidBridge::Bridge()->JNI()->PushLocalFrame(mEntries);
|
||||||
@@ -191,6 +199,7 @@ protected:
|
|||||||
jmethodID jMoveTaskToBack;
|
jmethodID jMoveTaskToBack;
|
||||||
jmethodID jGetClipboardText;
|
jmethodID jGetClipboardText;
|
||||||
jmethodID jSetClipboardText;
|
jmethodID jSetClipboardText;
|
||||||
|
jmethodID jShowAlertNotification;
|
||||||
|
|
||||||
// stuff we need for CallEglCreateWindowSurface
|
// stuff we need for CallEglCreateWindowSurface
|
||||||
jclass jEGLSurfaceImplClass;
|
jclass jEGLSurfaceImplClass;
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "nsILocalFile.h"
|
#include "nsILocalFile.h"
|
||||||
|
#include "nsString.h"
|
||||||
|
|
||||||
#include "AndroidBridge.h"
|
#include "AndroidBridge.h"
|
||||||
|
|
||||||
@@ -57,6 +58,8 @@ extern "C" {
|
|||||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject sv);
|
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setSurfaceView(JNIEnv *jenv, jclass, jobject sv);
|
||||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setInitialSize(JNIEnv *jenv, jclass, int width, int height);
|
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_setInitialSize(JNIEnv *jenv, jclass, int width, int height);
|
||||||
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *, jclass);
|
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *, jclass);
|
||||||
|
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv *, jclass, jstring observerKey, jstring topic, jstring data);
|
||||||
|
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -98,3 +101,30 @@ Java_org_mozilla_gecko_GeckoAppShell_onResume(JNIEnv *jenv, jclass jc)
|
|||||||
if (nsAppShell::gAppShell)
|
if (nsAppShell::gAppShell)
|
||||||
nsAppShell::gAppShell->OnResume();
|
nsAppShell::gAppShell->OnResume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_EXPORT void JNICALL
|
||||||
|
Java_org_mozilla_gecko_GeckoAppShell_callObserver(JNIEnv *jenv, jclass, jstring jObserverKey, jstring jTopic, jstring jData)
|
||||||
|
{
|
||||||
|
if (!nsAppShell::gAppShell)
|
||||||
|
return;
|
||||||
|
|
||||||
|
nsJNIString sObserverKey(jObserverKey, jenv);
|
||||||
|
nsJNIString sTopic(jTopic, jenv);
|
||||||
|
nsJNIString sData(jData, jenv);
|
||||||
|
|
||||||
|
nsAppShell::gAppShell->CallObserver(sObserverKey, sTopic, sData);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_EXPORT void JNICALL
|
||||||
|
Java_org_mozilla_gecko_GeckoAppShell_removeObserver(JNIEnv *jenv, jclass, jstring jObserverKey)
|
||||||
|
{
|
||||||
|
if (!nsAppShell::gAppShell)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const jchar *observerKey = jenv->GetStringChars(jObserverKey, NULL);
|
||||||
|
nsString sObserverKey(observerKey);
|
||||||
|
sObserverKey.SetLength(jenv->GetStringLength(jObserverKey));
|
||||||
|
jenv->ReleaseStringChars(jObserverKey, observerKey);
|
||||||
|
|
||||||
|
nsAppShell::gAppShell->RemoveObserver(sObserverKey);
|
||||||
|
}
|
||||||
|
|||||||
@@ -441,16 +441,17 @@ AndroidRect::Init(JNIEnv *jenv, jobject jobj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsJNIString::nsJNIString(jstring jstr)
|
nsJNIString::nsJNIString(jstring jstr, JNIEnv *jenv)
|
||||||
{
|
{
|
||||||
if (!jstr) {
|
if (!jstr) {
|
||||||
SetIsVoid(PR_TRUE);
|
SetIsVoid(PR_TRUE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const jchar* jCharPtr = JNI()->GetStringChars(jstr, false);
|
JNIEnv *jni = jenv;
|
||||||
int len = JNI()->GetStringLength(jstr);
|
if (!jni)
|
||||||
nsresult rv;
|
jni = JNI();
|
||||||
|
const jchar* jCharPtr = jni->GetStringChars(jstr, false);
|
||||||
|
int len = jni->GetStringLength(jstr);
|
||||||
Assign(jCharPtr, len);
|
Assign(jCharPtr, len);
|
||||||
JNI()->ReleaseStringChars(jstr, jCharPtr);
|
jni->ReleaseStringChars(jstr, jCharPtr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -468,7 +468,7 @@ public:
|
|||||||
class nsJNIString : public nsString
|
class nsJNIString : public nsString
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
nsJNIString(jstring jstr);
|
nsJNIString(jstring jstr, JNIEnv *jenv = NULL);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -118,6 +118,8 @@ nsAppShell::Init()
|
|||||||
mQueueCond = PR_NewCondVar(mCondLock);
|
mQueueCond = PR_NewCondVar(mCondLock);
|
||||||
mPaused = PR_NewCondVar(mPausedLock);
|
mPaused = PR_NewCondVar(mPausedLock);
|
||||||
|
|
||||||
|
mObserversHash.Init();
|
||||||
|
|
||||||
return nsBaseAppShell::Init();
|
return nsBaseAppShell::Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,6 +369,67 @@ nsAppShell::OnResume()
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsAppShell::AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aObserver != nsnull, "nsAppShell::AddObserver: aObserver is null!");
|
||||||
|
return mObserversHash.Put(aObserverKey, aObserver) ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The XPCOM event that will call the observer on the main thread.
|
||||||
|
*/
|
||||||
|
class ObserverCaller : public nsRunnable {
|
||||||
|
public:
|
||||||
|
ObserverCaller(nsIObserver *aObserver, const char *aTopic, const PRUnichar *aData) :
|
||||||
|
mObserver(aObserver), mTopic(aTopic), mData(aData) {
|
||||||
|
NS_ASSERTION(aObserver != nsnull, "ObserverCaller: aObserver is null!");
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run() {
|
||||||
|
ALOG("ObserverCaller::Run: observer = %p, topic = '%s')",
|
||||||
|
(nsIObserver*)mObserver, mTopic.get());
|
||||||
|
mObserver->Observe(nsnull, mTopic.get(), mData.get());
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsCOMPtr<nsIObserver> mObserver;
|
||||||
|
nsCString mTopic;
|
||||||
|
nsString mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAppShell::CallObserver(const nsAString &aObserverKey, const nsAString &aTopic, const nsAString &aData)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIObserver> observer;
|
||||||
|
mObserversHash.Get(aObserverKey, getter_AddRefs(observer));
|
||||||
|
|
||||||
|
if (!observer) {
|
||||||
|
ALOG("nsAppShell::CallObserver: Observer was not found!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const NS_ConvertUTF16toUTF8 sTopic(aTopic);
|
||||||
|
const nsPromiseFlatString& sData = PromiseFlatString(aData);
|
||||||
|
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
// This branch will unlikely be hit, have it just in case
|
||||||
|
observer->Observe(nsnull, sTopic.get(), sData.get());
|
||||||
|
} else {
|
||||||
|
// Java is not running on main thread, so we have to use NS_DispatchToMainThread
|
||||||
|
nsCOMPtr<nsIRunnable> observerCaller = new ObserverCaller(observer, sTopic.get(), sData.get());
|
||||||
|
nsresult rv = NS_DispatchToMainThread(observerCaller);
|
||||||
|
ALOG("NS_DispatchToMainThread result: %d", rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsAppShell::RemoveObserver(const nsAString &aObserverKey)
|
||||||
|
{
|
||||||
|
mObserversHash.Remove(aObserverKey);
|
||||||
|
}
|
||||||
|
|
||||||
// Used by IPC code
|
// Used by IPC code
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "nsBaseAppShell.h"
|
#include "nsBaseAppShell.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
|
#include "nsInterfaceHashtable.h"
|
||||||
|
|
||||||
#include "prcvar.h"
|
#include "prcvar.h"
|
||||||
|
|
||||||
@@ -70,6 +71,10 @@ public:
|
|||||||
void RemoveNextEvent();
|
void RemoveNextEvent();
|
||||||
void OnResume();
|
void OnResume();
|
||||||
|
|
||||||
|
nsresult AddObserver(const nsAString &aObserverKey, nsIObserver *aObserver);
|
||||||
|
void CallObserver(const nsAString &aObserverKey, const nsAString &aTopic, const nsAString &aData);
|
||||||
|
void RemoveObserver(const nsAString &aObserverKey);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void ScheduleNativeEventCallback();
|
virtual void ScheduleNativeEventCallback();
|
||||||
virtual ~nsAppShell();
|
virtual ~nsAppShell();
|
||||||
@@ -81,6 +86,7 @@ protected:
|
|||||||
PRCondVar *mQueueCond;
|
PRCondVar *mQueueCond;
|
||||||
PRCondVar *mPaused;
|
PRCondVar *mPaused;
|
||||||
nsTArray<mozilla::AndroidGeckoEvent *> mEventQueue;
|
nsTArray<mozilla::AndroidGeckoEvent *> mEventQueue;
|
||||||
|
nsInterfaceHashtable<nsStringHashKey, nsIObserver> mObserversHash;
|
||||||
|
|
||||||
mozilla::AndroidGeckoEvent *GetNextEvent();
|
mozilla::AndroidGeckoEvent *GetNextEvent();
|
||||||
mozilla::AndroidGeckoEvent *PeekNextEvent();
|
mozilla::AndroidGeckoEvent *PeekNextEvent();
|
||||||
|
|||||||
Reference in New Issue
Block a user