Bug 778668 - Bubble the application name/origin/manifest in the desktop-notification mozChromeEvent [r=wchen]

This commit is contained in:
Fabrice Desré 2012-11-28 22:36:15 -08:00
parent f409f7fc8c
commit 0bcc3b3058
5 changed files with 176 additions and 23 deletions

View File

@ -263,6 +263,7 @@ var shell = {
ppmm.addMessageListener("dial-handler", this);
ppmm.addMessageListener("sms-handler", this);
ppmm.addMessageListener("mail-handler", this);
ppmm.addMessageListener("app-notification-send", AlertsHelper);
},
stop: function shell_stop() {
@ -609,8 +610,19 @@ var AlertsHelper = {
return;
let listener = this._listeners[detail.id];
let topic = detail.type == "desktop-notification-click" ? "alertclickcallback" : "alertfinished";
listener.observer.observe(null, topic, listener.cookie);
if (!listener)
return;
let topic = detail.type == "desktop-notification-click" ? "alertclickcallback"
: "alertfinished";
if (detail.id.startsWith("alert")) {
listener.observer.observe(null, topic, listener.cookie);
} else {
listener.mm.sendAsyncMessage("app-notification-return",
{ id: detail.id,
type: detail.type });
}
// we're done with this notification
if (topic === "alertfinished")
@ -623,23 +635,71 @@ var AlertsHelper = {
return id;
},
registerAppListener: function alertRegisterAppListener(id, mm, title, text,
manifestURL, imageURL) {
this._listeners[id] = {
mm: mm,
title: title,
text: text,
manifestURL: manifestURL,
imageURL: imageURL
};
},
showNotification: function alert_showNotification(imageUrl,
title,
text,
textClickable,
cookie,
id,
name,
manifestUrl) {
function send(appName, appIcon) {
shell.sendChromeEvent({
type: "desktop-notification",
id: id,
icon: imageUrl,
title: title,
text: text,
appName: appName,
appIcon: appIcon
});
}
// If we have a manifest URL, get the icon and title from the manifest
// to prevent spoofing.
if (manifestUrl && manifestUrl.length) {
let app = DOMApplicationRegistry.getAppByManifestURL(manifestUrl);
DOMApplicationRegistry.getManifestFor(app.origin, function(aManifest) {
let helper = new ManifestHelper(aManifest, app.origin);
send(helper.name, helper.iconURLForSize(128));
});
} else {
send(null, null);
}
},
showAlertNotification: function alert_showAlertNotification(imageUrl,
title,
text,
textClickable,
cookie,
alertListener,
name)
{
let id = this.registerListener(cookie, alertListener);
shell.sendChromeEvent({
type: "desktop-notification",
id: id,
icon: imageUrl,
title: title,
text: text
});
}
name) {
let id = this.registerListener(null, alertListener);
this.showNotification(imageUrl, title, text, textClickable, cookie,
id, name, null);
},
receiveMessage: function alert_receiveMessage(message) {
let data = message.data;
this.registerAppListener(data.id, message.target, data.title, data.text,
data.manifestURL, data.imageURL);
this.showNotification(data.imageURL, data.title, data.text,
data.textClickable, null,
data.id, null, data.manifestURL);
},
}
var WebappsHelper = {

View File

@ -1,26 +1,85 @@
/* 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/. */
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cc = Components.classes;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
return Cc["@mozilla.org/childprocessmessagemanager;1"]
.getService(Ci.nsIMessageSender);
});
// -----------------------------------------------------------------------
// Alerts Service
// -----------------------------------------------------------------------
function AlertsService() { }
function AlertsService() {
cpmm.addMessageListener("app-notification-return", this);
this._id = 0;
}
AlertsService.prototype = {
classID: Components.ID("{fe33c107-82a4-41d6-8c64-5353267e04c9}"),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService]),
QueryInterface: XPCOMUtils.generateQI([Ci.nsIAlertsService,
Ci.nsIAppNotificationService]),
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) {
// nsIAlertsService
showAlertNotification: function showAlertNotification(aImageUrl,
aTitle,
aText,
aTextClickable,
aCookie,
aAlertListener,
aName) {
let browser = Services.wm.getMostRecentWindow("navigator:browser");
browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName);
browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText,
aTextClickable, aCookie,
aAlertListener, aName);
},
// nsIAppNotificationService
_listeners: [],
receiveMessage: function receiveMessage(aMessage) {
let data = aMessage.data;
if (aMessage.name !== "app-notification-return" ||
!this._listeners[data.id]) {
return;
}
let obs = this._listeners[data.id];
let topic = data.type == "desktop-notification-click" ? "alertclickcallback"
: "alertfinished";
obs.observe(null, topic, null);
// we're done with this notification
if (topic === "alertfinished")
delete this._listeners[data.id];
},
// This method is called in the content process, so we remote the call
// to shell.js
showAppNotification: function showAppNotification(aImageURL,
aTitle,
aText,
aTextClickable,
aManifestURL,
aAlertListener) {
let id = "app-notif" + this._id++;
this._listeners[id] = aAlertListener;
cpmm.sendAsyncMessage("app-notification-send", {
imageURL: aImageURL,
title: aTitle,
text: aText,
textClickable: aTextClickable,
manifestURL: aManifestURL,
id: id
});
}
};

View File

@ -64,7 +64,6 @@
#include "nsIDOMTouchEvent.h"
#include "nsIInlineEventHandlers.h"
#include "nsWrapperCacheInlines.h"
#include "nsIDOMApplicationRegistry.h"
#include "nsIIdleObserver.h"
#include "nsIDOMWakeLock.h"
@ -1111,6 +1110,7 @@ protected:
friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils;
friend class PostMessageEvent;
friend class nsDOMDesktopNotification;
static WindowByIdTable* sWindowsById;
static bool sWarnedAboutWindowInternal;

View File

@ -6,7 +6,7 @@
interface nsIDOMEventListener;
interface nsIDOMDesktopNotification;
interface nsIObserver;
[scriptable, uuid(CCEA6185-0A3D-45AB-9058-1004DD4B8C50)]
interface nsIDOMDesktopNotificationCenter : nsISupports
@ -25,3 +25,15 @@ interface nsIDOMDesktopNotification : nsISupports
[implicit_jscontext] attribute jsval onclick;
[implicit_jscontext] attribute jsval onclose;
};
// Notification service that also provides the manifest URL
[scriptable, uuid(7fb4f0f9-ff5b-4620-8e1b-d82d723605af)]
interface nsIAppNotificationService : nsISupports
{
void showAppNotification(in AString imageUrl,
in AString title,
in AString text,
[optional] in boolean textClickable,
[optional] in AString manifestURL,
[optional] in nsIObserver alertListener);
};

View File

@ -10,6 +10,9 @@
#include "mozilla/dom/PBrowserChild.h"
#include "TabChild.h"
#include "mozilla/Preferences.h"
#include "nsGlobalWindow.h"
#include "nsIAppsService.h"
#include "nsIDOMDesktopNotification.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -27,13 +30,32 @@ NS_IMPL_ISUPPORTS1(AlertServiceObserver, nsIObserver)
nsresult
nsDOMDesktopNotification::PostDesktopNotification()
{
if (!mObserver)
mObserver = new AlertServiceObserver(this);
#ifdef MOZ_B2G
nsCOMPtr<nsIAppNotificationService> appNotifier =
do_GetService("@mozilla.org/system-alerts-service;1");
if (appNotifier) {
nsCOMPtr<nsPIDOMWindow> window = GetOwner();
uint32_t appId = (window.get())->GetDoc()->NodePrincipal()->GetAppId();
if (appId != nsIScriptSecurityManager::UNKNOWN_APP_ID) {
nsCOMPtr<nsIAppsService> appsService = do_GetService("@mozilla.org/AppsService;1");
nsString manifestUrl = EmptyString();
appsService->GetManifestURLByLocalId(appId, manifestUrl);
return appNotifier->ShowAppNotification(mIconURL, mTitle, mDescription,
true,
manifestUrl,
mObserver);
}
}
#endif
nsCOMPtr<nsIAlertsService> alerts = do_GetService("@mozilla.org/alerts-service;1");
if (!alerts)
return NS_ERROR_NOT_IMPLEMENTED;
if (!mObserver)
mObserver = new AlertServiceObserver(this);
return alerts->ShowAlertNotification(mIconURL, mTitle, mDescription,
true,
EmptyString(),