зеркало из https://github.com/mozilla/gecko-dev.git
Bug 814074 - Send a system message to the application when the application is not running anymore but waits for a notification. r=fabrice. a=blocking-basecamp.
This commit is contained in:
Родитель
a9d50d2c9b
Коммит
f4f353addb
|
@ -73,6 +73,10 @@ function getContentWindow() {
|
|||
return shell.contentBrowser.contentWindow;
|
||||
}
|
||||
|
||||
function debug(str) {
|
||||
dump(' -*- Shell.js: ' + str + '\n');
|
||||
}
|
||||
|
||||
var shell = {
|
||||
|
||||
get CrashSubmit() {
|
||||
|
@ -611,41 +615,62 @@ var AlertsHelper = {
|
|||
if (!detail || !detail.id)
|
||||
return;
|
||||
|
||||
let listener = this._listeners[detail.id];
|
||||
let uid = detail.id;
|
||||
let listener = this._listeners[uid];
|
||||
if (!listener)
|
||||
return;
|
||||
|
||||
let topic = detail.type == "desktop-notification-click" ? "alertclickcallback"
|
||||
: "alertfinished";
|
||||
|
||||
if (detail.id.startsWith("alert")) {
|
||||
if (uid.startsWith("app-notif")) {
|
||||
listener.mm.sendAsyncMessage("app-notification-return", {
|
||||
uid: uid,
|
||||
topic: topic,
|
||||
target: listener.target
|
||||
});
|
||||
} else if (uid.startsWith("alert")) {
|
||||
try {
|
||||
listener.observer.observe(null, topic, listener.cookie);
|
||||
} else {
|
||||
listener.mm.sendAsyncMessage("app-notification-return",
|
||||
{ id: detail.id,
|
||||
type: detail.type });
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
// we're done with this notification
|
||||
if (topic === "alertfinished")
|
||||
delete this._listeners[detail.id];
|
||||
if (topic === "alertfinished") {
|
||||
delete this._listeners[uid];
|
||||
}
|
||||
},
|
||||
|
||||
registerListener: function alert_registerListener(cookie, alertListener) {
|
||||
let id = "alert" + this._count++;
|
||||
this._listeners[id] = { observer: alertListener, cookie: cookie };
|
||||
return id;
|
||||
let uid = "alert" + this._count++;
|
||||
this._listeners[uid] = { observer: alertListener, cookie: cookie };
|
||||
return uid;
|
||||
},
|
||||
|
||||
registerAppListener: function alertRegisterAppListener(id, mm, title, text,
|
||||
manifestURL, imageURL) {
|
||||
this._listeners[id] = {
|
||||
mm: mm,
|
||||
title: title,
|
||||
text: text,
|
||||
manifestURL: manifestURL,
|
||||
imageURL: imageURL
|
||||
};
|
||||
registerAppListener: function alert_registerAppListener(uid, listener) {
|
||||
this._listeners[uid] = listener;
|
||||
|
||||
let app = DOMApplicationRegistry.getAppByManifestURL(listener.manifestURL);
|
||||
DOMApplicationRegistry.getManifestFor(app.origin, function(manifest) {
|
||||
let helper = new ManifestHelper(manifest, app.origin);
|
||||
let getNotificationURLFor = function(messages) {
|
||||
if (!messages)
|
||||
return null;
|
||||
|
||||
for (let i = 0; i < messages.length; i++) {
|
||||
let message = messages[i];
|
||||
if (message === "notification") {
|
||||
return helper.fullLaunchPath();
|
||||
} else if ("notification" in message) {
|
||||
return helper.resolveFromOrigin(message["notification"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listener.target = getNotificationURLFor(manifest.messages);
|
||||
|
||||
// Bug 816944 - Support notification messages for entry_points.
|
||||
});
|
||||
},
|
||||
|
||||
showNotification: function alert_showNotification(imageUrl,
|
||||
|
@ -653,13 +678,13 @@ var AlertsHelper = {
|
|||
text,
|
||||
textClickable,
|
||||
cookie,
|
||||
id,
|
||||
uid,
|
||||
name,
|
||||
manifestUrl) {
|
||||
function send(appName, appIcon) {
|
||||
shell.sendChromeEvent({
|
||||
type: "desktop-notification",
|
||||
id: id,
|
||||
id: uid,
|
||||
icon: imageUrl,
|
||||
title: title,
|
||||
text: text,
|
||||
|
@ -668,17 +693,17 @@ var AlertsHelper = {
|
|||
});
|
||||
}
|
||||
|
||||
if (!manifestUrl || !manifestUrl.length) {
|
||||
send(null, null);
|
||||
}
|
||||
|
||||
// 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,
|
||||
|
@ -688,19 +713,25 @@ var AlertsHelper = {
|
|||
cookie,
|
||||
alertListener,
|
||||
name) {
|
||||
let id = this.registerListener(null, alertListener);
|
||||
let uid = this.registerListener(null, alertListener);
|
||||
this.showNotification(imageUrl, title, text, textClickable, cookie,
|
||||
id, name, null);
|
||||
uid, name, null);
|
||||
},
|
||||
|
||||
receiveMessage: function alert_receiveMessage(message) {
|
||||
let data = message.data;
|
||||
let listener = {
|
||||
mm: message.target,
|
||||
title: data.title,
|
||||
text: data.text,
|
||||
manifestURL: data.manifestURL,
|
||||
imageURL: data.imageURL
|
||||
}
|
||||
this.registerAppListener(data.uid, listener);
|
||||
|
||||
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);
|
||||
data.uid, null, data.manifestURL);
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -9,18 +9,29 @@ const Cc = Components.classes;
|
|||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gSystemMessenger",
|
||||
"@mozilla.org/system-message-internal;1",
|
||||
"nsISystemMessagesInternal");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "uuidGenerator",
|
||||
"@mozilla.org/uuid-generator;1",
|
||||
"nsIUUIDGenerator");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "cpmm", function() {
|
||||
return Cc["@mozilla.org/childprocessmessagemanager;1"]
|
||||
.getService(Ci.nsIMessageSender);
|
||||
});
|
||||
|
||||
function debug(str) {
|
||||
dump("=*= AlertsService.js : " + str + "\n");
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Alerts Service
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
function AlertsService() {
|
||||
cpmm.addMessageListener("app-notification-return", this);
|
||||
this._id = 0;
|
||||
}
|
||||
|
||||
AlertsService.prototype = {
|
||||
|
@ -43,43 +54,67 @@ AlertsService.prototype = {
|
|||
},
|
||||
|
||||
// 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;
|
||||
let uid = "app-notif-" + uuidGenerator.generateUUID();
|
||||
|
||||
this._listeners[uid] = {
|
||||
observer: aAlertListener,
|
||||
title: aTitle,
|
||||
text: aText,
|
||||
manifestURL: aManifestURL,
|
||||
imageURL: aImageURL
|
||||
};
|
||||
|
||||
cpmm.sendAsyncMessage("app-notification-send", {
|
||||
imageURL: aImageURL,
|
||||
title: aTitle,
|
||||
text: aText,
|
||||
textClickable: aTextClickable,
|
||||
manifestURL: aManifestURL,
|
||||
id: id
|
||||
uid: uid
|
||||
});
|
||||
},
|
||||
|
||||
// AlertsService.js custom implementation
|
||||
_listeners: [],
|
||||
|
||||
receiveMessage: function receiveMessage(aMessage) {
|
||||
let data = aMessage.data;
|
||||
let listener = this._listeners[data.uid];
|
||||
if (aMessage.name !== "app-notification-return" || !listener) {
|
||||
return;
|
||||
}
|
||||
|
||||
let topic = data.topic;
|
||||
|
||||
try {
|
||||
listener.observer.observe(null, topic, null);
|
||||
} catch (e) {
|
||||
// It seems like there is no callbacks anymore, forward the click on
|
||||
// notification via a system message containing the title/text/icon of
|
||||
// the notification so the app get a change to react.
|
||||
if (data.target) {
|
||||
gSystemMessenger.sendMessage("notification", {
|
||||
title: listener.title,
|
||||
body: listener.text,
|
||||
imageURL: listener.imageURL
|
||||
},
|
||||
Services.io.newURI(data.target, null, null),
|
||||
Services.io.newURI(listener.manifestURL, null, null));
|
||||
}
|
||||
|
||||
cpmm.sendAsyncMessage("app-notification-sysmsg-request", listener);
|
||||
}
|
||||
|
||||
// we're done with this notification
|
||||
if (topic === "alertfinished") {
|
||||
delete this._listeners[data.uid];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -170,9 +170,15 @@ class AlertServiceObserver: public nsIObserver
|
|||
const char *aTopic,
|
||||
const PRUnichar *aData)
|
||||
{
|
||||
|
||||
// forward to parent
|
||||
if (mNotification)
|
||||
if (mNotification) {
|
||||
#ifdef MOZ_B2G
|
||||
if (NS_FAILED(mNotification->CheckInnerWindowCorrectness()))
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
#endif
|
||||
mNotification->HandleAlertServiceNotification(aTopic);
|
||||
}
|
||||
return NS_OK;
|
||||
};
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче