mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1209602 - XUL: Implement disabling notifications for a site. r=MattN
This commit is contained in:
parent
b7e57f14bd
commit
b55b7bd64f
@ -3,5 +3,7 @@ support-files =
|
||||
file_dom_notifications.html
|
||||
|
||||
[browser_notification_open_settings.js]
|
||||
[browser_notification_remove_permission.js]
|
||||
skip-if = e10s
|
||||
[browser_notification_tab_switching.js]
|
||||
skip-if = buildapp == 'mulet' || e10s # Bug 1100662 - content access causing uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 (or in RemoteAddonsChild.jsm)
|
||||
|
@ -0,0 +1,79 @@
|
||||
"use strict";
|
||||
|
||||
var tab;
|
||||
var notification;
|
||||
var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
|
||||
var alertWindowClosed = false;
|
||||
var permRemoved = false;
|
||||
|
||||
function test () {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let pm = Services.perms;
|
||||
registerCleanupFunction(function() {
|
||||
pm.remove(makeURI(notificationURL), "desktop-notification");
|
||||
gBrowser.removeTab(tab);
|
||||
window.restore();
|
||||
});
|
||||
|
||||
pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
|
||||
|
||||
tab = gBrowser.addTab(notificationURL);
|
||||
gBrowser.selectedTab = tab;
|
||||
tab.linkedBrowser.addEventListener("load", onLoad, true);
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
tab.linkedBrowser.removeEventListener("load", onLoad, true);
|
||||
let win = tab.linkedBrowser.contentWindow.wrappedJSObject;
|
||||
notification = win.showNotification2();
|
||||
notification.addEventListener("show", onAlertShowing);
|
||||
}
|
||||
|
||||
function onAlertShowing() {
|
||||
info("Notification alert showing");
|
||||
notification.removeEventListener("show", onAlertShowing);
|
||||
|
||||
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
|
||||
if (!alertWindow) {
|
||||
ok(true, "Notifications don't use XUL windows on all platforms.");
|
||||
notification.close();
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
ok(Services.perms.testExactPermission(makeURI(notificationURL), "desktop-notification"),
|
||||
"Permission should exist prior to removal");
|
||||
let disableForOriginMenuItem = alertWindow.document.getElementById("disableForOriginMenuItem");
|
||||
is(disableForOriginMenuItem.localName, "menuitem", "menuitem found");
|
||||
Services.obs.addObserver(permObserver, "perm-changed", false);
|
||||
alertWindow.addEventListener("beforeunload", onAlertClosing);
|
||||
disableForOriginMenuItem.click();
|
||||
info("Clicked on disable-for-origin menuitem")
|
||||
}
|
||||
|
||||
function permObserver(subject, topic, data) {
|
||||
if (topic != "perm-changed") {
|
||||
return;
|
||||
}
|
||||
|
||||
let permission = subject.QueryInterface(Ci.nsIPermission);
|
||||
is(permission.type, "desktop-notification", "desktop-notification permission changed");
|
||||
is(data, "deleted", "desktop-notification permission deleted");
|
||||
|
||||
Services.obs.removeObserver(permObserver, "perm-changed");
|
||||
permRemoved = true;
|
||||
if (alertWindowClosed) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
function onAlertClosing(event) {
|
||||
event.target.removeEventListener("beforeunload", onAlertClosing);
|
||||
|
||||
alertWindowClosed = true;
|
||||
if (permRemoved) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ function onAlertShowing() {
|
||||
|
||||
let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
|
||||
if (!alertWindow) {
|
||||
todo(false, "Notifications don't use XUL windows on all platforms.");
|
||||
ok(true, "Notifications don't use XUL windows on all platforms.");
|
||||
notification.close();
|
||||
newWindowOpenedFromTab.close();
|
||||
finish();
|
||||
|
@ -20,55 +20,3 @@ nsAlertsUtils::IsActionablePrincipal(nsIPrincipal* aPrincipal)
|
||||
!nsContentUtils::IsSystemOrExpandedPrincipal(aPrincipal) &&
|
||||
!aPrincipal->GetIsNullPrincipal();
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsAlertsUtils::GetSource(nsIPrincipal* aPrincipal, nsAString& aSource)
|
||||
{
|
||||
nsAutoString hostPort;
|
||||
GetSourceHostPort(aPrincipal, hostPort);
|
||||
if (hostPort.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIStringBundleService> stringService(
|
||||
mozilla::services::GetStringBundleService());
|
||||
if (!stringService) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIStringBundle> alertsBundle;
|
||||
if (NS_WARN_IF(NS_FAILED(stringService->CreateBundle(ALERTS_BUNDLE,
|
||||
getter_AddRefs(alertsBundle))))) {
|
||||
return;
|
||||
}
|
||||
const char16_t* params[1] = { hostPort.get() };
|
||||
nsXPIDLString result;
|
||||
if (NS_WARN_IF(NS_FAILED(
|
||||
alertsBundle->FormatStringFromName(MOZ_UTF16("source.label"), params, 1,
|
||||
getter_Copies(result))))) {
|
||||
return;
|
||||
}
|
||||
aSource = result;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsAlertsUtils::GetSourceHostPort(nsIPrincipal* aPrincipal,
|
||||
nsAString& aHostPort)
|
||||
{
|
||||
if (!IsActionablePrincipal(aPrincipal)) {
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
if (NS_WARN_IF(NS_FAILED(
|
||||
aPrincipal->GetURI(getter_AddRefs(principalURI))))) {
|
||||
return;
|
||||
}
|
||||
if (!principalURI) {
|
||||
return;
|
||||
}
|
||||
nsAutoCString hostPort;
|
||||
if (NS_WARN_IF(NS_FAILED(principalURI->GetHostPort(hostPort)))) {
|
||||
return;
|
||||
}
|
||||
CopyUTF8toUTF16(hostPort, aHostPort);
|
||||
}
|
||||
|
@ -21,19 +21,5 @@ public:
|
||||
*/
|
||||
static bool
|
||||
IsActionablePrincipal(nsIPrincipal* aPrincipal);
|
||||
|
||||
/**
|
||||
* Sets |aSource| to the localized notification source string, or an empty
|
||||
* string if |aPrincipal| is not actionable.
|
||||
*/
|
||||
static void
|
||||
GetSource(nsIPrincipal* aPrincipal, nsAString& aSource);
|
||||
|
||||
/**
|
||||
* Sets |aHostPort| to the host and port from |aPrincipal|'s URI, or an
|
||||
* empty string if |aPrincipal| is not actionable.
|
||||
*/
|
||||
static void
|
||||
GetSourceHostPort(nsIPrincipal* aPrincipal, nsAString& aHostPort);
|
||||
};
|
||||
#endif /* nsAlertsUtils_h */
|
||||
|
@ -136,15 +136,12 @@ nsXULAlerts::ShowAlertNotification(const nsAString& aImageUrl, const nsAString&
|
||||
rv = argsArray->AppendElement(ifptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// The source contains the host and port of the site that sent the
|
||||
// notification. It is empty for system alerts.
|
||||
nsCOMPtr<nsISupportsString> scriptableAlertSource (do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
|
||||
NS_ENSURE_TRUE(scriptableAlertSource, NS_ERROR_FAILURE);
|
||||
nsAutoString source;
|
||||
nsAlertsUtils::GetSource(aPrincipal, source);
|
||||
scriptableAlertSource->SetData(source);
|
||||
rv = argsArray->AppendElement(scriptableAlertSource);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// aPrincipal contains the scheme and hostPort of the
|
||||
// website that requested the notification. Optional.
|
||||
if (nsAlertsUtils::IsActionablePrincipal(aPrincipal)) {
|
||||
rv = argsArray->AppendElement(aPrincipal);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> newWindow;
|
||||
nsAutoCString features("chrome,dialog=yes,titlebar=no,popup=yes");
|
||||
|
@ -19,6 +19,7 @@ var gAlertListener = null;
|
||||
var gAlertTextClickable = false;
|
||||
var gAlertCookie = "";
|
||||
var gIsReplaced = false;
|
||||
var gPrincipal = null;
|
||||
|
||||
function prefillAlertInfo() {
|
||||
// unwrap all the args....
|
||||
@ -32,14 +33,39 @@ function prefillAlertInfo() {
|
||||
// arguments[7] --> lang
|
||||
// arguments[8] --> replaced alert window (nsIDOMWindow)
|
||||
// arguments[9] --> an optional callback listener (nsIObserver)
|
||||
// arguments[10] -> the localized alert source string
|
||||
// arguments[10] -> the nsIPrincipal of the site that requested the notification, optional
|
||||
|
||||
switch (window.arguments.length) {
|
||||
default:
|
||||
case 11: {
|
||||
if (window.arguments[10]) {
|
||||
document.getElementById('alertBox').setAttribute('hasOrigin', true);
|
||||
document.getElementById('alertSourceLabel').setAttribute('value', window.arguments[10]);
|
||||
let principal = window.arguments[10] &&
|
||||
window.arguments[10].QueryInterface(Ci.nsIPrincipal);
|
||||
let uri = principal.URI;
|
||||
let scheme;
|
||||
let hostPort;
|
||||
try {
|
||||
scheme = uri.scheme;
|
||||
hostPort = uri.hostPort;
|
||||
} catch (ex) {}
|
||||
// `scheme` is checked here to require a valid scheme (ftp, http,
|
||||
// https, for example) to be present on the nsIURI.
|
||||
if (scheme && hostPort) {
|
||||
const ALERT_BUNDLE = Services.strings.createBundle(
|
||||
"chrome://alerts/locale/alert.properties");
|
||||
|
||||
let label = document.getElementById("alertSourceLabel");
|
||||
let alertBox = document.getElementById("alertBox");
|
||||
alertBox.setAttribute("hasOrigin", true);
|
||||
label.setAttribute("value",
|
||||
ALERT_BUNDLE.formatStringFromName("source.label",
|
||||
[hostPort],
|
||||
1));
|
||||
let disableForOrigin = document.getElementById("disableForOriginMenuItem");
|
||||
disableForOrigin.setAttribute("label",
|
||||
ALERT_BUNDLE.formatStringFromName("webActions.disableForOrigin.label",
|
||||
[hostPort],
|
||||
1));
|
||||
gPrincipal = principal;
|
||||
}
|
||||
}
|
||||
case 10:
|
||||
@ -217,6 +243,12 @@ function onAlertClick() {
|
||||
}
|
||||
}
|
||||
|
||||
function disableForOrigin() {
|
||||
Services.perms.removeFromPrincipal(gPrincipal,
|
||||
"desktop-notification");
|
||||
onAlertClose();
|
||||
}
|
||||
|
||||
function onAlertClose() {
|
||||
let alertBox = document.getElementById("alertBox");
|
||||
if (alertBox.getAttribute("animate") == "true") {
|
||||
|
@ -43,7 +43,13 @@
|
||||
<spacer flex="1"/>
|
||||
<box id="alertFooter">
|
||||
<label id="alertSourceLabel" class="alertSource plain"/>
|
||||
<button type="menu" id="alertSettings" tooltiptext="&settings.label;"/>
|
||||
<button type="menu" id="alertSettings" tooltiptext="&settings.label;"
|
||||
onclick="event.stopPropagation();">
|
||||
<menupopup position="after_end">
|
||||
<menuitem id="disableForOriginMenuItem"
|
||||
oncommand="disableForOrigin();"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
</box>
|
||||
</vbox>
|
||||
</box>
|
||||
|
@ -8,7 +8,9 @@
|
||||
closeButton.title = Close
|
||||
# LOCALIZATION NOTE(actionButton.label): Used as the button label to provide more actions on OS X notifications. OS X will truncate this if it's too long.
|
||||
actionButton.label = …
|
||||
webActions.disable.label = Disable notifications from this site
|
||||
# LOCALIZATION NOTE(webActions.disableForOrigin.label): %S is replaced
|
||||
# with the hostname origin of the notification.
|
||||
webActions.disableForOrigin.label = Disable notifications from %S
|
||||
|
||||
# LOCALIZATION NOTE(source.label): Used to show the URL of the site that
|
||||
# sent the notification (e.g., "via mozilla.org"). "%1$S" is the source host
|
||||
|
@ -65,7 +65,6 @@ label {
|
||||
border-width: 0;
|
||||
min-width: 0;
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/utilities.svg#utilities");
|
||||
visibility: hidden; /* Temporary until bug 1209602 or bug 1205172 is fixed. */
|
||||
}
|
||||
|
||||
#alertSettings:hover {
|
||||
@ -73,7 +72,7 @@ label {
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
#alertSettings["open"],
|
||||
#alertSettings[open],
|
||||
#alertSettings:hover:active {
|
||||
background-color: rgba(107,107,107,.4);
|
||||
}
|
||||
|
@ -243,10 +243,17 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||
id<FakeNSUserNotification> notification = [[unClass alloc] init];
|
||||
notification.title = nsCocoaUtils::ToNSString(aAlertTitle);
|
||||
|
||||
nsCOMPtr<nsIURI> principalURI;
|
||||
nsAutoString hostPort;
|
||||
nsAlertsUtils::GetSourceHostPort(aPrincipal, hostPort);
|
||||
if (!hostPort.IsEmpty()) {
|
||||
notification.subtitle = nsCocoaUtils::ToNSString(hostPort);
|
||||
if (NS_SUCCEEDED(aPrincipal->GetURI(getter_AddRefs(principalURI)))) {
|
||||
if (principalURI) {
|
||||
nsAutoCString hostPortTemp;
|
||||
if (NS_SUCCEEDED(principalURI->GetHostPort(hostPortTemp))) {
|
||||
if (!hostPortTemp.IsEmpty()) {
|
||||
CopyUTF8toUTF16(hostPortTemp, hostPort);
|
||||
notification.subtitle = nsCocoaUtils::ToNSString(hostPort);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notification.informativeText = nsCocoaUtils::ToNSString(aAlertText);
|
||||
@ -264,8 +271,13 @@ OSXNotificationCenter::ShowAlertNotification(const nsAString & aImageUrl, const
|
||||
getter_Copies(closeButtonTitle));
|
||||
bundle->GetStringFromName(NS_LITERAL_STRING("actionButton.label").get(),
|
||||
getter_Copies(actionButtonTitle));
|
||||
bundle->GetStringFromName(NS_LITERAL_STRING("webActions.disable.label").get(),
|
||||
getter_Copies(disableButtonTitle));
|
||||
if (!hostPort.IsEmpty()) {
|
||||
const char16_t* formatStrings[] = { hostPort.get() };
|
||||
bundle->FormatStringFromName(NS_LITERAL_STRING("webActions.disableForOrigin.label").get(),
|
||||
formatStrings,
|
||||
ArrayLength(formatStrings),
|
||||
getter_Copies(disableButtonTitle));
|
||||
}
|
||||
bundle->GetStringFromName(NS_LITERAL_STRING("webActions.settings.label").get(),
|
||||
getter_Copies(settingsButtonTitle));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user