зеркало из https://github.com/mozilla/gecko-dev.git
Bug 899585 - Add custom data support in the Notification constructor r=baku
This commit is contained in:
Родитель
10638101c5
Коммит
29ee85a120
|
@ -149,7 +149,8 @@ let AlertsHelper = {
|
||||||
dir: listener.dir,
|
dir: listener.dir,
|
||||||
id: listener.id,
|
id: listener.id,
|
||||||
tag: listener.tag,
|
tag: listener.tag,
|
||||||
timestamp: listener.timestamp
|
timestamp: listener.timestamp,
|
||||||
|
data: listener.dataObj
|
||||||
},
|
},
|
||||||
Services.io.newURI(listener.target, null, null),
|
Services.io.newURI(listener.target, null, null),
|
||||||
Services.io.newURI(listener.manifestURL, null, null)
|
Services.io.newURI(listener.manifestURL, null, null)
|
||||||
|
@ -199,8 +200,32 @@ let AlertsHelper = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
deserializeStructuredClone: function(dataString) {
|
||||||
|
if (!dataString) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let scContainer = Cc["@mozilla.org/docshell/structured-clone-container;1"].
|
||||||
|
createInstance(Ci.nsIStructuredCloneContainer);
|
||||||
|
|
||||||
|
// The maximum supported structured-clone serialization format version
|
||||||
|
// as defined in "js/public/StructuredClone.h"
|
||||||
|
let JS_STRUCTURED_CLONE_VERSION = 4;
|
||||||
|
scContainer.initFromBase64(dataString, JS_STRUCTURED_CLONE_VERSION);
|
||||||
|
let dataObj = scContainer.deserializeToVariant();
|
||||||
|
|
||||||
|
// We have to check whether dataObj contains DOM objects (supported by
|
||||||
|
// nsIStructuredCloneContainer, but not by Cu.cloneInto), e.g. ImageData.
|
||||||
|
// After the structured clone callback systems will be unified, we'll not
|
||||||
|
// have to perform this check anymore.
|
||||||
|
try {
|
||||||
|
let data = Cu.cloneInto(dataObj, {});
|
||||||
|
} catch(e) { dataObj = null; }
|
||||||
|
|
||||||
|
return dataObj;
|
||||||
|
},
|
||||||
|
|
||||||
showNotification: function(imageURL, title, text, textClickable, cookie,
|
showNotification: function(imageURL, title, text, textClickable, cookie,
|
||||||
uid, bidi, lang, manifestURL, timestamp) {
|
uid, bidi, lang, dataObj, manifestURL, timestamp) {
|
||||||
function send(appName, appIcon) {
|
function send(appName, appIcon) {
|
||||||
SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, {
|
SystemAppProxy._sendCustomEvent(kMozChromeNotificationEvent, {
|
||||||
type: kDesktopNotification,
|
type: kDesktopNotification,
|
||||||
|
@ -213,7 +238,8 @@ let AlertsHelper = {
|
||||||
appName: appName,
|
appName: appName,
|
||||||
appIcon: appIcon,
|
appIcon: appIcon,
|
||||||
manifestURL: manifestURL,
|
manifestURL: manifestURL,
|
||||||
timestamp: timestamp
|
timestamp: timestamp,
|
||||||
|
data: dataObj
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,15 +264,17 @@ let AlertsHelper = {
|
||||||
currentListener.observer.observe(null, kTopicAlertFinished, currentListener.cookie);
|
currentListener.observer.observe(null, kTopicAlertFinished, currentListener.cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let dataObj = this.deserializeStructuredClone(data.dataStr);
|
||||||
this.registerListener(data.name, data.cookie, data.alertListener);
|
this.registerListener(data.name, data.cookie, data.alertListener);
|
||||||
this.showNotification(data.imageURL, data.title, data.text,
|
this.showNotification(data.imageURL, data.title, data.text,
|
||||||
data.textClickable, data.cookie, data.name, data.bidi,
|
data.textClickable, data.cookie, data.name, data.bidi,
|
||||||
data.lang, null);
|
data.lang, dataObj, null);
|
||||||
},
|
},
|
||||||
|
|
||||||
showAppNotification: function(aMessage) {
|
showAppNotification: function(aMessage) {
|
||||||
let data = aMessage.data;
|
let data = aMessage.data;
|
||||||
let details = data.details;
|
let details = data.details;
|
||||||
|
let dataObject = this.deserializeStructuredClone(details.data);
|
||||||
let listener = {
|
let listener = {
|
||||||
mm: aMessage.target,
|
mm: aMessage.target,
|
||||||
title: data.title,
|
title: data.title,
|
||||||
|
@ -257,12 +285,14 @@ let AlertsHelper = {
|
||||||
id: details.id || undefined,
|
id: details.id || undefined,
|
||||||
dir: details.dir || undefined,
|
dir: details.dir || undefined,
|
||||||
tag: details.tag || undefined,
|
tag: details.tag || undefined,
|
||||||
timestamp: details.timestamp || undefined
|
timestamp: details.timestamp || undefined,
|
||||||
|
dataObj: dataObject || undefined
|
||||||
};
|
};
|
||||||
this.registerAppListener(data.uid, listener);
|
this.registerAppListener(data.uid, listener);
|
||||||
this.showNotification(data.imageURL, data.title, data.text,
|
this.showNotification(data.imageURL, data.title, data.text,
|
||||||
details.textClickable, null, data.uid, details.dir,
|
details.textClickable, null, data.uid, details.dir,
|
||||||
details.lang, details.manifestURL, details.timestamp);
|
details.lang, dataObject, details.manifestURL,
|
||||||
|
details.timestamp);
|
||||||
},
|
},
|
||||||
|
|
||||||
closeAlert: function(name) {
|
closeAlert: function(name) {
|
||||||
|
|
|
@ -69,7 +69,7 @@ AlertsService.prototype = {
|
||||||
// nsIAlertsService
|
// nsIAlertsService
|
||||||
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
|
showAlertNotification: function(aImageUrl, aTitle, aText, aTextClickable,
|
||||||
aCookie, aAlertListener, aName, aBidi,
|
aCookie, aAlertListener, aName, aBidi,
|
||||||
aLang) {
|
aLang, aDataStr) {
|
||||||
cpmm.sendAsyncMessage(kMessageAlertNotificationSend, {
|
cpmm.sendAsyncMessage(kMessageAlertNotificationSend, {
|
||||||
imageURL: aImageUrl,
|
imageURL: aImageUrl,
|
||||||
title: aTitle,
|
title: aTitle,
|
||||||
|
@ -79,7 +79,8 @@ AlertsService.prototype = {
|
||||||
listener: aAlertListener,
|
listener: aAlertListener,
|
||||||
id: aName,
|
id: aName,
|
||||||
dir: aBidi,
|
dir: aBidi,
|
||||||
lang: aLang
|
lang: aLang,
|
||||||
|
dataStr: aDataStr
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -95,6 +96,7 @@ AlertsService.prototype = {
|
||||||
let uid = (aDetails.id == "") ?
|
let uid = (aDetails.id == "") ?
|
||||||
"app-notif-" + uuidGenerator.generateUUID() : aDetails.id;
|
"app-notif-" + uuidGenerator.generateUUID() : aDetails.id;
|
||||||
|
|
||||||
|
let dataObj = this.deserializeStructuredClone(aDetails.data);
|
||||||
this._listeners[uid] = {
|
this._listeners[uid] = {
|
||||||
observer: aAlertListener,
|
observer: aAlertListener,
|
||||||
title: aTitle,
|
title: aTitle,
|
||||||
|
@ -106,7 +108,8 @@ AlertsService.prototype = {
|
||||||
dbId: aDetails.dbId || undefined,
|
dbId: aDetails.dbId || undefined,
|
||||||
dir: aDetails.dir || undefined,
|
dir: aDetails.dir || undefined,
|
||||||
tag: aDetails.tag || undefined,
|
tag: aDetails.tag || undefined,
|
||||||
timestamp: aDetails.timestamp || undefined
|
timestamp: aDetails.timestamp || undefined,
|
||||||
|
dataObj: dataObj || undefined
|
||||||
};
|
};
|
||||||
|
|
||||||
cpmm.sendAsyncMessage(kMessageAppNotificationSend, {
|
cpmm.sendAsyncMessage(kMessageAppNotificationSend, {
|
||||||
|
@ -151,7 +154,8 @@ AlertsService.prototype = {
|
||||||
id: listener.id,
|
id: listener.id,
|
||||||
tag: listener.tag,
|
tag: listener.tag,
|
||||||
dbId: listener.dbId,
|
dbId: listener.dbId,
|
||||||
timestamp: listener.timestamp
|
timestamp: listener.timestamp,
|
||||||
|
data: listener.dataObj || undefined,
|
||||||
},
|
},
|
||||||
Services.io.newURI(data.target, null, null),
|
Services.io.newURI(data.target, null, null),
|
||||||
Services.io.newURI(listener.manifestURL, null, null)
|
Services.io.newURI(listener.manifestURL, null, null)
|
||||||
|
@ -167,6 +171,30 @@ AlertsService.prototype = {
|
||||||
}
|
}
|
||||||
delete this._listeners[data.uid];
|
delete this._listeners[data.uid];
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
deserializeStructuredClone: function(dataString) {
|
||||||
|
if (!dataString) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let scContainer = Cc["@mozilla.org/docshell/structured-clone-container;1"].
|
||||||
|
createInstance(Ci.nsIStructuredCloneContainer);
|
||||||
|
|
||||||
|
// The maximum supported structured-clone serialization format version
|
||||||
|
// as defined in "js/public/StructuredClone.h"
|
||||||
|
let JS_STRUCTURED_CLONE_VERSION = 4;
|
||||||
|
scContainer.initFromBase64(dataString, JS_STRUCTURED_CLONE_VERSION);
|
||||||
|
let dataObj = scContainer.deserializeToVariant();
|
||||||
|
|
||||||
|
// We have to check whether dataObj contains DOM objects (supported by
|
||||||
|
// nsIStructuredCloneContainer, but not by Cu.cloneInto), e.g. ImageData.
|
||||||
|
// After the structured clone callback systems will be unified, we'll not
|
||||||
|
// have to perform this check anymore.
|
||||||
|
try {
|
||||||
|
let data = Cu.cloneInto(dataObj, {});
|
||||||
|
} catch(e) { dataObj = null; }
|
||||||
|
|
||||||
|
return dataObj;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ interface nsIStructuredCloneContainer : nsISupports
|
||||||
void initFromBase64(in AString aData,in unsigned long aFormatVersion);
|
void initFromBase64(in AString aData,in unsigned long aFormatVersion);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize the object this conatiner holds, returning it wrapped as
|
* Deserialize the object this container holds, returning it wrapped as
|
||||||
* an nsIVariant.
|
* an nsIVariant.
|
||||||
*/
|
*/
|
||||||
[implicit_jscontext]
|
[implicit_jscontext]
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
#include "domstubs.idl"
|
#include "domstubs.idl"
|
||||||
|
|
||||||
[scriptable, uuid(fb089720-1c5c-11e3-b773-0800200c9a66)]
|
[scriptable, uuid(9b12f566-2c7f-48ef-990d-e5092a71d11e)]
|
||||||
interface nsINotificationStorageCallback : nsISupports
|
interface nsINotificationStorageCallback : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -26,7 +26,8 @@ interface nsINotificationStorageCallback : nsISupports
|
||||||
in DOMString lang,
|
in DOMString lang,
|
||||||
in DOMString body,
|
in DOMString body,
|
||||||
in DOMString tag,
|
in DOMString tag,
|
||||||
in DOMString icon);
|
in DOMString icon,
|
||||||
|
in DOMString data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function used to notify C++ the we have returned
|
* Callback function used to notify C++ the we have returned
|
||||||
|
@ -39,7 +40,7 @@ interface nsINotificationStorageCallback : nsISupports
|
||||||
/**
|
/**
|
||||||
* Interface for notification persistence layer.
|
* Interface for notification persistence layer.
|
||||||
*/
|
*/
|
||||||
[scriptable, uuid(cc4656d7-2a2a-47f1-8016-55891e833d64)]
|
[scriptable, uuid(1be733d9-d614-43f2-9fd4-8f573a33b215)]
|
||||||
interface nsINotificationStorage : nsISupports
|
interface nsINotificationStorage : nsISupports
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -68,7 +69,8 @@ interface nsINotificationStorage : nsISupports
|
||||||
in DOMString body,
|
in DOMString body,
|
||||||
in DOMString tag,
|
in DOMString tag,
|
||||||
in DOMString icon,
|
in DOMString icon,
|
||||||
in DOMString alertName);
|
in DOMString alertName,
|
||||||
|
in DOMString data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve a list of notifications.
|
* Retrieve a list of notifications.
|
||||||
|
|
|
@ -3361,6 +3361,7 @@ ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsStri
|
||||||
const nsString& aText, const bool& aTextClickable,
|
const nsString& aText, const bool& aTextClickable,
|
||||||
const nsString& aCookie, const nsString& aName,
|
const nsString& aCookie, const nsString& aName,
|
||||||
const nsString& aBidi, const nsString& aLang,
|
const nsString& aBidi, const nsString& aLang,
|
||||||
|
const nsString& aData,
|
||||||
const IPC::Principal& aPrincipal)
|
const IPC::Principal& aPrincipal)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_CHILD_PERMISSIONS
|
#ifdef MOZ_CHILD_PERMISSIONS
|
||||||
|
@ -3374,7 +3375,8 @@ ContentParent::RecvShowAlertNotification(const nsString& aImageUrl, const nsStri
|
||||||
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
|
nsCOMPtr<nsIAlertsService> sysAlerts(do_GetService(NS_ALERTSERVICE_CONTRACTID));
|
||||||
if (sysAlerts) {
|
if (sysAlerts) {
|
||||||
sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable,
|
sysAlerts->ShowAlertNotification(aImageUrl, aTitle, aText, aTextClickable,
|
||||||
aCookie, this, aName, aBidi, aLang, aPrincipal);
|
aCookie, this, aName, aBidi, aLang,
|
||||||
|
aData, aPrincipal);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -530,6 +530,7 @@ private:
|
||||||
const nsString& aText, const bool& aTextClickable,
|
const nsString& aText, const bool& aTextClickable,
|
||||||
const nsString& aCookie, const nsString& aName,
|
const nsString& aCookie, const nsString& aName,
|
||||||
const nsString& aBidi, const nsString& aLang,
|
const nsString& aBidi, const nsString& aLang,
|
||||||
|
const nsString& aData,
|
||||||
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
|
const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool RecvCloseAlert(const nsString& aName,
|
virtual bool RecvCloseAlert(const nsString& aName,
|
||||||
|
|
|
@ -542,6 +542,7 @@ parent:
|
||||||
nsString name,
|
nsString name,
|
||||||
nsString bidi,
|
nsString bidi,
|
||||||
nsString lang,
|
nsString lang,
|
||||||
|
nsString data,
|
||||||
Principal principal);
|
Principal principal);
|
||||||
|
|
||||||
CloseAlert(nsString name, Principal principal);
|
CloseAlert(nsString name, Principal principal);
|
||||||
|
|
|
@ -60,7 +60,8 @@ ChromeNotifications.prototype = {
|
||||||
lang: notification.lang,
|
lang: notification.lang,
|
||||||
tag: notification.tag,
|
tag: notification.tag,
|
||||||
dbId: notification.id,
|
dbId: notification.id,
|
||||||
timestamp: notification.timestamp
|
timestamp: notification.timestamp,
|
||||||
|
data: notification.data
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
resentNotifications++;
|
resentNotifications++;
|
||||||
|
|
|
@ -111,6 +111,7 @@ DesktopNotification::PostDesktopNotification()
|
||||||
uniqueName,
|
uniqueName,
|
||||||
NS_LITERAL_STRING("auto"),
|
NS_LITERAL_STRING("auto"),
|
||||||
EmptyString(),
|
EmptyString(),
|
||||||
|
EmptyString(),
|
||||||
principal);
|
principal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include "mozilla/dom/Notification.h"
|
#include "mozilla/dom/Notification.h"
|
||||||
#include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
|
#include "mozilla/dom/AppNotificationServiceOptionsBinding.h"
|
||||||
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
#include "mozilla/dom/OwningNonNull.h"
|
#include "mozilla/dom/OwningNonNull.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
@ -16,10 +17,12 @@
|
||||||
#include "nsIPermissionManager.h"
|
#include "nsIPermissionManager.h"
|
||||||
#include "nsIUUIDGenerator.h"
|
#include "nsIUUIDGenerator.h"
|
||||||
#include "nsServiceManagerUtils.h"
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsStructuredCloneContainer.h"
|
||||||
#include "nsToolkitCompsCID.h"
|
#include "nsToolkitCompsCID.h"
|
||||||
#include "nsGlobalWindow.h"
|
#include "nsGlobalWindow.h"
|
||||||
#include "nsDOMJSUtils.h"
|
#include "nsDOMJSUtils.h"
|
||||||
#include "nsIScriptSecurityManager.h"
|
#include "nsIScriptSecurityManager.h"
|
||||||
|
#include "nsIXPConnect.h"
|
||||||
#include "mozilla/dom/PermissionMessageUtils.h"
|
#include "mozilla/dom/PermissionMessageUtils.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
#include "nsContentPermissionHelper.h"
|
#include "nsContentPermissionHelper.h"
|
||||||
|
@ -57,11 +60,12 @@ public:
|
||||||
const nsAString& aBody,
|
const nsAString& aBody,
|
||||||
const nsAString& aTag,
|
const nsAString& aTag,
|
||||||
const nsAString& aIcon,
|
const nsAString& aIcon,
|
||||||
|
const nsAString& aData,
|
||||||
JSContext* aCx)
|
JSContext* aCx)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!aID.IsEmpty());
|
MOZ_ASSERT(!aID.IsEmpty());
|
||||||
|
|
||||||
NotificationOptions options;
|
RootedDictionary<NotificationOptions> options(aCx);
|
||||||
options.mDir = Notification::StringToDirection(nsString(aDir));
|
options.mDir = Notification::StringToDirection(nsString(aDir));
|
||||||
options.mLang = aLang;
|
options.mLang = aLang;
|
||||||
options.mBody = aBody;
|
options.mBody = aBody;
|
||||||
|
@ -71,6 +75,12 @@ public:
|
||||||
aID,
|
aID,
|
||||||
aTitle,
|
aTitle,
|
||||||
options);
|
options);
|
||||||
|
ErrorResult rv;
|
||||||
|
notification->InitFromBase64(aCx, aData, rv);
|
||||||
|
if (rv.Failed()) {
|
||||||
|
return rv.ErrorCode();
|
||||||
|
}
|
||||||
|
|
||||||
JSAutoCompartment ac(aCx, mGlobal);
|
JSAutoCompartment ac(aCx, mGlobal);
|
||||||
JS::Rooted<JSObject*> element(aCx, notification->WrapObject(aCx));
|
JS::Rooted<JSObject*> element(aCx, notification->WrapObject(aCx));
|
||||||
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(element, NS_ERROR_FAILURE);
|
||||||
|
@ -371,7 +381,7 @@ NotificationObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
Notification::Notification(const nsAString& aID, const nsAString& aTitle, const nsAString& aBody,
|
Notification::Notification(const nsAString& aID, const nsAString& aTitle, const nsAString& aBody,
|
||||||
NotificationDirection aDir, const nsAString& aLang,
|
NotificationDirection aDir, const nsAString& aLang,
|
||||||
const nsAString& aTag, const nsAString& aIconUrl,
|
const nsAString& aTag, const nsAString& aIconUrl,
|
||||||
nsPIDOMWindow* aWindow)
|
nsPIDOMWindow* aWindow)
|
||||||
: DOMEventTargetHelper(aWindow),
|
: DOMEventTargetHelper(aWindow),
|
||||||
mID(aID), mTitle(aTitle), mBody(aBody), mDir(aDir), mLang(aLang),
|
mID(aID), mTitle(aTitle), mBody(aBody), mDir(aDir), mLang(aLang),
|
||||||
mTag(aTag), mIconUrl(aIconUrl), mIsClosed(false)
|
mTag(aTag), mIconUrl(aIconUrl), mIsClosed(false)
|
||||||
|
@ -404,11 +414,19 @@ Notification::Constructor(const GlobalObject& aGlobal,
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports());
|
||||||
MOZ_ASSERT(window, "Window should not be null.");
|
MOZ_ASSERT(window, "Window should not be null.");
|
||||||
|
|
||||||
nsRefPtr<Notification> notification = CreateInternal(window,
|
nsRefPtr<Notification> notification = CreateInternal(window,
|
||||||
EmptyString(),
|
EmptyString(),
|
||||||
aTitle,
|
aTitle,
|
||||||
aOptions);
|
aOptions);
|
||||||
|
|
||||||
|
// Make a structured clone of the aOptions.mData object
|
||||||
|
JS::Rooted<JS::Value> data(aGlobal.Context(), aOptions.mData);
|
||||||
|
notification->InitFromJSVal(aGlobal.Context(), data, aRv);
|
||||||
|
if (aRv.Failed()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Queue a task to show the notification.
|
// Queue a task to show the notification.
|
||||||
nsCOMPtr<nsIRunnable> showNotificationTask =
|
nsCOMPtr<nsIRunnable> showNotificationTask =
|
||||||
new NotificationTask(notification, NotificationTask::eShow);
|
new NotificationTask(notification, NotificationTask::eShow);
|
||||||
|
@ -435,6 +453,13 @@ Notification::Constructor(const GlobalObject& aGlobal,
|
||||||
nsString alertName;
|
nsString alertName;
|
||||||
notification->GetAlertName(alertName);
|
notification->GetAlertName(alertName);
|
||||||
|
|
||||||
|
nsString dataString;
|
||||||
|
nsCOMPtr<nsIStructuredCloneContainer> scContainer;
|
||||||
|
scContainer = notification->GetDataCloneContainer();
|
||||||
|
if (scContainer) {
|
||||||
|
scContainer->GetDataAsBase64(dataString);
|
||||||
|
}
|
||||||
|
|
||||||
aRv = notificationStorage->Put(origin,
|
aRv = notificationStorage->Put(origin,
|
||||||
id,
|
id,
|
||||||
aTitle,
|
aTitle,
|
||||||
|
@ -443,7 +468,9 @@ Notification::Constructor(const GlobalObject& aGlobal,
|
||||||
aOptions.mBody,
|
aOptions.mBody,
|
||||||
aOptions.mTag,
|
aOptions.mTag,
|
||||||
aOptions.mIcon,
|
aOptions.mIcon,
|
||||||
alertName);
|
alertName,
|
||||||
|
dataString);
|
||||||
|
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -481,10 +508,29 @@ Notification::CreateInternal(nsPIDOMWindow* aWindow,
|
||||||
aOptions.mLang,
|
aOptions.mLang,
|
||||||
aOptions.mTag,
|
aOptions.mTag,
|
||||||
aOptions.mIcon,
|
aOptions.mIcon,
|
||||||
aWindow);
|
aWindow);
|
||||||
return notification.forget();
|
return notification.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Notification::~Notification() {}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_CLASS(Notification)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDataObjectContainer)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(Notification, DOMEventTargetHelper)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDataObjectContainer)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF_INHERITED(Notification, DOMEventTargetHelper)
|
||||||
|
NS_IMPL_RELEASE_INHERITED(Notification, DOMEventTargetHelper)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Notification)
|
||||||
|
NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
|
||||||
|
|
||||||
nsIPrincipal*
|
nsIPrincipal*
|
||||||
Notification::GetPrincipal()
|
Notification::GetPrincipal()
|
||||||
{
|
{
|
||||||
|
@ -531,6 +577,13 @@ Notification::ShowInternal()
|
||||||
|
|
||||||
nsCOMPtr<nsIObserver> observer = new NotificationObserver(this);
|
nsCOMPtr<nsIObserver> observer = new NotificationObserver(this);
|
||||||
|
|
||||||
|
// mDataObjectContainer might be uninitialized here because the notification
|
||||||
|
// was constructed with an undefined data property.
|
||||||
|
nsString dataStr;
|
||||||
|
if (mDataObjectContainer) {
|
||||||
|
mDataObjectContainer->GetDataAsBase64(dataStr);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef MOZ_B2G
|
#ifdef MOZ_B2G
|
||||||
nsCOMPtr<nsIAppNotificationService> appNotifier =
|
nsCOMPtr<nsIAppNotificationService> appNotifier =
|
||||||
do_GetService("@mozilla.org/system-alerts-service;1");
|
do_GetService("@mozilla.org/system-alerts-service;1");
|
||||||
|
@ -553,6 +606,7 @@ Notification::ShowInternal()
|
||||||
ops.mDir = DirectionToString(mDir);
|
ops.mDir = DirectionToString(mDir);
|
||||||
ops.mLang = mLang;
|
ops.mLang = mLang;
|
||||||
ops.mTag = mTag;
|
ops.mTag = mTag;
|
||||||
|
ops.mData = dataStr;
|
||||||
|
|
||||||
if (!ToJSValue(cx, ops, &val)) {
|
if (!ToJSValue(cx, ops, &val)) {
|
||||||
NS_WARNING("Converting dict to object failed!");
|
NS_WARNING("Converting dict to object failed!");
|
||||||
|
@ -574,7 +628,7 @@ Notification::ShowInternal()
|
||||||
alertService->ShowAlertNotification(absoluteUrl, mTitle, mBody, true,
|
alertService->ShowAlertNotification(absoluteUrl, mTitle, mBody, true,
|
||||||
uniqueCookie, observer, mAlertName,
|
uniqueCookie, observer, mAlertName,
|
||||||
DirectionToString(mDir), mLang,
|
DirectionToString(mDir), mLang,
|
||||||
GetPrincipal());
|
dataStr, GetPrincipal());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -780,6 +834,54 @@ Notification::GetOrigin(nsPIDOMWindow* aWindow, nsString& aOrigin)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStructuredCloneContainer* Notification::GetDataCloneContainer()
|
||||||
|
{
|
||||||
|
return mDataObjectContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Notification::GetData(JSContext* aCx,
|
||||||
|
JS::MutableHandle<JS::Value> aRetval)
|
||||||
|
{
|
||||||
|
if (!mData && mDataObjectContainer) {
|
||||||
|
nsresult rv;
|
||||||
|
rv = mDataObjectContainer->DeserializeToVariant(aCx, getter_AddRefs(mData));
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
aRetval.setNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mData) {
|
||||||
|
aRetval.setNull();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
VariantToJsval(aCx, mData, aRetval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Notification::InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (mDataObjectContainer || aData.isNull()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mDataObjectContainer = new nsStructuredCloneContainer();
|
||||||
|
aRv = mDataObjectContainer->InitFromJSVal(aData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Notification::InitFromBase64(JSContext* aCx, const nsAString& aData,
|
||||||
|
ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
if (mDataObjectContainer || aData.IsEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto container = new nsStructuredCloneContainer();
|
||||||
|
aRv = container->InitFromBase64(aData, JS_STRUCTURED_CLONE_VERSION,
|
||||||
|
aCx);
|
||||||
|
mDataObjectContainer = container;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
|
||||||
class nsIPrincipal;
|
class nsIPrincipal;
|
||||||
|
class nsIStructuredCloneContainer;
|
||||||
|
class nsIVariant;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
namespace dom {
|
||||||
|
@ -34,6 +36,9 @@ public:
|
||||||
IMPL_EVENT_HANDLER(error)
|
IMPL_EVENT_HANDLER(error)
|
||||||
IMPL_EVENT_HANDLER(close)
|
IMPL_EVENT_HANDLER(close)
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS_INHERITED
|
||||||
|
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Notification, DOMEventTargetHelper)
|
||||||
|
|
||||||
static already_AddRefed<Notification> Constructor(const GlobalObject& aGlobal,
|
static already_AddRefed<Notification> Constructor(const GlobalObject& aGlobal,
|
||||||
const nsAString& aTitle,
|
const nsAString& aTitle,
|
||||||
const NotificationOptions& aOption,
|
const NotificationOptions& aOption,
|
||||||
|
@ -72,6 +77,8 @@ public:
|
||||||
aRetval = mIconUrl;
|
aRetval = mIconUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsIStructuredCloneContainer* GetDataCloneContainer();
|
||||||
|
|
||||||
static void RequestPermission(const GlobalObject& aGlobal,
|
static void RequestPermission(const GlobalObject& aGlobal,
|
||||||
const Optional<OwningNonNull<NotificationPermissionCallback> >& aCallback,
|
const Optional<OwningNonNull<NotificationPermissionCallback> >& aCallback,
|
||||||
ErrorResult& aRv);
|
ErrorResult& aRv);
|
||||||
|
@ -91,11 +98,17 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval);
|
||||||
|
|
||||||
|
void InitFromJSVal(JSContext* aCx, JS::Handle<JS::Value> aData, ErrorResult& aRv);
|
||||||
|
|
||||||
|
void InitFromBase64(JSContext* aCx, const nsAString& aData, ErrorResult& aRv);
|
||||||
protected:
|
protected:
|
||||||
Notification(const nsAString& aID, const nsAString& aTitle, const nsAString& aBody,
|
Notification(const nsAString& aID, const nsAString& aTitle, const nsAString& aBody,
|
||||||
NotificationDirection aDir, const nsAString& aLang,
|
NotificationDirection aDir, const nsAString& aLang,
|
||||||
const nsAString& aTag, const nsAString& aIconUrl,
|
const nsAString& aTag, const nsAString& aIconUrl,
|
||||||
nsPIDOMWindow* aWindow);
|
nsPIDOMWindow* aWindow);
|
||||||
|
|
||||||
static already_AddRefed<Notification> CreateInternal(nsPIDOMWindow* aWindow,
|
static already_AddRefed<Notification> CreateInternal(nsPIDOMWindow* aWindow,
|
||||||
const nsAString& aID,
|
const nsAString& aID,
|
||||||
|
@ -145,6 +158,10 @@ protected:
|
||||||
nsString mLang;
|
nsString mLang;
|
||||||
nsString mTag;
|
nsString mTag;
|
||||||
nsString mIconUrl;
|
nsString mIconUrl;
|
||||||
|
nsCOMPtr<nsIStructuredCloneContainer> mDataObjectContainer;
|
||||||
|
|
||||||
|
// It's null until GetData is first called
|
||||||
|
nsCOMPtr<nsIVariant> mData;
|
||||||
|
|
||||||
nsString mAlertName;
|
nsString mAlertName;
|
||||||
|
|
||||||
|
@ -153,6 +170,8 @@ protected:
|
||||||
static uint32_t sCount;
|
static uint32_t sCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
virtual ~Notification();
|
||||||
|
|
||||||
nsIPrincipal* GetPrincipal();
|
nsIPrincipal* GetPrincipal();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,8 @@ NotificationStorage.prototype = {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
put: function(origin, id, title, dir, lang, body, tag, icon, alertName) {
|
put: function(origin, id, title, dir, lang, body, tag, icon, alertName,
|
||||||
|
data) {
|
||||||
if (DEBUG) { debug("PUT: " + id + ": " + title); }
|
if (DEBUG) { debug("PUT: " + id + ": " + title); }
|
||||||
var notification = {
|
var notification = {
|
||||||
id: id,
|
id: id,
|
||||||
|
@ -83,7 +84,8 @@ NotificationStorage.prototype = {
|
||||||
icon: icon,
|
icon: icon,
|
||||||
alertName: alertName,
|
alertName: alertName,
|
||||||
timestamp: new Date().getTime(),
|
timestamp: new Date().getTime(),
|
||||||
origin: origin
|
origin: origin,
|
||||||
|
data: data
|
||||||
};
|
};
|
||||||
|
|
||||||
this._notifications[id] = notification;
|
this._notifications[id] = notification;
|
||||||
|
@ -202,7 +204,8 @@ NotificationStorage.prototype = {
|
||||||
notification.lang,
|
notification.lang,
|
||||||
notification.body,
|
notification.body,
|
||||||
notification.tag,
|
notification.tag,
|
||||||
notification.icon);
|
notification.icon,
|
||||||
|
notification.data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (DEBUG) { debug("Error calling callback handle: " + e); }
|
if (DEBUG) { debug("Error calling callback handle: " + e); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,7 +48,8 @@ var MockServices = (function () {
|
||||||
dbId: aDetails.dbId || undefined,
|
dbId: aDetails.dbId || undefined,
|
||||||
dir: aDetails.dir || undefined,
|
dir: aDetails.dir || undefined,
|
||||||
tag: aDetails.tag || undefined,
|
tag: aDetails.tag || undefined,
|
||||||
timestamp: aDetails.timestamp || undefined
|
timestamp: aDetails.timestamp || undefined,
|
||||||
|
data: aDetails.data || undefined
|
||||||
};
|
};
|
||||||
this.showAlertNotification(aImageUrl, aTitle, aText, true, "", listener, aDetails.id);
|
this.showAlertNotification(aImageUrl, aTitle, aText, true, "", listener, aDetails.id);
|
||||||
},
|
},
|
||||||
|
|
|
@ -43,6 +43,34 @@ var NotificationTest = (function () {
|
||||||
})(tests);
|
})(tests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var fakeCustomData = (function () {
|
||||||
|
var buffer = new ArrayBuffer(2);
|
||||||
|
var dv = new DataView(buffer).setInt16(0, 42, true);
|
||||||
|
var canvas = document.createElement("canvas");
|
||||||
|
canvas.width = canvas.height = 100;
|
||||||
|
var context = canvas.getContext("2d");
|
||||||
|
|
||||||
|
var map = new Map();
|
||||||
|
var set = new Set();
|
||||||
|
map.set("test", 42);
|
||||||
|
set.add(4); set.add(2);
|
||||||
|
|
||||||
|
return {
|
||||||
|
primitives: {
|
||||||
|
a: 123,
|
||||||
|
b: "test",
|
||||||
|
c: true,
|
||||||
|
d: [1, 2, 3]
|
||||||
|
},
|
||||||
|
date: new Date(2013, 2, 1, 1, 10),
|
||||||
|
regexp: new RegExp("[^.]+"),
|
||||||
|
arrayBuffer: buffer,
|
||||||
|
imageData: context.createImageData(100, 100),
|
||||||
|
map: map,
|
||||||
|
set: set
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
// NotificationTest API
|
// NotificationTest API
|
||||||
return {
|
return {
|
||||||
run: function (tests, callback) {
|
run: function (tests, callback) {
|
||||||
|
@ -68,6 +96,33 @@ var NotificationTest = (function () {
|
||||||
// TODO: how??
|
// TODO: how??
|
||||||
},
|
},
|
||||||
|
|
||||||
info: info
|
info: info,
|
||||||
|
|
||||||
|
customDataMatches: function(dataObj) {
|
||||||
|
var url = "http://www.domain.com";
|
||||||
|
try {
|
||||||
|
return (JSON.stringify(dataObj.primitives) ===
|
||||||
|
JSON.stringify(fakeCustomData.primitives)) &&
|
||||||
|
(dataObj.date.toDateString() ===
|
||||||
|
fakeCustomData.date.toDateString()) &&
|
||||||
|
(dataObj.regexp.exec(url)[0].substr(7) === "www") &&
|
||||||
|
(new Int16Array(dataObj.arrayBuffer)[0] === 42) &&
|
||||||
|
(JSON.stringify(dataObj.imageData.data) ===
|
||||||
|
JSON.stringify(fakeCustomData.imageData.data)) &&
|
||||||
|
(dataObj.map.get("test") == 42) &&
|
||||||
|
(dataObj.set.has(4) && dataObj.set.has(2));
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
payload: {
|
||||||
|
body: "Body",
|
||||||
|
tag: "fakeTag",
|
||||||
|
icon: "icon.jpg",
|
||||||
|
lang: "en-US",
|
||||||
|
dir: "ltr",
|
||||||
|
data: fakeCustomData
|
||||||
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -9,7 +9,8 @@ var registrar = SpecialPowers.wrap(SpecialPowers.Components).manager.
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
cookie, alertListener, name, bidi, lang) {
|
cookie, alertListener, name, bidi,
|
||||||
|
lang, data) {
|
||||||
// probably should do this async....
|
// probably should do this async....
|
||||||
SpecialPowers.wrap(alertListener).observe(null, "alertshow", cookie);
|
SpecialPowers.wrap(alertListener).observe(null, "alertshow", cookie);
|
||||||
|
|
||||||
|
@ -22,7 +23,8 @@ var mockAlertsService = {
|
||||||
|
|
||||||
showAppNotification: function(imageUrl, title, text, alertListener, details) {
|
showAppNotification: function(imageUrl, title, text, alertListener, details) {
|
||||||
this.showAlertNotification(imageUrl, title, text, details.textClickable, "",
|
this.showAlertNotification(imageUrl, title, text, details.textClickable, "",
|
||||||
alertListener, details.name, details.dir, details.lang);
|
alertListener, details.name, details.dir,
|
||||||
|
details.lang, details.data);
|
||||||
},
|
},
|
||||||
|
|
||||||
QueryInterface: function(aIID) {
|
QueryInterface: function(aIID) {
|
||||||
|
|
|
@ -24,7 +24,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=782211
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
cookie, alertListener, name, dir, lang) {
|
cookie, alertListener, name, dir,
|
||||||
|
lang, data) {
|
||||||
notificationsCreated.push(name);
|
notificationsCreated.push(name);
|
||||||
if (notificationsCreated.length == 3) {
|
if (notificationsCreated.length == 3) {
|
||||||
checkNotifications();
|
checkNotifications();
|
||||||
|
|
|
@ -24,7 +24,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=874090
|
||||||
|
|
||||||
var mockAlertsService = {
|
var mockAlertsService = {
|
||||||
showAlertNotification: function(imageUrl, title, text, textClickable,
|
showAlertNotification: function(imageUrl, title, text, textClickable,
|
||||||
cookie, alertListener, name, dir, lang) {
|
cookie, alertListener, name, dir, lang, data) {
|
||||||
ok(true, "System principal was granted permission and is able to call showAlertNotification.");
|
ok(true, "System principal was granted permission and is able to call showAlertNotification.");
|
||||||
unregisterMock();
|
unregisterMock();
|
||||||
SimpleTest.finish();
|
SimpleTest.finish();
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
var info = NotificationTest.info;
|
var info = NotificationTest.info;
|
||||||
|
var options;
|
||||||
|
|
||||||
var steps = [
|
var steps = [
|
||||||
function () {
|
function () {
|
||||||
|
@ -62,13 +63,8 @@
|
||||||
function (done) {
|
function (done) {
|
||||||
info("Test create notification");
|
info("Test create notification");
|
||||||
|
|
||||||
var options = {
|
options = NotificationTest.payload;
|
||||||
dir: "auto",
|
|
||||||
lang: "",
|
|
||||||
body: "This is a notification body",
|
|
||||||
tag: "sometag",
|
|
||||||
icon: "icon.png"
|
|
||||||
};
|
|
||||||
var notification = new Notification("This is a title", options);
|
var notification = new Notification("This is a title", options);
|
||||||
|
|
||||||
ok(notification, "Notification exists");
|
ok(notification, "Notification exists");
|
||||||
|
@ -77,12 +73,15 @@
|
||||||
is(notification.onerror, null, "onerror() should be null");
|
is(notification.onerror, null, "onerror() should be null");
|
||||||
is(notification.onclose, null, "onclose() should be null");
|
is(notification.onclose, null, "onclose() should be null");
|
||||||
is(typeof notification.close, "function", "close() should exist");
|
is(typeof notification.close, "function", "close() should exist");
|
||||||
|
is(typeof notification.data, "object", "data should be a JS object");
|
||||||
|
|
||||||
is(notification.dir, options.dir, "auto should get set");
|
is(notification.dir, options.dir, "auto should get set");
|
||||||
is(notification.lang, options.lang, "lang should get set");
|
is(notification.lang, options.lang, "lang should get set");
|
||||||
is(notification.body, options.body, "body should get set");
|
is(notification.body, options.body, "body should get set");
|
||||||
is(notification.tag, options.tag, "tag should get set");
|
is(notification.tag, options.tag, "tag should get set");
|
||||||
is(notification.icon, options.icon, "icon should get set");
|
is(notification.icon, options.icon, "icon should get set");
|
||||||
|
ok(NotificationTest.customDataMatches(notification.data),
|
||||||
|
"data should get set");
|
||||||
|
|
||||||
// store notification in test context
|
// store notification in test context
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
|
|
|
@ -94,13 +94,8 @@
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
|
|
||||||
var payload = {
|
var payload = NotificationTest.payload;
|
||||||
body: "Body",
|
|
||||||
tag: "fakeTag",
|
|
||||||
icon: "icon.jpg",
|
|
||||||
lang: "en-US",
|
|
||||||
dir: "ltr"
|
|
||||||
};
|
|
||||||
var notif2 = new Notification("Title2", payload);
|
var notif2 = new Notification("Title2", payload);
|
||||||
ok(notif2, "Notification object is valid");
|
ok(notif2, "Notification object is valid");
|
||||||
notifications.push(notif2);
|
notifications.push(notif2);
|
||||||
|
@ -156,6 +151,16 @@
|
||||||
is(notif.dir, "ltr", "Notification dir is valid: " + notif.dir);
|
is(notif.dir, "ltr", "Notification dir is valid: " + notif.dir);
|
||||||
is(notif.tag, "fakeTag", "Notification tag is valid: " + notif.tag);
|
is(notif.tag, "fakeTag", "Notification tag is valid: " + notif.tag);
|
||||||
ok((notif.timestamp >= now), "Notification timestamp is valid: (" + notif.timestamp + " >= " + now + ")");
|
ok((notif.timestamp >= now), "Notification timestamp is valid: (" + notif.timestamp + " >= " + now + ")");
|
||||||
|
|
||||||
|
var scContainer =
|
||||||
|
SpecialPowers.Cc["@mozilla.org/docshell/structured-clone-container;1"].
|
||||||
|
createInstance(SpecialPowers.Ci.nsIStructuredCloneContainer);
|
||||||
|
scContainer.initFromBase64(notif.data, 4);
|
||||||
|
|
||||||
|
var dataObj = scContainer.deserializeToVariant().SpecialPowers_wrappedObject;
|
||||||
|
ok(NotificationTest.customDataMatches(dataObj),
|
||||||
|
"Notification data is valid");
|
||||||
|
|
||||||
notif2.close();
|
notif2.close();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,13 +45,8 @@
|
||||||
function (done) {
|
function (done) {
|
||||||
info("Test adding a notification, and making sure get returns it");
|
info("Test adding a notification, and making sure get returns it");
|
||||||
NotificationTest.allowNotifications();
|
NotificationTest.allowNotifications();
|
||||||
var options = {
|
var options = NotificationTest.payload;
|
||||||
dir: "auto",
|
|
||||||
lang: "",
|
|
||||||
body: "This is a notification body",
|
|
||||||
tag: "sometag",
|
|
||||||
icon: "icon.png"
|
|
||||||
};
|
|
||||||
var notification = new Notification("This is a title", options);
|
var notification = new Notification("This is a title", options);
|
||||||
var promise = Notification.get();
|
var promise = Notification.get();
|
||||||
promise.then(function (notifications) {
|
promise.then(function (notifications) {
|
||||||
|
@ -61,6 +56,11 @@
|
||||||
if (notification.tag === options.tag) {
|
if (notification.tag === options.tag) {
|
||||||
ok(true, "should contain newly created notification");
|
ok(true, "should contain newly created notification");
|
||||||
for (var key in options) {
|
for (var key in options) {
|
||||||
|
if (key === "data") {
|
||||||
|
ok(NotificationTest.customDataMatches(notification.data),
|
||||||
|
"data property should match");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
is(notification[key], options[key], key + " property should match");
|
is(notification[key], options[key], key + " property should match");
|
||||||
}
|
}
|
||||||
notification.close();
|
notification.close();
|
||||||
|
|
|
@ -14,4 +14,5 @@ dictionary AppNotificationServiceOptions {
|
||||||
DOMString dir = "";
|
DOMString dir = "";
|
||||||
DOMString lang = "";
|
DOMString lang = "";
|
||||||
DOMString tag = "";
|
DOMString tag = "";
|
||||||
|
DOMString data = "";
|
||||||
};
|
};
|
||||||
|
|
|
@ -49,6 +49,9 @@ interface Notification : EventTarget {
|
||||||
[Pure]
|
[Pure]
|
||||||
readonly attribute DOMString? icon;
|
readonly attribute DOMString? icon;
|
||||||
|
|
||||||
|
[Constant]
|
||||||
|
readonly attribute any data;
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,6 +61,7 @@ dictionary NotificationOptions {
|
||||||
DOMString body = "";
|
DOMString body = "";
|
||||||
DOMString tag = "";
|
DOMString tag = "";
|
||||||
DOMString icon = "";
|
DOMString icon = "";
|
||||||
|
any data = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
dictionary GetNotificationOptions {
|
dictionary GetNotificationOptions {
|
||||||
|
|
|
@ -69,6 +69,7 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
||||||
const nsAString & aAlertName,
|
const nsAString & aAlertName,
|
||||||
const nsAString & aBidi,
|
const nsAString & aBidi,
|
||||||
const nsAString & aLang,
|
const nsAString & aLang,
|
||||||
|
const nsAString & aData,
|
||||||
nsIPrincipal * aPrincipal)
|
nsIPrincipal * aPrincipal)
|
||||||
{
|
{
|
||||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||||
|
@ -85,6 +86,7 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
||||||
PromiseFlatString(aAlertName),
|
PromiseFlatString(aAlertName),
|
||||||
PromiseFlatString(aBidi),
|
PromiseFlatString(aBidi),
|
||||||
PromiseFlatString(aLang),
|
PromiseFlatString(aLang),
|
||||||
|
PromiseFlatString(aData),
|
||||||
IPC::Principal(aPrincipal));
|
IPC::Principal(aPrincipal));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +102,8 @@ NS_IMETHODIMP nsAlertsService::ShowAlertNotification(const nsAString & aImageUrl
|
||||||
if (sysAlerts) {
|
if (sysAlerts) {
|
||||||
return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
|
return sysAlerts->ShowAlertNotification(aImageUrl, aAlertTitle, aAlertText, aAlertTextClickable,
|
||||||
aAlertCookie, aAlertListener, aAlertName,
|
aAlertCookie, aAlertListener, aAlertName,
|
||||||
aBidi, aLang, IPC::Principal(aPrincipal));
|
aBidi, aLang, aData,
|
||||||
|
IPC::Principal(aPrincipal));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ShouldShowAlert()) {
|
if (!ShouldShowAlert()) {
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
interface nsIPrincipal;
|
interface nsIPrincipal;
|
||||||
|
|
||||||
[scriptable, uuid(160e87e1-d57d-456b-b6ea-17826f6ea7a8)]
|
[scriptable, uuid(d446bede-fcf7-403d-b6b6-5fd67b19ba58)]
|
||||||
interface nsIAlertsService : nsISupports
|
interface nsIAlertsService : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -61,6 +61,7 @@ interface nsIAlertsService : nsISupports
|
||||||
[optional] in AString name,
|
[optional] in AString name,
|
||||||
[optional] in AString dir,
|
[optional] in AString dir,
|
||||||
[optional] in AString lang,
|
[optional] in AString lang,
|
||||||
|
[optional] in AString data,
|
||||||
[optional] in nsIPrincipal principal);
|
[optional] in nsIPrincipal principal);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -2750,7 +2750,7 @@ nsDownload::SetState(DownloadState aState)
|
||||||
message, !removeWhenDone,
|
message, !removeWhenDone,
|
||||||
mPrivate ? NS_LITERAL_STRING("private") : NS_LITERAL_STRING("non-private"),
|
mPrivate ? NS_LITERAL_STRING("private") : NS_LITERAL_STRING("non-private"),
|
||||||
mDownloadManager, EmptyString(), NS_LITERAL_STRING("auto"),
|
mDownloadManager, EmptyString(), NS_LITERAL_STRING("auto"),
|
||||||
EmptyString(), nullptr);
|
EmptyString(), EmptyString(), nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -202,6 +202,7 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||||
const nsAString & aAlertName,
|
const nsAString & aAlertName,
|
||||||
const nsAString & aBidi,
|
const nsAString & aBidi,
|
||||||
const nsAString & aLang,
|
const nsAString & aLang,
|
||||||
|
const nsAString & aData,
|
||||||
nsIPrincipal * aPrincipal)
|
nsIPrincipal * aPrincipal)
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||||
|
|
Загрузка…
Ссылка в новой задаче