author | Fabrice Desré <fabrice@mozilla.com> |
Wed, 28 Nov 2012 22:36:15 -0800 | |
changeset 114466 | 60378fae4e94b39e96841cc6c44fcd2a7cc6b591 |
parent 114465 | 602add2d02e6fcf9913acfac62eb0d24970c37c6 |
child 114467 | 14e5a7d93bc07794d0d2db2e6fe468424e394a36 |
push id | 23917 |
push user | emorley@mozilla.com |
push date | Thu, 29 Nov 2012 14:20:29 +0000 |
treeherder | mozilla-central@c72d38e7a212 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | wchen |
bugs | 778668 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -258,16 +258,17 @@ var shell = { this.contentBrowser.src = homeURL; this.isHomeLoaded = false; ppmm.addMessageListener("content-handler", this); 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() { window.removeEventListener('keydown', this, true); window.removeEventListener('keypress', this, true); window.removeEventListener('keyup', this, true); window.removeEventListener('MozApplicationManifest', this); window.removeEventListener('mozfullscreenchange', this); @@ -604,47 +605,106 @@ var AlertsHelper = { _listeners: {}, _count: 0, handleEvent: function alert_handleEvent(detail) { if (!detail || !detail.id) 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") delete this._listeners[detail.id]; }, registerListener: function alert_registerListener(cookie, alertListener) { let id = "alert" + this._count++; this._listeners[id] = { observer: alertListener, cookie: cookie }; 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 = { _installers: {}, _count: 0, init: function webapps_init() { Services.obs.addObserver(this, "webapps-launch", false);
--- a/b2g/components/AlertsService.js +++ b/b2g/components/AlertsService.js @@ -1,27 +1,86 @@ /* 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]), + + // 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); + }, + + // nsIAppNotificationService + _listeners: [], + + receiveMessage: function receiveMessage(aMessage) { + let data = aMessage.data; + if (aMessage.name !== "app-notification-return" || + !this._listeners[data.id]) { + return; + } - showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName) { - let browser = Services.wm.getMostRecentWindow("navigator:browser"); - browser.AlertsHelper.showAlertNotification(aImageUrl, aTitle, aText, aTextClickable, aCookie, aAlertListener, aName); + 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 + }); } }; this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AlertsService]);
--- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -59,17 +59,16 @@ #include "nsIContent.h" #include "nsIIDBFactory.h" #include "nsFrameMessageManager.h" #include "mozilla/LinkedList.h" #include "mozilla/TimeStamp.h" #include "nsIDOMTouchEvent.h" #include "nsIInlineEventHandlers.h" #include "nsWrapperCacheInlines.h" -#include "nsIDOMApplicationRegistry.h" #include "nsIIdleObserver.h" #include "nsIDOMWakeLock.h" // JS includes #include "jsapi.h" #ifdef MOZ_B2G #include "nsIDOMWindowB2G.h" @@ -1106,16 +1105,17 @@ protected: nsTHashtable<nsPtrHashKey<nsDOMEventTargetHelper> > mEventTargetObjects; nsTArray<uint32_t> mEnabledSensors; friend class nsDOMScriptableHelper; friend class nsDOMWindowUtils; friend class PostMessageEvent; + friend class nsDOMDesktopNotification; static WindowByIdTable* sWindowsById; static bool sWarnedAboutWindowInternal; }; /* * nsGlobalChromeWindow inherits from nsGlobalWindow. It is the global * object created for a Chrome Window only.
--- a/dom/interfaces/notification/nsIDOMDesktopNotification.idl +++ b/dom/interfaces/notification/nsIDOMDesktopNotification.idl @@ -1,17 +1,17 @@ /* 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/. */ #include "domstubs.idl" interface nsIDOMEventListener; interface nsIDOMDesktopNotification; - +interface nsIObserver; [scriptable, uuid(CCEA6185-0A3D-45AB-9058-1004DD4B8C50)] interface nsIDOMDesktopNotificationCenter : nsISupports { nsIDOMDesktopNotification createNotification(in DOMString title, in DOMString description, [optional] in DOMString iconURL); }; @@ -20,8 +20,20 @@ interface nsIDOMDesktopNotificationCente [scriptable, uuid(77bc6adc-77d6-4b29-9844-7eaac25e995d)] interface nsIDOMDesktopNotification : nsISupports { void show(); [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); +};
--- a/dom/src/notification/nsDesktopNotification.cpp +++ b/dom/src/notification/nsDesktopNotification.cpp @@ -5,16 +5,19 @@ #include "nsDesktopNotification.h" #include "nsContentPermissionHelper.h" #include "nsXULAppAPI.h" #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; /* ------------------------------------------------------------------------ */ /* AlertServiceObserver */ /* ------------------------------------------------------------------------ */ @@ -22,23 +25,42 @@ NS_IMPL_ISUPPORTS1(AlertServiceObserver, /* ------------------------------------------------------------------------ */ /* nsDesktopNotification */ /* ------------------------------------------------------------------------ */ 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(), mObserver, EmptyString()); } DOMCI_DATA(DesktopNotification, nsDOMDesktopNotification)